LCOV - code coverage report
Current view: top level - sw/source/core/crsr - bookmrk.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 132 200 66.0 %
Date: 2014-04-11 Functions: 32 50 64.0 %
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 <bookmrk.hxx>
      21             : #include <IDocumentMarkAccess.hxx>
      22             : #include <IDocumentUndoRedo.hxx>
      23             : #include <doc.hxx>
      24             : #include <ndtxt.hxx>
      25             : #include <pam.hxx>
      26             : #include <swserv.hxx>
      27             : #include <sfx2/linkmgr.hxx>
      28             : #include <swtypes.hxx>
      29             : #include <UndoBookmark.hxx>
      30             : #include <unobookmark.hxx>
      31             : #include <rtl/random.h>
      32             : #include <xmloff/odffields.hxx>
      33             : 
      34             : using namespace ::sw::mark;
      35             : using namespace ::com::sun::star;
      36             : using namespace ::com::sun::star::uno;
      37             : 
      38             : namespace
      39             : {
      40      122728 :     static void lcl_FixPosition(SwPosition& rPos)
      41             :     {
      42             :         // make sure the position has 1) the proper node, and 2) a proper index
      43      122728 :         SwTxtNode* pTxtNode = rPos.nNode.GetNode().GetTxtNode();
      44      122728 :         if(pTxtNode == NULL && rPos.nContent.GetIndex() > 0)
      45             :         {
      46             :             OSL_TRACE(
      47             :                 "bookmrk.cxx::lcl_FixPosition"
      48             :                 " - illegal position: %d without proper TxtNode", rPos.nContent.GetIndex());
      49           0 :             rPos.nContent.Assign(NULL, 0);
      50             :         }
      51      122728 :         else if(pTxtNode != NULL && rPos.nContent.GetIndex() > pTxtNode->Len())
      52             :         {
      53             :             OSL_TRACE(
      54             :                 "bookmrk.cxx::lcl_FixPosition"
      55             :                 " - illegal position: %d is beyond %d", rPos.nContent.GetIndex(), pTxtNode->Len());
      56           0 :             rPos.nContent.Assign(pTxtNode, pTxtNode->Len());
      57             :         }
      58      122728 :     }
      59             : 
      60          89 :     static void lcl_AssureFieldMarksSet(Fieldmark* const pField,
      61             :         SwDoc* const io_pDoc,
      62             :         const sal_Unicode aStartMark,
      63             :         const sal_Unicode aEndMark)
      64             :     {
      65          89 :         io_pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_UI_REPLACE, NULL);
      66             : 
      67          89 :         SwPosition rStart = pField->GetMarkStart();
      68          89 :         SwTxtNode const*const pStartTxtNode = rStart.nNode.GetNode().GetTxtNode();
      69          89 :         const sal_Unicode ch_start = ( rStart.nContent.GetIndex() >= pStartTxtNode->GetTxt().getLength() ) ? 0 :
      70          89 :             pStartTxtNode->GetTxt()[rStart.nContent.GetIndex()];
      71          89 :         if( ( ch_start != aStartMark ) && ( aEndMark != CH_TXT_ATR_FORMELEMENT ) )
      72             :         {
      73          81 :             SwPaM aStartPaM(rStart);
      74          81 :             io_pDoc->InsertString(aStartPaM, OUString(aStartMark));
      75          81 :             rStart.nContent--;
      76          81 :             pField->SetMarkStartPos( rStart );
      77             :         }
      78             : 
      79          89 :         SwPosition& rEnd = pField->GetMarkEnd();
      80          89 :         SwTxtNode const*const pEndTxtNode = rEnd.nNode.GetNode().GetTxtNode();
      81         171 :         const sal_Int32 nEndPos = ( rEnd == rStart ||  rEnd.nContent.GetIndex() == 0 ) ?
      82          96 :             rEnd.nContent.GetIndex() : rEnd.nContent.GetIndex() - 1;
      83          89 :         const sal_Unicode ch_end = nEndPos >= pEndTxtNode->GetTxt().getLength() ? 0 : pEndTxtNode->GetTxt()[nEndPos];
      84          89 :         if ( aEndMark && ( ch_end != aEndMark ) )
      85             :         {
      86          89 :             SwPaM aEndPaM(rEnd);
      87          89 :             io_pDoc->InsertString(aEndPaM, OUString(aEndMark));
      88          89 :             rEnd.nContent++;
      89             :         }
      90             : 
      91          89 :         io_pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_UI_REPLACE, NULL);
      92          89 :     };
      93             : 
      94           0 :     static void lcl_RemoveFieldMarks(Fieldmark* const pField,
      95             :         SwDoc* const io_pDoc,
      96             :         const sal_Unicode aStartMark,
      97             :         const sal_Unicode aEndMark)
      98             :     {
      99           0 :         io_pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_UI_REPLACE, NULL);
     100             : 
     101           0 :         const SwPosition& rStart = pField->GetMarkStart();
     102           0 :         SwTxtNode const*const pStartTxtNode = rStart.nNode.GetNode().GetTxtNode();
     103             :         const sal_Unicode ch_start =
     104           0 :             pStartTxtNode->GetTxt()[rStart.nContent.GetIndex()];
     105             : 
     106           0 :         if( ch_start == aStartMark )
     107             :         {
     108           0 :             SwPaM aStart(rStart, rStart);
     109           0 :             aStart.End()->nContent++;
     110           0 :             io_pDoc->DeleteRange(aStart);
     111             :         }
     112             : 
     113           0 :         const SwPosition& rEnd = pField->GetMarkEnd();
     114           0 :         SwTxtNode const*const pEndTxtNode = rEnd.nNode.GetNode().GetTxtNode();
     115           0 :         const sal_Int32 nEndPos = ( rEnd == rStart ||  rEnd.nContent.GetIndex() == 0 )
     116           0 :                                    ? rEnd.nContent.GetIndex()
     117           0 :                                    : rEnd.nContent.GetIndex() - 1;
     118           0 :         const sal_Unicode ch_end = pEndTxtNode->GetTxt()[nEndPos];
     119           0 :         if ( ch_end == aEndMark )
     120             :         {
     121           0 :             SwPaM aEnd(rEnd, rEnd);
     122           0 :             aEnd.Start()->nContent--;
     123           0 :             io_pDoc->DeleteRange(aEnd);
     124             :         }
     125             : 
     126           0 :         io_pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_UI_REPLACE, NULL);
     127           0 :     };
     128             : }
     129             : 
     130             : namespace sw { namespace mark
     131             : {
     132       83847 :     MarkBase::MarkBase(const SwPaM& aPaM,
     133             :         const OUString& rName)
     134             :         : SwModify(0)
     135       83847 :         , m_pPos1(new SwPosition(*(aPaM.GetPoint())))
     136      167694 :         , m_aName(rName)
     137             :     {
     138       83847 :         lcl_FixPosition(*m_pPos1);
     139       83847 :         if (aPaM.HasMark() && (*aPaM.GetMark() != *aPaM.GetPoint()))
     140             :         {
     141       38881 :             MarkBase::SetOtherMarkPos(*(aPaM.GetMark()));
     142       38881 :             lcl_FixPosition(*m_pPos2);
     143             :         }
     144       83847 :     }
     145             : 
     146             :     // For fieldmarks, the CH_TXT_ATR_FIELDSTART and CH_TXT_ATR_FIELDEND
     147             :     // themselves are part of the covered range. This is guaranteed by
     148             :     // TextFieldmark::InitDoc/lcl_AssureFieldMarksSet.
     149        1029 :     bool MarkBase::IsCoveringPosition(const SwPosition& rPos) const
     150             :     {
     151        1029 :         return GetMarkStart() <= rPos && rPos < GetMarkEnd();
     152             :     }
     153             : 
     154        1345 :     void MarkBase::SetMarkPos(const SwPosition& rNewPos)
     155             :     {
     156        1345 :         ::boost::scoped_ptr<SwPosition>(new SwPosition(rNewPos)).swap(m_pPos1);
     157        1345 :     }
     158             : 
     159       40308 :     void MarkBase::SetOtherMarkPos(const SwPosition& rNewPos)
     160             :     {
     161       40308 :         ::boost::scoped_ptr<SwPosition>(new SwPosition(rNewPos)).swap(m_pPos2);
     162       40308 :     }
     163             : 
     164           0 :     OUString MarkBase::ToString( ) const
     165             :     {
     166           0 :         return "Mark: ( Name, [ Node1, Index1 ] ): ( " + m_aName + ", [ "
     167           0 :             + OUString::number( GetMarkPos().nNode.GetIndex( ) )  + ", "
     168           0 :             + OUString::number( GetMarkPos().nContent.GetIndex( ) ) + " ] )";
     169             :     }
     170             : 
     171       83847 :     MarkBase::~MarkBase()
     172       83847 :     { }
     173             : 
     174       83838 :     OUString MarkBase::GenerateNewName(const OUString& rPrefix)
     175             :     {
     176       83838 :         static bool bHack = (getenv("LIBO_ONEWAY_STABLE_ODF_EXPORT") != NULL);
     177             : 
     178       83838 :         if (bHack)
     179             :         {
     180             :             static sal_Int64 nIdCounter = SAL_CONST_INT64(6000000000);
     181           0 :             return rPrefix + OUString::number(nIdCounter++);
     182             :         }
     183             :         else
     184             :         {
     185       83838 :             static rtlRandomPool aPool = rtl_random_createPool();
     186       83838 :             static OUString sUniquePostfix;
     187             :             static sal_Int32 nCount = SAL_MAX_INT32;
     188       83838 :             OUStringBuffer aResult(rPrefix);
     189       83838 :             if(nCount == SAL_MAX_INT32)
     190             :             {
     191             :                 sal_Int32 nRandom;
     192          27 :                 rtl_random_getBytes(aPool, &nRandom, sizeof(nRandom));
     193          27 :                 sUniquePostfix = OUStringBuffer(13).append('_').append(static_cast<sal_Int32>(abs(nRandom))).makeStringAndClear();
     194          27 :                 nCount = 0;
     195             :             }
     196             :             // putting the counter in front of the random parts will speed up string comparisons
     197       83838 :             return aResult.append(nCount++).append(sUniquePostfix).makeStringAndClear();
     198             :         }
     199             :     }
     200             : 
     201           0 :     void MarkBase::Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew )
     202             :     {
     203           0 :         NotifyClients(pOld, pNew);
     204           0 :         if (pOld && (RES_REMOVE_UNO_OBJECT == pOld->Which()))
     205             :         {   // invalidate cached uno object
     206           0 :             SetXBookmark(uno::Reference<text::XTextContent>(0));
     207             :         }
     208           0 :     }
     209             : 
     210             :     // TODO: everything else uses MarkBase::GenerateNewName ?
     211           0 :     NavigatorReminder::NavigatorReminder(const SwPaM& rPaM)
     212           0 :         : MarkBase(rPaM, OUString("__NavigatorReminder__"))
     213           0 :     { }
     214             : 
     215       80193 :     UnoMark::UnoMark(const SwPaM& aPaM)
     216       80193 :         : MarkBase(aPaM, MarkBase::GenerateNewName(OUString("__UnoMark__")))
     217       80193 :     { }
     218             : 
     219        3526 :     DdeBookmark::DdeBookmark(const SwPaM& aPaM)
     220             :         : MarkBase(aPaM, MarkBase::GenerateNewName(OUString("__DdeLink__")))
     221        3526 :         , m_aRefObj(NULL)
     222        3526 :     { }
     223             : 
     224           2 :     void DdeBookmark::SetRefObject(SwServerObject* pObj)
     225             :     {
     226           2 :         m_aRefObj = pObj;
     227           2 :     }
     228             : 
     229         225 :     void DdeBookmark::DeregisterFromDoc(SwDoc* const pDoc)
     230             :     {
     231         225 :         if(m_aRefObj.Is())
     232           0 :             pDoc->GetLinkManager().RemoveServer(m_aRefObj);
     233         225 :     }
     234             : 
     235        7054 :     DdeBookmark::~DdeBookmark()
     236             :     {
     237        3526 :         if( m_aRefObj.Is() )
     238             :         {
     239           1 :             if(m_aRefObj->HasDataLinks())
     240             :             {
     241           0 :                 ::sfx2::SvLinkSource* p = &m_aRefObj;
     242           0 :                 p->SendDataChanged();
     243             :             }
     244           1 :             m_aRefObj->SetNoServer();
     245             :         }
     246        3528 :     }
     247             : 
     248        3525 :     Bookmark::Bookmark(const SwPaM& aPaM,
     249             :         const KeyCode& rCode,
     250             :         const OUString& rName,
     251             :         const OUString& rShortName)
     252             :         : DdeBookmark(aPaM)
     253             :         , ::sfx2::Metadatable()
     254             :         , m_aCode(rCode)
     255        3525 :         , m_sShortName(rShortName)
     256             :     {
     257        3525 :         m_aName = rName;
     258        3525 :     }
     259             : 
     260        3525 :     void Bookmark::InitDoc(SwDoc* const io_pDoc)
     261             :     {
     262        3525 :         if (io_pDoc->GetIDocumentUndoRedo().DoesUndo())
     263             :         {
     264        1039 :             io_pDoc->GetIDocumentUndoRedo().AppendUndo(
     265        1039 :                     new SwUndoInsBookmark(*this));
     266             :         }
     267        3525 :         io_pDoc->SetModified();
     268        3525 :     }
     269             : 
     270          14 :     ::sfx2::IXmlIdRegistry& Bookmark::GetRegistry()
     271             :     {
     272          14 :         SwDoc *const pDoc( GetMarkPos().GetDoc() );
     273             :         OSL_ENSURE(pDoc, "Bookmark::MakeUnoObject: no doc?");
     274          14 :         return pDoc->GetXmlIdRegistry();
     275             :     }
     276             : 
     277        1308 :     bool Bookmark::IsInClipboard() const
     278             :     {
     279        1308 :         SwDoc *const pDoc( GetMarkPos().GetDoc() );
     280             :         OSL_ENSURE(pDoc, "Bookmark::IsInClipboard: no doc?");
     281        1308 :         return pDoc->IsClipBoard();
     282             :     }
     283             : 
     284        1308 :     bool Bookmark::IsInUndo() const
     285             :     {
     286        1308 :         return false;
     287             :     }
     288             : 
     289          16 :     bool Bookmark::IsInContent() const
     290             :     {
     291          16 :         SwDoc *const pDoc( GetMarkPos().GetDoc() );
     292             :         OSL_ENSURE(pDoc, "Bookmark::IsInContent: no doc?");
     293          16 :         return !pDoc->IsInHeaderFooter( SwNodeIndex(GetMarkPos().nNode) );
     294             :     }
     295             : 
     296           0 :     uno::Reference< rdf::XMetadatable > Bookmark::MakeUnoObject()
     297             :     {
     298           0 :         SwDoc *const pDoc( GetMarkPos().GetDoc() );
     299             :         OSL_ENSURE(pDoc, "Bookmark::MakeUnoObject: no doc?");
     300             :         const uno::Reference< rdf::XMetadatable> xMeta(
     301           0 :                 SwXBookmark::CreateXBookmark(*pDoc, *this), uno::UNO_QUERY);
     302           0 :         return xMeta;
     303             :     }
     304             : 
     305          89 :     Fieldmark::Fieldmark(const SwPaM& rPaM)
     306          89 :         : MarkBase(rPaM, MarkBase::GenerateNewName(OUString("__Fieldmark__")))
     307             :     {
     308          89 :         if(!IsExpanded())
     309          86 :             SetOtherMarkPos(GetMarkPos());
     310          89 :     }
     311             : 
     312          81 :     void Fieldmark::SetMarkStartPos( const SwPosition& rNewStartPos )
     313             :     {
     314          81 :         if ( GetMarkPos( ) <= GetOtherMarkPos( ) )
     315          81 :             return SetMarkPos( rNewStartPos );
     316             :         else
     317           0 :             return SetOtherMarkPos( rNewStartPos );
     318             :     }
     319             : 
     320           8 :     void Fieldmark::SetMarkEndPos( const SwPosition& rNewEndPos )
     321             :     {
     322           8 :         if ( GetMarkPos( ) <= GetOtherMarkPos( ) )
     323           8 :             return SetOtherMarkPos( rNewEndPos );
     324             :         else
     325           0 :             return SetMarkPos( rNewEndPos );
     326             :     }
     327             : 
     328           0 :     OUString Fieldmark::ToString( ) const
     329             :     {
     330           0 :         return "Fieldmark: ( Name, Type, [ Nd1, Id1 ], [ Nd2, Id2 ] ): ( " + m_aName + ", "
     331           0 :             + m_aFieldname + ", [ " + OUString::number( GetMarkPos().nNode.GetIndex( ) )
     332           0 :             + ", " + OUString::number( GetMarkPos( ).nContent.GetIndex( ) ) + " ], ["
     333           0 :             + OUString::number( GetOtherMarkPos().nNode.GetIndex( ) ) + ", "
     334           0 :             + OUString::number( GetOtherMarkPos( ).nContent.GetIndex( ) ) + " ] ) ";
     335             :     }
     336             : 
     337           0 :     void Fieldmark::Invalidate( )
     338             :     {
     339             :         // TODO: Does exist a better solution to trigger a format of the
     340             :         //       fieldmark portion? If yes, please use it.
     341           0 :         SwPaM aPaM( this->GetMarkPos(), this->GetOtherMarkPos() );
     342           0 :         aPaM.InvalidatePaM();
     343           0 :     }
     344             : 
     345          81 :     TextFieldmark::TextFieldmark(const SwPaM& rPaM)
     346          81 :         : Fieldmark(rPaM)
     347          81 :     { }
     348             : 
     349          81 :     void TextFieldmark::InitDoc(SwDoc* const io_pDoc)
     350             :     {
     351          81 :         lcl_AssureFieldMarksSet(this, io_pDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND);
     352          81 :     }
     353             : 
     354           0 :     void TextFieldmark::ReleaseDoc(SwDoc* const pDoc)
     355             :     {
     356           0 :         lcl_RemoveFieldMarks(this, pDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND);
     357           0 :     }
     358             : 
     359           8 :     CheckboxFieldmark::CheckboxFieldmark(const SwPaM& rPaM)
     360           8 :         : Fieldmark(rPaM)
     361           8 :     { }
     362             : 
     363           8 :     void CheckboxFieldmark::InitDoc(SwDoc* const io_pDoc)
     364             :     {
     365           8 :         lcl_AssureFieldMarksSet(this, io_pDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FORMELEMENT);
     366             : 
     367             :         // For some reason the end mark is moved from 1 by the Insert: we don't
     368             :         // want this for checkboxes
     369           8 :         SwPosition aNewEndPos = this->GetMarkEnd();
     370           8 :         aNewEndPos.nContent--;
     371           8 :         SetMarkEndPos( aNewEndPos );
     372           8 :     }
     373             : 
     374           0 :     void CheckboxFieldmark::ReleaseDoc(SwDoc* const pDoc)
     375             :     {
     376             :         lcl_RemoveFieldMarks(this, pDoc,
     377           0 :                 CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FORMELEMENT);
     378           0 :     }
     379             : 
     380           7 :     void CheckboxFieldmark::SetChecked(bool checked)
     381             :     {
     382           7 :         if ( IsChecked() != checked )
     383             :         {
     384           2 :             (*GetParameters())[OUString(ODF_FORMCHECKBOX_RESULT)] = makeAny(checked);
     385             :             // mark document as modified
     386           2 :             SwDoc *const pDoc( GetMarkPos().GetDoc() );
     387           2 :             if ( pDoc )
     388           2 :                 pDoc->SetModified();
     389             :         }
     390           7 :     }
     391             : 
     392           8 :     bool CheckboxFieldmark::IsChecked() const
     393             :     {
     394           8 :         bool bResult = false;
     395           8 :         parameter_map_t::const_iterator pResult = GetParameters()->find(OUString(ODF_FORMCHECKBOX_RESULT));
     396           8 :         if(pResult != GetParameters()->end())
     397           0 :             pResult->second >>= bResult;
     398           8 :         return bResult;
     399             :     }
     400             : 
     401           0 :     OUString CheckboxFieldmark::toString( ) const
     402             :     {
     403             : 
     404             :         return "CheckboxFieldmark: ( Name, Type, [ Nd1, Id1 ], [ Nd2, Id2 ] ): ( "
     405           0 :             + m_aName + ", " + GetFieldname() + ", [ "
     406           0 :             + OUString::number(GetMarkPos().nNode.GetIndex( ) ) + ", "
     407           0 :             + OUString::number( GetMarkPos( ).nContent.GetIndex( ) ) + " ], ["
     408           0 :             + OUString::number( GetOtherMarkPos().nNode.GetIndex( ) ) + ", "
     409           0 :             + OUString::number( GetOtherMarkPos( ).nContent.GetIndex( ) ) + " ] ) ";
     410             :     }
     411             : }}
     412             : 
     413             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10