LCOV - code coverage report
Current view: top level - sw/source/core/doc - docbm.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 436 580 75.2 %
Date: 2015-06-13 12:38:46 Functions: 54 65 83.1 %
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 <boost/function.hpp>
      24             : #include <cntfrm.hxx>
      25             : #include <crossrefbookmark.hxx>
      26             : #include <annotationmark.hxx>
      27             : #include <dcontact.hxx>
      28             : #include <doc.hxx>
      29             : #include <IDocumentRedlineAccess.hxx>
      30             : #include <IDocumentState.hxx>
      31             : #include <IDocumentUndoRedo.hxx>
      32             : #include <docary.hxx>
      33             : #include <xmloff/odffields.hxx>
      34             : #include <editsh.hxx>
      35             : #include <fmtanchr.hxx>
      36             : #include <frmfmt.hxx>
      37             : #include <functional>
      38             : #include <hintids.hxx>
      39             : #include <mvsave.hxx>
      40             : #include <ndtxt.hxx>
      41             : #include <node.hxx>
      42             : #include <pam.hxx>
      43             : #include <redline.hxx>
      44             : #include <rolbck.hxx>
      45             : #include <rtl/ustrbuf.hxx>
      46             : #include <rtl/ustring.hxx>
      47             : #include <sal/types.h>
      48             : #include <sortedobjs.hxx>
      49             : #include <sfx2/linkmgr.hxx>
      50             : #include <swserv.hxx>
      51             : #include <swundo.hxx>
      52             : #include <UndoBookmark.hxx>
      53             : #include <unocrsr.hxx>
      54             : #include <viscrs.hxx>
      55             : #include <edimp.hxx>
      56             : #include <tools/datetimeutils.hxx>
      57             : 
      58             : using namespace ::boost;
      59             : using namespace ::sw::mark;
      60             : 
      61             : namespace
      62             : {
      63      117255 :     static bool lcl_GreaterThan( const SwPosition& rPos, const SwNodeIndex& rNdIdx, const SwIndex* pIdx )
      64             :     {
      65             :         return pIdx != NULL
      66       49410 :                ? ( rPos.nNode > rNdIdx
      67       53607 :                    || ( rPos.nNode == rNdIdx
      68        1734 :                         && rPos.nContent >= pIdx->GetIndex() ) )
      69      166665 :                : rPos.nNode >= rNdIdx;
      70             :     }
      71             : 
      72       74279 :     static bool lcl_Lower( const SwPosition& rPos, const SwNodeIndex& rNdIdx, const SwIndex* pIdx )
      73             :     {
      74       74279 :         return rPos.nNode < rNdIdx
      75       75582 :                || ( pIdx != NULL
      76        4330 :                     && rPos.nNode == rNdIdx
      77       74805 :                     && rPos.nContent < pIdx->GetIndex() );
      78             :     }
      79             : 
      80      389639 :     static bool lcl_MarkOrderingByStart(const IDocumentMarkAccess::pMark_t& rpFirst,
      81             :         const IDocumentMarkAccess::pMark_t& rpSecond)
      82             :     {
      83      389639 :         return rpFirst->GetMarkStart() < rpSecond->GetMarkStart();
      84             :     }
      85             : 
      86           0 :     static bool lcl_MarkOrderingByEnd(const IDocumentMarkAccess::pMark_t& rpFirst,
      87             :         const IDocumentMarkAccess::pMark_t& rpSecond)
      88             :     {
      89           0 :         return rpFirst->GetMarkEnd() < rpSecond->GetMarkEnd();
      90             :     }
      91             : 
      92      115394 :     static void lcl_InsertMarkSorted(IDocumentMarkAccess::container_t& io_vMarks,
      93             :         const IDocumentMarkAccess::pMark_t& pMark)
      94             :     {
      95             :         io_vMarks.insert(
      96             :             lower_bound(
      97             :                 io_vMarks.begin(),
      98             :                 io_vMarks.end(),
      99             :                 pMark,
     100             :                 &lcl_MarkOrderingByStart),
     101      115394 :             pMark);
     102      115394 :     }
     103             : 
     104           1 :     static inline ::std::unique_ptr<SwPosition> lcl_PositionFromContentNode(
     105             :         SwContentNode * const pContentNode,
     106             :         const bool bAtEnd=false)
     107             :     {
     108           1 :         ::std::unique_ptr<SwPosition> pResult(new SwPosition(*pContentNode));
     109           1 :         pResult->nContent.Assign(pContentNode, bAtEnd ? pContentNode->Len() : 0);
     110           1 :         return pResult;
     111             :     }
     112             : 
     113             :     // return a position at the begin of rEnd, if it is a ContentNode
     114             :     // else set it to the begin of the Node after rEnd, if there is one
     115             :     // else set it to the end of the node before rStt
     116             :     // else set it to the ContentNode of the Pos outside the Range
     117           1 :     static inline ::std::unique_ptr<SwPosition> lcl_FindExpelPosition(
     118             :         const SwNodeIndex& rStt,
     119             :         const SwNodeIndex& rEnd,
     120             :         const SwPosition& rOtherPosition)
     121             :     {
     122           1 :         SwContentNode * pNode = rEnd.GetNode().GetContentNode();
     123           1 :         bool bPosAtEndOfNode = false;
     124           1 :         if ( pNode == NULL)
     125             :         {
     126           0 :             SwNodeIndex aEnd = SwNodeIndex(rEnd);
     127           0 :             pNode = rEnd.GetNodes().GoNext( &aEnd );
     128           0 :             bPosAtEndOfNode = false;
     129             :         }
     130           1 :         if ( pNode == NULL )
     131             :         {
     132           0 :             SwNodeIndex aStt = SwNodeIndex(rStt);
     133           0 :             pNode = SwNodes::GoPrevious(&aStt);
     134           0 :             bPosAtEndOfNode = true;
     135             :         }
     136           1 :         if ( pNode != NULL )
     137             :         {
     138           1 :             return lcl_PositionFromContentNode( pNode, bPosAtEndOfNode );
     139             :         }
     140             : 
     141           0 :         return ::std::unique_ptr<SwPosition>(new SwPosition(rOtherPosition));
     142             :     }
     143             : 
     144           1 :     static IMark* lcl_getMarkAfter(const IDocumentMarkAccess::container_t& rMarks, const SwPosition& rPos)
     145             :     {
     146             :         IDocumentMarkAccess::const_iterator_t pMarkAfter = upper_bound(
     147             :             rMarks.begin(),
     148             :             rMarks.end(),
     149             :             rPos,
     150           1 :             sw::mark::CompareIMarkStartsAfter());
     151           1 :         if(pMarkAfter == rMarks.end()) return NULL;
     152           1 :         return pMarkAfter->get();
     153             :     };
     154             : 
     155           0 :     static IMark* lcl_getMarkBefore(const IDocumentMarkAccess::container_t& rMarks, const SwPosition& rPos)
     156             :     {
     157             :         // candidates from which to choose the mark before
     158           0 :         IDocumentMarkAccess::container_t vCandidates;
     159             :         // no need to consider marks starting after rPos
     160             :         IDocumentMarkAccess::const_iterator_t pCandidatesEnd = upper_bound(
     161             :             rMarks.begin(),
     162             :             rMarks.end(),
     163             :             rPos,
     164           0 :             sw::mark::CompareIMarkStartsAfter());
     165           0 :         vCandidates.reserve(pCandidatesEnd - rMarks.begin());
     166             :         // only marks ending before are candidates
     167             :         remove_copy_if(
     168             :             rMarks.begin(),
     169             :             pCandidatesEnd,
     170             :             back_inserter(vCandidates),
     171           0 :             boost::bind( ::std::logical_not<bool>(), boost::bind( &IMark::EndsBefore, _1, rPos ) ) );
     172             :         // no candidate left => we are in front of the first mark or there are none
     173           0 :         if(!vCandidates.size()) return NULL;
     174             :         // return the highest (last) candidate using mark end ordering
     175           0 :         return max_element(vCandidates.begin(), vCandidates.end(), &lcl_MarkOrderingByEnd)->get();
     176             :     }
     177             : 
     178       42804 :     static bool lcl_FixCorrectedMark(
     179             :         const bool bChangedPos,
     180             :         const bool bChangedOPos,
     181             :         MarkBase* io_pMark )
     182             :     {
     183       42804 :         if ( IDocumentMarkAccess::GetType(*io_pMark) == IDocumentMarkAccess::MarkType::ANNOTATIONMARK )
     184             :         {
     185             :             // annotation marks are allowed to span a table cell range.
     186             :             // but trigger sorting to be save
     187          23 :             return true;
     188             :         }
     189             : 
     190       84242 :         if ( ( bChangedPos || bChangedOPos )
     191        1602 :              && io_pMark->IsExpanded()
     192       45795 :              && io_pMark->GetOtherMarkPos().nNode.GetNode().FindTableBoxStartNode() !=
     193        1507 :                     io_pMark->GetMarkPos().nNode.GetNode().FindTableBoxStartNode() )
     194             :         {
     195           0 :             if ( !bChangedOPos )
     196             :             {
     197           0 :                 io_pMark->SetMarkPos( io_pMark->GetOtherMarkPos() );
     198             :             }
     199           0 :             io_pMark->ClearOtherMarkPos();
     200           0 :             DdeBookmark * const pDdeBkmk = dynamic_cast< DdeBookmark*>(io_pMark);
     201           0 :             if ( pDdeBkmk != NULL
     202           0 :                  && pDdeBkmk->IsServer() )
     203             :             {
     204           0 :                 pDdeBkmk->SetRefObject(NULL);
     205             :             }
     206           0 :             return true;
     207             :         }
     208       42781 :         return false;
     209             :     }
     210             : 
     211         455 :     static IDocumentMarkAccess::iterator_t lcl_FindMark(
     212             :         IDocumentMarkAccess::container_t& rMarks,
     213             :         const IDocumentMarkAccess::pMark_t& rpMarkToFind)
     214             :     {
     215             :         IDocumentMarkAccess::iterator_t ppCurrentMark = lower_bound(
     216             :             rMarks.begin(), rMarks.end(),
     217         455 :             rpMarkToFind, &lcl_MarkOrderingByStart);
     218             :         // since there are usually not too many marks on the same start
     219             :         // position, we are not doing a bisect search for the upper bound
     220             :         // but instead start to iterate from pMarkLow directly
     221         971 :         while(ppCurrentMark != rMarks.end() && **ppCurrentMark == *rpMarkToFind)
     222             :         {
     223         516 :             if(ppCurrentMark->get() == rpMarkToFind.get())
     224             :             {
     225             :                 //OSL_TRACE("found mark named '%s'",
     226             :                 //    OUStringToOString(ppCurrentMark->get()->GetName(), RTL_TEXTENCODING_UTF8).getStr());
     227         455 :                 return ppCurrentMark;
     228             :             }
     229          61 :             ++ppCurrentMark;
     230             :         }
     231             :         // reached a mark starting on a later start pos or the end of the
     232             :         // vector => not found
     233           0 :         return rMarks.end();
     234             :     };
     235             : 
     236         524 :     static IDocumentMarkAccess::iterator_t lcl_FindMarkAtPos(
     237             :         IDocumentMarkAccess::container_t& rMarks,
     238             :         const SwPosition& rPos,
     239             :         const IDocumentMarkAccess::MarkType eType)
     240             :     {
     241        1605 :         for(IDocumentMarkAccess::iterator_t ppCurrentMark = lower_bound(
     242             :                 rMarks.begin(), rMarks.end(),
     243             :                 rPos,
     244         524 :                 sw::mark::CompareIMarkStartsBefore());
     245        1070 :             ppCurrentMark != rMarks.end();
     246             :             ++ppCurrentMark)
     247             :         {
     248             :             // Once we reach a mark starting after the target pos
     249             :             // we do not need to continue
     250         440 :             if(ppCurrentMark->get()->StartsAfter(rPos))
     251           1 :                 break;
     252         439 :             if(IDocumentMarkAccess::GetType(**ppCurrentMark) == eType)
     253             :             {
     254             :                 //OSL_TRACE("found mark named '%s'",
     255             :                 //    OUStringToOString(ppCurrentMark->get()->GetName(), RTL_TEXTENCODING_UTF8).getStr());
     256         428 :                 return ppCurrentMark;
     257             :             }
     258             :         }
     259             :         // reached a mark starting on a later start pos or the end of the
     260             :         // vector => not found
     261          96 :         return rMarks.end();
     262             :     };
     263             : 
     264       12128 :     static IDocumentMarkAccess::const_iterator_t lcl_FindMarkByName(
     265             :         const OUString& rName,
     266             :         IDocumentMarkAccess::const_iterator_t ppMarksBegin,
     267             :         IDocumentMarkAccess::const_iterator_t ppMarksEnd)
     268             :     {
     269             :         return find_if(
     270             :             ppMarksBegin,
     271             :             ppMarksEnd,
     272       12128 :             boost::bind(&OUString::equals, boost::bind(&IMark::GetName, _1), rName));
     273             :     }
     274             : 
     275             : #if 0
     276             :     static void lcl_DebugMarks(IDocumentMarkAccess::container_t vMarks)
     277             :     {
     278             :         OSL_TRACE("%d Marks", vMarks.size());
     279             :         for(IDocumentMarkAccess::iterator_t ppMark = vMarks.begin();
     280             :             ppMark != vMarks.end();
     281             :             ppMark++)
     282             :         {
     283             :             IMark* pMark = ppMark->get();
     284             :             OString sName = OUStringToOString(pMark->GetName(), RTL_TEXTENCODING_UTF8);
     285             :             const SwPosition* const pStPos = &pMark->GetMarkStart();
     286             :             const SwPosition* const pEndPos = &pMark->GetMarkEnd();
     287             :             OSL_TRACE("%s %s %d,%d %d,%d",
     288             :                 typeid(*pMark).name(),
     289             :                 sName.getStr(),
     290             :                 pStPos->nNode.GetIndex(),
     291             :                 pStPos->nContent.GetIndex(),
     292             :                 pEndPos->nNode.GetIndex(),
     293             :                 pEndPos->nContent.GetIndex());
     294             :         }
     295             :     };
     296             : #endif
     297             : }
     298             : 
     299     3532429 : IDocumentMarkAccess::MarkType IDocumentMarkAccess::GetType(const IMark& rBkmk)
     300             : {
     301     3532429 :     const std::type_info* const pMarkTypeInfo = &typeid(rBkmk);
     302             :     // not using dynamic_cast<> here for performance
     303     3532429 :     if(*pMarkTypeInfo == typeid(UnoMark))
     304     2168009 :         return MarkType::UNO_BOOKMARK;
     305     1364420 :     else if(*pMarkTypeInfo == typeid(DdeBookmark))
     306           1 :         return MarkType::DDE_BOOKMARK;
     307     1364419 :     else if(*pMarkTypeInfo == typeid(Bookmark))
     308     1356450 :         return MarkType::BOOKMARK;
     309        7969 :     else if(*pMarkTypeInfo == typeid(CrossRefHeadingBookmark))
     310        2235 :         return MarkType::CROSSREF_HEADING_BOOKMARK;
     311        5734 :     else if(*pMarkTypeInfo == typeid(CrossRefNumItemBookmark))
     312           9 :         return MarkType::CROSSREF_NUMITEM_BOOKMARK;
     313        5725 :     else if(*pMarkTypeInfo == typeid(AnnotationMark))
     314         321 :         return MarkType::ANNOTATIONMARK;
     315        5404 :     else if(*pMarkTypeInfo == typeid(TextFieldmark))
     316        4947 :         return MarkType::TEXT_FIELDMARK;
     317         457 :     else if(*pMarkTypeInfo == typeid(CheckboxFieldmark))
     318         457 :         return MarkType::CHECKBOX_FIELDMARK;
     319           0 :     else if(*pMarkTypeInfo == typeid(NavigatorReminder))
     320           0 :         return MarkType::NAVIGATOR_REMINDER;
     321             :     else
     322             :     {
     323             :         assert(false && "IDocumentMarkAccess::GetType(..)"
     324             :             " - unknown MarkType. This needs to be fixed!");
     325           0 :         return MarkType::UNO_BOOKMARK;
     326             :     }
     327             : }
     328             : 
     329        4989 : OUString IDocumentMarkAccess::GetCrossRefHeadingBookmarkNamePrefix()
     330             : {
     331        4989 :     return OUString("__RefHeading__");
     332             : }
     333             : 
     334         510 : bool IDocumentMarkAccess::IsLegalPaMForCrossRefHeadingBookmark( const SwPaM& rPaM )
     335             : {
     336        1020 :     return rPaM.Start()->nNode.GetNode().IsTextNode() &&
     337        1530 :            rPaM.Start()->nContent.GetIndex() == 0 &&
     338         510 :            ( !rPaM.HasMark() ||
     339           0 :              ( rPaM.GetMark()->nNode == rPaM.GetPoint()->nNode &&
     340         510 :                rPaM.End()->nContent.GetIndex() == rPaM.End()->nNode.GetNode().GetTextNode()->Len() ) );
     341             : }
     342             : 
     343             : namespace sw { namespace mark
     344             : {
     345        2958 :     MarkManager::MarkManager(SwDoc& rDoc)
     346             :         : m_vAllMarks()
     347             :         , m_vBookmarks()
     348             :         , m_vFieldmarks()
     349             :         , m_vAnnotationMarks()
     350        2958 :         , m_pDoc(&rDoc)
     351        2958 :     { }
     352             : 
     353      111191 :     ::sw::mark::IMark* MarkManager::makeMark(const SwPaM& rPaM,
     354             :         const OUString& rName,
     355             :         const IDocumentMarkAccess::MarkType eType)
     356             :     {
     357             : #if 0
     358             :         {
     359             :             OString sName = OUStringToOString(rName, RTL_TEXTENCODING_UTF8);
     360             :             const SwPosition* const pPos1 = rPaM.GetPoint();
     361             :             const SwPosition* pPos2 = pPos1;
     362             :             if(rPaM.HasMark())
     363             :                 pPos2 = rPaM.GetMark();
     364             :             OSL_TRACE("%s %d,%d %d,%d",
     365             :                 sName.getStr(),
     366             :                 pPos1->nNode.GetIndex(),
     367             :                 pPos1->nContent.GetIndex(),
     368             :                 pPos2->nNode.GetIndex(),
     369             :                 pPos2->nContent.GetIndex());
     370             :         }
     371             : #endif
     372             :         // see for example _SaveContentIdx, Shells
     373             :         OSL_PRECOND(m_vAllMarks.size() < USHRT_MAX,
     374             :             "MarkManager::makeMark(..)"
     375             :             " - more than USHRT_MAX marks are not supported correctly");
     376             :         // There should only be one CrossRefBookmark per Textnode per Type
     377      444234 :         if ((eType == MarkType::CROSSREF_NUMITEM_BOOKMARK || eType == MarkType::CROSSREF_HEADING_BOOKMARK)
     378      223424 :             && (lcl_FindMarkAtPos(m_vBookmarks, *rPaM.Start(), eType) != m_vBookmarks.end()))
     379             :         {   // this can happen via UNO API
     380             :             SAL_WARN("sw.core", "MarkManager::makeMark(..)"
     381             :                 " - refusing to create duplicate CrossRefBookmark");
     382         427 :             return 0;
     383             :         }
     384             : 
     385             :         // create mark
     386      110764 :         pMark_t pMark;
     387      110764 :         switch(eType)
     388             :         {
     389             :             case IDocumentMarkAccess::MarkType::TEXT_FIELDMARK:
     390         104 :                 pMark = boost::shared_ptr<IMark>(new TextFieldmark(rPaM));
     391         104 :                 break;
     392             :             case IDocumentMarkAccess::MarkType::CHECKBOX_FIELDMARK:
     393          34 :                 pMark = boost::shared_ptr<IMark>(new CheckboxFieldmark(rPaM));
     394          34 :                 break;
     395             :             case IDocumentMarkAccess::MarkType::NAVIGATOR_REMINDER:
     396           0 :                 pMark = boost::shared_ptr<IMark>(new NavigatorReminder(rPaM));
     397           0 :                 break;
     398             :             case IDocumentMarkAccess::MarkType::BOOKMARK:
     399        4340 :                 pMark = boost::shared_ptr<IMark>(new Bookmark(rPaM, vcl::KeyCode(), rName, OUString()));
     400        4340 :                 break;
     401             :             case IDocumentMarkAccess::MarkType::DDE_BOOKMARK:
     402           1 :                 pMark = boost::shared_ptr<IMark>(new DdeBookmark(rPaM));
     403           1 :                 break;
     404             :             case IDocumentMarkAccess::MarkType::CROSSREF_HEADING_BOOKMARK:
     405          85 :                 pMark = boost::shared_ptr<IMark>(new CrossRefHeadingBookmark(rPaM, vcl::KeyCode(), rName, OUString()));
     406          85 :                 break;
     407             :             case IDocumentMarkAccess::MarkType::CROSSREF_NUMITEM_BOOKMARK:
     408           9 :                 pMark = boost::shared_ptr<IMark>(new CrossRefNumItemBookmark(rPaM, vcl::KeyCode(), rName, OUString()));
     409           9 :                 break;
     410             :             case IDocumentMarkAccess::MarkType::UNO_BOOKMARK:
     411      106133 :                 pMark = boost::shared_ptr<IMark>(new UnoMark(rPaM));
     412      106133 :                 break;
     413             :             case IDocumentMarkAccess::MarkType::ANNOTATIONMARK:
     414          58 :                 pMark = boost::shared_ptr<IMark>(new AnnotationMark( rPaM, rName ));
     415          58 :                 break;
     416             :         }
     417             :         assert(pMark.get() &&
     418             :             "MarkManager::makeMark(..)"
     419             :             " - Mark was not created.");
     420      110764 :         MarkBase* pMarkBase = dynamic_cast<MarkBase*>(pMark.get());
     421             : 
     422      110764 :         if (!pMarkBase)
     423           0 :             return 0;
     424             : 
     425      110764 :         if(pMark->GetMarkPos() != pMark->GetMarkStart())
     426        1908 :             pMarkBase->Swap();
     427             : 
     428             :         // for performance reasons, we trust UnoMarks to have a (generated) unique name
     429      110764 :         if ( eType != IDocumentMarkAccess::MarkType::UNO_BOOKMARK )
     430        4631 :             pMarkBase->SetName( getUniqueMarkName( pMarkBase->GetName() ) );
     431             : 
     432             :         // register mark
     433      110764 :         m_aMarkNamesSet.insert(pMarkBase->GetName());
     434      110764 :         lcl_InsertMarkSorted(m_vAllMarks, pMark);
     435      110764 :         switch(eType)
     436             :         {
     437             :             case IDocumentMarkAccess::MarkType::BOOKMARK:
     438             :             case IDocumentMarkAccess::MarkType::CROSSREF_NUMITEM_BOOKMARK:
     439             :             case IDocumentMarkAccess::MarkType::CROSSREF_HEADING_BOOKMARK:
     440        4434 :                 lcl_InsertMarkSorted(m_vBookmarks, pMark);
     441        4434 :                 break;
     442             :             case IDocumentMarkAccess::MarkType::TEXT_FIELDMARK:
     443             :             case IDocumentMarkAccess::MarkType::CHECKBOX_FIELDMARK:
     444         138 :                 lcl_InsertMarkSorted(m_vFieldmarks, pMark);
     445         138 :                 break;
     446             :             case IDocumentMarkAccess::MarkType::ANNOTATIONMARK:
     447          58 :                 lcl_InsertMarkSorted( m_vAnnotationMarks, pMark );
     448          58 :                 break;
     449             :             case IDocumentMarkAccess::MarkType::NAVIGATOR_REMINDER:
     450             :             case IDocumentMarkAccess::MarkType::DDE_BOOKMARK:
     451             :             case IDocumentMarkAccess::MarkType::UNO_BOOKMARK:
     452             :                 // no special array for these
     453      106134 :                 break;
     454             :         }
     455      110764 :         pMarkBase->InitDoc(m_pDoc);
     456             : #if 0
     457             :         OSL_TRACE("--- makeType ---");
     458             :         OSL_TRACE("Marks");
     459             :         lcl_DebugMarks(m_vAllMarks);
     460             :         OSL_TRACE("Bookmarks");
     461             :         lcl_DebugMarks(m_vBookmarks);
     462             :         OSL_TRACE("Fieldmarks");
     463             :         lcl_DebugMarks(m_vFieldmarks);
     464             : #endif
     465             : 
     466      110764 :         return pMark.get();
     467             :     }
     468             : 
     469           5 :     ::sw::mark::IFieldmark* MarkManager::makeFieldBookmark(
     470             :         const SwPaM& rPaM,
     471             :         const OUString& rName,
     472             :         const OUString& rType )
     473             :     {
     474             :         sw::mark::IMark* pMark = makeMark( rPaM, rName,
     475           5 :                 IDocumentMarkAccess::MarkType::TEXT_FIELDMARK );
     476           5 :         sw::mark::IFieldmark* pFieldMark = dynamic_cast<sw::mark::IFieldmark*>( pMark );
     477           5 :         if (pFieldMark)
     478           5 :             pFieldMark->SetFieldname( rType );
     479             : 
     480           5 :         return pFieldMark;
     481             :     }
     482             : 
     483           4 :     ::sw::mark::IFieldmark* MarkManager::makeNoTextFieldBookmark(
     484             :         const SwPaM& rPaM,
     485             :         const OUString& rName,
     486             :         const OUString& rType)
     487             :     {
     488             :         sw::mark::IMark* pMark = makeMark( rPaM, rName,
     489           4 :                 IDocumentMarkAccess::MarkType::CHECKBOX_FIELDMARK );
     490           4 :         sw::mark::IFieldmark* pFieldMark = dynamic_cast<sw::mark::IFieldmark*>( pMark );
     491           4 :         if (pFieldMark)
     492           4 :             pFieldMark->SetFieldname( rType );
     493             : 
     494           4 :         return pFieldMark;
     495             :     }
     496             : 
     497           3 :     ::sw::mark::IMark* MarkManager::getMarkForTextNode(
     498             :         const SwTextNode& rTextNode,
     499             :         const IDocumentMarkAccess::MarkType eType )
     500             :     {
     501           3 :         SwPosition aPos(rTextNode);
     502           3 :         aPos.nContent.Assign(&(const_cast<SwTextNode&>(rTextNode)), 0);
     503           3 :         const iterator_t ppExistingMark = lcl_FindMarkAtPos(m_vBookmarks, aPos, eType);
     504           3 :         if(ppExistingMark != m_vBookmarks.end())
     505           1 :             return ppExistingMark->get();
     506           4 :         const SwPaM aPaM(aPos);
     507           5 :         return makeMark(aPaM, OUString(), eType);
     508             :     }
     509             : 
     510          58 :     sw::mark::IMark* MarkManager::makeAnnotationMark(
     511             :         const SwPaM& rPaM,
     512             :         const OUString& rName )
     513             :     {
     514          58 :         return makeMark( rPaM, rName, IDocumentMarkAccess::MarkType::ANNOTATIONMARK );
     515             :     }
     516             : 
     517           9 :     void MarkManager::repositionMark(
     518             :         ::sw::mark::IMark* const io_pMark,
     519             :         const SwPaM& rPaM)
     520             :     {
     521             :         assert(io_pMark->GetMarkPos().GetDoc() == m_pDoc &&
     522             :             "<MarkManager::repositionMark(..)>"
     523             :             " - Mark is not in my doc.");
     524           9 :         MarkBase* const pMarkBase = dynamic_cast< MarkBase* >(io_pMark);
     525           9 :         if (!pMarkBase)
     526           9 :             return;
     527             : 
     528           9 :         pMarkBase->SetMarkPos(*(rPaM.GetPoint()));
     529           9 :         if(rPaM.HasMark())
     530           0 :             pMarkBase->SetOtherMarkPos(*(rPaM.GetMark()));
     531             :         else
     532           9 :             pMarkBase->ClearOtherMarkPos();
     533             : 
     534           9 :         if(pMarkBase->GetMarkPos() != pMarkBase->GetMarkStart())
     535           0 :             pMarkBase->Swap();
     536             : 
     537           9 :         sortMarks();
     538             :     }
     539             : 
     540         384 :     bool MarkManager::renameMark(
     541             :         ::sw::mark::IMark* io_pMark,
     542             :         const OUString& rNewName )
     543             :     {
     544             :         assert(io_pMark->GetMarkPos().GetDoc() == m_pDoc &&
     545             :             "<MarkManager::renameMark(..)>"
     546             :             " - Mark is not in my doc.");
     547         384 :         if ( io_pMark->GetName() == rNewName )
     548          12 :             return true;
     549         372 :         if ( findMark(rNewName) != m_vAllMarks.end() )
     550         366 :             return false;
     551           6 :         if (::sw::mark::MarkBase* pMarkBase = dynamic_cast< ::sw::mark::MarkBase* >(io_pMark))
     552             :         {
     553           6 :             const OUString sOldName(pMarkBase->GetName());
     554           6 :             m_aMarkNamesSet.erase(sOldName);
     555           6 :             m_aMarkNamesSet.insert(rNewName);
     556           6 :             pMarkBase->SetName(rNewName);
     557             : 
     558           6 :             if (dynamic_cast< ::sw::mark::Bookmark* >(io_pMark))
     559             :             {
     560           5 :                 if (m_pDoc->GetIDocumentUndoRedo().DoesUndo())
     561             :                 {
     562           3 :                     m_pDoc->GetIDocumentUndoRedo().AppendUndo(
     563           3 :                             new SwUndoRenameBookmark(sOldName, rNewName));
     564             :                 }
     565           5 :                 m_pDoc->getIDocumentState().SetModified();
     566           6 :             }
     567             :         }
     568           6 :         return true;
     569             :     }
     570             : 
     571        2962 :     void MarkManager::correctMarksAbsolute(
     572             :         const SwNodeIndex& rOldNode,
     573             :         const SwPosition& rNewPos,
     574             :         const sal_Int32 nOffset)
     575             :     {
     576        2962 :         const SwNode* const pOldNode = &rOldNode.GetNode();
     577        2962 :         SwPosition aNewPos(rNewPos);
     578        2962 :         aNewPos.nContent += nOffset;
     579        2962 :         bool isSortingNeeded = false;
     580             : 
     581       47901 :         for(iterator_t ppMark = m_vAllMarks.begin();
     582       31934 :             ppMark != m_vAllMarks.end();
     583             :             ++ppMark)
     584             :         {
     585       13005 :             ::sw::mark::MarkBase* pMark = dynamic_cast< ::sw::mark::MarkBase* >(ppMark->get());
     586       13005 :             if (!pMark)
     587           0 :                 continue;
     588             :             // is on position ??
     589       13005 :             bool bChangedPos = false;
     590       13005 :             if(&pMark->GetMarkPos().nNode.GetNode() == pOldNode)
     591             :             {
     592           1 :                 pMark->SetMarkPos(aNewPos);
     593           1 :                 bChangedPos = true;
     594             :             }
     595       13005 :             bool bChangedOPos = false;
     596       14778 :             if (pMark->IsExpanded() &&
     597        1773 :                 &pMark->GetOtherMarkPos().nNode.GetNode() == pOldNode)
     598             :             {
     599             :                 // shift the OtherMark to aNewPos
     600           4 :                 pMark->SetOtherMarkPos(aNewPos);
     601           4 :                 bChangedOPos= true;
     602             :             }
     603             :             // illegal selection? collapse the mark and restore sorting later
     604       13005 :             isSortingNeeded |= lcl_FixCorrectedMark(bChangedPos, bChangedOPos, pMark);
     605             :         }
     606             : 
     607             :         // restore sorting if needed
     608        2962 :         if(isSortingNeeded)
     609           0 :             sortMarks();
     610             : #if 0
     611             :         OSL_TRACE("correctMarksAbsolute");
     612             :         lcl_DebugMarks(m_vAllMarks);
     613             : #endif
     614        2962 :     }
     615             : 
     616        2830 :     void MarkManager::correctMarksRelative(const SwNodeIndex& rOldNode, const SwPosition& rNewPos, const sal_Int32 nOffset)
     617             :     {
     618        2830 :         const SwNode* const pOldNode = &rOldNode.GetNode();
     619        2830 :         SwPosition aNewPos(rNewPos);
     620        2830 :         aNewPos.nContent += nOffset;
     621        2830 :         bool isSortingNeeded = false;
     622             : 
     623       97263 :         for(iterator_t ppMark = m_vAllMarks.begin();
     624       64842 :             ppMark != m_vAllMarks.end();
     625             :             ++ppMark)
     626             :         {
     627             :             // is on position ??
     628       29591 :             bool bChangedPos = false, bChangedOPos = false;
     629       29591 :             ::sw::mark::MarkBase* const pMark = dynamic_cast< ::sw::mark::MarkBase* >(ppMark->get());
     630       29591 :             if (!pMark)
     631           0 :                 continue;
     632       29591 :             if(&pMark->GetMarkPos().nNode.GetNode() == pOldNode)
     633             :             {
     634        1296 :                 SwPosition aNewPosRel(aNewPos);
     635        1296 :                 if (dynamic_cast< ::sw::mark::CrossRefBookmark *>(pMark))
     636             :                 {
     637             :                     // ensure that cross ref bookmark always starts at 0
     638           0 :                     aNewPosRel.nContent = 0; // HACK for WW8 import
     639             :                 }
     640        1296 :                 aNewPosRel.nContent += pMark->GetMarkPos().nContent.GetIndex();
     641        1296 :                 pMark->SetMarkPos(aNewPosRel);
     642        1296 :                 bChangedPos = true;
     643             :             }
     644       44822 :             if(pMark->IsExpanded() &&
     645       15231 :                 &pMark->GetOtherMarkPos().nNode.GetNode() == pOldNode)
     646             :             {
     647        1303 :                 SwPosition aNewPosRel(aNewPos);
     648        1303 :                 aNewPosRel.nContent += pMark->GetOtherMarkPos().nContent.GetIndex();
     649        1303 :                 pMark->SetOtherMarkPos(aNewPosRel);
     650        1303 :                 bChangedOPos = true;
     651             :             }
     652             :             // illegal selection? collapse the mark and restore sorting later
     653       29591 :             isSortingNeeded |= lcl_FixCorrectedMark(bChangedPos, bChangedOPos, pMark);
     654             :         }
     655             : 
     656             :         // restore sorting if needed
     657        2830 :         if(isSortingNeeded)
     658          16 :             sortMarks();
     659             : #if 0
     660             :         OSL_TRACE("correctMarksRelative");
     661             :         lcl_DebugMarks(m_vAllMarks);
     662             : #endif
     663        2830 :     }
     664             : 
     665       13836 :     void MarkManager::deleteMarks(
     666             :             const SwNodeIndex& rStt,
     667             :             const SwNodeIndex& rEnd,
     668             :             ::std::vector<SaveBookmark>* pSaveBkmk,
     669             :             const SwIndex* pSttIdx,
     670             :             const SwIndex* pEndIdx )
     671             :     {
     672       13836 :         ::std::vector<const_iterator_t> vMarksToDelete;
     673       13836 :         bool bIsSortingNeeded = false;
     674             : 
     675             :         // boolean indicating, if at least one mark has been moved while collecting marks for deletion
     676       13836 :         bool bMarksMoved = false;
     677             : 
     678             :         // copy all bookmarks in the move area to a vector storing all position data as offset
     679             :         // reassignment is performed after the move
     680      329589 :         for(iterator_t ppMark = m_vAllMarks.begin();
     681      219726 :             ppMark != m_vAllMarks.end();
     682             :             ++ppMark)
     683             :         {
     684             :             // navigator marks should not be moved
     685             :             // TODO: Check if this might make them invalid
     686       96027 :             if(IDocumentMarkAccess::GetType(**ppMark) == MarkType::NAVIGATOR_REMINDER)
     687           0 :                 continue;
     688             : 
     689       96027 :             ::sw::mark::MarkBase* pMark = dynamic_cast< ::sw::mark::MarkBase* >(ppMark->get());
     690             : 
     691       96027 :             if (!pMark)
     692           0 :                 continue;
     693             : 
     694             :             // on position ??
     695       96027 :             bool bIsPosInRange = lcl_GreaterThan(pMark->GetMarkPos(), rStt, pSttIdx)
     696       96027 :                                  && lcl_Lower(pMark->GetMarkPos(), rEnd, pEndIdx);
     697       96027 :             bool bIsOtherPosInRange = pMark->IsExpanded()
     698       21228 :                                       && lcl_GreaterThan(pMark->GetOtherMarkPos(), rStt, pSttIdx)
     699      109105 :                                       && lcl_Lower(pMark->GetOtherMarkPos(), rEnd, pEndIdx);
     700             :             // special case: completely in range, touching the end?
     701       96027 :             if ( pEndIdx != NULL
     702       96131 :                  && ( ( bIsOtherPosInRange
     703         185 :                         && pMark->GetMarkPos().nNode == rEnd
     704          84 :                         && pMark->GetMarkPos().nContent == *pEndIdx )
     705       40365 :                       || ( bIsPosInRange
     706        1040 :                            && pMark->IsExpanded()
     707         126 :                            && pMark->GetOtherMarkPos().nNode == rEnd
     708         126 :                            && pMark->GetOtherMarkPos().nContent == *pEndIdx ) ) )
     709             :             {
     710         104 :                 bIsPosInRange = true, bIsOtherPosInRange = true;
     711             :             }
     712             : 
     713       96027 :             if ( bIsPosInRange
     714       97118 :                  && ( bIsOtherPosInRange
     715        1010 :                       || !pMark->IsExpanded() ) )
     716             :             {
     717             :                 // completely in range
     718             : 
     719        1091 :                 bool bDeleteMark = true;
     720             :                 {
     721        1091 :                     switch ( IDocumentMarkAccess::GetType( *pMark ) )
     722             :                     {
     723             :                     case IDocumentMarkAccess::MarkType::CROSSREF_HEADING_BOOKMARK:
     724             :                     case IDocumentMarkAccess::MarkType::CROSSREF_NUMITEM_BOOKMARK:
     725             :                         // no delete of cross-reference bookmarks, if range is inside one paragraph
     726           0 :                         bDeleteMark = rStt != rEnd;
     727           0 :                         break;
     728             :                     case IDocumentMarkAccess::MarkType::UNO_BOOKMARK:
     729             :                         // no delete of UNO mark, if it is not expanded and only touches the start of the range
     730             :                         bDeleteMark = bIsOtherPosInRange
     731         593 :                                       || pMark->IsExpanded()
     732         593 :                                       || pSttIdx == NULL
     733        1685 :                                       || !( pMark->GetMarkPos().nNode == rStt
     734         938 :                                             && pMark->GetMarkPos().nContent == *pSttIdx );
     735         697 :                         break;
     736             :                     default:
     737         394 :                         bDeleteMark = true;
     738         394 :                         break;
     739             :                     }
     740             :                 }
     741             : 
     742        1091 :                 if ( bDeleteMark )
     743             :                 {
     744         850 :                     if ( pSaveBkmk )
     745             :                     {
     746           0 :                         pSaveBkmk->push_back( SaveBookmark( true, true, *pMark, rStt, pSttIdx ) );
     747             :                     }
     748         850 :                     vMarksToDelete.push_back(ppMark);
     749             :                 }
     750             :             }
     751       94936 :             else if ( bIsPosInRange != bIsOtherPosInRange )
     752             :             {
     753             :                 // the bookmark is partially in the range
     754             :                 // move position of that is in the range out of it
     755             : 
     756         208 :                 ::std::unique_ptr< SwPosition > pNewPos;
     757             :                 {
     758         208 :                     if ( pEndIdx != NULL )
     759             :                     {
     760         207 :                         pNewPos = ::std::unique_ptr< SwPosition >( new SwPosition( rEnd, *pEndIdx ) );
     761             :                     }
     762             :                     else
     763             :                     {
     764           3 :                         pNewPos =
     765           2 :                             lcl_FindExpelPosition( rStt, rEnd, bIsPosInRange ? pMark->GetOtherMarkPos() : pMark->GetMarkPos() );
     766             :                     }
     767             :                 }
     768             : 
     769         208 :                 bool bMoveMark = true;
     770             :                 {
     771         208 :                     switch ( IDocumentMarkAccess::GetType( *pMark ) )
     772             :                     {
     773             :                     case IDocumentMarkAccess::MarkType::CROSSREF_HEADING_BOOKMARK:
     774             :                     case IDocumentMarkAccess::MarkType::CROSSREF_NUMITEM_BOOKMARK:
     775             :                         // no move of cross-reference bookmarks, if move occurs inside a certain node
     776           0 :                         bMoveMark = pMark->GetMarkPos().nNode != pNewPos->nNode;
     777           0 :                         break;
     778             :                     case IDocumentMarkAccess::MarkType::ANNOTATIONMARK:
     779             :                         // no move of annotation marks, if method is called to collect deleted marks
     780           4 :                         bMoveMark = pSaveBkmk == NULL;
     781           4 :                         break;
     782             :                     default:
     783         204 :                         bMoveMark = true;
     784         204 :                         break;
     785             :                     }
     786             :                 }
     787         208 :                 if ( bMoveMark )
     788             :                 {
     789         208 :                     if ( bIsPosInRange )
     790          23 :                         pMark->SetMarkPos(*pNewPos);
     791             :                     else
     792         185 :                         pMark->SetOtherMarkPos(*pNewPos);
     793         208 :                     bMarksMoved = true;
     794             : 
     795             :                     // illegal selection? collapse the mark and restore sorting later
     796         208 :                     bIsSortingNeeded |= lcl_FixCorrectedMark( bIsPosInRange, bIsOtherPosInRange, pMark );
     797         208 :                 }
     798             :             }
     799             :         }
     800             : 
     801             :         {
     802             :             // fdo#61016 delay the deletion of the fieldmark characters
     803             :             // to prevent that from deleting the marks on that position
     804             :             // which would invalidate the iterators in vMarksToDelete
     805       13836 :             std::vector< ::boost::shared_ptr<ILazyDeleter> > vDelay;
     806       13836 :             vDelay.reserve(vMarksToDelete.size());
     807             : 
     808             :             // If needed, sort mark containers containing subsets of the marks
     809             :             // in order to assure sorting.  The sorting is critical for the
     810             :             // deletion of a mark as it is searched in these container for
     811             :             // deletion.
     812       13836 :             if ( vMarksToDelete.size() > 0 && bMarksMoved )
     813             :             {
     814          11 :                 sortSubsetMarks();
     815             :             }
     816             :             // we just remembered the iterators to delete, so we do not need to search
     817             :             // for the shared_ptr<> (the entry in m_vAllMarks) again
     818             :             // reverse iteration, since erasing an entry invalidates iterators
     819             :             // behind it (the iterators in vMarksToDelete are sorted)
     820       44058 :             for ( ::std::vector< const_iterator_t >::reverse_iterator pppMark = vMarksToDelete.rbegin();
     821       29372 :                   pppMark != vMarksToDelete.rend();
     822             :                   ++pppMark )
     823             :             {
     824         850 :                 vDelay.push_back(deleteMark(*pppMark));
     825       13836 :             }
     826             :         } // scope to kill vDelay
     827             : 
     828       13836 :         if ( bIsSortingNeeded )
     829             :         {
     830           4 :             sortMarks();
     831       13836 :         }
     832             : 
     833             : #if 0
     834             :         OSL_TRACE("deleteMarks");
     835             :         lcl_DebugMarks(m_vAllMarks);
     836             : #endif
     837       13836 :     }
     838             : 
     839             :     struct LazyFieldmarkDeleter : public IDocumentMarkAccess::ILazyDeleter
     840             :     {
     841             :         ::boost::shared_ptr<IMark> const m_pFieldmark;
     842             :         SwDoc *const m_pDoc;
     843           0 :         LazyFieldmarkDeleter(
     844             :                 ::boost::shared_ptr<IMark> const& pMark, SwDoc *const pDoc)
     845           0 :             : m_pFieldmark(pMark), m_pDoc(pDoc)
     846           0 :         { }
     847           0 :         virtual ~LazyFieldmarkDeleter()
     848           0 :         {
     849             :             Fieldmark *const pFieldMark(
     850           0 :                     dynamic_cast<Fieldmark*>(m_pFieldmark.get()));
     851             :             assert(pFieldMark);
     852           0 :             pFieldMark->ReleaseDoc(m_pDoc);
     853           0 :         }
     854             :     };
     855             : 
     856             :     ::boost::shared_ptr<IDocumentMarkAccess::ILazyDeleter>
     857      102239 :         MarkManager::deleteMark(const const_iterator_t& ppMark)
     858             :     {
     859      102239 :         ::boost::shared_ptr<ILazyDeleter> ret;
     860      102239 :         if (ppMark == m_vAllMarks.end()) return ret;
     861             : 
     862      102239 :         switch(IDocumentMarkAccess::GetType(**ppMark))
     863             :         {
     864             :             case IDocumentMarkAccess::MarkType::BOOKMARK:
     865             :             case IDocumentMarkAccess::MarkType::CROSSREF_HEADING_BOOKMARK:
     866             :             case IDocumentMarkAccess::MarkType::CROSSREF_NUMITEM_BOOKMARK:
     867             :                 {
     868         455 :                     IDocumentMarkAccess::iterator_t ppBookmark = lcl_FindMark(m_vBookmarks, *ppMark);
     869         455 :                     if ( ppBookmark != m_vBookmarks.end() )
     870             :                     {
     871         455 :                         m_vBookmarks.erase(ppBookmark);
     872             :                     }
     873             :                     else
     874             :                     {
     875             :                         assert(false &&
     876             :                             "<MarkManager::deleteMark(..)> - Bookmark not found in Bookmark container.");
     877             :                     }
     878             :                 }
     879         455 :                 break;
     880             : 
     881             :             case IDocumentMarkAccess::MarkType::TEXT_FIELDMARK:
     882             :             case IDocumentMarkAccess::MarkType::CHECKBOX_FIELDMARK:
     883             :                 {
     884           0 :                     IDocumentMarkAccess::iterator_t ppFieldmark = lcl_FindMark(m_vFieldmarks, *ppMark);
     885           0 :                     if ( ppFieldmark != m_vFieldmarks.end() )
     886             :                     {
     887           0 :                         m_vFieldmarks.erase(ppFieldmark);
     888           0 :                         ret.reset(new LazyFieldmarkDeleter(*ppMark, m_pDoc));
     889             :                     }
     890             :                     else
     891             :                     {
     892             :                         assert(false &&
     893             :                             "<MarkManager::deleteMark(..)> - Fieldmark not found in Fieldmark container.");
     894             :                     }
     895             :                 }
     896           0 :                 break;
     897             : 
     898             :             case IDocumentMarkAccess::MarkType::ANNOTATIONMARK:
     899             :                 {
     900           0 :                     IDocumentMarkAccess::iterator_t ppAnnotationMark = lcl_FindMark(m_vAnnotationMarks, *ppMark);
     901           0 :                     if ( ppAnnotationMark != m_vAnnotationMarks.end() )
     902             :                     {
     903           0 :                         m_vAnnotationMarks.erase(ppAnnotationMark);
     904             :                     }
     905             :                     else
     906             :                     {
     907             :                         assert(false &&
     908             :                             "<MarkManager::deleteMark(..)> - Annotation Mark not found in Annotation Mark container.");
     909             :                     }
     910             :                 }
     911           0 :                 break;
     912             : 
     913             :             case IDocumentMarkAccess::MarkType::NAVIGATOR_REMINDER:
     914             :             case IDocumentMarkAccess::MarkType::DDE_BOOKMARK:
     915             :             case IDocumentMarkAccess::MarkType::UNO_BOOKMARK:
     916             :                 // no special marks container
     917      101784 :                 break;
     918             :         }
     919      102239 :         DdeBookmark* const pDdeBookmark = dynamic_cast<DdeBookmark*>(ppMark->get());
     920      102239 :         if(pDdeBookmark)
     921         455 :             pDdeBookmark->DeregisterFromDoc(m_pDoc);
     922             :         //Effective STL Item 27, get a non-const iterator aI at the same
     923             :         //position as const iterator ppMark was
     924      102239 :         iterator_t aI = m_vAllMarks.begin();
     925      102239 :         std::advance(aI, std::distance<const_iterator_t>(aI, ppMark));
     926             : 
     927             :         //fdo#37974
     928             :         //a) a mark destructor may callback into this method.
     929             :         //b) vector::erase first calls the destructor of the object, then
     930             :         //removes it from the vector.
     931             :         //So if the only reference to the object is the one
     932             :         //in the vector then we may reenter this method when the mark
     933             :         //is destructed but before it is removed, i.e. findMark still
     934             :         //finds the object whose destructor is being run. Take a temp
     935             :         //extra reference on the shared_ptr, remove the entry from the
     936             :         //vector, and on xHoldPastErase release findMark won't find
     937             :         //it anymore.
     938      102239 :         pMark_t xHoldPastErase = *aI;
     939      102239 :         m_aMarkNamesSet.erase(ppMark->get()->GetName());
     940      102239 :         m_vAllMarks.erase(aI);
     941      102239 :         return ret;
     942             :     }
     943             : 
     944      101201 :     void MarkManager::deleteMark(const IMark* const pMark)
     945             :     {
     946             :         assert(pMark->GetMarkPos().GetDoc() == m_pDoc &&
     947             :             "<MarkManager::deleteMark(..)>"
     948             :             " - Mark is not in my doc.");
     949             :         // finds the last Mark that is starting before pMark
     950             :         // (pMarkLow < pMark)
     951             :         iterator_t pMarkLow =
     952             :             lower_bound(
     953             :                 m_vAllMarks.begin(),
     954             :                 m_vAllMarks.end(),
     955      101201 :                 pMark->GetMarkStart(),
     956      101201 :                 sw::mark::CompareIMarkStartsBefore());
     957      101201 :         iterator_t pMarkHigh = m_vAllMarks.end();
     958             :         iterator_t pMarkFound =
     959             :             find_if(
     960             :                 pMarkLow,
     961             :                 pMarkHigh,
     962      101201 :                 boost::bind( ::std::equal_to<const IMark*>(), boost::bind(&boost::shared_ptr<IMark>::get, _1), pMark ) );
     963      101201 :         if(pMarkFound != pMarkHigh)
     964      101201 :             deleteMark(pMarkFound);
     965      101201 :     }
     966             : 
     967        2970 :     void MarkManager::clearAllMarks()
     968             :     {
     969        2970 :         m_vFieldmarks.clear();
     970        2970 :         m_vBookmarks.clear();
     971        2970 :         m_aMarkNamesSet.clear();
     972             : 
     973        2970 :         m_vAnnotationMarks.clear();
     974             : 
     975             : #if OSL_DEBUG_LEVEL > 0
     976             :         for(iterator_t pBkmk = m_vAllMarks.begin();
     977             :             pBkmk != m_vAllMarks.end();
     978             :             ++pBkmk)
     979             :             OSL_ENSURE( pBkmk->unique(),
     980             :                         "<MarkManager::clearAllMarks(..)> - a Bookmark is still in use.");
     981             : #endif
     982        2970 :         m_vAllMarks.clear();
     983        2970 :     }
     984             : 
     985        6014 :     IDocumentMarkAccess::const_iterator_t MarkManager::findMark(const OUString& rName) const
     986             :     {
     987        6014 :         return lcl_FindMarkByName(rName, m_vAllMarks.begin(), m_vAllMarks.end());
     988             :     }
     989             : 
     990        4977 :     IDocumentMarkAccess::const_iterator_t MarkManager::findBookmark(const OUString& rName) const
     991             :     {
     992        4977 :         return lcl_FindMarkByName(rName, m_vBookmarks.begin(), m_vBookmarks.end());
     993             :     }
     994             : 
     995     1374694 :     IDocumentMarkAccess::const_iterator_t MarkManager::getAllMarksBegin() const
     996     1374694 :         { return m_vAllMarks.begin(); }
     997             : 
     998       21568 :     IDocumentMarkAccess::const_iterator_t MarkManager::getAllMarksEnd() const
     999       21568 :         { return m_vAllMarks.end(); }
    1000             : 
    1001      997366 :     sal_Int32 MarkManager::getAllMarksCount() const
    1002      997366 :         { return m_vAllMarks.size(); }
    1003             : 
    1004          84 :     IDocumentMarkAccess::const_iterator_t MarkManager::getBookmarksBegin() const
    1005          84 :         { return m_vBookmarks.begin(); }
    1006             : 
    1007        9908 :     IDocumentMarkAccess::const_iterator_t MarkManager::getBookmarksEnd() const
    1008        9908 :         { return m_vBookmarks.end(); }
    1009             : 
    1010        1953 :     sal_Int32 MarkManager::getBookmarksCount() const
    1011        1953 :         { return m_vBookmarks.size(); }
    1012             : 
    1013       83850 :     IFieldmark* MarkManager::getFieldmarkFor(const SwPosition& rPos) const
    1014             :     {
    1015             :         const_iterator_t pFieldmark = find_if(
    1016             :             m_vFieldmarks.begin(),
    1017             :             m_vFieldmarks.end( ),
    1018       83850 :             boost::bind(&IMark::IsCoveringPosition, _1, rPos));
    1019       83850 :         if(pFieldmark == m_vFieldmarks.end()) return NULL;
    1020         138 :         return dynamic_cast<IFieldmark*>(pFieldmark->get());
    1021             :     }
    1022             : 
    1023           0 :     IFieldmark* MarkManager::getDropDownFor(const SwPosition& rPos) const
    1024             :     {
    1025           0 :         IFieldmark *pMark = getFieldmarkFor(rPos);
    1026           0 :         if (!pMark || pMark->GetFieldname() != ODF_FORMDROPDOWN)
    1027           0 :             return NULL;
    1028           0 :         return pMark;
    1029             :     }
    1030             : 
    1031        9131 :     std::vector<IFieldmark*> MarkManager::getDropDownsFor(const SwPaM &rPaM) const
    1032             :     {
    1033        9131 :         std::vector<IFieldmark*> aRet;
    1034             : 
    1035       18287 :         for (IDocumentMarkAccess::const_iterator_t aI = m_vFieldmarks.begin(),
    1036        9131 :             aEnd = m_vFieldmarks.end(); aI != aEnd; ++aI)
    1037             :         {
    1038          25 :             boost::shared_ptr<IMark> xI = *aI;
    1039          25 :             const SwPosition &rStart = xI->GetMarkPos();
    1040          25 :             if (!rPaM.ContainsPosition(rStart))
    1041          20 :                 continue;
    1042             : 
    1043           5 :             IFieldmark *pMark = dynamic_cast<IFieldmark*>(xI.get());
    1044           5 :             if (!pMark || pMark->GetFieldname() != ODF_FORMDROPDOWN)
    1045           3 :                 continue;
    1046             : 
    1047           2 :             aRet.push_back(pMark);
    1048           2 :         }
    1049             : 
    1050        9131 :         return aRet;
    1051             :     }
    1052             : 
    1053           1 :     IFieldmark* MarkManager::getFieldmarkAfter(const SwPosition& rPos) const
    1054           1 :         { return dynamic_cast<IFieldmark*>(lcl_getMarkAfter(m_vFieldmarks, rPos)); }
    1055             : 
    1056           0 :     IFieldmark* MarkManager::getFieldmarkBefore(const SwPosition& rPos) const
    1057           0 :         { return dynamic_cast<IFieldmark*>(lcl_getMarkBefore(m_vFieldmarks, rPos)); }
    1058             : 
    1059         551 :     IDocumentMarkAccess::const_iterator_t MarkManager::getAnnotationMarksBegin() const
    1060             :     {
    1061         551 :         return m_vAnnotationMarks.begin();
    1062             :     }
    1063             : 
    1064        1254 :     IDocumentMarkAccess::const_iterator_t MarkManager::getAnnotationMarksEnd() const
    1065             :     {
    1066        1254 :         return m_vAnnotationMarks.end();
    1067             :     }
    1068             : 
    1069       31131 :     sal_Int32 MarkManager::getAnnotationMarksCount() const
    1070             :     {
    1071       31131 :         return m_vAnnotationMarks.size();
    1072             :     }
    1073             : 
    1074        1137 :     IDocumentMarkAccess::const_iterator_t MarkManager::findAnnotationMark( const OUString& rName ) const
    1075             :     {
    1076        1137 :         return lcl_FindMarkByName( rName, m_vAnnotationMarks.begin(), m_vAnnotationMarks.end() );
    1077             :     }
    1078             : 
    1079           2 :     IMark* MarkManager::getAnnotationMarkFor(const SwPosition& rPos) const
    1080             :     {
    1081             :         const_iterator_t pAnnotationMark = find_if(
    1082             :             m_vAnnotationMarks.begin(),
    1083             :             m_vAnnotationMarks.end( ),
    1084           2 :             boost::bind(&IMark::IsCoveringPosition, _1, rPos));
    1085           2 :         if (pAnnotationMark == m_vAnnotationMarks.end())
    1086           1 :             return NULL;
    1087           1 :         return pAnnotationMark->get();
    1088             :     }
    1089             : 
    1090             : 
    1091        4631 :     OUString MarkManager::getUniqueMarkName(const OUString& rName) const
    1092             :     {
    1093             :         OSL_ENSURE(rName.getLength(),
    1094             :             "<MarkManager::getUniqueMarkName(..)> - a name should be proposed");
    1095        4631 :         if( m_pDoc->IsInMailMerge())
    1096             :         {
    1097           0 :             OUString newName = rName + "MailMergeMark"
    1098           0 :                     + OStringToOUString( DateTimeToOString( DateTime( DateTime::SYSTEM )), RTL_TEXTENCODING_ASCII_US )
    1099           0 :                     + OUString::number( m_vAllMarks.size() + 1 );
    1100           0 :             return newName;
    1101             :         }
    1102             : 
    1103        4631 :         if ( findMark(rName) == getAllMarksEnd() )
    1104             :         {
    1105        4599 :             return rName;
    1106             :         }
    1107          32 :         OUStringBuffer sBuf;
    1108          64 :         OUString sTmp;
    1109             : 
    1110             :         // Try the name "<rName>XXX", where XXX is a number. Start the number at the existing count rather than 1
    1111             :         // in order to increase the chance that already the first one will not exist.
    1112          32 :         sal_Int32 nCnt = m_vAllMarks.size() + 1;
    1113          64 :         while(nCnt < SAL_MAX_INT32)
    1114             :         {
    1115          32 :             sTmp = sBuf.append(rName).append(nCnt).makeStringAndClear();
    1116          32 :             nCnt++;
    1117          32 :             if ( findMark(sTmp) == getAllMarksEnd() )
    1118             :             {
    1119          32 :                 break;
    1120             :             }
    1121             :         }
    1122          64 :         return sTmp;
    1123             :     }
    1124             : 
    1125           4 :     void MarkManager::assureSortedMarkContainers() const
    1126             :     {
    1127           4 :         const_cast< MarkManager* >(this)->sortMarks();
    1128           4 :     }
    1129             : 
    1130          44 :     void MarkManager::sortSubsetMarks()
    1131             :     {
    1132          44 :         sort(m_vBookmarks.begin(), m_vBookmarks.end(), &lcl_MarkOrderingByStart);
    1133          44 :         sort(m_vFieldmarks.begin(), m_vFieldmarks.end(), &lcl_MarkOrderingByStart);
    1134          44 :         sort(m_vAnnotationMarks.begin(), m_vAnnotationMarks.end(), &lcl_MarkOrderingByStart);
    1135          44 :     }
    1136             : 
    1137          33 :     void MarkManager::sortMarks()
    1138             :     {
    1139          33 :         sort(m_vAllMarks.begin(), m_vAllMarks.end(), &lcl_MarkOrderingByStart);
    1140          33 :         sortSubsetMarks();
    1141          33 :     }
    1142             : 
    1143           0 : void MarkManager::dumpAsXml(xmlTextWriterPtr pWriter) const
    1144             : {
    1145             :     struct
    1146             :     {
    1147             :         const char* pName;
    1148             :         const container_t* pContainer;
    1149             :     } aContainers[] =
    1150             :     {
    1151             :         // UNO marks are only part of all marks.
    1152             :         {"allmarks", &m_vAllMarks},
    1153             :         {"bookmarks", &m_vBookmarks},
    1154             :         {"fieldmarks", &m_vFieldmarks},
    1155             :         {"annotationmarks", &m_vAnnotationMarks}
    1156           0 :     };
    1157             : 
    1158           0 :     xmlTextWriterStartElement(pWriter, BAD_CAST("markManager"));
    1159           0 :     for (size_t i = 0; i < SAL_N_ELEMENTS(aContainers); ++i)
    1160             :     {
    1161           0 :         if (!aContainers[i].pContainer->empty())
    1162             :         {
    1163           0 :             xmlTextWriterStartElement(pWriter, BAD_CAST(aContainers[i].pName));
    1164           0 :             for (const_iterator_t it = aContainers[i].pContainer->begin(); it != aContainers[i].pContainer->end(); ++it)
    1165           0 :                 (*it)->dumpAsXml(pWriter);
    1166           0 :             xmlTextWriterEndElement(pWriter);
    1167             :         }
    1168             :     }
    1169           0 :     xmlTextWriterEndElement(pWriter);
    1170           0 : }
    1171             : 
    1172             : }} // namespace ::sw::mark
    1173             : 
    1174             : namespace
    1175             : {
    1176       12404 :     static inline bool lcl_Greater( const SwPosition& rPos, const SwNodeIndex& rNdIdx, const SwIndex* pIdx )
    1177             :     {
    1178       12404 :         return rPos.nNode > rNdIdx || ( pIdx && rPos.nNode == rNdIdx && rPos.nContent > pIdx->GetIndex() );
    1179             :     }
    1180             : }
    1181             : 
    1182             : // IDocumentMarkAccess for SwDoc
    1183      317489 : IDocumentMarkAccess* SwDoc::getIDocumentMarkAccess()
    1184      317489 :     { return static_cast< IDocumentMarkAccess* >(mpMarkManager.get()); }
    1185             : 
    1186       48638 : const IDocumentMarkAccess* SwDoc::getIDocumentMarkAccess() const
    1187       48638 :     { return static_cast< IDocumentMarkAccess* >(mpMarkManager.get()); }
    1188             : 
    1189           0 : SaveBookmark::SaveBookmark(
    1190             :     bool bSavePos,
    1191             :     bool bSaveOtherPos,
    1192             :     const IMark& rBkmk,
    1193             :     const SwNodeIndex & rMvPos,
    1194             :     const SwIndex* pIdx)
    1195           0 :     : m_aName(rBkmk.GetName())
    1196             :     , m_aShortName()
    1197             :     , m_aCode()
    1198             :     , m_bSavePos(bSavePos)
    1199             :     , m_bSaveOtherPos(bSaveOtherPos)
    1200           0 :     , m_eOrigBkmType(IDocumentMarkAccess::GetType(rBkmk))
    1201             : {
    1202           0 :     const IBookmark* const pBookmark = dynamic_cast< const IBookmark* >(&rBkmk);
    1203           0 :     if(pBookmark)
    1204             :     {
    1205           0 :         m_aShortName = pBookmark->GetShortName();
    1206           0 :         m_aCode = pBookmark->GetKeyCode();
    1207             : 
    1208             :         ::sfx2::Metadatable const*const pMetadatable(
    1209           0 :                 dynamic_cast< ::sfx2::Metadatable const* >(pBookmark));
    1210           0 :         if (pMetadatable)
    1211             :         {
    1212           0 :             m_pMetadataUndo = pMetadatable->CreateUndo();
    1213             :         }
    1214             :     }
    1215           0 :     m_nNode1 = rBkmk.GetMarkPos().nNode.GetIndex();
    1216           0 :     m_nContent1 = rBkmk.GetMarkPos().nContent.GetIndex();
    1217             : 
    1218           0 :     if(m_bSavePos)
    1219             :     {
    1220           0 :         m_nNode1 -= rMvPos.GetIndex();
    1221           0 :         if(pIdx && !m_nNode1)
    1222           0 :             m_nContent1 -= pIdx->GetIndex();
    1223             :     }
    1224             : 
    1225           0 :     if(rBkmk.IsExpanded())
    1226             :     {
    1227           0 :         m_nNode2 = rBkmk.GetOtherMarkPos().nNode.GetIndex();
    1228           0 :         m_nContent2 = rBkmk.GetOtherMarkPos().nContent.GetIndex();
    1229             : 
    1230           0 :         if(m_bSaveOtherPos)
    1231             :         {
    1232           0 :             m_nNode2 -= rMvPos.GetIndex();
    1233           0 :             if(pIdx && !m_nNode2)
    1234           0 :                 m_nContent2 -= pIdx->GetIndex();
    1235             :         }
    1236             :     }
    1237             :     else
    1238             :     {
    1239           0 :         m_nNode2 = ULONG_MAX;
    1240           0 :         m_nContent2 = -1;
    1241             :     }
    1242           0 : }
    1243             : 
    1244           0 : void SaveBookmark::SetInDoc(
    1245             :     SwDoc* pDoc,
    1246             :     const SwNodeIndex& rNewPos,
    1247             :     const SwIndex* pIdx)
    1248             : {
    1249           0 :     SwPaM aPam(rNewPos.GetNode());
    1250           0 :     if(pIdx)
    1251           0 :         aPam.GetPoint()->nContent = *pIdx;
    1252             : 
    1253           0 :     if(ULONG_MAX != m_nNode2)
    1254             :     {
    1255           0 :         aPam.SetMark();
    1256             : 
    1257           0 :         if(m_bSaveOtherPos)
    1258             :         {
    1259           0 :             aPam.GetMark()->nNode += m_nNode2;
    1260           0 :             if(pIdx && !m_nNode2)
    1261           0 :                 aPam.GetMark()->nContent += m_nContent2;
    1262             :             else
    1263           0 :                 aPam.GetMark()->nContent.Assign(aPam.GetContentNode(false), m_nContent2);
    1264             :         }
    1265             :         else
    1266             :         {
    1267           0 :             aPam.GetMark()->nNode = m_nNode2;
    1268           0 :             aPam.GetMark()->nContent.Assign(aPam.GetContentNode(false), m_nContent2);
    1269             :         }
    1270             :     }
    1271             : 
    1272           0 :     if(m_bSavePos)
    1273             :     {
    1274           0 :         aPam.GetPoint()->nNode += m_nNode1;
    1275             : 
    1276           0 :         if(pIdx && !m_nNode1)
    1277           0 :             aPam.GetPoint()->nContent += m_nContent1;
    1278             :         else
    1279           0 :             aPam.GetPoint()->nContent.Assign(aPam.GetContentNode(), m_nContent1);
    1280             :     }
    1281             :     else
    1282             :     {
    1283           0 :         aPam.GetPoint()->nNode = m_nNode1;
    1284           0 :         aPam.GetPoint()->nContent.Assign(aPam.GetContentNode(), m_nContent1);
    1285             :     }
    1286             : 
    1287           0 :     if(!aPam.HasMark()
    1288           0 :         || CheckNodesRange(aPam.GetPoint()->nNode, aPam.GetMark()->nNode, true))
    1289             :     {
    1290           0 :         ::sw::mark::IBookmark* const pBookmark = dynamic_cast< ::sw::mark::IBookmark* >(pDoc->getIDocumentMarkAccess()->makeMark(aPam, m_aName, m_eOrigBkmType));
    1291           0 :         if(pBookmark)
    1292             :         {
    1293           0 :             pBookmark->SetKeyCode(m_aCode);
    1294           0 :             pBookmark->SetShortName(m_aShortName);
    1295           0 :             if (m_pMetadataUndo)
    1296             :             {
    1297             :                 ::sfx2::Metadatable * const pMeta(
    1298           0 :                     dynamic_cast< ::sfx2::Metadatable* >(pBookmark));
    1299             :                 assert(pMeta && "metadata undo, but not metadatable?");
    1300           0 :                 if (pMeta)
    1301             :                 {
    1302           0 :                     pMeta->RestoreMetadata(m_pMetadataUndo);
    1303             :                 }
    1304             :             }
    1305             :         }
    1306           0 :     }
    1307           0 : }
    1308             : 
    1309             : // _DelBookmarks
    1310             : 
    1311       13836 : void _DelBookmarks(
    1312             :     const SwNodeIndex& rStt,
    1313             :     const SwNodeIndex& rEnd,
    1314             :     ::std::vector<SaveBookmark> * pSaveBkmk,
    1315             :     const SwIndex* pSttIdx,
    1316             :     const SwIndex* pEndIdx)
    1317             : {
    1318             :     // illegal range ??
    1319       27672 :     if(rStt.GetIndex() > rEnd.GetIndex()
    1320       13836 :         || (rStt == rEnd && (!pSttIdx || pSttIdx->GetIndex() >= pEndIdx->GetIndex())))
    1321       13836 :         return;
    1322       13836 :     SwDoc* const pDoc = rStt.GetNode().GetDoc();
    1323             : 
    1324       13836 :     pDoc->getIDocumentMarkAccess()->deleteMarks(rStt, rEnd, pSaveBkmk, pSttIdx, pEndIdx);
    1325             : 
    1326             :     // Copy all Redlines which are in the move area into an array
    1327             :     // which holds all position information as offset.
    1328             :     // Assignement happens after moving.
    1329       13836 :     SwRedlineTable& rTable = pDoc->getIDocumentRedlineAccess().GetRedlineTable();
    1330       20038 :     for(SwRedlineTable::size_type nCnt = 0; nCnt < rTable.size(); ++nCnt )
    1331             :     {
    1332             :         // Is at position?
    1333        6202 :         SwRangeRedline* pRedl = rTable[ nCnt ];
    1334             : 
    1335        6202 :         SwPosition *const pRStt = pRedl->Start();
    1336        6202 :         SwPosition *const pREnd = pRedl->End();
    1337             : 
    1338        6202 :         if( lcl_Greater( *pRStt, rStt, pSttIdx ) && lcl_Lower( *pRStt, rEnd, pEndIdx ))
    1339             :         {
    1340           2 :             pRStt->nNode = rEnd;
    1341           2 :             if( pEndIdx )
    1342           0 :                 pRStt->nContent = *pEndIdx;
    1343             :             else
    1344             :             {
    1345           2 :                 bool bStt = true;
    1346           2 :                 SwContentNode* pCNd = pRStt->nNode.GetNode().GetContentNode();
    1347           2 :                 if( !pCNd && 0 == ( pCNd = pDoc->GetNodes().GoNext( &pRStt->nNode )) )
    1348             :                 {
    1349           2 :                     bStt = false;
    1350           2 :                     pRStt->nNode = rStt;
    1351           2 :                     if( 0 == ( pCNd = SwNodes::GoPrevious( &pRStt->nNode )) )
    1352             :                     {
    1353           2 :                         pRStt->nNode = pREnd->nNode;
    1354           2 :                         pCNd = pRStt->nNode.GetNode().GetContentNode();
    1355             :                     }
    1356             :                 }
    1357           2 :                 pRStt->nContent.Assign( pCNd, bStt ? 0 : pCNd->Len() );
    1358             :             }
    1359             :         }
    1360        6202 :         if( lcl_Greater( *pREnd, rStt, pSttIdx ) && lcl_Lower( *pREnd, rEnd, pEndIdx ))
    1361             :         {
    1362           2 :             pREnd->nNode = rStt;
    1363           2 :             if( pSttIdx )
    1364           0 :                 pREnd->nContent = *pSttIdx;
    1365             :             else
    1366             :             {
    1367           2 :                 bool bStt = false;
    1368           2 :                 SwContentNode* pCNd = pREnd->nNode.GetNode().GetContentNode();
    1369           2 :                 if( !pCNd && 0 == ( pCNd = SwNodes::GoPrevious( &pREnd->nNode )) )
    1370             :                 {
    1371           2 :                     bStt = true;
    1372           2 :                     pREnd->nNode = rEnd;
    1373           2 :                     if( 0 == ( pCNd = pDoc->GetNodes().GoNext( &pREnd->nNode )) )
    1374             :                     {
    1375           2 :                         pREnd->nNode = pRStt->nNode;
    1376           2 :                         pCNd = pREnd->nNode.GetNode().GetContentNode();
    1377             :                     }
    1378             :                 }
    1379           2 :                 pREnd->nContent.Assign( pCNd, bStt ? 0 : pCNd->Len() );
    1380             :             }
    1381             :         }
    1382             :     }
    1383         177 : }
    1384             : 
    1385             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11