diff options
Diffstat (limited to 'sw/source/core/text/txtfrm.cxx')
-rw-r--r-- | sw/source/core/text/txtfrm.cxx | 606 |
1 files changed, 396 insertions, 210 deletions
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx index acd1b1b4f5be..4ce78faf1e4f 100644 --- a/sw/source/core/text/txtfrm.cxx +++ b/sw/source/core/text/txtfrm.cxx @@ -17,6 +17,8 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <config_wasm_strip.h> + #include <hintids.hxx> #include <hints.hxx> #include <svl/ctloptions.hxx> @@ -24,7 +26,7 @@ #include <editeng/lrspitem.hxx> #include <editeng/brushitem.hxx> #include <editeng/pgrditem.hxx> -#include <unotools/configmgr.hxx> +#include <comphelper/configuration.hxx> #include <swmodule.hxx> #include <SwSmartTagMgr.hxx> #include <doc.hxx> @@ -66,11 +68,15 @@ #include <fmtflcnt.hxx> #include <fmtcntnt.hxx> #include <numrule.hxx> -#include <IGrammarContact.hxx> +#include <GrammarContact.hxx> #include <calbck.hxx> #include <ftnidx.hxx> #include <ftnfrm.hxx> +#include <wrtsh.hxx> +#include <view.hxx> +#include <edtwin.hxx> +#include <FrameControlsManager.hxx> namespace sw { @@ -281,15 +287,15 @@ namespace sw { } } - bool FrameContainsNode(SwContentFrame const& rFrame, sal_uLong const nNodeIndex) + bool FrameContainsNode(SwContentFrame const& rFrame, SwNodeOffset const nNodeIndex) { if (rFrame.IsTextFrame()) { SwTextFrame const& rTextFrame(static_cast<SwTextFrame const&>(rFrame)); if (sw::MergedPara const*const pMerged = rTextFrame.GetMergedPara()) { - sal_uLong const nFirst(pMerged->pFirstNode->GetIndex()); - sal_uLong const nLast(pMerged->pLastNode->GetIndex()); + SwNodeOffset const nFirst(pMerged->pFirstNode->GetIndex()); + SwNodeOffset const nLast(pMerged->pLastNode->GetIndex()); return (nFirst <= nNodeIndex && nNodeIndex <= nLast); } else @@ -321,16 +327,16 @@ namespace sw { } SwTextNode * - GetParaPropsNode(SwRootFrame const& rLayout, SwNodeIndex const& rPos) + GetParaPropsNode(SwRootFrame const& rLayout, SwNode const& rPos) { - SwTextNode *const pTextNode(rPos.GetNode().GetTextNode()); + const SwTextNode *const pTextNode(rPos.GetTextNode()); if (pTextNode && !sw::IsParaPropsNode(rLayout, *pTextNode)) { return static_cast<SwTextFrame*>(pTextNode->getLayoutFrame(&rLayout))->GetMergedPara()->pParaPropsNode; } else { - return pTextNode; + return const_cast<SwTextNode*>(pTextNode); } } @@ -338,19 +344,16 @@ namespace sw { GetParaPropsPos(SwRootFrame const& rLayout, SwPosition const& rPos) { SwPosition pos(rPos); - SwTextNode const*const pNode(pos.nNode.GetNode().GetTextNode()); + SwTextNode const*const pNode(pos.GetNode().GetTextNode()); if (pNode) - { - pos.nNode = *sw::GetParaPropsNode(rLayout, *pNode); - pos.nContent.Assign(pos.nNode.GetNode().GetContentNode(), 0); - } + pos.Assign( *sw::GetParaPropsNode(rLayout, *pNode) ); return pos; } std::pair<SwTextNode *, SwTextNode *> - GetFirstAndLastNode(SwRootFrame const& rLayout, SwNodeIndex const& rPos) + GetFirstAndLastNode(SwRootFrame const& rLayout, SwNode const& rPos) { - SwTextNode *const pTextNode(rPos.GetNode().GetTextNode()); + SwTextNode *const pTextNode(const_cast<SwTextNode*>(rPos.GetTextNode())); if (pTextNode && rLayout.HasMergedParas()) { if (SwTextFrame const*const pFrame = static_cast<SwTextFrame*>(pTextNode->getLayoutFrame(&rLayout))) @@ -379,8 +382,7 @@ namespace sw { rFormatSet.ClearItem(RES_BREAK); static_assert(RES_PAGEDESC + 1 == sal_uInt16(RES_BREAK), "first-node items must be adjacent"); - SfxItemSet firstSet(*rFormatSet.GetPool(), - svl::Items<RES_PAGEDESC, RES_BREAK>{}); + SfxItemSetFixed<RES_PAGEDESC, RES_BREAK> firstSet(*rFormatSet.GetPool()); pMerged->pFirstNode->SwContentNode::GetAttr(firstSet); rFormatSet.Put(firstSet); @@ -398,10 +400,10 @@ namespace sw { { rFormatSet.ClearItem(i); } - SfxItemSet propsSet(*rFormatSet.GetPool(), - svl::Items<RES_PARATR_BEGIN, RES_PAGEDESC, + SfxItemSetFixed<RES_PARATR_BEGIN, RES_PAGEDESC, RES_BREAK+1, RES_FRMATR_END, - XATTR_FILL_FIRST, XATTR_FILL_LAST+1>{}); + XATTR_FILL_FIRST, XATTR_FILL_LAST+1> + propsSet(*rFormatSet.GetPool()); pMerged->pParaPropsNode->SwContentNode::GetAttr(propsSet); rFormatSet.Put(propsSet); return *pMerged->pParaPropsNode; @@ -709,13 +711,13 @@ SwLayoutModeModifier::~SwLayoutModeModifier() void SwLayoutModeModifier::Modify( bool bChgToRTL ) { const_cast<OutputDevice&>(m_rOut).SetLayoutMode( bChgToRTL ? - ComplexTextLayoutFlags::BiDiStrong | ComplexTextLayoutFlags::BiDiRtl : - ComplexTextLayoutFlags::BiDiStrong ); + vcl::text::ComplexTextLayoutFlags::BiDiStrong | vcl::text::ComplexTextLayoutFlags::BiDiRtl : + vcl::text::ComplexTextLayoutFlags::BiDiStrong ); } void SwLayoutModeModifier::SetAuto() { - const ComplexTextLayoutFlags nNewLayoutMode = m_nOldLayoutMode & ~ComplexTextLayoutFlags::BiDiStrong; + const vcl::text::ComplexTextLayoutFlags nNewLayoutMode = m_nOldLayoutMode & ~vcl::text::ComplexTextLayoutFlags::BiDiStrong; const_cast<OutputDevice&>(m_rOut).SetLayoutMode( nNewLayoutMode ); } @@ -723,11 +725,11 @@ SwDigitModeModifier::SwDigitModeModifier( const OutputDevice& rOutp, LanguageTyp rOut( rOutp ), nOldLanguageType( rOutp.GetDigitLanguage() ) { LanguageType eLang = eCurLang; - if (utl::ConfigManager::IsFuzzing()) + if (comphelper::IsFuzzing()) eLang = LANGUAGE_ENGLISH_US; else { - const SvtCTLOptions::TextNumerals nTextNumerals = SW_MOD()->GetCTLOptions().GetCTLTextNumerals(); + const SvtCTLOptions::TextNumerals nTextNumerals = SvtCTLOptions::GetCTLTextNumerals(); if ( SvtCTLOptions::NUMERALS_HINDI == nTextNumerals ) eLang = LANGUAGE_ARABIC_SAUDI_ARABIA; @@ -791,6 +793,124 @@ SwTextFrame::SwTextFrame(SwTextNode * const pNode, SwFrame* pSib, m_pMergedPara = CheckParaRedlineMerge(*this, *pNode, eMode); } +void SwTextFrame::dumpAsXmlAttributes(xmlTextWriterPtr writer) const +{ + SwContentFrame::dumpAsXmlAttributes(writer); + + const SwTextNode *pTextNode = GetTextNodeFirst(); + (void)xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "txtNodeIndex" ), "%" SAL_PRIdINT32, sal_Int32(pTextNode->GetIndex()) ); + + OString aMode = "Horizontal"_ostr; + if (IsVertLRBT()) + { + aMode = "VertBTLR"_ostr; + } + else if (IsVertLR()) + { + aMode = "VertLR"_ostr; + } + else if (IsVertical()) + { + aMode = "Vertical"_ostr; + } + (void)xmlTextWriterWriteAttribute(writer, BAD_CAST("WritingMode"), BAD_CAST(aMode.getStr())); +} + +void SwTextFrame::dumpAsXml(xmlTextWriterPtr writer) const +{ + (void)xmlTextWriterStartElement(writer, reinterpret_cast<const xmlChar*>("txt")); + dumpAsXmlAttributes( writer ); + if ( HasFollow() ) + (void)xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "follow" ), "%" SAL_PRIuUINT32, GetFollow()->GetFrameId() ); + + if (m_pPrecede != nullptr) + (void)xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "precede" ), "%" SAL_PRIuUINT32, static_cast<SwTextFrame*>(m_pPrecede)->GetFrameId() ); + + (void)xmlTextWriterWriteAttribute(writer, BAD_CAST("offset"), BAD_CAST(OString::number(static_cast<sal_Int32>(mnOffset)).getStr())); + + sw::MergedPara const*const pMerged(GetMergedPara()); + if (pMerged) + { + (void)xmlTextWriterStartElement( writer, BAD_CAST( "merged" ) ); + (void)xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "paraPropsNodeIndex" ), "%" SAL_PRIdINT32, sal_Int32(pMerged->pParaPropsNode->GetIndex()) ); + for (auto const& e : pMerged->extents) + { + (void)xmlTextWriterStartElement( writer, BAD_CAST( "extent" ) ); + (void)xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "txtNodeIndex" ), "%" SAL_PRIdINT32, sal_Int32(e.pNode->GetIndex()) ); + (void)xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "start" ), "%" SAL_PRIdINT32, e.nStart ); + (void)xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "end" ), "%" SAL_PRIdINT32, e.nEnd ); + (void)xmlTextWriterEndElement( writer ); + } + (void)xmlTextWriterEndElement( writer ); + } + + (void)xmlTextWriterStartElement(writer, BAD_CAST("infos")); + dumpInfosAsXml(writer); + (void)xmlTextWriterEndElement(writer); + + // Dump Anchored objects if any + const SwSortedObjs* pAnchored = GetDrawObjs(); + if ( pAnchored && pAnchored->size() > 0 ) + { + (void)xmlTextWriterStartElement( writer, BAD_CAST( "anchored" ) ); + + for (SwAnchoredObject* pObject : *pAnchored) + { + pObject->dumpAsXml( writer ); + } + + (void)xmlTextWriterEndElement( writer ); + } + + // Dump the children + OUString aText = GetText( ); + for ( int i = 0; i < 32; i++ ) + { + aText = aText.replace( i, '*' ); + } + auto nTextOffset = static_cast<sal_Int32>(GetOffset()); + sal_Int32 nTextLength = aText.getLength() - nTextOffset; + if (const SwTextFrame* pTextFrameFollow = GetFollow()) + { + nTextLength = static_cast<sal_Int32>(pTextFrameFollow->GetOffset() - GetOffset()); + } + if (nTextLength > 0) + { + OString aText8 + = OUStringToOString(aText.subView(nTextOffset, nTextLength), RTL_TEXTENCODING_UTF8); + (void)xmlTextWriterWriteString( writer, + reinterpret_cast<const xmlChar *>(aText8.getStr( )) ); + } + if (const SwParaPortion* pPara = GetPara()) + { + (void)xmlTextWriterStartElement(writer, BAD_CAST("SwParaPortion")); + TextFrameIndex nOffset(0); + const OUString& rText = GetText(); + (void)xmlTextWriterWriteFormatAttribute(writer, BAD_CAST("ptr"), "%p", pPara); + const SwLineLayout* pLine = pPara; + if (IsFollow()) + { + nOffset += GetOffset(); + } + while (pLine) + { + (void)xmlTextWriterStartElement(writer, BAD_CAST("SwLineLayout")); + pLine->dumpAsXmlAttributes(writer, rText, nOffset); + const SwLinePortion* pPor = pLine->GetFirstPortion(); + while (pPor) + { + pPor->dumpAsXml(writer, rText, nOffset); + pPor = pPor->GetNextPortion(); + } + (void)xmlTextWriterEndElement(writer); + pLine = pLine->GetNext(); + } + (void)xmlTextWriterEndElement(writer); + } + + (void)xmlTextWriterEndElement(writer); +} + namespace sw { SwTextFrame * MakeTextFrame(SwTextNode & rNode, SwFrame *const pSibling, @@ -809,13 +929,13 @@ void RemoveFootnotesForNode( } const SwFootnoteIdxs &rFootnoteIdxs = rTextNode.GetDoc().GetFootnoteIdxs(); size_t nPos = 0; - sal_uLong const nIndex = rTextNode.GetIndex(); + SwNodeOffset const nIndex = rTextNode.GetIndex(); rFootnoteIdxs.SeekEntry( rTextNode, &nPos ); if (nPos < rFootnoteIdxs.size()) { - while (nPos && &rTextNode == &(rFootnoteIdxs[ nPos ]->GetTextNode())) + while (nPos && rTextNode == (rFootnoteIdxs[ nPos ]->GetTextNode())) --nPos; - if (nPos || &rTextNode != &(rFootnoteIdxs[ nPos ]->GetTextNode())) + if (nPos || rTextNode != (rFootnoteIdxs[ nPos ]->GetTextNode())) ++nPos; } size_t iter(0); @@ -878,6 +998,12 @@ void SwTextFrame::DestroyImpl() } } + if (!GetDoc().IsInDtor()) + { + if (SwView* pView = GetActiveView()) + pView->GetEditWin().GetFrameControlsManager().RemoveControls(this); + } + SwContentFrame::DestroyImpl(); } @@ -1251,15 +1377,14 @@ TextFrameIndex SwTextFrame::MapModelToView(SwTextNode const*const pNode, sal_Int } else { - assert(static_cast<SwTextNode*>(const_cast<sw::BroadcastingModify*>(SwFrame::GetDep())) == pNode); return TextFrameIndex(nIndex); } } TextFrameIndex SwTextFrame::MapModelToViewPos(SwPosition const& rPos) const { - SwTextNode const*const pNode(rPos.nNode.GetNode().GetTextNode()); - sal_Int32 const nIndex(rPos.nContent.GetIndex()); + SwTextNode const*const pNode(rPos.GetNode().GetTextNode()); + sal_Int32 const nIndex(rPos.GetContentIndex()); return MapModelToView(pNode, nIndex); } @@ -1333,11 +1458,11 @@ SwDoc const& SwTextFrame::GetDoc() const } LanguageType SwTextFrame::GetLangOfChar(TextFrameIndex const nIndex, - sal_uInt16 const nScript, bool const bNoChar) const + sal_uInt16 const nScript, bool const bNoChar, bool const bNoneIfNoHyphenation) const { // a single character can be mapped uniquely! std::pair<SwTextNode const*, sal_Int32> const pos(MapViewToModel(nIndex)); - return pos.first->GetLang(pos.second, bNoChar ? 0 : 1, nScript); + return pos.first->GetLang(pos.second, bNoChar ? 0 : 1, nScript, bNoneIfNoHyphenation); } void SwTextFrame::ResetPreps() @@ -1359,6 +1484,9 @@ bool SwTextFrame::IsHiddenNow() const return true; } + if (SwContentFrame::IsHiddenNow()) + return true; + bool bHiddenCharsHidePara(false); bool bHiddenParaField(false); if (m_pMergedPara) @@ -1424,6 +1552,19 @@ bool SwTextFrame::IsHiddenNow() const ( bHiddenCharsHidePara && !pVsh->GetViewOptions()->IsShowHiddenChar() ) ) { + // in order to put the cursor in the body text, one paragraph must + // be visible - check this for the 1st body paragraph + if (IsInDocBody() && FindPrevCnt() == nullptr) + { + for (SwContentFrame const* pNext = FindNextCnt(true); + pNext != nullptr; pNext = pNext->FindNextCnt(true)) + { + if (!pNext->IsHiddenNow()) + return true; + } + SAL_INFO("sw.core", "unhiding one body paragraph"); + return false; + } return true; } } @@ -1477,7 +1618,7 @@ void SwTextFrame::HideFootnotes(TextFrameIndex const nStart, TextFrameIndex cons */ bool sw_HideObj( const SwTextFrame& _rFrame, const RndStdIds _eAnchorType, - SwPosition const& rAnchorPos, + SwFormatAnchor const& rFormatAnchor, SwAnchoredObject* _pAnchoredObj ) { bool bRet( true ); @@ -1491,9 +1632,9 @@ bool sw_HideObj( const SwTextFrame& _rFrame, pIDSA->get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION) && _rFrame.IsInDocBody() && !_rFrame.FindNextCnt() ) { - SwTextNode const& rNode(*rAnchorPos.nNode.GetNode().GetTextNode()); + SwTextNode const& rNode(*rFormatAnchor.GetAnchorNode()->GetTextNode()); assert(FrameContainsNode(_rFrame, rNode.GetIndex())); - sal_Int32 const nObjAnchorPos(rAnchorPos.nContent.GetIndex()); + sal_Int32 const nObjAnchorPos(rFormatAnchor.GetAnchorContentOffset()); const sal_Unicode cAnchorChar = nObjAnchorPos < rNode.Len() ? rNode.GetText()[nObjAnchorPos] : 0; @@ -1552,7 +1693,7 @@ void SwTextFrame::HideAndShowObjects() // under certain conditions const RndStdIds eAnchorType( pContact->GetAnchorId() ); if ((eAnchorType != RndStdIds::FLY_AT_CHAR) || - sw_HideObj(*this, eAnchorType, pContact->GetContentAnchor(), + sw_HideObj(*this, eAnchorType, pContact->GetAnchorFormat(), i )) { pContact->MoveObjToInvisibleLayer( pObj ); @@ -1586,13 +1727,13 @@ void SwTextFrame::HideAndShowObjects() { sal_Int32 nHiddenStart; sal_Int32 nHiddenEnd; - const SwPosition& rAnchor = pContact->GetContentAnchor(); + const SwFormatAnchor& rAnchorFormat = pContact->GetAnchorFormat(); SwScriptInfo::GetBoundsOfHiddenRange( - *rAnchor.nNode.GetNode().GetTextNode(), - rAnchor.nContent.GetIndex(), nHiddenStart, nHiddenEnd); + *rAnchorFormat.GetAnchorNode()->GetTextNode(), + rAnchorFormat.GetAnchorContentOffset(), nHiddenStart, nHiddenEnd); // Under certain conditions if ( nHiddenStart != COMPLETE_STRING && bShouldBeHidden && - sw_HideObj(*this, eAnchorType, rAnchor, i)) + sw_HideObj(*this, eAnchorType, rAnchorFormat, i)) { pContact->MoveObjToInvisibleLayer( pObj ); } @@ -1622,15 +1763,15 @@ void SwTextFrame::HideAndShowObjects() * line has to be formatted as well. * nFound is <= nEndLine. */ -TextFrameIndex SwTextFrame::FindBrk(const OUString &rText, +TextFrameIndex SwTextFrame::FindBrk(std::u16string_view aText, const TextFrameIndex nStart, const TextFrameIndex nEnd) { sal_Int32 nFound = sal_Int32(nStart); - const sal_Int32 nEndLine = std::min(sal_Int32(nEnd), rText.getLength() - 1); + const sal_Int32 nEndLine = std::min(sal_Int32(nEnd), sal_Int32(aText.size()) - 1); // Skip all leading blanks. - while( nFound <= nEndLine && ' ' == rText[nFound] ) + while( nFound <= nEndLine && ' ' == aText[nFound] ) { nFound++; } @@ -1639,7 +1780,7 @@ TextFrameIndex SwTextFrame::FindBrk(const OUString &rText, // "Dr.$Meyer" at the beginning of the second line. Typing a blank after that // doesn't result in the word moving into first line, even though that would work. // For this reason we don't skip the dummy char. - while( nFound <= nEndLine && ' ' != rText[nFound] ) + while( nFound <= nEndLine && ' ' != aText[nFound] ) { nFound++; } @@ -1649,6 +1790,8 @@ TextFrameIndex SwTextFrame::FindBrk(const OUString &rText, bool SwTextFrame::IsIdxInside(TextFrameIndex const nPos, TextFrameIndex const nLen) const { + if (nPos == TextFrameIndex(COMPLETE_STRING)) // the "not found" range + return false; // Silence over-eager warning emitted at least by GCC trunk towards 6: #if defined __GNUC__ && !defined __clang__ #pragma GCC diagnostic push @@ -1699,7 +1842,7 @@ void SwTextFrame::InvalidateRange_( const SwCharRange &aRange, const tools::Long // linelengths are being added, that's why it's negative // if chars have been added and positive, if chars have // deleted - pPara->GetDelta() += nD; + pPara->SetDelta(pPara->GetDelta() + nD); bInv = true; } SwCharRange &rReformat = pPara->GetReformat(); @@ -1725,7 +1868,7 @@ void SwTextFrame::CalcLineSpace() return; if( GetDrawObjs() || - GetTextNodeForParaProps()->GetSwAttrSet().GetLRSpace().IsAutoFirst()) + GetTextNodeForParaProps()->GetSwAttrSet().GetFirstLineIndent().IsAutoFirst()) { Init(); return; @@ -1792,48 +1935,48 @@ static void lcl_SetWrong( SwTextFrame& rFrame, SwTextNode const& rNode, { if ( !rFrame.IsFollow() ) { - SwTextNode* pTextNode = const_cast<SwTextNode*>(&rNode); - IGrammarContact* pGrammarContact = getGrammarContact( *pTextNode ); + SwTextNode& rTextNode = const_cast<SwTextNode&>(rNode); + sw::GrammarContact* pGrammarContact = sw::getGrammarContactFor(rTextNode); SwGrammarMarkUp* pWrongGrammar = pGrammarContact ? - pGrammarContact->getGrammarCheck( *pTextNode, false ) : - pTextNode->GetGrammarCheck(); - bool bGrammarProxy = pWrongGrammar != pTextNode->GetGrammarCheck(); + pGrammarContact->getGrammarCheck( rTextNode, false ) : + rTextNode.GetGrammarCheck(); + bool bGrammarProxy = pWrongGrammar != rTextNode.GetGrammarCheck(); if( bMove ) { - if( pTextNode->GetWrong() ) - pTextNode->GetWrong()->Move( nPos, nCnt ); + if( rTextNode.GetWrong() ) + rTextNode.GetWrong()->Move( nPos, nCnt ); if( pWrongGrammar ) pWrongGrammar->MoveGrammar( nPos, nCnt ); - if( bGrammarProxy && pTextNode->GetGrammarCheck() ) - pTextNode->GetGrammarCheck()->MoveGrammar( nPos, nCnt ); - if( pTextNode->GetSmartTags() ) - pTextNode->GetSmartTags()->Move( nPos, nCnt ); + if( bGrammarProxy && rTextNode.GetGrammarCheck() ) + rTextNode.GetGrammarCheck()->MoveGrammar( nPos, nCnt ); + if( rTextNode.GetSmartTags() ) + rTextNode.GetSmartTags()->Move( nPos, nCnt ); } else { - if( pTextNode->GetWrong() ) - pTextNode->GetWrong()->Invalidate( nPos, nCnt ); + if( rTextNode.GetWrong() ) + rTextNode.GetWrong()->Invalidate( nPos, nCnt ); if( pWrongGrammar ) pWrongGrammar->Invalidate( nPos, nCnt ); - if( pTextNode->GetSmartTags() ) - pTextNode->GetSmartTags()->Invalidate( nPos, nCnt ); + if( rTextNode.GetSmartTags() ) + rTextNode.GetSmartTags()->Invalidate( nPos, nCnt ); } const sal_Int32 nEnd = nPos + (nCnt > 0 ? nCnt : 1 ); - if ( !pTextNode->GetWrong() && !pTextNode->IsWrongDirty() ) + if ( !rTextNode.GetWrong() && !rTextNode.IsWrongDirty() ) { - pTextNode->SetWrong( new SwWrongList( WRONGLIST_SPELL ) ); - pTextNode->GetWrong()->SetInvalid( nPos, nEnd ); + rTextNode.SetWrong( std::make_unique<SwWrongList>( WRONGLIST_SPELL ) ); + rTextNode.GetWrong()->SetInvalid( nPos, nEnd ); } - if ( !pTextNode->GetSmartTags() && !pTextNode->IsSmartTagDirty() ) + if ( !rTextNode.GetSmartTags() && !rTextNode.IsSmartTagDirty() ) { - pTextNode->SetSmartTags( new SwWrongList( WRONGLIST_SMARTTAG ) ); - pTextNode->GetSmartTags()->SetInvalid( nPos, nEnd ); + rTextNode.SetSmartTags( std::make_unique<SwWrongList>( WRONGLIST_SMARTTAG ) ); + rTextNode.GetSmartTags()->SetInvalid( nPos, nEnd ); } - pTextNode->SetWrongDirty(SwTextNode::WrongState::TODO); - pTextNode->SetGrammarCheckDirty( true ); - pTextNode->SetWordCountDirty( true ); - pTextNode->SetAutoCompleteWordDirty( true ); - pTextNode->SetSmartTagDirty( true ); + rTextNode.SetWrongDirty(sw::WrongState::TODO); + rTextNode.SetGrammarCheckDirty( true ); + rTextNode.SetWordCountDirty( true ); + rTextNode.SetAutoCompleteWordDirty( true ); + rTextNode.SetSmartTagDirty( true ); } SwRootFrame *pRootFrame = rFrame.getRootFrame(); @@ -1926,7 +2069,7 @@ void UpdateMergedParaForMove(sw::MergedPara & rMerged, // assert(nDeleted == it.second - it.first); if(nDeleted) { - // InvalidateRange/lcl_SetScriptInval was called sufficiently for SwInsText + // InvalidateRange/lcl_SetScriptInval was called sufficiently for InsertText lcl_SetWrong(rTextFrame, rDestNode, nStart, it.first - it.second, false); TextFrameIndex const nIndex(sw::MapModelToView(rMerged, &rDestNode, nStart)); lcl_ModifyOfst(rTextFrame, nIndex, nDeleted, &o3tl::operator-<sal_Int32, Tag_TextFrameIndex>); @@ -1940,6 +2083,7 @@ void UpdateMergedParaForMove(sw::MergedPara & rMerged, * Related: fdo#56031 filter out attribute changes that don't matter for * humans/a11y to stop flooding the destination mortal with useless noise */ +#if !ENABLE_WASM_STRIP_ACCESSIBILITY static bool isA11yRelevantAttribute(sal_uInt16 nWhich) { return nWhich != RES_CHRATR_RSID; @@ -1953,6 +2097,7 @@ static bool hasA11yRelevantAttribute( const std::vector<sal_uInt16>& rWhichFmtAt return false; } +#endif // ENABLE_WASM_STRIP_ACCESSIBILITY // Note: for now this overrides SwClient::SwClientNotify; the intermediary // classes still override SwClient::Modify, which should continue to work @@ -1965,16 +2110,55 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint) SfxPoolItem const* pOld(nullptr); SfxPoolItem const* pNew(nullptr); sw::MoveText const* pMoveText(nullptr); + sw::InsertText const* pInsertText(nullptr); + sw::DeleteText const* pDeleteText(nullptr); + sw::DeleteChar const* pDeleteChar(nullptr); sw::RedlineDelText const* pRedlineDelText(nullptr); sw::RedlineUnDelText const* pRedlineUnDelText(nullptr); sal_uInt16 nWhich = 0; - if (auto const pHint = dynamic_cast<sw::LegacyModifyHint const*>(&rHint)) + if (rHint.GetId() == SfxHintId::SwLegacyModify) { + auto pHint = static_cast<const sw::LegacyModifyHint*>(&rHint); pOld = pHint->m_pOld; pNew = pHint->m_pNew; nWhich = pHint->GetWhich(); } + else if (rHint.GetId() == SfxHintId::SwInsertText) + { + pInsertText = static_cast<const sw::InsertText*>(&rHint); + } + else if (rHint.GetId() == SfxHintId::SwDeleteText) + { + pDeleteText = static_cast<const sw::DeleteText*>(&rHint); + } + else if (rHint.GetId() == SfxHintId::SwDeleteChar) + { + pDeleteChar = static_cast<const sw::DeleteChar*>(&rHint); + } + else if (rHint.GetId() == SfxHintId::SwDocPosUpdateAtIndex) + { + auto pDocPosAt = static_cast<const sw::DocPosUpdateAtIndex*>(&rHint); + Broadcast(SfxHint()); // notify SwAccessibleParagraph + if(IsLocked()) + return; + if(pDocPosAt->m_nDocPos > getFrameArea().Top()) + return; + TextFrameIndex const nIndex(MapModelToView( + &pDocPosAt->m_rNode, + pDocPosAt->m_nIndex)); + InvalidateRange(SwCharRange(nIndex, TextFrameIndex(1))); + return; + } + else if (rHint.GetId() == SfxHintId::SwVirtPageNumHint) + { + auto& rVirtPageNumHint = const_cast<sw::VirtPageNumHint&>(static_cast<const sw::VirtPageNumHint&>(rHint)); + if(!IsInDocBody() || IsFollow() || rVirtPageNumHint.IsFound()) + return; + if(const SwPageFrame* pPage = FindPageFrame()) + pPage->UpdateVirtPageNumInfo(rVirtPageNumHint, this); + return; + } else if (auto const pHt = dynamic_cast<sw::MoveText const*>(&rHint)) { pMoveText = pHt; @@ -2106,7 +2290,7 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint) && m_pMergedPara->pFirstNode->GetIndex() <= pMoveText->pDestNode->GetIndex() && pMoveText->pDestNode->GetIndex() <= m_pMergedPara->pLastNode->GetIndex()) { // if it's not 2 nodes in merged frame, assume the target node doesn't have frames at all - assert(std::abs(static_cast<tools::Long>(rNode.GetIndex()) - static_cast<tools::Long>(pMoveText->pDestNode->GetIndex())) == 1); + assert(abs(rNode.GetIndex() - pMoveText->pDestNode->GetIndex()) == SwNodeOffset(1)); UpdateMergedParaForMove(*m_pMergedPara, *this, bRecalcFootnoteFlag, @@ -2121,23 +2305,28 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint) // assert(!m_pMergedPara || !getRootFrame()->IsHideRedlines() || !pMoveText->pDestNode->getLayoutFrame(getRootFrame())); } } - else switch (nWhich) + else if (pInsertText) { - case RES_LINENUMBER: + nPos = MapModelToView(&rNode, pInsertText->nPos); + // unlike redlines, inserting into fieldmark must be explicitly handled + bool isHidden(false); + switch (getRootFrame()->GetFieldmarkMode()) { - assert(false); // should have been forwarded to SwContentFrame - InvalidateLineNum(); + case sw::FieldmarkMode::ShowCommand: + isHidden = pInsertText->isInsideFieldmarkResult; + break; + case sw::FieldmarkMode::ShowResult: + isHidden = pInsertText->isInsideFieldmarkCommand; + break; + case sw::FieldmarkMode::ShowBoth: // just to avoid the warning + break; } - break; - case RES_INS_TXT: + if (!isHidden) { - sal_Int32 const nNPos = static_cast<const SwInsText*>(pNew)->nPos; - sal_Int32 const nNLen = static_cast<const SwInsText*>(pNew)->nLen; - nPos = MapModelToView(&rNode, nNPos); - nLen = TextFrameIndex(nNLen); + nLen = TextFrameIndex(pInsertText->nLen); if (m_pMergedPara) { - UpdateMergedParaForInsert(*m_pMergedPara, true, rNode, nNPos, nNLen); + UpdateMergedParaForInsert(*m_pMergedPara, true, rNode, pInsertText->nPos, pInsertText->nLen); } if( IsIdxInside( nPos, nLen ) ) { @@ -2150,64 +2339,67 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint) Prepare(); } else - InvalidateRange_( SwCharRange( nPos, nLen ), nNLen ); + InvalidateRange_( SwCharRange( nPos, nLen ), pInsertText->nLen ); } - lcl_SetWrong( *this, rNode, nNPos, nNLen, true ); lcl_SetScriptInval( *this, nPos ); bSetFieldsDirty = true; lcl_ModifyOfst(*this, nPos, nLen, &o3tl::operator+<sal_Int32, Tag_TextFrameIndex>); } - break; - case RES_DEL_CHR: + lcl_SetWrong( *this, rNode, pInsertText->nPos, pInsertText->nLen, true ); + } + else if (pDeleteText) + { + nPos = MapModelToView(&rNode, pDeleteText->nStart); + if (m_pMergedPara) + { // update merged before doing anything else + nLen = UpdateMergedParaForDelete(*m_pMergedPara, true, rNode, pDeleteText->nStart, pDeleteText->nLen); + } + else { - sal_Int32 const nNPos = static_cast<const SwDelChr*>(pNew)->nPos; - nPos = MapModelToView(&rNode, nNPos); - if (m_pMergedPara) - { - nLen = UpdateMergedParaForDelete(*m_pMergedPara, true, rNode, nNPos, 1); - } - else - { - nLen = TextFrameIndex(1); - } - lcl_SetWrong( *this, rNode, nNPos, -1, true ); - if (nLen) - { - InvalidateRange( SwCharRange(nPos, nLen), -1 ); - lcl_SetScriptInval( *this, nPos ); - bSetFieldsDirty = bRecalcFootnoteFlag = true; - lcl_ModifyOfst(*this, nPos, nLen, &o3tl::operator-<sal_Int32, Tag_TextFrameIndex>); - } + nLen = TextFrameIndex(pDeleteText->nLen); } - break; - case RES_DEL_TXT: + const sal_Int32 m = -pDeleteText->nLen; + if ((!m_pMergedPara || nLen) && IsIdxInside(nPos, nLen)) { - sal_Int32 const nNPos = static_cast<const SwDelText*>(pNew)->nStart; - sal_Int32 const nNLen = static_cast<const SwDelText*>(pNew)->nLen; - nPos = MapModelToView(&rNode, nNPos); - if (m_pMergedPara) - { // update merged before doing anything else - nLen = UpdateMergedParaForDelete(*m_pMergedPara, true, rNode, nNPos, nNLen); - } + if( !nLen ) + InvalidateSize(); else - { - nLen = TextFrameIndex(nNLen); - } - const sal_Int32 m = -nNLen; - if ((!m_pMergedPara || nLen) && IsIdxInside(nPos, nLen)) - { - if( !nLen ) - InvalidateSize(); - else - InvalidateRange( SwCharRange(nPos, TextFrameIndex(1)), m ); - } - lcl_SetWrong( *this, rNode, nNPos, m, true ); - if (nLen) - { - lcl_SetScriptInval( *this, nPos ); - bSetFieldsDirty = bRecalcFootnoteFlag = true; - lcl_ModifyOfst(*this, nPos, nLen, &o3tl::operator-<sal_Int32, Tag_TextFrameIndex>); - } + InvalidateRange( SwCharRange(nPos, TextFrameIndex(1)), m ); + } + lcl_SetWrong( *this, rNode, pDeleteText->nStart, m, true ); + if (nLen) + { + lcl_SetScriptInval( *this, nPos ); + bSetFieldsDirty = bRecalcFootnoteFlag = true; + lcl_ModifyOfst(*this, nPos, nLen, &o3tl::operator-<sal_Int32, Tag_TextFrameIndex>); + } + } + else if (pDeleteChar) + { + nPos = MapModelToView(&rNode, pDeleteChar->m_nPos); + if (m_pMergedPara) + { + nLen = UpdateMergedParaForDelete(*m_pMergedPara, true, rNode, pDeleteChar->m_nPos, 1); + } + else + { + nLen = TextFrameIndex(1); + } + lcl_SetWrong( *this, rNode, pDeleteChar->m_nPos, -1, true ); + if (nLen) + { + InvalidateRange( SwCharRange(nPos, nLen), -1 ); + lcl_SetScriptInval( *this, nPos ); + bSetFieldsDirty = bRecalcFootnoteFlag = true; + lcl_ModifyOfst(*this, nPos, nLen, &o3tl::operator-<sal_Int32, Tag_TextFrameIndex>); + } + } + else switch (nWhich) + { + case RES_LINENUMBER: + { + assert(false); // should have been forwarded to SwContentFrame + InvalidateLineNum(); } break; case RES_UPDATE_ATTR: @@ -2239,6 +2431,7 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint) } } +#if !ENABLE_WASM_STRIP_ACCESSIBILITY if( isA11yRelevantAttribute( pNewUpdate->getWhichAttr() ) && hasA11yRelevantAttribute( pNewUpdate->getFmtAttrs() ) ) { @@ -2248,6 +2441,7 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint) pViewSh->InvalidateAccessibleParaAttrs( *this ); } } +#endif } break; case RES_OBJECTDYING: @@ -2282,7 +2476,7 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint) nPos = MapModelToView(&rNode, nNPos); if (IsIdxInside(nPos, TextFrameIndex(1))) { - if( pNew == pOld ) + if (SfxPoolItem::areSame( pNew, pOld )) { // only repaint // opt: invalidate window? @@ -2305,7 +2499,7 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint) { // the hint may be sent from the anchor node, or from a // node in the footnote; the anchor index is only valid in the // anchor node! - assert(&rNode == &static_cast<const SwFormatFootnote*>(pNew)->GetTextFootnote()->GetTextNode()); + assert(rNode == static_cast<const SwFormatFootnote*>(pNew)->GetTextFootnote()->GetTextNode()); nPos = MapModelToView(&rNode, static_cast<const SwFormatFootnote*>(pNew)->GetTextFootnote()->GetStart()); } @@ -2322,29 +2516,26 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint) InvalidateLineNum(); const SwAttrSet& rNewSet = *static_cast<const SwAttrSetChg*>(pNew)->GetChgSet(); - const SfxPoolItem* pItem = nullptr; int nClear = 0; sal_uInt16 nCount = rNewSet.Count(); - if( SfxItemState::SET == rNewSet.GetItemState( RES_TXTATR_FTN, false, &pItem )) + if( const SwFormatFootnote* pItem = rNewSet.GetItemIfSet( RES_TXTATR_FTN, false ) ) { - nPos = MapModelToView(&rNode, - static_cast<const SwFormatFootnote*>(pItem)->GetTextFootnote()->GetStart()); + nPos = MapModelToView(&rNode, pItem->GetTextFootnote()->GetStart()); if (IsIdxInside(nPos, TextFrameIndex(1))) Prepare( PrepareHint::FootnoteInvalidation, pNew ); nClear = 0x01; --nCount; } - if( SfxItemState::SET == rNewSet.GetItemState( RES_TXTATR_FIELD, false, &pItem )) + if( const SwFormatField* pItem = rNewSet.GetItemIfSet( RES_TXTATR_FIELD, false ) ) { - nPos = MapModelToView(&rNode, - static_cast<const SwFormatField*>(pItem)->GetTextField()->GetStart()); + nPos = MapModelToView(&rNode, pItem->GetTextField()->GetStart()); if (IsIdxInside(nPos, TextFrameIndex(1))) { const SfxPoolItem* pOldItem = pOld ? &(static_cast<const SwAttrSetChg*>(pOld)->GetChgSet()->Get(RES_TXTATR_FIELD)) : nullptr; - if( pItem == pOldItem ) + if (SfxPoolItem::areSame( pItem, pOldItem )) { InvalidatePage(); SetCompletePaint(); @@ -2413,7 +2604,7 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint) for ( size_t i = 0; GetDrawObjs() && i < pObjs->size(); ++i ) { SwAnchoredObject* pAnchoredObj = (*pObjs)[i]; - if ( auto pFly = dynamic_cast<SwFlyFrame *>( pAnchoredObj ) ) + if ( auto pFly = pAnchoredObj->DynCastFlyFrame() ) { if( !pFly->IsFlyInContentFrame() ) { @@ -2545,6 +2736,7 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint) SwContentFrame::SwClientNotify(rModify, sw::LegacyModifyHint(pOld, pNew)); } +#if !ENABLE_WASM_STRIP_ACCESSIBILITY if (isA11yRelevantAttribute(nWhich)) { SwViewShell* pViewSh = getRootFrame() ? getRootFrame()->GetCurrShell() : nullptr; @@ -2553,25 +2745,9 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint) pViewSh->InvalidateAccessibleParaAttrs( *this ); } } +#endif } break; - - // Process SwDocPosUpdate - case RES_DOCPOS_UPDATE: - { - if( pOld && pNew ) - { - const SwDocPosUpdate *pDocPos = static_cast<const SwDocPosUpdate*>(pOld); - if( pDocPos->nDocPos <= getFrameArea().Top() ) - { - const SwFormatField *pField = static_cast<const SwFormatField *>(pNew); - TextFrameIndex const nIndex(MapModelToView(&rNode, - pField->GetTextField()->GetStart())); - InvalidateRange(SwCharRange(nIndex, TextFrameIndex(1))); - } - } - break; - } case RES_PARATR_SPLIT: if ( GetPrev() ) CheckKeep(); @@ -2598,38 +2774,12 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint) } // switch if( bSetFieldsDirty ) - GetDoc().getIDocumentFieldsAccess().SetFieldsDirty( true, &rNode, 1 ); + GetDoc().getIDocumentFieldsAccess().SetFieldsDirty( true, &rNode, SwNodeOffset(1) ); if ( bRecalcFootnoteFlag ) CalcFootnoteFlag(); } -bool SwTextFrame::GetInfo( SfxPoolItem &rHint ) const -{ - if ( RES_VIRTPAGENUM_INFO == rHint.Which() && IsInDocBody() && ! IsFollow() ) - { - SwVirtPageNumInfo &rInfo = static_cast<SwVirtPageNumInfo&>(rHint); - const SwPageFrame *pPage = FindPageFrame(); - if ( pPage ) - { - if ( pPage == rInfo.GetOrigPage() && !GetPrev() ) - { - // this should be the one - // (could only differ temporarily; is that disturbing?) - rInfo.SetInfo( pPage, this ); - return false; - } - if ( pPage->GetPhyPageNum() < rInfo.GetOrigPage()->GetPhyPageNum() && - (!rInfo.GetPage() || pPage->GetPhyPageNum() > rInfo.GetPage()->GetPhyPageNum())) - { - // this could be the one - rInfo.SetInfo( pPage, this ); - } - } - } - return true; -} - void SwTextFrame::PrepWidows( const sal_uInt16 nNeed, bool bNotify ) { OSL_ENSURE(GetFollow() && nNeed, "+SwTextFrame::Prepare: lost all friends"); @@ -2765,7 +2915,12 @@ bool SwTextFrame::Prepare( const PrepareHint ePrep, const void* pVoid, } } - if( !HasPara() && PrepareHint::MustFit != ePrep ) + // Split fly anchors are technically empty (have no SwParaPortion), but otherwise behave like + // other split text frames, which are non-empty. + bool bSplitFlyAnchor = GetOffset() == TextFrameIndex(0) && HasFollow() + && GetFollow()->GetOffset() == TextFrameIndex(0); + + if( !HasPara() && !bSplitFlyAnchor && PrepareHint::MustFit != ePrep ) { SetInvalidVert( true ); // Test OSL_ENSURE( !IsLocked(), "SwTextFrame::Prepare: three of a perfect pair" ); @@ -2943,7 +3098,7 @@ bool SwTextFrame::Prepare( const PrepareHint ePrep, const void* pVoid, SwAnchoredObject* pAnchoredObj = (*GetDrawObjs())[i]; // i#28701 - consider all // to-character anchored objects - if ( pAnchoredObj->GetFrameFormat().GetAnchor().GetAnchorId() + if ( pAnchoredObj->GetFrameFormat()->GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_CHAR ) { bFormat = true; @@ -2958,7 +3113,13 @@ bool SwTextFrame::Prepare( const PrepareHint ePrep, const void* pVoid, if( aTextFly.IsOn() ) { // Does any free-flying frame overlap? - bFormat = aTextFly.Relax() || IsUndersized(); + const bool bRelaxed = aTextFly.Relax(); + bFormat = bRelaxed || IsUndersized(); + if (bRelaxed) + { + // It's possible that pPara was deleted above; retrieve it again + pPara = aAccess.GetPara(); + } } } } @@ -3200,7 +3361,7 @@ bool SwTextFrame::TestFormat( const SwFrame* pPrv, SwTwips &rMaxHeight, bool &bS SwTestFormat aSave( this, pPrv, rMaxHeight ); - return SwTextFrame::WouldFit( rMaxHeight, bSplit, true ); + return SwTextFrame::WouldFit(rMaxHeight, bSplit, true, false); } /** @@ -3215,7 +3376,7 @@ bool SwTextFrame::TestFormat( const SwFrame* pPrv, SwTwips &rMaxHeight, bool &bS * * @returns true if I can split */ -bool SwTextFrame::WouldFit( SwTwips &rMaxHeight, bool &bSplit, bool bTst ) +bool SwTextFrame::WouldFit(SwTwips &rMaxHeight, bool &bSplit, bool bTst, bool bMoveBwd) { OSL_ENSURE( ! IsVertical() || ! IsSwapped(), "SwTextFrame::WouldFit with swapped frame" ); @@ -3298,7 +3459,7 @@ bool SwTextFrame::WouldFit( SwTwips &rMaxHeight, bool &bSplit, bool bTst ) // is breaking necessary? bSplit = !aFrameBreak.IsInside( aLine ); if ( bSplit ) - bRet = !aFrameBreak.IsKeepAlways() && aFrameBreak.WouldFit( aLine, rMaxHeight, bTst ); + bRet = !aFrameBreak.IsKeepAlways() && aFrameBreak.WouldFit(aLine, rMaxHeight, bTst, bMoveBwd); else { // we need the total height including the current line @@ -3312,7 +3473,7 @@ bool SwTextFrame::WouldFit( SwTwips &rMaxHeight, bool &bSplit, bool bTst ) return bRet; } -sal_uInt16 SwTextFrame::GetParHeight() const +SwTwips SwTextFrame::GetParHeight() const { OSL_ENSURE( ! IsVertical() || ! IsSwapped(), "SwTextFrame::GetParHeight with swapped frame" ); @@ -3320,11 +3481,11 @@ sal_uInt16 SwTextFrame::GetParHeight() const if( !HasPara() ) { // For non-empty paragraphs this is a special case // For UnderSized we can simply just ask 1 Twip more - sal_uInt16 nRet = static_cast<sal_uInt16>(getFramePrintArea().SSize().Height()); + sal_uInt16 nRet = o3tl::narrowing<sal_uInt16>(getFramePrintArea().SSize().Height()); if( IsUndersized() ) { if( IsEmpty() || GetText().isEmpty() ) - nRet = static_cast<sal_uInt16>(EmptyHeight()); + nRet = o3tl::narrowing<sal_uInt16>(EmptyHeight()); else ++nRet; } @@ -3333,7 +3494,7 @@ sal_uInt16 SwTextFrame::GetParHeight() const // TODO: Refactor and improve code const SwLineLayout* pLineLayout = GetPara(); - sal_uInt16 nHeight = pLineLayout ? pLineLayout->GetRealHeight() : 0; + SwTwips nHeight = pLineLayout ? pLineLayout->GetRealHeight() : 0; // Is this paragraph scrolled? Our height until now is at least // one line height too low then @@ -3475,7 +3636,7 @@ void SwTextFrame::CalcAdditionalFirstLineOffset() nListLevel = MAXLEVEL - 1; const SwNumFormat& rNumFormat = - pTextNode->GetNumRule()->Get( static_cast<sal_uInt16>(nListLevel) ); + pTextNode->GetNumRule()->Get( o3tl::narrowing<sal_uInt16>(nListLevel) ); if ( rNumFormat.GetPositionAndSpaceMode() != SvxNumberFormat::LABEL_ALIGNMENT ) return; @@ -3722,19 +3883,33 @@ sal_uInt16 SwTextFrame::FirstLineHeight() const if ( !HasPara() ) { if( IsEmpty() && isFrameAreaDefinitionValid() ) - return IsVertical() ? static_cast<sal_uInt16>(getFramePrintArea().Width()) : static_cast<sal_uInt16>(getFramePrintArea().Height()); + return IsVertical() ? o3tl::narrowing<sal_uInt16>(getFramePrintArea().Width()) : o3tl::narrowing<sal_uInt16>(getFramePrintArea().Height()); return USHRT_MAX; } const SwParaPortion *pPara = GetPara(); if ( !pPara ) return USHRT_MAX; - return pPara->Height(); + // tdf#146500 Lines with only fly overlap cannot be "moved", so the idea + // here is to continue until there's some text. + // FIXME ideally we want to count a fly to the line in which it is anchored + // - it may even be anchored in some other paragraph! SwFlyPortion doesn't + // have a pointer sadly so no way to find out. + sal_uInt16 nHeight(0); + for (SwLineLayout const* pLine = pPara; pLine; pLine = pLine->GetNext()) + { + nHeight += pLine->Height(); + if (::sw::FindNonFlyPortion(*pLine)) + { + break; + } + } + return nHeight; } -sal_uInt16 SwTextFrame::GetLineCount(TextFrameIndex const nPos) +sal_Int32 SwTextFrame::GetLineCount(TextFrameIndex const nPos) { - sal_uInt16 nRet = 0; + sal_Int32 nRet = 0; SwTextFrame *pFrame = this; do { @@ -3756,7 +3931,7 @@ sal_uInt16 SwTextFrame::GetLineCount(TextFrameIndex const nPos) void SwTextFrame::ChgThisLines() { // not necessary to format here (GetFormatted etc.), because we have to come from there! - sal_uInt32 nNew = 0; + sal_Int32 nNew = 0; const SwLineNumberInfo &rInf = GetDoc().GetLineNumberInfo(); if ( !GetText().isEmpty() && HasPara() ) { @@ -3816,9 +3991,9 @@ void SwTextFrame::RecalcAllLines() if ( IsInTab() ) return; - const sal_uLong nOld = GetAllLines(); + const sal_Int32 nOld = GetAllLines(); const SwFormatLineNumber &rLineNum = GetTextNodeForParaProps()->GetSwAttrSet().GetLineNumber(); - sal_uLong nNewNum; + sal_Int32 nNewNum; const bool bRestart = GetDoc().GetLineNumberInfo().IsRestartEachPage(); if ( !IsFollow() && rLineNum.GetStartValue() && rLineNum.IsCount() ) @@ -3882,7 +4057,7 @@ void SwTextFrame::VisitPortions( SwPortionHandler& rPH ) const pPor = pPor->GetNextPortion(); } - rPH.LineBreak(pLine->Width()); + rPH.LineBreak(); pLine = pLine->GetNext(); } } @@ -4024,4 +4199,15 @@ void SwTextFrame::repaintTextFrames( const SwTextNode& rNode ) } } +void SwTextFrame::UpdateOutlineContentVisibilityButton(SwWrtShell* pWrtSh) const +{ + if (pWrtSh && pWrtSh->GetViewOptions()->IsShowOutlineContentVisibilityButton() && + GetTextNodeFirst()->IsOutline()) + { + SwEditWin& rEditWin = pWrtSh->GetView().GetEditWin(); + SwFrameControlsManager& rMngr = rEditWin.GetFrameControlsManager(); + rMngr.SetOutlineContentVisibilityButton(this); + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |