607 lines
21 KiB
C++
607 lines
21 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
#include <libxml/xmlwriter.h>
|
|
#include <fmtftn.hxx>
|
|
#include <doc.hxx>
|
|
#include <DocumentContentOperationsManager.hxx>
|
|
#include <IDocumentStylePoolAccess.hxx>
|
|
#include <cntfrm.hxx>
|
|
#include <rootfrm.hxx>
|
|
#include <pagefrm.hxx>
|
|
#include <txtftn.hxx>
|
|
#include <ftnidx.hxx>
|
|
#include <ftninfo.hxx>
|
|
#include <ndtxt.hxx>
|
|
#include <poolfmt.hxx>
|
|
#include <ftnfrm.hxx>
|
|
#include <ndindex.hxx>
|
|
#include <fmtftntx.hxx>
|
|
#include <section.hxx>
|
|
#include <calbck.hxx>
|
|
#include <hints.hxx>
|
|
#include <pam.hxx>
|
|
#include <rtl/ustrbuf.hxx>
|
|
#include <vcl/svapp.hxx>
|
|
#include <unotextrange.hxx>
|
|
#include <osl/diagnose.h>
|
|
#include <unofootnote.hxx>
|
|
|
|
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 )
|
|
return false; // Invalid sequence number.
|
|
if ( rUsedNums.count(requested) )
|
|
return false; // Number already used.
|
|
return true;
|
|
}
|
|
|
|
/// 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( const auto& 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 );
|
|
}
|
|
|
|
}
|
|
|
|
SwFormatFootnote::SwFormatFootnote( bool bEndNote )
|
|
: SfxPoolItem( RES_TXTATR_FTN )
|
|
, m_pTextAttr(nullptr)
|
|
, m_nNumber(0)
|
|
, m_nNumberRLHidden(0)
|
|
, m_bEndNote(bEndNote)
|
|
{
|
|
setNonShareable();
|
|
}
|
|
|
|
void SwFormatFootnote::SetXFootnote(rtl::Reference<SwXFootnote> const& xNote)
|
|
{ m_wXFootnote = xNote.get(); }
|
|
|
|
bool SwFormatFootnote::operator==( const SfxPoolItem& rAttr ) const
|
|
{
|
|
assert(SfxPoolItem::operator==(rAttr));
|
|
return m_nNumber == static_cast<const SwFormatFootnote&>(rAttr).m_nNumber &&
|
|
//FIXME?
|
|
m_aNumber == static_cast<const SwFormatFootnote&>(rAttr).m_aNumber &&
|
|
m_bEndNote == static_cast<const SwFormatFootnote&>(rAttr).m_bEndNote;
|
|
}
|
|
|
|
SwFormatFootnote* SwFormatFootnote::Clone( SfxItemPool* ) const
|
|
{
|
|
SwFormatFootnote* pNew = new SwFormatFootnote;
|
|
pNew->m_aNumber = m_aNumber;
|
|
pNew->m_nNumber = m_nNumber;
|
|
pNew->m_nNumberRLHidden = m_nNumberRLHidden;
|
|
pNew->m_bEndNote = m_bEndNote;
|
|
return pNew;
|
|
}
|
|
|
|
void SwFormatFootnote::InvalidateFootnote()
|
|
{
|
|
if (auto xUnoFootnote = m_wXFootnote.get())
|
|
{
|
|
xUnoFootnote->OnFormatFootnoteDeleted();
|
|
m_wXFootnote.clear();
|
|
}
|
|
}
|
|
|
|
void SwFormatFootnote::SetEndNote( bool b )
|
|
{
|
|
if ( b != m_bEndNote )
|
|
{
|
|
if ( GetTextFootnote() )
|
|
{
|
|
GetTextFootnote()->DelFrames(nullptr);
|
|
}
|
|
m_bEndNote = b;
|
|
}
|
|
}
|
|
|
|
SwFormatFootnote::~SwFormatFootnote()
|
|
{
|
|
}
|
|
|
|
OUString SwFormatFootnote::GetFootnoteText(SwRootFrame const& rLayout) const
|
|
{
|
|
OUStringBuffer buf;
|
|
if( m_pTextAttr->GetStartNode() )
|
|
{
|
|
SwNodeIndex aIdx( *m_pTextAttr->GetStartNode(), 1 );
|
|
SwContentNode* pCNd = aIdx.GetNode().GetTextNode();
|
|
if( !pCNd )
|
|
pCNd = SwNodes::GoNext(&aIdx);
|
|
|
|
if( pCNd->IsTextNode() ) {
|
|
buf.append(static_cast<SwTextNode*>(pCNd)->GetExpandText(&rLayout));
|
|
|
|
++aIdx;
|
|
while ( !aIdx.GetNode().IsEndNode() ) {
|
|
if ( aIdx.GetNode().IsTextNode() )
|
|
{
|
|
buf.append(" " + aIdx.GetNode().GetTextNode()->GetExpandText(&rLayout));
|
|
}
|
|
++aIdx;
|
|
}
|
|
}
|
|
}
|
|
return buf.makeStringAndClear();
|
|
}
|
|
|
|
/// return the view string of the foot/endnote
|
|
OUString SwFormatFootnote::GetViewNumStr(const SwDoc& rDoc,
|
|
SwRootFrame const*const pLayout, bool bInclStrings) const
|
|
{
|
|
OUString sRet( GetNumStr() );
|
|
if( sRet.isEmpty() )
|
|
{
|
|
// in this case the number is needed, get it via SwDoc's FootnoteInfo
|
|
bool bMakeNum = true;
|
|
const SwSectionNode* pSectNd = m_pTextAttr
|
|
? SwUpdFootnoteEndNtAtEnd::FindSectNdWithEndAttr( *m_pTextAttr )
|
|
: nullptr;
|
|
sal_uInt16 const nNumber(pLayout && pLayout->IsHideRedlines()
|
|
? GetNumberRLHidden()
|
|
: GetNumber());
|
|
|
|
if( pSectNd )
|
|
{
|
|
const SwFormatFootnoteEndAtTextEnd& rFootnoteEnd = static_cast<const SwFormatFootnoteEndAtTextEnd&>(
|
|
pSectNd->GetSection().GetFormat()->GetFormatAttr(
|
|
IsEndNote() ?
|
|
o3tl::narrowing<sal_uInt16>(RES_END_AT_TXTEND) :
|
|
o3tl::narrowing<sal_uInt16>(RES_FTN_AT_TXTEND) ) );
|
|
|
|
if( FTNEND_ATTXTEND_OWNNUMANDFMT == rFootnoteEnd.GetValue() )
|
|
{
|
|
bMakeNum = false;
|
|
sRet = rFootnoteEnd.GetSwNumType().GetNumStr( nNumber );
|
|
if( bInclStrings )
|
|
{
|
|
sRet = rFootnoteEnd.GetPrefix() + sRet + rFootnoteEnd.GetSuffix();
|
|
}
|
|
}
|
|
}
|
|
|
|
if( bMakeNum )
|
|
{
|
|
const SwEndNoteInfo* pInfo;
|
|
if( IsEndNote() )
|
|
pInfo = &rDoc.GetEndNoteInfo();
|
|
else
|
|
pInfo = &rDoc.GetFootnoteInfo();
|
|
sRet = pInfo->m_aFormat.GetNumStr( nNumber );
|
|
if( bInclStrings )
|
|
{
|
|
sRet = pInfo->GetPrefix() + sRet + pInfo->GetSuffix();
|
|
}
|
|
}
|
|
}
|
|
return sRet;
|
|
}
|
|
|
|
rtl::Reference<SwXTextRange> SwFormatFootnote::getAnchor(SwDoc& rDoc) const
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
if (!m_pTextAttr)
|
|
return {};
|
|
SwPaM aPam(m_pTextAttr->GetTextNode(), m_pTextAttr->GetStart());
|
|
aPam.SetMark();
|
|
aPam.GetMark()->AdjustContent(+1);
|
|
rtl::Reference<SwXTextRange> xRet =
|
|
SwXTextRange::CreateXTextRange(rDoc, *aPam.Start(), aPam.End());
|
|
return xRet;
|
|
}
|
|
|
|
void SwFormatFootnote::dumpAsXml(xmlTextWriterPtr pWriter) const
|
|
{
|
|
(void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwFormatFootnote"));
|
|
(void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
|
|
(void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("text-attr"), "%p", m_pTextAttr);
|
|
(void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("endnote"),
|
|
BAD_CAST(OString::boolean(m_bEndNote).getStr()));
|
|
|
|
SfxPoolItem::dumpAsXml(pWriter);
|
|
|
|
(void)xmlTextWriterEndElement(pWriter);
|
|
}
|
|
|
|
SwTextFootnote::SwTextFootnote(
|
|
const SfxPoolItemHolder& rAttr,
|
|
sal_Int32 nStartPos )
|
|
: SwTextAttr( rAttr, nStartPos )
|
|
, m_pTextNode( nullptr )
|
|
, m_nSeqNo( USHRT_MAX )
|
|
{
|
|
SwFormatFootnote& rSwFormatFootnote(static_cast<SwFormatFootnote&>(GetAttr()));
|
|
rSwFormatFootnote.m_pTextAttr = this;
|
|
SetHasDummyChar(true);
|
|
}
|
|
|
|
SwTextFootnote::~SwTextFootnote()
|
|
{
|
|
SetStartNode( nullptr );
|
|
}
|
|
|
|
void SwTextFootnote::SetStartNode( const SwNodeIndex *pNewNode, bool bDelNode )
|
|
{
|
|
if( pNewNode )
|
|
{
|
|
m_oStartNode = *pNewNode;
|
|
}
|
|
else if ( 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::SetNumber(const sal_uInt16 nNewNum,
|
|
sal_uInt16 const nNumberRLHidden, const OUString &sNumStr)
|
|
{
|
|
SwFormatFootnote& rFootnote = const_cast<SwFormatFootnote&>(GetFootnote());
|
|
|
|
rFootnote.m_aNumber = sNumStr;
|
|
if ( sNumStr.isEmpty() )
|
|
{
|
|
rFootnote.m_nNumber = nNewNum;
|
|
rFootnote.m_nNumberRLHidden = nNumberRLHidden;
|
|
}
|
|
InvalidateNumberInLayout();
|
|
}
|
|
|
|
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;
|
|
|
|
m_pTextNode->GetDoc().GetDocumentContentOperationsManager().CopyWithFlyInFly(aRg, aEnd.GetNode());
|
|
|
|
// 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;
|
|
|
|
if( GetFootnote().IsEndNote() )
|
|
{
|
|
pInfo = &rNodes.GetDoc().GetEndNoteInfo();
|
|
nPoolId = RES_POOLCOLL_ENDNOTE;
|
|
}
|
|
else
|
|
{
|
|
pInfo = &rNodes.GetDoc().GetFootnoteInfo();
|
|
nPoolId = RES_POOLCOLL_FOOTNOTE;
|
|
}
|
|
|
|
pFormatColl = pInfo->GetFootnoteTextColl();
|
|
if( nullptr == pFormatColl )
|
|
pFormatColl = rNodes.GetDoc().getIDocumentStylePoolAccess().GetTextCollFromPool( nPoolId );
|
|
|
|
SwStartNode* pSttNd = rNodes.MakeTextSection( rNodes.GetEndOfInserts(),
|
|
SwFootnoteStartNode, pFormatColl );
|
|
m_oStartNode = *pSttNd;
|
|
}
|
|
|
|
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;
|
|
|
|
SwNodeIndex aIdx( *m_oStartNode );
|
|
SwContentNode* pCNd = SwNodes::GoNext(&aIdx);
|
|
if( !pCNd )
|
|
return;
|
|
|
|
SwIterator<SwContentFrame, SwContentNode, sw::IteratorMode::UnwrapMulti> aIter(*pCNd);
|
|
for( SwContentFrame* pFnd = aIter.First(); pFnd; pFnd = aIter.Next() )
|
|
{
|
|
if( pRoot != pFnd->getRootFrame() && pRoot )
|
|
continue;
|
|
SwPageFrame* pPage = pFnd->FindPageFrame();
|
|
|
|
SwFrame *pFrame = pFnd->GetUpper();
|
|
while ( pFrame && !pFrame->IsFootnoteFrame() )
|
|
pFrame = pFrame->GetUpper();
|
|
|
|
SwFootnoteFrame *pFootnote = static_cast<SwFootnoteFrame*>(pFrame);
|
|
while ( pFootnote && pFootnote->GetMaster() )
|
|
pFootnote = pFootnote->GetMaster();
|
|
OSL_ENSURE( pFootnote->GetAttr() == this, "Footnote mismatch error." );
|
|
|
|
while ( pFootnote )
|
|
{
|
|
SwFootnoteFrame *pFoll = pFootnote->GetFollow();
|
|
pFootnote->Cut();
|
|
SwFrame::DestroyFrame(pFootnote);
|
|
pFootnote = pFoll;
|
|
}
|
|
|
|
// #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;
|
|
|
|
SwDoc& rDoc = m_pTextNode->GetDoc();
|
|
if( rDoc.IsInReading() )
|
|
return;
|
|
|
|
std::set<sal_uInt16> aUsedNums;
|
|
std::vector<SwTextFootnote*> badRefNums;
|
|
::lcl_FillUsedFootnoteRefNumbers(rDoc, this, aUsedNums, badRefNums);
|
|
if ( ::lcl_IsRefNumAvailable(aUsedNums, m_nSeqNo) )
|
|
return;
|
|
std::vector<sal_uInt16> unused;
|
|
::lcl_FillUnusedSeqRefNums(unused, aUsedNums, 1);
|
|
m_nSeqNo = unused[0];
|
|
}
|
|
|
|
/// 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];
|
|
}
|
|
}
|
|
|
|
void SwTextFootnote::CheckCondColl()
|
|
{
|
|
if( GetStartNode() )
|
|
static_cast<SwStartNode&>(GetStartNode()->GetNode()).CheckSectionCondColl();
|
|
}
|
|
|
|
void SwTextFootnote::dumpAsXml(xmlTextWriterPtr pWriter) const
|
|
{
|
|
(void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwTextFootnote"));
|
|
SwTextAttr::dumpAsXml(pWriter);
|
|
|
|
if (m_oStartNode)
|
|
{
|
|
(void)xmlTextWriterStartElement(pWriter, BAD_CAST("m_oStartNode"));
|
|
(void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("index"),
|
|
BAD_CAST(OString::number(sal_Int32(m_oStartNode->GetIndex())).getStr()));
|
|
(void)xmlTextWriterEndElement(pWriter);
|
|
}
|
|
if (m_pTextNode)
|
|
{
|
|
(void)xmlTextWriterStartElement(pWriter, BAD_CAST("m_pTextNode"));
|
|
(void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("index"),
|
|
BAD_CAST(OString::number(sal_Int32(m_pTextNode->GetIndex())).getStr()));
|
|
(void)xmlTextWriterEndElement(pWriter);
|
|
}
|
|
(void)xmlTextWriterStartElement(pWriter, BAD_CAST("m_nSeqNo"));
|
|
(void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"),
|
|
BAD_CAST(OString::number(m_nSeqNo).getStr()));
|
|
(void)xmlTextWriterEndElement(pWriter);
|
|
|
|
(void)xmlTextWriterEndElement(pWriter);
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|