X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=Src%2FDirView.cpp;h=e21a88beaf03455c879595c974ff17926426d0b0;hb=00f56c6786360fbfea8e4130474b3eb258166af6;hp=fcf9061c563d6d9ba777de6690a6d774a4601f53;hpb=8e87622ac47fc89c842c11cd142fb2c79ba41b34;p=winmerge-jp%2Fwinmerge-jp.git diff --git a/Src/DirView.cpp b/Src/DirView.cpp index fcf9061c5..e21a88bea 100644 --- a/Src/DirView.cpp +++ b/Src/DirView.cpp @@ -2,21 +2,7 @@ // WinMerge: an interactive diff/merge utility // Copyright (C) 1997-2000 Thingamahoochie Software // Author: Dean Grimm -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -// +// SPDX-License-Identifier: GPL-2.0-or-later ///////////////////////////////////////////////////////////////////////////// /** * @file DirView.cpp @@ -38,7 +24,7 @@ #include "MainFrm.h" #include "resource.h" #include "FileTransform.h" -#include "SelectUnpackerDlg.h" +#include "SelectPluginDlg.h" #include "paths.h" #include "7zCommon.h" #include "OptionsDef.h" @@ -46,11 +32,11 @@ #include "BCMenu.h" #include "DirCmpReportDlg.h" #include "DirCmpReport.h" -#include "DirCompProgressBar.h" #include "CompareStatisticsDlg.h" #include "LoadSaveCodepageDlg.h" #include "ConfirmFolderCopyDlg.h" #include "DirColsDlg.h" +#include "DirAdditionalPropertiesDlg.h" #include "DirSelectFilesDlg.h" #include "UniFile.h" #include "ShellContextMenu.h" @@ -60,6 +46,9 @@ #include "FileOrFolderSelect.h" #include "IntToIntMap.h" #include "PatchTool.h" +#include "SyntaxColors.h" +#include "Shell.h" +#include "DirTravel.h" #include #include @@ -102,13 +91,8 @@ IMPLEMENT_DYNCREATE(CDirView, CListView) CDirView::CDirView() : m_pList(nullptr) - , m_nHiddenItems(0) - , m_bNeedSearchFirstDiffItem(true) - , m_bNeedSearchLastDiffItem(true) - , m_firstDiffItem(-1) - , m_lastDiffItem(-1) - , m_pCmpProgressBar(nullptr) , m_compareStart(0) + , m_elapsed(0) , m_bTreeMode(false) , m_dirfilter(std::bind(&COptionsMgr::GetBool, GetOptionsMgr(), _1)) , m_pShellContextMenuLeft(nullptr) @@ -122,11 +106,11 @@ CDirView::CDirView() m_dwDefaultStyle &= ~LVS_TYPEMASK; // Show selection all the time, so user can see current item even when // focus is elsewhere (ie, on file edit window) - m_dwDefaultStyle |= LVS_REPORT | LVS_SHOWSELALWAYS | LVS_EDITLABELS; + m_dwDefaultStyle |= LVS_REPORT | LVS_SHOWSELALWAYS | LVS_EDITLABELS | LVS_OWNERDATA; m_bTreeMode = GetOptionsMgr()->GetBool(OPT_TREE_MODE); m_bExpandSubdirs = GetOptionsMgr()->GetBool(OPT_DIRVIEW_EXPAND_SUBDIRS); - m_bEscCloses = GetOptionsMgr()->GetBool(OPT_CLOSE_WITH_ESC); + m_nEscCloses = GetOptionsMgr()->GetInt(OPT_CLOSE_WITH_ESC); Options::DirColors::Load(GetOptionsMgr(), m_cachedColors); m_bUseColors = GetOptionsMgr()->GetBool(OPT_DIRCLR_USE_COLORS); } @@ -136,96 +120,209 @@ CDirView::~CDirView() } BEGIN_MESSAGE_MAP(CDirView, CListView) - ON_WM_CONTEXTMENU() //{{AFX_MSG_MAP(CDirView) + ON_WM_CONTEXTMENU() ON_WM_LBUTTONDBLCLK() + ON_WM_SIZE() + ON_WM_DESTROY() + ON_WM_CHAR() + ON_WM_KEYDOWN() + ON_WM_TIMER() + ON_MESSAGE(MSG_UI_UPDATE, OnUpdateUIMessage) + ON_COMMAND(ID_EDIT_COPY, OnEditCopy) + ON_COMMAND(ID_EDIT_CUT, OnEditCut) + ON_COMMAND(ID_EDIT_PASTE, OnEditPaste) + ON_COMMAND(ID_EDIT_UNDO, OnEditUndo) + ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo) + ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateSave) + ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnClick) + ON_NOTIFY_REFLECT(LVN_ITEMCHANGED, OnItemChanged) + ON_NOTIFY_REFLECT(LVN_BEGINLABELEDIT, OnBeginLabelEdit) + ON_NOTIFY_REFLECT(LVN_ENDLABELEDIT, OnEndLabelEdit) + ON_NOTIFY_REFLECT(LVN_ODFINDITEM, OnODFindItem) + ON_NOTIFY_REFLECT(NM_CLICK, OnClick) + ON_NOTIFY_REFLECT(LVN_BEGINDRAG, OnBeginDrag) + ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw) + // [File] menu + ON_COMMAND(ID_FILE_LEFT_READONLY, OnReadOnly) + ON_COMMAND(ID_FILE_MIDDLE_READONLY, OnReadOnly) + ON_COMMAND(ID_FILE_RIGHT_READONLY, OnReadOnly) + ON_UPDATE_COMMAND_UI(ID_FILE_LEFT_READONLY, OnUpdateReadOnly) + ON_UPDATE_COMMAND_UI(ID_FILE_MIDDLE_READONLY, OnUpdateReadOnly) + ON_UPDATE_COMMAND_UI(ID_FILE_RIGHT_READONLY, OnUpdateReadOnly) + ON_COMMAND(ID_FILE_ENCODING, OnFileEncoding) + // [Edit] menu + ON_COMMAND(ID_EDIT_SELECT_ALL, OnSelectAll) + ON_UPDATE_COMMAND_UI(ID_EDIT_SELECT_ALL, OnUpdateSelectAll) + // [View] menu + ON_COMMAND(ID_OPTIONS_SHOWDIFFERENT, OnOptionsShowDifferent) + ON_COMMAND(ID_OPTIONS_SHOWIDENTICAL, OnOptionsShowIdentical) + ON_COMMAND(ID_OPTIONS_SHOWUNIQUELEFT, OnOptionsShowUniqueLeft) + ON_COMMAND(ID_OPTIONS_SHOWUNIQUEMIDDLE, OnOptionsShowUniqueMiddle) + ON_COMMAND(ID_OPTIONS_SHOWUNIQUERIGHT, OnOptionsShowUniqueRight) + ON_COMMAND(ID_OPTIONS_SHOWBINARIES, OnOptionsShowBinaries) + ON_COMMAND(ID_OPTIONS_SHOWSKIPPED, OnOptionsShowSkipped) + ON_COMMAND(ID_OPTIONS_SHOWDIFFERENTLEFTONLY, OnOptionsShowDifferentLeftOnly) + ON_COMMAND(ID_OPTIONS_SHOWDIFFERENTMIDDLEONLY, OnOptionsShowDifferentMiddleOnly) + ON_COMMAND(ID_OPTIONS_SHOWDIFFERENTRIGHTONLY, OnOptionsShowDifferentRightOnly) + ON_COMMAND(ID_OPTIONS_SHOWMISSINGLEFTONLY, OnOptionsShowMissingLeftOnly) + ON_COMMAND(ID_OPTIONS_SHOWMISSINGMIDDLEONLY, OnOptionsShowMissingMiddleOnly) + ON_COMMAND(ID_OPTIONS_SHOWMISSINGRIGHTONLY, OnOptionsShowMissingRightOnly) + ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWDIFFERENT, OnUpdateOptionsShowdifferent) + ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWIDENTICAL, OnUpdateOptionsShowidentical) + ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWUNIQUELEFT, OnUpdateOptionsShowuniqueleft) + ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWUNIQUEMIDDLE, OnUpdateOptionsShowuniquemiddle) + ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWUNIQUERIGHT, OnUpdateOptionsShowuniqueright) + ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWBINARIES, OnUpdateOptionsShowBinaries) + ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWSKIPPED, OnUpdateOptionsShowSkipped) + ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWDIFFERENTLEFTONLY, OnUpdateOptionsShowDifferentLeftOnly) + ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWDIFFERENTMIDDLEONLY, OnUpdateOptionsShowDifferentMiddleOnly) + ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWDIFFERENTRIGHTONLY, OnUpdateOptionsShowDifferentRightOnly) + ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWMISSINGLEFTONLY, OnUpdateOptionsShowMissingLeftOnly) + ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWMISSINGMIDDLEONLY, OnUpdateOptionsShowMissingMiddleOnly) + ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWMISSINGRIGHTONLY, OnUpdateOptionsShowMissingRightOnly) + ON_COMMAND(ID_VIEW_SHOWHIDDENITEMS, OnViewShowHiddenItems) + ON_UPDATE_COMMAND_UI(ID_VIEW_SHOWHIDDENITEMS, OnUpdateViewShowHiddenItems) + ON_COMMAND(ID_VIEW_TREEMODE, OnViewTreeMode) + ON_COMMAND(ID_VIEW_EXPAND_ALLSUBDIRS, OnViewExpandAllSubdirs) + ON_COMMAND(ID_VIEW_COLLAPSE_ALLSUBDIRS, OnViewCollapseAllSubdirs) + ON_UPDATE_COMMAND_UI(ID_VIEW_TREEMODE, OnUpdateViewTreeMode) + ON_UPDATE_COMMAND_UI(ID_VIEW_EXPAND_ALLSUBDIRS, OnUpdateViewExpandAllSubdirs) + ON_UPDATE_COMMAND_UI(ID_VIEW_COLLAPSE_ALLSUBDIRS, OnUpdateViewCollapseAllSubdirs) + ON_COMMAND(ID_SWAPPANES_SWAP12, (OnViewSwapPanes<0, 1>)) + ON_COMMAND(ID_SWAPPANES_SWAP23, (OnViewSwapPanes<1, 2>)) + ON_COMMAND(ID_SWAPPANES_SWAP13, (OnViewSwapPanes<0, 2>)) + ON_UPDATE_COMMAND_UI(ID_SWAPPANES_SWAP12, (OnUpdateViewSwapPanes<0, 1>)) + ON_UPDATE_COMMAND_UI(ID_SWAPPANES_SWAP23, (OnUpdateViewSwapPanes<1, 2>)) + ON_UPDATE_COMMAND_UI(ID_SWAPPANES_SWAP13, (OnUpdateViewSwapPanes<0, 2>)) + ON_COMMAND(ID_VIEW_DIR_STATISTICS, OnViewCompareStatistics) + ON_COMMAND(ID_REFRESH, OnRefresh) + ON_UPDATE_COMMAND_UI(ID_REFRESH, OnUpdateRefresh) + ON_COMMAND(ID_RESCAN, OnMarkedRescan) + // [Merge] menu or Context menu + ON_COMMAND_RANGE(ID_MERGE_COMPARE, ID_MERGE_COMPARE_IN_NEW_WINDOW, OnMergeCompare) + ON_UPDATE_COMMAND_UI_RANGE(ID_MERGE_COMPARE, ID_MERGE_COMPARE_IN_NEW_WINDOW, OnUpdateMergeCompare) + ON_COMMAND(ID_FIRSTDIFF, OnFirstdiff) + ON_COMMAND(ID_LASTDIFF, OnLastdiff) + ON_COMMAND(ID_NEXTDIFF, OnNextdiff) + ON_COMMAND(ID_PREVDIFF, OnPrevdiff) + ON_COMMAND(ID_CURDIFF, OnCurdiff) + ON_UPDATE_COMMAND_UI(ID_FIRSTDIFF, OnUpdateFirstdiff) + ON_UPDATE_COMMAND_UI(ID_LASTDIFF, OnUpdateLastdiff) + ON_UPDATE_COMMAND_UI(ID_NEXTDIFF, OnUpdateNextdiff) + ON_UPDATE_COMMAND_UI(ID_PREVDIFF, OnUpdatePrevdiff) + ON_UPDATE_COMMAND_UI(ID_CURDIFF, OnUpdateCurdiff) ON_COMMAND_RANGE(ID_L2R, ID_R2L, OnDirCopy) ON_UPDATE_COMMAND_UI_RANGE(ID_L2R, ID_R2L, OnUpdateDirCopy) + ON_COMMAND(ID_MERGE_DELETE, OnDelete) + ON_UPDATE_COMMAND_UI(ID_MERGE_DELETE, OnUpdateDelete) + // [Tools] menu + ON_COMMAND(ID_TOOLS_CUSTOMIZECOLUMNS, OnCustomizeColumns) + ON_COMMAND(ID_TOOLS_GENERATEREPORT, OnToolsGenerateReport) + ON_COMMAND(ID_TOOLS_GENERATEPATCH, OnToolsGeneratePatch) + ON_MESSAGE(MSG_GENERATE_FLIE_COMPARE_REPORT, OnGenerateFileCmpReport) + // [Plugins] menu + ON_COMMAND(ID_OPEN_WITH_UNPACKER, OnOpenWithUnpacker) + ON_UPDATE_COMMAND_UI(ID_OPEN_WITH_UNPACKER, OnUpdateCtxtOpenWithUnpacker) + // [Help] menu + ON_COMMAND(ID_HELP, OnHelp) + // Context menu + // Context menu -> Compare Non-horizontally + ON_COMMAND(ID_MERGE_COMPARE_LEFT1_LEFT2, OnMergeCompare2) + ON_COMMAND(ID_MERGE_COMPARE_RIGHT1_RIGHT2, OnMergeCompare2) + ON_COMMAND(ID_MERGE_COMPARE_LEFT1_RIGHT2, OnMergeCompare2) + ON_COMMAND(ID_MERGE_COMPARE_LEFT2_RIGHT1, OnMergeCompare2) + ON_UPDATE_COMMAND_UI(ID_MERGE_COMPARE_LEFT1_LEFT2, OnUpdateMergeCompare2) + ON_UPDATE_COMMAND_UI(ID_MERGE_COMPARE_RIGHT1_RIGHT2, OnUpdateMergeCompare2) + ON_UPDATE_COMMAND_UI(ID_MERGE_COMPARE_LEFT1_RIGHT2, OnUpdateMergeCompare2) + ON_UPDATE_COMMAND_UI(ID_MERGE_COMPARE_LEFT2_RIGHT1, OnUpdateMergeCompare2) + ON_COMMAND(ID_MERGE_COMPARE_NONHORIZONTALLY, OnMergeCompareNonHorizontally) + // Context menu -> Compare As + ON_COMMAND_RANGE(ID_MERGE_COMPARE_TEXT, ID_MERGE_COMPARE_WEBPAGE, OnMergeCompareAs) + ON_COMMAND_RANGE(ID_UNPACKERS_FIRST, ID_UNPACKERS_LAST, OnMergeCompareAs) + ON_UPDATE_COMMAND_UI_RANGE(ID_MERGE_COMPARE_TEXT, ID_MERGE_COMPARE_WEBPAGE, OnUpdateMergeCompare) + ON_UPDATE_COMMAND_UI(ID_NO_UNPACKER, OnUpdateNoUnpacker) + // Context menu -> Copy ON_COMMAND(ID_DIR_COPY_LEFT_TO_RIGHT, (OnCtxtDirCopy)) - ON_UPDATE_COMMAND_UI(ID_DIR_COPY_LEFT_TO_RIGHT, (OnUpdateCtxtDirCopy)) ON_COMMAND(ID_DIR_COPY_LEFT_TO_MIDDLE, (OnCtxtDirCopy)) - ON_UPDATE_COMMAND_UI(ID_DIR_COPY_LEFT_TO_MIDDLE, (OnUpdateCtxtDirCopy)) ON_COMMAND(ID_DIR_COPY_RIGHT_TO_LEFT, (OnCtxtDirCopy)) - ON_UPDATE_COMMAND_UI(ID_DIR_COPY_RIGHT_TO_LEFT, (OnUpdateCtxtDirCopy)) ON_COMMAND(ID_DIR_COPY_RIGHT_TO_MIDDLE, (OnCtxtDirCopy)) - ON_UPDATE_COMMAND_UI(ID_DIR_COPY_RIGHT_TO_MIDDLE, (OnUpdateCtxtDirCopy)) ON_COMMAND(ID_DIR_COPY_MIDDLE_TO_LEFT, (OnCtxtDirCopy)) - ON_UPDATE_COMMAND_UI(ID_DIR_COPY_MIDDLE_TO_LEFT, (OnUpdateCtxtDirCopy)) ON_COMMAND(ID_DIR_COPY_MIDDLE_TO_RIGHT, (OnCtxtDirCopy)) + ON_UPDATE_COMMAND_UI(ID_DIR_COPY_LEFT_TO_RIGHT, (OnUpdateCtxtDirCopy)) + ON_UPDATE_COMMAND_UI(ID_DIR_COPY_LEFT_TO_MIDDLE, (OnUpdateCtxtDirCopy)) + ON_UPDATE_COMMAND_UI(ID_DIR_COPY_RIGHT_TO_LEFT, (OnUpdateCtxtDirCopy)) + ON_UPDATE_COMMAND_UI(ID_DIR_COPY_RIGHT_TO_MIDDLE, (OnUpdateCtxtDirCopy)) + ON_UPDATE_COMMAND_UI(ID_DIR_COPY_MIDDLE_TO_LEFT, (OnUpdateCtxtDirCopy)) ON_UPDATE_COMMAND_UI(ID_DIR_COPY_MIDDLE_TO_RIGHT, (OnUpdateCtxtDirCopy)) + ON_COMMAND(ID_DIR_COPY_LEFT_TO_BROWSE, OnCtxtDirCopyTo) + ON_COMMAND(ID_DIR_COPY_MIDDLE_TO_BROWSE, OnCtxtDirCopyTo) + ON_COMMAND(ID_DIR_COPY_RIGHT_TO_BROWSE, OnCtxtDirCopyTo) + ON_UPDATE_COMMAND_UI(ID_DIR_COPY_LEFT_TO_BROWSE, OnUpdateCtxtDirCopyTo) + ON_UPDATE_COMMAND_UI(ID_DIR_COPY_MIDDLE_TO_BROWSE, OnUpdateCtxtDirCopyTo) + ON_UPDATE_COMMAND_UI(ID_DIR_COPY_RIGHT_TO_BROWSE, OnUpdateCtxtDirCopyTo) + // Context menu -> Move + ON_COMMAND(ID_DIR_MOVE_LEFT_TO_BROWSE, OnCtxtDirMoveTo) + ON_COMMAND(ID_DIR_MOVE_MIDDLE_TO_BROWSE, OnCtxtDirMoveTo) + ON_COMMAND(ID_DIR_MOVE_RIGHT_TO_BROWSE, OnCtxtDirMoveTo) + ON_UPDATE_COMMAND_UI(ID_DIR_MOVE_LEFT_TO_BROWSE, OnUpdateCtxtDirMoveTo) + ON_UPDATE_COMMAND_UI(ID_DIR_MOVE_MIDDLE_TO_BROWSE, OnUpdateCtxtDirMoveTo) + ON_UPDATE_COMMAND_UI(ID_DIR_MOVE_RIGHT_TO_BROWSE, OnUpdateCtxtDirMoveTo) + // Context menu -> Delete ON_COMMAND(ID_DIR_DEL_LEFT, OnCtxtDirDel) - ON_UPDATE_COMMAND_UI(ID_DIR_DEL_LEFT, OnUpdateCtxtDirDel) ON_COMMAND(ID_DIR_DEL_RIGHT, OnCtxtDirDel) - ON_UPDATE_COMMAND_UI(ID_DIR_DEL_MIDDLE, OnUpdateCtxtDirDel) ON_COMMAND(ID_DIR_DEL_MIDDLE, OnCtxtDirDel) - ON_UPDATE_COMMAND_UI(ID_DIR_DEL_RIGHT, OnUpdateCtxtDirDel) ON_COMMAND(ID_DIR_DEL_BOTH, OnCtxtDirDelBoth) - ON_UPDATE_COMMAND_UI(ID_DIR_DEL_BOTH, OnUpdateCtxtDirDelBoth) ON_COMMAND(ID_DIR_DEL_ALL, OnCtxtDirDelBoth) + ON_UPDATE_COMMAND_UI(ID_DIR_DEL_LEFT, OnUpdateCtxtDirDel) + ON_UPDATE_COMMAND_UI(ID_DIR_DEL_MIDDLE, OnUpdateCtxtDirDel) + ON_UPDATE_COMMAND_UI(ID_DIR_DEL_RIGHT, OnUpdateCtxtDirDel) + ON_UPDATE_COMMAND_UI(ID_DIR_DEL_BOTH, OnUpdateCtxtDirDelBoth) ON_UPDATE_COMMAND_UI(ID_DIR_DEL_ALL, OnUpdateCtxtDirDelBoth) + // Context menu -> Rename, Hide Items + ON_COMMAND(ID_DIR_ITEM_RENAME, OnItemRename) + ON_UPDATE_COMMAND_UI(ID_DIR_ITEM_RENAME, OnUpdateItemRename) + ON_COMMAND(ID_DIR_HIDE_FILENAMES, OnHideFilenames) + ON_UPDATE_COMMAND_UI(ID_DIR_HIDE_FILENAMES, OnUpdateHideFilenames) + // Context menu -> Open Left ON_COMMAND(ID_DIR_OPEN_LEFT, OnCtxtDirOpen) - ON_UPDATE_COMMAND_UI(ID_DIR_OPEN_LEFT, OnUpdateCtxtDirOpen) + ON_COMMAND(ID_DIR_OPEN_LEFT_WITHEDITOR, OnCtxtDirOpenWithEditor) ON_COMMAND(ID_DIR_OPEN_LEFT_WITH, OnCtxtDirOpenWith) - ON_UPDATE_COMMAND_UI(ID_DIR_OPEN_LEFT_WITH, OnUpdateCtxtDirOpenWith) ON_COMMAND(ID_DIR_OPEN_LEFT_PARENT_FOLDER, OnCtxtDirOpenParentFolder) + ON_UPDATE_COMMAND_UI(ID_DIR_OPEN_LEFT, OnUpdateCtxtDirOpen) + ON_UPDATE_COMMAND_UI(ID_DIR_OPEN_LEFT_WITHEDITOR, OnUpdateCtxtDirOpenWithEditor) + ON_UPDATE_COMMAND_UI(ID_DIR_OPEN_LEFT_WITH, OnUpdateCtxtDirOpenWith) ON_UPDATE_COMMAND_UI(ID_DIR_OPEN_LEFT_PARENT_FOLDER, OnUpdateCtxtDirOpenParentFolder) + // Context menu -> Open Middle ON_COMMAND(ID_DIR_OPEN_MIDDLE, OnCtxtDirOpen) - ON_UPDATE_COMMAND_UI(ID_DIR_OPEN_MIDDLE, OnUpdateCtxtDirOpen) + ON_COMMAND(ID_DIR_OPEN_MIDDLE_WITHEDITOR, OnCtxtDirOpenWithEditor) ON_COMMAND(ID_DIR_OPEN_MIDDLE_WITH, OnCtxtDirOpenWith) + ON_COMMAND(ID_DIR_OPEN_MIDDLE_PARENT_FOLDER, OnCtxtDirOpenParentFolder) + ON_UPDATE_COMMAND_UI(ID_DIR_OPEN_MIDDLE, OnUpdateCtxtDirOpen) + ON_UPDATE_COMMAND_UI(ID_DIR_OPEN_MIDDLE_WITHEDITOR, OnUpdateCtxtDirOpenWithEditor) ON_UPDATE_COMMAND_UI(ID_DIR_OPEN_MIDDLE_WITH, OnUpdateCtxtDirOpenWith) ON_UPDATE_COMMAND_UI(ID_DIR_OPEN_MIDDLE_PARENT_FOLDER, OnUpdateCtxtDirOpenParentFolder) - ON_COMMAND(ID_DIR_OPEN_MIDDLE_PARENT_FOLDER, OnCtxtDirOpenParentFolder) + // Context menu -> Open Right ON_COMMAND(ID_DIR_OPEN_RIGHT, OnCtxtDirOpen) - ON_UPDATE_COMMAND_UI(ID_DIR_OPEN_RIGHT, OnUpdateCtxtDirOpen) + ON_COMMAND(ID_DIR_OPEN_RIGHT_WITHEDITOR, OnCtxtDirOpenWithEditor) ON_COMMAND(ID_DIR_OPEN_RIGHT_WITH, OnCtxtDirOpenWith) - ON_UPDATE_COMMAND_UI(ID_DIR_OPEN_RIGHT_WITH, OnUpdateCtxtDirOpenWith) ON_COMMAND(ID_DIR_OPEN_RIGHT_PARENT_FOLDER, OnCtxtDirOpenParentFolder) - ON_UPDATE_COMMAND_UI(ID_DIR_OPEN_RIGHT_PARENT_FOLDER, OnUpdateCtxtDirOpenParentFolder) - ON_COMMAND(ID_POPUP_OPEN_WITH_UNPACKER, OnCtxtOpenWithUnpacker) - ON_UPDATE_COMMAND_UI(ID_POPUP_OPEN_WITH_UNPACKER, OnUpdateCtxtOpenWithUnpacker) - ON_COMMAND(ID_DIR_OPEN_LEFT_WITHEDITOR, OnCtxtDirOpenWithEditor) - ON_UPDATE_COMMAND_UI(ID_DIR_OPEN_LEFT_WITHEDITOR, OnUpdateCtxtDirOpenWithEditor) - ON_COMMAND(ID_DIR_OPEN_MIDDLE_WITHEDITOR, OnCtxtDirOpenWithEditor) - ON_UPDATE_COMMAND_UI(ID_DIR_OPEN_MIDDLE_WITHEDITOR, OnUpdateCtxtDirOpenWithEditor) - ON_COMMAND(ID_DIR_OPEN_RIGHT_WITHEDITOR, OnCtxtDirOpenWithEditor) + ON_UPDATE_COMMAND_UI(ID_DIR_OPEN_RIGHT, OnUpdateCtxtDirOpen) ON_UPDATE_COMMAND_UI(ID_DIR_OPEN_RIGHT_WITHEDITOR, OnUpdateCtxtDirOpenWithEditor) - ON_COMMAND(ID_DIR_COPY_LEFT_TO_BROWSE, OnCtxtDirCopyTo) - ON_COMMAND(ID_DIR_COPY_MIDDLE_TO_BROWSE, OnCtxtDirCopyTo) - ON_COMMAND(ID_DIR_COPY_RIGHT_TO_BROWSE, OnCtxtDirCopyTo) - ON_UPDATE_COMMAND_UI(ID_DIR_COPY_LEFT_TO_BROWSE, OnUpdateCtxtDirCopyTo) - ON_UPDATE_COMMAND_UI(ID_DIR_COPY_MIDDLE_TO_BROWSE, OnUpdateCtxtDirCopyTo) - ON_UPDATE_COMMAND_UI(ID_DIR_COPY_RIGHT_TO_BROWSE, OnUpdateCtxtDirCopyTo) - ON_WM_DESTROY() - ON_WM_CHAR() - ON_WM_KEYDOWN() - ON_COMMAND(ID_FIRSTDIFF, OnFirstdiff) - ON_UPDATE_COMMAND_UI(ID_FIRSTDIFF, OnUpdateFirstdiff) - ON_COMMAND(ID_LASTDIFF, OnLastdiff) - ON_UPDATE_COMMAND_UI(ID_LASTDIFF, OnUpdateLastdiff) - ON_COMMAND(ID_NEXTDIFF, OnNextdiff) - ON_UPDATE_COMMAND_UI(ID_NEXTDIFF, OnUpdateNextdiff) - ON_COMMAND(ID_PREVDIFF, OnPrevdiff) - ON_UPDATE_COMMAND_UI(ID_PREVDIFF, OnUpdatePrevdiff) - ON_COMMAND(ID_CURDIFF, OnCurdiff) - ON_UPDATE_COMMAND_UI(ID_CURDIFF, OnUpdateCurdiff) - ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateSave) - ON_MESSAGE(MSG_UI_UPDATE, OnUpdateUIMessage) - ON_COMMAND(ID_REFRESH, OnRefresh) - ON_UPDATE_COMMAND_UI(ID_REFRESH, OnUpdateRefresh) - ON_WM_TIMER() - ON_UPDATE_COMMAND_UI(ID_STATUS_RIGHTDIR_RO, OnUpdateStatusRightRO) - ON_UPDATE_COMMAND_UI(ID_STATUS_MIDDLEDIR_RO, OnUpdateStatusMiddleRO) - ON_UPDATE_COMMAND_UI(ID_STATUS_LEFTDIR_RO, OnUpdateStatusLeftRO) - ON_COMMAND(ID_FILE_LEFT_READONLY, OnReadOnly) - ON_UPDATE_COMMAND_UI(ID_FILE_LEFT_READONLY, OnUpdateReadOnly) - ON_COMMAND(ID_FILE_MIDDLE_READONLY, OnReadOnly) - ON_UPDATE_COMMAND_UI(ID_FILE_MIDDLE_READONLY, OnUpdateReadOnly) - ON_COMMAND(ID_FILE_RIGHT_READONLY, OnReadOnly) - ON_UPDATE_COMMAND_UI(ID_FILE_RIGHT_READONLY, OnUpdateReadOnly) - ON_COMMAND(ID_TOOLS_CUSTOMIZECOLUMNS, OnCustomizeColumns) - ON_COMMAND(ID_TOOLS_GENERATEREPORT, OnToolsGenerateReport) - ON_COMMAND(ID_TOOLS_GENERATEPATCH, OnToolsGeneratePatch) - ON_MESSAGE(MSG_GENERATE_FLIE_COMPARE_REPORT, OnGenerateFileCmpReport) + ON_UPDATE_COMMAND_UI(ID_DIR_OPEN_RIGHT_WITH, OnUpdateCtxtDirOpenWith) + ON_UPDATE_COMMAND_UI(ID_DIR_OPEN_RIGHT_PARENT_FOLDER, OnUpdateCtxtDirOpenParentFolder) + // Context menu -> Copy Pathnames + ON_COMMAND(ID_DIR_COPY_PATHNAMES_LEFT, OnCopyPathnames) + ON_COMMAND(ID_DIR_COPY_PATHNAMES_MIDDLE, OnCopyPathnames) + ON_COMMAND(ID_DIR_COPY_PATHNAMES_RIGHT, OnCopyPathnames) + ON_COMMAND(ID_DIR_COPY_PATHNAMES_BOTH, OnCopyBothPathnames) + ON_COMMAND(ID_DIR_COPY_PATHNAMES_ALL, OnCopyBothPathnames) + ON_UPDATE_COMMAND_UI(ID_DIR_COPY_PATHNAMES_LEFT, OnUpdateCtxtDirCopy2) + ON_UPDATE_COMMAND_UI(ID_DIR_COPY_PATHNAMES_MIDDLE, OnUpdateCtxtDirCopy2) + ON_UPDATE_COMMAND_UI(ID_DIR_COPY_PATHNAMES_RIGHT, OnUpdateCtxtDirCopy2) + ON_UPDATE_COMMAND_UI(ID_DIR_COPY_PATHNAMES_BOTH, OnUpdateCtxtDirCopyBoth2) + ON_UPDATE_COMMAND_UI(ID_DIR_COPY_PATHNAMES_ALL, OnUpdateCtxtDirCopyBoth2) + // Context menu -> Zip ON_COMMAND(ID_DIR_ZIP_LEFT, OnCtxtDirZip) ON_COMMAND(ID_DIR_ZIP_MIDDLE, OnCtxtDirZip) ON_COMMAND(ID_DIR_ZIP_RIGHT, OnCtxtDirZip) @@ -238,119 +335,35 @@ BEGIN_MESSAGE_MAP(CDirView, CListView) ON_UPDATE_COMMAND_UI(ID_DIR_ZIP_BOTH, OnUpdateCtxtDirCopyBothTo) ON_UPDATE_COMMAND_UI(ID_DIR_ZIP_ALL, OnUpdateCtxtDirCopyBothTo) ON_UPDATE_COMMAND_UI(ID_DIR_ZIP_BOTH_DIFFS_ONLY, OnUpdateCtxtDirCopyBothDiffsOnlyTo) + // Context menu -> Left/Middle/Right Shell menu ON_COMMAND(ID_DIR_SHELL_CONTEXT_MENU_LEFT, OnCtxtDirShellContextMenu) ON_COMMAND(ID_DIR_SHELL_CONTEXT_MENU_MIDDLE, OnCtxtDirShellContextMenu) ON_COMMAND(ID_DIR_SHELL_CONTEXT_MENU_RIGHT, OnCtxtDirShellContextMenu) - ON_COMMAND(ID_EDIT_SELECT_ALL, OnSelectAll) - ON_UPDATE_COMMAND_UI(ID_EDIT_SELECT_ALL, OnUpdateSelectAll) - ON_COMMAND_RANGE(ID_PREDIFF_MANUAL, ID_PREDIFF_AUTO, OnPluginPredifferMode) - ON_UPDATE_COMMAND_UI_RANGE(ID_PREDIFF_MANUAL, ID_PREDIFF_AUTO, OnUpdatePluginPredifferMode) - ON_COMMAND(ID_DIR_COPY_PATHNAMES_LEFT, OnCopyPathnames) - ON_COMMAND(ID_DIR_COPY_PATHNAMES_MIDDLE, OnCopyPathnames) - ON_COMMAND(ID_DIR_COPY_PATHNAMES_RIGHT, OnCopyPathnames) - ON_COMMAND(ID_DIR_COPY_PATHNAMES_BOTH, OnCopyBothPathnames) - ON_COMMAND(ID_DIR_COPY_PATHNAMES_ALL, OnCopyBothPathnames) - ON_UPDATE_COMMAND_UI(ID_DIR_COPY_PATHNAMES_LEFT, OnUpdateCtxtDirCopyTo) - ON_UPDATE_COMMAND_UI(ID_DIR_COPY_PATHNAMES_MIDDLE, OnUpdateCtxtDirCopyTo) - ON_UPDATE_COMMAND_UI(ID_DIR_COPY_PATHNAMES_RIGHT, OnUpdateCtxtDirCopyTo) - ON_UPDATE_COMMAND_UI(ID_DIR_COPY_PATHNAMES_BOTH, OnUpdateCtxtDirCopyBothTo) - ON_UPDATE_COMMAND_UI(ID_DIR_COPY_PATHNAMES_ALL, OnUpdateCtxtDirCopyBothTo) + // Context menu -> Plugin settings + ON_COMMAND_RANGE(ID_PREDIFFER_SETTINGS_NONE, ID_PREDIFFER_SETTINGS_SELECT, OnPluginSettings) + ON_COMMAND_RANGE(ID_UNPACKER_SETTINGS_NONE, ID_UNPACKER_SETTINGS_SELECT, OnPluginSettings) + ON_UPDATE_COMMAND_UI_RANGE(ID_PREDIFFER_SETTINGS_NONE, ID_PREDIFFER_SETTINGS_SELECT, OnUpdatePluginMode) + ON_UPDATE_COMMAND_UI_RANGE(ID_UNPACKER_SETTINGS_NONE, ID_UNPACKER_SETTINGS_SELECT, OnUpdatePluginMode) + // Context menu -> Copy Filenames ON_COMMAND(ID_DIR_COPY_FILENAMES, OnCopyFilenames) ON_UPDATE_COMMAND_UI(ID_DIR_COPY_FILENAMES, OnUpdateCopyFilenames) + // Context menu -> Copy Items to Clipboard ON_COMMAND(ID_DIR_COPY_LEFT_TO_CLIPBOARD, OnCopyToClipboard) ON_COMMAND(ID_DIR_COPY_MIDDLE_TO_CLIPBOARD, OnCopyToClipboard) ON_COMMAND(ID_DIR_COPY_RIGHT_TO_CLIPBOARD, OnCopyToClipboard) ON_COMMAND(ID_DIR_COPY_BOTH_TO_CLIPBOARD, OnCopyBothToClipboard) ON_COMMAND(ID_DIR_COPY_ALL_TO_CLIPBOARD, OnCopyBothToClipboard) - ON_UPDATE_COMMAND_UI(ID_DIR_COPY_LEFT_TO_CLIPBOARD, OnUpdateCtxtDirCopyTo) - ON_UPDATE_COMMAND_UI(ID_DIR_COPY_MIDDLE_TO_CLIPBOARD, OnUpdateCtxtDirCopyTo) - ON_UPDATE_COMMAND_UI(ID_DIR_COPY_RIGHT_TO_CLIPBOARD, OnUpdateCtxtDirCopyTo) - ON_UPDATE_COMMAND_UI(ID_DIR_COPY_BOTH_TO_CLIPBOARD, OnUpdateCtxtDirCopyBothTo) - ON_UPDATE_COMMAND_UI(ID_DIR_COPY_ALL_TO_CLIPBOARD, OnUpdateCtxtDirCopyBothTo) - ON_COMMAND(ID_DIR_ITEM_RENAME, OnItemRename) - ON_UPDATE_COMMAND_UI(ID_DIR_ITEM_RENAME, OnUpdateItemRename) - ON_COMMAND(ID_DIR_HIDE_FILENAMES, OnHideFilenames) - ON_COMMAND(ID_DIR_MOVE_LEFT_TO_BROWSE, OnCtxtDirMoveTo) - ON_UPDATE_COMMAND_UI(ID_DIR_MOVE_LEFT_TO_BROWSE, OnUpdateCtxtDirMoveTo) - ON_COMMAND(ID_DIR_MOVE_MIDDLE_TO_BROWSE, OnCtxtDirMoveTo) - ON_UPDATE_COMMAND_UI(ID_DIR_MOVE_MIDDLE_TO_BROWSE, OnUpdateCtxtDirMoveTo) - ON_COMMAND(ID_DIR_MOVE_RIGHT_TO_BROWSE, OnCtxtDirMoveTo) - ON_UPDATE_COMMAND_UI(ID_DIR_MOVE_RIGHT_TO_BROWSE, OnUpdateCtxtDirMoveTo) - ON_UPDATE_COMMAND_UI(ID_DIR_HIDE_FILENAMES, OnUpdateHideFilenames) - ON_WM_SIZE() - ON_COMMAND(ID_MERGE_DELETE, OnDelete) - ON_UPDATE_COMMAND_UI(ID_MERGE_DELETE, OnUpdateDelete) - ON_COMMAND(ID_RESCAN, OnMarkedRescan) + ON_UPDATE_COMMAND_UI(ID_DIR_COPY_LEFT_TO_CLIPBOARD, OnUpdateCtxtDirCopy2) + ON_UPDATE_COMMAND_UI(ID_DIR_COPY_MIDDLE_TO_CLIPBOARD, OnUpdateCtxtDirCopy2) + ON_UPDATE_COMMAND_UI(ID_DIR_COPY_RIGHT_TO_CLIPBOARD, OnUpdateCtxtDirCopy2) + ON_UPDATE_COMMAND_UI(ID_DIR_COPY_BOTH_TO_CLIPBOARD, OnUpdateCtxtDirCopyBoth2) + ON_UPDATE_COMMAND_UI(ID_DIR_COPY_ALL_TO_CLIPBOARD, OnUpdateCtxtDirCopyBoth2) + // Status bar ON_UPDATE_COMMAND_UI(ID_STATUS_DIFFNUM, OnUpdateStatusNum) - ON_COMMAND(ID_VIEW_SHOWHIDDENITEMS, OnViewShowHiddenItems) - ON_UPDATE_COMMAND_UI(ID_VIEW_SHOWHIDDENITEMS, OnUpdateViewShowHiddenItems) - ON_COMMAND(ID_MERGE_COMPARE, OnMergeCompare) - ON_UPDATE_COMMAND_UI(ID_MERGE_COMPARE, OnUpdateMergeCompare) - ON_COMMAND(ID_MERGE_COMPARE_LEFT1_LEFT2, OnMergeCompare2) - ON_UPDATE_COMMAND_UI(ID_MERGE_COMPARE_LEFT1_LEFT2, OnUpdateMergeCompare2) - ON_COMMAND(ID_MERGE_COMPARE_RIGHT1_RIGHT2, OnMergeCompare2) - ON_UPDATE_COMMAND_UI(ID_MERGE_COMPARE_RIGHT1_RIGHT2, OnUpdateMergeCompare2) - ON_COMMAND(ID_MERGE_COMPARE_LEFT1_RIGHT2, OnMergeCompare2) - ON_UPDATE_COMMAND_UI(ID_MERGE_COMPARE_LEFT1_RIGHT2, OnUpdateMergeCompare2) - ON_COMMAND(ID_MERGE_COMPARE_LEFT2_RIGHT1, OnMergeCompare2) - ON_UPDATE_COMMAND_UI(ID_MERGE_COMPARE_LEFT2_RIGHT1, OnUpdateMergeCompare2) - ON_COMMAND(ID_MERGE_COMPARE_NONHORIZONTALLY, OnMergeCompareNonHorizontally) - ON_COMMAND(ID_MERGE_COMPARE_XML, OnMergeCompareXML) - ON_UPDATE_COMMAND_UI(ID_MERGE_COMPARE_XML, OnUpdateMergeCompare) - ON_COMMAND_RANGE(ID_MERGE_COMPARE_HEX, ID_MERGE_COMPARE_IMAGE, OnMergeCompareAs) - ON_UPDATE_COMMAND_UI_RANGE(ID_MERGE_COMPARE_HEX, ID_MERGE_COMPARE_IMAGE, OnUpdateMergeCompare) - ON_COMMAND(ID_VIEW_TREEMODE, OnViewTreeMode) - ON_UPDATE_COMMAND_UI(ID_VIEW_TREEMODE, OnUpdateViewTreeMode) - ON_COMMAND(ID_VIEW_EXPAND_ALLSUBDIRS, OnViewExpandAllSubdirs) - ON_UPDATE_COMMAND_UI(ID_VIEW_EXPAND_ALLSUBDIRS, OnUpdateViewExpandAllSubdirs) - ON_COMMAND(ID_VIEW_COLLAPSE_ALLSUBDIRS, OnViewCollapseAllSubdirs) - ON_UPDATE_COMMAND_UI(ID_VIEW_COLLAPSE_ALLSUBDIRS, OnUpdateViewCollapseAllSubdirs) - ON_COMMAND(ID_VIEW_SWAPPANES, OnViewSwapPanes) - ON_COMMAND(ID_VIEW_DIR_STATISTICS, OnViewCompareStatistics) - ON_COMMAND(ID_OPTIONS_SHOWDIFFERENT, OnOptionsShowDifferent) - ON_COMMAND(ID_OPTIONS_SHOWIDENTICAL, OnOptionsShowIdentical) - ON_COMMAND(ID_OPTIONS_SHOWUNIQUELEFT, OnOptionsShowUniqueLeft) - ON_COMMAND(ID_OPTIONS_SHOWUNIQUEMIDDLE, OnOptionsShowUniqueMiddle) - ON_COMMAND(ID_OPTIONS_SHOWUNIQUERIGHT, OnOptionsShowUniqueRight) - ON_COMMAND(ID_OPTIONS_SHOWBINARIES, OnOptionsShowBinaries) - ON_COMMAND(ID_OPTIONS_SHOWSKIPPED, OnOptionsShowSkipped) - ON_COMMAND(ID_OPTIONS_SHOWDIFFERENTLEFTONLY, OnOptionsShowDifferentLeftOnly) - ON_COMMAND(ID_OPTIONS_SHOWDIFFERENTMIDDLEONLY, OnOptionsShowDifferentMiddleOnly) - ON_COMMAND(ID_OPTIONS_SHOWDIFFERENTRIGHTONLY, OnOptionsShowDifferentRightOnly) - ON_COMMAND(ID_OPTIONS_SHOWMISSINGLEFTONLY, OnOptionsShowMissingLeftOnly) - ON_COMMAND(ID_OPTIONS_SHOWMISSINGMIDDLEONLY, OnOptionsShowMissingMiddleOnly) - ON_COMMAND(ID_OPTIONS_SHOWMISSINGRIGHTONLY, OnOptionsShowMissingRightOnly) - ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWDIFFERENT, OnUpdateOptionsShowdifferent) - ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWIDENTICAL, OnUpdateOptionsShowidentical) - ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWUNIQUELEFT, OnUpdateOptionsShowuniqueleft) - ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWUNIQUEMIDDLE, OnUpdateOptionsShowuniquemiddle) - ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWUNIQUERIGHT, OnUpdateOptionsShowuniqueright) - ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWBINARIES, OnUpdateOptionsShowBinaries) - ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWSKIPPED, OnUpdateOptionsShowSkipped) - ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWDIFFERENTLEFTONLY, OnUpdateOptionsShowDifferentLeftOnly) - ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWDIFFERENTMIDDLEONLY, OnUpdateOptionsShowDifferentMiddleOnly) - ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWDIFFERENTRIGHTONLY, OnUpdateOptionsShowDifferentRightOnly) - ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWMISSINGLEFTONLY, OnUpdateOptionsShowMissingLeftOnly) - ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWMISSINGMIDDLEONLY, OnUpdateOptionsShowMissingMiddleOnly) - ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWMISSINGRIGHTONLY, OnUpdateOptionsShowMissingRightOnly) - ON_COMMAND(ID_FILE_ENCODING, OnFileEncoding) - ON_COMMAND(ID_HELP, OnHelp) - ON_COMMAND(ID_EDIT_COPY, OnEditCopy) - ON_COMMAND(ID_EDIT_CUT, OnEditCut) - ON_COMMAND(ID_EDIT_PASTE, OnEditPaste) - ON_COMMAND(ID_EDIT_UNDO, OnEditUndo) - ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo) + ON_UPDATE_COMMAND_UI(ID_STATUS_RIGHTDIR_RO, OnUpdateStatusRightRO) + ON_UPDATE_COMMAND_UI(ID_STATUS_MIDDLEDIR_RO, OnUpdateStatusMiddleRO) + ON_UPDATE_COMMAND_UI(ID_STATUS_LEFTDIR_RO, OnUpdateStatusLeftRO) //}}AFX_MSG_MAP - ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnClick) - ON_NOTIFY_REFLECT(LVN_ITEMCHANGED, OnItemChanged) - ON_NOTIFY_REFLECT(LVN_BEGINLABELEDIT, OnBeginLabelEdit) - ON_NOTIFY_REFLECT(LVN_ENDLABELEDIT, OnEndLabelEdit) - ON_NOTIFY_REFLECT(NM_CLICK, OnClick) - ON_NOTIFY_REFLECT(LVN_BEGINDRAG, OnBeginDrag) - ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw) - ON_BN_CLICKED(IDC_COMPARISON_STOP, OnBnClickedComparisonStop) - ON_BN_CLICKED(IDC_COMPARISON_PAUSE, OnBnClickedComparisonPause) - ON_BN_CLICKED(IDC_COMPARISON_CONTINUE, OnBnClickedComparisonContinue) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// @@ -381,11 +394,14 @@ void CDirView::OnInitialUpdate() return 48; }(); const int iconCY = iconCX; - CListView::OnInitialUpdate(); + __super::OnInitialUpdate(); m_pList = &GetListCtrl(); - m_pIList.reset(new IListCtrlImpl(m_pList->m_hWnd)); - GetDocument()->SetDirView(this); - m_pColItems.reset(new DirViewColItems(GetDocument()->m_nDirs)); + m_pIList.reset(new IListCtrlImpl(m_pList->m_hWnd, m_listViewItems)); + CDirDoc* pDoc = GetDocument(); + pDoc->SetDirView(this); + + auto properties = strutils::split>(GetOptionsMgr()->GetString(OPT_ADDITIONAL_PROPERTIES), ' '); + m_pColItems.reset(new DirViewColItems(pDoc->m_nDirs, properties)); m_pList->SendMessage(CCM_SETUNICODEFORMAT, TRUE, 0); @@ -396,6 +412,9 @@ void CDirView::OnInitialUpdate() CWnd::SetFont(&m_font, TRUE); } + if (m_bUseColors) + m_pList->SetBkColor(m_cachedColors.clrDirMargin); + // Replace standard header with sort header HWND hWnd = ListView_GetHeader(m_pList->m_hWnd); if (hWnd != nullptr) @@ -417,7 +436,8 @@ void CDirView::OnInitialUpdate() IDI_COMPARE_ERROR, IDI_FOLDERUP, IDI_FOLDERUP_DISABLE, IDI_COMPARE_ABORTED, - IDI_NOTEQUALTEXTFILE, IDI_EQUALTEXTFILE + IDI_NOTEQUALTEXTFILE, IDI_EQUALTEXTFILE, + IDI_NOTEQUALIMAGE, IDI_EQUALIMAGE, }; for (auto id : icon_ids) VERIFY(-1 != m_imageList.Add((HICON)LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(id), IMAGE_ICON, iconCX, iconCY, 0))); @@ -430,7 +450,7 @@ void CDirView::OnInitialUpdate() // Restore column orders as they had them last time they ran m_pColItems->LoadColumnOrders( - (const TCHAR *)theApp.GetProfileString(GetDocument()->m_nDirs < 3 ? _T("DirView") : _T("DirView3"), _T("ColumnOrders"))); + GetOptionsMgr()->GetString(pDoc->m_nDirs < 3 ? OPT_DIRVIEW_COLUMN_ORDERS : OPT_DIRVIEW3_COLUMN_ORDERS)); // Display column headers (in appropriate order) ReloadColumns(); @@ -438,13 +458,13 @@ void CDirView::OnInitialUpdate() // Show selection across entire row.u // Also allow user to rearrange columns via drag&drop of headers. // Also enable infotips. - DWORD exstyle = LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP | LVS_EX_INFOTIP; + DWORD exstyle = LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP | LVS_EX_INFOTIP | LVS_EX_DOUBLEBUFFER; m_pList->SetExtendedStyle(exstyle); } BOOL CDirView::PreCreateWindow(CREATESTRUCT& cs) { - CListView::PreCreateWindow(cs); + __super::PreCreateWindow(cs); cs.dwExStyle &= ~WS_EX_CLIENTEDGE; return TRUE; } @@ -457,17 +477,6 @@ BOOL CDirView::PreCreateWindow(CREATESTRUCT& cs) */ void CDirView::StartCompare(CompareStats *pCompareStats) { - if (m_pCmpProgressBar == nullptr) - m_pCmpProgressBar.reset(new DirCompProgressBar()); - - if (!::IsWindow(m_pCmpProgressBar->GetSafeHwnd())) - m_pCmpProgressBar->Create(GetParentFrame()); - - m_pCmpProgressBar->SetCompareStat(pCompareStats); - m_pCmpProgressBar->StartUpdating(); - - GetParentFrame()->ShowControlBar(m_pCmpProgressBar.get(), TRUE, FALSE); - m_compareStart = clock(); } @@ -492,11 +501,11 @@ void CDirView::OnLButtonDblClk(UINT nFlags, CPoint point) } else { - CWaitCursor waitstatus; OpenSelection(); } } - CListView::OnLButtonDblClk(nFlags, point); + if (GetFocus() == this) + __super::OnLButtonDblClk(nFlags, point); } /** @@ -508,8 +517,8 @@ void CDirView::ReloadColumns() UpdateColumnNames(); m_pColItems->LoadColumnWidths( - (const TCHAR *)theApp.GetProfileString(GetDocument()->m_nDirs < 3 ? _T("DirView") : _T("DirView3"), _T("ColumnWidths")), - std::bind(&CListCtrl::SetColumnWidth, m_pList, _1, _2), DefColumnWidth); + GetOptionsMgr()->GetString(GetDocument()->m_nDirs < 3 ? OPT_DIRVIEW_COLUMN_WIDTHS : OPT_DIRVIEW3_COLUMN_WIDTHS), + std::bind(&CListCtrl::SetColumnWidth, m_pList, _1, _2), GetDefColumnWidth()); SetColAlignments(); } @@ -540,14 +549,13 @@ void CDirView::RedisplayChildren(DIFFITEM *diffpos, int level, UINT &index, int index++; if (di.HasChildren()) { - m_pList->SetItemState(index - 1, INDEXTOSTATEIMAGEMASK((di.customFlags & ViewCustomFlags::EXPANDED) ? 2 : 1), LVIS_STATEIMAGEMASK); if (di.customFlags & ViewCustomFlags::EXPANDED) RedisplayChildren(ctxt.GetFirstChildDiffPosition(curdiffpos), level + 1, index, alldiffs); } } else { - if (!ctxt.m_bRecursive || !di.diffcode.isDirectory() || !di.diffcode.existAll()) + if (!ctxt.m_bRecursive || !di.diffcode.isDirectory() || (!di.diffcode.existAll() && !di.HasChildren())) { AddNewItem(index, curdiffpos, I_IMAGECALLBACK, 0); index++; @@ -559,6 +567,8 @@ void CDirView::RedisplayChildren(DIFFITEM *diffpos, int level, UINT &index, int } } } + m_firstDiffItem.reset(); + m_lastDiffItem.reset(); } /** @@ -595,9 +605,8 @@ void CDirView::Redisplay() GetParentFrame()->SetLastCompareResult(alldiffs); SortColumnsAppropriately(); SetRedraw(TRUE); - - m_bNeedSearchLastDiffItem = true; - m_bNeedSearchFirstDiffItem = true; + m_pList->SetItemCount(static_cast(m_listViewItems.size())); + m_pList->Invalidate(); } /** @@ -683,7 +692,7 @@ static void NTAPI CheckContextMenu(BCMenu *pPopup, UINT uIDItem, BOOL bCheck) */ void CDirView::ListContextMenu(CPoint point, int /*i*/) { - CDirDoc *pDoc = GetDocument(); + CDirDoc* pDoc = GetDocument(); BCMenu menu; VERIFY(menu.LoadMenu(IDR_POPUP_DIRVIEW)); VERIFY(menu.LoadToolbar(IDR_MAINFRAME)); @@ -693,6 +702,16 @@ void CDirView::ListContextMenu(CPoint point, int /*i*/) BCMenu *pPopup = static_cast(menu.GetSubMenu(0)); ASSERT(pPopup != nullptr); + int sel = GetFocusedItem(); + if (sel == -1) + sel = GetFirstSelectedInd(); + if (sel == -1) + return; + const DIFFITEM& di = GetDiffItem(sel); + if (GetDiffContext().m_bRecursive && di.diffcode.isDirectory()) + pPopup->RemoveMenu(ID_MERGE_COMPARE, MF_BYCOMMAND); + if (!di.diffcode.isDirectory()) + pPopup->RemoveMenu(ID_MERGE_COMPARE_IN_NEW_WINDOW, MF_BYCOMMAND); if (pDoc->m_nDirs < 3) { pPopup->RemoveMenu(ID_DIR_COPY_LEFT_TO_MIDDLE, MF_BYCOMMAND); @@ -916,6 +935,8 @@ void CDirView::DoDirAction(DirActions::method_type func, const String& status_me ConfirmAndPerformActions(actionScript); } catch (ContentsChangedException& e) { AfxMessageBox(e.m_msg.c_str(), MB_ICONWARNING); + } catch (FileOperationException& e) { + AfxMessageBox(e.m_msg.c_str(), MB_ICONWARNING); } } @@ -941,7 +962,7 @@ void CDirView::DoDirActionTo(SIDE_TYPE stype, DirActions::method_type func, cons try { // First we build a list of desired actions FileActionScript actionScript; - actionScript.m_destBase = destPath; + actionScript.m_destBase = std::move(destPath); DirItemWithIndexIterator begin(m_pIList.get(), -1, true); DirItemWithIndexIterator end; FileActionScript *rsltScript; @@ -998,9 +1019,12 @@ void CDirView::PerformActionList(FileActionScript & actionScript) actionScript.SetParentWindow(GetMainFrame()->GetSafeHwnd()); theApp.AddOperation(); - if (actionScript.Run()) + bool succeeded = actionScript.Run(); + if (succeeded) UpdateAfterFileScript(actionScript); theApp.RemoveOperation(); + if (!succeeded && !actionScript.IsCanceled()) + throw FileOperationException(_T("File operation failed")); } /** @@ -1099,17 +1123,20 @@ void CDirView::OnColumnClick(NMHDR *pNMHDR, LRESULT *pResult) void CDirView::SortColumnsAppropriately() { int sortCol = GetOptionsMgr()->GetInt((GetDocument()->m_nDirs < 3) ? OPT_DIRVIEW_SORT_COLUMN : OPT_DIRVIEW_SORT_COLUMN3); - if (sortCol == -1 || sortCol >= m_pColItems->GetColCount()) + if (sortCol < 0 || sortCol >= m_pColItems->GetColCount()) return; bool bSortAscending = GetOptionsMgr()->GetBool(OPT_DIRVIEW_SORT_ASCENDING); m_ctlSortHeader.SetSortImage(m_pColItems->ColLogToPhys(sortCol), bSortAscending); //sort using static CompareFunc comparison function CompareState cs(&GetDiffContext(), m_pColItems.get(), sortCol, bSortAscending, m_bTreeMode); - GetListCtrl().SortItems(cs.CompareFunc, reinterpret_cast(&cs)); + std::stable_sort(m_listViewItems.begin(), m_listViewItems.end(), [&cs](const ListViewOwnerDataItem& a, const ListViewOwnerDataItem& b) + { return CompareState::CompareFunc(a.lParam, b.lParam, reinterpret_cast(&cs)) < 0; }); - m_bNeedSearchLastDiffItem = true; - m_bNeedSearchFirstDiffItem = true; + m_firstDiffItem.reset(); + m_lastDiffItem.reset(); + + m_pList->Invalidate(); } /// Do any last minute work as view closes @@ -1117,14 +1144,17 @@ void CDirView::OnDestroy() { DeleteAllDisplayItems(); - String secname = GetDocument()->m_nDirs < 3 ? _T("DirView") : _T("DirView3"); - theApp.WriteProfileString(secname.c_str(), _T("ColumnOrders"), m_pColItems->SaveColumnOrders().c_str()); - theApp.WriteProfileString(secname.c_str(), _T("ColumnWidths"), - m_pColItems->SaveColumnWidths(std::bind(&CListCtrl::GetColumnWidth, m_pList, _1)).c_str()); - - CListView::OnDestroy(); + { + const String keyname = GetDocument()->m_nDirs < 3 ? OPT_DIRVIEW_COLUMN_ORDERS : OPT_DIRVIEW3_COLUMN_ORDERS; + GetOptionsMgr()->SaveOption(keyname, m_pColItems->SaveColumnOrders()); + } + { + const String keyname = GetDocument()->m_nDirs < 3 ? OPT_DIRVIEW_COLUMN_WIDTHS : OPT_DIRVIEW3_COLUMN_WIDTHS; + GetOptionsMgr()->SaveOption(keyname, + m_pColItems->SaveColumnWidths(std::bind(&CListCtrl::GetColumnWidth, m_pList, _1))); + } - GetMainFrame()->ClearStatusbarItemCount(); + __super::OnDestroy(); } /** @@ -1147,12 +1177,11 @@ void CDirView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) } else { - CWaitCursor waitstatus; OpenSelection(); } } } - CListView::OnChar(nChar, nRepCnt, nFlags); + __super::OnChar(nChar, nRepCnt, nFlags); } /** @@ -1189,7 +1218,6 @@ void CDirView::CollapseSubdir(int sel) m_pList->SetRedraw(FALSE); // Turn off updating (better performance) dip.customFlags &= ~ViewCustomFlags::EXPANDED; - m_pList->SetItemState(sel, INDEXTOSTATEIMAGEMASK(1), LVIS_STATEIMAGEMASK); int count = m_pList->GetItemCount(); for (int i = sel + 1; i < count; i++) @@ -1197,6 +1225,7 @@ void CDirView::CollapseSubdir(int sel) const DIFFITEM& di = GetDiffItem(i); if (!di.IsAncestor(&dip)) break; + m_listViewItems.erase(m_listViewItems.begin() + i); m_pList->DeleteItem(i--); count--; } @@ -1215,7 +1244,9 @@ void CDirView::ExpandSubdir(int sel, bool bRecursive) return; m_pList->SetRedraw(FALSE); // Turn off updating (better performance) - m_pList->SetItemState(sel, INDEXTOSTATEIMAGEMASK(2), LVIS_STATEIMAGEMASK); + + const int top = m_pList->GetTopIndex(); + const size_t num = m_listViewItems.size(); CDiffContext &ctxt = GetDiffContext(); dip.customFlags |= ViewCustomFlags::EXPANDED; @@ -1227,15 +1258,21 @@ void CDirView::ExpandSubdir(int sel, bool bRecursive) int alldiffs; RedisplayChildren(diffpos, dip.GetDepth() + 1, indext, alldiffs); + for (size_t i = 0; i < m_listViewItems.size() - num; ++i) + m_pList->InsertItem(sel + 1, nullptr); + SortColumnsAppropriately(); m_pList->SetRedraw(TRUE); // Turn updating back on + m_pList->SetItemCount(static_cast(m_listViewItems.size())); + m_pList->EnsureVisible(top, TRUE); + m_pList->Invalidate(); } /** * @brief Open parent folder if possible. */ -void CDirView::OpenParentDirectory() +void CDirView::OpenParentDirectory(CDirDoc *pDocOpen) { CDirDoc *pDoc = GetDocument(); PathContext pathsParent; @@ -1243,15 +1280,13 @@ void CDirView::OpenParentDirectory() { case AllowUpwardDirectory::ParentIsTempPath: pDoc->m_pTempPathContext = pDoc->m_pTempPathContext->DeleteHead(); - // fall through (no break!) + [[fallthrough]]; case AllowUpwardDirectory::ParentIsRegularPath: - { DWORD dwFlags[3]; for (int nIndex = 0; nIndex < pathsParent.GetSize(); ++nIndex) dwFlags[nIndex] = FFILEOPEN_NOMRU | (pDoc->GetReadOnly(nIndex) ? FFILEOPEN_READONLY : 0); - GetMainFrame()->DoFileOpen(&pathsParent, dwFlags, nullptr, _T(""), GetDiffContext().m_bRecursive, (GetAsyncKeyState(VK_CONTROL) & 0x8000) ? nullptr : pDoc); - } - // fall through (no break!) + GetMainFrame()->DoFileOrFolderOpen(&pathsParent, dwFlags, nullptr, _T(""), GetDiffContext().m_bRecursive, (GetAsyncKeyState(VK_CONTROL) & 0x8000) ? nullptr : pDocOpen); + [[fallthrough]]; case AllowUpwardDirectory::No: break; default: @@ -1284,10 +1319,11 @@ bool CDirView::GetSelectedItems(int * sel1, int * sel2, int * sel3) /** * @brief Open special items (parent folders etc). + * @param [in] pDoc Pointer to CDirDoc object. * @param [in] pos1 First item position. * @param [in] pos2 Second item position. */ -void CDirView::OpenSpecialItems(DIFFITEM *pos1, DIFFITEM *pos2, DIFFITEM *pos3) +void CDirView::OpenSpecialItems(CDirDoc *pDoc, DIFFITEM *pos1, DIFFITEM *pos2, DIFFITEM *pos3) { if (pos2==nullptr && pos3==nullptr) { @@ -1295,7 +1331,7 @@ void CDirView::OpenSpecialItems(DIFFITEM *pos1, DIFFITEM *pos2, DIFFITEM *pos3) // SPECIAL_ITEM_POS is position for // special items, but there is currenly // only one (parent folder) - OpenParentDirectory(); + OpenParentDirectory(pDoc); } else { @@ -1322,7 +1358,7 @@ static bool CreateFoldersPair(const PathContext& paths) strutils::format_string1( _("The folder exists only in other side and cannot be opened.\n\nDo you want to create a matching folder:\n%1\nto the other side and open these folders?"), path); - int res = AfxMessageBox(message.c_str(), MB_YESNO | MB_ICONWARNING | MB_DONT_ASK_AGAIN); + int res = AfxMessageBox(message.c_str(), MB_YESNO | MB_ICONWARNING | MB_DONT_ASK_AGAIN, IDS_CREATE_PAIR_FOLDER); if (res == IDYES) created = paths::CreateIfNeeded(path); } @@ -1330,7 +1366,7 @@ static bool CreateFoldersPair(const PathContext& paths) return created; } -void CDirView::Open(const PathContext& paths, DWORD dwFlags[3], PackingInfo * infoUnpacker) +void CDirView::Open(CDirDoc *pDoc, const PathContext& paths, DWORD dwFlags[3], FileTextEncoding encoding[3], PackingInfo * infoUnpacker) { bool isdir = false; for (auto path : paths) @@ -1338,17 +1374,17 @@ void CDirView::Open(const PathContext& paths, DWORD dwFlags[3], PackingInfo * in if (paths::DoesPathExist(path) == paths::IS_EXISTING_DIR) isdir = true; } - CDirDoc * pDoc = GetDocument(); if (isdir) { // Open subfolders // Don't add folders to MRU - GetMainFrame()->DoFileOpen(&paths, dwFlags, nullptr, _T(""), GetDiffContext().m_bRecursive, (GetAsyncKeyState(VK_CONTROL) & 0x8000) ? nullptr : pDoc); + GetMainFrame()->DoFileOrFolderOpen(&paths, dwFlags, nullptr, _T(""), GetDiffContext().m_bRecursive, + ((GetAsyncKeyState(VK_CONTROL) & 0x8000) || GetDiffContext().m_bRecursive) ? nullptr : pDoc); } else if (HasZipSupport() && std::count_if(paths.begin(), paths.end(), ArchiveGuessFormat) == paths.GetSize()) { // Open archives, not adding paths to MRU - GetMainFrame()->DoFileOpen(&paths, dwFlags, nullptr, _T(""), GetDiffContext().m_bRecursive, nullptr, _T(""), infoUnpacker); + GetMainFrame()->DoFileOrFolderOpen(&paths, dwFlags, nullptr, _T(""), GetDiffContext().m_bRecursive, nullptr, infoUnpacker, nullptr); } else { @@ -1360,18 +1396,33 @@ void CDirView::Open(const PathContext& paths, DWORD dwFlags[3], PackingInfo * in // then it was set in a previous diff after unpacking, so we trust it // Open identical and different files + PathContext filteredPaths; FileLocation fileloc[3]; String strDesc[3]; - const String sUntitled[] = { _("Untitled left"), paths.GetSize() < 3 ? _("Untitled right") : _("untitled middle"), _("Untitled right") }; + const String sUntitled[] = { _("Untitled left"), paths.GetSize() < 3 ? _("Untitled right") : _("Untitled middle"), _("Untitled right") }; for (int i = 0; i < paths.GetSize(); ++i) { if (paths::DoesPathExist(paths[i]) == paths::DOES_NOT_EXIST) + { strDesc[i] = sUntitled[i]; + filteredPaths.SetPath(i, _T("NUL"), false); + } else + { fileloc[i].setPath(paths[i]); + fileloc[i].encoding = encoding[i]; + filteredPaths.SetPath(i, paths[i], false); + } } - GetMainFrame()->ShowAutoMergeDoc(pDoc, paths.GetSize(), fileloc, + if (!infoUnpacker) + { + PrediffingInfo* infoPrediffer = nullptr; + String filteredFilenames = CDiffContext::GetFilteredFilenames(filteredPaths); + GetDiffContext().FetchPluginInfos(filteredFilenames, &infoUnpacker, &infoPrediffer); + } + + GetMainFrame()->ShowAutoMergeDoc(0, GetDocument(), paths.GetSize(), fileloc, dwFlags, strDesc, _T(""), infoUnpacker); } } @@ -1386,10 +1437,9 @@ void CDirView::Open(const PathContext& paths, DWORD dwFlags[3], PackingInfo * in * This handles the case that one item is selected * and the case that two items are selected (one on each side) */ -void CDirView::OpenSelection(SELECTIONTYPE selectionType /*= SELECTIONTYPE_NORMAL*/, PackingInfo * infoUnpacker /*= nullptr*/) +void CDirView::OpenSelection(CDirDoc *pDoc, SELECTIONTYPE selectionType /*= SELECTIONTYPE_NORMAL*/, PackingInfo * infoUnpacker /*= nullptr*/, bool openableForDir /*= true*/) { Merge7zFormatMergePluginScope scope(infoUnpacker); - CDirDoc * pDoc = GetDocument(); const CDiffContext& ctxt = GetDiffContext(); // First, figure out what was selected (store into pos1 & pos2) @@ -1414,9 +1464,9 @@ void CDirView::OpenSelection(SELECTIONTYPE selectionType /*= SELECTIONTYPE_NORMA // Now handle the various cases of what was selected - if (pos1 == (DIFFITEM *)SPECIAL_ITEM_POS) + if (IsDiffItemSpecial(pos1)) { - OpenSpecialItems(pos1, pos2, pos3); + OpenSpecialItems(pDoc, pos1, pos2, pos3); return; } @@ -1425,19 +1475,20 @@ void CDirView::OpenSelection(SELECTIONTYPE selectionType /*= SELECTIONTYPE_NORMA const DIFFITEM *pdi[3] = {0}; // left & right items (di1==di2 if single selection) bool isdir = false; // set if we're comparing directories int nPane[3]; + FileTextEncoding encoding[3]; String errmsg; bool success; if (pos2 && !pos3) success = GetOpenTwoItems(ctxt, selectionType, pos1, pos2, pdi, - paths, sel1, sel2, isdir, nPane, errmsg); + paths, sel1, sel2, isdir, nPane, encoding, errmsg, openableForDir); else if (pos2 && pos3) success = GetOpenThreeItems(ctxt, pos1, pos2, pos3, pdi, - paths, sel1, sel2, sel3, isdir, nPane, errmsg); + paths, sel1, sel2, sel3, isdir, nPane, encoding, errmsg, openableForDir); else { // Only one item selected, so perform diff on its sides success = GetOpenOneItem(ctxt, pos1, pdi, - paths, sel1, isdir, nPane, errmsg); + paths, sel1, isdir, nPane, encoding, errmsg, openableForDir); if (isdir) CreateFoldersPair(paths); } @@ -1453,9 +1504,14 @@ void CDirView::OpenSelection(SELECTIONTYPE selectionType /*= SELECTIONTYPE_NORMA DWORD dwFlags[3]; for (int nIndex = 0; nIndex < paths.GetSize(); nIndex++) - dwFlags[nIndex] = FFILEOPEN_NOMRU | (pDoc->GetReadOnly(nPane[nIndex]) ? FFILEOPEN_READONLY : 0); + dwFlags[nIndex] = FFILEOPEN_NOMRU | (GetDocument()->GetReadOnly(nPane[nIndex]) ? FFILEOPEN_READONLY : 0); - Open(paths, dwFlags, infoUnpacker); + Open(pDoc, paths, dwFlags, encoding, infoUnpacker); +} + +void CDirView::OpenSelection(SELECTIONTYPE selectionType /*= SELECTIONTYPE_NORMAL*/, PackingInfo* infoUnpacker /*= nullptr*/, bool openableForDir /*= true*/) +{ + OpenSelection(GetDocument(), selectionType, infoUnpacker, openableForDir); } void CDirView::OpenSelectionAs(UINT id) @@ -1463,12 +1519,12 @@ void CDirView::OpenSelectionAs(UINT id) CDirDoc * pDoc = GetDocument(); const CDiffContext& ctxt = GetDiffContext(); - // First, figure out what was selected (store into pos1 & pos2) - DIFFITEM *pos1 = nullptr, *pos2 = nullptr; + // First, figure out what was selected (store into pos1 & pos2 & pos3) + DIFFITEM *pos1 = nullptr, *pos2 = nullptr, *pos3 = nullptr; int sel1 = -1, sel2 = -1, sel3 = -1; if (!GetSelectedItems(&sel1, &sel2, &sel3)) { - // Must have 1 or 2 items selected + // Must have 1 or 2 or 3 items selected // Not valid action return; } @@ -1476,11 +1532,16 @@ void CDirView::OpenSelectionAs(UINT id) pos1 = GetItemKey(sel1); ASSERT(pos1); if (sel2 != -1) + { pos2 = GetItemKey(sel2); + ASSERT(pos2 != nullptr); + if (sel3 != -1) + pos3 = GetItemKey(sel3); + } // Now handle the various cases of what was selected - if (pos1 == (DIFFITEM *)SPECIAL_ITEM_POS) + if (IsDiffItemSpecial(pos1)) { ASSERT(false); return; @@ -1491,16 +1552,20 @@ void CDirView::OpenSelectionAs(UINT id) const DIFFITEM *pdi[3]; // left & right items (di1==di2 if single selection) bool isdir = false; // set if we're comparing directories int nPane[3]; + FileTextEncoding encoding[3]; String errmsg; bool success; - if (pos2) + if (pos2 && !pos3) success = GetOpenTwoItems(ctxt, SELECTIONTYPE_NORMAL, pos1, pos2, pdi, - paths, sel1, sel2, isdir, nPane, errmsg); + paths, sel1, sel2, isdir, nPane, encoding, errmsg, false); + else if (pos2 && pos3) + success = GetOpenThreeItems(ctxt, pos1, pos2, pos3, pdi, + paths, sel1, sel2, sel3, isdir, nPane, encoding, errmsg, false); else { // Only one item selected, so perform diff on its sides success = GetOpenOneItem(ctxt, pos1, pdi, - paths, sel1, isdir, nPane, errmsg); + paths, sel1, isdir, nPane, encoding, errmsg, false); } if (!success) { @@ -1510,17 +1575,40 @@ void CDirView::OpenSelectionAs(UINT id) } // Open identical and different files + const String sUntitled[] = { _("Untitled left"), paths.GetSize() < 3 ? _("Untitled right") : _("Untitled middle"), _("Untitled right") }; DWORD dwFlags[3] = { 0 }; + String strDesc[3]; + PathContext filteredPaths; FileLocation fileloc[3]; for (int pane = 0; pane < paths.GetSize(); pane++) { - fileloc[pane].setPath(paths[pane]); + if (paths::DoesPathExist(paths[pane]) == paths::DOES_NOT_EXIST) + { + strDesc[pane] = sUntitled[pane]; + filteredPaths.SetPath(pane, _T("NUL"), false); + } + else + { + fileloc[pane].setPath(paths[pane]); + fileloc[pane].encoding = encoding[pane]; + filteredPaths.SetPath(pane, paths[pane]); + } dwFlags[pane] |= FFILEOPEN_NOMRU | (pDoc->GetReadOnly(nPane[pane]) ? FFILEOPEN_READONLY : 0); } - if (id == ID_MERGE_COMPARE_HEX) - GetMainFrame()->ShowHexMergeDoc(pDoc, paths.GetSize(), fileloc, dwFlags, nullptr); + if (ID_UNPACKERS_FIRST <= id && id <= ID_UNPACKERS_LAST) + { + PackingInfo infoUnpacker( + CMainFrame::GetPluginPipelineByMenuId(id, FileTransform::UnpackerEventNames, ID_UNPACKERS_FIRST)); + GetMainFrame()->DoFileOrFolderOpen(&paths, dwFlags, strDesc, _T(""), + ctxt.m_bRecursive, nullptr, &infoUnpacker, nullptr, 0); + } else - GetMainFrame()->ShowImgMergeDoc(pDoc, paths.GetSize(), fileloc, dwFlags, nullptr); + { + PackingInfo* infoUnpacker = nullptr; + PrediffingInfo* infoPrediffer = nullptr; + GetDiffContext().FetchPluginInfos(CDiffContext::GetFilteredFilenames(filteredPaths), &infoUnpacker, &infoPrediffer); + GetMainFrame()->ShowMergeDoc(id, pDoc, paths.GetSize(), fileloc, dwFlags, strDesc, _T(""), infoUnpacker); + } } /// User chose (context menu) delete left @@ -1579,13 +1667,32 @@ void CDirView::OnUpdateCtxtDirCopyBothDiffsOnlyTo(CCmdUI* pCmdUI) } /** + * @brief Update "Copy | Left/Right/Both " item + */ +template +void CDirView::OnUpdateCtxtDirCopy2(CCmdUI* pCmdUI) +{ + Counts counts = Count(&DirActions::IsItemCopyableToOn); + pCmdUI->Enable(counts.count > 0); + pCmdUI->SetText(FormatMenuItemString(stype, counts.count, counts.total).c_str()); +} + +void CDirView::OnUpdateCtxtDirCopyBoth2(CCmdUI* pCmdUI) +{ + Counts counts = Count(&DirActions::IsItemCopyableBothToOn); + pCmdUI->Enable(counts.count > 0); + pCmdUI->SetText(FormatMenuItemStringAll(GetDocument()->m_nDirs, counts.count, counts.total).c_str()); +} + +/** * @brief Get keydata associated with item in given index. * @param [in] idx Item's index to list in UI. * @return Key for item in given index. */ DIFFITEM *CDirView::GetItemKey(int idx) const { - return (DIFFITEM *) m_pList->GetItemData(idx); + ASSERT(idx >= 0 && idx < static_cast(m_listViewItems.size())); + return reinterpret_cast(m_listViewItems[idx].lParam); } // SetItemKey & GetItemKey encapsulate how the display list items @@ -1611,7 +1718,7 @@ DIFFITEM &CDirView::GetDiffItem(int sel) DIFFITEM *diffpos = GetItemKey(sel); // If it is special item, return empty DIFFITEM - if (diffpos == (DIFFITEM *)SPECIAL_ITEM_POS) + if (IsDiffItemSpecial(diffpos)) { return *DIFFITEM::GetEmptyItem(); } @@ -1620,20 +1727,45 @@ DIFFITEM &CDirView::GetDiffItem(int sel) void CDirView::DeleteItem(int sel, bool removeDIFFITEM) { + DIFFITEM *diffpos = GetItemKey(sel); + if (IsDiffItemSpecial(diffpos)) + return; if (m_bTreeMode) + { CollapseSubdir(sel); - if (removeDIFFITEM) + m_listViewItems.erase(m_listViewItems.begin() + sel); + m_pList->DeleteItem(sel); + } + else if (GetDiffContext().m_bRecursive || diffpos->HasChildren()) { - DIFFITEM *diffpos = GetItemKey(sel); - if (diffpos != (DIFFITEM *)SPECIAL_ITEM_POS) + DirItemIterator it; + for (it = RevBegin(); it != RevEnd(); ) { - if (diffpos->HasChildren()) - diffpos->RemoveChildren(); - diffpos->DelinkFromSiblings(); - delete diffpos; + DIFFITEM& di = *it; + int cursel = it.m_sel; + ++it; + if (di.IsAncestor(diffpos) || diffpos == &di) + { + m_listViewItems.erase(m_listViewItems.begin() + cursel); + m_pList->DeleteItem(cursel); + } } } - m_pList->DeleteItem(sel); + else + { + m_listViewItems.erase(m_listViewItems.begin() + sel); + m_pList->DeleteItem(sel); + } + if (removeDIFFITEM) + { + if (diffpos->HasChildren()) + diffpos->RemoveChildren(); + diffpos->DelinkFromSiblings(); + delete diffpos; + } + + m_firstDiffItem.reset(); + m_lastDiffItem.reset(); } void CDirView::DeleteAllDisplayItems() @@ -1641,6 +1773,10 @@ void CDirView::DeleteAllDisplayItems() // item data are just positions (diffposes) // that is, they contain no memory needing to be freed m_pList->DeleteAllItems(); + m_listViewItems.clear(); + + m_firstDiffItem.reset(); + m_lastDiffItem.reset(); } /** @@ -1649,11 +1785,12 @@ void CDirView::DeleteAllDisplayItems() */ int CDirView::GetItemIndex(DIFFITEM *key) { - LVFINDINFO findInfo; - - findInfo.flags = LVFI_PARAM; // Search for itemdata - findInfo.lParam = (LPARAM)key; - return m_pList->FindItem(&findInfo); + for (size_t i = 0; i < m_listViewItems.size(); ++i) + { + if (m_listViewItems[i].lParam == reinterpret_cast(key)) + return static_cast(i); + } + return 0; } /** @@ -1663,7 +1800,7 @@ int CDirView::GetItemIndex(DIFFITEM *key) void CDirView::GetItemFileNames(int sel, String& strLeft, String& strRight) const { DIFFITEM *diffpos = GetItemKey(sel); - if (diffpos == (DIFFITEM *)SPECIAL_ITEM_POS) + if (IsDiffItemSpecial(diffpos)) { strLeft.erase(); strRight.erase(); @@ -1682,7 +1819,7 @@ void CDirView::GetItemFileNames(int sel, String& strLeft, String& strRight) cons void CDirView::GetItemFileNames(int sel, PathContext * paths) const { DIFFITEM *diffpos = GetItemKey(sel); - if (diffpos == (DIFFITEM *)SPECIAL_ITEM_POS) + if (IsDiffItemSpecial(diffpos)) { for (int nIndex = 0; nIndex < GetDocument()->m_nDirs; nIndex++) paths->SetPath(nIndex, _T("")); @@ -1709,11 +1846,7 @@ void CDirView::DoOpen(SIDE_TYPE stype) DirItemIterator dirBegin = SelBegin(); String file = GetSelectedFileName(dirBegin, stype, GetDiffContext()); if (file.empty()) return; - HINSTANCE rtn = ShellExecute(::GetDesktopWindow(), _T("edit"), file.c_str(), 0, 0, SW_SHOWNORMAL); - if (reinterpret_cast(rtn) == SE_ERR_NOASSOC) - rtn = ShellExecute(::GetDesktopWindow(), _T("open"), file.c_str(), 0, 0, SW_SHOWNORMAL); - if (reinterpret_cast(rtn) == SE_ERR_NOASSOC) - DoOpenWith(stype); + shell::Edit(file.c_str()); } /// Open with dialog for file on selected side @@ -1724,11 +1857,7 @@ void CDirView::DoOpenWith(SIDE_TYPE stype) DirItemIterator dirBegin = SelBegin(); String file = GetSelectedFileName(dirBegin, stype, GetDiffContext()); if (file.empty()) return; - CString sysdir; - if (!GetSystemDirectory(sysdir.GetBuffer(MAX_PATH), MAX_PATH)) return; - sysdir.ReleaseBuffer(); - CString arg = (CString)_T("shell32.dll,OpenAs_RunDLL ") + file.c_str(); - ShellExecute(::GetDesktopWindow(), 0, _T("RUNDLL32.EXE"), arg, sysdir, SW_SHOWNORMAL); + shell::OpenWith(file.c_str()); } /// Open selected file on specified side to external editor @@ -1740,7 +1869,7 @@ void CDirView::DoOpenWithEditor(SIDE_TYPE stype) String file = GetSelectedFileName(dirBegin, stype, GetDiffContext()); if (file.empty()) return; - theApp.OpenFileToExternalEditor(file); + CMergeApp::OpenFileToExternalEditor(file); } void CDirView::DoOpenParentFolder(SIDE_TYPE stype) @@ -1750,8 +1879,7 @@ void CDirView::DoOpenParentFolder(SIDE_TYPE stype) DirItemIterator dirBegin = SelBegin(); String file = GetSelectedFileName(dirBegin, stype, GetDiffContext()); if (file.empty()) return; - String parentFolder = paths::GetParentPath(file); - ShellExecute(::GetDesktopWindow(), _T("open"), parentFolder.c_str(), 0, 0, SW_SHOWNORMAL); + shell::OpenParentFolder(file.c_str()); } /// User chose (context menu) open left @@ -1825,7 +1953,7 @@ void CDirView::OnUpdateCtxtDirOpenParentFolder(CCmdUI* pCmdUI) } // Used for Open -void CDirView::DoUpdateOpen(SELECTIONTYPE selectionType, CCmdUI* pCmdUI) +void CDirView::DoUpdateOpen(SELECTIONTYPE selectionType, CCmdUI* pCmdUI, bool openableForDir /*= true*/) { int sel1 = -1, sel2 = -1, sel3 = -1; if (!GetSelectedItems(&sel1, &sel2, &sel3)) @@ -1842,13 +1970,22 @@ void CDirView::DoUpdateOpen(SELECTIONTYPE selectionType, CCmdUI* pCmdUI) pCmdUI->Enable(FALSE); return; } + if (!openableForDir) + { + const DIFFITEM& di1 = GetDiffItem(sel1); + if (di1.diffcode.isDirectory() || IsDiffItemSpecial(GetItemKey(sel1))) + { + pCmdUI->Enable(FALSE); + return; + } + } } else if (sel3 == -1) { // Two items selected const DIFFITEM& di1 = GetDiffItem(sel1); const DIFFITEM& di2 = GetDiffItem(sel2); - if (!AreItemsOpenable(GetDiffContext(), selectionType, di1, di2)) + if (!AreItemsOpenable(GetDiffContext(), selectionType, di1, di2, openableForDir)) { pCmdUI->Enable(FALSE); return; @@ -1860,7 +1997,7 @@ void CDirView::DoUpdateOpen(SELECTIONTYPE selectionType, CCmdUI* pCmdUI) const DIFFITEM& di1 = GetDiffItem(sel1); const DIFFITEM& di2 = GetDiffItem(sel2); const DIFFITEM& di3 = GetDiffItem(sel3); - if (selectionType != SELECTIONTYPE_NORMAL || !::AreItemsOpenable(GetDiffContext(), di1, di2, di3)) + if (selectionType != SELECTIONTYPE_NORMAL || !::AreItemsOpenable(GetDiffContext(), di1, di2, di3, openableForDir)) { pCmdUI->Enable(FALSE); return; @@ -1986,6 +2123,123 @@ void CDirView::OpenPrevDiff() } } +void CDirView::OpenFirstFile() +{ + int currentInd = GetFocusedItem(); + int firstFileInd = 0; + // Skip directories + while (firstFileInd <= currentInd) + { + DIFFITEM& dip = GetDiffItem(firstFileInd); + if (!dip.diffcode.isDirectory()) + { + MoveFocus(currentInd, firstFileInd, 1); + OpenSelection(); + break; + } + firstFileInd++; + } +} + +bool CDirView::IsFirstFile() +{ + int currentInd = GetFocusedItem(); + int firstFileInd = 0; + while (firstFileInd <= currentInd) + { + DIFFITEM& dip = GetDiffItem(firstFileInd); + if (!dip.diffcode.isDirectory()) + { + if (currentInd == firstFileInd) + return true; + else + return false; + } + firstFileInd++; + } + return false; +} + +void CDirView::OpenLastFile() +{ + const int count = m_pList->GetItemCount(); + int currentInd = GetFocusedItem(); + int lastFileInd = count - 1; + // Skip directories + while (lastFileInd >= 0) + { + DIFFITEM& dip = GetDiffItem(lastFileInd); + if (!dip.diffcode.isDirectory()) + { + MoveFocus(currentInd, lastFileInd, 1); + OpenSelection(); + break; + } + lastFileInd--; + } +} + +bool CDirView::IsLastFile() +{ + const int count = m_pList->GetItemCount(); + int currentInd = GetFocusedItem(); + int lastFileInd = count - 1; + while (lastFileInd >= currentInd) + { + DIFFITEM& dip = GetDiffItem(lastFileInd); + if (!dip.diffcode.isDirectory()) + { + if (currentInd == lastFileInd) + return true; + else + return false; + } + lastFileInd--; + } + return false; +} + +void CDirView::OpenNextFile() +{ + const int count = m_pList->GetItemCount(); + int currentInd = GetFocusedItem(); + int nextInd = currentInd + 1; + if (currentInd >= 0) + { + while (nextInd < count) + { + DIFFITEM& dip = GetDiffItem(nextInd); + MoveFocus(nextInd - 1, nextInd, 1); + if (!dip.diffcode.isDirectory()) + { + OpenSelection(); + break; + } + nextInd++; + } + } +} + +void CDirView::OpenPrevFile() +{ + int currentInd = GetFocusedItem(); + int prevInd = currentInd - 1; + if (currentInd >= 0) + { + while (prevInd >= 0) + { + DIFFITEM& dip = GetDiffItem(prevInd); + MoveFocus(prevInd + 1, prevInd, 1); + if (!dip.diffcode.isDirectory()) + { + OpenSelection(); + break; + } + prevInd--; + } + } +} + void CDirView::SetActivePane(int pane) { if (m_nActivePane >= 0) @@ -2056,28 +2310,24 @@ int CDirView::GetFocusedItem() int CDirView::GetFirstDifferentItem() { - if (!m_bNeedSearchFirstDiffItem) - return m_firstDiffItem; - - DirItemIterator it = - std::find_if(Begin(), End(), MakeDirActions(&DirActions::IsItemNavigableDiff)); - m_firstDiffItem = it.m_sel; - m_bNeedSearchFirstDiffItem = false; - - return m_firstDiffItem; + if (!m_firstDiffItem.has_value()) + { + DirItemIterator it = + std::find_if(Begin(), End(), MakeDirActions(&DirActions::IsItemNavigableDiff)); + m_firstDiffItem = it.m_sel; + } + return m_firstDiffItem.value(); } int CDirView::GetLastDifferentItem() { - if (!m_bNeedSearchLastDiffItem) - return m_lastDiffItem; - - DirItemIterator it = - std::find_if(RevBegin(), RevEnd(), MakeDirActions(&DirActions::IsItemNavigableDiff)); - m_lastDiffItem = it.m_sel; - m_bNeedSearchLastDiffItem = false; - - return m_lastDiffItem; + if (!m_lastDiffItem.has_value()) + { + DirItemIterator it = + std::find_if(RevBegin(), RevEnd(), MakeDirActions(&DirActions::IsItemNavigableDiff)); + m_lastDiffItem = it.m_sel; + } + return m_lastDiffItem.value(); } /** @@ -2095,6 +2345,7 @@ void CDirView::MoveFocus(int currentInd, int i, int selCount) m_pList->SetItemState(currentInd, 0, LVIS_SELECTED); m_pList->SetItemState(currentInd, 0, LVIS_FOCUSED); m_pList->SetItemState(i, LVIS_SELECTED, LVIS_SELECTED); + m_pList->SetSelectionMark(i); } // Move focus to specified item @@ -2112,7 +2363,7 @@ CDirFrame * CDirView::GetParentFrame() { // can't verify cast without introducing more coupling // (CDirView doesn't include DirFrame.h) - return static_cast(CListView::GetParentFrame()); + return static_cast(__super::GetParentFrame()); } void CDirView::OnRefresh() @@ -2131,13 +2382,13 @@ BOOL CDirView::PreTranslateMessage(MSG* pMsg) // Check if we got 'ESC pressed' -message if (pMsg->wParam == VK_ESCAPE) { - if (m_pCmpProgressBar != nullptr) + if (GetDocument()->m_diffThread.GetThreadState() == CDiffThread::THREAD_COMPARING) { - OnBnClickedComparisonStop(); + GetDocument()->AbortCurrentScan(); return TRUE; } - if (m_bEscCloses) + if (m_nEscCloses != 0) { AfxGetMainWnd()->PostMessage(WM_COMMAND, ID_FILE_CLOSE); return FALSE; @@ -2155,7 +2406,7 @@ BOOL CDirView::PreTranslateMessage(MSG* pMsg) { if (!GetDiffContext().m_bRecursive) { - OpenParentDirectory(); + OpenParentDirectory(GetDocument()); return FALSE; } else if (m_bTreeMode && sel >= 0) @@ -2223,7 +2474,7 @@ BOOL CDirView::PreTranslateMessage(MSG* pMsg) } } } - return CListView::PreTranslateMessage(pMsg); + return __super::PreTranslateMessage(pMsg); } void CDirView::OnUpdateRefresh(CCmdUI* pCmdUI) @@ -2244,12 +2495,19 @@ LRESULT CDirView::OnUpdateUIMessage(WPARAM wParam, LPARAM lParam) CDirDoc * pDoc = GetDocument(); ASSERT(pDoc != nullptr); + // Since the Collect thread deletes the DiffItems in the rescan by "Update selection", + // the UI update process should not be executed until the Collect thread process is completed + // to avoid accessing the deleted DiffItem. + if (pDoc->m_diffThread.IsMarkedRescan() && pDoc->m_diffThread.GetCollectThreadState() != CDiffThread::THREAD_COMPLETED) + { + ASSERT(0); + return 0; // return value unused + } + if (wParam == CDiffThread::EVENT_COMPARE_COMPLETED) { - // Close and destroy the dialog after compare - if (m_pCmpProgressBar != nullptr) - GetParentFrame()->ShowControlBar(m_pCmpProgressBar.get(), FALSE, FALSE); - m_pCmpProgressBar.reset(); + if (pDoc->GetDiffContext().m_pPropertySystem && pDoc->GetDiffContext().m_pPropertySystem->HasHashProperties()) + pDoc->GetDiffContext().CreateDuplicateValueMap(); pDoc->CompareReady(); @@ -2268,11 +2526,9 @@ LRESULT CDirView::OnUpdateUIMessage(WPARAM wParam, LPARAM lParam) MoveFocus(0, 0, 0); // If compare took more than TimeToSignalCompare seconds, notify user - clock_t elapsed = clock() - m_compareStart; - GetParentFrame()->SetStatus( - strutils::format(_("Elapsed time: %ld ms"), elapsed).c_str() - ); - if (elapsed > TimeToSignalCompare * CLOCKS_PER_SEC) + m_elapsed = clock() - m_compareStart; + SetTimer(STATUSBAR_UPDATE, 150, nullptr); + if (m_elapsed > TimeToSignalCompare * CLOCKS_PER_SEC) MessageBeep(IDOK); GetMainFrame()->StartFlashing(); } @@ -2295,12 +2551,13 @@ LRESULT CDirView::OnUpdateUIMessage(WPARAM wParam, LPARAM lParam) else Redisplay(); } + + HideItems(GetDiffContext().m_vCurrentlyHiddenItems); } return 0; // return value unused } - BOOL CDirView::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) { NMHDR * hdr = reinterpret_cast(lParam); @@ -2309,7 +2566,7 @@ BOOL CDirView::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) if (hdr->code == HDN_BEGINDRAG) return OnHeaderBeginDrag((LPNMHEADER)hdr, pResult); - return CListView::OnNotify(wParam, lParam, pResult); + return __super::OnNotify(wParam, lParam, pResult); } BOOL CDirView::OnChildNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult) @@ -2327,7 +2584,7 @@ BOOL CDirView::OnChildNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* p return TRUE; } } - return CListView::OnChildNotify(uMsg, wParam, lParam, pResult); + return __super::OnChildNotify(uMsg, wParam, lParam, pResult); } /** @@ -2337,8 +2594,8 @@ bool CDirView::OnHeaderBeginDrag(LPNMHEADER hdr, LRESULT* pResult) { // save column widths before user reorders them // so we can reload them on the end drag - String secname = GetDocument()->m_nDirs < 3 ? _T("DirView") : _T("DirView3"); - theApp.WriteProfileString(secname.c_str(), _T("ColumnWidths"), + const String keyname = GetDocument()->m_nDirs < 3 ? OPT_DIRVIEW_COLUMN_WIDTHS : OPT_DIRVIEW3_COLUMN_WIDTHS; + GetOptionsMgr()->SaveOption(keyname, m_pColItems->SaveColumnWidths(std::bind(&CListCtrl::GetColumnWidth, m_pList, _1)).c_str()); return true; } @@ -2428,18 +2685,28 @@ void CDirView::OnTimer(UINT_PTR nIDEvent) // Now redraw screen UpdateColumnNames(); m_pColItems->LoadColumnWidths( - (const TCHAR *)theApp.GetProfileString(GetDocument()->m_nDirs < 3 ? _T("DirView") : _T("DirView3"), _T("ColumnWidths")), - std::bind(&CListCtrl::SetColumnWidth, m_pList, _1, _2), DefColumnWidth); + GetOptionsMgr()->GetString(GetDocument()->m_nDirs < 3 ? OPT_DIRVIEW_COLUMN_WIDTHS : OPT_DIRVIEW3_COLUMN_WIDTHS), + std::bind(&CListCtrl::SetColumnWidth, m_pList, _1, _2), GetDefColumnWidth()); Redisplay(); } else if (nIDEvent == STATUSBAR_UPDATE) { + KillTimer(STATUSBAR_UPDATE); int items = GetSelectedCount(); - String msg = (items == 1) ? _("1 item selected") : strutils::format_string1(_("%1 items selected"), strutils::to_str(items)); + String msg; + if (m_elapsed != 0) + { + msg = strutils::format(_("Elapsed time: %ld ms"), m_elapsed); + m_elapsed = 0; + } + else + { + msg = (items == 1) ? _("1 item selected") : strutils::format_string1(_("%1 items selected"), strutils::to_str(items)); + } GetParentFrame()->SetStatus(msg.c_str()); } - CListView::OnTimer(nIDEvent); + __super::OnTimer(nIDEvent); } /** @@ -2507,26 +2774,28 @@ void CDirView::OnCustomizeColumns() { // Located in DirViewColHandler.cpp OnEditColumns(); - String secname = GetDocument()->m_nDirs < 3 ? _T("DirView") : _T("DirView3"); - theApp.WriteProfileString(secname.c_str(), _T("ColumnOrders"), m_pColItems->SaveColumnOrders().c_str()); + const String keyname = GetDocument()->m_nDirs < 3 ? OPT_DIRVIEW_COLUMN_ORDERS : OPT_DIRVIEW3_COLUMN_ORDERS; + GetOptionsMgr()->SaveOption(keyname, m_pColItems->SaveColumnOrders()); } -void CDirView::OnCtxtOpenWithUnpacker() +void CDirView::OnOpenWithUnpacker() { int sel = -1; sel = m_pList->GetNextItem(sel, LVNI_SELECTED); if (sel != -1) { + PackingInfo* infoUnpacker = nullptr; + PrediffingInfo* infoPrediffer = nullptr; + CDiffContext& ctxt = GetDiffContext(); + String filteredFilenames = ctxt.GetFilteredFilenames(GetDiffItem(sel)); + ctxt.FetchPluginInfos(filteredFilenames, &infoUnpacker, &infoPrediffer); // let the user choose a handler - CSelectUnpackerDlg dlg(GetDiffItem(sel).diffFileInfo[0].filename, this); - // create now a new infoUnpacker to initialize the manual/automatic flag - PackingInfo infoUnpacker(PLUGIN_AUTO); - dlg.SetInitialInfoHandler(&infoUnpacker); - + CSelectPluginDlg dlg(infoUnpacker->GetPluginPipeline(), filteredFilenames, + CSelectPluginDlg::PluginType::Unpacker, false, this); if (dlg.DoModal() == IDOK) { - infoUnpacker = dlg.GetInfoHandler(); - OpenSelection(SELECTIONTYPE_NORMAL, &infoUnpacker); + PackingInfo infoUnpackerNew(dlg.GetPluginPipeline()); + OpenSelection(SELECTIONTYPE_NORMAL, &infoUnpackerNew, false); } } @@ -2548,6 +2817,11 @@ void CDirView::OnUpdateCtxtOpenWithUnpacker(CCmdUI* pCmdUI) int sel = -1; sel = m_pList->GetNextItem(sel, LVNI_SELECTED); const DIFFITEM& di = GetDiffItem(sel); + if (di.diffcode.isDirectory()) + { + pCmdUI->Enable(FALSE); + return; + } pCmdUI->Enable(IsItemDeletableOnBoth(GetDiffContext(), di)); } } @@ -2570,6 +2844,7 @@ std::vector CDirView::GetCurrentColRegKeys() struct FileCmpReport: public IFileCmpReport { explicit FileCmpReport(CDirView *pDirView) : m_pDirView(pDirView) {} + ~FileCmpReport() override {} bool operator()(REPORT_TYPE nReportType, IListCtrl *pList, int nIndex, const String &sDestDir, String &sLinkPath) override { const CDiffContext& ctxt = m_pDirView->GetDiffContext(); @@ -2583,7 +2858,7 @@ struct FileCmpReport: public IFileCmpReport return false; } - sLinkPath = di.diffFileInfo[0].GetFile(); + sLinkPath = strutils::format(_T("%d_"), nIndex) + di.diffFileInfo[0].GetFile(); strutils::replace(sLinkPath, _T("\\"), _T("_")); sLinkPath += _T(".html"); @@ -2616,14 +2891,10 @@ private: LRESULT CDirView::OnGenerateFileCmpReport(WPARAM wParam, LPARAM lParam) { OpenSelection(); - CFrameWnd * pFrame = GetMainFrame()->GetActiveFrame(); - IMergeDoc * pMergeDoc = dynamic_cast(pFrame->GetActiveDocument()); - if (pMergeDoc == nullptr) - pMergeDoc = dynamic_cast(pFrame); auto *pReportFileName = reinterpret_cast(wParam); bool *pCompleted = reinterpret_cast(lParam); - if (pMergeDoc != nullptr) + if (IMergeDoc * pMergeDoc = GetMainFrame()->GetActiveIMergeDoc()) { pMergeDoc->GenerateReport(pReportFileName); pMergeDoc->CloseNow(); @@ -2665,7 +2936,7 @@ void CDirView::OnToolsGenerateReport() pReport->SetRootPaths(paths); pReport->SetColumns(m_pColItems->GetDispColCount()); pReport->SetFileCmpReport(new FileCmpReport(this)); - pReport->SetList(new IListCtrlImpl(m_pList->m_hWnd)); + pReport->SetList(new IListCtrlImpl(m_pList->m_hWnd, m_listViewItems)); pReport->SetReportType(dlg.m_nReportType); pReport->SetReportFile(dlg.m_sReportFile); pReport->SetCopyToClipboard(dlg.m_bCopyToClipboard); @@ -2697,12 +2968,6 @@ void CDirView::OnToolsGeneratePatch() MB_DONT_DISPLAY_AGAIN, IDS_CANNOT_CREATE_BINARYPATCH); bValidFiles = false; } - else if (item.diffcode.isDirectory()) - { - LangMessageBox(IDS_CANNOT_CREATE_DIRPATCH, MB_ICONWARNING | - MB_DONT_DISPLAY_AGAIN, IDS_CANNOT_CREATE_DIRPATCH); - bValidFiles = false; - } if (bValidFiles) { @@ -2748,11 +3013,11 @@ int CDirView::AddSpecialItems() { case AllowUpwardDirectory::No: bEnable = false; - // fall through + [[fallthrough]]; default: AddParentFolderItem(bEnable); retVal = 1; - // fall through + [[fallthrough]]; case AllowUpwardDirectory::Never: break; } @@ -2845,7 +3110,7 @@ void CDirView::OnSelectAll() { // Don't select special items (SPECIAL_ITEM_POS) DIFFITEM *diffpos = GetItemKey(i); - if (diffpos != (DIFFITEM *)SPECIAL_ITEM_POS) + if (!IsDiffItemSpecial(diffpos)) m_pList->SetItemState(i, LVIS_SELECTED, LVIS_SELECTED); } } @@ -2863,16 +3128,44 @@ void CDirView::OnUpdateSelectAll(CCmdUI* pCmdUI) /** * @brief Handle clicks in plugin context view in list */ -void CDirView::OnPluginPredifferMode(UINT nID) +void CDirView::OnPluginSettings(UINT nID) { - ApplyPluginPrediffSetting(SelBegin(), SelEnd(), GetDiffContext(), - (nID == ID_PREDIFF_AUTO) ? PLUGIN_AUTO : PLUGIN_MANUAL); + bool unpacker = (ID_UNPACKER_SETTINGS_NONE <= nID && nID <= ID_UNPACKER_SETTINGS_SELECT); + String pluginPipeline; + switch (nID) + { + case ID_PREDIFFER_SETTINGS_NONE: + case ID_UNPACKER_SETTINGS_NONE: + pluginPipeline.clear(); + break; + case ID_PREDIFFER_SETTINGS_AUTO: + case ID_UNPACKER_SETTINGS_AUTO: + pluginPipeline = _T(""); + break; + case ID_PREDIFFER_SETTINGS_SELECT: + case ID_UNPACKER_SETTINGS_SELECT: + int sel = m_pList->GetNextItem(-1, LVNI_SELECTED); + PackingInfo* infoUnpacker = nullptr; + PrediffingInfo* infoPrediffer = nullptr; + CDiffContext& ctxt = GetDiffContext(); + String filteredFilenames = ctxt.GetFilteredFilenames(GetDiffItem(sel)); + ctxt.FetchPluginInfos(filteredFilenames, &infoUnpacker, &infoPrediffer); + GetDiffContext().FetchPluginInfos(filteredFilenames, &infoUnpacker, &infoPrediffer); + CSelectPluginDlg dlg(infoUnpacker->GetPluginPipeline(), filteredFilenames, + unpacker ? CSelectPluginDlg::PluginType::Unpacker : CSelectPluginDlg::PluginType::Prediffer, false, this); + if (dlg.DoModal() != IDOK) + return; + pluginPipeline = dlg.GetPluginPipeline(); + break; + } + ApplyPluginPipeline(SelBegin(), SelEnd(), GetDiffContext(), unpacker, pluginPipeline); + Invalidate(); } /** * @brief Updates just before displaying plugin context view in list */ -void CDirView::OnUpdatePluginPredifferMode(CCmdUI* pCmdUI) +void CDirView::OnUpdatePluginMode(CCmdUI* pCmdUI) { // 2004-04-03, Perry // CMainFrame::OnUpdatePluginUnpackMode handles this for global unpacking @@ -2887,10 +3180,12 @@ void CDirView::OnUpdatePluginPredifferMode(CCmdUI* pCmdUI) if (pPopup == nullptr) return; - std::pair counts = CountPredifferYesNo(SelBegin(), SelEnd(), GetDiffContext()); + bool unpacker = (ID_UNPACKER_SETTINGS_NONE <= pCmdUI->m_nID && pCmdUI->m_nID <= ID_UNPACKER_SETTINGS_SELECT); + auto counts = CountPluginNoneAutoOthers(SelBegin(), SelEnd(), GetDiffContext(), unpacker); - CheckContextMenu(pPopup, ID_PREDIFF_AUTO, (counts.first > 0)); - CheckContextMenu(pPopup, ID_PREDIFF_MANUAL, (counts.second > 0)); + CheckContextMenu(pPopup, unpacker ? ID_UNPACKER_SETTINGS_NONE : ID_PREDIFFER_SETTINGS_NONE, (std::get<0>(counts) > 0)); + CheckContextMenu(pPopup, unpacker ? ID_UNPACKER_SETTINGS_AUTO : ID_PREDIFFER_SETTINGS_AUTO, (std::get<1>(counts) > 0)); + CheckContextMenu(pPopup, unpacker ? ID_UNPACKER_SETTINGS_SELECT : ID_PREDIFFER_SETTINGS_SELECT, (std::get<2>(counts) > 0)); } /** @@ -2898,10 +3193,12 @@ void CDirView::OnUpdatePluginPredifferMode(CCmdUI* pCmdUI) */ void CDirView::RefreshOptions() { - m_bEscCloses = GetOptionsMgr()->GetBool(OPT_CLOSE_WITH_ESC); + m_nEscCloses = GetOptionsMgr()->GetInt(OPT_CLOSE_WITH_ESC); m_bExpandSubdirs = GetOptionsMgr()->GetBool(OPT_DIRVIEW_EXPAND_SUBDIRS); Options::DirColors::Load(GetOptionsMgr(), m_cachedColors); m_bUseColors = GetOptionsMgr()->GetBool(OPT_DIRCLR_USE_COLORS); + m_pList->SetBkColor(m_bUseColors ? m_cachedColors.clrDirMargin : GetSysColor(COLOR_WINDOW)); + Invalidate(); } /** @@ -2980,7 +3277,12 @@ void CDirView::OnItemRename() void CDirView::OnUpdateItemRename(CCmdUI* pCmdUI) { bool bEnabled = (1 == m_pList->GetSelectedCount()); - pCmdUI->Enable(bEnabled && SelBegin() != SelEnd()); + if (bEnabled) + { + Counts counts = Count(&DirActions::IsItemRenamable); + bEnabled = (counts.count > 0 && counts.total == 1); + } + pCmdUI->Enable(bEnabled); } /** @@ -2988,15 +3290,64 @@ void CDirView::OnUpdateItemRename(CCmdUI* pCmdUI) */ void CDirView::OnHideFilenames() { + CDiffContext& ctxt = GetDiffContext(); + int selection_index; + String hiddden_item_path; + m_pList->SetRedraw(FALSE); // Turn off updating (better performance) DirItemIterator it; + while ((it = SelRevBegin()) != SelRevEnd()) { DIFFITEM &di = *it; + selection_index = it.m_sel; + hiddden_item_path = di.getItemRelativePath(); SetItemViewFlag(di, ViewCustomFlags::HIDDEN, ViewCustomFlags::VISIBILITY); - DeleteItem(it.m_sel); - m_nHiddenItems++; + DeleteItem(selection_index); + ctxt.m_vCurrentlyHiddenItems.push_back(hiddden_item_path); + } + m_pList->SetRedraw(TRUE); // Turn updating back on +} + +/** + * @brief determine if an item-relative-path is contained in the list of items to hide + */ +bool CDirView::IsItemToHide(const String& currentItem, const std::vector& ItemsToHide) const +{ + return std::find(ItemsToHide.begin(), ItemsToHide.end(), currentItem) != ItemsToHide.end(); +} + +/** + * @brief hides items specified in the .winmerge file + */ + +void CDirView::HideItems(const std::vector& ItemsToHide) +{ + CDiffContext& ctxt = GetDiffContext(); + DIFFITEM *diffpos = ctxt.GetFirstDiffPosition(); + while (diffpos != nullptr) + { + DIFFITEM &di = ctxt.GetNextDiffRefPosition(diffpos); + if (IsItemToHide(di.getItemRelativePath(), ItemsToHide)) + SetItemViewFlag(di, ViewCustomFlags::HIDDEN, ViewCustomFlags::VISIBILITY); } + + m_pList->SetRedraw(FALSE); // Turn off updating (better performance) + + int num_hidden = 0; + const size_t num_to_hide = ItemsToHide.size(); + DirItemIterator it = RevBegin(); + while((num_hidden < num_to_hide) && (it != RevEnd())) + { + DIFFITEM& di = *it; + if (di.customFlags & ViewCustomFlags::HIDDEN) + { + DeleteItem(it.m_sel); + num_hidden++; + } + ++it; + } + m_pList->SetRedraw(TRUE); // Turn updating back on } @@ -3031,7 +3382,7 @@ void CDirView::OnUpdateCtxtDirMoveTo(CCmdUI* pCmdUI) */ void CDirView::OnSize(UINT nType, int cx, int cy) { - CListView::OnSize(nType, cx, cy); + __super::OnSize(nType, cx, cy); GetDocument()->SetTitle(nullptr); } @@ -3064,9 +3415,7 @@ void CDirView::OnItemChanged(NMHDR* pNMHDR, LRESULT* pResult) if ((pNMListView->uOldState & LVIS_SELECTED) != (pNMListView->uNewState & LVIS_SELECTED)) { - int items = GetSelectedCount(); - String msg = (items == 1) ? _("1 item selected") : strutils::format_string1(_("%1 items selected"), strutils::to_str(items)); - GetParentFrame()->SetStatus(msg.c_str()); + SetTimer(STATUSBAR_UPDATE, 100, nullptr); } *pResult = 0; } @@ -3078,7 +3427,8 @@ void CDirView::OnItemChanged(NMHDR* pNMHDR, LRESULT* pResult) */ afx_msg void CDirView::OnBeginLabelEdit(NMHDR* pNMHDR, LRESULT* pResult) { - *pResult = (SelBegin() == SelEnd()); + Counts counts = Count(&DirActions::IsItemRenamable); + *pResult = !(counts.count > 0 && counts.total == 1); // If label edit is allowed. if (*pResult == FALSE) @@ -3132,16 +3482,75 @@ afx_msg void CDirView::OnEndLabelEdit(NMHDR* pNMHDR, LRESULT* pResult) CString sText; pEdit->GetWindowText(sText); - if (!sText.IsEmpty()) + if (!sText.IsEmpty() && paths::IsValidName(String(sText))) { try { - DirItemIterator dirBegin = SelBegin(); - *pResult = DoItemRename(dirBegin, GetDiffContext(), String(sText)); + DirItemIterator it(m_pIList.get(), reinterpret_cast(pNMHDR)->item.iItem); + DIFFITEM& di = *it; + unsigned sideFlags = (di.diffcode.diffcode & DIFFCODE::SIDEFLAGS); + *pResult = DoItemRename(it, GetDiffContext(), String(sText)); + // Rescan the item if side flags change due to renaming. + if (*pResult) + { + if ((di.diffcode.diffcode & DIFFCODE::SIDEFLAGS) != sideFlags) + { + // Delete the item with the same file name as after renaming. + if (di.HasParent()) + { + for (DIFFITEM* pItem = di.GetParentLink()->GetFirstChild(); pItem != nullptr; pItem = pItem->GetFwdSiblingLink()) + { + if ((pItem != &di) && (pItem->diffcode.isDirectory() == di.diffcode.isDirectory()) && (collstr(pItem->diffFileInfo[0].filename, di.diffFileInfo[0].filename, false) == 0)) + { + pItem->DelinkFromSiblings(); + delete pItem; + break; + } + } + } + // Rescan the item. + MarkForRescan(di); + m_pSavedTreeState.reset(SaveTreeState(GetDiffContext())); + GetDocument()->SetMarkedRescan(); + GetDocument()->Rescan(); + } + else { + int nDirs = GetDiffContext().GetCompareDirs(); + assert(nDirs == 2 || nDirs == 3); + UpdatePaths(nDirs, di); + + int nIdx = reinterpret_cast(pNMHDR)->item.iItem; + UpdateDiffItemStatus(nIdx); + } + } } catch (ContentsChangedException& e) { AfxMessageBox(e.m_msg.c_str(), MB_ICONWARNING); } } + else + { + LangMessageBox(IDS_ERROR_INVALID_DIR_FILE_NAME, MB_ICONWARNING); + } + } +} + +void CDirView::OnODFindItem(NMHDR* pNMHDR, LRESULT* pResult) +{ + NMLVFINDITEM* pFindItem = reinterpret_cast(pNMHDR); + if (pFindItem->lvfi.flags & LVFI_STRING) + { + String text = strutils::makelower(pFindItem->lvfi.psz); + for (size_t i = pFindItem->iStart; i < m_listViewItems.size(); ++i) + { + DIFFITEM *di = GetItemKey(static_cast(i)); + String filename = strutils::makelower(di->diffFileInfo[0].filename); + if (di && _tcsncmp(text.c_str(), filename.c_str(), text.length()) == 0) + { + *pResult = i; + return; + } + } } + *pResult = -1; } /** @@ -3179,7 +3588,7 @@ void CDirView::OnUpdateStatusNum(CCmdUI* pCmdUI) { // Don't show number to special items DIFFITEM *pos = GetItemKey(focusItem); - if (pos != (DIFFITEM *)SPECIAL_ITEM_POS) + if (!IsDiffItemSpecial(pos)) { // If compare is non-recursive reduce special items count bool bRecursive = GetDiffContext().m_bRecursive; @@ -3201,8 +3610,9 @@ void CDirView::OnUpdateStatusNum(CCmdUI* pCmdUI) */ void CDirView::OnViewShowHiddenItems() { + CDiffContext& ctxt = GetDiffContext(); SetItemViewFlag(GetDiffContext(), ViewCustomFlags::VISIBLE, ViewCustomFlags::VISIBILITY); - m_nHiddenItems = 0; + ctxt.m_vCurrentlyHiddenItems.clear(); Redisplay(); } @@ -3211,7 +3621,8 @@ void CDirView::OnViewShowHiddenItems() */ void CDirView::OnUpdateViewShowHiddenItems(CCmdUI* pCmdUI) { - pCmdUI->Enable(m_nHiddenItems > 0); + const CDiffContext& ctxt = GetDiffContext(); + pCmdUI->Enable(ctxt.m_vCurrentlyHiddenItems.size() > 0); } /** @@ -3275,12 +3686,20 @@ void CDirView::OnUpdateViewCollapseAllSubdirs(CCmdUI* pCmdUI) pCmdUI->Enable(m_bTreeMode && GetDiffContext().m_bRecursive); } +template void CDirView::OnViewSwapPanes() { - GetDocument()->Swap(0, GetDocument()->m_nDirs - 1); + GetDocument()->Swap(pane1, pane2); Redisplay(); } +template +void CDirView::OnUpdateViewSwapPanes(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(pane2 < GetDocument()->m_nDirs && + GetDocument()->m_diffThread.GetThreadState() == CDiffThread::THREAD_COMPLETED); +} + /** * @brief Show/Hide different files/directories */ @@ -3483,16 +3902,14 @@ void CDirView::OnUpdateOptionsShowMissingRightOnly(CCmdUI* pCmdUI) pCmdUI->SetCheck(m_dirfilter.show_missing_right_only); } -void CDirView::OnMergeCompare() +void CDirView::OnMergeCompare(UINT nID) { - CWaitCursor waitstatus; - OpenSelection(); + OpenSelection(nID == ID_MERGE_COMPARE ? GetDocument() : nullptr); } template void CDirView::OnMergeCompare2() { - CWaitCursor waitstatus; OpenSelection(seltype); } @@ -3511,6 +3928,7 @@ void CDirView::OnMergeCompareNonHorizontally() if (dlg.DoModal() == IDOK && dlg.m_selectedButtons.size() > 0) { CDirDoc *pDoc = GetDocument(); + FileTextEncoding encoding[3]; DWORD dwFlags[3] = {}; PathContext paths; for (int nIndex = 0; nIndex < static_cast(dlg.m_selectedButtons.size()); ++nIndex) @@ -3518,30 +3936,28 @@ void CDirView::OnMergeCompareNonHorizontally() int n = dlg.m_selectedButtons[nIndex]; dwFlags[nIndex] = FFILEOPEN_NOMRU | (pDoc->GetReadOnly(n % 3) ? FFILEOPEN_READONLY : 0); if (dlg.m_pdi[n / 3]) + { paths.SetPath(nIndex, GetItemFileName(pDoc->GetDiffContext(), *dlg.m_pdi[n / 3], n % 3)); + encoding[nIndex] = dlg.m_pdi[n / 3]->diffFileInfo[n % 3].encoding; + } } if (paths.GetSize() == 1) paths.SetRight(_T("")); - Open(paths, dwFlags); + Open(GetDocument(), paths, dwFlags, encoding); } } -void CDirView::OnMergeCompareXML() -{ - CWaitCursor waitstatus; - PackingInfo packingInfo(PLUGIN_BUILTIN_XML); - OpenSelection(SELECTIONTYPE_NORMAL, &packingInfo); -} - void CDirView::OnMergeCompareAs(UINT nID) { - CWaitCursor waitstatus; OpenSelectionAs(nID); } void CDirView::OnUpdateMergeCompare(CCmdUI *pCmdUI) { - DoUpdateOpen(SELECTIONTYPE_NORMAL, pCmdUI); + bool openableForDir = !((pCmdUI->m_nID >= ID_MERGE_COMPARE_TEXT && pCmdUI->m_nID <= ID_MERGE_COMPARE_WEBPAGE) || + (pCmdUI->m_nID >= ID_UNPACKERS_FIRST && pCmdUI->m_nID <= ID_UNPACKERS_LAST)); + + DoUpdateOpen(SELECTIONTYPE_NORMAL, pCmdUI, openableForDir); } template @@ -3550,6 +3966,20 @@ void CDirView::OnUpdateMergeCompare2(CCmdUI *pCmdUI) DoUpdateOpen(seltype, pCmdUI); } +void CDirView::OnUpdateNoUnpacker(CCmdUI *pCmdUI) +{ + pCmdUI->Enable(); + pCmdUI->m_pMenu->DeleteMenu(pCmdUI->m_nID, MF_BYCOMMAND); + + int sel = GetSingleSelectedItem(); + if (sel == -1 || GetItemKey(sel) == reinterpret_cast(SPECIAL_ITEM_POS)) + return; + + String filteredFilenames = GetDiffContext().GetFilteredFilenames(*GetItemKey(sel)); + CMainFrame::AppendPluginMenus(pCmdUI->m_pMenu, filteredFilenames, + FileTransform::UnpackerEventNames, true, ID_UNPACKERS_FIRST); +} + void CDirView::OnViewCompareStatistics() { CompareStatisticsDlg dlg(GetDocument()->GetCompareStats()); @@ -3694,7 +4124,6 @@ void CDirView::OnUpdateEditUndo(CCmdUI* pCmdUI) CEdit *pEdit = m_pList->GetEditControl(); pCmdUI->Enable(pEdit && pEdit->CanUndo()); } - /** * @brief Returns CShellContextMenu object that owns given HMENU. * @@ -3754,7 +4183,7 @@ LRESULT CDirView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) pMenu->HandleMenuMessage(message, wParam, lParam, res); } - return CListView::WindowProc(message, wParam, lParam); + return __super::WindowProc(message, wParam, lParam); } /** @@ -3792,27 +4221,6 @@ void CDirView::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult) } } -void CDirView::OnBnClickedComparisonStop() -{ - if (m_pCmpProgressBar != nullptr) - m_pCmpProgressBar->EndUpdating(); - GetDocument()->AbortCurrentScan(); -} - -void CDirView::OnBnClickedComparisonPause() -{ - if (m_pCmpProgressBar != nullptr) - m_pCmpProgressBar->SetPaused(true); - GetDocument()->PauseCurrentScan(); -} - -void CDirView::OnBnClickedComparisonContinue() -{ - if (m_pCmpProgressBar != nullptr) - m_pCmpProgressBar->SetPaused(false); - GetDocument()->ContinueCurrentScan(); -} - /** * @brief Populate colors for items in view, depending on difference status */ @@ -3822,8 +4230,8 @@ void CDirView::GetColors (int nRow, int nCol, COLORREF& clrBk, COLORREF& clrText if (di.isEmpty()) { - clrText = ::GetSysColor (COLOR_WINDOWTEXT); - clrBk = ::GetSysColor (COLOR_WINDOW); + clrText = theApp.GetMainSyntaxColors()->GetColor(COLORINDEX_NORMALTEXT); + clrBk = theApp.GetMainSyntaxColors()->GetColor(COLORINDEX_BKGND); } else if (di.diffcode.isResultFiltered()) { @@ -3847,8 +4255,8 @@ void CDirView::GetColors (int nRow, int nCol, COLORREF& clrBk, COLORREF& clrText } else { - clrText = ::GetSysColor (COLOR_WINDOWTEXT); - clrBk = ::GetSysColor (COLOR_WINDOW); + clrText = theApp.GetMainSyntaxColors()->GetColor(COLORINDEX_NORMALTEXT); + clrBk = theApp.GetMainSyntaxColors()->GetColor(COLORINDEX_BKGND); } } @@ -3857,15 +4265,18 @@ void CDirView::OnSearch() CDirDoc *pDoc = GetDocument(); m_pList->SetRedraw(FALSE); // Turn off updating (better performance) int nRows = m_pList->GetItemCount(); + CDiffContext& ctxt = GetDiffContext(); + for (int currRow = nRows - 1; currRow >= 0; currRow--) { DIFFITEM *pos = GetItemKey(currRow); - if (pos == (DIFFITEM *)SPECIAL_ITEM_POS) + if (IsDiffItemSpecial(pos)) continue; bool bFound = false; DIFFITEM &di = GetDiffItem(currRow); PathContext paths; + for (int i = 0; i < pDoc->m_nDirs; i++) { if (di.diffcode.exists(i) && !di.diffcode.isDirectory()) @@ -3902,9 +4313,10 @@ void CDirView::OnSearch() } if (!bFound) { + String hiddden_item_path = di.getItemRelativePath(); SetItemViewFlag(di, ViewCustomFlags::HIDDEN, ViewCustomFlags::VISIBILITY); DeleteItem(currRow); - m_nHiddenItems++; + ctxt.m_vCurrentlyHiddenItems.push_back(hiddden_item_path); } } m_pList->SetRedraw(TRUE); // Turn updating back on @@ -3915,8 +4327,6 @@ void CDirView::OnSearch() */ void CDirView::OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult) { - COleDataSource *DropData = new COleDataSource(); - std::list list; CopyPathnamesForDragAndDrop(SelBegin(), SelEnd(), std::back_inserter(list), GetDiffContext()); String filesForDroping = strutils::join(list.begin(), list.end(), _T("\n")) + _T("\n"); @@ -3927,6 +4337,7 @@ void CDirView::OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult) HGLOBAL hMem = GlobalReAlloc(file.Detach(), (filesForDroping.length() + 1) * sizeof(TCHAR), 0); if (hMem != nullptr) { + COleDataSource* DropData = new COleDataSource(); DropData->CacheGlobalData(CF_UNICODETEXT, hMem); DROPEFFECT de = DropData->DoDragDrop(DROPEFFECT_COPY | DROPEFFECT_MOVE, nullptr); } @@ -3940,7 +4351,7 @@ void CDirView::NameColumn(const DirColInfo *col, int subitem) int phys = m_pColItems->ColLogToPhys(subitem); if (phys>=0) { - String s = tr(col->idNameContext, col->idName); + String s = col->GetDisplayName(); LV_COLUMN lvc; lvc.mask = LVCF_TEXT; lvc.pszText = const_cast(s.c_str()); @@ -3955,7 +4366,8 @@ void CDirView::UpdateColumnNames() for (int i=0; iGetDirColInfo(i); - NameColumn(col, i); + if (col) + NameColumn(col, i); } } @@ -3968,10 +4380,13 @@ void CDirView::SetColAlignments() for (int i=0; iGetDirColInfo(i); - LVCOLUMN lvc; - lvc.mask = LVCF_FMT; - lvc.fmt = col->alignment; - m_pList->SetColumn(m_pColItems->ColLogToPhys(i), &lvc); + if (col) + { + LVCOLUMN lvc; + lvc.mask = LVCF_FMT; + lvc.fmt = col->alignment; + m_pList->SetColumn(m_pColItems->ColLogToPhys(i), &lvc); + } } } @@ -4005,17 +4420,16 @@ int CALLBACK CDirView::CompareState::CompareFunc(LPARAM lParam1, LPARAM lParam2, } /// Add new item to list view -int CDirView::AddNewItem(int i, DIFFITEM *diffpos, int iImage, int iIndent) +void CDirView::AddNewItem(int i, DIFFITEM *diffpos, int iImage, int iIndent) { - LV_ITEM lvItem; - lvItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE | LVIF_INDENT; - lvItem.iItem = i; + ListViewOwnerDataItem lvItem; lvItem.iIndent = iIndent; - lvItem.iSubItem = 0; - lvItem.pszText = LPSTR_TEXTCALLBACK; lvItem.lParam = (LPARAM)diffpos; lvItem.iImage = iImage; - return GetListCtrl().InsertItem(&lvItem); + if (i == static_cast(m_listViewItems.size())) + m_listViewItems.push_back(lvItem); + else + m_listViewItems.insert(m_listViewItems.begin() + i, lvItem); } /** @@ -4025,6 +4439,24 @@ int CDirView::AddNewItem(int i, DIFFITEM *diffpos, int iImage, int iIndent) void CDirView::UpdateDiffItemStatus(UINT nIdx) { GetListCtrl().RedrawItems(nIdx, nIdx); + const DIFFITEM& di = GetDiffItem(nIdx); + if (di.diffcode.isDirectory()) + { + DirItemIterator it; + for (it = RevBegin(); it != RevEnd(); ) + { + DIFFITEM& di2 = *it; + int cursel = it.m_sel; + ++it; + if (di2.IsAncestor(&di)) + { + if ((di2.diffcode.diffcode & DIFFCODE::SIDEFLAGS) == 0) + DeleteItem(cursel, true); + else + GetListCtrl().RedrawItems(cursel, cursel); + } + } + } } static String rgDispinfoText[2]; // used in function below @@ -4052,10 +4484,13 @@ static LPTSTR NTAPI AllocDispinfoText(const String &s) void CDirView::ReflectGetdispinfo(NMLVDISPINFO *pParam) { int nIdx = pParam->item.iItem; + if (nIdx >= static_cast(m_listViewItems.size())) + return; + DIFFITEM *key = reinterpret_cast(m_listViewItems[nIdx].lParam); int i = m_pColItems->ColPhysToLog(pParam->item.iSubItem); - DIFFITEM *key = GetItemKey(nIdx); - if (key == (DIFFITEM *)SPECIAL_ITEM_POS) + if (IsDiffItemSpecial(key)) { + pParam->item.iImage = m_listViewItems[nIdx].iImage; if (m_pColItems->IsColName(i)) { pParam->item.pszText = _T(".."); @@ -4074,10 +4509,23 @@ void CDirView::ReflectGetdispinfo(NMLVDISPINFO *pParam) if (pParam->item.mask & LVIF_IMAGE) { pParam->item.iImage = GetColImage(di); + if ((pParam->item.mask & LVIF_STATE) == 0) + { + // for WinXP + pParam->item.mask |= LVIF_STATE; + pParam->item.state = m_pList->GetItemState(nIdx, static_cast(~LVIS_STATEIMAGEMASK)); + } + } + if (pParam->item.mask & LVIF_INDENT) + { + pParam->item.iIndent = m_listViewItems[nIdx].iIndent; + } + if (pParam->item.mask & LVIF_STATE) + { + pParam->item.stateMask |= LVIS_STATEIMAGEMASK; + if (di.HasChildren()) + pParam->item.state |= INDEXTOSTATEIMAGEMASK((di.customFlags & ViewCustomFlags::EXPANDED) ? 2 : 1); } - - m_bNeedSearchLastDiffItem = true; - m_bNeedSearchFirstDiffItem = true; } /** @@ -4085,40 +4533,67 @@ void CDirView::ReflectGetdispinfo(NMLVDISPINFO *pParam) */ void CDirView::OnEditColumns() { - CDirColsDlg dlg; - // List all the currently displayed columns - for (int col=0; colGetItemCount(); ++col) - { - int l = m_pColItems->ColPhysToLog(col); - dlg.AddColumn(m_pColItems->GetColDisplayName(l), m_pColItems->GetColDescription(l), l, col); - } - // Now add all the columns not currently displayed - int l=0; - for (l=0; lGetColCount(); ++l) + bool bReset = false; + CDirColsDlg::ColumnArray cols; + + for (;;) { - if (m_pColItems->ColLogToPhys(l)==-1) + CDirColsDlg dlg; + // List all the currently displayed columns + for (int col=0; colGetItemCount(); ++col) { - dlg.AddColumn(m_pColItems->GetColDisplayName(l), m_pColItems->GetColDescription(l), l); + int l = m_pColItems->ColPhysToLog(col); + dlg.AddColumn(m_pColItems->GetColDisplayName(l), m_pColItems->GetColDescription(l), l, col); } - } + // Now add all the columns not currently displayed + int l=0; + for (l=0; lGetColCount(); ++l) + { + if (m_pColItems->ColLogToPhys(l)==-1) + { + dlg.AddColumn(m_pColItems->GetColDisplayName(l), m_pColItems->GetColDescription(l), l); + } + } + assert(m_pColItems->GetColCount() == dlg.GetColumns().size()); - // Add default order of columns for resetting to defaults - for (l = 0; l < m_pColItems->GetColCount(); ++l) - { - int phy = m_pColItems->GetColDefaultOrder(l); - dlg.AddDefColumn(m_pColItems->GetColDisplayName(l), l, phy); - } + // Add default order of columns for resetting to defaults + for (l = 0; l < m_pColItems->GetColCount(); ++l) + { + int phy = m_pColItems->GetColDefaultOrder(l); + dlg.AddDefColumn(m_pColItems->GetColDisplayName(l), l, phy); + } - if (dlg.DoModal() != IDOK) - return; + if (dlg.DoModal() != IDOK) + return; + + if (!dlg.GetShowAdditionalProperties()) + { + bReset = dlg.m_bReset; + cols = dlg.GetColumns(); + break; + } + + CDirAdditionalPropertiesDlg dlgAdditionalProperties(m_pColItems->GetAdditionalPropertyNames()); + if (dlgAdditionalProperties.DoModal() == IDOK) + { + auto& selectedCanonicalNames = dlgAdditionalProperties.GetSelectedCanonicalNames(); + GetOptionsMgr()->SaveOption(OPT_ADDITIONAL_PROPERTIES, + strutils::join(selectedCanonicalNames.begin(), selectedCanonicalNames.end(), _T(" "))); + m_pColItems->SetAdditionalPropertyNames(selectedCanonicalNames); + m_pColItems->SaveColumnOrders(); + GetDiffContext().m_pPropertySystem.reset(new PropertySystem(m_pColItems->GetAdditionalPropertyNames())); + GetDiffContext().ClearAllAdditionalProperties(); + auto* pDoc = GetDocument(); + ReloadColumns(); + } + } - String secname = GetDocument()->m_nDirs < 3 ? _T("DirView") : _T("DirView3"); - theApp.WriteProfileString(secname.c_str(), _T("ColumnWidths"), - (dlg.m_bReset ? m_pColItems->ResetColumnWidths(DefColumnWidth) : - m_pColItems->SaveColumnWidths(std::bind(&CListCtrl::GetColumnWidth, m_pList, _1))).c_str()); + const String keyname = GetDocument()->m_nDirs < 3 ? OPT_DIRVIEW_COLUMN_WIDTHS : OPT_DIRVIEW3_COLUMN_WIDTHS; + GetOptionsMgr()->SaveOption(keyname, + (bReset ? m_pColItems->ResetColumnWidths(GetDefColumnWidth()) : + m_pColItems->SaveColumnWidths(std::bind(&CListCtrl::GetColumnWidth, m_pList, _1)))); // Reset our data to reflect the new data from the dialog - const CDirColsDlg::ColumnArray & cols = dlg.GetColumns(); m_pColItems->ClearColumnOrders(); const int sortColumn = GetOptionsMgr()->GetInt((GetDocument()->m_nDirs < 3) ? OPT_DIRVIEW_SORT_COLUMN : OPT_DIRVIEW_SORT_COLUMN3); std::vector colorder(m_pColItems->GetColCount(), -1); @@ -4141,14 +4616,12 @@ void CDirView::OnEditColumns() if (m_pColItems->GetDispColCount() < 1) { - // Ignore them if they didn't leave a column showing + // Set them back to default if they didn't leave a column showing + // (However, if none of the items are checked, this process will not be executed because the "OK" button in the "Display Columns" dialog cannot be pressed.) m_pColItems->ResetColumnOrdering(); } - else - { - ReloadColumns(); - Redisplay(); - } + ReloadColumns(); + Redisplay(); } DirActions CDirView::MakeDirActions(DirActions::method_type func) const