From bbf48565b62375c75698936aa5aadcb2c8c3dea1 Mon Sep 17 00:00:00 2001 From: Laurent Ganier Date: Sun, 7 Sep 2003 20:18:06 +0000 Subject: [PATCH] [ 799464 ] preserve positions during Rescan (2.1) --- Src/GhostTextBuffer.cpp | 11 +++++ Src/GhostTextView.cpp | 96 +++++++++++++++++++++++++++++++++----- Src/GhostTextView.h | 53 ++++++++++++++++++--- Src/MergeDoc.cpp | 8 ++-- Src/editlib/ccrystaleditview.cpp | 23 ++++++++- Src/editlib/ccrystaleditview.h | 7 +-- Src/editlib/ccrystaltextbuffer.cpp | 6 +++ Src/editlib/ccrystaltextbuffer.h | 1 + Src/editlib/ccrystaltextview.cpp | 7 +++ Src/editlib/ccrystaltextview.h | 5 +- Src/readme.txt | 6 +++ 11 files changed, 195 insertions(+), 28 deletions(-) diff --git a/Src/GhostTextBuffer.cpp b/Src/GhostTextBuffer.cpp index ae811b1d8..d2c9a5149 100644 --- a/Src/GhostTextBuffer.cpp +++ b/Src/GhostTextBuffer.cpp @@ -541,6 +541,13 @@ AddUndoRecord (BOOL bInsert, const CPoint & ptStartPos, const CPoint & ptEndPos, //////////////////////////////////////////////////////////////////////////// // edition functions +/** + * + * @param nEndLine and nEndChar are the coordinates of the end od the inserted text + * They are valid as long as you do not call FlushUndoGroup + * If you need to call FlushUndoGroup, just store them in a variable which + * is preserved with real line number during Rescan (m_ptCursorPos, m_ptLastChange for example) + */ BOOL CGhostTextBuffer:: InsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR pszText, int &nEndLine, int &nEndChar, int nAction, BOOL bHistory /*=TRUE*/) @@ -618,6 +625,10 @@ InsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR pszText, if (bGroupFlag) FlushUndoGroup (pSource); + + // nEndLine may have changed during Rescan + nEndLine = m_ptLastChange.y; + return TRUE; } diff --git a/Src/GhostTextView.cpp b/Src/GhostTextView.cpp index 2da4ec518..b52e90f5b 100644 --- a/Src/GhostTextView.cpp +++ b/Src/GhostTextView.cpp @@ -67,30 +67,102 @@ DetachFromBuffer () -void CGhostTextView:: -PopCursor () +void CGhostTextView::popPosition(SCursorPushed Ssrc, CPoint & pt) { - CPoint ptCursorLast = m_ptCursorLast; - ptCursorLast.y = m_pGhostTextBuffer->ComputeApparentLine(m_ptCursorLast.y, m_ptCursorLast_nGhost); - if (ptCursorLast.y >= GetLineCount()) + pt.x = Ssrc.x; + pt.y = m_pGhostTextBuffer->ComputeApparentLine(Ssrc.y, Ssrc.nToFirstReal); + // if the cursor was in a trailing ghost line, and this disappeared, + // got at the end of the last line + if (pt.y >= GetLineCount()) { - ptCursorLast.y = GetLineCount()-1; - ptCursorLast.x = GetLineLength(ptCursorLast.y); + pt.y = GetLineCount()-1; + pt.x = GetLineLength(pt.y); } +} + +void CGhostTextView::pushPosition(SCursorPushed & Sdest, CPoint pt) +{ + Sdest.x = pt.x; + Sdest.y = m_pGhostTextBuffer->ComputeRealLineAndGhostAdjustment(pt.y, Sdest.nToFirstReal); +} + +void CGhostTextView:: +PopCursors () +{ + CPoint ptCursorLast = m_ptCursorLast; + popPosition(m_ptCursorPosPushed, ptCursorLast); + ASSERT_VALIDTEXTPOS (ptCursorLast); SetCursorPos (ptCursorLast); - SetSelection (ptCursorLast, ptCursorLast); - SetAnchor (ptCursorLast); + + popPosition(m_ptSelStartPushed, m_ptSelStart); + ASSERT_VALIDTEXTPOS (m_ptSelStart); + popPosition(m_ptSelEndPushed, m_ptSelEnd); + ASSERT_VALIDTEXTPOS (m_ptSelEnd); + popPosition(m_ptAnchorPushed, m_ptAnchor); + ASSERT_VALIDTEXTPOS (m_ptAnchor); + // laoran 2003/09/03 + // here is what we did before, maybe we have to do it, but test with pushed positions + // SetSelection (ptCursorLast, ptCursorLast); + // SetAnchor (ptCursorLast); + + if (m_bDraggingText == TRUE) + { + popPosition(m_ptDraggedTextBeginPushed, m_ptDraggedTextBegin); + ASSERT_VALIDTEXTPOS(m_ptDraggedTextBegin); + popPosition(m_ptDraggedTextEndPushed, m_ptDraggedTextEnd); + ASSERT_VALIDTEXTPOS(m_ptDraggedTextEnd); + } + if (m_bDropPosVisible == TRUE) + { + popPosition(m_ptSavedCaretPosPushed, m_ptSavedCaretPos); + ASSERT_VALIDTEXTPOS(m_ptSavedCaretPos); + } + if (m_bSelectionPushed == TRUE) + { + popPosition(m_ptSavedSelStartPushed, m_ptSavedSelStart); + ASSERT_VALIDTEXTPOS(m_ptSavedSelStart); + popPosition(m_ptSavedSelEndPushed, m_ptSavedSelEnd); + ASSERT_VALIDTEXTPOS(m_ptSavedSelEnd); + } + + CPoint ptLastChange; + if (m_ptLastChangePushed.y == 0 && m_ptLastChangePushed.nToFirstReal == 1) + ptLastChange = CPoint(-1,-1); + else + { + popPosition(m_ptLastChangePushed, ptLastChange); + ASSERT_VALIDTEXTPOS(ptLastChange); + } + m_pGhostTextBuffer->RestoreLastChangePos(ptLastChange); } void CGhostTextView:: -PushCursor () +PushCursors () { - m_ptCursorLast.x = m_ptCursorPos.x; - m_ptCursorLast.y = m_pGhostTextBuffer->ComputeRealLineAndGhostAdjustment(m_ptCursorPos.y, m_ptCursorLast_nGhost); + pushPosition(m_ptCursorPosPushed, m_ptCursorPos); + pushPosition(m_ptSelStartPushed, m_ptSelStart); + pushPosition(m_ptSelEndPushed, m_ptSelEnd); + pushPosition(m_ptAnchorPushed, m_ptAnchor); + if (m_bDraggingText == TRUE) + { + pushPosition(m_ptDraggedTextBeginPushed, m_ptDraggedTextBegin); + pushPosition(m_ptDraggedTextEndPushed, m_ptDraggedTextEnd); + } + if (m_bDropPosVisible == TRUE) + pushPosition(m_ptSavedCaretPosPushed, m_ptSavedCaretPos); + if (m_bSelectionPushed == TRUE) + { + pushPosition(m_ptSavedSelStartPushed, m_ptSavedSelStart); + pushPosition(m_ptSavedSelEndPushed, m_ptSavedSelEnd); + } + + pushPosition(m_ptLastChangePushed, m_pGhostTextBuffer->GetLastChangePos()); } + + int CGhostTextView::ComputeRealLine (int nApparentLine) const { return m_pGhostTextBuffer->ComputeRealLine(nApparentLine); diff --git a/Src/GhostTextView.h b/Src/GhostTextView.h index 308072777..65eae512d 100644 --- a/Src/GhostTextView.h +++ b/Src/GhostTextView.h @@ -34,19 +34,60 @@ class EDITPADC_CLASS CGhostTextView : public CCrystalEditViewEx private: CGhostTextBuffer * m_pGhostTextBuffer; - /** real cursor position to preserve cursor during Rescan */ - CPoint m_ptCursorLast; - /** real cursor position to preserve cursor during Rescan */ - int m_ptCursorLast_nGhost; + /** + * @brief Real point structure to preserve a position during Rescan + * + * @note The preserved positions are also updated in CCrystalTextView::UpdateView + * or in CCrystalEditView::UpdateView + * except for m_ptLastChange, which is set just after the call to UpdateView + */ + struct SCursorPushed + { + int x; + // real line number of itself (is the line is real)/the first real line after this line (else) + int y; + // 0 (is the line is real)/ distance to the first real line after this one + int nToFirstReal; + }; + + /** + * @brief Save a position to be able to restore it after Rescan. + * The saved position is based only on real lines + * + * @note We can only push/pop valid positions + * For positions which are sometimes invalid, use a flag + */ + void pushPosition(SCursorPushed & Sdest, CPoint pt); + void popPosition(SCursorPushed Ssrc, CPoint & pt); + + /// basic cursor + SCursorPushed m_ptCursorPosPushed; + /// selection extremities + SCursorPushed m_ptSelStartPushed, m_ptSelEndPushed; + /// anchor point for selection (during shift is pressed) + SCursorPushed m_ptAnchorPushed; + /// during dragging, extremities of dragged text : if (m_bDraggingText == TRUE) + SCursorPushed m_ptDraggedTextBeginPushed, m_ptDraggedTextEndPushed; + /// during drag/drop, droping position : if (m_bDropPosVisible == TRUE) + SCursorPushed m_ptSavedCaretPosPushed; + /// memorize selected text during OnEditReplace : if (m_bSelectionPushed == TRUE) + SCursorPushed m_ptSavedSelStartPushed, m_ptSavedSelEndPushed; + /** last change position, in the buffer ; used in insertText + * initialized with (-1,-1), so don't assert for this invalid value + */ + SCursorPushed m_ptLastChangePushed; + // Other CPoint used but not preserved : + // m_ptDrawSelStart, m_ptDrawSelEnd : built from m_ptSelStart and m_ptSelEnd + // m_ptDropPos : only used inside one function which does not change the buffer public: virtual void AttachToBuffer (CCrystalTextBuffer * pBuf = NULL); virtual void DetachFromBuffer (); /** real cursor function to preserve cursor during Rescan */ - void PopCursor (); + void PopCursors (); /** real cursor function to preserve cursor during Rescan */ - void PushCursor (); + void PushCursors (); int ComputeApparentLine (int nRealLine) const; int ComputeRealLine (int nApparentLine) const; diff --git a/Src/MergeDoc.cpp b/Src/MergeDoc.cpp index 876583c76..50838d807 100644 --- a/Src/MergeDoc.cpp +++ b/Src/MergeDoc.cpp @@ -1271,14 +1271,14 @@ void CMergeDoc::FlushAndRescan(BOOL bForced /* =FALSE */) int nRescanResult = RESCAN_OK; - m_pLeftView->PushCursor(); - m_pRightView->PushCursor(); + m_pLeftView->PushCursors(); + m_pRightView->PushCursors(); nRescanResult = Rescan(bForced); UpdateAllViews(NULL); - m_pLeftView->PopCursor(); - m_pRightView->PopCursor(); + m_pLeftView->PopCursors(); + m_pRightView->PopCursors(); if (curView) curView->EnsureVisible(curView->GetCursorPos()); diff --git a/Src/editlib/ccrystaleditview.cpp b/Src/editlib/ccrystaleditview.cpp index cdc51ccef..facf4b373 100644 --- a/Src/editlib/ccrystaleditview.cpp +++ b/Src/editlib/ccrystaleditview.cpp @@ -1111,6 +1111,16 @@ DoDropText (COleDataObject * pDataObject, const CPoint & ptClient) if (pszText == NULL) return FALSE; + // Open the undo group + // When we drag from the same panel, it is already open, so do nothing + // (we could test m_pTextBuffer->m_bUndoGroup if it were not a protected member) + BOOL bGroupFlag = FALSE; + if (! IsDraggingText()) + { + m_pTextBuffer->BeginUndoGroup (); + bGroupFlag = TRUE; + } + int x, y; m_pTextBuffer->InsertText (this, ptDropPos.y, ptDropPos.x, pszText, y, x, CE_ACTION_DRAGDROP); // [JRT] @@ -1121,6 +1131,9 @@ DoDropText (COleDataObject * pDataObject, const CPoint & ptClient) SetCursorPos (ptCurPos); EnsureVisible (ptCurPos); + if (bGroupFlag) + m_pTextBuffer->FlushUndoGroup (this); + ::GlobalUnlock (hData); return TRUE; } @@ -1224,6 +1237,11 @@ UpdateView (CCrystalTextView * pSource, CUpdateContext * pContext, DWORD dwFlags ASSERT_VALIDTEXTPOS (m_ptSavedSelStart); ASSERT_VALIDTEXTPOS (m_ptSavedSelEnd); } + if (m_bDropPosVisible ) + { + pContext->RecalcPoint (m_ptSavedCaretPos); + ASSERT_VALIDTEXTPOS (m_ptSavedCaretPos); + } } void CCrystalEditView:: @@ -1375,8 +1393,6 @@ ReplaceSelection (LPCTSTR pszNewText, DWORD dwFlags) m_nLastReplaceLen = _tcslen (pszNewText); } - m_pTextBuffer->FlushUndoGroup(this); - CPoint ptEndOfBlock = CPoint (x, y); ASSERT_VALIDTEXTPOS (ptCursorPos); ASSERT_VALIDTEXTPOS (ptEndOfBlock); @@ -1384,6 +1400,9 @@ ReplaceSelection (LPCTSTR pszNewText, DWORD dwFlags) SetSelection (ptCursorPos, ptEndOfBlock); SetCursorPos (ptEndOfBlock); //EnsureVisible (ptEndOfBlock); + + m_pTextBuffer->FlushUndoGroup(this); + return TRUE; } diff --git a/Src/editlib/ccrystaleditview.h b/Src/editlib/ccrystaleditview.h index 1500eedf5..08dec8196 100644 --- a/Src/editlib/ccrystaleditview.h +++ b/Src/editlib/ccrystaleditview.h @@ -64,13 +64,14 @@ protected: BOOL m_bLastReplace; DWORD m_dwLastReplaceFlags; -private : - BOOL m_bOvrMode; +protected: BOOL m_bDropPosVisible; CPoint m_ptSavedCaretPos; - CPoint m_ptDropPos; BOOL m_bSelectionPushed; CPoint m_ptSavedSelStart, m_ptSavedSelEnd; +private : + BOOL m_bOvrMode; + CPoint m_ptDropPos; BOOL m_bAutoIndent; // [JRT] diff --git a/Src/editlib/ccrystaltextbuffer.cpp b/Src/editlib/ccrystaltextbuffer.cpp index 18d7b37ce..65d9f21ec 100644 --- a/Src/editlib/ccrystaltextbuffer.cpp +++ b/Src/editlib/ccrystaltextbuffer.cpp @@ -1526,6 +1526,7 @@ InsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR pszText, if (bGroupFlag) FlushUndoGroup (pSource); + return TRUE; } @@ -1766,6 +1767,11 @@ CPoint CCrystalTextBuffer::GetLastChangePos() const return m_ptLastChange; } //END SW +void CCrystalTextBuffer::RestoreLastChangePos(CPoint pt) +{ + m_ptLastChange = pt; +} + void CCrystalTextBuffer::DeleteLine(int line) { diff --git a/Src/editlib/ccrystaltextbuffer.h b/Src/editlib/ccrystaltextbuffer.h index d03b0c2d2..268e27bf1 100644 --- a/Src/editlib/ccrystaltextbuffer.h +++ b/Src/editlib/ccrystaltextbuffer.h @@ -323,6 +323,7 @@ public : */ CPoint GetLastChangePos() const; //END SW + void RestoreLastChangePos(CPoint pt); void DeleteLine(int line); diff --git a/Src/editlib/ccrystaltextview.cpp b/Src/editlib/ccrystaltextview.cpp index c127dc2f3..c60621f8c 100644 --- a/Src/editlib/ccrystaltextview.cpp +++ b/Src/editlib/ccrystaltextview.cpp @@ -1501,6 +1501,7 @@ DrawMargin (CDC * pdc, const CRect & rect, int nLineIndex) BOOL CCrystalTextView:: IsInsideSelBlock (CPoint ptTextPos) { + PrepareSelBounds(); ASSERT_VALIDTEXTPOS (ptTextPos); if (ptTextPos.y < m_ptDrawSelStart.y) return FALSE; @@ -1526,6 +1527,12 @@ IsInsideSelection (const CPoint & ptTextPos) return IsInsideSelBlock (ptTextPos); } +/** + * @brief : class the selection extremities in ascending order + * + * @note : Updates m_ptDrawSelStart and m_ptDrawSelEnd + * This function must be called before reading these values + */ void CCrystalTextView:: PrepareSelBounds () { diff --git a/Src/editlib/ccrystaltextview.h b/Src/editlib/ccrystaltextview.h index 47283c99a..2302faf70 100644 --- a/Src/editlib/ccrystaltextview.h +++ b/Src/editlib/ccrystaltextview.h @@ -115,7 +115,9 @@ private : int m_nIdealCharPos; BOOL m_bFocused; +protected: CPoint m_ptAnchor; +private: LOGFONT m_lfBaseFont; CFont *m_apFonts[4]; @@ -144,13 +146,14 @@ private : */ CArray *m_pnActualLineLength; +protected: BOOL m_bPreparingToDrag; BOOL m_bDraggingText; BOOL m_bDragSelection, m_bWordSelection, m_bLineSelection; UINT m_nDragSelTimer; CPoint m_ptDrawSelStart, m_ptDrawSelEnd; -protected: + CPoint m_ptCursorPos, m_ptCursorLast; CPoint m_ptSelStart, m_ptSelEnd; void PrepareSelBounds (); diff --git a/Src/readme.txt b/Src/readme.txt index d093aecf8..13a42a15a 100644 --- a/Src/readme.txt +++ b/Src/readme.txt @@ -1,3 +1,9 @@ +2003-09-07 Laoran + PATCH: [ 799464 ] preserve positions during Rescan (2.1) + WinMerge: GhostTextBuffer.cpp GhostTextView.cpp GhostTextView.h MergeDoc.cpp + editlib: ccrystaleditview.cpp ccrystaleditview.h ccrystaltextbuffer.cpp ccrystaltextbuffer.h + ccrystaltextview.cpp ccrystaltextview.h + 2003-09-07 Kimmo BUG: [ 802063 ] files_analyzeFile bug for UNIX file (2.1) WinMerge: files.cpp -- 2.11.0