/** *Localhelperfunction.ChecksifnLowershouldbetakenastheboundary *forthefootnote.
*/ static SwTwips lcl_GetFootnoteLower( const SwTextFrame* pFrame, SwTwips nLower )
{ // nLower is an absolute value. It denotes the bottom of the line // containing the footnote.
SwRectFnSet aRectFnSet(pFrame);
OSL_ENSURE( !pFrame->IsVertical() || !pFrame->IsSwapped(), "lcl_GetFootnoteLower with swapped frame" );
SwTwips nAdd;
SwTwips nRet = nLower;
// Check if text is inside a table. if ( pFrame->IsInTab() )
{ // If pFrame is inside a table, we have to check if // a) The table is not allowed to split or // b) The table row is not allowed to split
// Inside a table, there are no footnotes, // see SwFrame::FindFootnoteBossFrame. So we don't have to check // the case that pFrame is inside a (footnote collecting) section // within the table. const SwFrame* pRow = pFrame; while( !pRow->IsRowFrame() || !pRow->GetUpper()->IsTabFrame() )
pRow = pRow->GetUpper(); const SwTabFrame* pTabFrame = static_cast<const SwTabFrame*>(pRow->GetUpper());
OSL_ENSURE( pTabFrame && pRow &&
pRow->GetUpper()->IsTabFrame(), "Upper of row should be tab" );
// #i10770#: If there are fly frames anchored at previous paragraphs, // the deadline should consider their lower borders. const SwFrame* pStartFrame = pFrame->GetUpper()->GetLower();
OSL_ENSURE( pStartFrame, "Upper has no lower" );
SwTwips nFlyLower = aRectFnSet.IsVert() ? LONG_MAX : 0; while ( pStartFrame != pFrame )
{
assert(pStartFrame && "Frame chain is broken"); if ( pStartFrame->GetDrawObjs() )
{ const SwSortedObjs &rObjs = *pStartFrame->GetDrawObjs(); for (SwAnchoredObject* pAnchoredObj : rObjs)
{ if (pAnchoredObj->GetFrameFormat()->GetSurround().GetSurround()
== text::WrapTextMode_THROUGH)
{ continue; // tdf#161718 no effect on text flow, skip
}
if( !HasPara() )
{ // #109071# GetFormatted() does not work here, because most probably // the frame is currently locked. We return the previous value. return pThis->mnFootnoteLine > 0 ?
pThis->mnFootnoteLine :
IsVertical() ? getFrameArea().Left() : getFrameArea().Bottom();
}
SwTwips nHeight = pRef->IsInFootnoteConnect() ? 1 : pRef->GetFootnoteLine( pFootnoteFrame->GetAttr() ); if( nHeight )
{ // As odd as it may seem: the first Footnote on the page may not touch the // Footnote Reference, when entering text in the Footnote Area. const SwFrame *pCont = pFootnoteFrame->GetUpper();
// Height within the Container which we're allowed to consume anyways
SwRectFnSet aRectFnSet(pCont);
SwTwips nTmp = aRectFnSet.YDiff( aRectFnSet.GetPrtBottom(*pCont),
aRectFnSet.GetTop(getFrameArea()) );
if (bEndn)
{ if (!pEndBoss)
pEndBoss = pSource->FindFootnoteBossFrame();
} else
{ if (!pFootnoteBoss)
{
pFootnoteBoss = pSource->FindFootnoteBossFrame( true ); if( pFootnoteBoss->GetUpper()->IsSctFrame() )
{
SwSectionFrame* pSect = static_cast<SwSectionFrame*>(
pFootnoteBoss->GetUpper()); if (pSect->IsFootnoteAtEnd())
bFootnoteEndDoc = false;
}
}
}
// We don't delete, but move instead. // Three cases are to be considered: // 1) There's neither Follow nor PrevFollow: // -> RemoveFootnote() (maybe even a OSL_ENSURE(value)) // // 2) nStart > GetOffset, I have a Follow // -> Footnote moves into Follow // // 3) nStart < GetOffset, I am a Follow // -> Footnote moves into the PrevFollow // // Both need to be on one Page/in one Column
SwFootnoteFrame *pFootnoteFrame = SwFootnoteBossFrame::FindFootnote(pSource, pFootnote);
// We break the oscillation if (bRemove && !bFootnoteEndDoc && HasPara())
{
ValidateBodyFrame();
ValidateFrame();
}
// We call the RemoveFootnote from within the FindBreak, because the last line is // to be passed to the Follow. The Offset of the Follow is, however, outdated; // it'll be set soon. CalcFntFlag depends on a correctly set Follow Offset. // Therefore we temporarily calculate the Follow Offset here
TextFrameIndex nOldOfst(COMPLETE_STRING); if( HasFollow() && nStart > GetOffset() )
{
nOldOfst = GetFollow()->GetOffset();
GetFollow()->ManipOfst(nStart + (bRollBack ? nLen : TextFrameIndex(0)));
}
pSource->CalcFootnoteFlag(); if (nOldOfst < TextFrameIndex(COMPLETE_STRING))
GetFollow()->ManipOfst( nOldOfst );
}
mbFootnote = true;
mbInFootnoteConnect = true; // Just reset! // See if pFootnote is an endnote on a separate endnote page. constbool bEnd = pFootnote->GetFootnote().IsEndNote();
// We want to store this value, because it is needed as a fallback // in GetFootnoteLine(), if there is no paragraph information available
mnFootnoteLine = nDeadLine;
// We always need a parent (Page/Column)
SwSectionFrame *pSect;
SwContentFrame *pContent = this; if( bEnd && IsInSct() )
{
pSect = FindSctFrame(); if( pSect->IsEndnAtEnd() )
pContent = pSect->FindLastContent( SwFindMode::EndNote ); if( !pContent )
pContent = this;
}
if( nDiff >= 0 )
{ // If the Footnote has been registered to a Follow, we need to // rewire it now too if ( pSrcFrame != this )
SwFootnoteBossFrame::ChangeFootnoteRef( pSrcFrame, pFootnote, this );
// We have some room left, so the Footnote can grow if ( pFootnoteFrame->GetFollow() && nDiff > 0 )
{
SwFrameDeleteGuard aDeleteGuard(pCont);
SwTwips nHeight = aRectFnSet.GetHeight(pCont->getFrameArea());
pBoss->RearrangeFootnotes( nDeadLine, false, pFootnote );
ValidateBodyFrame();
ValidateFrame();
SwViewShell *pSh = getRootFrame()->GetCurrShell(); if ( pSh && nHeight == aRectFnSet.GetHeight(pCont->getFrameArea()) ) // So that we don't miss anything
pSh->InvalidateWindows( pCont->getFrameArea() );
}
mbInFootnoteConnect = false; return;
} else
bBrutal = true;
} else
{ // Ref and Footnote are not on one Page; attempt to move is necessary
SwFrame* pTmp = this; while( pTmp->GetNext() && pSrcFrame != pTmp )
pTmp = pTmp->GetNext(); if( pSrcFrame == pTmp )
bBrutal = true; else
{ // If our Parent is in a column Area, but the Page already has a // FootnoteContainer, we can only brute force it if( pSect && pSect->FindFootnoteBossFrame( !bEnd )->FindFootnoteCont() )
bBrutal = true;
// The brute force method: Remove Footnote and append. // We need to call SetFootnoteDeadLine(), as we can more easily adapt the // nMaxFootnoteHeight after RemoveFootnote if( bBrutal )
{
pBoss->RemoveFootnote( pSrcFrame, pFootnote, false );
std::unique_ptr<SwSaveFootnoteHeight> pHeight(bEnd ? nullptr : new SwSaveFootnoteHeight( pBoss, nDeadLine ));
pBoss->AppendFootnote( this, pFootnote );
}
}
// In column Areas, that not yet reach the Page's border a RearrangeFootnotes is not // useful yet, as the Footnote container has not yet been calculated if( !pSect || !pSect->Growable() )
{ // Validate environment, to avoid oscillation
SwSaveFootnoteHeight aNochmal( pBoss, nDeadLine );
ValidateBodyFrame();
pBoss->RearrangeFootnotes( nDeadLine, true );
ValidateFrame();
} elseif( pSect->IsFootnoteAtEnd() )
{
ValidateBodyFrame();
ValidateFrame();
}
// We just refresh. // The Connect does not do anything useful in this case, but will // mostly throw away the Footnote and create it anew. if( !rInf.IsQuick() )
m_pFrame->ConnectFootnote( pFootnote, nLower );
// We see whether our Append has caused some Footnote to // still be on the Page/Column. If not, our line disappears too, // which will lead to the following undesired behaviour: // Footnote1 still fits onto the Page/Column, but Footnote2 doesn't. // The Footnote2 Reference remains on the Page/Column. The Footnote itself // is on the next Page/Column. // // Exception: If the Page/Column cannot accommodate another line, // the Footnote Reference should be moved to the next one. if( !rFootnote.IsEndNote() )
{
SwSectionFrame *pSct = pBoss->FindSctFrame(); bool bAtSctEnd = pSct && pSct->IsFootnoteAtEnd(); if( FTNPOS_CHAPTER != pDoc->GetFootnoteInfo().m_ePos || bAtSctEnd )
{
SwFrame* pFootnoteCont = pBoss->FindFootnoteCont(); // If the Parent is within an Area, it can only be a Column of this // Area. If this one is not the first Column, we can avoid it. if( !m_pFrame->IsInTab() && ( GetLineNr() > 1 || m_pFrame->GetPrev() ||
( !bAtSctEnd && m_pFrame->GetIndPrev() ) ||
( pSct && pBoss->GetPrev() ) ) )
{ if( !pFootnoteCont )
{
rInf.SetStop( true ); return nullptr;
} else
{ // There must not be any Footnote Containers in column Areas and at the same time on the // Page/Page column if( pSct && !bAtSctEnd ) // Is the Container in a (column) Area?
{
SwFootnoteBossFrame* pTmp = pBoss->FindSctFrame()->FindFootnoteBossFrame( true );
SwFootnoteContFrame* pFootnoteC = pTmp->FindFootnoteCont(); if( pFootnoteC )
{
SwFootnoteFrame* pTmpFrame = static_cast<SwFootnoteFrame*>(pFootnoteC->Lower()); if( pTmpFrame && *pTmpFrame < pFootnote )
{
rInf.SetStop( true ); return nullptr;
}
}
} // Is this the last Line that fits?
SwTwips nTmpBot = Y() + nReal * 2;
if( pScrFrame && nDiff < 0 )
{ if( pFootnoteFrame )
{
SwFootnoteBossFrame *pFootnoteBoss = pFootnoteFrame->FindFootnoteBossFrame(); if( pFootnoteBoss != pBoss )
{ // We're in the last Line and the Footnote has moved // to another Page. We also want to be on that Page!
rInf.SetStop( true ); return nullptr;
}
}
}
}
}
}
} // Finally: Create FootnotePortion and exit ...
SwFootnotePortion *pRet = new SwFootnotePortion(
rFootnote.GetViewNumStr(*pDoc, m_pFrame->getRootFrame()),
pFootnote, nReal );
rInf.SetFootnoteInside( true );
return pRet;
}
/** *TheportionfortheFootnoteNumberingintheFootnoteArea
*/
SwNumberPortion *SwTextFormatter::NewFootnoteNumPortion( SwTextFormatInfo const &rInf ) const
{
OSL_ENSURE( m_pFrame->IsInFootnote() && !m_pFrame->GetIndPrev() && !rInf.IsFootnoteDone(), "This is the wrong place for a ftnnumber" ); if( rInf.GetTextStart() != m_nStart ||
rInf.GetTextStart() != rInf.GetIdx() ) return nullptr;
// #i37142# // Underline style of paragraph font should not be considered // Overline style of paragraph font should not be considered // Weight style of paragraph font should not be considered // Posture style of paragraph font should not be considered // See also #i18463# and SwTextFormatter::NewNumberPortion()
pNumFnt->SetUnderline( LINESTYLE_NONE );
pNumFnt->SetOverline( LINESTYLE_NONE );
pNumFnt->SetItalic( ITALIC_NONE, SwFontScript::Latin );
pNumFnt->SetItalic( ITALIC_NONE, SwFontScript::CJK );
pNumFnt->SetItalic( ITALIC_NONE, SwFontScript::CTL );
pNumFnt->SetWeight( WEIGHT_NORMAL, SwFontScript::Latin );
pNumFnt->SetWeight( WEIGHT_NORMAL, SwFontScript::CJK );
pNumFnt->SetWeight( WEIGHT_NORMAL, SwFontScript::CTL );
// A remark on QuoVadis/ErgoSum: // We use the Font set for the Paragraph for these texts. // Thus, we initialize: // TODO: ResetFont();
FeedInf( rInf );
SeekStartAndChg( rInf, true ); if( GetRedln() && m_pCurr->HasRedline() )
{
std::pair<SwTextNode const*, sal_Int32> const pos(
GetTextFrame()->MapViewToModel(nOffset));
GetRedln()->Seek(*m_pFont, pos.first->GetIndex(), pos.second, 0);
}
// A tricky special case: Flyfrms extend into the Line and are at the // position we want to insert the Quovadis text // Let's see if it is that bad indeed:
SwLinePortion *pPor = m_pCurr->GetFirstPortion();
SwTwips nLastLeft = 0; while( pPor )
{ if ( pPor->IsFlyPortion() )
nLastLeft = static_cast<SwFlyPortion*>(pPor)->GetFix() + static_cast<SwFlyPortion*>(pPor)->Width();
pPor = pPor->GetNextPortion();
}
// The old game all over again: we want the Line to wrap around // at a certain point, so we adjust the width. // nLastLeft is now basically the right margin const SwTwips nOldRealWidth = rInf.RealWidth();
rInf.RealWidth( nOldRealWidth - nLastLeft );
// It's possible that there's a Margin Portion at the end, which would // just cause a lot of trouble, when respanning
pPor = m_pCurr->FindLastPortion();
SwGluePortion *pGlue = pPor->IsMarginPortion() ? static_cast<SwMarginPortion*>(pPor) : nullptr; if( pGlue )
{
pGlue->Height( 0 );
pGlue->Width( 0 );
pGlue->SetLen(TextFrameIndex(0));
pGlue->SetAscent( 0 );
pGlue->SetNextPortion( nullptr );
pGlue->SetFixWidth(0);
}
// Finally: we insert the QuoVadis Portion
pCurrPor = pQuo; while ( pCurrPor )
{ // pPor->Append deletes the pPortion pointer of pPor. // Therefore we have to keep a pointer to the next portion
pQuo = static_cast<SwQuoVadisPortion*>(pCurrPor->GetNextPortion());
pPor->Append( pCurrPor );
pPor = pPor->GetNextPortion();
pCurrPor = pQuo;
}
m_pCurr->Width( m_pCurr->Width() + nQuoWidth );
// And adjust again, due to the adjustment and due to the following special // case: // The DummyUser has set a smaller Font in the Line than the one used // by the QuoVadis text ...
CalcAdjustLine( m_pCurr );
// we reduce footnote size, if we are inside a double line portion if (!m_pOld->GetEscapement() && 50 == m_pOld->GetPropr())
{
Size aSize = m_pFnt->GetSize(m_pFnt->GetActual());
m_pFnt->SetSize(Size(aSize.Width() / 2, aSize.Height() / 2), m_pFnt->GetActual());
}
// set the correct rotation at the footnote font if( const SvxCharRotateItem* pItem = rSet.GetItemIfSet( RES_CHRATR_ROTATE ) )
m_pFnt->SetVertical(pItem->GetValue(),
rInf.GetTextFrame()->IsVertical());
bool SwQuoVadisPortion::Format( SwTextFormatInfo &rInf )
{ // First try; maybe the Text fits
CheckScript( rInf ); bool bFull = SwFieldPortion::Format( rInf );
SetLen(TextFrameIndex(0));
if( bFull )
{ // Second try; we make the String shorter
m_aExpand = "...";
bFull = SwFieldPortion::Format( rInf );
SetLen(TextFrameIndex(0)); if( bFull ) // Third try; we're done: we crush
Width(rInf.Width() - rInf.X());
// No multiline Fields for QuoVadis and ErgoSum if( rInf.GetRest() )
{ delete rInf.GetRest();
rInf.SetRest( nullptr );
}
} return bFull;
}
bool SwQuoVadisPortion::GetExpText( const SwTextSizeInfo &, OUString &rText ) const
{
rText = m_aExpand; // if this QuoVadisPortion has a follow, the follow is responsible for // the ergo text. if ( ! HasFollow() )
rText += m_aErgo; returntrue;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.