LCOV - code coverage report
Current view: top level - libreoffice/sw/source/filter/xml - XMLRedlineImportHelper.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 48 246 19.5 %
Date: 2012-12-27 Functions: 5 25 20.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 "XMLRedlineImportHelper.hxx"
      21             : #include <unotextcursor.hxx>
      22             : #include <unotextrange.hxx>
      23             : #include <unocrsr.hxx>
      24             : #include "doc.hxx"
      25             : #include <tools/datetime.hxx>
      26             : #include "poolfmt.hxx"
      27             : #include "unoredline.hxx"
      28             : #include <xmloff/xmltoken.hxx>
      29             : #include <com/sun/star/frame/XModel.hpp>
      30             : 
      31             : // for locking SolarMutex: svapp + mutex
      32             : #include <vcl/svapp.hxx>
      33             : #include <osl/mutex.hxx>
      34             : 
      35             : 
      36             : 
      37             : using namespace ::com::sun::star;
      38             : using namespace ::com::sun::star::uno;
      39             : using namespace ::xmloff::token;
      40             : 
      41             : using ::rtl::OUString;
      42             : using ::com::sun::star::frame::XModel;
      43             : using ::com::sun::star::text::XTextCursor;
      44             : using ::com::sun::star::text::XTextRange;
      45             : using ::com::sun::star::text::XText;
      46             : using ::com::sun::star::text::XWordCursor;
      47             : using ::com::sun::star::lang::XUnoTunnel;
      48             : using ::com::sun::star::beans::XPropertySet;
      49             : using ::com::sun::star::beans::XPropertySetInfo;
      50             : // collision with tools/DateTime: use UNO DateTime as util::DateTime
      51             : // using util::DateTime;
      52             : 
      53             : 
      54             : //
      55             : // a few helper functions
      56             : //
      57             : 
      58           0 : static SwDoc* lcl_GetDocViaTunnel( Reference<XTextCursor> & rCursor )
      59             : {
      60           0 :     Reference<XUnoTunnel> xTunnel( rCursor, UNO_QUERY);
      61             :     OSL_ENSURE(xTunnel.is(), "missing XUnoTunnel for XTextCursor");
      62             :     OTextCursorHelper *const pXCursor =
      63           0 :         ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xTunnel);
      64             :     OSL_ENSURE( pXCursor, "OTextCursorHelper missing" );
      65           0 :     return (pXCursor) ? pXCursor->GetDoc() : 0;
      66             : }
      67             : 
      68           0 : static SwDoc* lcl_GetDocViaTunnel( Reference<XTextRange> & rRange )
      69             : {
      70           0 :     Reference<XUnoTunnel> xTunnel(rRange, UNO_QUERY);
      71             :     OSL_ENSURE(xTunnel.is(), "missing XUnoTunnel for XTextRange");
      72             :     SwXTextRange *const pXRange =
      73           0 :         ::sw::UnoTunnelGetImplementation<SwXTextRange>(xTunnel);
      74             :     // #i115174#: this may be a SvxUnoTextRange
      75             : //    OSL_ENSURE( pXRange, "SwXTextRange missing" );
      76           0 :     return (pXRange) ? pXRange->GetDoc() : 0;
      77             : }
      78             : 
      79             : 
      80             : //
      81             : // XTextRangeOrNodeIndexPosition: store a position into the text
      82             : // *either* as an XTextRange or as an SwNodeIndex. The reason is that
      83             : // we must store either pointers to StartNodes (because redlines may
      84             : // start on start nodes) or to a text position, and there appears to
      85             : // be no existing type that could do both. Things are complicated by
      86             : // the matter that (e.g in section import) we delete a few characters,
      87             : // which may cause bookmarks (as used by XTextRange) to be deleted.
      88             : //
      89             : 
      90             : class XTextRangeOrNodeIndexPosition
      91             : {
      92             :     Reference<XTextRange> xRange;
      93             :     SwNodeIndex* pIndex;    /// pIndex will point to the *previous* node
      94             : 
      95             : public:
      96             :     XTextRangeOrNodeIndexPosition();
      97             :     ~XTextRangeOrNodeIndexPosition();
      98             : 
      99             :     void Set( Reference<XTextRange> & rRange );
     100             :     void Set( SwNodeIndex& rIndex );
     101             :     void SetAsNodeIndex( Reference<XTextRange> & rRange );
     102             : 
     103             :     void CopyPositionInto(SwPosition& rPos, SwDoc & rDoc);
     104             :     SwDoc* GetDoc();
     105             : 
     106             :     sal_Bool IsValid();
     107             : };
     108             : 
     109           0 : XTextRangeOrNodeIndexPosition::XTextRangeOrNodeIndexPosition() :
     110             :     xRange(NULL),
     111           0 :     pIndex(NULL)
     112             : {
     113           0 : }
     114             : 
     115           0 : XTextRangeOrNodeIndexPosition::~XTextRangeOrNodeIndexPosition()
     116             : {
     117           0 :     delete pIndex;
     118           0 : }
     119             : 
     120           0 : void XTextRangeOrNodeIndexPosition::Set( Reference<XTextRange> & rRange )
     121             : {
     122           0 :     xRange = rRange->getStart();    // set bookmark
     123           0 :     if (NULL != pIndex)
     124             :     {
     125           0 :         delete pIndex;
     126           0 :         pIndex = NULL;
     127             :     }
     128           0 : }
     129             : 
     130           0 : void XTextRangeOrNodeIndexPosition::Set( SwNodeIndex& rIndex )
     131             : {
     132           0 :     if (NULL != pIndex)
     133           0 :         delete pIndex;
     134             : 
     135           0 :     pIndex = new SwNodeIndex(rIndex);
     136           0 :     (*pIndex)-- ;   // previous node!!!
     137           0 :     xRange = NULL;
     138           0 : }
     139             : 
     140           0 : void XTextRangeOrNodeIndexPosition::SetAsNodeIndex(
     141             :     Reference<XTextRange> & rRange )
     142             : {
     143             :     // XTextRange -> XTunnel -> SwXTextRange
     144           0 :     SwDoc* pDoc = lcl_GetDocViaTunnel(rRange);
     145             : 
     146           0 :     if (!pDoc)
     147             :     {
     148             :         OSL_TRACE("SetAsNodeIndex: no SwDoc");
     149           0 :         return;
     150             :     }
     151             : 
     152             :     // SwXTextRange -> PaM
     153           0 :     SwUnoInternalPaM aPaM(*pDoc);
     154             : #if OSL_DEBUG_LEVEL > 0
     155             :     sal_Bool bSuccess =
     156             : #endif
     157           0 :         ::sw::XTextRangeToSwPaM(aPaM, rRange);
     158             :     OSL_ENSURE(bSuccess, "illegal range");
     159             : 
     160             :     // PaM -> Index
     161           0 :     Set(aPaM.GetPoint()->nNode);
     162             : }
     163             : 
     164             : void
     165           0 : XTextRangeOrNodeIndexPosition::CopyPositionInto(SwPosition& rPos, SwDoc & rDoc)
     166             : {
     167             :     OSL_ENSURE(IsValid(), "Can't get Position");
     168             : 
     169             :     // create PAM from start cursor (if no node index is present)
     170           0 :     if (NULL == pIndex)
     171             :     {
     172           0 :         SwUnoInternalPaM aUnoPaM(rDoc);
     173             : #if OSL_DEBUG_LEVEL > 0
     174             :         sal_Bool bSuccess =
     175             : #endif
     176           0 :             ::sw::XTextRangeToSwPaM(aUnoPaM, xRange);
     177             :         OSL_ENSURE(bSuccess, "illegal range");
     178             : 
     179           0 :         rPos = *aUnoPaM.GetPoint();
     180             :     }
     181             :     else
     182             :     {
     183           0 :         rPos.nNode = *pIndex;
     184           0 :         rPos.nNode++;           // pIndex points to previous index !!!
     185           0 :         rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), 0 );
     186             :     }
     187           0 : }
     188             : 
     189           0 : SwDoc* XTextRangeOrNodeIndexPosition::GetDoc()
     190             : {
     191             :     OSL_ENSURE(IsValid(), "Can't get Doc");
     192             : 
     193           0 :     return (NULL != pIndex) ? pIndex->GetNodes().GetDoc() : lcl_GetDocViaTunnel(xRange);
     194             : }
     195             : 
     196           0 : sal_Bool XTextRangeOrNodeIndexPosition::IsValid()
     197             : {
     198           0 :     return ( xRange.is() || (pIndex != NULL) );
     199             : }
     200             : 
     201             : 
     202             : //
     203             : // RedlineInfo: temporary storage for redline data
     204             : //
     205             : 
     206             : class RedlineInfo
     207             : {
     208             : public:
     209             :     RedlineInfo();
     210             :     ~RedlineInfo();
     211             : 
     212             :     /// redline type (insert, delete, ...)
     213             :     RedlineType_t eType;
     214             : 
     215             :     // info fields:
     216             :     OUString sAuthor;               /// change author string
     217             :     OUString sComment;              /// change comment string
     218             :     util::DateTime aDateTime;       /// change DateTime
     219             :     sal_Bool bMergeLastParagraph;   /// the SwRedline::IsDelLastPara flag
     220             : 
     221             :     // each position can may be either empty, an XTextRange, or an SwNodeIndex
     222             : 
     223             :     // start pos of anchor (may be empty)
     224             :     XTextRangeOrNodeIndexPosition aAnchorStart;
     225             : 
     226             :     // end pos of anchor (may be empty)
     227             :     XTextRangeOrNodeIndexPosition aAnchorEnd;
     228             : 
     229             :     /// index of content node (maybe NULL)
     230             :     SwNodeIndex* pContentIndex;
     231             : 
     232             :     /// next redline info (for hierarchical redlines)
     233             :     RedlineInfo* pNextRedline;
     234             : 
     235             :     /// store whether we expect an adjustment for this redline
     236             :     sal_Bool bNeedsAdjustment;
     237             : };
     238             : 
     239           0 : RedlineInfo::RedlineInfo() :
     240             :     eType(nsRedlineType_t::REDLINE_INSERT),
     241             :     sAuthor(),
     242             :     sComment(),
     243             :     aDateTime(),
     244             :     bMergeLastParagraph( sal_False ),
     245             :     aAnchorStart(),
     246             :     aAnchorEnd(),
     247             :     pContentIndex(NULL),
     248             :     pNextRedline(NULL),
     249           0 :     bNeedsAdjustment( sal_False )
     250             : {
     251           0 : }
     252             : 
     253           0 : RedlineInfo::~RedlineInfo()
     254             : {
     255           0 :     delete pContentIndex;
     256           0 :     delete pNextRedline;
     257           0 : }
     258             : 
     259             : 
     260             : //
     261             : // XMLRedlineImportHelper
     262             : //
     263             : 
     264          71 : XMLRedlineImportHelper::XMLRedlineImportHelper(
     265             :     sal_Bool bNoRedlinesPlease,
     266             :     const Reference<XPropertySet> & rModel,
     267             :     const Reference<XPropertySet> & rImportInfo ) :
     268             :         sEmpty(),
     269          71 :         sInsertion( GetXMLToken( XML_INSERTION )),
     270          71 :         sDeletion( GetXMLToken( XML_DELETION )),
     271          71 :         sFormatChange( GetXMLToken( XML_FORMAT_CHANGE )),
     272             :         sShowChanges(RTL_CONSTASCII_USTRINGPARAM("ShowChanges")),
     273             :         sRecordChanges(RTL_CONSTASCII_USTRINGPARAM("RecordChanges")),
     274             :         sRedlineProtectionKey(RTL_CONSTASCII_USTRINGPARAM("RedlineProtectionKey")),
     275             :         aRedlineMap(),
     276             :         bIgnoreRedlines(bNoRedlinesPlease),
     277             :         xModelPropertySet(rModel),
     278         284 :         xImportInfoPropertySet(rImportInfo)
     279             : {
     280             :     // check to see if redline mode is handled outside of component
     281          71 :     sal_Bool bHandleShowChanges = sal_True;
     282          71 :     sal_Bool bHandleRecordChanges = sal_True;
     283          71 :     sal_Bool bHandleProtectionKey = sal_True;
     284          71 :     if ( xImportInfoPropertySet.is() )
     285             :     {
     286             :         Reference<XPropertySetInfo> xInfo =
     287          71 :             xImportInfoPropertySet->getPropertySetInfo();
     288             : 
     289          71 :         bHandleShowChanges = ! xInfo->hasPropertyByName( sShowChanges );
     290          71 :         bHandleRecordChanges = ! xInfo->hasPropertyByName( sRecordChanges );
     291          71 :         bHandleProtectionKey = ! xInfo->hasPropertyByName( sRedlineProtectionKey );
     292             :     }
     293             : 
     294             :     // get redline mode
     295             :     bShowChanges = *(sal_Bool*)
     296             :         ( bHandleShowChanges ? xModelPropertySet : xImportInfoPropertySet )
     297          71 :         ->getPropertyValue( sShowChanges ).getValue();
     298             :     bRecordChanges = *(sal_Bool*)
     299             :         ( bHandleRecordChanges ? xModelPropertySet : xImportInfoPropertySet )
     300          71 :         ->getPropertyValue( sRecordChanges ).getValue();
     301             :     {
     302             :         Any aAny = (bHandleProtectionKey  ? xModelPropertySet
     303             :                                           : xImportInfoPropertySet )
     304          71 :                         ->getPropertyValue( sRedlineProtectionKey );
     305          71 :         aAny >>= aProtectionKey;
     306             :     }
     307             : 
     308             :     // set redline mode to "don't record changes"
     309          71 :     if( bHandleRecordChanges )
     310             :     {
     311           0 :         Any aAny;
     312           0 :         sal_Bool bTmp = sal_False;
     313           0 :         aAny.setValue( &bTmp, ::getBooleanCppuType() );
     314           0 :         xModelPropertySet->setPropertyValue( sRecordChanges, aAny );
     315             :     }
     316          71 : }
     317             : 
     318         213 : XMLRedlineImportHelper::~XMLRedlineImportHelper()
     319             : {
     320             :     // delete all left over (and obviously incomplete) RedlineInfos (and map)
     321          71 :     RedlineMapType::iterator aFind = aRedlineMap.begin();
     322          71 :     for( ; aRedlineMap.end() != aFind; ++aFind )
     323             :     {
     324           0 :         RedlineInfo* pInfo = aFind->second;
     325             : 
     326             :         // left-over redlines. Insert them if possible (but assert),
     327             :         // and delete the incomplete ones. Finally, delete it.
     328           0 :         if( IsReady(pInfo) )
     329             :         {
     330             :             OSL_FAIL("forgotten RedlineInfo; now inserted");
     331           0 :             InsertIntoDocument( pInfo );
     332             :         }
     333             :         else
     334             :         {
     335             :             // try if only the adjustment was missing
     336           0 :             pInfo->bNeedsAdjustment = sal_False;
     337           0 :             if( IsReady(pInfo) )
     338             :             {
     339             :                 OSL_FAIL("RedlineInfo without adjustment; now inserted");
     340           0 :                 InsertIntoDocument( pInfo );
     341             :             }
     342             :             else
     343             :             {
     344             :                 // this situation occurs if redlines aren't closed
     345             :                 // (i.e. end without start, or start without
     346             :                 // end). This may well be a problem in the file,
     347             :                 // rather than the code.
     348             :                 OSL_FAIL("incomplete redline (maybe file was corrupt); "
     349             :                           "now deleted");
     350             :             }
     351             :         }
     352           0 :         delete pInfo;
     353             :     }
     354          71 :     aRedlineMap.clear();
     355             : 
     356             :     // set redline mode, either to info property set, or directly to
     357             :     // the document
     358          71 :     sal_Bool bHandleShowChanges = sal_True;
     359          71 :     sal_Bool bHandleRecordChanges = sal_True;
     360          71 :     sal_Bool bHandleProtectionKey = sal_True;
     361          71 :     if ( xImportInfoPropertySet.is() )
     362             :     {
     363             :         Reference<XPropertySetInfo> xInfo =
     364          71 :             xImportInfoPropertySet->getPropertySetInfo();
     365             : 
     366          71 :         bHandleShowChanges = ! xInfo->hasPropertyByName( sShowChanges );
     367          71 :         bHandleRecordChanges = ! xInfo->hasPropertyByName( sRecordChanges );
     368          71 :         bHandleProtectionKey = ! xInfo->hasPropertyByName( sRedlineProtectionKey );
     369             :     }
     370             : 
     371             :     // set redline mode & key
     372          71 :     Any aAny;
     373             : 
     374          71 :     aAny.setValue( &bShowChanges, ::getBooleanCppuType() );
     375          71 :     if ( bHandleShowChanges )
     376           0 :         xModelPropertySet->setPropertyValue( sShowChanges, aAny );
     377             :     else
     378          71 :         xImportInfoPropertySet->setPropertyValue( sShowChanges, aAny );
     379             : 
     380          71 :     aAny.setValue( &bRecordChanges, ::getBooleanCppuType() );
     381          71 :     if ( bHandleRecordChanges )
     382           0 :         xModelPropertySet->setPropertyValue( sRecordChanges, aAny );
     383             :     else
     384          71 :         xImportInfoPropertySet->setPropertyValue( sRecordChanges, aAny );
     385             : 
     386          71 :     aAny <<= aProtectionKey;
     387          71 :     if ( bHandleProtectionKey )
     388           0 :         xModelPropertySet->setPropertyValue( sRedlineProtectionKey, aAny );
     389             :     else
     390          71 :         xImportInfoPropertySet->setPropertyValue( sRedlineProtectionKey, aAny);
     391         142 : }
     392             : 
     393           0 : void XMLRedlineImportHelper::Add(
     394             :     const OUString& rType,
     395             :     const OUString& rId,
     396             :     const OUString& rAuthor,
     397             :     const OUString& rComment,
     398             :     const util::DateTime& rDateTime,
     399             :     sal_Bool bMergeLastPara)
     400             : {
     401             :     // we need to do the following:
     402             :     // 1) parse type string
     403             :     // 2) create RedlineInfo and fill it with data
     404             :     // 3) check for existing redline with same ID
     405             :     // 3a) insert redline into map
     406             :     // 3b) attach to existing redline
     407             : 
     408             :     // ad 1)
     409             :     RedlineType_t eType;
     410           0 :     if (rType.equals(sInsertion))
     411             :     {
     412           0 :         eType = nsRedlineType_t::REDLINE_INSERT;
     413             :     }
     414           0 :     else if (rType.equals(sDeletion))
     415             :     {
     416           0 :         eType = nsRedlineType_t::REDLINE_DELETE;
     417             :     }
     418           0 :     else if (rType.equals(sFormatChange))
     419             :     {
     420           0 :         eType = nsRedlineType_t::REDLINE_FORMAT;
     421             :     }
     422             :     else
     423             :     {
     424             :         // no proper type found: early out!
     425           0 :         return;
     426             :     }
     427             : 
     428             :     // ad 2) create a new RedlineInfo
     429           0 :     RedlineInfo* pInfo = new RedlineInfo();
     430             : 
     431             :     // fill entries
     432           0 :     pInfo->eType = eType;
     433           0 :     pInfo->sAuthor = rAuthor;
     434           0 :     pInfo->sComment = rComment;
     435           0 :     pInfo->aDateTime = rDateTime;
     436           0 :     pInfo->bMergeLastParagraph = bMergeLastPara;
     437             : 
     438             : 
     439             :     // ad 3)
     440           0 :     if (aRedlineMap.end() == aRedlineMap.find(rId))
     441             :     {
     442             :         // 3a) insert into map
     443           0 :         aRedlineMap[rId] = pInfo;
     444             :     }
     445             :     else
     446             :     {
     447             :         // 3b) we already have a redline with this name: hierarchical redlines
     448             :         // insert pInfo as last element in the chain.
     449             :         // (hierarchy sanity checking happens on insertino into the document)
     450             : 
     451             :         // find last element
     452             :         RedlineInfo* pInfoChain;
     453           0 :         for( pInfoChain = aRedlineMap[rId];
     454             :             NULL != pInfoChain->pNextRedline;
     455             :             pInfoChain = pInfoChain->pNextRedline) ; // empty loop
     456             : 
     457             :         // insert as last element
     458           0 :         pInfoChain->pNextRedline = pInfo;
     459             :     }
     460             : }
     461             : 
     462           0 : Reference<XTextCursor> XMLRedlineImportHelper::CreateRedlineTextSection(
     463             :     Reference<XTextCursor> xOldCursor,
     464             :     const OUString& rId)
     465             : {
     466           0 :     Reference<XTextCursor> xReturn;
     467             : 
     468             :     // this method will modify the document directly -> lock SolarMutex
     469           0 :     SolarMutexGuard aGuard;
     470             : 
     471             :     // get RedlineInfo
     472           0 :     RedlineMapType::iterator aFind = aRedlineMap.find(rId);
     473           0 :     if (aRedlineMap.end() != aFind)
     474             :     {
     475             :         // get document from old cursor (via tunnel)
     476           0 :         SwDoc* pDoc = lcl_GetDocViaTunnel(xOldCursor);
     477             : 
     478           0 :         if (!pDoc)
     479             :         {
     480             :             OSL_TRACE("XMLRedlineImportHelper::CreateRedlineTextSection: "
     481             :                 "no SwDoc => cannot create section.");
     482           0 :             return 0;
     483             :         }
     484             : 
     485             :         // create text section for redline
     486             :         SwTxtFmtColl *pColl = pDoc->GetTxtCollFromPool
     487           0 :             (RES_POOLCOLL_STANDARD, false );
     488           0 :         SwStartNode* pRedlineNode = pDoc->GetNodes().MakeTextSection(
     489           0 :             pDoc->GetNodes().GetEndOfRedlines(),
     490             :             SwNormalStartNode,
     491           0 :             pColl);
     492             : 
     493             :         // remember node-index in RedlineInfo
     494           0 :         SwNodeIndex aIndex(*pRedlineNode);
     495           0 :         aFind->second->pContentIndex = new SwNodeIndex(aIndex);
     496             : 
     497             :         // create XText for document
     498           0 :         SwXText* pXText = new SwXRedlineText(pDoc, aIndex);
     499           0 :         Reference<XText> xText = pXText;  // keep Reference until end of method
     500             : 
     501             :         // create (UNO-) cursor
     502           0 :         SwPosition aPos(*pRedlineNode);
     503             :         SwXTextCursor *const pXCursor =
     504           0 :             new SwXTextCursor(*pDoc, pXText, CURSOR_REDLINE, aPos);
     505           0 :         pXCursor->GetCursor()->Move(fnMoveForward, fnGoNode);
     506             :         // cast to avoid ambiguity
     507           0 :         xReturn = static_cast<text::XWordCursor*>(pXCursor);
     508             :     }
     509             :     // else: unknown redline -> Ignore
     510             : 
     511           0 :     return xReturn;
     512             : }
     513             : 
     514           0 : void XMLRedlineImportHelper::SetCursor(
     515             :     const OUString& rId,
     516             :     sal_Bool bStart,
     517             :     Reference<XTextRange> & rRange,
     518             :     sal_Bool bIsOutsideOfParagraph)
     519             : {
     520           0 :     RedlineMapType::iterator aFind = aRedlineMap.find(rId);
     521           0 :     if (aRedlineMap.end() != aFind)
     522             :     {
     523             :         // RedlineInfo found; now set Cursor
     524           0 :         RedlineInfo* pInfo = aFind->second;
     525           0 :         if (bIsOutsideOfParagraph)
     526             :         {
     527             :             // outside of paragraph: remember SwNodeIndex
     528           0 :             if (bStart)
     529             :             {
     530           0 :                 pInfo->aAnchorStart.SetAsNodeIndex(rRange);
     531             :             }
     532             :             else
     533             :             {
     534           0 :                 pInfo->aAnchorEnd.SetAsNodeIndex(rRange);
     535             :             }
     536             : 
     537             :             // also remember that we expect an adjustment for this redline
     538           0 :             pInfo->bNeedsAdjustment = sal_True;
     539             :         }
     540             :         else
     541             :         {
     542             :             // inside of a paragraph: use regular XTextRanges (bookmarks)
     543           0 :             if (bStart)
     544           0 :                 pInfo->aAnchorStart.Set(rRange);
     545             :             else
     546           0 :                 pInfo->aAnchorEnd.Set(rRange);
     547             :         }
     548             : 
     549             :         // if this Cursor was the last missing info, we insert the
     550             :         // node into the document
     551             :         // then we can remove the entry from the map and destroy the object
     552           0 :         if (IsReady(pInfo))
     553             :         {
     554           0 :             InsertIntoDocument(pInfo);
     555           0 :             aRedlineMap.erase(rId);
     556           0 :             delete pInfo;
     557             :         }
     558             :     }
     559             :     // else: unknown Id -> ignore
     560           0 : }
     561             : 
     562           0 : void XMLRedlineImportHelper::AdjustStartNodeCursor(
     563             :     const OUString& rId,        /// ID used in RedlineAdd() call
     564             :     sal_Bool /*bStart*/,
     565             :     Reference<XTextRange> & /*rRange*/)
     566             : {
     567             :     // this method will modify the document directly -> lock SolarMutex
     568           0 :     SolarMutexGuard aGuard;
     569             : 
     570             :     // start + end nodes are treated the same. For either it's
     571             :     // necessary that the target node already exists.
     572             : 
     573           0 :     RedlineMapType::iterator aFind = aRedlineMap.find(rId);
     574           0 :     if (aRedlineMap.end() != aFind)
     575             :     {
     576             :         // RedlineInfo found; now set Cursor
     577           0 :         RedlineInfo* pInfo = aFind->second;
     578             : 
     579           0 :         pInfo->bNeedsAdjustment = sal_False;
     580             : 
     581             :         // if now ready, insert into document
     582           0 :         if( IsReady(pInfo) )
     583             :         {
     584           0 :             InsertIntoDocument(pInfo);
     585           0 :             aRedlineMap.erase(rId);
     586           0 :             delete pInfo;
     587             :         }
     588           0 :     }
     589             :     // else: can't find redline -> ignore
     590           0 : }
     591             : 
     592             : 
     593           0 : inline sal_Bool XMLRedlineImportHelper::IsReady(RedlineInfo* pRedline)
     594             : {
     595             :     // we can insert a redline if we have start & end, and we don't
     596             :     // expect adjustments for either of these
     597           0 :     return ( pRedline->aAnchorEnd.IsValid() &&
     598           0 :              pRedline->aAnchorStart.IsValid() &&
     599           0 :              !pRedline->bNeedsAdjustment );
     600             : }
     601             : 
     602           0 : void XMLRedlineImportHelper::InsertIntoDocument(RedlineInfo* pRedlineInfo)
     603             : {
     604             :     OSL_ENSURE(NULL != pRedlineInfo, "need redline info");
     605             :     OSL_ENSURE(IsReady(pRedlineInfo), "redline info not complete yet!");
     606             : 
     607             :     // this method will modify the document directly -> lock SolarMutex
     608           0 :     SolarMutexGuard aGuard;
     609             : 
     610             :     // Insert the Redline as described by pRedlineInfo into the
     611             :     // document.  If we are in insert mode, don't insert any redlines
     612             :     // (and delete 'deleted' inline redlines)
     613             : 
     614             :     // get the document (from one of the positions)
     615           0 :     SwDoc* pDoc = pRedlineInfo->aAnchorStart.GetDoc();
     616             : 
     617           0 :     if (!pDoc)
     618             :     {
     619             :         OSL_TRACE("XMLRedlineImportHelper::InsertIntoDocument: "
     620             :                 "no SwDoc => cannot insert redline.");
     621           0 :         return;
     622             :     }
     623             : 
     624             :     // now create the PaM for the redline
     625           0 :     SwPaM aPaM(pDoc->GetNodes().GetEndOfContent());
     626           0 :     pRedlineInfo->aAnchorStart.CopyPositionInto(*aPaM.GetPoint(), *pDoc);
     627           0 :     aPaM.SetMark();
     628           0 :     pRedlineInfo->aAnchorEnd.CopyPositionInto(*aPaM.GetPoint(), *pDoc);
     629             : 
     630             :     // collapse PaM if (start == end)
     631           0 :     if (*aPaM.GetPoint() == *aPaM.GetMark())
     632             :     {
     633           0 :         aPaM.DeleteMark();
     634             :     }
     635             : 
     636             : 
     637             :     // cover three cases:
     638             :     // 1) empty redlines (no range, no content)
     639             :     // 2) check for:
     640             :     //    a) bIgnoreRedline (e.g. insert mode)
     641             :     //    b) illegal PaM range (CheckNodesRange())
     642             :     // 3) normal case: insert redline
     643           0 :     if( !aPaM.HasMark() && (pRedlineInfo->pContentIndex == NULL) )
     644             :     {
     645             :         // these redlines have no function, and will thus be ignored (just as
     646             :         // in sw3io), so no action here
     647             :     }
     648           0 :     else if ( bIgnoreRedlines ||
     649           0 :          !CheckNodesRange( aPaM.GetPoint()->nNode,
     650           0 :                            aPaM.GetMark()->nNode,
     651           0 :                            sal_True ) )
     652             :     {
     653             :         // ignore redline (e.g. file loaded in insert mode):
     654             :         // delete 'deleted' redlines and forget about the whole thing
     655           0 :         if (nsRedlineType_t::REDLINE_DELETE == pRedlineInfo->eType)
     656             :         {
     657           0 :             pDoc->DeleteRange(aPaM);
     658             :             // And what about the "deleted nodes"?
     659             :             // They have to be deleted as well (#i80689)!
     660           0 :             if( bIgnoreRedlines && pRedlineInfo->pContentIndex != NULL )
     661             :             {
     662           0 :                 SwNodeIndex aIdx( *pRedlineInfo->pContentIndex );
     663           0 :                 const SwNode* pEnd = aIdx.GetNode().EndOfSectionNode();
     664           0 :                 if( pEnd )
     665             :                 {
     666           0 :                     SwNodeIndex aEnd( *pEnd, 1 );
     667           0 :                     SwPaM aDel( aIdx, aEnd );
     668           0 :                     pDoc->DeleteRange(aDel);
     669           0 :                 }
     670             :             }
     671             :         }
     672             :     }
     673             :     else
     674             :     {
     675             :         // regular file loading: insert redline
     676             : 
     677             :         // create redline (using pRedlineData which gets copied in SwRedline())
     678           0 :         SwRedlineData* pRedlineData = ConvertRedline(pRedlineInfo, pDoc);
     679             :         SwRedline* pRedline =
     680             :             new SwRedline( pRedlineData, *aPaM.GetPoint(), sal_True,
     681           0 :                            !pRedlineInfo->bMergeLastParagraph, sal_False );
     682             : 
     683             :         // set mark
     684           0 :         if( aPaM.HasMark() )
     685             :         {
     686           0 :             pRedline->SetMark();
     687           0 :             *(pRedline->GetMark()) = *aPaM.GetMark();
     688             :         }
     689             : 
     690             :         // set content node (if necessary)
     691           0 :         if (NULL != pRedlineInfo->pContentIndex)
     692             :         {
     693           0 :             sal_uLong nPoint = aPaM.GetPoint()->nNode.GetIndex();
     694           0 :             if( nPoint < pRedlineInfo->pContentIndex->GetIndex() ||
     695           0 :                 nPoint > pRedlineInfo->pContentIndex->GetNode().EndOfSectionIndex() )
     696           0 :                 pRedline->SetContentIdx(pRedlineInfo->pContentIndex);
     697             : #if OSL_DEBUG_LEVEL > 1
     698             :             else
     699             :                 OSL_FAIL( "Recursive change tracking" );
     700             : #endif
     701             :         }
     702             : 
     703             :         // set redline mode (without doing the associated book-keeping)
     704           0 :         pDoc->SetRedlineMode_intern(nsRedlineMode_t::REDLINE_ON);
     705           0 :         pDoc->AppendRedline(pRedline, false);
     706           0 :         pDoc->SetRedlineMode_intern(nsRedlineMode_t::REDLINE_NONE);
     707           0 :     }
     708             : }
     709             : 
     710           0 : SwRedlineData* XMLRedlineImportHelper::ConvertRedline(
     711             :     RedlineInfo* pRedlineInfo,
     712             :     SwDoc* pDoc)
     713             : {
     714             :     // convert info:
     715             :     // 1) Author String -> Author ID (default to zero)
     716             :     sal_uInt16 nAuthorId = (NULL == pDoc) ? 0 :
     717           0 :         pDoc->InsertRedlineAuthor( pRedlineInfo->sAuthor );
     718             : 
     719             :     // 2) util::DateTime -> DateTime
     720           0 :     DateTime aDT( DateTime::EMPTY );
     721           0 :     aDT.SetYear(    pRedlineInfo->aDateTime.Year );
     722           0 :     aDT.SetMonth(   pRedlineInfo->aDateTime.Month );
     723           0 :     aDT.SetDay(     pRedlineInfo->aDateTime.Day );
     724           0 :     aDT.SetHour(    pRedlineInfo->aDateTime.Hours );
     725           0 :     aDT.SetMin(     pRedlineInfo->aDateTime.Minutes );
     726           0 :     aDT.SetSec(     pRedlineInfo->aDateTime.Seconds );
     727           0 :     aDT.Set100Sec(  pRedlineInfo->aDateTime.HundredthSeconds );
     728             : 
     729             :     // 3) recursively convert next redline
     730             :     //    ( check presence and sanity of hierarchical redline info )
     731           0 :     SwRedlineData* pNext = NULL;
     732           0 :     if ( (NULL != pRedlineInfo->pNextRedline) &&
     733             :          (nsRedlineType_t::REDLINE_DELETE == pRedlineInfo->eType) &&
     734             :          (nsRedlineType_t::REDLINE_INSERT == pRedlineInfo->pNextRedline->eType) )
     735             :     {
     736           0 :         pNext = ConvertRedline(pRedlineInfo->pNextRedline, pDoc);
     737             :     }
     738             : 
     739             :     // create redline data
     740             :     SwRedlineData* pData = new SwRedlineData(pRedlineInfo->eType,
     741             :                                              nAuthorId, aDT,
     742             :                                              pRedlineInfo->sComment,
     743             :                                              pNext, // next data (if available)
     744           0 :                                              NULL); // no extra data
     745             : 
     746           0 :     return pData;
     747             : }
     748             : 
     749             : 
     750          18 : void XMLRedlineImportHelper::SetShowChanges( sal_Bool bShow )
     751             : {
     752          18 :     bShowChanges = bShow;
     753          18 : }
     754             : 
     755           0 : void XMLRedlineImportHelper::SetRecordChanges( sal_Bool bRecord )
     756             : {
     757           0 :     bRecordChanges = bRecord;
     758           0 : }
     759             : 
     760          17 : void XMLRedlineImportHelper::SetProtectionKey(
     761             :     const Sequence<sal_Int8> & rKey )
     762             : {
     763          17 :     aProtectionKey = rKey;
     764          17 : }
     765             : 
     766             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10