LCOV - code coverage report
Current view: top level - libreoffice/sw/source/core/crsr - bookmrk.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 100 205 48.8 %
Date: 2012-12-27 Functions: 22 51 43.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <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             : 
      35          76 : SV_IMPL_REF( SwServerObject )
      36             : 
      37             : using namespace ::sw::mark;
      38             : using namespace ::com::sun::star;
      39             : using namespace ::com::sun::star::uno;
      40             : 
      41             : namespace
      42             : {
      43        2701 :     static void lcl_FixPosition(SwPosition& rPos)
      44             :     {
      45             :         // make sure the position has 1) the proper node, and 2) a proper index
      46        2701 :         SwTxtNode* pTxtNode = rPos.nNode.GetNode().GetTxtNode();
      47        2701 :         if(pTxtNode == NULL && rPos.nContent.GetIndex() > 0)
      48             :         {
      49             :             OSL_TRACE(
      50             :                 "bookmrk.cxx::lcl_FixPosition"
      51             :                 " - illegal position: %d without proper TxtNode", rPos.nContent.GetIndex());
      52           0 :             rPos.nContent.Assign(NULL, 0);
      53             :         }
      54        2701 :         else if(pTxtNode != NULL && rPos.nContent.GetIndex() > pTxtNode->Len())
      55             :         {
      56             :             OSL_TRACE(
      57             :                 "bookmrk.cxx::lcl_FixPosition"
      58             :                 " - illegal position: %d is beyond %d", rPos.nContent.GetIndex(), pTxtNode->Len());
      59           0 :             rPos.nContent.Assign(pTxtNode, pTxtNode->Len());
      60             :         }
      61        2701 :     }
      62             : 
      63           7 :     static void lcl_AssureFieldMarksSet(Fieldmark* const pField,
      64             :         SwDoc* const io_pDoc,
      65             :         const sal_Unicode aStartMark,
      66             :         const sal_Unicode aEndMark)
      67             :     {
      68           7 :         SwPosition& rStart = pField->GetMarkStart();
      69           7 :         SwPosition& rEnd = pField->GetMarkEnd();
      70             :         SwTxtNode const*const pStartTxtNode =
      71           7 :             rStart.nNode.GetNode().GetTxtNode();
      72           7 :         SwTxtNode const*const pEndTxtNode = rEnd.nNode.GetNode().GetTxtNode();
      73           7 :         const sal_Unicode ch_start=pStartTxtNode->GetTxt().GetChar(rStart.nContent.GetIndex());
      74          13 :         xub_StrLen nEndPos = ( rEnd == rStart ||  rEnd.nContent.GetIndex() == 0 ) ?
      75          13 :             rEnd.nContent.GetIndex() : rEnd.nContent.GetIndex() - 1;
      76           7 :         const sal_Unicode ch_end=pEndTxtNode->GetTxt().GetChar( nEndPos );
      77           7 :         SwPaM aStartPaM(rStart);
      78           7 :         SwPaM aEndPaM(rEnd);
      79           7 :         io_pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_UI_REPLACE, NULL);
      80           7 :         if( ( ch_start != aStartMark ) && ( aEndMark != CH_TXT_ATR_FORMELEMENT ) )
      81             :         {
      82           6 :             io_pDoc->InsertString(aStartPaM, rtl::OUString(aStartMark));
      83           6 :             rStart.nContent--;
      84             :         }
      85           7 :         if ( aEndMark && ( ch_end != aEndMark ) )
      86             :         {
      87           7 :             io_pDoc->InsertString(aEndPaM, rtl::OUString(aEndMark));
      88           7 :             rEnd.nContent++;
      89             :         }
      90           7 :         io_pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_UI_REPLACE, NULL);
      91           7 :     };
      92             : 
      93           0 :     static void lcl_RemoveFieldMarks(Fieldmark* const pField,
      94             :         SwDoc* const io_pDoc,
      95             :         const sal_Unicode aStartMark,
      96             :         const sal_Unicode aEndMark)
      97             :     {
      98           0 :         SwPosition& rStart = pField->GetMarkStart();
      99           0 :         SwPosition& rEnd = pField->GetMarkEnd();
     100             :         SwTxtNode const*const pStartTxtNode =
     101           0 :             rStart.nNode.GetNode().GetTxtNode();
     102           0 :         SwTxtNode const*const pEndTxtNode = rEnd.nNode.GetNode().GetTxtNode();
     103           0 :         const sal_Unicode ch_start=pStartTxtNode->GetTxt().GetChar(rStart.nContent.GetIndex());
     104           0 :         xub_StrLen nEndPos = ( rEnd == rStart ||  rEnd.nContent.GetIndex() == 0 ) ?
     105           0 :             rEnd.nContent.GetIndex() : rEnd.nContent.GetIndex() - 1;
     106           0 :         const sal_Unicode ch_end=pEndTxtNode->GetTxt().GetChar( nEndPos );
     107           0 :         SwPaM aStartPaM(rStart);
     108           0 :         SwPaM aEndPaM(rEnd);
     109           0 :         io_pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_UI_REPLACE, NULL);
     110           0 :         if( ch_start == aStartMark )
     111             :         {
     112           0 :             SwPaM aStart(rStart, rStart);
     113           0 :             aStart.End()->nContent++;
     114           0 :             io_pDoc->DeleteRange(aStart);
     115             :         }
     116           0 :         if ( ch_end == aEndMark )
     117             :         {
     118           0 :             SwPaM aEnd(rEnd, rEnd);
     119           0 :             aEnd.Start()->nContent--;
     120           0 :             io_pDoc->DeleteRange(aEnd);
     121             :         }
     122           0 :         io_pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_UI_REPLACE, NULL);
     123           0 :     };
     124             : }
     125             : 
     126             : namespace sw { namespace mark
     127             : {
     128        2085 :     MarkBase::MarkBase(const SwPaM& aPaM,
     129             :         const ::rtl::OUString& rName)
     130             :         : SwModify(0)
     131        2085 :         , m_pPos1(new SwPosition(*(aPaM.GetPoint())))
     132        4170 :         , m_aName(rName)
     133             :     {
     134        2085 :         lcl_FixPosition(*m_pPos1);
     135        2085 :         if (aPaM.HasMark() && (*aPaM.GetMark() != *aPaM.GetPoint()))
     136             :         {
     137         616 :             MarkBase::SetOtherMarkPos(*(aPaM.GetMark()));
     138         616 :             lcl_FixPosition(*m_pPos2);
     139             :         }
     140        2085 :     }
     141             : 
     142             :     // For fieldmarks, the CH_TXT_ATR_FIELDSTART and CH_TXT_ATR_FIELDEND
     143             :     // themselves are part of the covered range. This is guaranteed by
     144             :     // TextFieldmark::InitDoc/lcl_AssureFieldMarksSet.
     145          79 :     bool MarkBase::IsCoveringPosition(const SwPosition& rPos) const
     146             :     {
     147          79 :         return GetMarkStart() <= rPos && rPos < GetMarkEnd();
     148             :     }
     149             : 
     150           0 :     void MarkBase::SetMarkPos(const SwPosition& rNewPos)
     151             :     {
     152           0 :         ::boost::scoped_ptr<SwPosition>(new SwPosition(rNewPos)).swap(m_pPos1);
     153           0 :     }
     154             : 
     155         617 :     void MarkBase::SetOtherMarkPos(const SwPosition& rNewPos)
     156             :     {
     157         617 :         ::boost::scoped_ptr<SwPosition>(new SwPosition(rNewPos)).swap(m_pPos2);
     158         617 :     }
     159             : 
     160           0 :     rtl::OUString MarkBase::ToString( ) const
     161             :     {
     162           0 :         rtl::OUStringBuffer buf;
     163           0 :         buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("Mark: ( Name, [ Node1, Index1 ] ): ( "));
     164           0 :         buf.append( m_aName ).appendAscii(RTL_CONSTASCII_STRINGPARAM(", [ "));
     165           0 :         buf.append( sal_Int32( GetMarkPos().nNode.GetIndex( ) ) )
     166           0 :             .appendAscii(RTL_CONSTASCII_STRINGPARAM(", "));
     167           0 :         buf.append( sal_Int32( GetMarkPos().nContent.GetIndex( ) ) )
     168           0 :             .appendAscii(RTL_CONSTASCII_STRINGPARAM(" ] )") );
     169             : 
     170           0 :         return buf.makeStringAndClear( );
     171             :     }
     172             : 
     173        2070 :     MarkBase::~MarkBase()
     174        6210 :     { }
     175             : 
     176        2085 :     ::rtl::OUString MarkBase::GenerateNewName(const ::rtl::OUString& rPrefix)
     177             :     {
     178        2085 :         static rtlRandomPool aPool = rtl_random_createPool();
     179        2085 :         static ::rtl::OUString sUniquePostfix;
     180             :         static sal_Int32 nCount = SAL_MAX_INT32;
     181        2085 :         ::rtl::OUStringBuffer aResult(rPrefix);
     182        2085 :         if(nCount == SAL_MAX_INT32)
     183             :         {
     184             :             sal_Int32 nRandom;
     185           7 :             rtl_random_getBytes(aPool, &nRandom, sizeof(nRandom));
     186           7 :             sUniquePostfix = ::rtl::OUStringBuffer(13).append('_').append(static_cast<sal_Int32>(abs(nRandom))).makeStringAndClear();
     187           7 :             nCount = 0;
     188             :         }
     189             :         // putting the counter in front of the random parts will speed up string comparisons
     190        2085 :         return aResult.append(nCount++).append(sUniquePostfix).makeStringAndClear();
     191             :     }
     192             : 
     193             : 
     194           0 :     void MarkBase::Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew )
     195             :     {
     196           0 :         NotifyClients(pOld, pNew);
     197           0 :         if (pOld && (RES_REMOVE_UNO_OBJECT == pOld->Which()))
     198             :         {   // invalidate cached uno object
     199           0 :             SetXBookmark(uno::Reference<text::XTextContent>(0));
     200             :         }
     201           0 :     }
     202             : 
     203             :     // TODO: everything else uses MarkBase::GenerateNewName ?
     204           0 :     NavigatorReminder::NavigatorReminder(const SwPaM& rPaM)
     205           0 :         : MarkBase(rPaM, rtl::OUString("__NavigatorReminder__"))
     206           0 :     { }
     207             : 
     208        2059 :     UnoMark::UnoMark(const SwPaM& aPaM)
     209        2059 :         : MarkBase(aPaM, MarkBase::GenerateNewName(rtl::OUString("__UnoMark__")))
     210        2059 :     { }
     211             : 
     212          19 :     DdeBookmark::DdeBookmark(const SwPaM& aPaM)
     213             :         : MarkBase(aPaM, MarkBase::GenerateNewName(rtl::OUString("__DdeLink__")))
     214          19 :         , m_aRefObj(NULL)
     215          19 :     { }
     216             : 
     217           0 :     void DdeBookmark::SetRefObject(SwServerObject* pObj)
     218             :     {
     219           0 :         m_aRefObj = pObj;
     220           0 :     }
     221             : 
     222           4 :     void DdeBookmark::DeregisterFromDoc(SwDoc* const pDoc)
     223             :     {
     224           4 :         if(m_aRefObj.Is())
     225           0 :             pDoc->GetLinkManager().RemoveServer(m_aRefObj);
     226           4 :     }
     227             : 
     228          22 :     DdeBookmark::~DdeBookmark()
     229             :     {
     230          11 :         if( m_aRefObj.Is() )
     231             :         {
     232           0 :             if(m_aRefObj->HasDataLinks())
     233             :             {
     234           0 :                 ::sfx2::SvLinkSource* p = &m_aRefObj;
     235           0 :                 p->SendDataChanged();
     236             :             }
     237           0 :             m_aRefObj->SetNoServer();
     238             :         }
     239          33 :     }
     240             : 
     241          19 :     Bookmark::Bookmark(const SwPaM& aPaM,
     242             :         const KeyCode& rCode,
     243             :         const ::rtl::OUString& rName,
     244             :         const ::rtl::OUString& rShortName)
     245             :         : DdeBookmark(aPaM)
     246             :         , ::sfx2::Metadatable()
     247             :         , m_aCode(rCode)
     248          19 :         , m_sShortName(rShortName)
     249             :     {
     250          19 :         m_aName = rName;
     251          19 :     }
     252             : 
     253          19 :     void Bookmark::InitDoc(SwDoc* const io_pDoc)
     254             :     {
     255          19 :         if (io_pDoc->GetIDocumentUndoRedo().DoesUndo())
     256             :         {
     257           0 :             io_pDoc->GetIDocumentUndoRedo().AppendUndo(
     258           0 :                     new SwUndoInsBookmark(*this));
     259             :         }
     260          19 :         io_pDoc->SetModified();
     261          19 :     }
     262             : 
     263           0 :     ::sfx2::IXmlIdRegistry& Bookmark::GetRegistry()
     264             :     {
     265           0 :         SwDoc *const pDoc( GetMarkPos().GetDoc() );
     266             :         OSL_ENSURE(pDoc, "Bookmark::MakeUnoObject: no doc?");
     267           0 :         return pDoc->GetXmlIdRegistry();
     268             :     }
     269             : 
     270           0 :     bool Bookmark::IsInClipboard() const
     271             :     {
     272           0 :         SwDoc *const pDoc( GetMarkPos().GetDoc() );
     273             :         OSL_ENSURE(pDoc, "Bookmark::IsInClipboard: no doc?");
     274           0 :         return pDoc->IsClipBoard();
     275             :     }
     276             : 
     277           0 :     bool Bookmark::IsInUndo() const
     278             :     {
     279           0 :         return false;
     280             :     }
     281             : 
     282           0 :     bool Bookmark::IsInContent() const
     283             :     {
     284           0 :         SwDoc *const pDoc( GetMarkPos().GetDoc() );
     285             :         OSL_ENSURE(pDoc, "Bookmark::IsInContent: no doc?");
     286           0 :         return !pDoc->IsInHeaderFooter( SwNodeIndex(GetMarkPos().nNode) );
     287             :     }
     288             : 
     289           0 :     uno::Reference< rdf::XMetadatable > Bookmark::MakeUnoObject()
     290             :     {
     291           0 :         SwDoc *const pDoc( GetMarkPos().GetDoc() );
     292             :         OSL_ENSURE(pDoc, "Bookmark::MakeUnoObject: no doc?");
     293             :         const uno::Reference< rdf::XMetadatable> xMeta(
     294           0 :                 SwXBookmark::CreateXBookmark(*pDoc, *this), uno::UNO_QUERY);
     295           0 :         return xMeta;
     296             :     }
     297             : 
     298           7 :     Fieldmark::Fieldmark(const SwPaM& rPaM)
     299           7 :         : MarkBase(rPaM, MarkBase::GenerateNewName(rtl::OUString("__Fieldmark__")))
     300             :     {
     301           7 :         if(!IsExpanded())
     302           1 :             SetOtherMarkPos(GetMarkPos());
     303           7 :     }
     304             : 
     305           0 :     rtl::OUString Fieldmark::ToString( ) const
     306             :     {
     307           0 :         rtl::OUStringBuffer buf;
     308             :         buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(
     309           0 :             "Fieldmark: ( Name, Type, [ Nd1, Id1 ], [ Nd2, Id2 ] ): ( "));
     310           0 :         buf.append( m_aName ).appendAscii(RTL_CONSTASCII_STRINGPARAM(", "));
     311           0 :         buf.append( m_aFieldname ).appendAscii(RTL_CONSTASCII_STRINGPARAM(", [ "));
     312           0 :         buf.append( sal_Int32( GetMarkPos().nNode.GetIndex( ) ) )
     313           0 :             .appendAscii(RTL_CONSTASCII_STRINGPARAM(", "));
     314           0 :         buf.append( sal_Int32( GetMarkPos( ).nContent.GetIndex( ) ) )
     315           0 :             .appendAscii(RTL_CONSTASCII_STRINGPARAM(" ], ["));
     316           0 :         buf.append( sal_Int32( GetOtherMarkPos().nNode.GetIndex( ) ) )
     317           0 :             .appendAscii(RTL_CONSTASCII_STRINGPARAM(", "));
     318           0 :         buf.append( sal_Int32( GetOtherMarkPos( ).nContent.GetIndex( ) ) )
     319           0 :             .appendAscii(RTL_CONSTASCII_STRINGPARAM(" ] ) "));
     320             : 
     321           0 :         return buf.makeStringAndClear( );
     322             :     }
     323             : 
     324           0 :     void Fieldmark::Invalidate( )
     325             :     {
     326             :         // TODO: Does exist a better solution to trigger a format of the
     327             :         //       fieldmark portion? If yes, please use it.
     328           0 :         SwPaM aPaM( this->GetMarkPos(), this->GetOtherMarkPos() );
     329           0 :         aPaM.InvalidatePaM();
     330           0 :     }
     331             : 
     332           6 :     TextFieldmark::TextFieldmark(const SwPaM& rPaM)
     333           6 :         : Fieldmark(rPaM)
     334           6 :     { }
     335             : 
     336           6 :     void TextFieldmark::InitDoc(SwDoc* const io_pDoc)
     337             :     {
     338           6 :         lcl_AssureFieldMarksSet(this, io_pDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND);
     339           6 :     }
     340             : 
     341           0 :     void TextFieldmark::ReleaseDoc(SwDoc* const pDoc)
     342             :     {
     343           0 :         lcl_RemoveFieldMarks(this, pDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND);
     344           0 :     }
     345             : 
     346           1 :     CheckboxFieldmark::CheckboxFieldmark(const SwPaM& rPaM)
     347           1 :         : Fieldmark(rPaM)
     348           1 :     { }
     349             : 
     350           1 :     void CheckboxFieldmark::InitDoc(SwDoc* const io_pDoc)
     351             :     {
     352           1 :         lcl_AssureFieldMarksSet(this, io_pDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FORMELEMENT);
     353             : 
     354             :         // For some reason the end mark is moved from 1 by the Insert: we don't
     355             :         // want this for checkboxes
     356           1 :         this->GetMarkEnd( ).nContent--;
     357           1 :     }
     358           1 :     void CheckboxFieldmark::SetChecked(bool checked)
     359             :     {
     360           1 :         if ( IsChecked() != checked )
     361             :         {
     362           1 :             (*GetParameters())[::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODF_FORMCHECKBOX_RESULT))] = makeAny(checked);
     363             :             // mark document as modified
     364           1 :             SwDoc *const pDoc( GetMarkPos().GetDoc() );
     365           1 :             if ( pDoc )
     366           1 :                 pDoc->SetModified();
     367             :         }
     368           1 :     }
     369             : 
     370           1 :     bool CheckboxFieldmark::IsChecked() const
     371             :     {
     372           1 :         bool bResult = false;
     373           1 :         parameter_map_t::const_iterator pResult = GetParameters()->find(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODF_FORMCHECKBOX_RESULT)));
     374           1 :         if(pResult != GetParameters()->end())
     375           0 :             pResult->second >>= bResult;
     376           1 :         return bResult;
     377             :     }
     378             : 
     379           0 :     rtl::OUString CheckboxFieldmark::toString( ) const
     380             :     {
     381           0 :         rtl::OUStringBuffer buf;
     382             :         buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(
     383           0 :             "CheckboxFieldmark: ( Name, Type, [ Nd1, Id1 ], [ Nd2, Id2 ] ): ( "));
     384           0 :         buf.append( m_aName ).appendAscii(RTL_CONSTASCII_STRINGPARAM(", "));
     385           0 :         buf.append( GetFieldname() ).appendAscii(RTL_CONSTASCII_STRINGPARAM(", [ "));
     386           0 :         buf.append( sal_Int32( GetMarkPos().nNode.GetIndex( ) ) )
     387           0 :             .appendAscii(RTL_CONSTASCII_STRINGPARAM(", "));
     388           0 :         buf.append( sal_Int32( GetMarkPos( ).nContent.GetIndex( ) ) )
     389           0 :             .appendAscii(RTL_CONSTASCII_STRINGPARAM(" ], ["));
     390           0 :         buf.append( sal_Int32( GetOtherMarkPos().nNode.GetIndex( ) ) )
     391           0 :             .appendAscii(RTL_CONSTASCII_STRINGPARAM(", "));
     392           0 :         buf.append( sal_Int32( GetOtherMarkPos( ).nContent.GetIndex( ) ) )
     393           0 :             .appendAscii(RTL_CONSTASCII_STRINGPARAM(" ] ) "));
     394             : 
     395           0 :         return buf.makeStringAndClear( );
     396             :     }
     397             : }}
     398             : 
     399             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10