Blob Blame History Raw
From fd1692b657838f137c8974eae7730510b7d190df Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm@redhat.com>
Date: Fri, 24 Apr 2020 16:38:26 +0100
Subject: [PATCH] Resolves: tdf#132288 don't merge adjacent properties for
 spell checking
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

spell checking relies on each attribute chunk being unmerged with identical
adjacent chunks

squash includes...

nStartPosition and nEndPosition are always the same

and

tdf#132288 preservation of footnote depends on reverse iteration

like TextCharAttribList::FindAttrib does which spell checking
used before

commit 243b5b392906042ab03800e0b5765e6f3513372c
Author: Caolán McNamara <caolanm@redhat.com>
Date:   Fri Jun 14 21:56:44 2019 +0100

    weld SpellDialog

converted to use an EditEngine instead of a TextEngine in order to
be able to host it in a native widget

Change-Id: Ia835fa054cad0dee4304f16724b9eb0c29b46102
---
 cui/source/dialogs/SpellDialog.cxx | 37 ++++++++++++++++--------------
 editeng/inc/editdoc.hxx            |  3 +++
 editeng/source/editeng/editdoc.cxx | 12 +++++++++-
 editeng/source/editeng/editeng.cxx |  4 ++++
 include/editeng/editeng.hxx        |  5 ++++
 5 files changed, 43 insertions(+), 18 deletions(-)

diff --git a/cui/source/dialogs/SpellDialog.cxx b/cui/source/dialogs/SpellDialog.cxx
index 1bb15c934552..17bff36056fb 100644
--- a/cui/source/dialogs/SpellDialog.cxx
+++ b/cui/source/dialogs/SpellDialog.cxx
@@ -1142,6 +1142,8 @@ void SentenceEditWindow_Impl::SetDrawingArea(weld::DrawingArea* pDrawingArea)
                pDrawingArea->get_text_height() * 6);
     pDrawingArea->set_size_request(aSize.Width(), aSize.Height());
     WeldEditView::SetDrawingArea(pDrawingArea);
+    // tdf#132288 don't merge equal adjacent attributes
+    m_xEditEngine->DisableAttributeExpanding();
 }
 
 SentenceEditWindow_Impl::~SentenceEditWindow_Impl()
