diff options
Diffstat (limited to 'sw/source/core/text/porrst.cxx')
-rw-r--r-- | sw/source/core/text/porrst.cxx | 386 |
1 files changed, 329 insertions, 57 deletions
diff --git a/sw/source/core/text/porrst.cxx b/sw/source/core/text/porrst.cxx index fe94c2e9aa0b..ff1e029ae141 100644 --- a/sw/source/core/text/porrst.cxx +++ b/sw/source/core/text/porrst.cxx @@ -22,7 +22,10 @@ #include <editeng/escapementitem.hxx> #include <editeng/lrspitem.hxx> #include <editeng/pgrditem.hxx> +#include <editeng/fontitem.hxx> #include <vcl/svapp.hxx> +#include <comphelper/scopeguard.hxx> + #include <viewsh.hxx> #include <viewopt.hxx> #include <ndtxt.hxx> @@ -39,18 +42,25 @@ #include "redlnitr.hxx" #include "atrhndl.hxx" #include <rootfrm.hxx> +#include <formatlinebreak.hxx> +#include <txatbase.hxx> #include <IDocumentRedlineAccess.hxx> #include <IDocumentSettingAccess.hxx> #include <IDocumentDeviceAccess.hxx> +#include <IDocumentLayoutAccess.hxx> #include <crsrsh.hxx> +#include <swtypes.hxx> +#include <strings.hrc> +#include <flyfrms.hxx> +#include <bodyfrm.hxx> SwTmpEndPortion::SwTmpEndPortion( const SwLinePortion &rPortion, const FontLineStyle eUL, const FontStrikeout eStrkout, const Color& rCol ) : - eUnderline( eUL ), eStrikeout( eStrkout ), aColor( rCol ) + m_eUnderline( eUL ), m_eStrikeout( eStrkout ), m_aColor( rCol ) { Height( rPortion.Height() ); SetAscent( rPortion.GetAscent() ); @@ -66,14 +76,24 @@ void SwTmpEndPortion::Paint( const SwTextPaintInfo &rInf ) const SwFont aFont(*pOldFnt); + const SwDoc& rDoc = rInf.GetTextFrame()->GetDoc(); + if (aFont.IsSymbol(rDoc.getIDocumentLayoutAccess().GetCurrentViewShell())) + { + const SvxFontItem& rFontItem = rDoc.GetDefault(RES_CHRATR_FONT); + aFont.SetName( rFontItem.GetFamilyName(), SwFontScript::Latin ); + aFont.SetStyleName( rFontItem.GetStyleName(), SwFontScript::Latin ); + aFont.SetFamily( rFontItem.GetFamily(), SwFontScript::Latin ); + aFont.SetPitch( rFontItem.GetPitch(), SwFontScript::Latin ); + aFont.SetCharSet( rFontItem.GetCharSet(), SwFontScript::Latin ); + } // Paint strikeout/underline based on redline color and settings // (with an extra pilcrow in the background, because there is // no SetStrikeoutColor(), also SetUnderColor() doesn't work()). - if ( eUnderline != LINESTYLE_NONE || eStrikeout != STRIKEOUT_NONE ) + if ( m_eUnderline != LINESTYLE_NONE || m_eStrikeout != STRIKEOUT_NONE ) { - aFont.SetColor( aColor ); - aFont.SetUnderline( eUnderline ); - aFont.SetStrikeout( eStrikeout ); + aFont.SetColor( m_aColor ); + aFont.SetUnderline( m_eUnderline ); + aFont.SetStrikeout( m_eStrikeout ); const_cast<SwTextPaintInfo&>(rInf).SetFont(&aFont); @@ -93,12 +113,19 @@ void SwTmpEndPortion::Paint( const SwTextPaintInfo &rInf ) const const_cast<SwTextPaintInfo&>(rInf).SetFont(const_cast<SwFont*>(pOldFnt)); } -SwBreakPortion::SwBreakPortion( const SwLinePortion &rPortion ) +SwBreakPortion::SwBreakPortion( const SwLinePortion &rPortion, const SwTextAttr* pAttr ) : SwLinePortion( rPortion ) { mnLineLength = TextFrameIndex(1); m_eRedline = RedlineType::None; SetWhichPor( PortionType::Break ); + + m_eClear = SwLineBreakClear::NONE; + if (pAttr && pAttr->Which() == RES_TXTATR_LINEBREAK) + { + m_eClear = pAttr->GetLineBreak().GetValue(); + } + m_nTextHeight = 0; } TextFrameIndex SwBreakPortion::GetModelPositionForViewPoint(const sal_uInt16) const @@ -114,40 +141,61 @@ SwLinePortion *SwBreakPortion::Compress() void SwBreakPortion::Paint( const SwTextPaintInfo &rInf ) const { - if( rInf.OnWin() && rInf.GetOpt().IsLineBreak() ) - { - rInf.DrawLineBreak( *this ); + if( !(rInf.OnWin() && rInf.GetOpt().IsLineBreak()) ) + return; - // paint redlining - if (m_eRedline != RedlineType::None) + // Reduce height to text height for the duration of the print, so the vertical height will look + // correct for the line break character, even for clearing breaks. + SwTwips nHeight = Height(); + SwTwips nVertPosOffset = (nHeight - m_nTextHeight) / 2; + auto pPortion = const_cast<SwBreakPortion*>(this); + pPortion->Height(m_nTextHeight, false); + if (rInf.GetTextFrame()->IsVertical()) + { + // Compensate for the offset done in SwTextCursor::AdjustBaseLine() for the vertical case. + const_cast<SwTextPaintInfo&>(rInf).Y(rInf.Y() + nVertPosOffset); + } + comphelper::ScopeGuard g( + [pPortion, nHeight, &rInf, nVertPosOffset] { - sal_Int16 nNoBreakWidth = rInf.GetTextSize(S_NOBREAK_FOR_REDLINE).Width(); - if ( nNoBreakWidth > 0 ) + if (rInf.GetTextFrame()->IsVertical()) { - // approximate portion size with multiple no-break spaces - // and draw these spaces (at least a single one) by DrawText - // painting the requested redline underline/strikeout - sal_Int16 nSpaces = (LINE_BREAK_WIDTH + nNoBreakWidth/2) / nNoBreakWidth; - OUStringBuffer aBuf(S_NOBREAK_FOR_REDLINE); - for (sal_Int16 i = 1; i < nSpaces; ++i) - aBuf.append(S_NOBREAK_FOR_REDLINE); + const_cast<SwTextPaintInfo&>(rInf).Y(rInf.Y() - nVertPosOffset); + } + pPortion->Height(nHeight, false); + }); - const SwFont* pOldFnt = rInf.GetFont(); + rInf.DrawLineBreak( *this ); - SwFont aFont(*pOldFnt); + // paint redlining + if (m_eRedline == RedlineType::None) + return; - if (m_eRedline == RedlineType::Delete) - aFont.SetUnderline( LINESTYLE_NONE ); - else - aFont.SetStrikeout( STRIKEOUT_NONE ); + sal_Int16 nNoBreakWidth = rInf.GetTextSize(S_NOBREAK_FOR_REDLINE).Width(); + if ( nNoBreakWidth > 0 ) + { + // approximate portion size with multiple no-break spaces + // and draw these spaces (at least a single one) by DrawText + // painting the requested redline underline/strikeout + sal_Int16 nSpaces = (LINE_BREAK_WIDTH + nNoBreakWidth/2) / nNoBreakWidth; + OUStringBuffer aBuf(S_NOBREAK_FOR_REDLINE); + for (sal_Int16 i = 1; i < nSpaces; ++i) + aBuf.append(S_NOBREAK_FOR_REDLINE); - const_cast<SwTextPaintInfo&>(rInf).SetFont(&aFont); + const SwFont* pOldFnt = rInf.GetFont(); - rInf.DrawText(aBuf.makeStringAndClear(), *this); + SwFont aFont(*pOldFnt); - const_cast<SwTextPaintInfo&>(rInf).SetFont(const_cast<SwFont*>(pOldFnt)); - } - } + if (m_eRedline == RedlineType::Delete) + aFont.SetUnderline( LINESTYLE_NONE ); + else + aFont.SetStrikeout( STRIKEOUT_NONE ); + + const_cast<SwTextPaintInfo&>(rInf).SetFont(&aFont); + + rInf.DrawText(aBuf.makeStringAndClear(), *this); + + const_cast<SwTextPaintInfo&>(rInf).SetFont(const_cast<SwFont*>(pOldFnt)); } } @@ -156,6 +204,29 @@ bool SwBreakPortion::Format( SwTextFormatInfo &rInf ) const SwLinePortion *pRoot = rInf.GetRoot(); Width( 0 ); Height( pRoot->Height() ); + m_nTextHeight = Height(); + + // See if this is a clearing break. If so, calculate how much we need to "jump down" so the next + // line can again use the full text width. + SwLineBreakClear eClear = m_eClear; + if (rInf.GetTextFrame()->IsRightToLeft() && eClear != SwLineBreakClear::ALL) + { + // RTL ignores left/right breaks. + eClear = SwLineBreakClear::NONE; + } + if (eClear != SwLineBreakClear::NONE) + { + SwTextFly& rTextFly = rInf.GetTextFly(); + if (rTextFly.IsOn()) + { + SwTwips nHeight = rTextFly.GetMaxBottom(*this, rInf) - rInf.Y(); + if (nHeight > Height()) + { + Height(nHeight, /*bText=*/false); + } + } + } + SetAscent( pRoot->GetAscent() ); if (rInf.GetIdx() + TextFrameIndex(1) == TextFrameIndex(rInf.GetText().getLength())) rInf.SetNewLine( true ); @@ -167,21 +238,36 @@ void SwBreakPortion::HandlePortion( SwPortionHandler& rPH ) const rPH.Text( GetLen(), GetWhichPor() ); } +void SwBreakPortion::dumpAsXml(xmlTextWriterPtr pWriter, const OUString& rText, TextFrameIndex& + nOffset) const +{ + (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwBreakPortion")); + dumpAsXmlAttributes(pWriter, rText, nOffset); + nOffset += GetLen(); + + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("text-height"), + BAD_CAST(OString::number(m_nTextHeight).getStr())); + + (void)xmlTextWriterEndElement(pWriter); +} + +SwLineBreakClear SwBreakPortion::GetClear() const { return m_eClear; } + SwKernPortion::SwKernPortion( SwLinePortion &rPortion, short nKrn, bool bBG, bool bGK ) : - nKern( nKrn ), bBackground( bBG ), bGridKern( bGK ) + m_nKern( nKrn ), m_bBackground( bBG ), m_bGridKern( bGK ) { Height( rPortion.Height() ); SetAscent( rPortion.GetAscent() ); mnLineLength = TextFrameIndex(0); SetWhichPor( PortionType::Kern ); - if( nKern > 0 ) - Width( nKern ); + if( m_nKern > 0 ) + Width( m_nKern ); rPortion.Insert( this ); } SwKernPortion::SwKernPortion( const SwLinePortion& rPortion ) : - nKern( 0 ), bBackground( false ), bGridKern( true ) + m_nKern( 0 ), m_bBackground( false ), m_bGridKern( true ) { Height( rPortion.Height() ); SetAscent( rPortion.GetAscent() ); @@ -196,7 +282,7 @@ void SwKernPortion::Paint( const SwTextPaintInfo &rInf ) const return; // bBackground is set for Kerning Portions between two fields - if ( bBackground ) + if ( m_bBackground ) rInf.DrawViewOpt( *this, PortionType::Field ); rInf.DrawBackBrush( *this ); @@ -219,20 +305,20 @@ void SwKernPortion::Paint( const SwTextPaintInfo &rInf ) const void SwKernPortion::FormatEOL( SwTextFormatInfo &rInf ) { - if ( bGridKern ) + if ( m_bGridKern ) return; if( rInf.GetLast() == this ) rInf.SetLast( FindPrevPortion( rInf.GetRoot() ) ); - if( nKern < 0 ) - Width( -nKern ); + if( m_nKern < 0 ) + Width( -m_nKern ); else Width( 0 ); rInf.GetLast()->FormatEOL( rInf ); } SwArrowPortion::SwArrowPortion( const SwLinePortion &rPortion ) : - bLeft( true ) + m_bLeft( true ) { Height( rPortion.Height() ); SetAscent( rPortion.GetAscent() ); @@ -241,19 +327,19 @@ SwArrowPortion::SwArrowPortion( const SwLinePortion &rPortion ) : } SwArrowPortion::SwArrowPortion( const SwTextPaintInfo &rInf ) - : bLeft( false ) + : m_bLeft( false ) { - Height( static_cast<sal_uInt16>(rInf.GetTextFrame()->getFramePrintArea().Height()) ); - aPos.setX( rInf.GetTextFrame()->getFrameArea().Left() + + Height( o3tl::narrowing<sal_uInt16>(rInf.GetTextFrame()->getFramePrintArea().Height()) ); + m_aPos.setX( rInf.GetTextFrame()->getFrameArea().Left() + rInf.GetTextFrame()->getFramePrintArea().Right() ); - aPos.setY( rInf.GetTextFrame()->getFrameArea().Top() + + m_aPos.setY( rInf.GetTextFrame()->getFrameArea().Top() + rInf.GetTextFrame()->getFramePrintArea().Bottom() ); SetWhichPor( PortionType::Arrow ); } void SwArrowPortion::Paint( const SwTextPaintInfo &rInf ) const { - const_cast<SwArrowPortion*>(this)->aPos = rInf.GetPos(); + const_cast<SwArrowPortion*>(this)->m_aPos = rInf.GetPos(); } SwLinePortion *SwArrowPortion::Compress() { return this; } @@ -338,7 +424,18 @@ bool SwTextFrame::FormatEmpty() bool bCollapse = EmptyHeight( ) == 1 && IsCollapse( ); // sw_redlinehide: just disable FormatEmpty optimisation for now - if (HasFollow() || GetMergedPara() || GetTextNodeFirst()->GetpSwpHints() || + // Split fly frames: non-last parts of the anchor want this optimization to clear the old + // content. + SwFlyAtContentFrame* pNonLastSplitFlyDrawObj = HasNonLastSplitFlyDrawObj(); + bool bHasNonLastSplitFlyDrawObj = pNonLastSplitFlyDrawObj != nullptr; + + if (pNonLastSplitFlyDrawObj && pNonLastSplitFlyDrawObj->IsWrapOnAllPages()) + { + // Split fly: the anchor is non-empty on all pages in the "wrap on all pages" case. + bHasNonLastSplitFlyDrawObj = false; + } + + if ((HasFollow() && !bHasNonLastSplitFlyDrawObj) || GetMergedPara() || (GetTextNodeFirst()->GetpSwpHints() && !bHasNonLastSplitFlyDrawObj) || nullptr != GetTextNodeForParaProps()->GetNumRule() || GetTextNodeFirst()->HasHiddenCharAttribute(true) || IsInFootnote() || ( HasPara() && GetPara()->IsPrepMustFit() ) ) @@ -352,18 +449,27 @@ bool SwTextFrame::FormatEmpty() const SvxLineSpacingItem &rSpacing = aSet.GetLineSpacing(); if( !bCollapse && ( SvxLineSpaceRule::Min == rSpacing.GetLineSpaceRule() || SvxLineSpaceRule::Fix == rSpacing.GetLineSpaceRule() || - aSet.GetLRSpace().IsAutoFirst() ) ) + aSet.GetFirstLineIndent().IsAutoFirst())) + { return false; + } SwTextFly aTextFly( this ); SwRect aRect; bool bFirstFlyCheck = 0 != getFramePrintArea().Height(); if ( !bCollapse && bFirstFlyCheck && - aTextFly.IsOn() && aTextFly.IsAnyObj( aRect ) ) + aTextFly.IsOn() && aTextFly.IsAnyObj( aRect ) && !bHasNonLastSplitFlyDrawObj ) + return false; + + if (IsEmptyWithSplitFly()) + { + // We don't want this optimization in case the paragraph is not really empty, because it has + // a fly frame and it also needs space for the empty paragraph in a next line. return false; + } // only need to check one node because of early return on GetMerged() - for (SwIndex const* pIndex = GetTextNodeFirst()->GetFirstIndex(); + for (SwContentIndex const* pIndex = GetTextNodeFirst()->GetFirstIndex(); pIndex; pIndex = pIndex->GetNext()) { sw::mark::IMark const*const pMark = pIndex->GetMark(); @@ -384,7 +490,26 @@ bool SwTextFrame::FormatEmpty() } SwRectFnSet aRectFnSet(this); - const SwTwips nChg = nHeight - aRectFnSet.GetHeight(getFramePrintArea()); + SwTwips nChg = nHeight - aRectFnSet.GetHeight(getFramePrintArea()); + const SwBodyFrame* pBody = FindBodyFrame(); + if (pNonLastSplitFlyDrawObj && pBody) + { + // See if we need to increase the text frame height due to split flys. This is necessary for + // anchors of inner floating tables, where moving to a next page moves indirectly, so we + // want a correct text frame height. + SwTwips nFrameBottom = aRectFnSet.GetBottom(getFrameArea()) + nChg; + SwTwips nFlyBottom = aRectFnSet.GetBottom(pNonLastSplitFlyDrawObj->getFrameArea()); + SwTwips nBodyBottom = aRectFnSet.GetBottom(pBody->getFrameArea()); + if (nFlyBottom > nBodyBottom) + { + // This is the legacy case where flys may overlap with footer frames. + nFlyBottom = nBodyBottom; + } + if (pNonLastSplitFlyDrawObj->isFrameAreaPositionValid() && nFlyBottom > nFrameBottom) + { + nChg += (nFlyBottom - nFrameBottom); + } + } if( !nChg ) SetUndersized( false ); @@ -455,7 +580,7 @@ bool SwTextFrame::FillRegister( SwTwips& rRegStart, sal_uInt16& rRegDiff ) pOut = GetDoc().getIDocumentDeviceAccess().getReferenceDevice( true ); if( pSh && !pOut ) - pOut = pSh->GetWin(); + pOut = pSh->GetWin()->GetOutDev(); if( !pOut ) pOut = Application::GetDefaultDevice(); @@ -493,7 +618,7 @@ bool SwTextFrame::FillRegister( SwTwips& rRegStart, sal_uInt16& rRegDiff ) nTmp /= 100; if( !nTmp ) ++nTmp; - rRegDiff = static_cast<sal_uInt16>(nTmp); + rRegDiff = o3tl::narrowing<sal_uInt16>(nTmp); nNetHeight = rRegDiff; break; } @@ -527,7 +652,7 @@ void SwHiddenTextPortion::Paint( const SwTextPaintInfo & rInf) const { #ifdef DBG_UTIL OutputDevice* pOut = const_cast<OutputDevice*>(rInf.GetOut()); - Color aCol( SwViewOption::GetFieldShadingsColor() ); + Color aCol( rInf.GetOpt().GetFieldShadingsColor() ); Color aOldColor( pOut->GetFillColor() ); pOut->SetFillColor( aCol ); Point aPos( rInf.GetPos() ); @@ -549,10 +674,10 @@ bool SwHiddenTextPortion::Format( SwTextFormatInfo &rInf ) return false; }; -bool SwControlCharPortion::DoPaint(SwTextPaintInfo const&, +bool SwControlCharPortion::DoPaint(SwTextPaintInfo const& rTextPaintInfo, OUString & rOutString, SwFont & rTmpFont, int &) const { - if (mcChar == CHAR_ZWNBSP || !SwViewOption::IsFieldShadings()) + if (mcChar == CHAR_WJ || !rTextPaintInfo.GetOpt().IsFieldShadings()) { return false; } @@ -580,6 +705,7 @@ bool SwControlCharPortion::DoPaint(SwTextPaintInfo const&, bool SwBookmarkPortion::DoPaint(SwTextPaintInfo const& rTextPaintInfo, OUString & rOutString, SwFont & rFont, int & rDeltaY) const { + // custom color is visible without field shading, too if (!rTextPaintInfo.GetOpt().IsShowBookmarks()) { return false; @@ -594,10 +720,11 @@ bool SwBookmarkPortion::DoPaint(SwTextPaintInfo const& rTextPaintInfo, Size aSize(rFont.GetSize(rFont.GetActual())); // use also the external leading (line gap) of the portion, but don't use // 100% of it because i can't figure out how to baseline align that - auto const nFactor = (Height() * 95) / aSize.Height(); + assert(aSize.Height() != 0); + auto const nFactor = aSize.Height() > 0 ? (Height() * 95) / aSize.Height() : Height(); rFont.SetProportion(nFactor); rFont.SetWeight(WEIGHT_THIN, rFont.GetActual()); - rFont.SetColor(NON_PRINTING_CHARACTER_COLOR); + rFont.SetColor(rTextPaintInfo.GetOpt().GetFieldShadingsColor()); // reset these to default... rFont.SetAlign(ALIGN_BASELINE); rFont.SetUnderline(LINESTYLE_NONE); @@ -668,6 +795,151 @@ void SwControlCharPortion::Paint( const SwTextPaintInfo &rInf ) const const_cast< SwTextPaintInfo& >( rInf ).SetPos( aOldPos ); } +void SwBookmarkPortion::Paint( const SwTextPaintInfo &rInf ) const +{ + if ( !Width() ) // is only set during prepaint mode + return; + + rInf.DrawViewOpt(*this, GetWhichPor()); + + int deltaY(0); + SwFont aTmpFont( *rInf.GetFont() ); + OUString aOutString; + + if (!(rInf.OnWin() + && !rInf.GetOpt().IsPagePreview() + && !rInf.GetOpt().IsReadonly() + && DoPaint(rInf, aOutString, aTmpFont, deltaY))) + return; + + SwFontSave aFontSave( rInf, &aTmpFont ); + + if ( !mnHalfCharWidth ) + mnHalfCharWidth = rInf.GetTextSize( aOutString ).Width() / 2; + + Point aOldPos = rInf.GetPos(); + Point aNewPos( aOldPos ); + auto const deltaX((Width() / 2) - mnHalfCharWidth); + switch (rInf.GetFont()->GetOrientation(rInf.GetTextFrame()->IsVertical()).get()) + { + case 0: + aNewPos.AdjustX(deltaX); + aNewPos.AdjustY(deltaY); + break; + case 900: + aNewPos.AdjustY(-deltaX); + aNewPos.AdjustX(deltaY); + break; + case 2700: + aNewPos.AdjustY(deltaX); + aNewPos.AdjustX(-deltaY); + break; + default: + assert(false); + break; + } + + // draw end marks before the character position + if ( m_nStart == 0 || m_nEnd == 0 ) + { + // single type boundary marks are there outside of the bookmark text + // some |text| here + // [[ ]] + if (m_nStart > 1) + aNewPos.AdjustX(static_cast<tools::Long>(mnHalfCharWidth) * -2 * (m_aColors.size() - 1)); + } + else if ( m_nStart != 0 && m_nEnd != 0 ) + // both end and start boundary marks: adjust them around the bookmark position + // |te|xt| + // ]] [[ + aNewPos.AdjustX(static_cast<tools::Long>(mnHalfCharWidth) * -(2 * m_nEnd - 1 + m_nPoint) ); + + const_cast< SwTextPaintInfo& >( rInf ).SetPos( aNewPos ); + + for ( const auto& it : m_aColors ) + { + // set bold for custom colored bookmark symbol + // and draw multiple symbols showing all custom colors + aTmpFont.SetWeight( COL_TRANSPARENT == std::get<1>(it) ? WEIGHT_THIN : WEIGHT_BOLD, aTmpFont.GetActual() ); + aTmpFont.SetColor( COL_TRANSPARENT == std::get<1>(it) ? rInf.GetOpt().GetFieldShadingsColor() : std::get<1>(it) ); + aOutString = OUString(std::get<0>(it) == SwScriptInfo::MarkKind::Start ? '[' : ']'); + + // MarkKind::Point: drawn I-beam (e.g. U+2336) as overlapping ][ + if ( std::get<0>(it) == SwScriptInfo::MarkKind::Point ) + { + aNewPos.AdjustX(-mnHalfCharWidth * 5/16); + const_cast< SwTextPaintInfo& >( rInf ).SetPos( aNewPos ); + rInf.DrawText( aOutString, *this ); + + // when the overlapping vertical lines are 50 pixel width on the screen, + // this distance (half width * 5/8) still results precise overlapping + aNewPos.AdjustX(mnHalfCharWidth * 5/8); + const_cast< SwTextPaintInfo& >( rInf ).SetPos( aNewPos ); + aOutString = OUString('['); + } + rInf.DrawText( aOutString, *this ); + // place the next symbol after the previous one + // TODO: fix orientation and start/end + aNewPos.AdjustX(mnHalfCharWidth * 2); + const_cast< SwTextPaintInfo& >( rInf ).SetPos( aNewPos ); + } + + const_cast< SwTextPaintInfo& >( rInf ).SetPos( aOldPos ); +} + +void SwBookmarkPortion::HandlePortion( SwPortionHandler& rPH ) const +{ + OUStringBuffer aStr; + for ( const auto& it : m_aColors ) + { + aStr.append("#" + std::get<2>(it) + " " + SwResId(STR_BOOKMARK_DEF_NAME)); + switch (std::get<0>(it)) + { + case SwScriptInfo::MarkKind::Point: + break; + case SwScriptInfo::MarkKind::Start: + aStr.append(" " + SwResId(STR_CAPTION_BEGINNING)); + break; + case SwScriptInfo::MarkKind::End: + aStr.append(" " + SwResId(STR_CAPTION_END)); + break; + } + } + + rPH.Special( GetLen(), aStr.makeStringAndClear(), GetWhichPor() ); +} + +void SwBookmarkPortion::dumpAsXml(xmlTextWriterPtr pWriter, const OUString& rText, TextFrameIndex& nOffset) const +{ + (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwBookmarkPortion")); + dumpAsXmlAttributes(pWriter, rText, nOffset); + nOffset += GetLen(); + + if (!m_aColors.empty()) + { + OUStringBuffer aStr; + for (const auto& rColor : m_aColors) + { + aStr.append("#" + std::get<2>(rColor) + " " + SwResId(STR_BOOKMARK_DEF_NAME)); + switch (std::get<0>(rColor)) + { + case SwScriptInfo::MarkKind::Point: + break; + case SwScriptInfo::MarkKind::Start: + aStr.append(" " + SwResId(STR_CAPTION_BEGINNING)); + break; + case SwScriptInfo::MarkKind::End: + aStr.append(" " + SwResId(STR_CAPTION_END)); + break; + } + } + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("colors"), + BAD_CAST(aStr.makeStringAndClear().toUtf8().getStr())); + } + + (void)xmlTextWriterEndElement(pWriter); +} + bool SwControlCharPortion::Format( SwTextFormatInfo &rInf ) { const SwLinePortion* pRoot = rInf.GetRoot(); |