namespace { /// Get a sorted list of the used footnote reference numbers. /// @param[in] rDoc The active document. /// @param[in] pExclude A footnote whose reference number should be excluded from the set. /// @param[out] rUsedRef The set of used reference numbers. /// @param[out] rInvalid A returned list of all items that had an invalid reference number. void lcl_FillUsedFootnoteRefNumbers(SwDoc &rDoc,
SwTextFootnote const *pExclude,
std::set<sal_uInt16> &rUsedRef,
std::vector<SwTextFootnote*> &rInvalid)
{
SwFootnoteIdxs& ftnIdxs = rDoc.GetFootnoteIdxs();
rInvalid.clear();
for( size_t n = 0; n < ftnIdxs.size(); ++n )
{
SwTextFootnote* pTextFootnote = ftnIdxs[ n ]; if ( pTextFootnote != pExclude )
{ if ( USHRT_MAX == pTextFootnote->GetSeqRefNo() )
{
rInvalid.push_back(pTextFootnote);
} else
{
rUsedRef.insert( pTextFootnote->GetSeqRefNo() );
}
}
}
}
/// Check whether a requested reference number is available. /// @param[in] rUsedNums Set of used reference numbers. /// @param[in] requested The requested reference number. /// @returns true if the number is available, false if not. bool lcl_IsRefNumAvailable(std::set<sal_uInt16> const &rUsedNums,
sal_uInt16 requested)
{ if ( USHRT_MAX == requested ) returnfalse; // Invalid sequence number. if ( rUsedNums.count(requested) ) returnfalse; // Number already used. returntrue;
}
/// Get the first few unused sequential reference numbers. /// @param[out] rLowestUnusedNums The lowest unused sequential reference numbers. /// @param[in] rUsedNums The set of used sequential reference numbers. /// @param[in] numRequired The number of reference number required. void lcl_FillUnusedSeqRefNums(std::vector<sal_uInt16> &rLowestUnusedNums, const std::set<sal_uInt16> &rUsedNums,
size_t numRequired)
{ if (!numRequired) return;
rLowestUnusedNums.reserve(numRequired);
sal_uInt16 newNum = 0; //Start by using numbers from gaps in rUsedNums for( constauto& rNum : rUsedNums )
{ while ( newNum < rNum )
{
rLowestUnusedNums.push_back( newNum++ ); if ( --numRequired == 0) return;
}
newNum++;
} //Filled in all gaps. Fill the rest of the list with new numbers. do
{
rLowestUnusedNums.push_back( newNum++ );
} while ( --numRequired > 0 );
}
void SwTextFootnote::SetStartNode( const SwNodeIndex *pNewNode, bool bDelNode )
{ if( pNewNode )
{
m_oStartNode = *pNewNode;
} elseif ( m_oStartNode )
{ // need to do 2 things: // 1) unregister footnotes at their pages // 2) delete the footnote section in the Inserts of the nodes-array
SwDoc* pDoc; if ( m_pTextNode )
{
pDoc = &m_pTextNode->GetDoc();
} else
{ //JP 27.01.97: the sw3-Reader creates a StartNode but the // attribute isn't anchored in the TextNode yet. // If it is deleted (e.g. Insert File with footnote // inside fly frame), the content must also be deleted.
pDoc = &m_oStartNode->GetNodes().GetDoc();
}
// If called from ~SwDoc(), must not delete the footnote nodes, // and not necessary to delete the footnote frames. if( !pDoc->IsInDtor() )
{ if( bDelNode )
{ // 2) delete the section for the footnote nodes // it's possible that the Inserts have already been deleted (how???)
pDoc->getIDocumentContentOperations().DeleteSection( &m_oStartNode->GetNode() );
} else // If the nodes are not deleted, their frames must be removed // from the page (deleted), there is nothing else that deletes // them (particularly not Undo)
DelFrames( nullptr );
}
m_oStartNode.reset();
// remove the footnote from the SwDoc's array for( size_t n = 0; n < pDoc->GetFootnoteIdxs().size(); ++n ) if( this == pDoc->GetFootnoteIdxs()[n] )
{
pDoc->GetFootnoteIdxs().erase( pDoc->GetFootnoteIdxs().begin() + n ); // if necessary, update following footnotes if( !pDoc->IsInDtor() && n < pDoc->GetFootnoteIdxs().size() )
{
pDoc->GetFootnoteIdxs().UpdateFootnote( pDoc->GetFootnoteIdxs()[n]->GetTextNode() );
} break;
}
}
}
void SwTextFootnote::InvalidateNumberInLayout()
{
assert(m_pTextNode);
SwNodes &rNodes = m_pTextNode->GetDoc().GetNodes(); const sw::LegacyModifyHint aHint(nullptr, &GetFootnote());
m_pTextNode->TriggerNodeUpdate(aHint); if ( m_oStartNode )
{ // must iterate over all TextNodes because of footnotes on other pages
SwNodeOffset nSttIdx = m_oStartNode->GetIndex() + 1;
SwNodeOffset nEndIdx = m_oStartNode->GetNode().EndOfSectionIndex(); for( ; nSttIdx < nEndIdx; ++nSttIdx )
{
SwNode* pNd; if( ( pNd = rNodes[ nSttIdx ] )->IsTextNode() ) static_cast<SwTextNode*>(pNd)->TriggerNodeUpdate(aHint);
}
}
}
void SwTextFootnote::CopyFootnote(
SwTextFootnote & rDest,
SwTextNode & rDestNode ) const
{ if (m_oStartNode && !rDest.GetStartNode())
{ // dest missing node section? create it here! // (happens in SwTextNode::CopyText if pDest == this)
rDest.MakeNewTextSection( rDestNode.GetNodes() );
} if (m_oStartNode && rDest.GetStartNode())
{ // footnotes not necessarily in same document!
SwDoc& rDstDoc = rDestNode.GetDoc();
SwNodes &rDstNodes = rDstDoc.GetNodes();
// copy only the content of the section
SwNodeRange aRg( m_oStartNode->GetNode(), SwNodeOffset(1),
*m_oStartNode->GetNode().EndOfSectionNode() );
// insert at the end of rDest, i.e., the nodes are appended. // nDestLen contains number of ContentNodes in rDest _before_ copy.
SwNodeIndex aStart( *(rDest.GetStartNode()) );
SwNodeIndex aEnd( *aStart.GetNode().EndOfSectionNode() );
SwNodeOffset nDestLen = aEnd.GetIndex() - aStart.GetIndex() - 1;
// in case the destination section was not empty, delete the old nodes // before: Src: SxxxE, Dst: SnE // now: Src: SxxxE, Dst: SnxxxE // after: Src: SxxxE, Dst: SxxxE
++aStart;
rDstNodes.Delete( aStart, nDestLen );
}
// also copy user defined number string if( !GetFootnote().m_aNumber.isEmpty() )
{ const_cast<SwFormatFootnote &>(rDest.GetFootnote()).m_aNumber = GetFootnote().m_aNumber;
}
}
/// create a new nodes-array section for the footnote void SwTextFootnote::MakeNewTextSection( SwNodes& rNodes )
{ if ( m_oStartNode ) return;
// set the footnote style on the SwTextNode
SwTextFormatColl *pFormatColl; const SwEndNoteInfo* pInfo;
sal_uInt16 nPoolId;
void SwTextFootnote::DelFrames(SwRootFrame const*const pRoot)
{ // delete the FootnoteFrames from the pages
OSL_ENSURE( m_pTextNode, "SwTextFootnote: where is my TextNode?" ); if ( !m_pTextNode ) return;
bool bFrameFnd = false;
{
SwIterator<SwContentFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*m_pTextNode); for( SwContentFrame* pFnd = aIter.First(); pFnd; pFnd = aIter.Next() )
{ if( pRoot != pFnd->getRootFrame() && pRoot ) continue;
SwPageFrame* pPage = pFnd->FindPageFrame(); if( pPage )
{ // note: we have found the correct frame only if the footnote // was actually removed; in case this is called from // SwTextFrame::DestroyImpl(), then that frame isn't connected // to SwPageFrame any more, and RemoveFootnote on any follow // must not prevent the fall-back to the !bFrameFnd code.
bFrameFnd = pPage->RemoveFootnote(pFnd, this);
}
}
} //JP 13.05.97: if the layout is deleted before the footnotes are deleted, // try to delete the footnote's frames by another way if ( bFrameFnd || !m_oStartNode ) return;
// #i20556# During hiding of a section, the connection // to the layout is already lost. pPage may be 0: if ( pPage )
pPage->UpdateFootnoteNum();
}
}
/// Set the sequence number for the current footnote. /// @returns The new sequence number or USHRT_MAX if invalid. void SwTextFootnote::SetSeqRefNo()
{ if( !m_pTextNode ) return;
/// Set a unique sequential reference number for every footnote in the document. /// @param[in] rDoc The document to be processed. void SwTextFootnote::SetUniqueSeqRefNo( SwDoc& rDoc )
{
std::set<sal_uInt16> aUsedNums;
std::vector<SwTextFootnote*> badRefNums;
::lcl_FillUsedFootnoteRefNumbers(rDoc, nullptr, aUsedNums, badRefNums);
std::vector<sal_uInt16> aUnused;
::lcl_FillUnusedSeqRefNums(aUnused, aUsedNums, badRefNums.size());
for (size_t i = 0; i < badRefNums.size(); ++i)
{
badRefNums[i]->m_nSeqNo = aUnused[i];
}
}
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.