3 #include "UnicodeString.h"
4 #include "DiffContext.h"
5 #include "FileActionScript.h"
7 #include "IntToIntMap.h"
9 #include "FileTransform.h"
14 class FileActionScript;
15 class CTempPathContext;
18 * @brief Folder compare icon indexes.
19 * This `enum` defines indexes for the imagelist used for folder/file compare icons.
20 * Note that this enum must be in synch with code in CDirView::OnInitialUpdate() and
21 * GetColImage(). Also remember that icons are in resource file...
49 DIFFIMG_DIRUP_DISABLE,
65 SELECTIONTYPE_LEFT1LEFT2,
66 SELECTIONTYPE_RIGHT1RIGHT2,
67 SELECTIONTYPE_LEFT1RIGHT2,
68 SELECTIONTYPE_LEFT2RIGHT1
77 struct AllowUpwardDirectory
89 struct DirViewFilterSettings
91 template<class GetOptionBool>
92 explicit DirViewFilterSettings(GetOptionBool getoptbool)
94 show_skipped = getoptbool(OPT_SHOW_SKIPPED);
95 show_unique_left = getoptbool(OPT_SHOW_UNIQUE_LEFT);
96 show_unique_middle = getoptbool(OPT_SHOW_UNIQUE_MIDDLE);
97 show_unique_right = getoptbool(OPT_SHOW_UNIQUE_RIGHT);
98 show_binaries = getoptbool(OPT_SHOW_BINARIES);
99 show_identical = getoptbool(OPT_SHOW_IDENTICAL);
100 show_different = getoptbool(OPT_SHOW_DIFFERENT);
101 show_different_left_only = getoptbool(OPT_SHOW_DIFFERENT_LEFT_ONLY);
102 show_different_middle_only = getoptbool(OPT_SHOW_DIFFERENT_MIDDLE_ONLY);
103 show_different_right_only = getoptbool(OPT_SHOW_DIFFERENT_RIGHT_ONLY);
104 show_missing_left_only = getoptbool(OPT_SHOW_MISSING_LEFT_ONLY);
105 show_missing_middle_only = getoptbool(OPT_SHOW_MISSING_MIDDLE_ONLY);
106 show_missing_right_only = getoptbool(OPT_SHOW_MISSING_RIGHT_ONLY);
107 tree_mode = getoptbool(OPT_TREE_MODE);
110 bool show_unique_left;
111 bool show_unique_middle;
112 bool show_unique_right;
116 bool show_different_left_only;
117 bool show_different_middle_only;
118 bool show_different_right_only;
119 bool show_missing_left_only;
120 bool show_missing_middle_only;
121 bool show_missing_right_only;
125 typedef std::map<String, bool> DirViewTreeState;
127 String NumToStr(int n);
128 String FormatFilesAffectedString(int nFilesAffected, int nFilesTotal);
129 String FormatMenuItemString(SIDE_TYPE src, int count, int total);
130 String FormatMenuItemString(SIDE_TYPE src, SIDE_TYPE dst, int count, int total);
131 String FormatMenuItemStringAll(int nDirs, int count, int total);
132 String FormatMenuItemString(const String& fmt1, const String& fmt2, int count, int total);
133 String FormatMenuItemStringTo(SIDE_TYPE src, int count, int total);
134 String FormatMenuItemStringAllTo(int nDirs, int count, int total);
135 String FormatMenuItemStringDifferencesTo(int count, int total);
137 void ConfirmActionList(const CDiffContext& ctxt, const FileActionScript & actionList);
138 UPDATEITEM_TYPE UpdateDiffAfterOperation(const FileActionItem & act, CDiffContext& ctxt, DIFFITEM &di);
140 DIFFITEM *FindItemFromPaths(const CDiffContext& ctxt, const PathContext& paths);
142 bool IsItemCopyable(const DIFFITEM &di, int index);
143 bool IsItemMovable(const DIFFITEM &di, int index);
144 bool IsItemDeletable(const DIFFITEM &di, int index);
145 bool IsItemDeletableOnBoth(const CDiffContext& ctxt, const DIFFITEM &di);
146 bool AreItemsOpenable(const CDiffContext& ctxt, SELECTIONTYPE selectionType, const DIFFITEM &di1, const DIFFITEM &di2, bool openableForDir = true);
147 bool AreItemsOpenable(const CDiffContext& ctxt, const DIFFITEM &di1, const DIFFITEM &di2, const DIFFITEM &di3, bool openableForDir = true);
148 bool IsItemOpenableOn(const DIFFITEM &di, int index);
149 bool IsItemOpenableOnWith(const DIFFITEM &di, int index);
150 bool IsItemCopyableToOn(const DIFFITEM &di, int index);
151 bool IsItemNavigableDiff(const CDiffContext& ctxt, const DIFFITEM &di);
152 bool IsItemExistAll(const CDiffContext& ctxt, const DIFFITEM &di);
153 bool IsShowable(const CDiffContext& ctxt, const DIFFITEM &di, const DirViewFilterSettings& filter);
155 bool GetOpenOneItem(const CDiffContext& ctxt, DIFFITEM *pos1, const DIFFITEM *pdi[3],
156 PathContext &paths, int & sel1, bool & isDir, int nPane[3], FileTextEncoding encoding[3], String& errmsg, bool openableForDir = true);
157 bool GetOpenTwoItems(const CDiffContext& ctxt, SELECTIONTYPE selectionType, DIFFITEM *pos1, DIFFITEM *pos2, const DIFFITEM *pdi[3],
158 PathContext &paths, int & sel1, int & sel2, bool & isDir, int nPane[3], FileTextEncoding encoding[3], String& errmsg, bool openableForDir = true);
159 bool GetOpenThreeItems(const CDiffContext& ctxt, DIFFITEM *pos1, DIFFITEM *pos2, DIFFITEM *pos3, const DIFFITEM *pdi[3],
160 PathContext &paths, int & sel1, int & sel2, int & sel3, bool & isDir, int nPane[3], FileTextEncoding encoding[3], String& errmsg, bool openableForDir = true);
162 void GetItemFileNames(const CDiffContext& ctxt, const DIFFITEM& di, String& strLeft, String& strRight);
163 PathContext GetItemFileNames(const CDiffContext& ctxt, const DIFFITEM& di);
164 String GetItemFileName(const CDiffContext& ctx, const DIFFITEM &di, int index);
165 int GetColImage(const DIFFITEM &di);
167 void SetDiffStatus(DIFFITEM& di, unsigned diffcode, unsigned mask);
168 void SetDiffCompare(DIFFITEM& di, unsigned diffcode);
169 void CopyDiffSideAndProperties(DIFFITEM& di, int src, int dst);
170 void UnsetDiffSide(DIFFITEM& di, int index);
171 void UpdateStatusFromDisk(CDiffContext& ctxt, DIFFITEM& di, int index);
172 int UpdateCompareFlagsAfterSync(DIFFITEM& di, bool bRecursive);
173 void UpdatePaths(int nDirs, DIFFITEM& di);
174 void SetDiffCounts(DIFFITEM& di, unsigned diffs, unsigned ignored);
175 void SetItemViewFlag(DIFFITEM& di, unsigned flag, unsigned mask);
176 void SetItemViewFlag(CDiffContext& ctxt, unsigned flag, unsigned mask);
177 void MarkForRescan(DIFFITEM& di);
179 bool RenameOnSameDir(const String& szOldFileName, const String& szNewFileName);
181 void ExpandSubdirs(CDiffContext& ctxt, DIFFITEM& dip);
182 void ExpandAllSubdirs(CDiffContext &ctxt);
183 void ExpandDifferentSubdirs(CDiffContext &ctxt);
184 void ExpandIdenticalSubdirs(CDiffContext &ctxt);
185 void CollapseAllSubdirs(CDiffContext &ctxt);
186 DirViewTreeState *SaveTreeState(const CDiffContext& ctxt);
187 void RestoreTreeState(CDiffContext &ctxt, DirViewTreeState *pTreeState);
189 AllowUpwardDirectory::ReturnCode
190 CheckAllowUpwardDirectory(const CDiffContext& ctxt, const CTempPathContext *pTempPathContext, PathContext &pathsParent);
192 inline int SideToIndex(const CDiffContext& ctxt, SIDE_TYPE stype)
196 case SIDE_MIDDLE: return ctxt.GetCompareDirs() == 3 ? 1 : -1;
197 case SIDE_RIGHT: return ctxt.GetCompareDirs() - 1;
202 struct ConfirmationNeededException
212 struct ContentsChangedException
214 explicit ContentsChangedException(const String& failpath);
218 struct FileOperationException
220 explicit FileOperationException(const String& msg);
226 typedef bool (DirActions::*method_type2)(const DIFFITEM& di) const;
227 typedef FileActionScript *(DirActions::*method_type)(FileActionScript *, const std::pair<int, const DIFFITEM *>& it) const;
229 DirActions(const CDiffContext& ctxt, const bool RO[], method_type func = nullptr, method_type2 func2 = nullptr) :
230 m_ctxt(ctxt), m_RO(RO), m_cur_method(func), m_cur_method2(func2) {}
232 template <SIDE_TYPE src, SIDE_TYPE dst>
233 bool IsItemCopyableOnTo(const DIFFITEM& di) const
235 return (di.diffcode.diffcode != 0 && !m_RO[SideToIndex(m_ctxt, dst)] && ::IsItemCopyable(di, SideToIndex(m_ctxt, src)));
238 template <SIDE_TYPE src>
239 bool IsItemCopyableToOn(const DIFFITEM& di) const
241 return (di.diffcode.diffcode != 0 && ::IsItemCopyableToOn(di, SideToIndex(m_ctxt, src)));
244 bool IsItemCopyableBothToOn(const DIFFITEM& di) const
246 if (di.diffcode.diffcode != 0)
249 for (i = 0; i < m_ctxt.GetCompareDirs(); ++i)
251 if (!::IsItemCopyableToOn(di, i))
254 return (i == m_ctxt.GetCompareDirs());
260 * @brief Return whether the specified diff item is renamable.
261 * @param [in] di Diff item to check
262 * @return true if the specified diff item is renamable.
264 bool IsItemRenamable(const DIFFITEM& di) const
266 int nDirs = m_ctxt.GetCompareDirs();
267 for (int i = 0; i < nDirs; i++)
268 if (di.diffcode.exists(i) && m_RO[i])
273 template <SIDE_TYPE src, SIDE_TYPE dst>
274 bool IsItemMovableOnTo(const DIFFITEM& di) const
276 const int idx = SideToIndex(m_ctxt, src);
277 return (di.diffcode.diffcode != 0 && !m_RO[idx] && !m_RO[SideToIndex(m_ctxt, dst)] && ::IsItemMovable(di, idx));
280 template <SIDE_TYPE src>
281 bool IsItemMovableToOn(const DIFFITEM& di) const
283 const int idx = SideToIndex(m_ctxt, src);
284 return (di.diffcode.diffcode != 0 && !m_RO[idx] && IsItemDeletable(di, idx) && ::IsItemCopyableToOn(di, idx));
287 template <SIDE_TYPE src>
288 bool IsItemDeletableOn(const DIFFITEM& di) const
290 const int idx = SideToIndex(m_ctxt, src);
291 return (di.diffcode.diffcode != 0 && !m_RO[idx] && IsItemDeletable(di, idx));
294 bool IsItemDeletableOnBoth(const DIFFITEM& di) const
296 if (di.diffcode.diffcode != 0)
299 for (i = 0; i < m_ctxt.GetCompareDirs(); ++i)
301 if (m_RO[i] || !IsItemDeletable(di, i))
304 return (i == m_ctxt.GetCompareDirs());
308 bool IsItemDeletableOnEitherOrBoth(const DIFFITEM& di) const
310 if (di.diffcode.diffcode != 0)
313 for (i = 0; i < m_ctxt.GetCompareDirs(); ++i)
315 if (!m_RO[i] && IsItemDeletable(di, i))
318 return (i < m_ctxt.GetCompareDirs());
323 template <SIDE_TYPE src>
324 bool IsItemOpenableOn(const DIFFITEM& di) const
326 return (di.diffcode.diffcode != 0 && ::IsItemOpenableOn(di, SideToIndex(m_ctxt, src)));
329 template <SIDE_TYPE src>
330 bool IsItemOpenableOnWith(const DIFFITEM& di) const
332 return (di.diffcode.diffcode != 0 && ::IsItemOpenableOnWith(di, SideToIndex(m_ctxt, src)));
335 template <SIDE_TYPE src>
336 bool IsParentFolderOpenable(const DIFFITEM& di) const
338 return (di.diffcode.diffcode != 0 && di.diffcode.exists(SideToIndex(m_ctxt, src)));
341 bool IsItemFile(const DIFFITEM& di) const
343 return (di.diffcode.diffcode != 0 && !di.diffcode.isDirectory());
346 template <SIDE_TYPE src>
347 bool IsItemExist(const DIFFITEM& di) const
349 return (di.diffcode.diffcode != 0 && di.diffcode.exists(SideToIndex(m_ctxt, src)));
352 template <SIDE_TYPE src>
353 bool IsItemEditableEncoding(const DIFFITEM& di) const
355 const int index = SideToIndex(m_ctxt, src);
356 return (di.diffcode.diffcode != 0 && di.diffcode.exists(index) && di.diffFileInfo[index].IsEditableEncoding());
359 bool IsItemNavigableDiff(const DIFFITEM& di) const
361 return ::IsItemNavigableDiff(m_ctxt, di);
364 FileActionScript *CopyItem(FileActionScript *pscript, const std::pair<int, const DIFFITEM *>& it, SIDE_TYPE src, SIDE_TYPE dst) const
366 const DIFFITEM& di = *it.second;
367 const int srcidx = SideToIndex(m_ctxt, src);
368 const int dstidx = SideToIndex(m_ctxt, dst);
369 if (di.diffcode.diffcode != 0 && !m_RO[dstidx] && IsItemCopyable(di, srcidx))
372 act.src = GetItemFileName(m_ctxt, di, srcidx);
373 act.dest = GetItemFileName(m_ctxt, di, dstidx);
375 // We must check that paths still exists
376 if (paths::DoesPathExist(act.src) == paths::DOES_NOT_EXIST)
377 throw ContentsChangedException(act.src);
379 act.context = it.first;
380 act.dirflag = di.diffcode.isDirectory();
381 act.atype = FileAction::ACT_COPY;
382 act.UIResult = FileActionItem::UI_SYNC;
383 act.UIOrigin = srcidx;
384 act.UIDestination = dstidx;
385 pscript->AddActionItem(act);
390 template<SIDE_TYPE src, SIDE_TYPE to>
391 FileActionScript *Copy(FileActionScript *pscript, const std::pair<int, const DIFFITEM *>& it) const
393 return CopyItem(pscript, it, src, to);
396 FileActionScript *MoveItem(FileActionScript *pscript, const std::pair<int, const DIFFITEM *>& it, SIDE_TYPE src, SIDE_TYPE dst) const
398 const DIFFITEM& di = *it.second;
399 const int srcidx = SideToIndex(m_ctxt, src);
400 const int dstidx = SideToIndex(m_ctxt, dst);
401 if (di.diffcode.diffcode != 0 && !m_RO[dstidx] && IsItemMovable(di, srcidx))
404 act.src = GetItemFileName(m_ctxt, di, srcidx);
405 act.dest = GetItemFileName(m_ctxt, di, dstidx);
407 // We must check that paths still exists
408 if (paths::DoesPathExist(act.src) == paths::DOES_NOT_EXIST)
409 throw ContentsChangedException(act.src);
411 act.context = it.first;
412 act.dirflag = di.diffcode.isDirectory();
413 act.atype = FileAction::ACT_MOVE;
414 act.UIResult = FileActionItem::UI_MOVE;
415 act.UIOrigin = srcidx;
416 act.UIDestination = dstidx;
417 pscript->AddActionItem(act);
422 template<SIDE_TYPE src, SIDE_TYPE to>
423 FileActionScript *Move(FileActionScript *pscript, const std::pair<int, const DIFFITEM *>& it) const
425 return MoveItem(pscript, it, src, to);
428 FileActionScript *DeleteItem(FileActionScript *pscript, const std::pair<int, const DIFFITEM *>& it, SIDE_TYPE src) const
430 const DIFFITEM& di = *it.second;
431 const int index = SideToIndex(m_ctxt, src);
432 if (di.diffcode.diffcode != 0 && !m_RO[index] && IsItemDeletable(di, index))
435 act.src = GetItemFileName(m_ctxt, di, index);
437 // We must check that path still exists
438 if (paths::DoesPathExist(act.src) == paths::DOES_NOT_EXIST)
439 throw ContentsChangedException(act.src);
441 act.context = it.first;
442 act.dirflag = di.diffcode.isDirectory();
443 act.atype = FileAction::ACT_DEL;
444 act.UIOrigin = index;
445 act.UIResult = FileActionItem::UI_DEL;
446 pscript->AddActionItem(act);
451 template<SIDE_TYPE src>
452 FileActionScript *DeleteOn(FileActionScript *pscript, const std::pair<int, const DIFFITEM *>& it) const
454 return DeleteItem(pscript, it, src);
457 FileActionScript *DeleteOnBoth(FileActionScript *pscript, const std::pair<int, const DIFFITEM *>& it) const
459 const DIFFITEM& di = *it.second;
461 if (di.diffcode.diffcode != 0 && IsItemDeletableOnBoth(di) &&
462 (std::count(m_RO, m_RO + m_ctxt.GetCompareDirs(), true) == 0))
464 for (int i = 0; i < m_ctxt.GetCompareDirs(); ++i)
467 act.src = GetItemFileName(m_ctxt, di, i);
468 // We must first check that paths still exists
469 if (paths::DoesPathExist(act.src) == paths::DOES_NOT_EXIST)
470 throw ContentsChangedException(act.src);
471 act.context = it.first;
472 act.dirflag = di.diffcode.isDirectory();
473 act.atype = FileAction::ACT_DEL;
475 act.UIResult = FileActionItem::UI_DEL;
476 pscript->AddActionItem(act);
482 FileActionScript *DeleteOnEitherOrBoth(FileActionScript *pscript, const std::pair<int, const DIFFITEM *>& it) const
484 const DIFFITEM& di = *it.second;
485 if (di.diffcode.diffcode != 0)
487 for (int i = 0; i < m_ctxt.GetCompareDirs(); ++i)
489 if (IsItemDeletable(di, i) && !m_RO[i])
492 act.src = GetItemFileName(m_ctxt, di, i);
493 // We must first check that paths still exists
494 if (paths::DoesPathExist(act.src) == paths::DOES_NOT_EXIST)
495 throw ContentsChangedException(act.src);
496 act.UIResult = FileActionItem::UI_DEL;
497 act.dirflag = di.diffcode.isDirectory();
498 act.context = it.first;
500 act.atype = FileAction::ACT_DEL;
501 pscript->AddActionItem(act);
508 FileActionScript *CopyOrMoveItemTo(FileActionScript *pscript, const std::pair<int, const DIFFITEM *>& it, FileAction::ACT_TYPE atype, SIDE_TYPE src) const
510 const int index = SideToIndex(m_ctxt, src);
511 const DIFFITEM& di = *it.second;
513 if (di.diffcode.diffcode != 0 && di.diffcode.exists(index) &&
514 (atype == FileAction::ACT_MOVE ? (!m_RO[index] && IsItemDeletable(di, index)) : true))
517 act.src = GetItemFileName(m_ctxt, di, index);
519 // We must check that path still exists
520 if (paths::DoesPathExist(act.src) == paths::DOES_NOT_EXIST)
521 throw ContentsChangedException(act.src);
523 act.dest = paths::ConcatPath(pscript->m_destBase, di.diffFileInfo[index].GetFile());
524 act.dirflag = di.diffcode.isDirectory();
525 act.context = it.first;
527 act.UIResult = (atype == FileAction::ACT_COPY) ? FileActionItem::UI_DONT_CARE : FileActionItem::UI_DEL;
528 act.UIOrigin = index;
529 pscript->AddActionItem(act);
534 template<SIDE_TYPE src>
535 FileActionScript *CopyTo(FileActionScript *pscript, const std::pair<int, const DIFFITEM *>& it) const
537 return CopyOrMoveItemTo(pscript, it, FileAction::ACT_COPY, src);
540 template<SIDE_TYPE src>
541 FileActionScript *MoveTo(FileActionScript *pscript, const std::pair<int, const DIFFITEM *>& it) const
543 return CopyOrMoveItemTo(pscript, it, FileAction::ACT_MOVE, src);
546 FileActionScript *operator()(FileActionScript *pscript, const std::pair<int, const DIFFITEM *>& it) const
548 return ((*this).*m_cur_method)(pscript, it);
551 bool operator()(const DIFFITEM &di) const
553 return ((*this).*m_cur_method2)(di);
556 method_type m_cur_method;
557 method_type2 m_cur_method2;
558 const CDiffContext& m_ctxt;
563 Counts() : count(0), total(0) {}
564 Counts(int c, int t): count(c), total(t) {}
569 template<class InputIterator, class Predicate>
570 Counts Count(const InputIterator& begin, const InputIterator& end, const Predicate& pred)
572 int count = 0, total = 0;
573 for (InputIterator it = begin; it != end; ++it)
579 return Counts(count, total);
583 * @brief Rename selected item on both left and right sides.
585 * @param szNewItemName [in] New item name.
587 * @return true if at least one file was renamed successfully.
589 template<class InputIterator>
590 bool DoItemRename(InputIterator& it, const CDiffContext& ctxt, const String& szNewItemName)
593 int nDirs = ctxt.GetCompareDirs();
595 assert(it != InputIterator());
597 // We must check that paths still exists
599 paths = ::GetItemFileNames(ctxt, di);
600 for (int index = 0; index < nDirs; index++)
602 if (di.diffcode.exists(index) && paths::DoesPathExist(paths[index]) == paths::DOES_NOT_EXIST)
603 throw ContentsChangedException(paths[index]);
606 bool bRename[3] = {false};
607 for (int index = 0; index < nDirs; index++)
609 if (di.diffcode.exists(index))
610 bRename[index] = RenameOnSameDir(paths[index], szNewItemName);
613 if (std::count(bRename, bRename + nDirs, true) == 0)
616 di.diffcode.setSideNone();
617 for (int index = 0; index < nDirs; index++)
619 di.diffFileInfo[index].filename = szNewItemName;
620 bool bSetSideFlag = bRename[index];
623 paths::PATH_EXISTENCE pathExist = paths::DoesPathExist(GetItemFileName(ctxt, di, index));
624 bool bIsDirectory = di.diffcode.isDirectory();
625 if (((pathExist == paths::IS_EXISTING_DIR) && bIsDirectory) || ((pathExist == paths::IS_EXISTING_FILE) && !bIsDirectory))
629 di.diffcode.setSideFlag(index);
634 template<class InputIterator, class OutputIterator>
635 OutputIterator CopyPathnames(const InputIterator& begin, const InputIterator& end, OutputIterator result, SIDE_TYPE stype, const CDiffContext& ctxt)
637 const int index = SideToIndex(ctxt, stype);
638 for (InputIterator it = begin; it != end; ++it)
640 const DIFFITEM& di = *it;
641 if (di.diffcode.exists(index))
643 *result = GetItemFileName(ctxt, di, index);
650 template<class InputIterator, class OutputIterator>
651 OutputIterator CopyBothPathnames(const InputIterator& begin, const InputIterator& end, OutputIterator result, const CDiffContext& ctxt)
653 for (InputIterator it = begin; it != end; ++it)
655 const DIFFITEM& di = *it;
656 for (int i = 0; i < ctxt.GetCompareDirs(); ++i)
658 if (di.diffcode.exists(i))
660 *result = GetItemFileName(ctxt, di, i);
668 template<class InputIterator, class OutputIterator>
669 OutputIterator CopyFilenames(const InputIterator& begin, const InputIterator& end, OutputIterator result)
671 for (InputIterator it = begin; it != end; ++it)
673 const DIFFITEM& di = *it;
674 if (!di.diffcode.isDirectory())
676 *result = di.diffFileInfo[0].filename;
683 template<class InputIterator, class OutputIterator>
684 OutputIterator CopyPathnamesForDragAndDrop(const InputIterator& begin, const InputIterator& end, OutputIterator result, const CDiffContext& ctxt)
686 for (InputIterator it = begin; it != end; ++it)
688 const DIFFITEM& di = *it;
690 // check for special items (e.g not "..")
691 if (di.diffcode.diffcode == 0)
694 for (int i = 0; i < ctxt.GetCompareDirs(); ++i)
696 if (di.diffcode.exists(i))
698 *result = GetItemFileName(ctxt, di, i);
706 template<class InputIterator, class BinaryFunction>
707 void ApplyFolderNameAndFileName(const InputIterator& begin, const InputIterator& end, SIDE_TYPE stype,
708 const CDiffContext& ctxt, BinaryFunction func)
710 int index = SideToIndex(ctxt, stype);
711 for (InputIterator it = begin; it != end; ++it)
713 const DIFFITEM& di = *it;
714 if (di.diffcode.diffcode == 0 /* Invalid value, this must be special item */ ||
715 !di.diffcode.exists(index))
717 String filename = di.diffFileInfo[index].filename;
718 String currentDir = di.getFilepath(index, ctxt.GetNormalizedPath(index));
719 func(currentDir, filename);
724 * @brief Apply specified setting for prediffing to all selected items
726 template<class InputIterator>
727 void ApplyPluginPipeline(const InputIterator& begin, const InputIterator& end, const CDiffContext& ctxt, bool unpacker, const String& pluginPipeline)
729 // Unlike other group actions, here we don't build an action list
730 // to execute; we just apply this change directly
731 if( !ctxt.m_bPluginsEnabled || ctxt.m_piPluginInfos == nullptr )
733 for (InputIterator it = begin; it != end; ++it)
735 const DIFFITEM& di = *it;
736 if (!di.diffcode.isDirectory())
738 PackingInfo * infoUnpacker = nullptr;
739 PrediffingInfo * infoPrediffer = nullptr;
740 String filteredFilenames = ctxt.GetFilteredFilenames(di);
741 const_cast<CDiffContext&>(ctxt).FetchPluginInfos(filteredFilenames, &infoUnpacker, &infoPrediffer);
743 infoUnpacker->SetPluginPipeline(pluginPipeline);
745 infoPrediffer->SetPluginPipeline(pluginPipeline);
751 * @brief Updates just before displaying plugin context view in list
753 template<class InputIterator>
754 std::tuple<int, int, int> CountPluginNoneAutoOthers(const InputIterator& begin, const InputIterator& end, const CDiffContext& ctxt, bool unpacker)
759 if( !ctxt.m_bPluginsEnabled || ctxt.m_piPluginInfos == nullptr )
760 return std::make_tuple(nNone, nAuto, nOthers);
762 for (InputIterator it = begin; it != end; ++it)
764 const DIFFITEM& di = *it;
765 if (di.diffcode.diffcode == 0) // Invalid value, this must be special item
768 // note the prediffer flag for 'files present on both sides and not skipped'
769 if (!di.diffcode.isDirectory() && !di.diffcode.isBin() && IsItemExistAll(ctxt, di)
770 && !di.diffcode.isResultFiltered())
772 PackingInfo * infoUnpacker;
773 PrediffingInfo * infoPrediffer;
774 String filteredFilenames = ctxt.GetFilteredFilenames(di);
775 const_cast<CDiffContext&>(ctxt).FetchPluginInfos(filteredFilenames, &infoUnpacker, &infoPrediffer);
776 String pluginPipeline = unpacker ? infoUnpacker->GetPluginPipeline() : infoPrediffer->GetPluginPipeline();
777 if (pluginPipeline.empty())
779 else if (pluginPipeline == _T("<Automatic>"))
785 return std::make_tuple(nNone, nAuto, nOthers);
788 template<class InputIterator>
789 IntToIntMap CountCodepages(const InputIterator& begin, const InputIterator& end, const CDiffContext& ctxt)
792 for (InputIterator it = begin; it != end; ++it)
794 const DIFFITEM& di = *it;
795 for (int i = 0; i < ctxt.GetCompareDirs(); ++i)
797 if (di.diffcode.diffcode != 0 && di.diffcode.exists(i))
798 map.Increment(di.diffFileInfo[i].encoding.m_codepage);
804 template<class InputIterator>
805 void ApplyCodepage(const InputIterator& begin, const InputIterator& end, CDiffContext& ctxt, const bool affect[3], int nCodepage)
807 for (InputIterator it = begin; it != end; ++it)
810 if (di.diffcode.diffcode == 0) // Invalid value, this must be special item
812 if (di.diffcode.isDirectory())
815 for (int i = 0; i < ctxt.GetCompareDirs(); ++i)
817 // Does it exist on left? (ie, right or both)
818 if (affect[i] && di.diffcode.exists(i) && di.diffFileInfo[i].IsEditableEncoding())
820 di.diffFileInfo[i].encoding.SetCodepage(nCodepage);
826 /// get file name on specified side for first selected item
827 template<class InputIterator>
828 String GetSelectedFileName(InputIterator& it, SIDE_TYPE stype, const CDiffContext& ctxt)
830 if (it == InputIterator())
832 return GetItemFileName(ctxt, *it, SideToIndex(ctxt, stype));