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

Generated by: LCOV version 1.10