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

Generated by: LCOV version 1.10