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