@@ -1150,13 +1152,14 @@ SentenceEditWindow_Impl::~SentenceEditWindow_Impl()
 
 namespace
 {
-    const EECharAttrib* FindCharAttrib(int nStartPosition, int nEndPosition, sal_uInt16 nWhich, std::vector<EECharAttrib>& rAttribList)
+    const EECharAttrib* FindCharAttrib(int nPosition, sal_uInt16 nWhich, std::vector<EECharAttrib>& rAttribList)
     {
-        for (const auto& rTextAtr : rAttribList)
+        for (auto it = rAttribList.rbegin(); it != rAttribList.rend(); ++it)
         {
+            const auto& rTextAtr = *it;
             if (rTextAtr.pAttr->Which() != nWhich)
                 continue;
-            if (rTextAtr.nStart <= nStartPosition && rTextAtr.nEnd >= nEndPosition)
+            if (rTextAtr.nStart <= nPosition && rTextAtr.nEnd >= nPosition)
             {
                 return &rTextAtr;
             }
@@ -1272,8 +1275,8 @@ bool SentenceEditWindow_Impl::KeyInput(const KeyEvent& rKeyEvt)
         m_xEditEngine->GetCharAttribs(0, aAttribList);
 
         auto nCursor = aCurrentSelection.nStartPos;
-        const EECharAttrib* pBackAttr = FindCharAttrib(nCursor, nCursor, EE_CHAR_BKGCOLOR, aAttribList);
-        const EECharAttrib* pErrorAttr = FindCharAttrib(nCursor, nCursor, EE_CHAR_GRABBAG, aAttribList);
+        const EECharAttrib* pBackAttr = FindCharAttrib(nCursor, EE_CHAR_BKGCOLOR, aAttribList);
+        const EECharAttrib* pErrorAttr = FindCharAttrib(nCursor, EE_CHAR_GRABBAG, aAttribList);
         const EECharAttrib* pBackAttrLeft = nullptr;
         const EECharAttrib* pErrorAttrLeft = nullptr;
 
@@ -1299,8 +1302,8 @@ bool SentenceEditWindow_Impl::KeyInput(const KeyEvent& rKeyEvt)
                 while (nCursor < aCurrentSelection.nEndPos)
                 {
                     ++nCursor;
-                    const EECharAttrib* pIntBackAttr = FindCharAttrib(nCursor, nCursor, EE_CHAR_BKGCOLOR, aAttribList);
-                    const EECharAttrib* pIntErrorAttr = FindCharAttrib(nCursor, nCursor, EE_CHAR_GRABBAG, aAttribList);
+                    const EECharAttrib* pIntBackAttr = FindCharAttrib(nCursor, EE_CHAR_BKGCOLOR, aAttribList);
+                    const EECharAttrib* pIntErrorAttr = FindCharAttrib(nCursor, EE_CHAR_GRABBAG, aAttribList);
                     //if any attr has been found then BRACE
                     if (pIntBackAttr || pIntErrorAttr)
                         nSelectionType = BRACE;
@@ -1342,8 +1345,8 @@ bool SentenceEditWindow_Impl::KeyInput(const KeyEvent& rKeyEvt)
             if (nCursor)
             {
                 --nCursor;
-                pBackAttrLeft = FindCharAttrib(nCursor, nCursor, EE_CHAR_BKGCOLOR, aAttribList);
-                pErrorAttrLeft = FindCharAttrib(nCursor, nCursor, EE_CHAR_GRABBAG, aAttribList);
+                pBackAttrLeft = FindCharAttrib(nCursor, EE_CHAR_BKGCOLOR, aAttribList);
+                pErrorAttrLeft = FindCharAttrib(nCursor, EE_CHAR_GRABBAG, aAttribList);
                 bHasFieldLeft = pBackAttrLeft !=nullptr;
                 bHasErrorLeft = pErrorAttrLeft != nullptr;
                 ++nCursor;
@@ -1492,8 +1495,8 @@ bool SentenceEditWindow_Impl::KeyInput(const KeyEvent& rKeyEvt)
         //start position
         if (!IsUndoEditMode() && bIsErrorActive)
         {
-            const EECharAttrib* pFontColor = FindCharAttrib(nCursor, nCursor, EE_CHAR_COLOR, aAttribList);
-            const EECharAttrib* pErrorAttrib = FindCharAttrib(m_nErrorStart, m_nErrorStart, EE_CHAR_GRABBAG, aAttribList);
+            const EECharAttrib* pFontColor = FindCharAttrib(nCursor, EE_CHAR_COLOR, aAttribList);
+            const EECharAttrib* pErrorAttrib = FindCharAttrib(m_nErrorStart, EE_CHAR_GRABBAG, aAttribList);
             if (pFontColor && pErrorAttrib)
             {
                 m_nErrorStart = pFontColor->nStart;
@@ -1695,7 +1698,7 @@ int SentenceEditWindow_Impl::ChangeMarkedWord(const OUString& rNewWord, Language
     auto nDiffLen = rNewWord.getLength() - m_nErrorEnd + m_nErrorStart;
     //Remove spell error attribute
     m_xEditEngine->UndoActionStart(SPELLUNDO_MOVE_ERROREND);
-    const EECharAttrib* pErrorAttrib = FindCharAttrib(m_nErrorStart, m_nErrorStart, EE_CHAR_GRABBAG, aAttribList);
+    const EECharAttrib* pErrorAttrib = FindCharAttrib(m_nErrorStart, EE_CHAR_GRABBAG, aAttribList);
     DBG_ASSERT(pErrorAttrib, "no error attribute found");
     bool bSpellErrorDescription = false;
     SpellErrorDescription aSpellErrorDescription;
@@ -1706,7 +1709,7 @@ int SentenceEditWindow_Impl::ChangeMarkedWord(const OUString& rNewWord, Language
         bSpellErrorDescription = true;
     }
 
-    const EECharAttrib* pBackAttrib = FindCharAttrib(m_nErrorStart, m_nErrorStart, EE_CHAR_BKGCOLOR, aAttribList);
+    const EECharAttrib* pBackAttrib = FindCharAttrib(m_nErrorStart, EE_CHAR_BKGCOLOR, aAttribList);
 
     ESelection aSel(0, m_nErrorStart, 0, m_nErrorEnd);
     m_xEditEngine->QuickInsertText(rNewWord, aSel);
@@ -1721,7 +1724,7 @@ int SentenceEditWindow_Impl::ChangeMarkedWord(const OUString& rNewWord, Language
         //attributes following an error at the start of the text are not moved but expanded from the
         //text engine - this is done to keep full-paragraph-attributes
         //in the current case that handling is not desired
-        const EECharAttrib* pLangAttrib = FindCharAttrib(m_nErrorEnd, m_nErrorEnd, EE_CHAR_LANGUAGE, aAttribList);
+        const EECharAttrib* pLangAttrib = FindCharAttrib(m_nErrorEnd, EE_CHAR_LANGUAGE, aAttribList);
 
         if (pLangAttrib && !pLangAttrib->nStart && pLangAttrib->nEnd == nTextLen)
         {
@@ -1776,7 +1779,7 @@ bool SentenceEditWindow_Impl::GetErrorDescription(SpellErrorDescription& rSpellE
     std::vector<EECharAttrib> aAttribList;
     m_xEditEngine->GetCharAttribs(0, aAttribList);
 
-    if (const EECharAttrib* pEECharAttrib = FindCharAttrib(nPosition, nPosition, EE_CHAR_GRABBAG, aAttribList))
+    if (const EECharAttrib* pEECharAttrib = FindCharAttrib(nPosition, EE_CHAR_GRABBAG, aAttribList))
     {
         ExtractErrorDescription(*pEECharAttrib, rSpellErrorDescription);
         return true;
@@ -1895,7 +1898,7 @@ svx::SpellPortions SentenceEditWindow_Impl::CreateSpellPortions() const
         const EECharAttrib* pError = nullptr;
         while (nCursor < nTextLen)
         {
-            const EECharAttrib* pLang = FindCharAttrib(nCursor, nCursor, EE_CHAR_LANGUAGE, aAttribList);
+            const EECharAttrib* pLang = FindCharAttrib(nCursor, EE_CHAR_LANGUAGE, aAttribList);
             if(pLang && pLang != pLastLang)
             {
                 eLang = static_cast<const SvxLanguageItem*>(pLang->pAttr)->GetLanguage();
@@ -1903,7 +1906,7 @@ svx::SpellPortions SentenceEditWindow_Impl::CreateSpellPortions() const
                 lcl_InsertBreakPosition_Impl(aBreakPositions, pLang->nEnd, eLang);
                 pLastLang = pLang;
             }
-            pError = FindCharAttrib(nCursor, nCursor, EE_CHAR_GRABBAG, aAttribList);
+            pError = FindCharAttrib(nCursor, EE_CHAR_GRABBAG, aAttribList);
             if (pError && pLastError != pError)
             {
                 lcl_InsertBreakPosition_Impl(aBreakPositions, pError->nStart, eLang);
diff --git a/editeng/inc/editdoc.hxx b/editeng/inc/editdoc.hxx
index 089addc59c07..258fa945912c 100644
--- a/editeng/inc/editdoc.hxx
+++ b/editeng/inc/editdoc.hxx
@@ -747,6 +747,7 @@ private:
 
     bool            bOwnerOfPool:1;
     bool            bModified:1;
+    bool            bDisableAttributeExpanding:1;
 
 private:
     void            ImplDestroyContents();
@@ -761,6 +762,8 @@ public:
     bool            IsModified() const      { return bModified; }
     void            SetModified( bool b );
 
+    void            DisableAttributeExpanding() { bDisableAttributeExpanding = true; }
+
     void            SetModifyHdl( const Link<LinkParamNone*,void>& rLink ) { aModifyHdl = rLink; }
 
     void            CreateDefFont( bool bUseStyles );
diff --git a/editeng/source/editeng/editdoc.cxx b/editeng/source/editeng/editdoc.cxx
index 73a356054741..aacc0b2c7b6b 100644
--- a/editeng/source/editeng/editdoc.cxx
+++ b/editeng/source/editeng/editdoc.cxx
@@ -1906,7 +1906,8 @@ EditDoc::EditDoc( SfxItemPool* pPool ) :
     bIsTopToBottomVert(false),
     bIsFixedCellHeight(false),
     bOwnerOfPool(pPool == nullptr),
-    bModified(false)
+    bModified(false),
+    bDisableAttributeExpanding(false)
 {
     // Don't create an empty node, Clear() will be called in EditEngine-CTOR
 };
@@ -2354,6 +2355,15 @@ void EditDoc::InsertAttribInSelection( ContentNode* pNode, sal_Int32 nStart, sal
 
     RemoveAttribs( pNode, nStart, nEnd, pStartingAttrib, pEndingAttrib, rPoolItem.Which() );
 
+    // tdf#132288  By default inserting an attribute beside another that is of
+    // the same type expands the original instead of inserting another. But the
+    // spell check dialog doesn't want that behaviour
+    if (bDisableAttributeExpanding)
+    {
+        pStartingAttrib = nullptr;
+        pEndingAttrib = nullptr;
+    }
+
     if ( pStartingAttrib && pEndingAttrib &&
          ( *(pStartingAttrib->GetItem()) == rPoolItem ) &&
          ( *(pEndingAttrib->GetItem()) == rPoolItem ) )
diff --git a/editeng/source/editeng/editeng.cxx b/editeng/source/editeng/editeng.cxx
index 458f71b34d3f..f46106a5773c 100644
--- a/editeng/source/editeng/editeng.cxx
+++ b/editeng/source/editeng/editeng.cxx
@@ -2802,6 +2802,10 @@ bool EditEngine::IsPageOverflow() {
     return pImpEditEngine->IsPageOverflow();
 }
 
+void EditEngine::DisableAttributeExpanding() {
+    pImpEditEngine->GetEditDoc().DisableAttributeExpanding();
+}
+
 EFieldInfo::EFieldInfo()
 {
 }
diff --git a/include/editeng/editeng.hxx b/include/editeng/editeng.hxx
index f585ce8b5796..7d4129c0ad0b 100644
--- a/include/editeng/editeng.hxx
+++ b/include/editeng/editeng.hxx
@@ -618,6 +618,11 @@ public:
     sal_Int32 GetOverflowingLineNum() const;
     void ClearOverflowingParaNum();
     bool IsPageOverflow();
+
+    // tdf#132288  By default inserting an attribute beside another that is of
+    // the same type expands the original instead of inserting another. But the
+    // spell check dialog doesn't want that behaviour
+    void DisableAttributeExpanding();
 };
 
 #endif // INCLUDED_EDITENG_EDITENG_HXX
-- 
2.25.3