1 /////////////////////////////////////////////////////////////////////////////
2 // WinMerge: an interactive diff/merge utility
3 // Copyright (C) 1997 Dean P. Grimm
4 // SPDX-License-Identifier: GPL-2.0-or-later
5 /////////////////////////////////////////////////////////////////////////////
7 * @file MergeEditView.h
9 * @brief Declaration file for CMergeEditView
15 * @brief Non-diff lines shown above diff when scrolling to it
17 const UINT CONTEXT_LINES_ABOVE = 5;
20 * @brief Non-diff lines shown below diff when scrolling to it
22 const UINT CONTEXT_LINES_BELOW = 3;
25 #define FLAG_RESCAN_WAITS_FOR_IDLE 1
28 /////////////////////////////////////////////////////////////////////////////
29 // CMergeEditView view
31 #include "GhostTextView.h"
32 #include "OptionsDiffColors.h"
36 class IMergeEditStatus;
42 This class is the base class for WinMerge editor panels.
43 It hooks the painting of ghost lines (GetLineColors), the shared
44 scrollbar (OnUpdateSibling...).
45 It offers the UI interface commands to work with diffs
48 If we keep GetLineColors here, we should clear DIFF flag here
49 and not in CGhostTextBuffer (when insertText/deleteText).
50 Small problem... This class doesn't derives from CGhostTextBuffer...
51 We could define a new class which derives from CGhostTextBuffer to clear the DIFF flag.
52 and calls a virtual function for additional things to do on the flag.
53 Maybe in the future...
55 class CMergeEditView : public CGhostTextView
58 CMergeEditView(); // protected constructor used by dynamic creation
59 DECLARE_DYNCREATE(CMergeEditView)
60 CCrystalParser m_xParser; /**< Syntax parser used for syntax highlighting. */
65 * Index of pane this view is attached to.
66 * This indicates the pane number the view is attached to. If we swap panes
67 * then these indexes are changed.
72 IMergeEditStatus * m_piMergeEditStatus; /**< interface to status bar */
76 * Are automatic rescans enabled?
77 * If automatic rescans are enabled then we rescan files after edit
78 * events, unless timer suppresses rescan. We suppress rescans within
79 * certain time from previous rescan.
81 bool m_bAutomaticRescan;
82 /// first line of diff (first displayable line)
84 /// last line of diff (last displayable line)
89 This flag is set when we receive an OnTimer command, and we want
90 to wait for theApp::OnIdle before processing it
92 unsigned fTimerWaitingForIdle;
93 COLORSETTINGS m_cachedColors; /**< Cached color settings */
95 /// active prediffer ID : helper to check the radio button
96 int m_CurrentPredifferID;
98 bool m_bCurrentLineIsDiff; /**< `true` if cursor is in diff line */
100 bool m_bChangedSchemeManually; /**< `true` if the syntax highlighting scheme is changed manually */
104 void RefreshOptions();
105 bool EnableRescan(bool bEnable);
106 bool IsReadOnly(int pane) const;
107 void ShowDiff(bool bScroll, bool bSelectText);
108 virtual void OnEditOperation(int nAction, LPCTSTR pszText, size_t cchText) override;
109 bool IsLineInCurrentDiff(int nLine) const;
111 void SelectDiff(int nDiff, bool bScroll = true, bool bSelectText = true);
112 void DeselectDiffIfCursorNotInCurrentDiff();
113 virtual CCrystalTextBuffer *LocateTextBuffer ();
114 const CCrystalTextBuffer *LocateTextBuffer () const { return const_cast<CMergeEditView *>(this)->LocateTextBuffer(); };
115 void GetFullySelectedDiffs(int & firstDiff, int & lastDiff);
116 void GetFullySelectedDiffs(int & firstDiff, int & lastDiff, int & firstWordDiff, int & lastWordDiff, const CPoint *pptStart = nullptr, const CPoint *ppEnd = nullptr);
117 void GetSelectedDiffs(int & firstDiff, int & lastDiff);
118 std::map<int, std::vector<int>> GetColumnSelectedWordDiffIndice();
119 CString GetSelectedText();
120 CString GetLineText(int idx);
121 CMergeDoc* GetDocument();
122 const CMergeDoc *GetDocument() const { return const_cast<CMergeEditView *>(this)->GetDocument(); }
123 void UpdateResources();
124 bool IsModified() { return (LocateTextBuffer()->IsModified()); }
125 void PrimeListWithFile();
126 void SetStatusInterface(IMergeEditStatus * piMergeEditStatus);
127 void SelectArea(const CPoint & ptStart, const CPoint & ptEnd) { SetSelection(ptStart, ptEnd); } // make public
128 using CGhostTextView::GetSelection;
129 virtual void UpdateSiblingScrollPos (bool bHorz) override;
130 virtual std::vector<CrystalLineParser::TEXTBLOCK> GetMarkerTextBlocks(int nLineIndex) const;
131 virtual std::vector<CrystalLineParser::TEXTBLOCK> GetAdditionalTextBlocks (int nLineIndex) override;
132 virtual COLORREF GetColor(int nColorIndex) override;
133 virtual void GetLineColors (int nLineIndex, COLORREF & crBkgnd,
134 COLORREF & crText, bool & bDrawWhitespace) override;
135 virtual void GetLineColors2 (int nLineIndex, DWORD ignoreFlags
136 , COLORREF & crBkgnd, COLORREF & crText, bool & bDrawWhitespace);
137 void WMGoto() { OnWMGoto(); };
138 void GotoLine(UINT nLine, bool bRealLine, int pane, bool bMoveAnchor = true);
139 int GetTopLine() const { return m_nTopLine; }
140 using CCrystalTextView::GetScreenLines;
141 int GetTopSubLine() const { return m_nTopSubLine; }
142 using CCrystalTextView::GetSubLines;
143 using CCrystalTextView::GetSubLineCount;
144 using CCrystalTextView::GetSubLineIndex;
145 using CCrystalTextView::GetLineBySubLine;
146 virtual int GetEmptySubLines( int nLineIndex ) override;
147 virtual void InvalidateSubLineIndexCache( int nLineIndex ) override;
148 void RepaintLocationPane();
149 bool SetPredifferByName(const CString & prediffer);
150 void SetPredifferByMenu(UINT nID);
151 void DocumentsLoaded();
152 void UpdateLocationViewPosition(int nTopLine = -1, int nBottomLine = -1);
153 virtual void RecalcPageLayouts(CDC * pdc, CPrintInfo * pInfo) override;
154 virtual void GetPrintHeaderText(int nPageNum, CString & text) override;
155 virtual void PrintHeader(CDC * pdc, int nPageNum) override;
156 virtual void PrintFooter(CDC * pdc, int nPageNum) override;
157 virtual void SetWordWrapping( bool bWordWrap ) override;
158 void UpdateStatusbar();
159 CMergeEditView *GetGroupView(int nPane) const;
161 virtual void OnDisplayDiff(int nDiff=0);
163 // to customize the mergeview menu
164 static HMENU createScriptsSubmenu(HMENU hMenu);
165 HMENU createPrediffersSubmenu(HMENU hMenu);
167 bool IsInitialized() const;
168 bool IsCursorInDiff() const;
169 bool IsDiffVisible(int nDiff);
170 void ZoomText(short amount);
171 virtual bool QueryEditable() override;
172 virtual void EnsureVisible(CPoint pt) override;
173 virtual void EnsureVisible(CPoint ptStart, CPoint ptEnd) override;
174 bool EnsureInDiff(CPoint& pt);
175 void SetSelection(const CPoint& ptStart, const CPoint& ptEnd, bool bUpdateView = true) override;
176 void ScrollToSubLine(int nNewTopLine, bool bNoSmoothScroll = false, bool bTrackScrollBar = true) override;
177 void SetActivePane();
180 // ClassWizard generated virtual function overrides
181 //{{AFX_VIRTUAL(CMergeEditView)
183 virtual void OnInitialUpdate();
185 virtual void OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView);
186 virtual void OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint);
187 virtual BOOL PreTranslateMessage(MSG* pMsg);
188 virtual void OnBeginPrinting (CDC * pDC, CPrintInfo * pInfo);
189 virtual void OnEndPrinting (CDC * pDC, CPrintInfo * pInfo);
190 virtual void OnPrint(CDC* pDC, CPrintInfo* pInfo);
195 virtual ~CMergeEditView();
196 virtual void OnUpdateSibling (CCrystalTextView * pUpdateSource, bool bHorz);
197 virtual void OnUpdateCaret();
198 bool MergeModeKeyDown(MSG* pMsg);
199 int FindPrediffer(LPCTSTR prediffer) const;
200 bool IsDiffVisible(const DIFFRANGE& diff, int nLinesBelow = 0);
201 void OnNext3wayDiff(int type);
202 void OnUpdateNext3wayDiff(CCmdUI* pCmdUI, int type);
203 void OnPrev3wayDiff(int type);
204 void OnUpdatePrev3wayDiff(CCmdUI* pCmdUI, int type);
205 void OnDropFiles(const std::vector<String>& files);
207 // Generated message map functions
209 //{{AFX_MSG(CMergeEditView)
210 afx_msg void OnCurdiff();
211 afx_msg void OnUpdateCurdiff(CCmdUI* pCmdUI);
212 afx_msg void OnEditCopy();
213 afx_msg void OnUpdateEditCopy(CCmdUI* pCmdUI);
214 afx_msg void OnEditCut();
215 afx_msg void OnUpdateEditCut(CCmdUI* pCmdUI);
216 afx_msg void OnEditPaste();
217 afx_msg void OnUpdateEditPaste(CCmdUI* pCmdUI);
218 afx_msg void OnEditUndo();
219 afx_msg void OnFirstdiff();
220 afx_msg void OnUpdateFirstdiff(CCmdUI* pCmdUI);
221 afx_msg void OnLastdiff();
222 afx_msg void OnUpdateLastdiff(CCmdUI* pCmdUI);
223 afx_msg void OnNextdiff();
224 afx_msg void OnUpdateNextdiff(CCmdUI* pCmdUI);
225 afx_msg void OnPrevdiff();
226 afx_msg void OnUpdatePrevdiff(CCmdUI* pCmdUI);
227 afx_msg void OnNextConflict();
228 afx_msg void OnUpdateNextConflict(CCmdUI* pCmdUI);
229 afx_msg void OnPrevConflict();
230 afx_msg void OnUpdatePrevConflict(CCmdUI* pCmdUI);
231 afx_msg void OnNextdiffLM();
232 afx_msg void OnUpdateNextdiffLM(CCmdUI* pCmdUI);
233 afx_msg void OnPrevdiffLM();
234 afx_msg void OnUpdatePrevdiffLM(CCmdUI* pCmdUI);
235 afx_msg void OnNextdiffLR();
236 afx_msg void OnUpdateNextdiffLR(CCmdUI* pCmdUI);
237 afx_msg void OnPrevdiffLR();
238 afx_msg void OnUpdatePrevdiffLR(CCmdUI* pCmdUI);
239 afx_msg void OnNextdiffMR();
240 afx_msg void OnUpdateNextdiffMR(CCmdUI* pCmdUI);
241 afx_msg void OnPrevdiffMR();
242 afx_msg void OnUpdatePrevdiffMR(CCmdUI* pCmdUI);
243 afx_msg void OnNextdiffLO();
244 afx_msg void OnUpdateNextdiffLO(CCmdUI* pCmdUI);
245 afx_msg void OnPrevdiffLO();
246 afx_msg void OnUpdatePrevdiffLO(CCmdUI* pCmdUI);
247 afx_msg void OnNextdiffMO();
248 afx_msg void OnUpdateNextdiffMO(CCmdUI* pCmdUI);
249 afx_msg void OnPrevdiffMO();
250 afx_msg void OnUpdatePrevdiffMO(CCmdUI* pCmdUI);
251 afx_msg void OnNextdiffRO();
252 afx_msg void OnUpdateNextdiffRO(CCmdUI* pCmdUI);
253 afx_msg void OnPrevdiffRO();
254 afx_msg void OnUpdatePrevdiffRO(CCmdUI* pCmdUI);
255 afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
256 afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
257 afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
258 afx_msg void OnAllLeft();
259 afx_msg void OnUpdateAllLeft(CCmdUI* pCmdUI);
260 afx_msg void OnAllRight();
261 afx_msg void OnUpdateAllRight(CCmdUI* pCmdUI);
262 afx_msg void OnAutoMerge();
263 afx_msg void OnUpdateAutoMerge(CCmdUI* pCmdUI);
264 afx_msg void OnX2Y(int srcPane, int dstPane, bool selectedLineOnly = false);
265 afx_msg void OnUpdateX2Y(int dstPane, CCmdUI* pCmdUI);
266 afx_msg void OnL2r();
267 afx_msg void OnUpdateL2r(CCmdUI* pCmdUI);
268 afx_msg void OnLinesL2r();
269 afx_msg void OnUpdateLinesL2r(CCmdUI* pCmdUI);
270 afx_msg void OnR2l();
271 afx_msg void OnUpdateR2l(CCmdUI* pCmdUI);
272 afx_msg void OnLinesR2l();
273 afx_msg void OnUpdateLinesR2l(CCmdUI* pCmdUI);
274 afx_msg void OnCopyFromLeft();
275 afx_msg void OnUpdateCopyFromLeft(CCmdUI* pCmdUI);
276 afx_msg void OnCopyLinesFromLeft();
277 afx_msg void OnUpdateCopyLinesFromLeft(CCmdUI* pCmdUI);
278 afx_msg void OnCopyFromRight();
279 afx_msg void OnUpdateCopyFromRight(CCmdUI* pCmdUI);
280 afx_msg void OnCopyLinesFromRight();
281 afx_msg void OnUpdateCopyLinesFromRight(CCmdUI* pCmdUI);
282 afx_msg void OnAddSyncPoint();
283 afx_msg void OnClearSyncPoints();
284 afx_msg void OnUpdateClearSyncPoints(CCmdUI* pCmdUI);
285 afx_msg void OnUpdateEditUndo(CCmdUI* pCmdUI);
286 afx_msg void OnEditRedo();
287 afx_msg void OnUpdateEditRedo(CCmdUI* pCmdUI);
288 afx_msg void OnTimer(UINT_PTR nIDEvent);
289 afx_msg void OnUpdateFileSaveLeft(CCmdUI* pCmdUI);
290 afx_msg void OnUpdateFileSaveMiddle(CCmdUI* pCmdUI);
291 afx_msg void OnUpdateFileSaveRight(CCmdUI* pCmdUI);
292 afx_msg void OnRefresh();
293 afx_msg void OnUpdateFileSave(CCmdUI* pCmdUI);
294 template<bool reversed>
295 afx_msg void OnSelectLineDiff();
296 afx_msg void OnUpdateSelectLineDiff(CCmdUI* pCmdUI);
297 afx_msg void OnAddToSubstitutionFilters();
298 afx_msg void OnUpdateAddToSubstitutionFilters(CCmdUI* pCmdUI);
299 afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
300 afx_msg void OnUpdateEditReplace(CCmdUI* pCmdUI);
301 afx_msg void OnLeftReadOnly();
302 afx_msg void OnUpdateLeftReadOnly(CCmdUI* pCmdUI);
303 afx_msg void OnMiddleReadOnly();
304 afx_msg void OnUpdateMiddleReadOnly(CCmdUI* pCmdUI);
305 afx_msg void OnRightReadOnly();
306 afx_msg void OnUpdateRightReadOnly(CCmdUI* pCmdUI);
307 afx_msg void OnUpdateStatusRO(CCmdUI* pCmdUI);
308 afx_msg void OnConvertEolTo(UINT nID );
309 afx_msg void OnUpdateConvertEolTo(CCmdUI* pCmdUI);
310 afx_msg void OnUpdateStatusEOL(CCmdUI* pCmdUI);
311 afx_msg void OnL2RNext();
312 afx_msg void OnUpdateL2RNext(CCmdUI* pCmdUI);
313 afx_msg void OnR2LNext();
314 afx_msg void OnUpdateR2LNext(CCmdUI* pCmdUI);
315 afx_msg void OnChangePane();
316 afx_msg void OnWMGoto();
317 afx_msg void OnGotoMovedLineLM();
318 afx_msg void OnUpdateGotoMovedLineLM(CCmdUI* pCmdUI);
319 afx_msg void OnGotoMovedLineMR();
320 afx_msg void OnUpdateGotoMovedLineMR(CCmdUI* pCmdUI);
321 afx_msg void OnShellMenu();
322 afx_msg void OnUpdateShellMenu(CCmdUI* pCmdUI);
323 afx_msg void OnScripts(UINT nID );
324 afx_msg void OnUpdateNoPrediffer(CCmdUI* pCmdUI);
325 afx_msg void OnUpdatePrediffer(CCmdUI* pCmdUI);
326 afx_msg void OnNoPrediffer();
327 afx_msg void OnPrediffer(UINT nID );
328 afx_msg void OnHScroll (UINT nSBCode, UINT nPos, CScrollBar * pScrollBar);
329 afx_msg void OnVScroll (UINT nSBCode, UINT nPos, CScrollBar * pScrollBar);
330 afx_msg void OnEditCopyLineNumbers();
331 afx_msg void OnUpdateEditCopyLinenumbers(CCmdUI* pCmdUI);
332 afx_msg void OnViewLineDiffs();
333 afx_msg void OnUpdateViewLineDiffs(CCmdUI* pCmdUI);
334 afx_msg void OnViewLineNumbers();
335 afx_msg void OnUpdateViewLineNumbers(CCmdUI* pCmdUI);
336 afx_msg void OnViewWordWrap();
337 afx_msg void OnUpdateViewWordWrap(CCmdUI* pCmdUI);
338 afx_msg void OnViewWhitespace();
339 afx_msg void OnUpdateViewWhitespace(CCmdUI* pCmdUI);
340 afx_msg void OnViewEOL();
341 afx_msg void OnUpdateViewEOL(CCmdUI* pCmdUI);
342 afx_msg void OnOpenFile();
343 afx_msg void OnOpenFileWith();
344 afx_msg void OnOpenFileWithEditor();
345 afx_msg void OnViewSwapPanes12();
346 afx_msg void OnViewSwapPanes23();
347 afx_msg void OnViewSwapPanes13();
348 afx_msg void OnUpdateNoEditScripts(CCmdUI* pCmdUI);
349 afx_msg void OnSize(UINT nType, int cx, int cy);
350 afx_msg void OnHelp();
351 afx_msg void OnViewMargin();
352 afx_msg void OnUpdateViewMargin(CCmdUI* pCmdUI);
353 afx_msg void OnUpdateViewChangeScheme(CCmdUI *pCmdUI);
354 afx_msg void OnChangeScheme(UINT nID);
355 afx_msg void OnUpdateChangeScheme(CCmdUI* pCmdUI);
356 afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
357 afx_msg void OnMouseHWheel(UINT nFlags, short zDelta, CPoint pt);
358 afx_msg void OnViewZoomIn();
359 afx_msg void OnViewZoomOut();
360 afx_msg void OnViewZoomNormal();
361 afx_msg void OnWindowSplit();
362 afx_msg void OnUpdateWindowSplit(CCmdUI* pCmdUI);
363 afx_msg void OnStatusBarDblClick(NMHDR* pNMHDR, LRESULT* pResult);
366 DECLARE_MESSAGE_MAP()
369 #ifndef _DEBUG // debug version in DiffView.cpp
370 inline CMergeDoc* CMergeEditView::GetDocument()
371 { return reinterpret_cast<CMergeDoc*>(m_pDocument); }
375 * @brief Enable/Disable automatic rescanning
377 inline bool CMergeEditView::EnableRescan(bool bEnable)
379 bool bOldValue = m_bAutomaticRescan;
380 m_bAutomaticRescan = bEnable;
385 * @brief Check if cursor is inside difference.
386 * @return true if cursor is inside difference.
388 inline bool CMergeEditView::IsCursorInDiff() const
390 return m_bCurrentLineIsDiff;