/* -*- 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 .
*/
// We may have some flys anchored to paragraph where we inserting. // These flys will be saved in pFrameFormats array (only flys which exist BEFORE insertion!) // Then in SwUndoInserts::SetInsertRange the flys saved in pFrameFormats will NOT create Undos. // m_FlyUndos will only be filled with newly inserted flys.
m_pFrameFormats = sw::GetFlysAnchoredAt(rDoc, m_nSttNode, true);
} // consider Redline if( rDoc.getIDocumentRedlineAccess().IsRedlineOn() )
{
m_pRedlineData.reset( new SwRedlineData( RedlineType::Insert, rDoc.getIDocumentRedlineAccess().GetRedlineAuthor() ) );
SetRedlineFlags( rDoc.getIDocumentRedlineAccess().GetRedlineFlags() );
}
}
// This method does two things: // 1. Adjusts SwUndoRng members, required for Undo. // Members are: // SwUndoRng::nSttNode - all nodes starting from this node will be deleted during Undo (in SwUndoInserts::UndoImpl) // SwUndoRng::nSttContent - corresponding content index in SwUndoRng::nSttNode // SwUndoRng::nEndNode - end node for deletion // SwUndoRng::nEndContent - end content index // All these members are filled in during construction of SwUndoInserts instance, and can be adjusted using this method // // 2. Fills in m_FlyUndos array with flys anchored ONLY to first and last paragraphs (first == rPam.Start(), last == rPam.End()) // Flys, anchored to any paragraph, but not first and last, are handled by DelContentIndex (see SwUndoInserts::UndoImpl) and are not stored in m_FlyUndos.
// Fill m_FlyUndos with flys anchored to first and last paragraphs
if( !bScanFlys) return;
// than collect all new Flys
SwDoc& rDoc = rPam.GetDoc(); const size_t nArrLen = rDoc.GetSpzFrameFormats()->size(); for( size_t n = 0; n < nArrLen; ++n )
{
SwFrameFormat* pFormat = (*rDoc.GetSpzFrameFormats())[n];
SwFormatAnchor const*const pAnchor = &pFormat->GetAnchor(); if (IsCreateUndoForNewFly(*pAnchor, m_nSttNode, m_nEndNode))
{
std::vector<SwFrameFormat*>::iterator it; if( !m_pFrameFormats ||
m_pFrameFormats->end() == ( it = std::find( m_pFrameFormats->begin(), m_pFrameFormats->end(), pFormat ) ) )
{
std::shared_ptr<SwUndoInsLayFormat> const pFlyUndo =
std::make_shared<SwUndoInsLayFormat>(pFormat, SwNodeOffset(0), 0);
m_FlyUndos.push_back(pFlyUndo);
} else
m_pFrameFormats->erase( it );
}
}
m_pFrameFormats.reset();
}
/** This is not the same as IsDestroyFrameAnchoredAtChar() and intentionally so: because the SwUndoInserts::UndoImpl() must remove the flys at the start/end position that were inserted but not the ones at the start/insert position that were already there; handle all at-char flys at start/end node like this, even if they're not *on* the start/end position, because it makes it easier to ensure that the Undo/Redo run in inverse order.
*/ bool SwUndoInserts::IsCreateUndoForNewFly(SwFormatAnchor const& rAnchor,
SwNodeOffset const nStartNode, SwNodeOffset const nEndNode)
{
assert(nStartNode <= nEndNode);
if (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PAGE)
{ returntrue; // needed for SwUndoInserts/SwReader::Read()
}
if (m_pFrameFormats)
{
(void)xmlTextWriterStartElement(pWriter, BAD_CAST("m_pFrameFormats")); for (constauto& pFormat : *m_pFrameFormats)
{
pFormat->dumpAsXml(pWriter);
}
(void)xmlTextWriterEndElement(pWriter);
}
if (!m_FlyUndos.empty())
{
(void)xmlTextWriterStartElement(pWriter, BAD_CAST("m_FlyUndos")); for (constauto& pFly : m_FlyUndos)
{
pFly->dumpAsXml(pWriter);
}
(void)xmlTextWriterEndElement(pWriter);
}
(void)xmlTextWriterEndElement(pWriter);
}
SwUndoInserts::~SwUndoInserts()
{ if (m_oUndoNodeIndex) // delete also the section from UndoNodes array
{ // Insert saves content in IconSection
SwNodes& rUNds = m_oUndoNodeIndex->GetNodes();
rUNds.Delete(*m_oUndoNodeIndex,
rUNds.GetEndOfExtras().GetIndex() - m_oUndoNodeIndex->GetIndex());
m_oUndoNodeIndex.reset();
}
m_pFrameFormats.reset();
m_pRedlineData.reset();
}
// Undo Insert operation // It's important to note that Undo stores absolute node indexes. I.e. if during insertion, you insert nodes 31 to 33, // during Undo nodes with indices from 31 to 33 will be deleted. Undo doesn't check that nodes 31 to 33 are the same nodes which were inserted. // It just deletes them. // This may seem as bad programming practice, but Undo actions are strongly ordered. If you change your document in some way, a new Undo action is added. // During Undo most recent actions will be executed first. So during execution of particular Undo action indices will be correct. // But storing absolute indices leads to crashes if some action in Undo fails to roll back some modifications.
// Has following main steps: // 1. m_FlyUndos removes flys anchored to first and last paragraph in Undo range. // This array may be empty. // 2. DelContentIndex to delete footnotes, flys, bookmarks (see comment for this function) // Deleted flys are stored in pHistory array. // First and last paragraphs flys are not deleted by DelContentIndex! // For flys anchored to last paragraph, DelContentIndex re-anchors them to // the last paragraph that will remain after Undo. // 3. MoveToUndoNds moves nodes to Undo nodes array and removes them from document. // 4. Lastly (starting from if(pTextNode)), text from last paragraph is joined to last remaining paragraph and FormatColl for last paragraph is restored. // Format coll for last paragraph is removed during execution of UndoImpl
// if Point and Mark are different text nodes so a JoinNext has to be done bool bJoinNext = m_nSttNode != m_nEndNode &&
rPam.GetMark()->GetNode().GetTextNode() &&
rPam.GetPoint()->GetNode().GetTextNode();
// Is there any content? (loading from template does not have content) if( m_nSttNode != m_nEndNode || m_nSttContent != m_nEndContent )
{ if( m_nSttNode != m_nEndNode )
{
SwTextNode* pTextNd = rDoc.GetNodes()[ m_nEndNode ]->GetTextNode(); if (pTextNd && pTextNd->GetText().getLength() == m_nEndContent)
m_pLastNodeColl = pTextNd->GetTextColl();
}
// tdf#128739 correct cursors but do not delete bookmarks yet
::PaMCorrAbs(rPam, *rPam.End());
SetPaM(rPam);
}
// ... for consistency with the Insert File code in shellio.cxx, which // creates separate SwUndoInsLayFormat for mysterious reasons, do this // *before* anything else: // after SetPaM but before MoveToUndoNds and DelContentIndex. // note: there isn't an order dep wrt. initial Copy action because Undo // overwrites the indexes but there is wrt. Redo because that uses the // indexes if (!m_FlyUndos.empty())
{
SwNodeOffset nTmp = rPam.GetPoint()->GetNodeIndex(); for (size_t n = m_FlyUndos.size(); 0 < n; --n)
{
m_FlyUndos[ n-1 ]->UndoImpl(rContext);
}
m_nNodeDiff += nTmp - rPam.GetPoint()->GetNodeIndex();
}
if (m_nSttNode != m_nEndNode || m_nSttContent != m_nEndContent)
{ // are there Footnotes or ContentFlyFrames in text?
m_nSetPos = m_pHistory->Count();
SwNodeOffset nTmp = rPam.GetMark()->GetNodeIndex();
DelContentIndex(*rPam.GetMark(), *rPam.GetPoint(),
DelContentType::AllMask|DelContentType::ExcludeFlyAtStartEnd);
m_nNodeDiff += nTmp - rPam.GetMark()->GetNodeIndex(); if( *rPam.GetPoint() != *rPam.GetMark() )
{
m_oUndoNodeIndex.emplace(rDoc.GetNodes().GetEndOfContent());
MoveToUndoNds(rPam, &*m_oUndoNodeIndex);
// at-char anchors post SplitNode are on index 0 of 2nd node and will // remain there - move them back to the start (end would also work?) if (pFlysAtInsPos && isMoveFlyAnchors)
{ for (SwFrameFormat * pFly : *pFlysAtInsPos)
{
SwFormatAnchor const*const pAnchor = &pFly->GetAnchor(); if (pAnchor->GetAnchorId() == RndStdIds::FLY_AT_CHAR)
{
SwFormatAnchor anchor(*pAnchor);
anchor.SetAnchor( rPam.GetMark() );
pFly->SetFormatAttr(anchor);
}
}
}
}
// tdf#108124 the SwHistoryChangeFlyAnchor/SwHistoryFlyCnt must run before // m_FlyUndos as they were created by DelContentIndex()
m_pHistory->Rollback( rDoc, m_nSetPos );
// tdf#108124 (10/25/2017) // During UNDO we call SwUndoInsLayFormat::UndoImpl in reverse order, // firstly for m_FlyUndos[ m_FlyUndos.size()-1 ], etc. // As absolute node index of fly stored in SwUndoFlyBase::nNdPgPos we // should recover from Undo in direct order (last should be recovered first) // During REDO we should recover Flys (Images) in direct order, // firstly m_FlyUndos[0], then with m_FlyUndos[1] index, etc.
for (size_t n = 0; m_FlyUndos.size() > n; ++n)
{
m_FlyUndos[n]->RedoImpl(rContext);
}
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.