LCOV - code coverage report
Current view: top level - libreoffice/sw/source/core/doc - docbm.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 279 794 35.1 %
Date: 2012-12-17 Functions: 43 69 62.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <MarkManager.hxx>
      21             : #include <bookmrk.hxx>
      22             : #include <boost/bind.hpp>
      23             : #include <cntfrm.hxx>
      24             : #include <crossrefbookmark.hxx>
      25             : #include <dcontact.hxx>
      26             : #include <doc.hxx>
      27             : #include <docary.hxx>
      28             : #include <xmloff/odffields.hxx>
      29             : #include <editsh.hxx>
      30             : #include <fmtanchr.hxx>
      31             : #include <frmfmt.hxx>
      32             : #include <functional>
      33             : #include <hintids.hxx>
      34             : #include <mvsave.hxx>
      35             : #include <ndtxt.hxx>
      36             : #include <node.hxx>
      37             : #include <pam.hxx>
      38             : #include <redline.hxx>
      39             : #include <rolbck.hxx>
      40             : #include <rtl/ustrbuf.hxx>
      41             : #include <rtl/ustring.hxx>
      42             : #include <sal/types.h>
      43             : #include <sortedobjs.hxx>
      44             : #include <sfx2/linkmgr.hxx>
      45             : #include <swserv.hxx>
      46             : #include <swundo.hxx>
      47             : #include <unocrsr.hxx>
      48             : #include <viscrs.hxx>
      49             : #include <stdio.h>
      50             : 
      51             : 
      52             : using namespace ::std;
      53             : using namespace ::boost;
      54             : using namespace ::sw::mark;
      55             : 
      56             : namespace
      57             : {
      58        1148 :     static bool lcl_GreaterThan( const SwPosition& rPos, const SwNodeIndex& rNdIdx, const SwIndex* pIdx )
      59             :     {
      60        1148 :         return pIdx ? ( rPos.nNode > rNdIdx || ( rPos.nNode == rNdIdx && rPos.nContent >= pIdx->GetIndex() )) : rPos.nNode >= rNdIdx;
      61             :     }
      62             : 
      63         574 :     static bool lcl_Lower( const SwPosition& rPos, const SwNodeIndex& rNdIdx, const SwIndex* pIdx )
      64             :     {
      65         574 :         return rPos.nNode < rNdIdx || ( pIdx && rPos.nNode == rNdIdx && rPos.nContent < pIdx->GetIndex() );
      66             :     }
      67             : 
      68        5704 :     static bool lcl_MarkOrderingByStart(const IDocumentMarkAccess::pMark_t& rpFirst,
      69             :         const IDocumentMarkAccess::pMark_t& rpSecond)
      70             :     {
      71        5704 :         return rpFirst->GetMarkStart() < rpSecond->GetMarkStart();
      72             :     }
      73             : 
      74           0 :     static bool lcl_MarkOrderingByEnd(const IDocumentMarkAccess::pMark_t& rpFirst,
      75             :         const IDocumentMarkAccess::pMark_t& rpSecond)
      76             :     {
      77           0 :         return rpFirst->GetMarkEnd() < rpSecond->GetMarkEnd();
      78             :     }
      79             : 
      80        4396 :     static void lcl_InsertMarkSorted(IDocumentMarkAccess::container_t& io_vMarks,
      81             :         const IDocumentMarkAccess::pMark_t& pMark)
      82             :     {
      83             :         io_vMarks.insert(
      84             :             lower_bound(
      85             :                 io_vMarks.begin(),
      86             :                 io_vMarks.end(),
      87             :                 pMark,
      88             :                 &lcl_MarkOrderingByStart),
      89        4396 :             pMark);
      90        4396 :     }
      91             : 
      92             :     SAL_WNODEPRECATED_DECLARATIONS_PUSH
      93           0 :     static inline auto_ptr<SwPosition> lcl_PositionFromCntntNode(SwCntntNode * const pCntntNode, const bool bAtEnd=false)
      94             :     {
      95           0 :         auto_ptr<SwPosition> pResult(new SwPosition(*pCntntNode));
      96           0 :         pResult->nContent.Assign(pCntntNode, bAtEnd ? pCntntNode->Len() : 0);
      97           0 :         return pResult;
      98             :     }
      99             :     SAL_WNODEPRECATED_DECLARATIONS_POP
     100             : 
     101             :     // return a position at the begin of rEnd, if it is a CntntNode
     102             :     // else set it to the begin of the Node after rEnd, if there is one
     103             :     // else set it to the end of the node before rStt
     104             :     // else set it to the CntntNode of the Pos outside the Range
     105             :     SAL_WNODEPRECATED_DECLARATIONS_PUSH
     106           0 :     static inline auto_ptr<SwPosition> lcl_FindExpelPosition(const SwNodeIndex& rStt,
     107             :         const SwNodeIndex& rEnd,
     108             :         const SwPosition& rOtherPosition)
     109             :     {
     110           0 :         SwCntntNode * pNode = rEnd.GetNode().GetCntntNode();
     111           0 :         SwNodeIndex aStt = SwNodeIndex(rStt);
     112           0 :         SwNodeIndex aEnd = SwNodeIndex(rEnd);
     113           0 :         bool bAtEnd = false;
     114           0 :         if(!pNode)
     115           0 :             pNode = rEnd.GetNodes().GoNext(&aEnd), bAtEnd = false;
     116           0 :         if(!pNode)
     117           0 :             pNode = rStt.GetNodes().GoPrevious(&aStt), bAtEnd = true;
     118           0 :         if(pNode)
     119           0 :             return lcl_PositionFromCntntNode(pNode, bAtEnd);
     120           0 :         return auto_ptr<SwPosition>(new SwPosition(rOtherPosition));
     121             :     }
     122             :     SAL_WNODEPRECATED_DECLARATIONS_POP
     123             : 
     124           0 :     static IMark* lcl_getMarkAfter(const IDocumentMarkAccess::container_t& rMarks, const SwPosition& rPos)
     125             :     {
     126             :         IDocumentMarkAccess::const_iterator_t pMarkAfter = upper_bound(
     127             :             rMarks.begin(),
     128             :             rMarks.end(),
     129             :             rPos,
     130           0 :             boost::bind(&IMark::StartsAfter, _2, _1)); // finds the first that is starting after
     131           0 :         if(pMarkAfter == rMarks.end()) return NULL;
     132           0 :         return pMarkAfter->get();
     133             :     };
     134             : 
     135           0 :     static IMark* lcl_getMarkBefore(const IDocumentMarkAccess::container_t& rMarks, const SwPosition& rPos)
     136             :     {
     137             :         // candidates from which to choose the mark before
     138           0 :         IDocumentMarkAccess::container_t vCandidates;
     139             :         // no need to consider marks starting after rPos
     140             :         IDocumentMarkAccess::const_iterator_t pCandidatesEnd = upper_bound(
     141             :             rMarks.begin(),
     142             :             rMarks.end(),
     143             :             rPos,
     144           0 :             boost::bind(&IMark::StartsAfter, _2, _1));
     145           0 :         vCandidates.reserve(pCandidatesEnd - rMarks.begin());
     146             :         // only marks ending before are candidates
     147             :         remove_copy_if(
     148             :             rMarks.begin(),
     149             :             pCandidatesEnd,
     150             :             back_inserter(vCandidates),
     151           0 :             boost::bind(logical_not<bool>(), boost::bind(&IMark::EndsBefore, _1, rPos)));
     152             :         // no candidate left => we are in front of the first mark or there are none
     153           0 :         if(!vCandidates.size()) return NULL;
     154             :         // return the highest (last) candidate using mark end ordering
     155           0 :         return max_element(vCandidates.begin(), vCandidates.end(), &lcl_MarkOrderingByEnd)->get();
     156             :     }
     157             : 
     158         644 :     static bool lcl_FixCorrectedMark(bool bChangedPos, bool bChangedOPos, MarkBase* io_pMark)
     159             :     {
     160         644 :         if( (bChangedPos || bChangedOPos) && io_pMark->IsExpanded() &&
     161           0 :             io_pMark->GetOtherMarkPos().nNode.GetNode().FindTableBoxStartNode() !=
     162           0 :             io_pMark->GetMarkPos().nNode.GetNode().FindTableBoxStartNode() )
     163             :         {
     164           0 :             if(!bChangedOPos)
     165           0 :                 io_pMark->SetMarkPos(io_pMark->GetOtherMarkPos());
     166           0 :             io_pMark->ClearOtherMarkPos();
     167           0 :             DdeBookmark * const pDdeBkmk = dynamic_cast< DdeBookmark*>(io_pMark);
     168           0 :             if(pDdeBkmk && pDdeBkmk->IsServer())
     169           0 :                 pDdeBkmk->SetRefObject(NULL);
     170           0 :             return true;
     171             :         }
     172         644 :         return false;
     173             :     }
     174             : 
     175           6 :     static IDocumentMarkAccess::iterator_t lcl_FindMark(
     176             :         IDocumentMarkAccess::container_t& rMarks,
     177             :         const IDocumentMarkAccess::pMark_t& rpMarkToFind)
     178             :     {
     179             :         IDocumentMarkAccess::iterator_t ppCurrentMark = lower_bound(
     180             :             rMarks.begin(), rMarks.end(),
     181           6 :             rpMarkToFind, &lcl_MarkOrderingByStart);
     182             :         // since there are usually not too many marks on the same start
     183             :         // position, we are not doing a bisect search for the upper bound
     184             :         // but instead start to iterate from pMarkLow directly
     185          12 :         while(ppCurrentMark != rMarks.end() && **ppCurrentMark == *rpMarkToFind)
     186             :         {
     187           6 :             if(ppCurrentMark->get() == rpMarkToFind.get())
     188             :             {
     189             :                 //OSL_TRACE("found mark named '%s'",
     190             :                 //    ::rtl::OUStringToOString(ppCurrentMark->get()->GetName(), RTL_TEXTENCODING_UTF8).getStr());
     191           6 :                 return ppCurrentMark;
     192             :             }
     193           0 :             ++ppCurrentMark;
     194             :         }
     195             :         // reached a mark starting on a later start pos or the end of the
     196             :         // vector => not found
     197           0 :         return rMarks.end();
     198             :     };
     199             : 
     200           0 :     static IDocumentMarkAccess::iterator_t lcl_FindMarkAtPos(
     201             :         IDocumentMarkAccess::container_t& rMarks,
     202             :         const SwPosition& rPos,
     203             :         const IDocumentMarkAccess::MarkType eType)
     204             :     {
     205           0 :         for(IDocumentMarkAccess::iterator_t ppCurrentMark = lower_bound(
     206             :                 rMarks.begin(), rMarks.end(),
     207             :                 rPos,
     208           0 :                 boost::bind(&IMark::StartsBefore, _1, _2));
     209           0 :             ppCurrentMark != rMarks.end();
     210             :             ++ppCurrentMark)
     211             :         {
     212             :             // Once we reach a mark starting after the target pos
     213             :             // we do not need to continue
     214           0 :             if(ppCurrentMark->get()->StartsAfter(rPos))
     215           0 :                 break;
     216           0 :             if(IDocumentMarkAccess::GetType(**ppCurrentMark) == eType)
     217             :             {
     218             :                 //OSL_TRACE("found mark named '%s'",
     219             :                 //    ::rtl::OUStringToOString(ppCurrentMark->get()->GetName(), RTL_TEXTENCODING_UTF8).getStr());
     220           0 :                 return ppCurrentMark;
     221             :             }
     222             :         }
     223             :         // reached a mark starting on a later start pos or the end of the
     224             :         // vector => not found
     225           0 :         return rMarks.end();
     226             :     };
     227             : 
     228         124 :     static IDocumentMarkAccess::const_iterator_t lcl_FindMarkByName(
     229             :         const ::rtl::OUString& rName,
     230             :         IDocumentMarkAccess::const_iterator_t ppMarksBegin,
     231             :         IDocumentMarkAccess::const_iterator_t ppMarksEnd)
     232             :     {
     233             :         return find_if(
     234             :             ppMarksBegin,
     235             :             ppMarksEnd,
     236         124 :             boost::bind(&::rtl::OUString::equals, boost::bind(&IMark::GetName, _1), rName));
     237             :     }
     238             : 
     239             : #if 0
     240             :     static void lcl_DebugMarks(IDocumentMarkAccess::container_t vMarks)
     241             :     {
     242             :         OSL_TRACE("%d Marks", vMarks.size());
     243             :         for(IDocumentMarkAccess::iterator_t ppMark = vMarks.begin();
     244             :             ppMark != vMarks.end();
     245             :             ppMark++)
     246             :         {
     247             :             IMark* pMark = ppMark->get();
     248             :             ::rtl::OString sName = ::rtl::OUStringToOString(pMark->GetName(), RTL_TEXTENCODING_UTF8);
     249             :             const SwPosition* const pStPos = &pMark->GetMarkStart();
     250             :             const SwPosition* const pEndPos = &pMark->GetMarkEnd();
     251             :             OSL_TRACE("%s %s %d,%d %d,%d",
     252             :                 typeid(*pMark).name(),
     253             :                 sName.getStr(),
     254             :                 pStPos->nNode.GetIndex(),
     255             :                 pStPos->nContent.GetIndex(),
     256             :                 pEndPos->nNode.GetIndex(),
     257             :                 pEndPos->nContent.GetIndex());
     258             :         }
     259             :     };
     260             : #endif
     261             : }
     262             : 
     263        5448 : IDocumentMarkAccess::MarkType IDocumentMarkAccess::GetType(const IMark& rBkmk)
     264             : {
     265        5448 :     const std::type_info* const pMarkTypeInfo = &typeid(rBkmk);
     266             :     // not using dynamic_cast<> here for performance
     267        5448 :     if(*pMarkTypeInfo == typeid(UnoMark))
     268        5299 :         return UNO_BOOKMARK;
     269         149 :     else if(*pMarkTypeInfo == typeid(DdeBookmark))
     270           0 :         return DDE_BOOKMARK;
     271         149 :     else if(*pMarkTypeInfo == typeid(Bookmark))
     272         134 :         return BOOKMARK;
     273          15 :     else if(*pMarkTypeInfo == typeid(CrossRefHeadingBookmark))
     274           0 :         return CROSSREF_HEADING_BOOKMARK;
     275          15 :     else if(*pMarkTypeInfo == typeid(CrossRefNumItemBookmark))
     276           1 :         return CROSSREF_NUMITEM_BOOKMARK;
     277          14 :     else if(*pMarkTypeInfo == typeid(TextFieldmark))
     278          12 :         return TEXT_FIELDMARK;
     279           2 :     else if(*pMarkTypeInfo == typeid(CheckboxFieldmark))
     280           2 :         return CHECKBOX_FIELDMARK;
     281           0 :     else if(*pMarkTypeInfo == typeid(NavigatorReminder))
     282           0 :         return NAVIGATOR_REMINDER;
     283             :     else
     284             :     {
     285             :         OSL_FAIL("IDocumentMarkAccess::GetType(..)"
     286             :             " - unknown MarkType. This needs to be fixed!");
     287           0 :         return UNO_BOOKMARK;
     288             :     }
     289             : }
     290             : 
     291             : namespace sw { namespace mark
     292             : {
     293         558 :     MarkManager::MarkManager(SwDoc& rDoc)
     294         558 :         : m_pDoc(&rDoc)
     295         558 :     { }
     296        4335 :     ::sw::mark::IMark* MarkManager::makeMark(const SwPaM& rPaM,
     297             :         const ::rtl::OUString& rName,
     298             :         const IDocumentMarkAccess::MarkType eType)
     299             :     {
     300             : #if 0
     301             :         {
     302             :             ::rtl::OString sName = ::rtl::OUStringToOString(rName, RTL_TEXTENCODING_UTF8);
     303             :             const SwPosition* const pPos1 = rPaM.GetPoint();
     304             :             const SwPosition* pPos2 = pPos1;
     305             :             if(rPaM.HasMark())
     306             :                 pPos2 = rPaM.GetMark();
     307             :             OSL_TRACE("%s %d,%d %d,%d",
     308             :                 sName.getStr(),
     309             :                 pPos1->nNode.GetIndex(),
     310             :                 pPos1->nContent.GetIndex(),
     311             :                 pPos2->nNode.GetIndex(),
     312             :                 pPos2->nContent.GetIndex());
     313             :         }
     314             : #endif
     315             :         // see for example _SaveCntntIdx, Shells
     316             :         OSL_PRECOND(m_vMarks.size() < USHRT_MAX,
     317             :             "MarkManager::makeMark(..)"
     318             :             " - more than USHRT_MAX marks are not supported correctly");
     319             :         // There should only be one CrossRefBookmark per Textnode per Type
     320             :         OSL_PRECOND(
     321             :             (eType != CROSSREF_NUMITEM_BOOKMARK && eType != CROSSREF_HEADING_BOOKMARK)
     322             :             || (lcl_FindMarkAtPos(m_vBookmarks, *rPaM.GetPoint(), eType) == m_vBookmarks.end()),
     323             :             "MarkManager::makeMark(..)"
     324             :             " - creating duplicate CrossRefBookmark");
     325             : 
     326             :         // create mark
     327        4335 :         pMark_t pMark;
     328        4335 :         switch(eType)
     329             :         {
     330             :             case IDocumentMarkAccess::TEXT_FIELDMARK:
     331          12 :                 pMark = boost::shared_ptr<IMark>(new TextFieldmark(rPaM));
     332          12 :                 break;
     333             :             case IDocumentMarkAccess::CHECKBOX_FIELDMARK:
     334           2 :                 pMark = boost::shared_ptr<IMark>(new CheckboxFieldmark(rPaM));
     335           2 :                 break;
     336             :             case IDocumentMarkAccess::NAVIGATOR_REMINDER:
     337           0 :                 pMark = boost::shared_ptr<IMark>(new NavigatorReminder(rPaM));
     338           0 :                 break;
     339             :             case IDocumentMarkAccess::BOOKMARK:
     340          44 :                 pMark = boost::shared_ptr<IMark>(new Bookmark(rPaM, KeyCode(), rName, ::rtl::OUString()));
     341          44 :                 break;
     342             :             case IDocumentMarkAccess::DDE_BOOKMARK:
     343           0 :                 pMark = boost::shared_ptr<IMark>(new DdeBookmark(rPaM));
     344           0 :                 break;
     345             :             case IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK:
     346           0 :                 pMark = boost::shared_ptr<IMark>(new CrossRefHeadingBookmark(rPaM, KeyCode(), rName, ::rtl::OUString()));
     347           0 :                 break;
     348             :             case IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK:
     349           3 :                 pMark = boost::shared_ptr<IMark>(new CrossRefNumItemBookmark(rPaM, KeyCode(), rName, ::rtl::OUString()));
     350           3 :                 break;
     351             :             case IDocumentMarkAccess::UNO_BOOKMARK:
     352        4274 :                 pMark = boost::shared_ptr<IMark>(new UnoMark(rPaM));
     353        4274 :                 break;
     354             :         }
     355             :         OSL_ENSURE(pMark.get(),
     356             :             "MarkManager::makeMark(..)"
     357             :             " - Mark was not created.");
     358        4335 :         MarkBase* pMarkBase = dynamic_cast<MarkBase*>(pMark.get());
     359             : 
     360        4335 :         if(pMark->GetMarkPos() != pMark->GetMarkStart())
     361          22 :             pMarkBase->Swap();
     362             : 
     363             :         // for performance reasons, we trust UnoMarks to have a (generated) unique name
     364        4335 :         if(eType != IDocumentMarkAccess::UNO_BOOKMARK)
     365          61 :             pMarkBase->SetName(getUniqueMarkName(pMarkBase->GetName()));
     366             : 
     367             :         // register mark
     368        4335 :         m_aMarkNamesSet.insert(pMarkBase->GetName());
     369        4335 :         lcl_InsertMarkSorted(m_vMarks, pMark);
     370        4335 :         switch(eType)
     371             :         {
     372             :             case IDocumentMarkAccess::BOOKMARK:
     373             :             case IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK:
     374             :             case IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK:
     375          47 :                 lcl_InsertMarkSorted(m_vBookmarks, pMark);
     376          47 :                 break;
     377             :             case IDocumentMarkAccess::TEXT_FIELDMARK:
     378             :             case IDocumentMarkAccess::CHECKBOX_FIELDMARK:
     379          14 :                 lcl_InsertMarkSorted(m_vFieldmarks, pMark);
     380          14 :                 break;
     381             :             case IDocumentMarkAccess::NAVIGATOR_REMINDER:
     382             :             case IDocumentMarkAccess::DDE_BOOKMARK:
     383             :             case IDocumentMarkAccess::UNO_BOOKMARK:
     384             :             // no special array for these
     385        4274 :                 break;
     386             :         }
     387        4335 :         pMarkBase->InitDoc(m_pDoc);
     388             : #if 0
     389             :         OSL_TRACE("--- makeType ---");
     390             :         OSL_TRACE("Marks");
     391             :         lcl_DebugMarks(m_vMarks);
     392             :         OSL_TRACE("Bookmarks");
     393             :         lcl_DebugMarks(m_vBookmarks);
     394             :         OSL_TRACE("Fieldmarks");
     395             :         lcl_DebugMarks(m_vFieldmarks);
     396             : #endif
     397             : 
     398        4335 :         return pMark.get();
     399             :     }
     400             : 
     401          12 :     ::sw::mark::IFieldmark* MarkManager::makeFieldBookmark( const SwPaM& rPaM,
     402             :         const rtl::OUString& rName,
     403             :         const rtl::OUString& rType )
     404             :     {
     405             :         sw::mark::IMark* pMark = makeMark( rPaM, rName,
     406          12 :                 IDocumentMarkAccess::TEXT_FIELDMARK );
     407          12 :         sw::mark::IFieldmark* pFieldMark = dynamic_cast<sw::mark::IFieldmark*>( pMark );
     408          12 :         pFieldMark->SetFieldname( rType );
     409             : 
     410          12 :         return pFieldMark;
     411             :     }
     412             : 
     413           0 :     ::sw::mark::IFieldmark* MarkManager::makeNoTextFieldBookmark( const SwPaM& rPaM,
     414             :         const rtl::OUString& rName,
     415             :         const rtl::OUString& rType)
     416             :     {
     417             :         sw::mark::IMark* pMark = makeMark( rPaM, rName,
     418           0 :                 IDocumentMarkAccess::CHECKBOX_FIELDMARK );
     419           0 :         sw::mark::IFieldmark* pFieldMark = dynamic_cast<sw::mark::IFieldmark*>( pMark );
     420           0 :         pFieldMark->SetFieldname( rType );
     421             : 
     422           0 :         return pFieldMark;
     423             :     }
     424             : 
     425           0 :     ::sw::mark::IMark* MarkManager::getMarkForTxtNode(const SwTxtNode& rTxtNode,
     426             :         const IDocumentMarkAccess::MarkType eType)
     427             :     {
     428           0 :         SwPosition aPos(rTxtNode);
     429           0 :         aPos.nContent.Assign(&(const_cast<SwTxtNode&>(rTxtNode)), 0);
     430           0 :         const iterator_t ppExistingMark = lcl_FindMarkAtPos(m_vBookmarks, aPos, eType);
     431           0 :         if(ppExistingMark != m_vBookmarks.end())
     432           0 :             return ppExistingMark->get();
     433           0 :         const SwPaM aPaM(aPos);
     434           0 :         return makeMark(aPaM, ::rtl::OUString(), eType);
     435             :     }
     436             : 
     437           0 :     void MarkManager::repositionMark( ::sw::mark::IMark* const io_pMark,
     438             :         const SwPaM& rPaM)
     439             :     {
     440             :         OSL_PRECOND(io_pMark->GetMarkPos().GetDoc() == m_pDoc,
     441             :             "<MarkManager::repositionMark(..)>"
     442             :             " - Mark is not in my doc.");
     443           0 :         MarkBase* const pMarkBase = dynamic_cast< MarkBase* >(io_pMark);
     444           0 :         pMarkBase->SetMarkPos(*(rPaM.GetPoint()));
     445           0 :         if(rPaM.HasMark())
     446           0 :             pMarkBase->SetOtherMarkPos(*(rPaM.GetMark()));
     447             :         else
     448           0 :             pMarkBase->ClearOtherMarkPos();
     449             : 
     450           0 :         if(pMarkBase->GetMarkPos() != pMarkBase->GetMarkStart())
     451           0 :             pMarkBase->Swap();
     452             : 
     453           0 :         sortMarks();
     454           0 :     }
     455             : 
     456          10 :     bool MarkManager::renameMark(::sw::mark::IMark* io_pMark, const ::rtl::OUString& rNewName)
     457             :     {
     458             :         OSL_PRECOND(io_pMark->GetMarkPos().GetDoc() == m_pDoc,
     459             :             "<MarkManager::renameMark(..)>"
     460             :             " - Mark is not in my doc.");
     461          10 :         if(io_pMark->GetName() == rNewName)
     462           0 :             return true;
     463          10 :         if(hasMark(rNewName))
     464           6 :             return false;
     465           4 :         m_aMarkNamesSet.erase(dynamic_cast< ::sw::mark::MarkBase* >(io_pMark)->GetName());
     466           4 :         m_aMarkNamesSet.insert(rNewName);
     467           4 :         dynamic_cast< ::sw::mark::MarkBase* >(io_pMark)->SetName(rNewName);
     468           4 :         return true;
     469             :     }
     470             : 
     471         356 :     void MarkManager::correctMarksAbsolute(const SwNodeIndex& rOldNode, const SwPosition& rNewPos, const xub_StrLen nOffset)
     472             :     {
     473         356 :         const SwNode* const pOldNode = &rOldNode.GetNode();
     474         356 :         SwPosition aNewPos(rNewPos);
     475         356 :         aNewPos.nContent += nOffset;
     476         356 :         bool isSortingNeeded = false;
     477        1242 :         for(iterator_t ppMark = m_vMarks.begin();
     478         828 :             ppMark != m_vMarks.end();
     479             :             ++ppMark)
     480             :         {
     481             :             // is on position ??
     482          58 :             bool bChangedPos = false, bChangedOPos = false;
     483          58 :             ::sw::mark::MarkBase* pMark = dynamic_cast< ::sw::mark::MarkBase* >(ppMark->get());
     484          58 :             if(&pMark->GetMarkPos().nNode.GetNode() == pOldNode)
     485             :             {
     486           0 :                 pMark->SetMarkPos(aNewPos);
     487           0 :                 bChangedPos = true;
     488             :             }
     489          62 :             if (pMark->IsExpanded() &&
     490           4 :                 &pMark->GetOtherMarkPos().nNode.GetNode() == pOldNode)
     491             :             {
     492           0 :                 pMark->SetMarkPos(aNewPos);
     493           0 :                 bChangedOPos= true;
     494             :             }
     495             :             // illegal selection? collapse the mark and restore sorting later
     496          58 :             isSortingNeeded |= lcl_FixCorrectedMark(bChangedPos, bChangedOPos, pMark);
     497             :         }
     498             :         // restore sorting if needed
     499         356 :         if(isSortingNeeded)
     500           0 :             sortMarks();
     501             : #if 0
     502             :         OSL_TRACE("correctMarksAbsolute");
     503             :         lcl_DebugMarks(m_vMarks);
     504             : #endif
     505         356 :     }
     506             : 
     507         524 :     void MarkManager::correctMarksRelative(const SwNodeIndex& rOldNode, const SwPosition& rNewPos, const xub_StrLen nOffset)
     508             :     {
     509         524 :         const SwNode* const pOldNode = &rOldNode.GetNode();
     510         524 :         SwPosition aNewPos(rNewPos);
     511         524 :         aNewPos.nContent += nOffset;
     512         524 :         bool isSortingNeeded = false;
     513        3330 :         for(iterator_t ppMark = m_vMarks.begin();
     514        2220 :             ppMark != m_vMarks.end();
     515             :             ++ppMark)
     516             :         {
     517             :             // is on position ??
     518         586 :             bool bChangedPos = false, bChangedOPos = false;
     519         586 :             ::sw::mark::MarkBase* const pMark = dynamic_cast< ::sw::mark::MarkBase* >(ppMark->get());
     520         586 :             if(&pMark->GetMarkPos().nNode.GetNode() == pOldNode)
     521             :             {
     522           0 :                 SwPosition aNewPosRel(aNewPos);
     523           0 :                 aNewPosRel.nContent += pMark->GetMarkPos().nContent.GetIndex();
     524           0 :                 pMark->SetMarkPos(aNewPosRel);
     525           0 :                 bChangedPos = true;
     526             :             }
     527         604 :             if(pMark->IsExpanded() &&
     528          18 :                 &pMark->GetOtherMarkPos().nNode.GetNode() == pOldNode)
     529             :             {
     530           0 :                 SwPosition aNewPosRel(aNewPos);
     531           0 :                 aNewPosRel.nContent += pMark->GetOtherMarkPos().nContent.GetIndex();
     532           0 :                 pMark->SetOtherMarkPos(aNewPosRel);
     533           0 :                 bChangedOPos = true;
     534             :             }
     535             :             // illegal selection? collapse the mark and restore sorting later
     536         586 :             isSortingNeeded |= lcl_FixCorrectedMark(bChangedPos, bChangedOPos, pMark);
     537             :         }
     538             :         // restore sorting if needed
     539         524 :         if(isSortingNeeded)
     540           0 :             sortMarks();
     541             : #if 0
     542             :         OSL_TRACE("correctMarksRelative");
     543             :         lcl_DebugMarks(m_vMarks);
     544             : #endif
     545         524 :     }
     546             : 
     547        1324 :     void MarkManager::deleteMarks(
     548             :             const SwNodeIndex& rStt,
     549             :             const SwNodeIndex& rEnd,
     550             :             ::std::vector<SaveBookmark>* pSaveBkmk,
     551             :             const SwIndex* pSttIdx,
     552             :             const SwIndex* pEndIdx )
     553             :     {
     554        1324 :         vector<const_iterator_t> vMarksToDelete;
     555        1324 :         bool isSortingNeeded = false;
     556             :         // copy all bookmarks in the move area to a vector storing all position data as offsets
     557             :         // reassignment is performed after the move
     558        7266 :         for(iterator_t ppMark = m_vMarks.begin();
     559        4844 :             ppMark != m_vMarks.end();
     560             :             ++ppMark)
     561             :         {
     562             :             // navigator marks should not be moved
     563             :             // TODO: Check if this might make them invalid
     564        1098 :             if(IDocumentMarkAccess::GetType(**ppMark) == NAVIGATOR_REMINDER)
     565           0 :                 continue;
     566             : 
     567        1098 :             ::sw::mark::MarkBase* pMark = dynamic_cast< ::sw::mark::MarkBase* >(ppMark->get());
     568             :             // on position ??
     569        1098 :             bool isPosInRange = (lcl_GreaterThan(pMark->GetMarkPos(), rStt, pSttIdx) &&
     570        1098 :                 lcl_Lower(pMark->GetMarkPos(), rEnd, pEndIdx));
     571        1098 :             bool isOtherPosInRange = (pMark->IsExpanded() &&
     572          50 :                 lcl_GreaterThan(pMark->GetOtherMarkPos(), rStt, pSttIdx) &&
     573        1148 :                 lcl_Lower(pMark->GetOtherMarkPos(), rEnd, pEndIdx));
     574             :             // special case: completely in range, touching the end?
     575        1230 :             if(pEndIdx &&
     576             :                     ((isOtherPosInRange
     577           0 :                     && pMark->GetMarkPos().nNode == rEnd
     578           0 :                     && pMark->GetMarkPos().nContent == *pEndIdx)
     579             :                 || (isPosInRange
     580          76 :                     && pMark->IsExpanded()
     581          28 :                     && pMark->GetOtherMarkPos().nNode == rEnd
     582          28 :                     && pMark->GetOtherMarkPos().nContent == *pEndIdx)))
     583             :             {
     584          28 :                 isPosInRange = true, isOtherPosInRange = true;
     585             :             }
     586             : 
     587        1098 :             if(isPosInRange && (isOtherPosInRange || !pMark->IsExpanded()))
     588             :             {
     589             :                 // completely in range
     590             : 
     591             :                 // #i92125#
     592          76 :                 bool bKeepCrossRefBkmk( false );
     593             :                 {
     594         148 :                     if ( rStt == rEnd &&
     595          36 :                          ( IDocumentMarkAccess::GetType(*pMark) ==
     596             :                             IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK ||
     597          36 :                            IDocumentMarkAccess::GetType(*pMark) ==
     598             :                             IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK ) )
     599             :                     {
     600           0 :                         bKeepCrossRefBkmk = true;
     601             :                     }
     602             :                 }
     603          76 :                 if ( !bKeepCrossRefBkmk )
     604             :                 {
     605          76 :                     if(pSaveBkmk)
     606           0 :                         pSaveBkmk->push_back(SaveBookmark(true, true, *pMark, rStt, pSttIdx));
     607          76 :                     vMarksToDelete.push_back(ppMark);
     608             :                 }
     609             :             }
     610        1022 :             else if(isPosInRange ^ isOtherPosInRange)
     611             :             {
     612             :                 // the bookmark is partitially in the range
     613             :                 // move position of that is in the range out of it
     614             :                 SAL_WNODEPRECATED_DECLARATIONS_PUSH
     615           0 :                 auto_ptr<SwPosition> pNewPos;
     616           0 :                 if(pEndIdx)
     617             :                     pNewPos = auto_ptr<SwPosition>(new SwPosition(
     618             :                         rEnd,
     619           0 :                         *pEndIdx));
     620             :                 else
     621             :                     pNewPos = lcl_FindExpelPosition(
     622             :                         rStt,
     623             :                         rEnd,
     624           0 :                         isPosInRange ? pMark->GetOtherMarkPos() : pMark->GetMarkPos());
     625             :                 SAL_WNODEPRECATED_DECLARATIONS_POP
     626             : 
     627             :                 // #i92125#
     628             :                 // no move of position for cross-reference bookmarks,
     629             :                 // if move occurs inside a certain node
     630           0 :                 if ( ( IDocumentMarkAccess::GetType(*pMark) !=
     631             :                                 IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK &&
     632           0 :                        IDocumentMarkAccess::GetType(*pMark) !=
     633             :                                 IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK ) ||
     634           0 :                      pMark->GetMarkPos().nNode != pNewPos->nNode )
     635             :                 {
     636           0 :                     if(isPosInRange)
     637           0 :                         pMark->SetMarkPos(*pNewPos);
     638             :                     else
     639           0 :                         pMark->SetOtherMarkPos(*pNewPos);
     640             : 
     641             :                     // illegal selection? collapse the mark and restore sorting later
     642           0 :                     isSortingNeeded |= lcl_FixCorrectedMark(isPosInRange, isOtherPosInRange, pMark);
     643           0 :                 }
     644             :             }
     645             :         }
     646             : 
     647             :         // we just remembered the iterators to delete, so we do not need to search
     648             :         // for the boost::shared_ptr<> (the entry in m_vMarks) again
     649             :         // reverse iteration, since erasing an entry invalidates iterators
     650             :         // behind it (the iterators in vMarksToDelete are sorted)
     651        4200 :         for(vector<const_iterator_t>::reverse_iterator pppMark = vMarksToDelete.rbegin();
     652        2800 :             pppMark != vMarksToDelete.rend();
     653             :             ++pppMark)
     654             :         {
     655          76 :             deleteMark(*pppMark);
     656             :         }
     657        1324 :         if(isSortingNeeded)
     658           0 :             sortMarks();
     659             : #if 0
     660             :         OSL_TRACE("deleteMarks");
     661             :         lcl_DebugMarks(m_vMarks);
     662             : #endif
     663        1324 :     }
     664             : 
     665        4271 :     void MarkManager::deleteMark(const const_iterator_t ppMark)
     666             :     {
     667        8542 :         if(ppMark == m_vMarks.end()) return;
     668             : 
     669        4271 :         switch(IDocumentMarkAccess::GetType(**ppMark))
     670             :         {
     671             :             case IDocumentMarkAccess::BOOKMARK:
     672             :             case IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK:
     673             :             case IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK:
     674             :             // if(dynamic_cast<IBookmark*>)
     675             :             {
     676           6 :                 IDocumentMarkAccess::iterator_t ppBookmark = lcl_FindMark(m_vBookmarks, *ppMark);
     677             :                 OSL_ENSURE(ppBookmark != m_vBookmarks.end(),
     678             :                     "<MarkManager::deleteMark(..)>"
     679             :                     " - Bookmark not found.");
     680           6 :                 m_vBookmarks.erase(ppBookmark);
     681             :                 break;
     682             :             }
     683             :             case IDocumentMarkAccess::TEXT_FIELDMARK:
     684             :             case IDocumentMarkAccess::CHECKBOX_FIELDMARK:
     685             :             {
     686           0 :                 IDocumentMarkAccess::iterator_t ppFieldmark = lcl_FindMark(m_vFieldmarks, *ppMark);
     687             :                 OSL_ENSURE(ppFieldmark != m_vFieldmarks.end(),
     688             :                     "<MarkManager::deleteMark(..)>"
     689             :                     " - Bookmark not found.");
     690           0 :                 m_vFieldmarks.erase(ppFieldmark);
     691           0 :                 sw::mark::TextFieldmark* pTextFieldmark = dynamic_cast<sw::mark::TextFieldmark*>(ppMark->get());
     692           0 :                 if (pTextFieldmark)
     693           0 :                     pTextFieldmark->ReleaseDoc(m_pDoc);
     694             :                 break;
     695             :             }
     696             :             case IDocumentMarkAccess::NAVIGATOR_REMINDER:
     697             :             case IDocumentMarkAccess::DDE_BOOKMARK:
     698             :             case IDocumentMarkAccess::UNO_BOOKMARK:
     699             :             // no special array for these
     700        4265 :                 break;
     701             :         }
     702        4271 :         DdeBookmark* const pDdeBookmark = dynamic_cast<DdeBookmark*>(ppMark->get());
     703        4271 :         if(pDdeBookmark)
     704           6 :             pDdeBookmark->DeregisterFromDoc(m_pDoc);
     705             :         //Effective STL Item 27, get a non-const iterator aI at the same
     706             :         //position as const iterator ppMark was
     707        4271 :         iterator_t aI = m_vMarks.begin();
     708        4271 :         std::advance(aI, std::distance<const_iterator_t>(aI, ppMark));
     709             : 
     710             :         //fdo#37974
     711             :         //a) a mark destructor may callback into this method.
     712             :         //b) vector::erase first calls the destructor of the object, then
     713             :         //removes it from the vector.
     714             :         //So if the only reference to the object is the one
     715             :         //in the vector then we may reenter this method when the mark
     716             :         //is destructed but before it is removed, i.e. findMark still
     717             :         //finds the object whose destructor is being run. Take a temp
     718             :         //extra reference on the shared_ptr, remove the entry from the
     719             :         //vector, and on xHoldPastErase release findMark won't find
     720             :         //it anymore.
     721        4271 :         pMark_t xHoldPastErase = *aI;
     722        4271 :         m_aMarkNamesSet.erase(ppMark->get()->GetName());
     723        4271 :         m_vMarks.erase(aI);
     724             :     }
     725             : 
     726        4195 :     void MarkManager::deleteMark(const IMark* const pMark)
     727             :     {
     728             :         OSL_PRECOND(pMark->GetMarkPos().GetDoc() == m_pDoc,
     729             :             "<MarkManager::deleteMark(..)>"
     730             :             " - Mark is not in my doc.");
     731             :         // finds the last Mark that is starting before pMark
     732             :         // (pMarkLow < pMark)
     733             :         iterator_t pMarkLow = lower_bound(
     734             :             m_vMarks.begin(), m_vMarks.end(),
     735        4195 :             pMark->GetMarkStart(),
     736        8390 :             boost::bind(&IMark::StartsBefore, _1, _2));
     737             :         // finds the first Mark that pMark is starting before
     738             :         // (pMark < pMarkHigh)
     739             :         //iterator_t pMarkHigh = upper_bound(
     740             :         //    pMarkLow, m_vMarks.end(),
     741             :         //    pMark->GetMarkStart(),
     742             :         //    bind(&IMark::StartsBefore, _2, _1));
     743             :         // since it should be rare that pMark isnt found at all
     744             :         // we skip the bisect search on the upper bound
     745        4195 :         iterator_t pMarkHigh = m_vMarks.end();
     746             :         iterator_t pMarkFound = find_if(
     747             :             pMarkLow, pMarkHigh,
     748        4195 :             boost::bind(equal_to<const IMark*>(), boost::bind(&boost::shared_ptr<IMark>::get, _1), pMark));
     749        4195 :         if(pMarkFound != pMarkHigh)
     750        4195 :             deleteMark(pMarkFound);
     751        4195 :     }
     752             : 
     753         166 :     void MarkManager::clearAllMarks()
     754             :     {
     755         166 :         m_vFieldmarks.clear();
     756         166 :         m_vBookmarks.clear();
     757         166 :         m_aMarkNamesSet.clear();
     758             : #if OSL_DEBUG_LEVEL > 0
     759             :         for(iterator_t pBkmk = m_vMarks.begin();
     760             :             pBkmk != m_vMarks.end();
     761             :             ++pBkmk)
     762             :             OSL_ENSURE(pBkmk->unique(),
     763             :                 "<MarkManager::clearAllMarks(..)>"
     764             :                 " - a Bookmark is still in use.");
     765             : #endif
     766         166 :         m_vMarks.clear();
     767         166 :     }
     768             : 
     769         124 :     IDocumentMarkAccess::const_iterator_t MarkManager::findMark(const ::rtl::OUString& rName) const
     770             :     {
     771         124 :         return lcl_FindMarkByName(rName, m_vMarks.begin(), m_vMarks.end());
     772             :     }
     773             : 
     774           0 :     IDocumentMarkAccess::const_iterator_t MarkManager::findBookmark(const ::rtl::OUString& rName) const
     775             :     {
     776           0 :         return lcl_FindMarkByName(rName, m_vBookmarks.begin(), m_vBookmarks.end());
     777             :     }
     778             : 
     779       97074 :     IDocumentMarkAccess::const_iterator_t MarkManager::getMarksBegin() const
     780       97074 :         { return m_vMarks.begin(); }
     781             : 
     782      103895 :     IDocumentMarkAccess::const_iterator_t MarkManager::getMarksEnd() const
     783      103895 :         { return m_vMarks.end(); }
     784             : 
     785        2256 :     sal_Int32 MarkManager::getMarksCount() const
     786        2256 :         { return m_vMarks.size(); }
     787             : 
     788          58 :     IDocumentMarkAccess::const_iterator_t MarkManager::getBookmarksBegin() const
     789          58 :         { return m_vBookmarks.begin(); }
     790             : 
     791          37 :     IDocumentMarkAccess::const_iterator_t MarkManager::getBookmarksEnd() const
     792          37 :         { return m_vBookmarks.end(); }
     793             : 
     794         425 :     sal_Int32 MarkManager::getBookmarksCount() const
     795         425 :         { return m_vBookmarks.size(); }
     796             : 
     797        4754 :     IFieldmark* MarkManager::getFieldmarkFor(const SwPosition& rPos) const
     798             :     {
     799             :         const_iterator_t pFieldmark = find_if(
     800             :             m_vFieldmarks.begin(),
     801             :             m_vFieldmarks.end( ),
     802        4754 :             boost::bind(&IMark::IsCoveringPosition, _1, rPos));
     803        4754 :         if(pFieldmark == m_vFieldmarks.end()) return NULL;
     804          62 :         return dynamic_cast<IFieldmark*>(pFieldmark->get());
     805             :     }
     806             : 
     807           0 :     IFieldmark* MarkManager::getFieldmarkAfter(const SwPosition& rPos) const
     808           0 :         { return dynamic_cast<IFieldmark*>(lcl_getMarkAfter(m_vFieldmarks, rPos)); }
     809             : 
     810           0 :     IFieldmark* MarkManager::getFieldmarkBefore(const SwPosition& rPos) const
     811           0 :         { return dynamic_cast<IFieldmark*>(lcl_getMarkBefore(m_vFieldmarks, rPos)); }
     812             : 
     813             : 
     814          61 :     ::rtl::OUString MarkManager::getUniqueMarkName(const ::rtl::OUString& rName) const
     815             :     {
     816             :         OSL_ENSURE(!rName.isEmpty(),
     817             :             "<MarkManager::getUniqueMarkName(..)>"
     818             :             " - a name should be proposed");
     819          61 :         if(!hasMark(rName)) return rName;
     820           0 :         ::rtl::OUStringBuffer sBuf;
     821           0 :         ::rtl::OUString sTmp;
     822             : 
     823             :         // try the name "<rName>XXX" (where XXX is a number starting from 1) unless there is
     824             :         // a unused name. Due to performance-reasons (especially in mailmerge-Szenarios) there
     825             :         // is a map m_aMarkBasenameMapUniqueOffset which holds the next possible offset (XXX) for
     826             :         // rName (so there is no need to test for nCnt-values smaller than the offset).
     827           0 :         sal_Int32 nCnt = 1;
     828           0 :         MarkBasenameMapUniqueOffset_t::const_iterator aIter = m_aMarkBasenameMapUniqueOffset.find(rName);
     829           0 :         if(aIter != m_aMarkBasenameMapUniqueOffset.end()) nCnt = aIter->second;
     830           0 :         while(nCnt < SAL_MAX_INT32)
     831             :         {
     832           0 :             sTmp = sBuf.append(rName).append(nCnt).makeStringAndClear();
     833           0 :             nCnt++;
     834           0 :             if(!hasMark(sTmp)) break;
     835             :         }
     836           0 :         m_aMarkBasenameMapUniqueOffset[rName] = nCnt;
     837             : 
     838           0 :         return sTmp;
     839             :     }
     840             : 
     841           0 :     void MarkManager::sortMarks()
     842             :     {
     843           0 :         sort(m_vMarks.begin(), m_vMarks.end(), &lcl_MarkOrderingByStart);
     844           0 :         sort(m_vBookmarks.begin(), m_vBookmarks.end(), &lcl_MarkOrderingByStart);
     845           0 :         sort(m_vFieldmarks.begin(), m_vFieldmarks.end(), &lcl_MarkOrderingByStart);
     846           0 :     }
     847             : 
     848          71 :     bool MarkManager::hasMark(const ::rtl::OUString& rName) const
     849             :     {
     850          71 :         return (m_aMarkNamesSet.find(rName) != m_aMarkNamesSet.end());
     851             :     }
     852             : 
     853             : }} // namespace ::sw::mark
     854             : 
     855             : 
     856             : #define PCURCRSR (_pCurrCrsr)
     857             : #define FOREACHPAM_START(pSttCrsr) \
     858             :     {\
     859             :         SwPaM *_pStartCrsr = pSttCrsr, *_pCurrCrsr = pSttCrsr; \
     860             :         do {
     861             : 
     862             : #define FOREACHPAM_END() \
     863             :         } while( (_pCurrCrsr=(SwPaM *)_pCurrCrsr->GetNext()) != _pStartCrsr ); \
     864             :     }
     865             : #define PCURSH ((SwCrsrShell*)_pStartShell)
     866             : #define FOREACHSHELL_START( pEShell ) \
     867             :     {\
     868             :         ViewShell *_pStartShell = pEShell; \
     869             :         do { \
     870             :             if( _pStartShell->IsA( TYPE( SwCrsrShell )) ) \
     871             :             {
     872             : 
     873             : #define FOREACHSHELL_END( pEShell ) \
     874             :             } \
     875             :         } while((_pStartShell=(ViewShell*)_pStartShell->GetNext())!= pEShell ); \
     876             :     }
     877             : 
     878             : namespace
     879             : {
     880             :     // Array structure: 2 longs,
     881             :     //  1st long contains the type and position in the DocArray,
     882             :     //  2nd long contains the ContentPosition
     883             :     //
     884             :     //  CntntType --
     885             :     //          0x8000 = Bookmark Pos1
     886             :     //          0x8001 = Bookmark Pos2
     887             :     //          0x2000 = Paragraph anchored frame
     888             :     //          0x2001 = frame anchored at character, which should be moved
     889             :     //          0x1000 = Redline Mark
     890             :     //          0x1001 = Redline Point
     891             :     //          0x0800 = Crsr from the CrsrShell Mark
     892             :     //          0x0801 = Crsr from the CrsrShell Point
     893             :     //          0x0400 = UnoCrsr Mark
     894             :     //          0x0401 = UnoCrsr Point
     895             :     //
     896             : 
     897             :     class _SwSaveTypeCountContent
     898             :     {
     899             :         union {
     900             :             struct { sal_uInt16 nType, nCount; } TC;
     901             :             sal_uLong nTypeCount;
     902             :             } TYPECOUNT;
     903             :         xub_StrLen nContent;
     904             : 
     905             :     public:
     906        1226 :         _SwSaveTypeCountContent() { TYPECOUNT.nTypeCount = 0; nContent = 0; }
     907             :         _SwSaveTypeCountContent( sal_uInt16 nType )
     908             :             {
     909             :                 SetTypeAndCount( nType, 0 );
     910             :                 nContent = 0;
     911             :             }
     912           0 :         _SwSaveTypeCountContent( const std::vector<sal_uLong> &rArr, sal_uInt16& rPos )
     913             :             {
     914           0 :                 TYPECOUNT.nTypeCount = rArr[ rPos++ ];
     915           0 :                 nContent = static_cast<xub_StrLen>(rArr[ rPos++ ]);
     916           0 :             }
     917           0 :         void Add( std::vector<sal_uLong> &rArr )
     918             :         {
     919           0 :             rArr.push_back( TYPECOUNT.nTypeCount );
     920           0 :             rArr.push_back( nContent );
     921           0 :         }
     922             : 
     923           0 :         void SetType( sal_uInt16 n )        { TYPECOUNT.TC.nType = n; }
     924           0 :         sal_uInt16 GetType() const          { return TYPECOUNT.TC.nType; }
     925           0 :         void IncType()                  { ++TYPECOUNT.TC.nType; }
     926           0 :         void DecType()                  { --TYPECOUNT.TC.nType; }
     927             : 
     928        1226 :         void SetCount( sal_uInt16 n )       { TYPECOUNT.TC.nCount = n; }
     929        5652 :         sal_uInt16 GetCount() const         { return TYPECOUNT.TC.nCount; }
     930        1632 :         sal_uInt16 IncCount()               { return ++TYPECOUNT.TC.nCount; }
     931         794 :         sal_uInt16 DecCount()               { return --TYPECOUNT.TC.nCount; }
     932             : 
     933        3678 :         void SetTypeAndCount( sal_uInt16 nT, sal_uInt16 nC )
     934        3678 :             { TYPECOUNT.TC.nCount = nC; TYPECOUNT.TC.nType = nT; }
     935             : 
     936           0 :         void SetContent( xub_StrLen n )     { nContent = n; }
     937           0 :         xub_StrLen GetContent() const       { return nContent; }
     938             :     };
     939             : 
     940             :     // #i59534: If a paragraph will be splitted we have to restore some redline positions
     941             :     // This help function checks a position compared with a node and an content index
     942             : 
     943             :     static const int BEFORE_NODE = 0;          // Position before the given node index
     944             :     static const int BEFORE_SAME_NODE = 1;     // Same node index but content index before given content index
     945             :     static const int SAME_POSITION = 2;        // Same node index and samecontent index
     946             :     static const int BEHIND_SAME_NODE = 3;     // Same node index but content index behind given content index
     947             :     static const int BEHIND_NODE = 4;          // Position behind the given node index
     948             : 
     949           8 :     static int lcl_RelativePosition( const SwPosition& rPos, sal_uLong nNode, xub_StrLen nCntnt )
     950             :     {
     951           8 :         sal_uLong nIndex = rPos.nNode.GetIndex();
     952           8 :         int nReturn = BEFORE_NODE;
     953           8 :         if( nIndex == nNode )
     954             :         {
     955           0 :             xub_StrLen nCntIdx = rPos.nContent.GetIndex();
     956           0 :             if( nCntIdx < nCntnt )
     957           0 :                 nReturn = BEFORE_SAME_NODE;
     958           0 :             else if( nCntIdx == nCntnt )
     959           0 :                 nReturn = SAME_POSITION;
     960             :             else
     961           0 :                 nReturn = BEHIND_SAME_NODE;
     962             :         }
     963           8 :         else if( nIndex > nNode )
     964           0 :             nReturn = BEHIND_NODE;
     965           8 :         return nReturn;
     966             :     }
     967             : 
     968             : 
     969          20 :     static inline int lcl_Greater( const SwPosition& rPos, const SwNodeIndex& rNdIdx, const SwIndex* pIdx )
     970             :     {
     971          20 :         return rPos.nNode > rNdIdx || ( pIdx && rPos.nNode == rNdIdx && rPos.nContent > pIdx->GetIndex() );
     972             :     }
     973             : 
     974        1042 :     static void lcl_ChkPaM( std::vector<sal_uLong> &rSaveArr, sal_uLong nNode, xub_StrLen nCntnt,
     975             :                     const SwPaM& rPam, _SwSaveTypeCountContent& rSave,
     976             :                     bool bChkSelDirection )
     977             :     {
     978             :         // Respect direction of selection
     979             :         bool bBound1IsStart = !bChkSelDirection ? true :
     980           0 :                             ( *rPam.GetPoint() < *rPam.GetMark()
     981           0 :                                 ? rPam.GetPoint() == &rPam.GetBound()
     982        1042 :                                 : rPam.GetMark() == &rPam.GetBound());
     983             : 
     984        1042 :         const SwPosition* pPos = &rPam.GetBound( sal_True );
     985        1044 :         if( pPos->nNode.GetIndex() == nNode &&
     986           2 :             ( bBound1IsStart ? pPos->nContent.GetIndex() < nCntnt
     987           0 :                                 : pPos->nContent.GetIndex() <= nCntnt ))
     988             :         {
     989           0 :             rSave.SetContent( pPos->nContent.GetIndex() );
     990           0 :             rSave.Add( rSaveArr );
     991             :         }
     992             : 
     993        1042 :         pPos = &rPam.GetBound( sal_False );
     994        1044 :         if( pPos->nNode.GetIndex() == nNode &&
     995             :             ( (bBound1IsStart && bChkSelDirection)
     996           0 :                         ? pPos->nContent.GetIndex() <= nCntnt
     997           2 :                         : pPos->nContent.GetIndex() < nCntnt ))
     998             :         {
     999           0 :             rSave.SetContent( pPos->nContent.GetIndex() );
    1000           0 :             rSave.IncType();
    1001           0 :             rSave.Add( rSaveArr );
    1002           0 :             rSave.DecType();
    1003             :         }
    1004        1042 :     }
    1005             : 
    1006             : }
    1007             : 
    1008             : 
    1009             : // IDocumentMarkAccess for SwDoc
    1010             : 
    1011       13839 : IDocumentMarkAccess* SwDoc::getIDocumentMarkAccess()
    1012       13839 :     { return static_cast< IDocumentMarkAccess* >(pMarkManager.get()); }
    1013             : 
    1014       98656 : const IDocumentMarkAccess* SwDoc::getIDocumentMarkAccess() const
    1015       98656 :     { return static_cast< IDocumentMarkAccess* >(pMarkManager.get()); }
    1016             : 
    1017             : // SaveBookmark
    1018             : 
    1019           0 : SaveBookmark::SaveBookmark(
    1020             :     bool bSavePos,
    1021             :     bool bSaveOtherPos,
    1022             :     const IMark& rBkmk,
    1023             :     const SwNodeIndex & rMvPos,
    1024             :     const SwIndex* pIdx)
    1025           0 :     : m_aName(rBkmk.GetName())
    1026             :     , m_aShortName()
    1027             :     , m_aCode()
    1028             :     , m_bSavePos(bSavePos)
    1029             :     , m_bSaveOtherPos(bSaveOtherPos)
    1030           0 :     , m_eOrigBkmType(IDocumentMarkAccess::GetType(rBkmk))
    1031             : {
    1032           0 :     const IBookmark* const pBookmark = dynamic_cast< const IBookmark* >(&rBkmk);
    1033           0 :     if(pBookmark)
    1034             :     {
    1035           0 :         m_aShortName = pBookmark->GetShortName();
    1036           0 :         m_aCode = pBookmark->GetKeyCode();
    1037             : 
    1038             :         ::sfx2::Metadatable const*const pMetadatable(
    1039           0 :                 dynamic_cast< ::sfx2::Metadatable const* >(pBookmark));
    1040           0 :         if (pMetadatable)
    1041             :         {
    1042           0 :             m_pMetadataUndo = pMetadatable->CreateUndo();
    1043             :         }
    1044             :     }
    1045           0 :     m_nNode1 = rBkmk.GetMarkPos().nNode.GetIndex();
    1046           0 :     m_nCntnt1 = rBkmk.GetMarkPos().nContent.GetIndex();
    1047             : 
    1048           0 :     if(m_bSavePos)
    1049             :     {
    1050           0 :         m_nNode1 -= rMvPos.GetIndex();
    1051           0 :         if(pIdx && !m_nNode1)
    1052           0 :             m_nCntnt1 -= pIdx->GetIndex();
    1053             :     }
    1054             : 
    1055           0 :     if(rBkmk.IsExpanded())
    1056             :     {
    1057           0 :         m_nNode2 = rBkmk.GetOtherMarkPos().nNode.GetIndex();
    1058           0 :         m_nCntnt2 = rBkmk.GetOtherMarkPos().nContent.GetIndex();
    1059             : 
    1060           0 :         if(m_bSaveOtherPos)
    1061             :         {
    1062           0 :             m_nNode2 -= rMvPos.GetIndex();
    1063           0 :             if(pIdx && !m_nNode2)
    1064           0 :                 m_nCntnt2 -= pIdx->GetIndex();
    1065             :         }
    1066             :     }
    1067             :     else
    1068           0 :         m_nNode2 = ULONG_MAX, m_nCntnt2 = STRING_NOTFOUND;
    1069           0 : }
    1070             : 
    1071           0 : void SaveBookmark::SetInDoc(
    1072             :     SwDoc* pDoc,
    1073             :     const SwNodeIndex& rNewPos,
    1074             :     const SwIndex* pIdx)
    1075             : {
    1076           0 :     SwPaM aPam(rNewPos.GetNode());
    1077           0 :     if(pIdx)
    1078           0 :         aPam.GetPoint()->nContent = *pIdx;
    1079             : 
    1080           0 :     if(ULONG_MAX != m_nNode2)
    1081             :     {
    1082           0 :         aPam.SetMark();
    1083             : 
    1084           0 :         if(m_bSaveOtherPos)
    1085             :         {
    1086           0 :             aPam.GetMark()->nNode += m_nNode2;
    1087           0 :             if(pIdx && !m_nNode2)
    1088           0 :                 aPam.GetMark()->nContent += m_nCntnt2;
    1089             :             else
    1090           0 :                 aPam.GetMark()->nContent.Assign(aPam.GetCntntNode(sal_False), m_nCntnt2);
    1091             :         }
    1092             :         else
    1093             :         {
    1094           0 :             aPam.GetMark()->nNode = m_nNode2;
    1095           0 :             aPam.GetMark()->nContent.Assign(aPam.GetCntntNode(sal_False), m_nCntnt2);
    1096             :         }
    1097             :     }
    1098             : 
    1099           0 :     if(m_bSavePos)
    1100             :     {
    1101           0 :         aPam.GetPoint()->nNode += m_nNode1;
    1102             : 
    1103           0 :         if(pIdx && !m_nNode1)
    1104           0 :             aPam.GetPoint()->nContent += m_nCntnt1;
    1105             :         else
    1106           0 :             aPam.GetPoint()->nContent.Assign(aPam.GetCntntNode(), m_nCntnt1);
    1107             :     }
    1108             :     else
    1109             :     {
    1110           0 :         aPam.GetPoint()->nNode = m_nNode1;
    1111           0 :         aPam.GetPoint()->nContent.Assign(aPam.GetCntntNode(), m_nCntnt1);
    1112             :     }
    1113             : 
    1114           0 :     if(!aPam.HasMark()
    1115           0 :         || CheckNodesRange(aPam.GetPoint()->nNode, aPam.GetMark()->nNode, sal_True))
    1116             :     {
    1117           0 :         ::sw::mark::IBookmark* const pBookmark = dynamic_cast< ::sw::mark::IBookmark* >(pDoc->getIDocumentMarkAccess()->makeMark(aPam, m_aName, m_eOrigBkmType));
    1118           0 :         if(pBookmark)
    1119             :         {
    1120           0 :             pBookmark->SetKeyCode(m_aCode);
    1121           0 :             pBookmark->SetShortName(m_aShortName);
    1122           0 :             if (m_pMetadataUndo)
    1123             :             {
    1124             :                 ::sfx2::Metadatable * const pMeta(
    1125           0 :                     dynamic_cast< ::sfx2::Metadatable* >(pBookmark));
    1126             :                 OSL_ENSURE(pMeta, "metadata undo, but not metadatable?");
    1127           0 :                 if (pMeta)
    1128             :                 {
    1129           0 :                     pMeta->RestoreMetadata(m_pMetadataUndo);
    1130             :                 }
    1131             :             }
    1132             :         }
    1133           0 :     }
    1134           0 : }
    1135             : 
    1136             : // _DelBookmarks, _{Save,Restore}CntntIdx
    1137             : 
    1138        1324 : void _DelBookmarks(
    1139             :     const SwNodeIndex& rStt,
    1140             :     const SwNodeIndex& rEnd,
    1141             :     ::std::vector<SaveBookmark> * pSaveBkmk,
    1142             :     const SwIndex* pSttIdx,
    1143             :     const SwIndex* pEndIdx)
    1144             : {
    1145             :     // illegal range ??
    1146        2724 :     if(rStt.GetIndex() > rEnd.GetIndex()
    1147        1400 :         || (rStt == rEnd && (!pSttIdx || pSttIdx->GetIndex() >= pEndIdx->GetIndex())))
    1148        1324 :         return;
    1149        1324 :     SwDoc* const pDoc = rStt.GetNode().GetDoc();
    1150             : 
    1151        1324 :     pDoc->getIDocumentMarkAccess()->deleteMarks(rStt, rEnd, pSaveBkmk, pSttIdx, pEndIdx);
    1152             : 
    1153             :     // Copy all Redlines which are in the move area into an array
    1154             :     // which holds all position information as offset.
    1155             :     // Assignement happens after moving.
    1156        1324 :     SwRedlineTbl& rTbl = (SwRedlineTbl&)pDoc->GetRedlineTbl();
    1157        1334 :     for(sal_uInt16 nCnt = 0; nCnt < rTbl.size(); ++nCnt )
    1158             :     {
    1159             :         // Is at position?
    1160          10 :         SwRedline* pRedl = rTbl[ nCnt ];
    1161             : 
    1162          10 :         SwPosition *pRStt = &pRedl->GetBound(sal_True),
    1163          10 :                    *pREnd = &pRedl->GetBound(sal_False);
    1164          10 :         if( *pRStt > *pREnd )
    1165             :         {
    1166          10 :             SwPosition *pTmp = pRStt; pRStt = pREnd, pREnd = pTmp;
    1167             :         }
    1168             : 
    1169          10 :         if( lcl_Greater( *pRStt, rStt, pSttIdx ) && lcl_Lower( *pRStt, rEnd, pEndIdx ))
    1170             :         {
    1171           0 :             pRStt->nNode = rEnd;
    1172           0 :             if( pEndIdx )
    1173           0 :                 pRStt->nContent = *pEndIdx;
    1174             :             else
    1175             :             {
    1176           0 :                 bool bStt = true;
    1177           0 :                 SwCntntNode* pCNd = pRStt->nNode.GetNode().GetCntntNode();
    1178           0 :                 if( !pCNd && 0 == ( pCNd = pDoc->GetNodes().GoNext( &pRStt->nNode )) )
    1179             :                 {
    1180           0 :                     bStt = false;
    1181           0 :                     pRStt->nNode = rStt;
    1182           0 :                     if( 0 == ( pCNd = pDoc->GetNodes().GoPrevious( &pRStt->nNode )) )
    1183             :                     {
    1184           0 :                         pRStt->nNode = pREnd->nNode;
    1185           0 :                         pCNd = pRStt->nNode.GetNode().GetCntntNode();
    1186             :                     }
    1187             :                 }
    1188           0 :                 xub_StrLen nTmp = bStt ? 0 : pCNd->Len();
    1189           0 :                 pRStt->nContent.Assign( pCNd, nTmp );
    1190             :             }
    1191             :         }
    1192          10 :         if( lcl_Greater( *pREnd, rStt, pSttIdx ) && lcl_Lower( *pREnd, rEnd, pEndIdx ))
    1193             :         {
    1194           0 :             pREnd->nNode = rStt;
    1195           0 :             if( pSttIdx )
    1196           0 :                 pREnd->nContent = *pSttIdx;
    1197             :             else
    1198             :             {
    1199           0 :                 bool bStt = false;
    1200           0 :                 SwCntntNode* pCNd = pREnd->nNode.GetNode().GetCntntNode();
    1201           0 :                 if( !pCNd && 0 == ( pCNd = pDoc->GetNodes().GoPrevious( &pREnd->nNode )) )
    1202             :                 {
    1203           0 :                     bStt = true;
    1204           0 :                     pREnd->nNode = rEnd;
    1205           0 :                     if( 0 == ( pCNd = pDoc->GetNodes().GoNext( &pREnd->nNode )) )
    1206             :                     {
    1207           0 :                         pREnd->nNode = pRStt->nNode;
    1208           0 :                         pCNd = pREnd->nNode.GetNode().GetCntntNode();
    1209             :                     }
    1210             :                 }
    1211           0 :                 xub_StrLen nTmp = bStt ? 0 : pCNd->Len();
    1212           0 :                 pREnd->nContent.Assign( pCNd, nTmp );
    1213             :             }
    1214             :         }
    1215             :     }
    1216             : }
    1217             : 
    1218        1226 : void _SaveCntntIdx(SwDoc* pDoc,
    1219             :     sal_uLong nNode,
    1220             :     xub_StrLen nCntnt,
    1221             :     std::vector<sal_uLong> &rSaveArr,
    1222             :     sal_uInt8 nSaveFly)
    1223             : {
    1224             :     // 1. Bookmarks
    1225        1226 :     _SwSaveTypeCountContent aSave;
    1226        1226 :     aSave.SetTypeAndCount( 0x8000, 0 );
    1227             : 
    1228        1226 :     IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
    1229        1226 :     const sal_Int32 nBkmks = pMarkAccess->getMarksCount();
    1230        1812 :     for(; aSave.GetCount() < nBkmks; aSave.IncCount())
    1231             :     {
    1232         586 :         bool bEqual = false;
    1233         586 :         bool bLower = false;
    1234         586 :         const ::sw::mark::IMark* pBkmk = (pMarkAccess->getMarksBegin() + aSave.GetCount())->get();
    1235         586 :         if(pBkmk->GetMarkPos().nNode.GetIndex() == nNode
    1236           0 :             && pBkmk->GetMarkPos().nContent.GetIndex() <= nCntnt)
    1237             :         {
    1238           0 :             if(pBkmk->GetMarkPos().nContent.GetIndex() < nCntnt)
    1239             :             {
    1240           0 :                 bLower = true; // a hint for the other position...
    1241           0 :                 aSave.SetContent(pBkmk->GetMarkPos().nContent.GetIndex());
    1242           0 :                 aSave.Add(rSaveArr);
    1243             :             }
    1244             :             else // if a bookmark position is equal nCntnt, the other position
    1245           0 :                 bEqual = true; // has to decide if it is added to the array
    1246             :         }
    1247             : 
    1248         604 :         if(pBkmk->IsExpanded()
    1249          18 :             && pBkmk->GetOtherMarkPos().nNode.GetIndex() == nNode
    1250           0 :             && pBkmk->GetOtherMarkPos().nContent.GetIndex() <= nCntnt)
    1251             :         {
    1252           0 :             if(bLower || pBkmk->GetOtherMarkPos().nContent.GetIndex() < nCntnt)
    1253             :             {
    1254           0 :                 if(bEqual)
    1255             :                 { // the other position is before, the (main) position is equal
    1256           0 :                     aSave.SetContent(pBkmk->GetMarkPos().nContent.GetIndex());
    1257           0 :                     aSave.Add(rSaveArr);
    1258             :                 }
    1259           0 :                 aSave.SetContent(pBkmk->GetOtherMarkPos().nContent.GetIndex());
    1260           0 :                 aSave.IncType();
    1261           0 :                 aSave.Add(rSaveArr);
    1262           0 :                 aSave.DecType();
    1263             :             }
    1264             :         }
    1265             :     }
    1266             : 
    1267             :     // 2. Redlines
    1268        1226 :     aSave.SetTypeAndCount( 0x1000, 0 );
    1269        1226 :     const SwRedlineTbl& rRedlTbl = pDoc->GetRedlineTbl();
    1270        1230 :     for( ; aSave.GetCount() < rRedlTbl.size(); aSave.IncCount() )
    1271             :     {
    1272           4 :         const SwRedline* pRdl = rRedlTbl[ aSave.GetCount() ];
    1273           4 :         int nPointPos = lcl_RelativePosition( *pRdl->GetPoint(), nNode, nCntnt );
    1274           8 :         int nMarkPos = pRdl->HasMark() ? lcl_RelativePosition( *pRdl->GetMark(), nNode, nCntnt ) :
    1275           8 :                                           nPointPos;
    1276             :         // #i59534: We have to store the positions inside the same node before the insert position
    1277             :         // and the one at the insert position if the corresponding Point/Mark position is before
    1278             :         // the insert position.
    1279           4 :         if( nPointPos == BEFORE_SAME_NODE ||
    1280             :             ( nPointPos == SAME_POSITION && nMarkPos < SAME_POSITION ) )
    1281             :         {
    1282           0 :             aSave.SetContent( pRdl->GetPoint()->nContent.GetIndex() );
    1283           0 :             aSave.IncType();
    1284           0 :             aSave.Add( rSaveArr );
    1285           0 :             aSave.DecType();
    1286             :         }
    1287           4 :         if( pRdl->HasMark() && ( nMarkPos == BEFORE_SAME_NODE ||
    1288             :             ( nMarkPos == SAME_POSITION && nPointPos < SAME_POSITION ) ) )
    1289             :         {
    1290           0 :             aSave.SetContent( pRdl->GetMark()->nContent.GetIndex() );
    1291           0 :             aSave.Add( rSaveArr );
    1292             :         }
    1293             :     }
    1294             : 
    1295             :     // 4. Paragraph anchored objects
    1296             :     {
    1297        1226 :         SwCntntNode *pNode = pDoc->GetNodes()[nNode]->GetCntntNode();
    1298        1226 :         if( pNode )
    1299             :         {
    1300             : 
    1301        1226 :             SwFrm* pFrm = pNode->getLayoutFrm( pDoc->GetCurrentLayout() );
    1302             : #if OSL_DEBUG_LEVEL > 1
    1303             :             static bool bViaDoc = false;
    1304             :             if( bViaDoc )
    1305             :                 pFrm = NULL;
    1306             : #endif
    1307        1226 :             if( pFrm ) // Do we have a layout? Then it's a bit cheaper ...
    1308             :             {
    1309           0 :                 if( pFrm->GetDrawObjs() )
    1310             :                 {
    1311           0 :                     const SwSortedObjs& rDObj = *pFrm->GetDrawObjs();
    1312           0 :                     for( sal_uInt32 n = rDObj.Count(); n; )
    1313             :                     {
    1314           0 :                         SwAnchoredObject* pObj = rDObj[ --n ];
    1315           0 :                         const SwFrmFmt& rFmt = pObj->GetFrmFmt();
    1316           0 :                         const SwFmtAnchor& rAnchor = rFmt.GetAnchor();
    1317           0 :                         SwPosition const*const pAPos = rAnchor.GetCntntAnchor();
    1318           0 :                         if ( pAPos &&
    1319             :                              ( ( nSaveFly &&
    1320           0 :                                  FLY_AT_PARA == rAnchor.GetAnchorId() ) ||
    1321           0 :                                ( FLY_AT_CHAR == rAnchor.GetAnchorId() ) ) )
    1322             :                         {
    1323           0 :                             aSave.SetType( 0x2000 );
    1324           0 :                             aSave.SetContent( pAPos->nContent.GetIndex() );
    1325             : 
    1326             :                             OSL_ENSURE( nNode == pAPos->nNode.GetIndex(),
    1327             :                                     "_SaveCntntIdx: Wrong Node-Index" );
    1328           0 :                             if ( FLY_AT_CHAR == rAnchor.GetAnchorId() )
    1329             :                             {
    1330           0 :                                 if( nCntnt <= aSave.GetContent() )
    1331             :                                 {
    1332           0 :                                     if( SAVEFLY_SPLIT == nSaveFly )
    1333           0 :                                         aSave.IncType(); // = 0x2001;
    1334             :                                     else
    1335           0 :                                         continue;
    1336             :                                 }
    1337             :                             }
    1338           0 :                             aSave.SetCount( pDoc->GetSpzFrmFmts()->size() );
    1339           0 :                             while( aSave.GetCount() &&
    1340           0 :                                     &rFmt != (*pDoc->GetSpzFrmFmts())[
    1341           0 :                                     aSave.DecCount() ] )
    1342             :                                 ; // nothing
    1343             :                             OSL_ENSURE( &rFmt == (*pDoc->GetSpzFrmFmts())[
    1344             :                                                     aSave.GetCount() ],
    1345             :                                     "_SaveCntntIdx: Lost FrameFormat" );
    1346           0 :                             aSave.Add( rSaveArr );
    1347             :                         }
    1348             :                     }
    1349             :                 }
    1350             :             }
    1351             :             else // No layout, so it's a bit more expensive ...
    1352             :             {
    1353        3246 :                 for( aSave.SetCount( pDoc->GetSpzFrmFmts()->size() );
    1354        2020 :                         aSave.GetCount() ; )
    1355             :                 {
    1356         794 :                     SwFrmFmt* pFrmFmt = (*pDoc->GetSpzFrmFmts())[
    1357        1588 :                                                 aSave.DecCount() ];
    1358         994 :                     if ( RES_FLYFRMFMT != pFrmFmt->Which() &&
    1359         200 :                             RES_DRAWFRMFMT != pFrmFmt->Which() )
    1360           0 :                         continue;
    1361             : 
    1362         794 :                     const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
    1363         794 :                     SwPosition const*const pAPos = rAnchor.GetCntntAnchor();
    1364         794 :                     if ( pAPos && ( nNode == pAPos->nNode.GetIndex() ) &&
    1365           0 :                          ( FLY_AT_PARA == rAnchor.GetAnchorId() ||
    1366           0 :                            FLY_AT_CHAR == rAnchor.GetAnchorId() ) )
    1367             :                     {
    1368           0 :                         aSave.SetType( 0x2000 );
    1369           0 :                         aSave.SetContent( pAPos->nContent.GetIndex() );
    1370           0 :                         if ( FLY_AT_CHAR == rAnchor.GetAnchorId() )
    1371             :                         {
    1372           0 :                             if( nCntnt <= aSave.GetContent() )
    1373             :                             {
    1374           0 :                                 if( SAVEFLY_SPLIT == nSaveFly )
    1375           0 :                                     aSave.IncType(); // = 0x2001;
    1376             :                                 else
    1377           0 :                                     continue;
    1378             :                             }
    1379             :                         }
    1380           0 :                         aSave.Add( rSaveArr );
    1381             :                     }
    1382             :                 }
    1383             :             }
    1384             :         }
    1385             :     }
    1386             :     // 5. CrsrShell
    1387             :     {
    1388        1226 :         SwCrsrShell* pShell = pDoc->GetEditShell();
    1389        1226 :         if( pShell )
    1390             :         {
    1391           0 :             aSave.SetTypeAndCount( 0x800, 0 );
    1392           0 :             FOREACHSHELL_START( pShell )
    1393           0 :                 SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
    1394           0 :                 if( _pStkCrsr )
    1395           0 :                 do {
    1396             :                     lcl_ChkPaM( rSaveArr, nNode, nCntnt, *_pStkCrsr,
    1397           0 :                                 aSave, false );
    1398           0 :                     aSave.IncCount();
    1399             :                 } while ( (_pStkCrsr != 0 ) &&
    1400           0 :                     ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
    1401             : 
    1402           0 :                 FOREACHPAM_START( PCURSH->_GetCrsr() )
    1403             :                     lcl_ChkPaM( rSaveArr, nNode, nCntnt, *PCURCRSR,
    1404           0 :                                 aSave, false );
    1405           0 :                     aSave.IncCount();
    1406           0 :                 FOREACHPAM_END()
    1407             : 
    1408           0 :             FOREACHSHELL_END( pShell )
    1409             :         }
    1410             :     }
    1411             :     // 6. UnoCrsr
    1412             :     {
    1413        1226 :         aSave.SetTypeAndCount( 0x400, 0 );
    1414        1226 :         const SwUnoCrsrTbl& rTbl = pDoc->GetUnoCrsrTbl();
    1415        6804 :         for (SwUnoCrsrTbl::const_iterator it = rTbl.begin();
    1416        4536 :                 it != rTbl.end(); ++it)
    1417             :         {
    1418        2084 :             FOREACHPAM_START( *it )
    1419        1042 :                 lcl_ChkPaM( rSaveArr, nNode, nCntnt, *PCURCRSR, aSave, false );
    1420        1042 :                 aSave.IncCount();
    1421        1042 :             FOREACHPAM_END()
    1422             : 
    1423             :             SwUnoTableCrsr* pUnoTblCrsr =
    1424        1042 :                 dynamic_cast<SwUnoTableCrsr*>(*it);
    1425        1042 :             if( pUnoTblCrsr )
    1426             :             {
    1427           0 :                 FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
    1428           0 :                     lcl_ChkPaM( rSaveArr, nNode, nCntnt, *PCURCRSR, aSave, false );
    1429           0 :                     aSave.IncCount();
    1430           0 :                 FOREACHPAM_END()
    1431             :             }
    1432             :         }
    1433             :     }
    1434        1226 : }
    1435             : 
    1436             : 
    1437           0 : void _RestoreCntntIdx(SwDoc* pDoc,
    1438             :     std::vector<sal_uLong> &rSaveArr,
    1439             :     sal_uLong nNode,
    1440             :     xub_StrLen nOffset,
    1441             :     bool bAuto)
    1442             : {
    1443           0 :     SwCntntNode* pCNd = pDoc->GetNodes()[ nNode ]->GetCntntNode();
    1444           0 :     const SwRedlineTbl& rRedlTbl = pDoc->GetRedlineTbl();
    1445           0 :     SwFrmFmts* pSpz = pDoc->GetSpzFrmFmts();
    1446           0 :     IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
    1447           0 :     sal_uInt16 n = 0;
    1448           0 :     while( n < rSaveArr.size() )
    1449             :     {
    1450           0 :         _SwSaveTypeCountContent aSave( rSaveArr, n );
    1451           0 :         SwPosition* pPos = 0;
    1452           0 :         switch( aSave.GetType() )
    1453             :         {
    1454             :             case 0x8000:
    1455             :             {
    1456           0 :                 MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getMarksBegin()[aSave.GetCount()].get());
    1457           0 :                 SwPosition aNewPos(pMark->GetMarkPos());
    1458           0 :                 aNewPos.nNode = *pCNd;
    1459           0 :                 aNewPos.nContent.Assign(pCNd, aSave.GetContent() + nOffset);
    1460           0 :                 pMark->SetMarkPos(aNewPos);
    1461             :             }
    1462           0 :             break;
    1463             :             case 0x8001:
    1464             :             {
    1465           0 :                 MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getMarksBegin()[aSave.GetCount()].get());
    1466           0 :                 SwPosition aNewPos(pMark->GetOtherMarkPos());
    1467           0 :                 aNewPos.nNode = *pCNd;
    1468           0 :                 aNewPos.nContent.Assign(pCNd, aSave.GetContent() + nOffset);
    1469           0 :                 pMark->SetOtherMarkPos(aNewPos);
    1470             :             }
    1471           0 :             break;
    1472             :             case 0x1001:
    1473           0 :                 pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetPoint();
    1474           0 :                 break;
    1475             :             case 0x1000:
    1476           0 :                 pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetMark();
    1477           0 :                 break;
    1478             :             case 0x2000:
    1479             :                 {
    1480           0 :                     SwFrmFmt *pFrmFmt = (*pSpz)[ aSave.GetCount() ];
    1481           0 :                     const SwFmtAnchor& rFlyAnchor = pFrmFmt->GetAnchor();
    1482           0 :                     if( rFlyAnchor.GetCntntAnchor() )
    1483             :                     {
    1484           0 :                         SwFmtAnchor aNew( rFlyAnchor );
    1485           0 :                         SwPosition aNewPos( *rFlyAnchor.GetCntntAnchor() );
    1486           0 :                         aNewPos.nNode = *pCNd;
    1487           0 :                         if ( FLY_AT_CHAR == rFlyAnchor.GetAnchorId() )
    1488             :                         {
    1489             :                             aNewPos.nContent.Assign( pCNd,
    1490           0 :                                                      aSave.GetContent() + nOffset );
    1491             :                         }
    1492             :                         else
    1493             :                         {
    1494           0 :                             aNewPos.nContent.Assign( 0, 0 );
    1495             :                         }
    1496           0 :                         aNew.SetAnchor( &aNewPos );
    1497           0 :                         pFrmFmt->SetFmtAttr( aNew );
    1498             :                     }
    1499             :                 }
    1500           0 :                 break;
    1501             :             case 0x2001:
    1502           0 :                 if( bAuto )
    1503             :                 {
    1504           0 :                     SwFrmFmt *pFrmFmt = (*pSpz)[ aSave.GetCount() ];
    1505           0 :                     SfxPoolItem *pAnchor = (SfxPoolItem*)&pFrmFmt->GetAnchor();
    1506           0 :                     pFrmFmt->NotifyClients( pAnchor, pAnchor );
    1507             :                 }
    1508           0 :                 break;
    1509             : 
    1510             :             case 0x0800:
    1511             :             case 0x0801:
    1512             :                 {
    1513           0 :                     SwCrsrShell* pShell = pDoc->GetEditShell();
    1514           0 :                     if( pShell )
    1515             :                     {
    1516           0 :                         sal_uInt16 nCnt = 0;
    1517           0 :                         FOREACHSHELL_START( pShell )
    1518           0 :                             SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
    1519           0 :                             if( _pStkCrsr )
    1520           0 :                             do {
    1521           0 :                                 if( aSave.GetCount() == nCnt )
    1522             :                                 {
    1523             :                                     pPos = &_pStkCrsr->GetBound( 0x0800 ==
    1524           0 :                                                         aSave.GetType() );
    1525           0 :                                     break;
    1526             :                                 }
    1527           0 :                                 ++nCnt;
    1528             :                             } while ( (_pStkCrsr != 0 ) &&
    1529           0 :                                 ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
    1530             : 
    1531           0 :                             if( pPos )
    1532           0 :                                 break;
    1533             : 
    1534           0 :                             FOREACHPAM_START( PCURSH->_GetCrsr() )
    1535           0 :                                 if( aSave.GetCount() == nCnt )
    1536             :                                 {
    1537             :                                     pPos = &PCURCRSR->GetBound( 0x0800 ==
    1538           0 :                                                         aSave.GetType() );
    1539           0 :                                     break;
    1540             :                                 }
    1541           0 :                                 ++nCnt;
    1542           0 :                             FOREACHPAM_END()
    1543           0 :                             if( pPos )
    1544           0 :                                 break;
    1545             : 
    1546           0 :                         FOREACHSHELL_END( pShell )
    1547             :                     }
    1548             :             }
    1549           0 :             break;
    1550             : 
    1551             :         case 0x0400:
    1552             :         case 0x0401:
    1553             :             {
    1554           0 :                 sal_uInt16 nCnt = 0;
    1555           0 :                 const SwUnoCrsrTbl& rTbl = pDoc->GetUnoCrsrTbl();
    1556           0 :                 for (SwUnoCrsrTbl::const_iterator it = rTbl.begin();
    1557           0 :                         it != rTbl.end(); ++it)
    1558             :                 {
    1559           0 :                     FOREACHPAM_START( *it )
    1560           0 :                         if( aSave.GetCount() == nCnt )
    1561             :                         {
    1562             :                             pPos = &PCURCRSR->GetBound( 0x0400 ==
    1563           0 :                                                     aSave.GetType() );
    1564           0 :                             break;
    1565             :                         }
    1566           0 :                         ++nCnt;
    1567           0 :                     FOREACHPAM_END()
    1568           0 :                     if( pPos )
    1569           0 :                         break;
    1570             : 
    1571             :                     SwUnoTableCrsr* pUnoTblCrsr =
    1572           0 :                         dynamic_cast<SwUnoTableCrsr*>(*it);
    1573           0 :                     if ( pUnoTblCrsr )
    1574             :                     {
    1575           0 :                         FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
    1576           0 :                             if( aSave.GetCount() == nCnt )
    1577             :                             {
    1578             :                                 pPos = &PCURCRSR->GetBound( 0x0400 ==
    1579           0 :                                                     aSave.GetType() );
    1580           0 :                                 break;
    1581             :                             }
    1582           0 :                             ++nCnt;
    1583           0 :                         FOREACHPAM_END()
    1584             :                     }
    1585           0 :                     if ( pPos )
    1586           0 :                         break;
    1587             :                 }
    1588             :             }
    1589           0 :             break;
    1590             :         }
    1591             : 
    1592           0 :         if( pPos )
    1593             :         {
    1594           0 :             pPos->nNode = *pCNd;
    1595           0 :             pPos->nContent.Assign( pCNd, aSave.GetContent() + nOffset );
    1596             :         }
    1597             :     }
    1598           0 : }
    1599             : 
    1600           0 : void _RestoreCntntIdx(std::vector<sal_uLong> &rSaveArr,
    1601             :     const SwNode& rNd,
    1602             :     xub_StrLen nLen,
    1603             :     xub_StrLen nChkLen)
    1604             : {
    1605           0 :     const SwDoc* pDoc = rNd.GetDoc();
    1606           0 :     const SwRedlineTbl& rRedlTbl = pDoc->GetRedlineTbl();
    1607           0 :     const SwFrmFmts* pSpz = pDoc->GetSpzFrmFmts();
    1608           0 :     const IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
    1609           0 :     SwCntntNode* pCNd = (SwCntntNode*)rNd.GetCntntNode();
    1610             : 
    1611           0 :     sal_uInt16 n = 0;
    1612           0 :     while( n < rSaveArr.size() )
    1613             :     {
    1614           0 :         _SwSaveTypeCountContent aSave( rSaveArr, n );
    1615           0 :         if( aSave.GetContent() >= nChkLen )
    1616           0 :             rSaveArr[ n-1 ] -= nChkLen;
    1617             :         else
    1618             :         {
    1619           0 :             SwPosition* pPos = 0;
    1620           0 :             switch( aSave.GetType() )
    1621             :             {
    1622             :             case 0x8000:
    1623             :             {
    1624           0 :                 MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getMarksBegin()[aSave.GetCount()].get());
    1625           0 :                 SwPosition aNewPos(pMark->GetMarkPos());
    1626           0 :                 aNewPos.nNode = rNd;
    1627           0 :                 aNewPos.nContent.Assign(pCNd, Min(aSave.GetContent(), nLen));
    1628           0 :                 pMark->SetMarkPos(aNewPos);
    1629             :             }
    1630           0 :             break;
    1631             :             case 0x8001:
    1632             :             {
    1633           0 :                 MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getMarksBegin()[aSave.GetCount()].get());
    1634           0 :                 SwPosition aNewPos(pMark->GetOtherMarkPos());
    1635           0 :                 aNewPos.nNode = rNd;
    1636           0 :                 aNewPos.nContent.Assign(pCNd, Min(aSave.GetContent(), nLen));
    1637           0 :                 pMark->SetOtherMarkPos(aNewPos);
    1638             :             }
    1639           0 :             break;
    1640             :             case 0x1001:
    1641           0 :                 pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetPoint();
    1642           0 :                 break;
    1643             :             case 0x1000:
    1644           0 :                 pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetMark();
    1645           0 :                 break;
    1646             :             case 0x2000:
    1647             :             case 0x2001:
    1648             :                 {
    1649           0 :                     SwFrmFmt *pFrmFmt = (*pSpz)[ aSave.GetCount() ];
    1650           0 :                     const SwFmtAnchor& rFlyAnchor = pFrmFmt->GetAnchor();
    1651           0 :                     if( rFlyAnchor.GetCntntAnchor() )
    1652             :                     {
    1653           0 :                         SwFmtAnchor aNew( rFlyAnchor );
    1654           0 :                         SwPosition aNewPos( *rFlyAnchor.GetCntntAnchor() );
    1655           0 :                         aNewPos.nNode = rNd;
    1656           0 :                         if ( FLY_AT_CHAR == rFlyAnchor.GetAnchorId() )
    1657             :                         {
    1658             :                             aNewPos.nContent.Assign( pCNd, Min(
    1659           0 :                                                      aSave.GetContent(), nLen ) );
    1660             :                         }
    1661             :                         else
    1662             :                         {
    1663           0 :                             aNewPos.nContent.Assign( 0, 0 );
    1664             :                         }
    1665           0 :                         aNew.SetAnchor( &aNewPos );
    1666           0 :                         pFrmFmt->SetFmtAttr( aNew );
    1667             :                     }
    1668             :                 }
    1669           0 :                 break;
    1670             : 
    1671             :             case 0x0800:
    1672             :             case 0x0801:
    1673             :                 {
    1674           0 :                     SwCrsrShell* pShell = pDoc->GetEditShell();
    1675           0 :                     if( pShell )
    1676             :                     {
    1677           0 :                         sal_uInt16 nCnt = 0;
    1678           0 :                         FOREACHSHELL_START( pShell )
    1679           0 :                             SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
    1680           0 :                             if( _pStkCrsr )
    1681           0 :                             do {
    1682           0 :                                 if( aSave.GetCount() == nCnt )
    1683             :                                 {
    1684             :                                     pPos = &_pStkCrsr->GetBound( 0x0800 ==
    1685           0 :                                                 aSave.GetType() );
    1686           0 :                                     break;
    1687             :                                 }
    1688           0 :                                 ++nCnt;
    1689             :                             } while ( (_pStkCrsr != 0 ) &&
    1690           0 :                                 ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
    1691             : 
    1692           0 :                             if( pPos )
    1693           0 :                                 break;
    1694             : 
    1695           0 :                             FOREACHPAM_START( PCURSH->_GetCrsr() )
    1696           0 :                                 if( aSave.GetCount() == nCnt )
    1697             :                                 {
    1698             :                                     pPos = &PCURCRSR->GetBound( 0x0800 ==
    1699           0 :                                                 aSave.GetType() );
    1700           0 :                                     break;
    1701             :                                 }
    1702           0 :                                 ++nCnt;
    1703           0 :                             FOREACHPAM_END()
    1704           0 :                             if( pPos )
    1705           0 :                                 break;
    1706             : 
    1707           0 :                         FOREACHSHELL_END( pShell )
    1708             :                     }
    1709             :                 }
    1710           0 :                 break;
    1711             : 
    1712             :             case 0x0400:
    1713             :             case 0x0401:
    1714             :                 {
    1715           0 :                     sal_uInt16 nCnt = 0;
    1716           0 :                     const SwUnoCrsrTbl& rTbl = pDoc->GetUnoCrsrTbl();
    1717           0 :                     for (SwUnoCrsrTbl::const_iterator it = rTbl.begin();
    1718           0 :                             it != rTbl.end(); ++it)
    1719             :                     {
    1720           0 :                         FOREACHPAM_START( *it )
    1721           0 :                             if( aSave.GetCount() == nCnt )
    1722             :                             {
    1723             :                                 pPos = &PCURCRSR->GetBound( 0x0400 ==
    1724           0 :                                                     aSave.GetType() );
    1725           0 :                                 break;
    1726             :                             }
    1727           0 :                             ++nCnt;
    1728           0 :                         FOREACHPAM_END()
    1729           0 :                         if( pPos )
    1730           0 :                             break;
    1731             : 
    1732             :                         SwUnoTableCrsr* pUnoTblCrsr =
    1733           0 :                             dynamic_cast<SwUnoTableCrsr*>(*it);
    1734           0 :                         if ( pUnoTblCrsr )
    1735             :                         {
    1736           0 :                             FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
    1737           0 :                                 if( aSave.GetCount() == nCnt )
    1738             :                                 {
    1739             :                                     pPos = &PCURCRSR->GetBound( 0x0400 ==
    1740           0 :                                                     aSave.GetType() );
    1741           0 :                                     break;
    1742             :                                 }
    1743           0 :                                 ++nCnt;
    1744           0 :                             FOREACHPAM_END()
    1745             :                         }
    1746           0 :                         if ( pPos )
    1747           0 :                             break;
    1748             :                     }
    1749             :                 }
    1750           0 :                 break;
    1751             :             }
    1752             : 
    1753           0 :             if( pPos )
    1754             :             {
    1755           0 :                 pPos->nNode = rNd;
    1756           0 :                 pPos->nContent.Assign( pCNd, Min( aSave.GetContent(), nLen ) );
    1757             :             }
    1758           0 :             n -= 2;
    1759           0 :             rSaveArr.erase( rSaveArr.begin() + n, rSaveArr.begin() + n + 2);
    1760             :         }
    1761             :     }
    1762          72 : }
    1763             : 
    1764             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10