Rebased ref, commits from common ancestor: commit 663a185104b7dbc942859621f51068d50b479fa4 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Mon Oct 15 15:24:08 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Mon Oct 15 15:25:46 2018 +0200
sw_redlinehide_3: fix SwAccessibleParagraph not being disposed If it is merged, it doesn't have GetDep(). Change-Id: I5a362c03fe7fcb0a6246aef0a0ac2824c48ede36 diff --git a/sw/source/core/layout/ssfrm.cxx b/sw/source/core/layout/ssfrm.cxx index 8550f4a7f4f6..bdec06fb726c 100644 --- a/sw/source/core/layout/ssfrm.cxx +++ b/sw/source/core/layout/ssfrm.cxx @@ -325,8 +325,10 @@ void SwFrame::DestroyImpl() // accessible objects for fly and cell frames have been already disposed // by the destructors of the derived classes. - if( IsAccessibleFrame() && !(IsFlyFrame() || IsCellFrame()) && GetDep() ) + if (IsAccessibleFrame() && !(IsFlyFrame() || IsCellFrame()) + && (GetDep() || IsTextFrame())) // sw_redlinehide: text frame may not have Dep! { + assert(!IsTextFrame() || GetDep() || static_cast<SwTextFrame*>(this)->GetMergedPara()); SwRootFrame *pRootFrame = getRootFrame(); if( pRootFrame && pRootFrame->IsAnyShellAccessible() ) { commit 877ca8d821ec300810a76d1a2ddb2e409d225540 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Fri Oct 12 16:33:00 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Mon Oct 15 15:25:46 2018 +0200 sw_redlinehide_3: fix crash when storing clipboard document It doesn't have a layout, of course. Change-Id: Iec4809ec4a14e1fa9852d09619a8b344419b29e7 diff --git a/sw/source/filter/xml/wrtxml.cxx b/sw/source/filter/xml/wrtxml.cxx index df75d14868db..0d5e53d4c319 100644 --- a/sw/source/filter/xml/wrtxml.cxx +++ b/sw/source/filter/xml/wrtxml.cxx @@ -189,7 +189,8 @@ ErrCode SwXMLWriter::Write_( const uno::Reference < task::XStatusIndicator >& xS bool isShowChanges; if (officecfg::Office::Common::Misc::ExperimentalMode::get(xContext)) { // TODO: ideally this would be stored per-view... - isShowChanges = !m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout()->IsHideRedlines(); + SwRootFrame const*const pLayout(m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout()); + isShowChanges = pLayout == nullptr || !pLayout->IsHideRedlines(); } else { commit 20d2357e0050fbbd68dde7acaef72e26b8f2e1cc Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Fri Oct 12 16:31:31 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Mon Oct 15 15:25:46 2018 +0200 sw_redlinehide_3: fix SwAttrIter::SeekFwd() This never called Rst() in the loops because the m_nPosition wasn't updated. Change-Id: I5a9cf47d9fe6d92bb7fccf255acbbd22f04b7f47 diff --git a/sw/source/core/text/itratr.cxx b/sw/source/core/text/itratr.cxx index 0533fae9be27..18145cb38523 100644 --- a/sw/source/core/text/itratr.cxx +++ b/sw/source/core/text/itratr.cxx @@ -260,7 +260,7 @@ bool SwAttrIter::SeekStartAndChgAttrIter( OutputDevice* pOut, const bool bParaFo } // AMA: New AttrIter Nov 94 -void SwAttrIter::SeekFwd( const sal_Int32 nNewPos ) +void SwAttrIter::SeekFwd(const sal_Int32 nOldPos, const sal_Int32 nNewPos) { SwpHints const*const pHints(m_pTextNode->GetpSwpHints()); SwTextAttr *pTextAttr; @@ -276,7 +276,7 @@ void SwAttrIter::SeekFwd( const sal_Int32 nNewPos ) { // Close the TextAttributes, whose StartPos were before or at // the old nPos and are currently open - if (pTextAttr->GetStart() <= m_nPosition) Rst( pTextAttr ); + if (pTextAttr->GetStart() <= nOldPos) Rst( pTextAttr ); m_nEndIndex++; } } @@ -320,14 +320,15 @@ bool SwAttrIter::Seek(TextFrameIndex const nNewPos) sal_Int32 nPos(m_nPosition); do { + sal_Int32 const nOldPos(nPos); nPos = GetNextAttrImpl(m_pTextNode, m_nStartIndex, m_nEndIndex, nPos); if (nPos <= m_pTextNode->Len()) { - SeekFwd(nPos); + SeekFwd(nOldPos, nPos); } else { - SeekFwd(m_pTextNode->Len()); + SeekFwd(nOldPos, m_pTextNode->Len()); } } while (nPos < m_pTextNode->Len()); @@ -399,21 +400,22 @@ bool SwAttrIter::Seek(TextFrameIndex const nNewPos) sal_Int32 nPos(m_nPosition); do { + sal_Int32 const nOldPos(nPos); nPos = GetNextAttrImpl(m_pTextNode, m_nStartIndex, m_nEndIndex, nPos); if (nPos <= newPos.second) { - SeekFwd(nPos); + SeekFwd(nOldPos, nPos); } else { - SeekFwd(newPos.second); + SeekFwd(nOldPos, newPos.second); } } while (nPos < newPos.second); } else { - SeekFwd(newPos.second); + SeekFwd(m_nPosition, newPos.second); } } diff --git a/sw/source/core/text/itratr.hxx b/sw/source/core/text/itratr.hxx index 99741c87b965..959436609608 100644 --- a/sw/source/core/text/itratr.hxx +++ b/sw/source/core/text/itratr.hxx @@ -63,7 +63,7 @@ private: const SwTextNode* m_pTextNode; sw::MergedPara const* m_pMergedPara; - void SeekFwd( const sal_Int32 nPos ); + void SeekFwd(sal_Int32 nOldPos, sal_Int32 nNewPos); void SetFnt( SwFont* pNew ) { m_pFont = pNew; } void InitFontAndAttrHandler(SwTextNode const& rTextNode, OUString const& rText, bool const* pbVertLayout); commit b22bbacf5caf307a61bc77f410f5187766d5197d Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Fri Oct 12 15:06:35 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Mon Oct 15 15:25:46 2018 +0200 sw_redlinehide_3: fix SwAccessibleParagraph::getRunAttributes() index ... check, which should accept the past-the-last-char index, because as the comments say it returns the hard attributes of the SwTextNode as well, so it should work for empty paragraphs too. (similar fix was done in getCharacterAttributes() in IA2) Change-Id: I01e1a8f66f103b63584e88ce785ac2044c5db2b9 diff --git a/sw/source/core/access/accpara.cxx b/sw/source/core/access/accpara.cxx index eec1a569da46..2e66b453b57d 100644 --- a/sw/source/core/access/accpara.cxx +++ b/sw/source/core/access/accpara.cxx @@ -1415,7 +1415,7 @@ uno::Sequence<PropertyValue> SwAccessibleParagraph::getCharacterAttributes( const OUString& rText = GetString(); - if( ! IsValidChar( nIndex, rText.getLength()+1 ) ) + if (!IsValidPosition(nIndex, rText.getLength())) throw lang::IndexOutOfBoundsException(); bool bSupplementalMode = false; @@ -1844,7 +1844,7 @@ uno::Sequence< PropertyValue > SwAccessibleParagraph::getRunAttributes( { const OUString& rText = GetString(); - if ( !IsValidChar( nIndex, rText.getLength() ) ) + if (!IsValidPosition(nIndex, rText.getLength())) { throw lang::IndexOutOfBoundsException(); } commit 7b69774c9d407a728b7c72cabf53439692732cd2 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Thu Oct 11 18:03:27 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Mon Oct 15 15:25:46 2018 +0200 sw_redlinehide_3: rewrite MergedAttrIterByEnd It doesn't actually work with a similar logic to the other iterators, because it iterates ByEnd but forwards, so the hints and the extents don't come in a matching order. To prevent complicating this further, replace it with a new implementation that does only what the one client expects, and put it directly in SwTextFormatter replacing the previous integer iterator m_nHintEndIndex, so that it is created only once. Change-Id: I144bfcf7e837a4fb0e7ec279edfba4732d0ae897 diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx index 0cb3f3defe83..f537a98d0f95 100644 --- a/sw/source/core/inc/txtfrm.hxx +++ b/sw/source/core/inc/txtfrm.hxx @@ -971,11 +971,15 @@ public: }; class MergedAttrIterByEnd - : public MergedAttrIterBase { +private: + std::vector<std::pair<SwTextNode const*, SwTextAttr const*>> m_Hints; + SwTextNode const*const m_pNode; + size_t m_CurrentHint; public: - MergedAttrIterByEnd(SwTextFrame const& rFrame) : MergedAttrIterBase(rFrame) {} - SwTextAttr const* NextAttr(SwTextNode const** ppNode = nullptr); + MergedAttrIterByEnd(SwTextFrame const& rFrame); + SwTextAttr const* NextAttr(SwTextNode const*& rpNode); + void PrevAttr(); }; class MergedAttrIterReverse diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx index 16d35e581131..879da6c822d9 100644 --- a/sw/source/core/text/itrform2.cxx +++ b/sw/source/core/text/itrform2.cxx @@ -97,7 +97,7 @@ void SwTextFormatter::CtorInitTextFormatter( SwTextFrame *pNewFrame, SwTextForma nCntMidHyph = 0; nLeftScanIdx = TextFrameIndex(COMPLETE_STRING); nRightScanIdx = TextFrameIndex(0); - m_nHintEndIndex = 0; + m_pByEndIter.reset(); m_pFirstOfBorderMerge = nullptr; if (m_nStart > TextFrameIndex(GetInfo().GetText().getLength())) @@ -289,7 +289,7 @@ SwLinePortion *SwTextFormatter::Underflow( SwTextFormatInfo &rInf ) static_cast<SwFieldPortion*>(pRest)->IsNoLength()) { // HACK: decrement again, so we pick up the suffix in next line! - --m_nHintEndIndex; + m_pByEndIter->PrevAttr(); } delete pRest; rInf.SetRest(nullptr); diff --git a/sw/source/core/text/itrform2.hxx b/sw/source/core/text/itrform2.hxx index ff430b8616d1..555fed20cdcc 100644 --- a/sw/source/core/text/itrform2.hxx +++ b/sw/source/core/text/itrform2.hxx @@ -31,6 +31,8 @@ class SwExpandPortion; class SwMultiPortion; class SwFootnotePortion; +namespace sw { class MergedAttrIterByEnd; } + class SwTextFormatter : public SwTextPainter { const SwFormatDrop *pDropFormat; @@ -43,7 +45,7 @@ class SwTextFormatter : public SwTextPainter bool bFlyInCntBase : 1; // Base reference that sets a character-bound frame bool bTruncLines : 1; // Flag for extending the repaint rect, if needed bool bUnclipped : 1; // Flag whether repaint is larger than the fixed line height - size_t m_nHintEndIndex; // HACK for TryNewNoLengthPortion + std::unique_ptr<sw::MergedAttrIterByEnd> m_pByEndIter; // HACK for TryNewNoLengthPortion SwLinePortion* m_pFirstOfBorderMerge; // The first text portion of a joined border (during portion building) SwLinePortion *NewPortion( SwTextFormatInfo &rInf ); diff --git a/sw/source/core/text/txtfld.cxx b/sw/source/core/text/txtfld.cxx index b70b4bc7456b..196b11b84cf9 100644 --- a/sw/source/core/text/txtfld.cxx +++ b/sw/source/core/text/txtfld.cxx @@ -307,9 +307,9 @@ static SwFieldPortion * lcl_NewMetaPortion(SwTextAttr & rHint, const bool bPrefi /** * Try to create a new portion with zero length, for an end of a hint * (where there is no CH_TXTATR). Because there may be multiple hint ends at a - * given index, m_nHintEndIndex is used to keep track of the already created + * given index, m_pByEndIter is used to keep track of the already created * portions. But the portions created here may actually be deleted again, - * due to Underflow. In that case, m_nHintEndIndex must be decremented, + * due to Underflow. In that case, m_pByEndIter must be decremented, * so the portion will be created again on the next line. */ SwExpandPortion * SwTextFormatter::TryNewNoLengthPortion(SwTextFormatInfo const & rInfo) @@ -319,26 +319,24 @@ SwExpandPortion * SwTextFormatter::TryNewNoLengthPortion(SwTextFormatInfo const // sw_redlinehide: because there is a dummy character at the start of these // hints, it's impossible to have ends of hints from different nodes at the // same view position, so it's sufficient to check the hints of the current - // node. However, m_nHintEndIndex exists for the whole text frame, so + // node. However, m_pByEndIter exists for the whole text frame, so // it's necessary to iterate all hints for that purpose... + if (!m_pByEndIter) + { + m_pByEndIter.reset(new sw::MergedAttrIterByEnd(*rInfo.GetTextFrame())); + } SwTextNode const* pNode(nullptr); - sw::MergedAttrIterByEnd iter(*rInfo.GetTextFrame()); - size_t i(0); - for (SwTextAttr const* pHint = iter.NextAttr(&pNode); pHint; - pHint = iter.NextAttr(&pNode)) + for (SwTextAttr const* pHint = m_pByEndIter->NextAttr(pNode); pHint; + pHint = m_pByEndIter->NextAttr(pNode)) { - if (i++ < m_nHintEndIndex) - { - continue; // skip ones that were handled earlier - } SwTextAttr & rHint(const_cast<SwTextAttr&>(*pHint)); TextFrameIndex const nEnd( rInfo.GetTextFrame()->MapModelToView(pNode, *rHint.GetAnyEnd())); if (nEnd > nIdx) { + m_pByEndIter->PrevAttr(); break; } - ++m_nHintEndIndex; if (nEnd == nIdx) { if (RES_TXTATR_METAFIELD == rHint.Which()) diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx index a81a7df905d6..a07d712cd4c7 100644 --- a/sw/source/core/text/txtfrm.cxx +++ b/sw/source/core/text/txtfrm.cxx @@ -153,44 +153,24 @@ namespace sw { } } - SwTextAttr const* MergedAttrIterByEnd::NextAttr(SwTextNode const** ppNode) + MergedAttrIterByEnd::MergedAttrIterByEnd(SwTextFrame const& rFrame) + : m_pNode(rFrame.GetMergedPara() ? nullptr : rFrame.GetTextNodeFirst()) + , m_CurrentHint(0) { - if (m_pMerged) + if (!m_pNode) { - while (m_CurrentExtent < m_pMerged->extents.size()) + MergedAttrIterReverse iter(rFrame); + SwTextNode const* pNode(nullptr); + while (SwTextAttr const* pHint = iter.PrevAttr(&pNode)) { - sw::Extent const& rExtent(m_pMerged->extents[m_CurrentExtent]); - if (SwpHints const*const pHints = rExtent.pNode->GetpSwpHints()) - { - while (m_CurrentHint < pHints->Count()) - { - SwTextAttr const*const pHint( - pHints->GetSortedByEnd(m_CurrentHint)); - if (rExtent.nEnd <= *pHint->GetAnyEnd()) - { - break; - } - ++m_CurrentHint; - if (rExtent.nStart < *pHint->GetAnyEnd()) - { - if (ppNode) - { - *ppNode = rExtent.pNode; - } - return pHint; - } - } - } - ++m_CurrentExtent; - if (m_CurrentExtent < m_pMerged->extents.size() && - rExtent.pNode != m_pMerged->extents[m_CurrentExtent].pNode) - { - m_CurrentHint = 0; // reset - } + m_Hints.emplace_back(pNode, pHint); } - return nullptr; } - else + } + + SwTextAttr const* MergedAttrIterByEnd::NextAttr(SwTextNode const*& rpNode) + { + if (m_pNode) { SwpHints const*const pHints(m_pNode->GetpSwpHints()); if (pHints) @@ -200,15 +180,29 @@ namespace sw { SwTextAttr const*const pHint( pHints->GetSortedByEnd(m_CurrentHint)); ++m_CurrentHint; - if (ppNode) - { - *ppNode = m_pNode; - } + rpNode = m_pNode; return pHint; } } return nullptr; } + else + { + if (m_CurrentHint < m_Hints.size()) + { + auto const ret = m_Hints[m_Hints.size() - m_CurrentHint - 1]; + ++m_CurrentHint; + rpNode = ret.first; + return ret.second; + } + return nullptr; + } + } + + void MergedAttrIterByEnd::PrevAttr() + { + assert(0 < m_CurrentHint); // should only rewind as far as 0 + --m_CurrentHint; } MergedAttrIterReverse::MergedAttrIterReverse(SwTextFrame const& rFrame) commit 4f21227a29ed0860a555e4439b712267a7bedced Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Thu Oct 11 12:41:32 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Mon Oct 15 15:25:46 2018 +0200 sw_redlinehide_3: fix MergedAttrIterReverse Was using the wrong node when iterating; also the tricky case of empty or without-end hints at the start of an extent was wrong. MergedAttrIter also shouldn't include wihout-end hints and non-empty hints at the end of an extent. Change-Id: Ia0776c1d3043cbd6d76fa04905b4937ebba53398 diff --git a/sw/source/core/text/txtfld.cxx b/sw/source/core/text/txtfld.cxx index e66b7ed2c884..b70b4bc7456b 100644 --- a/sw/source/core/text/txtfld.cxx +++ b/sw/source/core/text/txtfld.cxx @@ -424,9 +424,9 @@ static void checkApplyParagraphMarkFormatToNumbering( SwFont* pNumFnt, SwTextFor for (SwTextAttr const* pHint = iter.PrevAttr(&pNode); pHint; pHint = iter.PrevAttr(&pNode)) { - TextFrameIndex const nHintStart( - rInf.GetTextFrame()->MapModelToView(pNode, pHint->GetStart())); - if (nHintStart < nTextLen) + TextFrameIndex const nHintEnd( + rInf.GetTextFrame()->MapModelToView(pNode, *pHint->GetAnyEnd())); + if (nHintEnd < nTextLen) { break; // only those at para end are interesting } diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx index 5603d7800914..a81a7df905d6 100644 --- a/sw/source/core/text/txtfrm.cxx +++ b/sw/source/core/text/txtfrm.cxx @@ -104,8 +104,12 @@ namespace sw { { while (m_CurrentHint < pHints->Count()) { - SwTextAttr const*const pHint(pHints->Get(m_CurrentHint)); - if (rExtent.nEnd < pHint->GetStart()) + SwTextAttr *const pHint(pHints->Get(m_CurrentHint)); + if (rExtent.nEnd < pHint->GetStart() + // <= if it has no end or isn't empty + || (rExtent.nEnd == pHint->GetStart() + && (!pHint->GetEnd() + || *pHint->GetEnd() != pHint->GetStart()))) { break; } @@ -238,13 +242,18 @@ namespace sw { { while (0 < m_CurrentHint) { - SwTextAttr const*const pHint(pHints->Get(m_CurrentHint - 1)); - if (pHint->GetStart() < rExtent.nStart) + SwTextAttr *const pHint( + pHints->GetSortedByEnd(m_CurrentHint - 1)); + if (*pHint->GetAnyEnd() < rExtent.nStart + // <= if it has end and isn't empty + || (pHint->GetEnd() + && *pHint->GetEnd() != pHint->GetStart() + && *pHint->GetEnd() == rExtent.nStart)) { break; } --m_CurrentHint; - if (pHint->GetStart() <= rExtent.nEnd) + if (*pHint->GetAnyEnd() <= rExtent.nEnd) { if (ppNode) { @@ -258,7 +267,8 @@ namespace sw { if (0 < m_CurrentExtent && rExtent.pNode != m_pMerged->extents[m_CurrentExtent-1].pNode) { - SwpHints const*const pHints(rExtent.pNode->GetpSwpHints()); + SwpHints const*const pHints( + m_pMerged->extents[m_CurrentExtent-1].pNode->GetpSwpHints()); m_CurrentHint = pHints ? pHints->Count() : 0; // reset } } @@ -271,7 +281,7 @@ namespace sw { { while (0 < m_CurrentHint) { - SwTextAttr const*const pHint(pHints->Get(m_CurrentHint - 1)); + SwTextAttr const*const pHint(pHints->GetSortedByEnd(m_CurrentHint - 1)); --m_CurrentHint; if (ppNode) { commit 8c8aa24eccf8a5468066af799971a46428917568 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Thu Oct 11 11:17:09 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Mon Oct 15 15:25:46 2018 +0200 sw_redlinehide_3: fix typo bug in SwCursorShell::GetSelText() Change-Id: Ieee07d149d045b7953ea8d5489f2fb6aed13e5e4 diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx index 565acb6d60fd..42febd5f6271 100644 --- a/sw/source/core/crsr/crsrsh.cxx +++ b/sw/source/core/crsr/crsrsh.cxx @@ -2428,7 +2428,7 @@ OUString SwCursorShell::GetSelText() const : 0); sal_Int32 const nEnd(i == pEnd->nNode.GetIndex() ? pEnd->nContent.GetIndex() - : pEnd->nNode.GetNode().GetTextNode()->Len()); + : rNode.GetTextNode()->Len()); buf.append(rNode.GetTextNode()->GetExpandText( nStart, nEnd - nStart, false, false, false, ExpandMode::HideDeletions)); commit 20c6a16446afb455f44dd336884f146718117705 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Wed Oct 10 16:49:58 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Mon Oct 15 15:25:46 2018 +0200 sw: simplify & fix SwAccessibleParagraph::getHyperLink() There is an inconsistency between getHyperLinkCount and getHyperLink, as the latter uses index 0 as a no-op for some ToC link that was never implemented, so all the real hyperlinks have their index offset by 1. Also it's pointless to call getHyperLinkCount once per loop iteration. (regression from 76c549eb01dcb7b5bf28a271ce00e386f3d388ba) Change-Id: Iec83b6680abbdff5d372ca40358bd1306f3bd991 diff --git a/sw/source/core/access/accpara.cxx b/sw/source/core/access/accpara.cxx index f323317d96cf..eec1a569da46 100644 --- a/sw/source/core/access/accpara.cxx +++ b/sw/source/core/access/accpara.cxx @@ -2892,36 +2892,13 @@ uno::Reference< XAccessibleHyperlink > SAL_CALL const SwTextFrame *pTextFrame = static_cast<const SwTextFrame*>( GetFrame() ); SwHyperlinkIter_Impl aHIter(*pTextFrame); - sal_Int32 nTIndex = -1; - SwTOXSortTabBase* pTBase = GetTOXSortTabBase(); SwTextNode const* pNode(nullptr); SwTextAttr* pHt = const_cast<SwTextAttr*>(aHIter.next(&pNode)); - while( (nLinkIndex < getHyperLinkCount()) && nTIndex < nLinkIndex) + for (sal_Int32 nTIndex = 0; pHt && nTIndex <= nLinkIndex; ++nTIndex) { - sal_Int32 nHStt = -1; - bool bH = false; - - if( pHt ) - nHStt = pHt->GetStart(); - bool bTOC = false; - // Inside TOC & get the first link - if( pTBase && nTIndex == -1 ) - { - nTIndex++; - bTOC = true; - } - else if( nHStt >= 0 ) - { - // only hyperlink available - nTIndex++; - bH = true; - } - if( nTIndex == nLinkIndex ) { // found - if( bH ) { // it's a hyperlink - if( pHt ) { if( !m_pHyperTextData ) m_pHyperTextData.reset( new SwAccessibleHyperTextData ); @@ -2955,15 +2932,8 @@ uno::Reference< XAccessibleHyperlink > SAL_CALL break; } - // iterate next - if( bH ) - // iterate next hyperlink - pHt = const_cast<SwTextAttr*>(aHIter.next(&pNode)); - else if(bTOC) - continue; - else - // no candidate, exit - break; + // iterate next hyperlink + pHt = const_cast<SwTextAttr*>(aHIter.next(&pNode)); } if( !xRet.is() ) throw lang::IndexOutOfBoundsException(); commit fe6bb0c290991d3122f36f0aadd9387d32e79889 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Wed Oct 10 14:44:14 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Mon Oct 15 15:25:46 2018 +0200 sw_redlinehide_3: convert SwAccessibleMap BuildSelectedParas() needs a little tweak to create idempotent map entries while it iterates over the nodes of a merged paragraph. InvalidateShapeInParaSelection() has some dodgy code to check if flys are selected; probably should check for the start pos. of the frame for AT_PARA anchor. Change-Id: I2abe5dff1fb7fd0b95cc6c78b756f250db5f0872 diff --git a/sw/source/core/access/accmap.cxx b/sw/source/core/access/accmap.cxx index eb6557db7bea..299f78eee657 100644 --- a/sw/source/core/access/accmap.cxx +++ b/sw/source/core/access/accmap.cxx @@ -598,13 +598,13 @@ public: struct SwAccessibleParaSelection { - sal_Int32 const nStartOfSelection; - sal_Int32 const nEndOfSelection; + TextFrameIndex const nStartOfSelection; + TextFrameIndex const nEndOfSelection; - SwAccessibleParaSelection( const sal_Int32 _nStartOfSelection, - const sal_Int32 _nEndOfSelection ) - : nStartOfSelection( _nStartOfSelection ), - nEndOfSelection( _nEndOfSelection ) + SwAccessibleParaSelection(const TextFrameIndex nStartOfSelection_, + const TextFrameIndex nEndOfSelection_) + : nStartOfSelection(nStartOfSelection_) + , nEndOfSelection(nEndOfSelection_) {} }; @@ -1173,6 +1173,18 @@ void SwAccessibleMap::InvalidateShapeInParaSelection() if( pCursor != nullptr ) { const SwTextNode* pNode = pPos->nNode.GetNode().GetTextNode(); + SwTextFrame const*const pFrame(static_cast<SwTextFrame*>(pNode->getLayoutFrame(pVSh->GetLayout()))); + sal_uLong nFirstNode(pFrame->GetTextNodeFirst()->GetIndex()); + sal_uLong nLastNode; + if (sw::MergedPara const*const pMerged = pFrame->GetMergedPara()) + { + nLastNode = pMerged->pLastNode->GetIndex(); + } + else + { + nLastNode = nFirstNode; + } + sal_uLong nHere = pNode->GetIndex(); for(SwPaM& rTmpCursor : pCursor->GetRingContainer()) @@ -1186,8 +1198,9 @@ void SwAccessibleMap::InvalidateShapeInParaSelection() sal_uLong nStartIndex = pStart->nNode.GetIndex(); SwPosition* pEnd = rTmpCursor.End(); sal_uLong nEndIndex = pEnd->nNode.GetIndex(); - if( ( nHere >= nStartIndex ) && (nHere <= nEndIndex) ) + if ((nStartIndex <= nLastNode) && (nFirstNode <= nEndIndex)) { + // FIXME: what about missing FLY_AT_CHAR? if( rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR ) { if( ( ((nHere == nStartIndex) && (nIndex >= pStart->nContent.GetIndex())) || (nHere > nStartIndex) ) @@ -1206,8 +1219,9 @@ void SwAccessibleMap::InvalidateShapeInParaSelection() } else if( rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA ) { - if( ((nHere > nStartIndex) || pStart->nContent.GetIndex() ==0 ) - && (nHere < nEndIndex ) ) + if (((nStartIndex < nFirstNode) || + (nFirstNode == nStartIndex && pStart->nContent.GetIndex() == 0)) + && (nLastNode < nEndIndex)) { uno::Reference < XAccessible > xAcc( (*aIter).second ); if( xAcc.is() ) @@ -1313,13 +1327,17 @@ void SwAccessibleMap::InvalidateShapeInParaSelection() { SwNodeIndex nStartIndex( rTmpCursor.Start()->nNode ); SwNodeIndex nEndIndex( rTmpCursor.End()->nNode ); - while(nStartIndex <= nEndIndex) + for (; nStartIndex <= nEndIndex; ++nStartIndex) { SwFrame *pFrame = nullptr; if(nStartIndex.GetNode().IsContentNode()) { SwContentNode* pCNd = static_cast<SwContentNode*>(&(nStartIndex.GetNode())); pFrame = SwIterator<SwFrame, SwContentNode, sw::IteratorMode::UnwrapMulti>(*pCNd).First(); + if (mapTemp.find(pFrame) != mapTemp.end()) + { + continue; // sw_redlinehide: once is enough + } } else if( nStartIndex.GetNode().IsTableNode() ) { @@ -1354,7 +1372,6 @@ void SwAccessibleMap::InvalidateShapeInParaSelection() mapTemp.emplace( pFrame, xAcc ); } } - ++nStartIndex; } } } @@ -3313,17 +3330,19 @@ std::unique_ptr<SwAccessibleSelectedParas_Impl> SwAccessibleMap::BuildSelectedPa { xWeakAcc = (*aMapIter).second; SwAccessibleParaSelection aDataEntry( - pTextNode == &(pStartPos->nNode.GetNode()) - ? pStartPos->nContent.GetIndex() - : 0, - pTextNode == &(pEndPos->nNode.GetNode()) - ? pEndPos->nContent.GetIndex() - : -1 ); + sw::FrameContainsNode(*pTextFrame, pStartPos->nNode.GetIndex()) + ? pTextFrame->MapModelToViewPos(*pStartPos) + : TextFrameIndex(0), + + sw::FrameContainsNode(*pTextFrame, pEndPos->nNode.GetIndex()) + ? pTextFrame->MapModelToViewPos(*pEndPos) + : TextFrameIndex(COMPLETE_STRING)); if ( !pRetSelectedParas ) { pRetSelectedParas.reset( new SwAccessibleSelectedParas_Impl); } + // sw_redlinehide: should be idempotent for multiple nodes in a merged para pRetSelectedParas->emplace( xWeakAcc, aDataEntry ); } } commit af0a9aaf9d9adaeacf3b3ca477adadd8efd07617 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Wed Oct 10 12:02:53 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Mon Oct 15 15:25:46 2018 +0200 sw_redlinehide_3: adapt SwAccessibleDocument::getAccFlowTo() This looks like it wants to deduplicate paragraphs; just use a std::set for the frames, and retrieve them with a particular SwPosition, which should deduplicate fine. Change-Id: I0d0bd5cc4eb8d41d0a2f64979ccfde62ebc3533a diff --git a/sw/source/core/access/accdoc.cxx b/sw/source/core/access/accdoc.cxx index b525e52e1abc..c4faadebe69c 100644 --- a/sw/source/core/access/accdoc.cxx +++ b/sw/source/core/access/accdoc.cxx @@ -834,24 +834,19 @@ css::uno::Sequence< css::uno::Any > if ( pCursorShell ) { SwPaM *_pStartCursor = pCursorShell->GetCursor(), *_pStartCursor2 = _pStartCursor; - SwContentNode* pPrevNode = nullptr; - std::vector<SwFrame*> vFrameList; + std::set<SwFrame*> vFrameList; do { if ( _pStartCursor && _pStartCursor->HasMark() ) { SwContentNode* pContentNode = _pStartCursor->GetContentNode(); - if ( pContentNode == pPrevNode ) - { - continue; - } - SwFrame* pFrame = pContentNode ? pContentNode->getLayoutFrame( pCursorShell->GetLayout() ) : nullptr; + SwFrame *const pFrame = pContentNode + ? pContentNode->getLayoutFrame(pCursorShell->GetLayout(), _pStartCursor->GetPoint()) + : nullptr; if ( pFrame ) { - vFrameList.push_back( pFrame ); + vFrameList.insert( pFrame ); } - - pPrevNode = pContentNode; } } @@ -860,7 +855,7 @@ css::uno::Sequence< css::uno::Any > if ( vFrameList.size() ) { uno::Sequence< uno::Any > aRet(vFrameList.size()); - std::vector<SwFrame*>::iterator aIter = vFrameList.begin(); + auto aIter = vFrameList.begin(); for ( sal_Int32 nIndex = 0; aIter != vFrameList.end(); ++aIter, nIndex++ ) { uno::Reference< XAccessible > xAcc = pAccMap->GetContext(*aIter, false); commit 336316f35d9f2797172d777a8ed2e7ac4742513f Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Wed Oct 10 11:28:22 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Mon Oct 15 15:25:46 2018 +0200 sw_redlinehide_3: remove SwTextFrame::GetTextNode() Change-Id: Ie46d8846887e9282ef40d63255f8a70e22f304e9 diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx index 5a9db1f0634a..0cb3f3defe83 100644 --- a/sw/source/core/inc/txtfrm.hxx +++ b/sw/source/core/inc/txtfrm.hxx @@ -416,11 +416,6 @@ public: /// Returns the text portion we want to edit (for inline see underneath) const OUString& GetText() const; - // TODO: remove GetTextNode - SwTextNode *GetTextNode() - { return static_cast<SwTextNode*>(SwFrame::GetDep()); } - const SwTextNode *GetTextNode() const - { return static_cast<const SwTextNode*>(SwFrame::GetDep()); } SwTextNode const* GetTextNodeForParaProps() const; SwTextNode * GetTextNodeFirst() { return const_cast<SwTextNode*>(const_cast<SwTextFrame const*>(this)->GetTextNodeFirst()); }; commit 7d0fecf2a33fa8a417484e8a2e0f19ea9ad356b5 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Wed Oct 10 11:26:04 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Mon Oct 15 15:25:46 2018 +0200 sw_redlinehide_3: minimally convert laycache.cxx Just fix the TextFrameIndex / GetTextNode usages. This does not make the layout cache actually work if IsHideRedlines is enabled, hence the layout cache remains disabled in that case. Change-Id: I9aa1fb490c3dd4fd26165f2e60513ec267857d78 diff --git a/sw/source/core/layout/laycache.cxx b/sw/source/core/layout/laycache.cxx index b507e0933293..f4110461d59a 100644 --- a/sw/source/core/layout/laycache.cxx +++ b/sw/source/core/layout/laycache.cxx @@ -201,7 +201,7 @@ void SwLayoutCache::Write( SvStream &rStream, const SwDoc& rDoc ) nNdIdx -= nStartOfContent; aIo.GetStream().WriteUInt32( nNdIdx ); if( bFollow ) - aIo.GetStream().WriteUInt32( static_cast<SwTextFrame*>(pTmp)->GetOfst() ); + aIo.GetStream().WriteUInt32( sal_Int32(static_cast<SwTextFrame*>(pTmp)->GetOfst()) ); aIo.CloseFlagRec(); /* Close Paragraph Record */ aIo.CloseRec(); @@ -357,8 +357,9 @@ bool SwLayoutCache::CompareLayout( const SwDoc& rDoc ) const if( pImpl->GetBreakIndex( nIndex ) != nNdIdx || SW_LAYCACHE_IO_REC_PARA != pImpl->GetBreakType( nIndex ) || - ( bFollow ? static_cast<const SwTextFrame*>(pTmp)->GetOfst() - : COMPLETE_STRING ) != pImpl->GetBreakOfst( nIndex ) ) + (bFollow + ? sal_Int32(static_cast<const SwTextFrame*>(pTmp)->GetOfst()) + : COMPLETE_STRING) != pImpl->GetBreakOfst(nIndex)) { return false; } @@ -799,7 +800,7 @@ bool SwLayHelper::CheckInsert( sal_uLong nNodeIndex ) sal_uInt16 nRepeat( 0 ); if( !bLongTab && mrpFrame->IsTextFrame() && SW_LAYCACHE_IO_REC_PARA == nType && - nOfst < static_cast<SwTextFrame*>(mrpFrame)->GetTextNode()->GetText().getLength()) + nOfst < static_cast<SwTextFrame*>(mrpFrame)->GetText().getLength()) bSplit = true; else if( mrpFrame->IsTabFrame() && nRowCount < nOfst && ( bLongTab || SW_LAYCACHE_IO_REC_TABLE == nType ) ) @@ -873,8 +874,8 @@ bool SwLayHelper::CheckInsert( sal_uLong nNodeIndex ) { SwTextFrame *const pNew = static_cast<SwTextFrame*>( static_cast<SwTextFrame*>(mrpFrame) - ->GetTextNode()->MakeFrame(mrpFrame)); - pNew->ManipOfst( nOfst ); + ->GetTextNodeFirst()->MakeFrame(mrpFrame)); + pNew->ManipOfst( TextFrameIndex(nOfst) ); pNew->SetFollow( static_cast<SwTextFrame*>(mrpFrame)->GetFollow() ); static_cast<SwTextFrame*>(mrpFrame)->SetFollow( pNew ); mrpFrame = pNew; diff --git a/sw/source/core/layout/layhelp.hxx b/sw/source/core/layout/layhelp.hxx index f4201ccb09b5..87b832321d98 100644 --- a/sw/source/core/layout/layhelp.hxx +++ b/sw/source/core/layout/layhelp.hxx @@ -53,6 +53,7 @@ typedef std::vector<SwFlyCache> SwPageFlyCache; class SwLayCacheImpl { std::vector<sal_uLong> mIndices; + /// either a textframe character offset, or a row index inside a table std::deque<sal_Int32> aOffset; std::vector<sal_uInt16> aType; SwPageFlyCache m_FlyCache; commit e0c14b5f74960edaeaf1fabaeff8454e8e6d3b6e Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Tue Oct 9 18:43:44 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Mon Oct 15 15:25:46 2018 +0200 sw_redlinehide_3: SwXTextViewCursor::getString() without redlines Change-Id: I734e27c95e20373f8de32f8db2183275c94144e5 diff --git a/sw/inc/unocrsrhelper.hxx b/sw/inc/unocrsrhelper.hxx index 7624c59afaf3..58cca5fc0618 100644 --- a/sw/inc/unocrsrhelper.hxx +++ b/sw/inc/unocrsrhelper.hxx @@ -36,6 +36,7 @@ class SwUnoTableCursor; class SwFormatColl; struct SwSortOptions; class SwDoc; +class SwRootFrame; namespace sw { namespace mark { class IMark; } } @@ -135,7 +136,7 @@ namespace SwUnoCursorHelper void GetCursorAttr(SwPaM & rPam, SfxItemSet & rSet, const bool bOnlyTextAttr = false, const bool bGetFromChrFormat = true); - void GetTextFromPam(SwPaM & rPam, OUString & rBuffer); + void GetTextFromPam(SwPaM & rPam, OUString & rBuffer, SwRootFrame const* pLayout = nullptr); SwFormatColl * GetCurTextFormatColl(SwPaM & rPam, const bool bConditional); void SelectPam(SwPaM & rPam, const bool bExpand); diff --git a/sw/source/core/unocore/unoobj.cxx b/sw/source/core/unocore/unoobj.cxx index d16972e71e3c..da69af11eaf9 100644 --- a/sw/source/core/unocore/unoobj.cxx +++ b/sw/source/core/unocore/unoobj.cxx @@ -160,7 +160,8 @@ void SwUnoCursorHelper::SelectPam(SwPaM & rPam, const bool bExpand) } } -void SwUnoCursorHelper::GetTextFromPam(SwPaM & rPam, OUString & rBuffer) +void SwUnoCursorHelper::GetTextFromPam(SwPaM & rPam, OUString & rBuffer, + SwRootFrame const*const pLayout) { if (!rPam.HasMark()) { @@ -188,6 +189,7 @@ void SwUnoCursorHelper::GetTextFromPam(SwPaM & rPam, OUString & rBuffer) // #i68522# const bool bOldShowProgress = xWrt->m_bShowProgress; xWrt->m_bShowProgress = false; + xWrt->m_bHideDeleteRedlines = pLayout && pLayout->IsHideRedlines(); if( ! aWriter.Write( xWrt ).IsError() ) { diff --git a/sw/source/uibase/uno/unotxvw.cxx b/sw/source/uibase/uno/unotxvw.cxx index 1348a5fde2bf..96f2a6de666b 100644 --- a/sw/source/uibase/uno/unotxvw.cxx +++ b/sw/source/uibase/uno/unotxvw.cxx @@ -1381,7 +1381,8 @@ OUString SwXTextViewCursor::getString() { SwWrtShell& rSh = m_pView->GetWrtShell(); SwPaM* pShellCursor = rSh.GetCursor(); - SwUnoCursorHelper::GetTextFromPam(*pShellCursor, uRet); + SwUnoCursorHelper::GetTextFromPam(*pShellCursor, uRet, + rSh.GetLayout()); break; } default:;//prevent warning commit e0dcbf643ca6ba60435fbe3acb715316b5bec77e Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Tue Oct 9 16:32:33 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Mon Oct 15 15:25:46 2018 +0200 sw_redlinehide_3: trivial conversions in new code in fntcache.cxx Change-Id: Id625ee27e69800780c04ea80d888f606cde0f308 diff --git a/sw/source/core/txtnode/fntcache.cxx b/sw/source/core/txtnode/fntcache.cxx index dd377d0c1090..5288649caaa2 100644 --- a/sw/source/core/txtnode/fntcache.cxx +++ b/sw/source/core/txtnode/fntcache.cxx @@ -1450,7 +1450,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) // get screen array std::unique_ptr<long[]> pScrArray(new long[sal_Int32(rInf.GetLen())]); - SwTextGlyphsKey aGlyphsKey{ &rInf.GetOut(), rInf.GetText(), rInf.GetIdx(), rInf.GetLen() }; + SwTextGlyphsKey aGlyphsKey{ &rInf.GetOut(), rInf.GetText(), sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()) }; SalLayoutGlyphs* pGlyphs = lcl_CreateLayout(aGlyphsKey, m_aTextGlyphs[aGlyphsKey]); rInf.GetOut().GetTextArray( rInf.GetText(), pScrArray.get(), sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), nullptr, pGlyphs); @@ -1465,7 +1465,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) if( !m_pPrtFont->IsSameInstance( m_pPrinter->GetFont() ) ) m_pPrinter->SetFont( *m_pPrtFont ); } - aGlyphsKey = SwTextGlyphsKey{ m_pPrinter, rInf.GetText(), rInf.GetIdx(), rInf.GetLen() }; + aGlyphsKey = SwTextGlyphsKey{ m_pPrinter, rInf.GetText(), sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()) }; pGlyphs = lcl_CreateLayout(aGlyphsKey, m_aTextGlyphs[aGlyphsKey]); m_pPrinter->GetTextArray(rInf.GetText(), pKernArray.get(), sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), nullptr, pGlyphs); @@ -2039,7 +2039,7 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf ) } else { - SwTextGlyphsKey aGlyphsKey{ &rInf.GetOut(), rInf.GetText(), rInf.GetIdx(), nLn }; + SwTextGlyphsKey aGlyphsKey{ &rInf.GetOut(), rInf.GetText(), sal_Int32(rInf.GetIdx()), sal_Int32(nLn) }; SalLayoutGlyphs* pGlyphs = lcl_CreateLayout(aGlyphsKey, m_aTextGlyphs[aGlyphsKey]); aTextSize.setWidth( rInf.GetOut().GetTextWidth( rInf.GetText(), sal_Int32(rInf.GetIdx()), sal_Int32(nLn), @@ -2076,7 +2076,7 @@ TextFrameIndex SwFntObj::GetCursorOfst(SwDrawTextInfo &rInf) { m_pPrinter->SetLayoutMode( rInf.GetOut().GetLayoutMode() ); m_pPrinter->SetDigitLanguage( rInf.GetOut().GetDigitLanguage() ); - SwTextGlyphsKey aGlyphsKey{ m_pPrinter, rInf.GetText(), rInf.GetIdx(), rInf.GetLen() }; + SwTextGlyphsKey aGlyphsKey{ m_pPrinter, rInf.GetText(), sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()) }; SalLayoutGlyphs* pGlyphs = lcl_CreateLayout(aGlyphsKey, m_aTextGlyphs[aGlyphsKey]); m_pPrinter->GetTextArray( rInf.GetText(), pKernArray.get(), sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), nullptr, pGlyphs); @@ -2491,7 +2491,7 @@ TextFrameIndex SwFont::GetTextBreak(SwDrawTextInfo const & rInf, long nTextWidth { SwFntAccess aFntAccess(m_aSub[m_nActual].m_nFontCacheId, m_aSub[m_nActual].m_nFontIndex, &m_aSub[m_nActual], rInf.GetShell()); - SwTextGlyphsKey aGlyphsKey{ &rInf.GetOut(), *pTmpText, nTmpIdx, nTmpLen }; + SwTextGlyphsKey aGlyphsKey{ &rInf.GetOut(), *pTmpText, sal_Int32(nTmpIdx), sal_Int32(nTmpLen) }; SalLayoutGlyphs* pGlyphs = lcl_CreateLayout(aGlyphsKey, aFntAccess.Get()->GetTextGlyphs()[aGlyphsKey]); nTextBreak = TextFrameIndex(rInf.GetOut().GetTextBreak( commit 0e95bf055098103b771ba5360bf0a87c586f8ed9 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Tue Oct 9 16:32:02 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Mon Oct 15 15:25:46 2018 +0200 sw_redlinehide_3: trivial conversions in new code in xmldump.cxx Change-Id: I37624c92549b4b3cd4d9616a4952163bf51526ef diff --git a/sw/source/core/text/xmldump.cxx b/sw/source/core/text/xmldump.cxx index 6dc0eb71971d..90d73c75dab5 100644 --- a/sw/source/core/text/xmldump.cxx +++ b/sw/source/core/text/xmldump.cxx @@ -133,12 +133,12 @@ class XmlPortionDumper:public SwPortionHandler xmlTextWriterWriteFormatAttribute(writer, BAD_CAST("nHeight"), "%i", static_cast<int>(nHeight)); if (nWidth > 0) xmlTextWriterWriteFormatAttribute(writer, BAD_CAST("nWidth"), "%i", static_cast<int>(nWidth)); - if (nLength > 0) + if (nLength > TextFrameIndex(0)) xmlTextWriterWriteAttribute(writer, BAD_CAST("Portion"), - BAD_CAST(m_rText.copy(ofs, nLength).toUtf8().getStr())); + BAD_CAST(m_rText.copy(sal_Int32(ofs), sal_Int32(nLength)).toUtf8().getStr())); xmlTextWriterEndElement( writer ); - m_aLine += m_rText.copy(ofs, nLength); + m_aLine += m_rText.copy(sal_Int32(ofs), sal_Int32(nLength)); ofs += nLength; } commit 4fadb914260034951d6d25304c52d5c31051a84e Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Tue Oct 9 16:17:03 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Mon Oct 15 15:25:46 2018 +0200 sw_redlinehide_3: bug in UpdateMergedParaForMove lcl_SetWrong works on model positions. Change-Id: I34353a09260e336c15696a7bc48a5922bfd92e4a diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx index af0422aa09ea..5603d7800914 100644 --- a/sw/source/core/text/txtfrm.cxx +++ b/sw/source/core/text/txtfrm.cxx @@ -1724,7 +1724,7 @@ void UpdateMergedParaForMove(sw::MergedPara & rMerged, if(nDeleted) { // InvalidateRange/lcl_SetScriptInval was called sufficiently for SwInsText - lcl_SetWrong(rTextFrame, rDestNode, nStart, -nDeleted, false); + lcl_SetWrong(rTextFrame, rDestNode, nStart, it.first - it.second, false); if (rTextFrame.HasFollow()) { TextFrameIndex const nIndex(sw::MapModelToView(rMerged, &rDestNode, nStart)); commit 4aae7fe8c047dcd49519c33a673f417270e42ef7 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Tue Oct 9 14:49:23 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Mon Oct 15 15:25:46 2018 +0200 sw_redlinehide_3: convert even more SwAccessibleParagraph functions ... and finally remove GetTextNode(). Change-Id: I7ad91bf709b705afcf7ada79fd2a97335329e8b7 diff --git a/sw/source/core/access/accpara.cxx b/sw/source/core/access/accpara.cxx index 1986a0ee8bd6..f323317d96cf 100644 --- a/sw/source/core/access/accpara.cxx +++ b/sw/source/core/access/accpara.cxx @@ -118,17 +118,6 @@ namespace com { namespace sun { namespace star { const sal_Char sServiceName[] = "com.sun.star.text.AccessibleParagraphView"; const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleParagraphView"; -const SwTextNode* SwAccessibleParagraph::GetTextNode() const -{ - const SwFrame* pFrame = GetFrame(); - OSL_ENSURE( pFrame->IsTextFrame(), "The text frame has mutated!" ); - - const SwTextNode* pNode = static_cast<const SwTextFrame*>(pFrame)->GetTextNode(); - OSL_ENSURE( pNode != nullptr, "A text frame without a text node." ); - - return pNode; -} - OUString const & SwAccessibleParagraph::GetString() { return GetPortionData().GetAccessibleString(); @@ -223,7 +212,8 @@ SwPaM* SwAccessibleParagraph::GetCursor( const bool _bForSelection ) bool SwAccessibleParagraph::IsHeading() const { - const SwTextNode *pTextNd = GetTextNode(); + SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame())); + const SwTextNode *pTextNd = pFrame->GetTextNodeForParaProps(); return pTextNd->IsOutline(); } @@ -246,9 +236,10 @@ void SwAccessibleParagraph::GetStates( // FOCUSED (simulates node index of cursor) SwPaM* pCaret = GetCursor( false ); // #i27301# - consider adjusted method signature - const SwTextNode* pTextNd = GetTextNode(); - if( pCaret != nullptr && pTextNd != nullptr && - pTextNd->GetIndex() == pCaret->GetPoint()->nNode.GetIndex() && + SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame())); + assert(pFrame); + if (pCaret != nullptr && + sw::FrameContainsNode(*pFrame, pCaret->GetPoint()->nNode.GetIndex()) && m_nOldCaretPos != -1) { vcl::Window *pWin = GetWindow(); @@ -544,7 +535,9 @@ bool SwAccessibleParagraph::IsValidRange( SwTOXSortTabBase* SwAccessibleParagraph::GetTOXSortTabBase() { - const SwTextNode* pTextNd = GetTextNode(); + SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame())); + assert(pFrame); + const SwTextNode *const pTextNd = pFrame->GetTextNodeFirst(); if( pTextNd ) { const SwSectionNode * pSectNd = pTextNd->FindSectionNode(); @@ -582,15 +575,7 @@ const SwRangeRedline* SwAccessibleParagraph::GetRedlineAtIndex() if ( pCrSr ) { SwPosition* pStart = pCrSr->Start(); - const SwTextNode* pNode = GetTextNode(); - if ( pNode ) - { - const SwDoc* pDoc = pNode->GetDoc(); - if ( pDoc ) - { - pRedline = pDoc->getIDocumentRedlineAccess().GetRedline( *pStart, nullptr ); - } - } + pRedline = pStart->GetDoc()->getIDocumentRedlineAccess().GetRedline(*pStart, nullptr); } return pRedline; @@ -1253,13 +1238,11 @@ OUString SwAccessibleParagraph::GetFieldTypeNameAtIndex(sal_Int32 nIndex) sal_Int32 nFieldIndex = GetPortionData().GetFieldIndex(nIndex); if (nFieldIndex >= 0) { - const SwpHints* pSwpHints = GetTextNode()->GetpSwpHints(); - if (pSwpHints) + SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame())); + sw::MergedAttrIter iter(*pFrame); + while (SwTextAttr const*const pHt = iter.NextAttr()) { - const size_t nSize = pSwpHints->Count(); - for( size_t i = 0; i < nSize; ++i ) { - const SwTextAttr* pHt = pSwpHints->Get(i); if ( ( pHt->Which() == RES_TXTATR_FIELD || pHt->Which() == RES_TXTATR_ANNOTATION || pHt->Which() == RES_TXTATR_INPUTFIELD ) @@ -1539,7 +1522,8 @@ void SwAccessibleParagraph::_getDefaultAttributesImpl( const bool bOnlyCharAttrs ) { // retrieve default attributes - const SwTextNode* pTextNode( GetTextNode() ); + SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame())); + const SwTextNode *const pTextNode(pFrame->GetTextNodeForParaProps()); std::unique_ptr<SfxItemSet> pSet; if ( !bOnlyCharAttrs ) { @@ -1876,7 +1860,8 @@ void SwAccessibleParagraph::_getSupplementalAttributesImpl( const uno::Sequence< OUString >& aRequestedAttributes, tAccParaPropValMap& rSupplementalAttrSeq ) { - const SwTextNode* pTextNode( GetTextNode() ); + SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame())); + const SwTextNode *const pTextNode(pFrame->GetTextNodeForParaProps()); std::unique_ptr<SfxItemSet> pSet; pSet.reset( new SfxItemSet( @@ -3062,13 +3047,22 @@ sal_Int32 SAL_CALL SwAccessibleParagraph::getSelectedPortionCount( ) { SolarMutexGuard g; - sal_Int32 nSeleted = 0; + sal_Int32 nSelected = 0; SwPaM* pCursor = GetCursor( true ); if( pCursor != nullptr ) { // get SwPosition for my node - const SwTextNode* pNode = GetTextNode(); - sal_uLong nHere = pNode->GetIndex(); + SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame())); + sal_uLong nFirstNode(pFrame->GetTextNodeFirst()->GetIndex()); + sal_uLong nLastNode; + if (sw::MergedPara const*const pMerged = pFrame->GetMergedPara()) + { + nLastNode = pMerged->pLastNode->GetIndex(); + } + else + { + nLastNode = nFirstNode; + } // iterate over ring for(SwPaM& rTmpCursor : pCursor->GetRingContainer()) @@ -3076,22 +3070,21 @@ sal_Int32 SAL_CALL SwAccessibleParagraph::getSelectedPortionCount( ) // ignore, if no mark if( rTmpCursor.HasMark() ) { - // check whether nHere is 'inside' pCursor + // check whether frame's node(s) are 'inside' pCursor SwPosition* pStart = rTmpCursor.Start(); sal_uLong nStartIndex = pStart->nNode.GetIndex(); SwPosition* pEnd = rTmpCursor.End(); sal_uLong nEndIndex = pEnd->nNode.GetIndex(); - if( ( nHere >= nStartIndex ) && - ( nHere <= nEndIndex ) ) + if ((nStartIndex <= nLastNode) && (nFirstNode <= nEndIndex)) { - nSeleted++; + nSelected++; } // else: this PaM doesn't point to this paragraph } // else: this PaM is collapsed and doesn't select anything } } - return nSeleted; + return nSelected; } @@ -3133,8 +3126,17 @@ sal_Bool SAL_CALL SwAccessibleParagraph::removeSelection( sal_Int32 selectionInd bool bRet = false; // get SwPosition for my node - const SwTextNode* pNode = GetTextNode(); - sal_uLong nHere = pNode->GetIndex(); + SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame())); + sal_uLong nFirstNode(pFrame->GetTextNodeFirst()->GetIndex()); + sal_uLong nLastNode; + if (sw::MergedPara const*const pMerged = pFrame->GetMergedPara()) + { + nLastNode = pMerged->pLastNode->GetIndex(); + } + else + { + nLastNode = nFirstNode; + } // iterate over ring SwPaM* pRingStart = pCursor; @@ -3143,13 +3145,12 @@ sal_Bool SAL_CALL SwAccessibleParagraph::removeSelection( sal_Int32 selectionInd // ignore, if no mark if( pCursor->HasMark() ) { - // check whether nHere is 'inside' pCursor + // check whether frame's node(s) are 'inside' pCursor SwPosition* pStart = pCursor->Start(); sal_uLong nStartIndex = pStart->nNode.GetIndex(); SwPosition* pEnd = pCursor->End(); sal_uLong nEndIndex = pEnd->nNode.GetIndex(); - if( ( nHere >= nStartIndex ) && - ( nHere <= nEndIndex ) ) + if ((nStartIndex <= nLastNode) && (nFirstNode <= nEndIndex)) { if( nSelected == 0 ) { diff --git a/sw/source/core/access/accpara.hxx b/sw/source/core/access/accpara.hxx index 676e99a9023b..26afc0df73eb 100644 --- a/sw/source/core/access/accpara.hxx +++ b/sw/source/core/access/accpara.hxx @@ -88,9 +88,6 @@ class SwAccessibleParagraph : std::unique_ptr<SwParaChangeTrackingInfo> mpParaChangeTrackInfo; // #i108125# - /// get the SwTextNode (requires frame; check before) - const SwTextNode* GetTextNode() const; - /// get the (accessible) text string (requires frame; check before) OUString const & GetString(); commit a71f0dddb17ac048fe4c51c77b2a82b0f6137f9d Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Tue Oct 9 15:53:17 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Mon Oct 15 15:25:46 2018 +0200 sw_redlinehide_3: convert SwAccessibleParagraph::_correctValues() Tricky usage of SwWrongList here, let's hope this works... Also, there is a similar bug here, the nIndex is in a11y coordinates but it was used directly as input to SwWrongList; better to convert first. Change-Id: I9b49b4dc84089c03df0e1302512d13d289d16161 diff --git a/sw/source/core/access/accpara.cxx b/sw/source/core/access/accpara.cxx index b3038c21875a..1986a0ee8bd6 100644 --- a/sw/source/core/access/accpara.cxx +++ b/sw/source/core/access/accpara.cxx @@ -2000,7 +2000,20 @@ void SwAccessibleParagraph::_correctValues( const sal_Int32 nIndex, } } - const SwTextNode* pTextNode( GetTextNode() ); + // sw_redlinehide: this function only needs SwWrongList for 1 character, + // and the end is excluded by InWrongWord(), + // so it ought to work to just pick the wrong-list/node that contains + // the character following the given nIndex + SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame())); + TextFrameIndex const nCorePos(GetPortionData().GetCoreViewPosition(nIndex)); + std::pair<SwTextNode*, sal_Int32> pos(pFrame->MapViewToModel(nCorePos)); + if (pos.first->Len() == pos.second + && nCorePos != TextFrameIndex(pFrame->GetText().getLength())) + { + pos = pFrame->MapViewToModel(nCorePos + TextFrameIndex(1)); // try this one instead + assert(pos.first->Len() != pos.second); + } + const SwTextNode *const pTextNode(pos.first); sal_Int32 nValues = rValues.size(); for (sal_Int32 i = 0; i < nValues; ++i) @@ -2067,7 +2080,7 @@ void SwAccessibleParagraph::_correctValues( const sal_Int32 nIndex, const SwWrongList* pWrongList = pTextNode->GetWrong(); if( nullptr != pWrongList ) { - sal_Int32 nBegin = nIndex; + sal_Int32 nBegin = pos.second; sal_Int32 nLen = 1; if (pWrongList->InWrongWord(nBegin, nLen) && !pTextNode->IsSymbolAt(nBegin)) { @@ -2088,7 +2101,7 @@ void SwAccessibleParagraph::_correctValues( const sal_Int32 nIndex, const SwWrongList* pWrongList = pTextNode->GetWrong(); if( nullptr != pWrongList ) { - sal_Int32 nBegin = nIndex; + sal_Int32 nBegin = pos.second; sal_Int32 nLen = 1; if (pWrongList->InWrongWord(nBegin, nLen) && !pTextNode->IsSymbolAt(nBegin)) { commit 6ae737fb16bac7a8cc3260077d48d0c05c486225 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Tue Oct 9 13:59:24 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Mon Oct 15 15:25:46 2018 +0200 sw_redlinehide_3: convert SwAccessibleParagraph::_getRunAttributesImpl There appears to be a bug here, in that the nIndex is an index into the accessiblity string, but it was used without conversion as a model position in SwPosition; let's try to fix that. Change-Id: I7a43ceacfe59102577f39ab4b8fec3b495db345d diff --git a/sw/source/core/access/accpara.cxx b/sw/source/core/access/accpara.cxx index caf95ac3a32c..b3038c21875a 100644 --- a/sw/source/core/access/accpara.cxx +++ b/sw/source/core/access/accpara.cxx @@ -1751,14 +1751,16 @@ void SwAccessibleParagraph::_getRunAttributesImpl( { // create PaM for character at position <nIndex> std::unique_ptr<SwPaM> pPaM; + const TextFrameIndex nCorePos(GetPortionData().GetCoreViewPosition(nIndex)); + SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame())); + SwPosition const aModelPos(pFrame->MapViewToModelPos(nCorePos)); + SwTextNode *const pTextNode(aModelPos.nNode.GetNode().GetTextNode()); { - const SwTextNode* pTextNode( GetTextNode() ); - std::unique_ptr<SwPosition> pStartPos( new SwPosition( *pTextNode ) ); - pStartPos->nContent.Assign( const_cast<SwTextNode*>(pTextNode), nIndex ); - std::unique_ptr<SwPosition> pEndPos( new SwPosition( *pTextNode ) ); - pEndPos->nContent.Assign( const_cast<SwTextNode*>(pTextNode), nIndex+1 ); - - pPaM.reset(new SwPaM( *pStartPos, *pEndPos )); + SwPosition const aEndPos(*pTextNode, + aModelPos.nContent.GetIndex() == pTextNode->Len() + ? pTextNode->Len() // ??? + : aModelPos.nContent.GetIndex() + 1); + pPaM.reset(new SwPaM(aModelPos, aEndPos)); } // retrieve character attributes for the created PaM <pPaM> @@ -1771,7 +1773,6 @@ void SwAccessibleParagraph::_getRunAttributesImpl( // SwXTextCursor::GetCursorAttr( *pPaM, aSet, sal_True, sal_True ); // get character attributes from automatic paragraph style and merge these into <aSet> { - const SwTextNode* pTextNode( GetTextNode() ); if ( pTextNode->HasSwAttrSet() ) { SfxItemSet aAutomaticParaStyleCharAttrs( pPaM->GetDoc()->GetAttrPool(), commit 8b4d1b202c89461f7fb947c007a0b072852fec68 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Tue Oct 9 12:59:01 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Mon Oct 15 15:25:46 2018 +0200 sw_redlinehide_3: convert more SwAccessibleParagraph functions Change-Id: I33079154b4775b1df55693bf6046adbf27b0c1e3 diff --git a/sw/source/core/access/accpara.cxx b/sw/source/core/access/accpara.cxx index f092d6267d8b..caf95ac3a32c 100644 --- a/sw/source/core/access/accpara.cxx +++ b/sw/source/core/access/accpara.cxx @@ -149,20 +149,21 @@ sal_Int32 SwAccessibleParagraph::GetCaretPos() if( pCaret != nullptr ) { - const SwTextNode* pNode = GetTextNode(); + SwTextFrame const*const pTextFrame(static_cast<SwTextFrame const*>(GetFrame())); + assert(pTextFrame); // check whether the point points into 'our' node SwPosition* pPoint = pCaret->GetPoint(); - if( pNode->GetIndex() == pPoint->nNode.GetIndex() ) + if (sw::FrameContainsNode(*pTextFrame, pPoint->nNode.GetIndex())) { // same node? Then check whether it's also within 'our' part // of the paragraph - const sal_Int32 nIndex = pPoint->nContent.GetIndex(); + const TextFrameIndex nIndex = pTextFrame->MapModelToViewPos(*pPoint); if(!GetPortionData().IsValidCorePosition( nIndex ) || - ( GetPortionData().IsZeroCorePositionData() && nIndex== 0) ) + (GetPortionData().IsZeroCorePositionData() + && nIndex == TextFrameIndex(0))) { - const SwTextFrame *pTextFrame = dynamic_cast<const SwTextFrame*>( GetFrame() ); - bool bFormat = (pTextFrame && pTextFrame->HasPara()); + bool bFormat = pTextFrame->HasPara(); if(bFormat) { ClearPortionData(); @@ -501,17 +502,17 @@ SwXTextPortion* SwAccessibleParagraph::CreateUnoPortion( IsValidRange(nStartIndex, nEndIndex, GetString().getLength()), "please check parameters before calling this method" ); - const sal_Int32 nStart = GetPortionData().GetCoreViewPosition(nStartIndex); - const sal_Int32 nEnd = (nEndIndex == -1) ? (nStart + 1) : - GetPortionData().GetCoreViewPosition(nEndIndex); + const TextFrameIndex nStart = GetPortionData().GetCoreViewPosition(nStartIndex); + const TextFrameIndex nEnd = (nEndIndex == -1) + ? (nStart + TextFrameIndex(1)) + : GetPortionData().GetCoreViewPosition(nEndIndex); // create UNO cursor - SwTextNode* pTextNode = const_cast<SwTextNode*>( GetTextNode() ); - SwIndex aIndex( pTextNode, nStart ); - SwPosition aStartPos( *pTextNode, aIndex ); - auto pUnoCursor(pTextNode->GetDoc()->CreateUnoCursor( aStartPos )); + SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame())); + SwPosition aStartPos(pFrame->MapViewToModelPos(nStart)); + auto pUnoCursor(const_cast<SwDoc&>(pFrame->GetDoc()).CreateUnoCursor(aStartPos)); pUnoCursor->SetMark(); - pUnoCursor->GetMark()->nContent = nEnd; + *pUnoCursor->GetMark() = pFrame->MapViewToModelPos(nEnd); // create a (dummy) text portion to be returned uno::Reference<text::XText> aEmpty; @@ -618,9 +619,9 @@ bool SwAccessibleParagraph::GetWordBoundary( assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is()); // get locale for this position - const sal_Int32 nModelPos = GetPortionData().GetCoreViewPosition(nPos); - lang::Locale aLocale = g_pBreakIt->GetLocale( - GetTextNode()->GetLang( nModelPos ) ); + SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame())); + const TextFrameIndex nCorePos = GetPortionData().GetCoreViewPosition(nPos); + lang::Locale aLocale = g_pBreakIt->GetLocale(pFrame->GetLangOfChar(nCorePos, 0, true)); // which type of word are we interested in? // (DICTIONARY_WORD includes punctuation, ANY_WORD doesn't.) @@ -685,9 +686,9 @@ bool SwAccessibleParagraph::GetGlyphBoundary( assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is()); // get locale for this position - const sal_Int32 nModelPos = GetPortionData().GetCoreViewPosition(nPos); - lang::Locale aLocale = g_pBreakIt->GetLocale( - GetTextNode()->GetLang( nModelPos ) ); + SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame())); + const TextFrameIndex nCorePos = GetPortionData().GetCoreViewPosition(nPos); + lang::Locale aLocale = g_pBreakIt->GetLocale(pFrame->GetLangOfChar(nCorePos, 0, true)); // get word boundary, as the Break-Iterator sees fit. const sal_Int16 nIterMode = i18n::CharacterIteratorMode::SKIPCELL; @@ -781,8 +782,7 @@ lang::Locale SAL_CALL SwAccessibleParagraph::getLocale() throw uno::RuntimeException("no SwTextFrame", static_cast<cppu::OWeakObject*>(this)); } - const SwTextNode *pTextNd = pTextFrame->GetTextNode(); - lang::Locale aLoc( g_pBreakIt->GetLocale( pTextNd->GetLang( 0 ) ) ); + lang::Locale aLoc(g_pBreakIt->GetLocale(pTextFrame->GetLangOfChar(TextFrameIndex(0), 0, true))); return aLoc; } @@ -833,11 +833,10 @@ void SAL_CALL SwAccessibleParagraph::grabFocus() SwCursorShell *pCursorSh = GetCursorShell(); SwPaM *pCursor = GetCursor( false ); // #i27301# - consider new method signature const SwTextFrame *pTextFrame = static_cast<const SwTextFrame*>( GetFrame() ); - const SwTextNode* pTextNd = pTextFrame->GetTextNode(); - if( pCursorSh != nullptr && pTextNd != nullptr && + if (pCursorSh != nullptr && ( pCursor == nullptr || - pCursor->GetPoint()->nNode.GetIndex() != pTextNd->GetIndex() || + !sw::FrameContainsNode(*pTextFrame, pCursor->GetPoint()->nNode.GetIndex()) || !pTextFrame->IsInside(pTextFrame->MapModelToViewPos(*pCursor->GetPoint())))) { // create pam for selection @@ -1139,9 +1138,9 @@ sal_Bool SAL_CALL SwAccessibleParagraph::setCaretPosition( sal_Int32 nIndex ) if( pCursorShell != nullptr ) { // create pam for selection - SwTextNode* pNode = const_cast<SwTextNode*>( GetTextNode() ); - SwIndex aIndex(pNode, GetPortionData().GetCoreViewPosition(nIndex)); - SwPosition aStartPos( *pNode, aIndex ); + SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame())); + TextFrameIndex const nFrameIndex(GetPortionData().GetCoreViewPosition(nIndex)); + SwPosition aStartPos(pFrame->MapViewToModelPos(nFrameIndex)); SwPaM aPaM( aStartPos ); // set PaM at cursor shell @@ -1188,26 +1187,25 @@ css::uno::Sequence< css::style::TabStop > SwAccessibleParagraph::GetCurrentTabSt aMoveState.m_bRealHeight = true; aMoveState.m_bRealWidth = true; SwSpecialPos aSpecialPos; - SwTextNode* pNode = const_cast<SwTextNode*>( GetTextNode() ); + SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame())); /* #i12332# FillSpecialPos does not accept nIndex == GetString().getLength(). In that case nPos is set to the length of the string in the core. This way GetCharRect returns the rectangle for a cursor at the end of the paragraph. */ - const sal_Int32 nPos = bBehindText - ? pNode->GetText().getLength() + const TextFrameIndex nPos = bBehindText + ? TextFrameIndex(pFrame->GetText().getLength()) : GetPortionData().FillSpecialPos(nIndex, aSpecialPos, aMoveState.m_pSpecialPos ); // call GetCharRect SwRect aCoreRect; - SwIndex aIndex( pNode, nPos ); - SwPosition aPosition( *pNode, aIndex ); + SwPosition aPosition(pFrame->MapViewToModelPos(nPos)); GetFrame()->GetCharRect( aCoreRect, aPosition, &aMoveState ); // already get the caret position css::uno::Sequence< css::style::TabStop > tabs; - const sal_Int32 nStrLen = GetTextNode()->GetText().getLength(); + const sal_Int32 nStrLen = pFrame->GetText().getLength(); if( nStrLen > 0 ) { SwFrame* pTFrame = const_cast<SwFrame*>(GetFrame()); @@ -2172,21 +2170,20 @@ awt::Rectangle SwAccessibleParagraph::getCharacterBounds( aMoveState.m_bRealHeight = true; aMoveState.m_bRealWidth = true; SwSpecialPos aSpecialPos; - SwTextNode* pNode = const_cast<SwTextNode*>( GetTextNode() ); + SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame())); /** #i12332# FillSpecialPos does not accept nIndex == GetString().getLength(). In that case nPos is set to the length of the string in the core. This way GetCharRect returns the rectangle for a cursor at the end of the paragraph. */ - const sal_Int32 nPos = bBehindText - ? pNode->GetText().getLength() + const TextFrameIndex nPos = bBehindText + ? TextFrameIndex(pFrame->GetText().getLength()) : GetPortionData().FillSpecialPos(nIndex, aSpecialPos, aMoveState.m_pSpecialPos ); // call GetCharRect SwRect aCoreRect; - SwIndex aIndex( pNode, nPos ); - SwPosition aPosition( *pNode, aIndex ); + SwPosition aPosition(pFrame->MapViewToModelPos(nPos)); GetFrame()->GetCharRect( aCoreRect, aPosition, &aMoveState ); // translate core coordinates into accessibility coordinates @@ -2223,11 +2220,6 @@ sal_Int32 SwAccessibleParagraph::getIndexAtPoint( const awt::Point& rPoint ) ThrowIfDisposed(); - // construct SwPosition (where GetCursorOfst() will put the result into) - SwTextNode* pNode = const_cast<SwTextNode*>( GetTextNode() ); - SwIndex aIndex( pNode, 0); - SwPosition aPos( *pNode, aIndex ); - // construct Point (translate into layout coordinates) vcl::Window *pWin = GetWindow(); if (!pWin) @@ -2262,14 +2254,17 @@ sal_Int32 SwAccessibleParagraph::getIndexAtPoint( const awt::Point& rPoint ) OSL_ENSURE( GetFrame() != nullptr, "The text frame has vanished!" ); OSL_ENSURE( GetFrame()->IsTextFrame(), "The text frame has mutated!" ); const SwTextFrame* pFrame = static_cast<const SwTextFrame*>( GetFrame() ); + // construct SwPosition (where GetCursorOfst() will put the result into) + SwTextNode* pNode = const_cast<SwTextNode*>(pFrame->GetTextNodeFirst()); + SwPosition aPos(*pNode, 0); SwCursorMoveState aMoveState; aMoveState.m_bPosMatchesBounds = true; const bool bSuccess = pFrame->GetCursorOfst( &aPos, aCorePoint, &aMoveState ); - SwIndex aContentIdx = aPos.nContent; - const sal_Int32 nIndex = aContentIdx.GetIndex(); - if ( nIndex > 0 ) + TextFrameIndex nIndex = pFrame->MapModelToViewPos(aPos); + if (TextFrameIndex(0) < nIndex) { + assert(bSuccess); SwRect aResultRect; pFrame->GetCharRect( aResultRect, aPos ); bool bVert = pFrame->IsVertical(); @@ -2279,19 +2274,20 @@ sal_Int32 SwAccessibleParagraph::getIndexAtPoint( const awt::Point& rPoint ) ( bVert && aResultRect.Pos().getY() > aCorePoint.getY()) || ( bR2L && aResultRect.Right() < aCorePoint.getX()) ) { - SwIndex aIdxPrev( pNode, nIndex - 1); - SwPosition aPosPrev( *pNode, aIdxPrev ); + SwPosition aPosPrev(pFrame->MapViewToModelPos(nIndex - TextFrameIndex(1))); SwRect aResultRectPrev; pFrame->GetCharRect( aResultRectPrev, aPosPrev ); if ( (!bVert && aResultRectPrev.Pos().getX() < aCorePoint.getX() && aResultRect.Pos().getY() == aResultRectPrev.Pos().getY()) || ( bVert && aResultRectPrev.Pos().getY() < aCorePoint.getY() && aResultRect.Pos().getX() == aResultRectPrev.Pos().getX()) || ( bR2L && aResultRectPrev.Right() > aCorePoint.getX() && aResultRect.Pos().getY() == aResultRectPrev.Pos().getY()) ) - aPos = aPosPrev; + { + --nIndex; + } } } - return bSuccess ? - GetPortionData().GetAccessiblePosition( aPos.nContent.GetIndex() ) + return bSuccess + ? GetPortionData().GetAccessiblePosition(nIndex) : -1; } @@ -2663,29 +2659,26 @@ sal_Bool SwAccessibleParagraph::replaceText( if( !IsEditableState() ) return false; - SwTextNode* pNode = const_cast<SwTextNode*>( GetTextNode() ); - // translate positions - sal_Int32 nStart; - sal_Int32 nEnd; + TextFrameIndex nStart; + TextFrameIndex nEnd; bool bSuccess = GetPortionData().GetEditableRange( nStartIndex, nEndIndex, nStart, nEnd ); // edit only if the range is editable if( bSuccess ) { + SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame())); // create SwPosition for nStartIndex - SwIndex aIndex( pNode, nStart ); - SwPosition aStartPos( *pNode, aIndex ); + SwPosition aStartPos(pFrame->MapViewToModelPos(nStart)); // create SwPosition for nEndIndex - SwPosition aEndPos( aStartPos ); - aEndPos.nContent = nEnd; + SwPosition aEndPos(pFrame->MapViewToModelPos(nEnd)); // now create XTextRange as helper and set string const uno::Reference<text::XTextRange> xRange( SwXTextRange::CreateXTextRange( - *pNode->GetDoc(), aStartPos, &aEndPos)); + const_cast<SwDoc&>(pFrame->GetDoc()), aStartPos, &aEndPos)); xRange->setString(sReplacement); // delete portion data commit b33e984d49740bf7d8aee99ad832df8c29beab6e Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Tue Oct 9 11:14:05 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Mon Oct 15 15:25:46 2018 +0200 sw_redlinehide_3: convert SwTextMarkupHelper and related ... ... functions in SwAccessibleParagraph, with the new WrongListIterator. Change-Id: Ie401dd867a06a1963e49fa54afa978ad1f1346f5 diff --git a/sw/source/core/access/accpara.cxx b/sw/source/core/access/accpara.cxx index fea50d58ac98..f092d6267d8b 100644 --- a/sw/source/core/access/accpara.cxx +++ b/sw/source/core/access/accpara.cxx @@ -3037,7 +3037,8 @@ sal_Int32 SAL_CALL SwAccessibleParagraph::getTextMarkupCount( sal_Int32 nTextMar break; default: { - pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTextNode() ) ); + SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame())); + pTextMarkupHelper.reset(new SwTextMarkupHelper(GetPortionData(), *pFrame)); } } @@ -3247,7 +3248,8 @@ sal_Int32 SAL_CALL SwAccessibleParagraph::addSelection( sal_Int32, sal_Int32 sta break; default: { - pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTextNode() ) ); + SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame())); + pTextMarkupHelper.reset(new SwTextMarkupHelper(GetPortionData(), *pFrame)); } } @@ -3281,7 +3283,8 @@ uno::Sequence< /*accessibility::*/TextSegment > SAL_CALL break; default: { - pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTextNode() ) ); + SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame())); + pTextMarkupHelper.reset(new SwTextMarkupHelper(GetPortionData(), *pFrame)); } } diff --git a/sw/source/core/access/textmarkuphelper.cxx b/sw/source/core/access/textmarkuphelper.cxx index 2bbc8ab81984..8633789af140 100644 --- a/sw/source/core/access/textmarkuphelper.cxx +++ b/sw/source/core/access/textmarkuphelper.cxx @@ -36,27 +36,26 @@ using namespace com::sun::star; namespace { /// @throws css::lang::IllegalArgumentException /// @throws css::uno::RuntimeException - const SwWrongList* getTextMarkupList( const SwTextNode& rTextNode, - const sal_Int32 nTextMarkupType ) + SwWrongList const* (SwTextNode::* + getTextMarkupFunc(const sal_Int32 nTextMarkupType))() const { - const SwWrongList* pTextMarkupList( nullptr ); switch ( nTextMarkupType ) { case text::TextMarkupType::SPELLCHECK: { - pTextMarkupList = rTextNode.GetWrong(); + return &SwTextNode::GetWrong; } break; case text::TextMarkupType::PROOFREADING: { // support not implemented yet - pTextMarkupList = nullptr; + return nullptr; } break; case text::TextMarkupType::SMARTTAG: { // support not implemented yet - pTextMarkupList = nullptr; + return nullptr; } break; default: @@ -64,17 +63,14 @@ namespace { throw lang::IllegalArgumentException(); } } - - return pTextMarkupList; } } // implementation of class <SwTextMarkupoHelper> SwTextMarkupHelper::SwTextMarkupHelper( const SwAccessiblePortionData& rPortionData, - const SwTextNode& rTextNode ) + const SwTextFrame& rTextFrame) : mrPortionData( rPortionData ) - // #i108125# - , mpTextNode( &rTextNode ) + , m_pTextFrame(&rTextFrame) , mpTextMarkupList( nullptr ) { } @@ -83,7 +79,7 @@ SwTextMarkupHelper::SwTextMarkupHelper( const SwAccessiblePortionData& rPortionD SwTextMarkupHelper::SwTextMarkupHelper( const SwAccessiblePortionData& rPortionData, const SwWrongList& rTextMarkupList ) : mrPortionData( rPortionData ) - , mpTextNode( nullptr ) + , m_pTextFrame( nullptr ) , mpTextMarkupList( &rTextMarkupList ) { } @@ -92,14 +88,19 @@ sal_Int32 SwTextMarkupHelper::getTextMarkupCount( const sal_Int32 nTextMarkupTyp { sal_Int32 nTextMarkupCount( 0 ); - // #i108125# - const SwWrongList* pTextMarkupList = - mpTextMarkupList - ? mpTextMarkupList - : getTextMarkupList( *mpTextNode, nTextMarkupType ); - if ( pTextMarkupList ) + if (mpTextMarkupList) + { + nTextMarkupCount = mpTextMarkupList->Count(); + } + else { - nTextMarkupCount = pTextMarkupList->Count(); + assert(m_pTextFrame); + SwWrongList const* (SwTextNode::*const pGetWrongList)() const = getTextMarkupFunc(nTextMarkupType); + if (pGetWrongList) + { + sw::WrongListIteratorCounter iter(*m_pTextFrame, pGetWrongList); + nTextMarkupCount = iter.GetElementCount(); + } } return nTextMarkupCount; @@ -119,22 +120,31 @@ css::accessibility::TextSegment aTextMarkupSegment.SegmentStart = -1; aTextMarkupSegment.SegmentEnd = -1; - // #i108125# - const SwWrongList* pTextMarkupList = - mpTextMarkupList - ? mpTextMarkupList - : getTextMarkupList( *mpTextNode, nTextMarkupType ); - if ( pTextMarkupList ) + std::unique_ptr<sw::WrongListIteratorCounter> pIter; + if (mpTextMarkupList) + { + pIter.reset(new sw::WrongListIteratorCounter(*mpTextMarkupList)); + } + else + { + assert(m_pTextFrame); + SwWrongList const* (SwTextNode::*const pGetWrongList)() const = getTextMarkupFunc(nTextMarkupType); + if (pGetWrongList) + { + pIter.reset(new sw::WrongListIteratorCounter(*m_pTextFrame, pGetWrongList)); + } + } + + if (pIter) { - const SwWrongArea* pTextMarkup = - pTextMarkupList->GetElement( static_cast<sal_uInt16>(nTextMarkupIndex) ); - if ( pTextMarkup ) + auto const oElement(pIter->GetElementAt(nTextMarkupIndex)); + if (oElement) { - const OUString rText = mrPortionData.GetAccessibleString(); + const OUString& rText = mrPortionData.GetAccessibleString(); const sal_Int32 nStartPos = - mrPortionData.GetAccessiblePosition( pTextMarkup->mnPos ); + mrPortionData.GetAccessiblePosition(oElement->first); const sal_Int32 nEndPos = - mrPortionData.GetAccessiblePosition( pTextMarkup->mnPos + pTextMarkup->mnLen ); + mrPortionData.GetAccessiblePosition(oElement->second); aTextMarkupSegment.SegmentText = rText.copy( nStartPos, nEndPos - nStartPos ); aTextMarkupSegment.SegmentStart = nStartPos; aTextMarkupSegment.SegmentEnd = nEndPos; @@ -155,7 +165,7 @@ css::uno::Sequence< css::accessibility::TextSegment > // assumption: // value of <nCharIndex> is in range [0..length of accessible text) - const sal_Int32 nCoreCharIndex = mrPortionData.GetCoreViewPosition(nCharIndex); + const TextFrameIndex nCoreCharIndex = mrPortionData.GetCoreViewPosition(nCharIndex); // Handling of portions with core length == 0 at the beginning of the // paragraph - e.g. numbering portion. if ( mrPortionData.GetAccessiblePosition( nCoreCharIndex ) > nCharIndex ) @@ -163,30 +173,37 @@ css::uno::Sequence< css::accessibility::TextSegment > return uno::Sequence< css::accessibility::TextSegment >(); } - // #i108125# - const SwWrongList* pTextMarkupList = - mpTextMarkupList - ? mpTextMarkupList - : getTextMarkupList( *mpTextNode, nTextMarkupType ); - std::vector< css::accessibility::TextSegment > aTmpTextMarkups; - if ( pTextMarkupList ) + std::unique_ptr<sw::WrongListIteratorCounter> pIter; + if (mpTextMarkupList) + { + pIter.reset(new sw::WrongListIteratorCounter(*mpTextMarkupList)); + } + else { - const OUString rText = mrPortionData.GetAccessibleString(); + assert(m_pTextFrame); + SwWrongList const* (SwTextNode::*const pGetWrongList)() const = getTextMarkupFunc(nTextMarkupType); + if (pGetWrongList) + { + pIter.reset(new sw::WrongListIteratorCounter(*m_pTextFrame, pGetWrongList)); + } + } - const sal_uInt16 nTextMarkupCount = pTextMarkupList->Count(); - for ( sal_uInt16 nTextMarkupIdx = 0; nTextMarkupIdx < nTextMarkupCount; ++nTextMarkupIdx ) + std::vector< css::accessibility::TextSegment > aTmpTextMarkups; + if (pIter) + { + const OUString& rText = mrPortionData.GetAccessibleString(); + sal_uInt16 count(pIter->GetElementCount()); + for (sal_uInt16 i = 0; i < count; ++i) { - const SwWrongArea* pTextMarkup = pTextMarkupList->GetElement( nTextMarkupIdx ); - OSL_ENSURE( pTextMarkup, - "<SwTextMarkupHelper::getTextMarkup(..)> - missing <SwWrongArea> instance" ); - if ( pTextMarkup && - pTextMarkup->mnPos <= nCoreCharIndex && - nCoreCharIndex < ( pTextMarkup->mnPos + pTextMarkup->mnLen ) ) + auto const oElement(pIter->GetElementAt(i)); + if (oElement && + oElement->first <= nCoreCharIndex && + nCoreCharIndex < oElement->second) { const sal_Int32 nStartPos = - mrPortionData.GetAccessiblePosition( pTextMarkup->mnPos ); + mrPortionData.GetAccessiblePosition(oElement->first); const sal_Int32 nEndPos = - mrPortionData.GetAccessiblePosition( pTextMarkup->mnPos + pTextMarkup->mnLen ); + mrPortionData.GetAccessiblePosition(oElement->second); css::accessibility::TextSegment aTextMarkupSegment; aTextMarkupSegment.SegmentText = rText.copy( nStartPos, nEndPos - nStartPos ); aTextMarkupSegment.SegmentStart = nStartPos; diff --git a/sw/source/core/access/textmarkuphelper.hxx b/sw/source/core/access/textmarkuphelper.hxx index de3af6013dc6..56a1cac5f9c4 100644 --- a/sw/source/core/access/textmarkuphelper.hxx +++ b/sw/source/core/access/textmarkuphelper.hxx @@ -30,13 +30,14 @@ struct TextSegment; } } } } class SwAccessiblePortionData; -class SwTextNode; +class SwTextFrame; class SwWrongList; // #i108125# + class SwTextMarkupHelper { public: SwTextMarkupHelper( const SwAccessiblePortionData& rPortionData, - const SwTextNode& rTextNode ); + const SwTextFrame& rTextFrame); SwTextMarkupHelper( const SwAccessiblePortionData& rPortionData, const SwWrongList& rTextMarkupList ); // #i108125# @@ -64,8 +65,7 @@ class SwTextMarkupHelper const SwAccessiblePortionData& mrPortionData; - // #i108125# - const SwTextNode* mpTextNode; + SwTextFrame const* m_pTextFrame; const SwWrongList* mpTextMarkupList; }; #endif commit 5d5cef6eda22730228a8c479000fbd4cdf39d072 Author: Michael Stahl <michael.st...@cib.de> AuthorDate: Tue Oct 9 11:11:07 2018 +0200 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Mon Oct 15 15:25:46 2018 +0200 sw_redlinehide_3: add another kind of WrongListIterator This is not very efficient but should be good enough for a11y use. Change-Id: Ibb00cf4ae18effb09673f3f7d9b9b2e1d72413b1 diff --git a/sw/source/core/inc/wrong.hxx b/sw/source/core/inc/wrong.hxx index 13f1f50507cf..8340d3337ca4 100644 --- a/sw/source/core/inc/wrong.hxx +++ b/sw/source/core/inc/wrong.hxx @@ -29,6 +29,8 @@ #include <vector> +#include <boost/optional.hpp> + #include <tools/color.hxx> #include <swtypes.hxx> #include <viewopt.hxx> @@ -346,9 +348,9 @@ namespace sw { struct MergedPara; -class WrongListIterator +class WrongListIteratorBase { -private: +protected: SwWrongList const* (SwTextNode::*const m_pGetWrongList)() const; sw::MergedPara const*const m_pMergedPara; size_t m_CurrentExtent; @@ -357,6 +359,17 @@ private: public: /// for the text frame + WrongListIteratorBase(SwTextFrame const& rFrame, + SwWrongList const* (SwTextNode::*pGetWrongList)() const); + /// for SwTextSlot + WrongListIteratorBase(SwWrongList const& rWrongList); +}; + +class WrongListIterator + : public WrongListIteratorBase +{ +public: + /// for the text frame WrongListIterator(SwTextFrame const& rFrame, SwWrongList const* (SwTextNode::*pGetWrongList)() const); /// for SwTextSlot @@ -371,6 +384,18 @@ public: } }; +class WrongListIteratorCounter + : public WrongListIteratorBase +{ +public: + WrongListIteratorCounter(SwTextFrame const& rFrame, + SwWrongList const* (SwTextNode::*pGetWrongList)() const); + WrongListIteratorCounter(SwWrongList const& rWrongList); + + sal_uInt16 GetElementCount(); + boost::optional<std::pair<TextFrameIndex, TextFrameIndex>> GetElementAt(sal_uInt16 nIndex); +}; + } // namespace sw #endif diff --git a/sw/source/core/text/wrong.cxx b/sw/source/core/text/wrong.cxx index d85cf9a99bdf..1ced790261f7 100644 --- a/sw/source/core/text/wrong.cxx +++ b/sw/source/core/text/wrong.cxx @@ -664,7 +664,7 @@ void SwWrongList::Insert( const OUString& rType, namespace sw { -WrongListIterator::WrongListIterator(SwTextFrame const& rFrame, +WrongListIteratorBase::WrongListIteratorBase(SwTextFrame const& rFrame, SwWrongList const* (SwTextNode::*pGetWrongList)() const) : m_pGetWrongList(pGetWrongList) , m_pMergedPara(rFrame.GetMergedPara()) @@ -676,7 +676,7 @@ WrongListIterator::WrongListIterator(SwTextFrame const& rFrame, { } -WrongListIterator::WrongListIterator(SwWrongList const& rWrongList) +WrongListIteratorBase::WrongListIteratorBase(SwWrongList const& rWrongList) : m_pGetWrongList(nullptr) , m_pMergedPara(nullptr) , m_CurrentExtent(0) @@ -685,6 +685,17 @@ WrongListIterator::WrongListIterator(SwWrongList const& rWrongList) { } +WrongListIterator::WrongListIterator(SwTextFrame const& rFrame, + SwWrongList const* (SwTextNode::*pGetWrongList)() const) + : WrongListIteratorBase(rFrame, pGetWrongList) +{ +} + +WrongListIterator::WrongListIterator(SwWrongList const& rWrongList) + : WrongListIteratorBase(rWrongList) +{ +} + bool WrongListIterator::Check(TextFrameIndex & rStart, TextFrameIndex & rLen) { if (m_pMergedPara) @@ -838,6 +849,118 @@ WrongListIterator::GetWrongElement(TextFrameIndex const nStart) return nullptr; } +WrongListIteratorCounter::WrongListIteratorCounter(SwTextFrame const& rFrame, + SwWrongList const* (SwTextNode::*pGetWrongList)() const) + : WrongListIteratorBase(rFrame, pGetWrongList) +{ +} + +WrongListIteratorCounter::WrongListIteratorCounter(SwWrongList const& rWrongList) + : WrongListIteratorBase(rWrongList) +{ +} + +sal_uInt16 WrongListIteratorCounter::GetElementCount() +{ + if (m_pMergedPara) + { + sal_uInt16 nRet(0); + m_CurrentExtent = 0; + m_CurrentIndex = TextFrameIndex(0); + SwNode const* pNode(nullptr); + sal_uInt16 InCurrentNode(0); + while (m_CurrentExtent < m_pMergedPara->extents.size()) + { + sw::Extent const& rExtent(m_pMergedPara->extents[m_CurrentExtent]); + if (rExtent.pNode != pNode) + { + InCurrentNode = 0; + pNode = rExtent.pNode; + } + SwWrongList const*const pWrongList((rExtent.pNode->*m_pGetWrongList)()); + for (; pWrongList && InCurrentNode < pWrongList->Count(); ++InCurrentNode) + { + SwWrongArea const*const pWrong(pWrongList->GetElement(InCurrentNode)); + TextFrameIndex const nExtentEnd( + m_CurrentIndex + TextFrameIndex(rExtent.nEnd - rExtent.nStart)); + if (nExtentEnd <= TextFrameIndex(pWrong->mnPos)) + { + break; // continue outer loop + } + if (m_CurrentIndex < TextFrameIndex(pWrong->mnPos + pWrong->mnLen)) + { + ++nRet; + } + } + m_CurrentIndex += TextFrameIndex(rExtent.nEnd - rExtent.nStart); + ++m_CurrentExtent; + } + return nRet; + } + else if (m_pWrongList) + { + return m_pWrongList->Count(); + } + return 0; +} + +boost::optional<std::pair<TextFrameIndex, TextFrameIndex>> +WrongListIteratorCounter::GetElementAt(sal_uInt16 nIndex) +{ + if (m_pMergedPara) + { + m_CurrentExtent = 0; + m_CurrentIndex = TextFrameIndex(0); + SwNode const* pNode(nullptr); + sal_uInt16 InCurrentNode(0); + while (m_CurrentExtent < m_pMergedPara->extents.size()) + { + sw::Extent const& rExtent(m_pMergedPara->extents[m_CurrentExtent]); + if (rExtent.pNode != pNode) + { + InCurrentNode = 0; + pNode = rExtent.pNode; + } + SwWrongList const*const pWrongList((rExtent.pNode->*m_pGetWrongList)()); + for (; pWrongList && InCurrentNode < pWrongList->Count(); ++InCurrentNode) + { + SwWrongArea const*const pWrong(pWrongList->GetElement(InCurrentNode)); + TextFrameIndex const nExtentEnd( + m_CurrentIndex + TextFrameIndex(rExtent.nEnd - rExtent.nStart)); + if (nExtentEnd <= TextFrameIndex(pWrong->mnPos)) + { + break; // continue outer loop + } + if (m_CurrentIndex < TextFrameIndex(pWrong->mnPos + pWrong->mnLen)) + { + if (nIndex == 0) + { + return boost::optional<std::pair<TextFrameIndex, TextFrameIndex>>( + std::pair<TextFrameIndex, TextFrameIndex>( + m_CurrentIndex - TextFrameIndex(rExtent.nStart - + std::max(rExtent.nStart, pWrong->mnPos)), + m_CurrentIndex - TextFrameIndex(rExtent.nStart - + std::min(pWrong->mnPos + pWrong->mnLen, rExtent.nEnd)))); + } + --nIndex; + } + } + m_CurrentIndex += TextFrameIndex(rExtent.nEnd - rExtent.nStart); + ++m_CurrentExtent; + } + return boost::optional<std::pair<TextFrameIndex, TextFrameIndex>>(); + } + else if (m_pWrongList) + { + SwWrongArea const*const pWrong(m_pWrongList->GetElement(nIndex)); + return boost::optional<std::pair<TextFrameIndex, TextFrameIndex>>( + std::pair<TextFrameIndex, TextFrameIndex>( + TextFrameIndex(pWrong->mnPos), + TextFrameIndex(pWrong->mnPos + pWrong->mnLen))); + } + return boost::optional<std::pair<TextFrameIndex, TextFrameIndex>>(); +} + } // namespace sw /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits