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 */
75 /// first line of diff (first displayable line)
77 /// last line of diff (last displayable line)
82 This flag is set when we receive an OnTimer command, and we want
83 to wait for theApp::OnIdle before processing it
85 unsigned fTimerWaitingForIdle;
86 COLORSETTINGS m_cachedColors; /**< Cached color settings */
88 bool m_bCurrentLineIsDiff; /**< `true` if cursor is in diff line */
90 bool m_bChangedSchemeManually; /**< `true` if the syntax highlighting scheme is changed manually */
94 void CopyProperties (CCrystalTextView* pSource) override;
98 void RefreshOptions();
99 bool IsReadOnly(int pane) const;
100 void ShowDiff(bool bScroll, bool bSelectText);
101 virtual void OnEditOperation(int nAction, LPCTSTR pszText, size_t cchText) override;
102 bool IsLineInCurrentDiff(int nLine) const;
104 void SelectDiff(int nDiff, bool bScroll = true, bool bSelectText = true);
105 void DeselectDiffIfCursorNotInCurrentDiff();
106 virtual CCrystalTextBuffer *LocateTextBuffer () override;
107 const CCrystalTextBuffer *LocateTextBuffer () const { return const_cast<CMergeEditView *>(this)->LocateTextBuffer(); };
108 void GetFullySelectedDiffs(int & firstDiff, int & lastDiff);
109 void GetFullySelectedDiffs(int & firstDiff, int & lastDiff, int & firstWordDiff, int & lastWordDiff, const CPoint *pptStart = nullptr, const CPoint *ppEnd = nullptr);
110 void GetSelectedDiffs(int & firstDiff, int & lastDiff);
111 std::map<int, std::vector<int>> GetColumnSelectedWordDiffIndice();
112 CString GetSelectedText();
113 std::pair<int, int> GetSelectedLineAndCharacterCount();
114 CString GetLineText(int idx);
115 CMergeDoc* GetDocument();
116 const CMergeDoc *GetDocument() const { return const_cast<CMergeEditView *>(this)->GetDocument(); }
117 void UpdateResources();
118 bool IsModified() { return (LocateTextBuffer()->IsModified()); }
119 void PrimeListWithFile();
120 void SetStatusInterface(IMergeEditStatus * piMergeEditStatus);
121 void SelectArea(const CPoint & ptStart, const CPoint & ptEnd) { SetSelection(ptStart, ptEnd); } // make public
122 using CGhostTextView::GetSelection;
123 virtual void UpdateSiblingScrollPos (bool bHorz) override;
124 virtual std::vector<CrystalLineParser::TEXTBLOCK> GetMarkerTextBlocks(int nLineIndex) const override;
125 virtual std::vector<CrystalLineParser::TEXTBLOCK> GetAdditionalTextBlocks (int nLineIndex) override;
126 virtual COLORREF GetColor(int nColorIndex) const override;
127 virtual void GetLineColors (int nLineIndex, COLORREF & crBkgnd,
128 COLORREF & crText, bool & bDrawWhitespace) override;
129 virtual void GetLineColors2 (int nLineIndex, DWORD ignoreFlags
130 , COLORREF & crBkgnd, COLORREF & crText, bool & bDrawWhitespace);
131 void WMGoto() { OnWMGoto(); };
132 void GotoLine(UINT nLine, bool bRealLine, int pane, bool bMoveAnchor = true);
133 int GetTopLine() const { return m_nTopLine; }
134 using CCrystalTextView::GetScreenLines;
135 int GetTopSubLine() const { return m_nTopSubLine; }
136 using CCrystalTextView::GetSubLines;
137 using CCrystalTextView::GetSubLineCount;
138 using CCrystalTextView::GetSubLineIndex;
139 using CCrystalTextView::GetLineBySubLine;
140 virtual int GetEmptySubLines( int nLineIndex ) override;
141 virtual void InvalidateSubLineIndexCache( int nLineIndex ) override;
142 void RepaintLocationPane();
143 void DocumentsLoaded();
144 void UpdateLocationViewPosition(int nTopLine = -1, int nBottomLine = -1);
145 virtual void RecalcPageLayouts(CDC * pdc, CPrintInfo * pInfo) override;
146 virtual void GetPrintHeaderText(int nPageNum, CString & text) override;
147 virtual void PrintHeader(CDC * pdc, int nPageNum) override;
148 virtual void PrintFooter(CDC * pdc, int nPageNum) override;
149 virtual void SetWordWrapping( bool bWordWrap ) override;
150 void UpdateStatusbar();
151 CMergeEditView *GetGroupView(int nPane) const;
153 virtual void OnDisplayDiff(int nDiff=0);
155 bool IsInitialized() const;
156 bool IsCursorInDiff() const;
157 bool IsDiffVisible(int nDiff);
158 void ZoomText(short amount);
159 virtual bool QueryEditable() override;
160 virtual void EnsureVisible(CPoint pt) override;
161 virtual void EnsureVisible(CPoint ptStart, CPoint ptEnd) override;
162 bool EnsureInDiff(CPoint& pt);
163 void SetSelection(const CPoint& ptStart, const CPoint& ptEnd, bool bUpdateView = true) override;
164 void ScrollToSubLine(int nNewTopLine, bool bNoSmoothScroll = false, bool bTrackScrollBar = true) override;
165 void SetActivePane();
168 // ClassWizard generated virtual function overrides
169 //{{AFX_VIRTUAL(CMergeEditView)
171 virtual void OnInitialUpdate();
173 virtual void OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView);
174 virtual void OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint);
175 virtual BOOL PreTranslateMessage(MSG* pMsg);
176 virtual void OnBeginPrinting (CDC * pDC, CPrintInfo * pInfo);
177 virtual void OnEndPrinting (CDC * pDC, CPrintInfo * pInfo);
178 virtual void OnPrint(CDC* pDC, CPrintInfo* pInfo);
183 virtual ~CMergeEditView();
184 virtual void OnUpdateSibling (CCrystalTextView * pUpdateSource, bool bHorz) override;
185 virtual void OnUpdateCaret() override;
186 bool MergeModeKeyDown(MSG* pMsg);
187 bool IsDiffVisible(const DIFFRANGE& diff, int nLinesBelow = 0);
188 void OnNext3wayDiff(int type);
189 void OnUpdateNext3wayDiff(CCmdUI* pCmdUI, int type);
190 void OnPrev3wayDiff(int type);
191 void OnUpdatePrev3wayDiff(CCmdUI* pCmdUI, int type);
192 void OnDropFiles(const std::vector<String>& files);
194 // Generated message map functions
196 //{{AFX_MSG(CMergeEditView)
197 afx_msg void OnCurdiff();
198 afx_msg void OnUpdateCurdiff(CCmdUI* pCmdUI);
199 afx_msg void OnEditCopy();
200 afx_msg void OnUpdateEditCopy(CCmdUI* pCmdUI);
201 afx_msg void OnEditCut();
202 afx_msg void OnUpdateEditCut(CCmdUI* pCmdUI);
203 afx_msg void OnEditPaste();
204 afx_msg void OnUpdateEditPaste(CCmdUI* pCmdUI);
205 afx_msg void OnEditUndo();
206 afx_msg void OnFirstdiff();
207 afx_msg void OnUpdateFirstdiff(CCmdUI* pCmdUI);
208 afx_msg void OnLastdiff();
209 afx_msg void OnUpdateLastdiff(CCmdUI* pCmdUI);
210 afx_msg void OnNextdiff();
211 afx_msg void OnUpdateNextdiff(CCmdUI* pCmdUI);
212 afx_msg void OnPrevdiff();
213 afx_msg void OnUpdatePrevdiff(CCmdUI* pCmdUI);
214 afx_msg void OnNextConflict();
215 afx_msg void OnUpdateNextConflict(CCmdUI* pCmdUI);
216 afx_msg void OnPrevConflict();
217 afx_msg void OnUpdatePrevConflict(CCmdUI* pCmdUI);
218 afx_msg void OnNextdiffLM();
219 afx_msg void OnUpdateNextdiffLM(CCmdUI* pCmdUI);
220 afx_msg void OnPrevdiffLM();
221 afx_msg void OnUpdatePrevdiffLM(CCmdUI* pCmdUI);
222 afx_msg void OnNextdiffLR();
223 afx_msg void OnUpdateNextdiffLR(CCmdUI* pCmdUI);
224 afx_msg void OnPrevdiffLR();
225 afx_msg void OnUpdatePrevdiffLR(CCmdUI* pCmdUI);
226 afx_msg void OnNextdiffMR();
227 afx_msg void OnUpdateNextdiffMR(CCmdUI* pCmdUI);
228 afx_msg void OnPrevdiffMR();
229 afx_msg void OnUpdatePrevdiffMR(CCmdUI* pCmdUI);
230 afx_msg void OnNextdiffLO();
231 afx_msg void OnUpdateNextdiffLO(CCmdUI* pCmdUI);
232 afx_msg void OnPrevdiffLO();
233 afx_msg void OnUpdatePrevdiffLO(CCmdUI* pCmdUI);
234 afx_msg void OnNextdiffMO();
235 afx_msg void OnUpdateNextdiffMO(CCmdUI* pCmdUI);
236 afx_msg void OnPrevdiffMO();
237 afx_msg void OnUpdatePrevdiffMO(CCmdUI* pCmdUI);
238 afx_msg void OnNextdiffRO();
239 afx_msg void OnUpdateNextdiffRO(CCmdUI* pCmdUI);
240 afx_msg void OnPrevdiffRO();
241 afx_msg void OnUpdatePrevdiffRO(CCmdUI* pCmdUI);
242 afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
243 afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
244 afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
245 afx_msg void OnAllLeft();
246 afx_msg void OnUpdateAllLeft(CCmdUI* pCmdUI);
247 afx_msg void OnAllRight();
248 afx_msg void OnUpdateAllRight(CCmdUI* pCmdUI);
249 afx_msg void OnAutoMerge();
250 afx_msg void OnUpdateAutoMerge(CCmdUI* pCmdUI);
251 afx_msg void OnX2Y(int srcPane, int dstPane, bool selectedLineOnly = false);
252 afx_msg void OnUpdateX2Y(int dstPane, CCmdUI* pCmdUI);
253 afx_msg void OnL2r();
254 afx_msg void OnUpdateL2r(CCmdUI* pCmdUI);
255 afx_msg void OnLinesL2r();
256 afx_msg void OnUpdateLinesL2r(CCmdUI* pCmdUI);
257 afx_msg void OnR2l();
258 afx_msg void OnUpdateR2l(CCmdUI* pCmdUI);
259 afx_msg void OnLinesR2l();
260 afx_msg void OnUpdateLinesR2l(CCmdUI* pCmdUI);
261 afx_msg void OnCopyFromLeft();
262 afx_msg void OnUpdateCopyFromLeft(CCmdUI* pCmdUI);
263 afx_msg void OnCopyLinesFromLeft();
264 afx_msg void OnUpdateCopyLinesFromLeft(CCmdUI* pCmdUI);
265 afx_msg void OnCopyFromRight();
266 afx_msg void OnUpdateCopyFromRight(CCmdUI* pCmdUI);
267 afx_msg void OnCopyLinesFromRight();
268 afx_msg void OnUpdateCopyLinesFromRight(CCmdUI* pCmdUI);
269 afx_msg void OnAddSyncPoint();
270 afx_msg void OnClearSyncPoints();
271 afx_msg void OnUpdateClearSyncPoints(CCmdUI* pCmdUI);
272 afx_msg void OnUpdateEditUndo(CCmdUI* pCmdUI);
273 afx_msg void OnEditRedo();
274 afx_msg void OnUpdateEditRedo(CCmdUI* pCmdUI);
275 afx_msg void OnTimer(UINT_PTR nIDEvent);
276 afx_msg void OnUpdateFileSaveLeft(CCmdUI* pCmdUI);
277 afx_msg void OnUpdateFileSaveMiddle(CCmdUI* pCmdUI);
278 afx_msg void OnUpdateFileSaveRight(CCmdUI* pCmdUI);
279 afx_msg void OnRefresh();
280 afx_msg void OnUpdateFileSave(CCmdUI* pCmdUI);
281 template<bool reversed>
282 afx_msg void OnSelectLineDiff();
283 afx_msg void OnUpdateSelectLineDiff(CCmdUI* pCmdUI);
284 afx_msg void OnAddToSubstitutionFilters();
285 afx_msg void OnUpdateAddToSubstitutionFilters(CCmdUI* pCmdUI);
286 afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
287 afx_msg void OnUpdateEditReplace(CCmdUI* pCmdUI);
288 afx_msg void OnLeftReadOnly();
289 afx_msg void OnUpdateLeftReadOnly(CCmdUI* pCmdUI);
290 afx_msg void OnMiddleReadOnly();
291 afx_msg void OnUpdateMiddleReadOnly(CCmdUI* pCmdUI);
292 afx_msg void OnRightReadOnly();
293 afx_msg void OnUpdateRightReadOnly(CCmdUI* pCmdUI);
294 afx_msg void OnUpdateStatusRO(CCmdUI* pCmdUI);
295 afx_msg void OnConvertEolTo(UINT nID );
296 afx_msg void OnUpdateConvertEolTo(CCmdUI* pCmdUI);
297 afx_msg void OnUpdateStatusEOL(CCmdUI* pCmdUI);
298 afx_msg void OnL2RNext();
299 afx_msg void OnUpdateL2RNext(CCmdUI* pCmdUI);
300 afx_msg void OnR2LNext();
301 afx_msg void OnUpdateR2LNext(CCmdUI* pCmdUI);
302 afx_msg void OnChangePane();
303 afx_msg void OnWMGoto();
304 afx_msg void OnGotoMovedLineLM();
305 afx_msg void OnUpdateGotoMovedLineLM(CCmdUI* pCmdUI);
306 afx_msg void OnGotoMovedLineMR();
307 afx_msg void OnUpdateGotoMovedLineMR(CCmdUI* pCmdUI);
308 afx_msg void OnShellMenu();
309 afx_msg void OnUpdateShellMenu(CCmdUI* pCmdUI);
310 afx_msg void OnScripts(UINT nID );
311 afx_msg void OnHScroll (UINT nSBCode, UINT nPos, CScrollBar * pScrollBar);
312 afx_msg void OnVScroll (UINT nSBCode, UINT nPos, CScrollBar * pScrollBar);
313 afx_msg void OnEditCopyLineNumbers();
314 afx_msg void OnUpdateEditCopyLinenumbers(CCmdUI* pCmdUI);
315 afx_msg void OnViewLineDiffs();
316 afx_msg void OnUpdateViewLineDiffs(CCmdUI* pCmdUI);
317 afx_msg void OnViewLineNumbers();
318 afx_msg void OnUpdateViewLineNumbers(CCmdUI* pCmdUI);
319 afx_msg void OnViewWordWrap();
320 afx_msg void OnUpdateViewWordWrap(CCmdUI* pCmdUI);
321 afx_msg void OnViewWhitespace();
322 afx_msg void OnUpdateViewWhitespace(CCmdUI* pCmdUI);
323 afx_msg void OnViewEOL();
324 afx_msg void OnUpdateViewEOL(CCmdUI* pCmdUI);
325 afx_msg void OnOpenFile();
326 afx_msg void OnOpenFileWith();
327 afx_msg void OnOpenFileWithEditor();
328 afx_msg void OnOpenParentFolder();
329 afx_msg void OnViewSwapPanes12();
330 afx_msg void OnViewSwapPanes23();
331 afx_msg void OnViewSwapPanes13();
332 afx_msg void OnSize(UINT nType, int cx, int cy);
333 afx_msg void OnHelp();
334 afx_msg void OnViewMargin();
335 afx_msg void OnUpdateViewMargin(CCmdUI* pCmdUI);
336 afx_msg void OnUpdateViewChangeScheme(CCmdUI *pCmdUI);
337 afx_msg void OnChangeScheme(UINT nID);
338 afx_msg void OnUpdateChangeScheme(CCmdUI* pCmdUI);
339 afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
340 afx_msg void OnMouseHWheel(UINT nFlags, short zDelta, CPoint pt);
341 afx_msg void OnViewZoomIn();
342 afx_msg void OnViewZoomOut();
343 afx_msg void OnViewZoomNormal();
344 afx_msg void OnWindowSplit();
345 afx_msg void OnUpdateWindowSplit(CCmdUI* pCmdUI);
346 afx_msg void OnStatusBarDblClick(NMHDR* pNMHDR, LRESULT* pResult);
349 DECLARE_MESSAGE_MAP()
352 #ifndef _DEBUG // debug version in DiffView.cpp
353 inline CMergeDoc* CMergeEditView::GetDocument()
354 { return reinterpret_cast<CMergeDoc*>(m_pDocument); }
358 * @brief Check if cursor is inside difference.
359 * @return true if cursor is inside difference.
361 inline bool CMergeEditView::IsCursorInDiff() const
363 return m_bCurrentLineIsDiff;