From fd1692b657838f137c8974eae7730510b7d190df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= 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 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& rAttribList) + const EECharAttrib* FindCharAttrib(int nPosition, sal_uInt16 nWhich, std::vector& 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 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(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& 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