diff options
Diffstat (limited to 'sw/source/filter/xml/XMLRedlineImportHelper.cxx')
-rw-r--r-- | sw/source/filter/xml/XMLRedlineImportHelper.cxx | 779 |
1 files changed, 779 insertions, 0 deletions
diff --git a/sw/source/filter/xml/XMLRedlineImportHelper.cxx b/sw/source/filter/xml/XMLRedlineImportHelper.cxx new file mode 100644 index 000000000000..1a1f1ed4aa2b --- /dev/null +++ b/sw/source/filter/xml/XMLRedlineImportHelper.cxx @@ -0,0 +1,779 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + + +#include "XMLRedlineImportHelper.hxx" +#include <unotextcursor.hxx> +#include <unotextrange.hxx> +#include <unocrsr.hxx> +#include "doc.hxx" +#include <tools/datetime.hxx> +#include "poolfmt.hxx" +#include "unoredline.hxx" +#include <xmloff/xmltoken.hxx> +#include <com/sun/star/frame/XModel.hpp> + +// for locking SolarMutex: svapp + mutex +#include <vcl/svapp.hxx> +#include <osl/mutex.hxx> + + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::xmloff::token; + +using ::rtl::OUString; +using ::com::sun::star::frame::XModel; +using ::com::sun::star::text::XTextCursor; +using ::com::sun::star::text::XTextRange; +using ::com::sun::star::text::XText; +using ::com::sun::star::text::XWordCursor; +using ::com::sun::star::lang::XUnoTunnel; +using ::com::sun::star::beans::XPropertySet; +using ::com::sun::star::beans::XPropertySetInfo; +// collision with tools/DateTime: use UNO DateTime as util::DateTime +// using util::DateTime; + + +// +// a few helper functions +// + +SwDoc* lcl_GetDocViaTunnel( Reference<XTextCursor> & rCursor ) +{ + Reference<XUnoTunnel> xTunnel( rCursor, UNO_QUERY); + OSL_ENSURE(xTunnel.is(), "missing XUnoTunnel for XTextCursor"); + OTextCursorHelper *const pXCursor = + ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xTunnel); + OSL_ENSURE( pXCursor, "OTextCursorHelper missing" ); + return (pXCursor) ? pXCursor->GetDoc() : 0; +} + +SwDoc* lcl_GetDocViaTunnel( Reference<XTextRange> & rRange ) +{ + Reference<XUnoTunnel> xTunnel(rRange, UNO_QUERY); + OSL_ENSURE(xTunnel.is(), "missing XUnoTunnel for XTextRange"); + SwXTextRange *const pXRange = + ::sw::UnoTunnelGetImplementation<SwXTextRange>(xTunnel); + // #i115174#: this may be a SvxUnoTextRange +// OSL_ENSURE( pXRange, "SwXTextRange missing" ); + return (pXRange) ? pXRange->GetDoc() : 0; +} + + +// +// XTextRangeOrNodeIndexPosition: store a position into the text +// *either* as an XTextRange or as an SwNodeIndex. The reason is that +// we must store either pointers to StartNodes (because redlines may +// start on start nodes) or to a text position, and there appears to +// be no existing type that could do both. Things are complicated by +// the matter that (e.g in section import) we delete a few characters, +// which may cause bookmarks (as used by XTextRange) to be deleted. +// + +class XTextRangeOrNodeIndexPosition +{ + Reference<XTextRange> xRange; + SwNodeIndex* pIndex; /// pIndex will point to the *previous* node + +public: + XTextRangeOrNodeIndexPosition(); + ~XTextRangeOrNodeIndexPosition(); + + void Set( Reference<XTextRange> & rRange ); + void Set( SwNodeIndex& rIndex ); + void SetAsNodeIndex( Reference<XTextRange> & rRange ); + + void CopyPositionInto(SwPosition& rPos, SwDoc & rDoc); + SwDoc* GetDoc(); + + sal_Bool IsValid(); +}; + +XTextRangeOrNodeIndexPosition::XTextRangeOrNodeIndexPosition() : + xRange(NULL), + pIndex(NULL) +{ +} + +XTextRangeOrNodeIndexPosition::~XTextRangeOrNodeIndexPosition() +{ + delete pIndex; +} + +void XTextRangeOrNodeIndexPosition::Set( Reference<XTextRange> & rRange ) +{ + xRange = rRange->getStart(); // set bookmark + if (NULL != pIndex) + { + delete pIndex; + pIndex = NULL; + } +} + +void XTextRangeOrNodeIndexPosition::Set( SwNodeIndex& rIndex ) +{ + if (NULL != pIndex) + delete pIndex; + + pIndex = new SwNodeIndex(rIndex); + (*pIndex)-- ; // previous node!!! + xRange = NULL; +} + +void XTextRangeOrNodeIndexPosition::SetAsNodeIndex( + Reference<XTextRange> & rRange ) +{ + // XTextRange -> XTunnel -> SwXTextRange + SwDoc* pDoc = lcl_GetDocViaTunnel(rRange); + + if (!pDoc) + { + OSL_TRACE("SetAsNodeIndex: no SwDoc"); + return; + } + + // SwXTextRange -> PaM + SwUnoInternalPaM aPaM(*pDoc); +#if OSL_DEBUG_LEVEL > 0 + sal_Bool bSuccess = +#endif + ::sw::XTextRangeToSwPaM(aPaM, rRange); + OSL_ENSURE(bSuccess, "illegal range"); + + // PaM -> Index + Set(aPaM.GetPoint()->nNode); +} + +void +XTextRangeOrNodeIndexPosition::CopyPositionInto(SwPosition& rPos, SwDoc & rDoc) +{ + OSL_ENSURE(IsValid(), "Can't get Position"); + + // create PAM from start cursor (if no node index is present) + if (NULL == pIndex) + { + SwUnoInternalPaM aUnoPaM(rDoc); +#if OSL_DEBUG_LEVEL > 0 + sal_Bool bSuccess = +#endif + ::sw::XTextRangeToSwPaM(aUnoPaM, xRange); + OSL_ENSURE(bSuccess, "illegal range"); + + rPos = *aUnoPaM.GetPoint(); + } + else + { + rPos.nNode = *pIndex; + rPos.nNode++; // pIndex points to previous index !!! + rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), 0 ); + } +} + +SwDoc* XTextRangeOrNodeIndexPosition::GetDoc() +{ + OSL_ENSURE(IsValid(), "Can't get Doc"); + + return (NULL != pIndex) ? pIndex->GetNodes().GetDoc() : lcl_GetDocViaTunnel(xRange); +} + +sal_Bool XTextRangeOrNodeIndexPosition::IsValid() +{ + return ( xRange.is() || (pIndex != NULL) ); +} + + +// +// RedlineInfo: temporary storage for redline data +// + +class RedlineInfo +{ +public: + RedlineInfo(); + ~RedlineInfo(); + + /// redline type (insert, delete, ...) + RedlineType_t eType; + + // info fields: + OUString sAuthor; /// change author string + OUString sComment; /// change comment string + util::DateTime aDateTime; /// change DateTime + sal_Bool bMergeLastParagraph; /// the SwRedline::IsDelLastPara flag + + // each position can may be either empty, an XTextRange, or an SwNodeIndex + + // start pos of anchor (may be empty) + XTextRangeOrNodeIndexPosition aAnchorStart; + + // end pos of anchor (may be empty) + XTextRangeOrNodeIndexPosition aAnchorEnd; + + /// index of content node (maybe NULL) + SwNodeIndex* pContentIndex; + + /// next redline info (for hierarchical redlines) + RedlineInfo* pNextRedline; + + /// store whether we expect an adjustment for this redline + sal_Bool bNeedsAdjustment; +}; + +RedlineInfo::RedlineInfo() : + eType(nsRedlineType_t::REDLINE_INSERT), + sAuthor(), + sComment(), + aDateTime(), + bMergeLastParagraph( sal_False ), + aAnchorStart(), + aAnchorEnd(), + pContentIndex(NULL), + pNextRedline(NULL), + bNeedsAdjustment( sal_False ) +{ +} + +RedlineInfo::~RedlineInfo() +{ + delete pContentIndex; + delete pNextRedline; +} + + +// +// XMLRedlineImportHelper +// + +XMLRedlineImportHelper::XMLRedlineImportHelper( + sal_Bool bNoRedlinesPlease, + const Reference<XPropertySet> & rModel, + const Reference<XPropertySet> & rImportInfo ) : + sEmpty(), + sInsertion( GetXMLToken( XML_INSERTION )), + sDeletion( GetXMLToken( XML_DELETION )), + sFormatChange( GetXMLToken( XML_FORMAT_CHANGE )), + sShowChanges(RTL_CONSTASCII_USTRINGPARAM("ShowChanges")), + sRecordChanges(RTL_CONSTASCII_USTRINGPARAM("RecordChanges")), + sRedlineProtectionKey(RTL_CONSTASCII_USTRINGPARAM("RedlineProtectionKey")), + aRedlineMap(), + bIgnoreRedlines(bNoRedlinesPlease), + xModelPropertySet(rModel), + xImportInfoPropertySet(rImportInfo) +{ + // check to see if redline mode is handled outside of component + sal_Bool bHandleShowChanges = sal_True; + sal_Bool bHandleRecordChanges = sal_True; + sal_Bool bHandleProtectionKey = sal_True; + if ( xImportInfoPropertySet.is() ) + { + Reference<XPropertySetInfo> xInfo = + xImportInfoPropertySet->getPropertySetInfo(); + + bHandleShowChanges = ! xInfo->hasPropertyByName( sShowChanges ); + bHandleRecordChanges = ! xInfo->hasPropertyByName( sRecordChanges ); + bHandleProtectionKey = ! xInfo->hasPropertyByName( sRedlineProtectionKey ); + } + + // get redline mode + bShowChanges = *(sal_Bool*) + ( bHandleShowChanges ? xModelPropertySet : xImportInfoPropertySet ) + ->getPropertyValue( sShowChanges ).getValue(); + bRecordChanges = *(sal_Bool*) + ( bHandleRecordChanges ? xModelPropertySet : xImportInfoPropertySet ) + ->getPropertyValue( sRecordChanges ).getValue(); + { + Any aAny = (bHandleProtectionKey ? xModelPropertySet + : xImportInfoPropertySet ) + ->getPropertyValue( sRedlineProtectionKey ); + aAny >>= aProtectionKey; + } + + // set redline mode to "don't record changes" + if( bHandleRecordChanges ) + { + Any aAny; + sal_Bool bTmp = sal_False; + aAny.setValue( &bTmp, ::getBooleanCppuType() ); + xModelPropertySet->setPropertyValue( sRecordChanges, aAny ); + } +} + +XMLRedlineImportHelper::~XMLRedlineImportHelper() +{ + // delete all left over (and obviously incomplete) RedlineInfos (and map) + RedlineMapType::iterator aFind = aRedlineMap.begin(); + for( ; aRedlineMap.end() != aFind; aFind++ ) + { + RedlineInfo* pInfo = aFind->second; + + // left-over redlines. Insert them if possible (but assert), + // and delete the incomplete ones. Finally, delete it. + if( IsReady(pInfo) ) + { + OSL_FAIL("forgotten RedlineInfo; now inserted"); + InsertIntoDocument( pInfo ); + } + else + { + // try if only the adjustment was missing + pInfo->bNeedsAdjustment = sal_False; + if( IsReady(pInfo) ) + { + OSL_FAIL("RedlineInfo without adjustment; now inserted"); + InsertIntoDocument( pInfo ); + } + else + { + // this situation occurs if redlines aren't closed + // (i.e. end without start, or start without + // end). This may well be a problem in the file, + // rather than the code. + OSL_FAIL("incomplete redline (maybe file was corrupt); " + "now deleted"); + } + } + delete pInfo; + } + aRedlineMap.clear(); + + // set redline mode, either to info property set, or directly to + // the document + sal_Bool bHandleShowChanges = sal_True; + sal_Bool bHandleRecordChanges = sal_True; + sal_Bool bHandleProtectionKey = sal_True; + if ( xImportInfoPropertySet.is() ) + { + Reference<XPropertySetInfo> xInfo = + xImportInfoPropertySet->getPropertySetInfo(); + + bHandleShowChanges = ! xInfo->hasPropertyByName( sShowChanges ); + bHandleRecordChanges = ! xInfo->hasPropertyByName( sRecordChanges ); + bHandleProtectionKey = ! xInfo->hasPropertyByName( sRedlineProtectionKey ); + } + + // set redline mode & key + Any aAny; + + aAny.setValue( &bShowChanges, ::getBooleanCppuType() ); + if ( bHandleShowChanges ) + xModelPropertySet->setPropertyValue( sShowChanges, aAny ); + else + xImportInfoPropertySet->setPropertyValue( sShowChanges, aAny ); + + aAny.setValue( &bRecordChanges, ::getBooleanCppuType() ); + if ( bHandleRecordChanges ) + xModelPropertySet->setPropertyValue( sRecordChanges, aAny ); + else + xImportInfoPropertySet->setPropertyValue( sRecordChanges, aAny ); + + aAny <<= aProtectionKey; + if ( bHandleProtectionKey ) + xModelPropertySet->setPropertyValue( sRedlineProtectionKey, aAny ); + else + xImportInfoPropertySet->setPropertyValue( sRedlineProtectionKey, aAny); +} + +void XMLRedlineImportHelper::Add( + const OUString& rType, + const OUString& rId, + const OUString& rAuthor, + const OUString& rComment, + const util::DateTime& rDateTime, + sal_Bool bMergeLastPara) +{ + // we need to do the following: + // 1) parse type string + // 2) create RedlineInfo and fill it with data + // 3) check for existing redline with same ID + // 3a) insert redline into map + // 3b) attach to existing redline + + // ad 1) + RedlineType_t eType; + if (rType.equals(sInsertion)) + { + eType = nsRedlineType_t::REDLINE_INSERT; + } + else if (rType.equals(sDeletion)) + { + eType = nsRedlineType_t::REDLINE_DELETE; + } + else if (rType.equals(sFormatChange)) + { + eType = nsRedlineType_t::REDLINE_FORMAT; + } + else + { + // no proper type found: early out! + return; + } + + // ad 2) create a new RedlineInfo + RedlineInfo* pInfo = new RedlineInfo(); + + // fill entries + pInfo->eType = eType; + pInfo->sAuthor = rAuthor; + pInfo->sComment = rComment; + pInfo->aDateTime = rDateTime; + pInfo->bMergeLastParagraph = bMergeLastPara; + + + // ad 3) + if (aRedlineMap.end() == aRedlineMap.find(rId)) + { + // 3a) insert into map + aRedlineMap[rId] = pInfo; + } + else + { + // 3b) we already have a redline with this name: hierarchical redlines + // insert pInfo as last element in the chain. + // (hierarchy sanity checking happens on insertino into the document) + + // find last element + RedlineInfo* pInfoChain; + for( pInfoChain = aRedlineMap[rId]; + NULL != pInfoChain->pNextRedline; + pInfoChain = pInfoChain->pNextRedline) ; // empty loop + + // insert as last element + pInfoChain->pNextRedline = pInfo; + } +} + +Reference<XTextCursor> XMLRedlineImportHelper::CreateRedlineTextSection( + Reference<XTextCursor> xOldCursor, + const OUString& rId) +{ + Reference<XTextCursor> xReturn; + + // this method will modify the document directly -> lock SolarMutex + SolarMutexGuard aGuard; + + // get RedlineInfo + RedlineMapType::iterator aFind = aRedlineMap.find(rId); + if (aRedlineMap.end() != aFind) + { + // get document from old cursor (via tunnel) + SwDoc* pDoc = lcl_GetDocViaTunnel(xOldCursor); + + if (!pDoc) + { + OSL_TRACE("XMLRedlineImportHelper::CreateRedlineTextSection: " + "no SwDoc => cannot create section."); + return 0; + } + + // create text section for redline + SwTxtFmtColl *pColl = pDoc->GetTxtCollFromPool + (RES_POOLCOLL_STANDARD, false ); + SwStartNode* pRedlineNode = pDoc->GetNodes().MakeTextSection( + pDoc->GetNodes().GetEndOfRedlines(), + SwNormalStartNode, + pColl); + + // remember node-index in RedlineInfo + SwNodeIndex aIndex(*pRedlineNode); + aFind->second->pContentIndex = new SwNodeIndex(aIndex); + + // create XText for document + SwXText* pXText = new SwXRedlineText(pDoc, aIndex); + Reference<XText> xText = pXText; // keep Reference until end of method + + // create (UNO-) cursor + SwPosition aPos(*pRedlineNode); + SwXTextCursor *const pXCursor = + new SwXTextCursor(*pDoc, pXText, CURSOR_REDLINE, aPos); + pXCursor->GetCursor()->Move(fnMoveForward, fnGoNode); + // cast to avoid ambiguity + xReturn = static_cast<text::XWordCursor*>(pXCursor); + } + // else: unknown redline -> Ignore + + return xReturn; +} + +void XMLRedlineImportHelper::SetCursor( + const OUString& rId, + sal_Bool bStart, + Reference<XTextRange> & rRange, + sal_Bool bIsOutsideOfParagraph) +{ + RedlineMapType::iterator aFind = aRedlineMap.find(rId); + if (aRedlineMap.end() != aFind) + { + // RedlineInfo found; now set Cursor + RedlineInfo* pInfo = aFind->second; + if (bIsOutsideOfParagraph) + { + // outside of paragraph: remember SwNodeIndex + if (bStart) + { + pInfo->aAnchorStart.SetAsNodeIndex(rRange); + } + else + { + pInfo->aAnchorEnd.SetAsNodeIndex(rRange); + } + + // also remember that we expect an adjustment for this redline + pInfo->bNeedsAdjustment = sal_True; + } + else + { + // inside of a paragraph: use regular XTextRanges (bookmarks) + if (bStart) + pInfo->aAnchorStart.Set(rRange); + else + pInfo->aAnchorEnd.Set(rRange); + } + + // if this Cursor was the last missing info, we insert the + // node into the document + // then we can remove the entry from the map and destroy the object + if (IsReady(pInfo)) + { + InsertIntoDocument(pInfo); + aRedlineMap.erase(rId); + delete pInfo; + } + } + // else: unknown Id -> ignore +} + +void XMLRedlineImportHelper::AdjustStartNodeCursor( + const OUString& rId, /// ID used in RedlineAdd() call + sal_Bool /*bStart*/, + Reference<XTextRange> & /*rRange*/) +{ + // this method will modify the document directly -> lock SolarMutex + SolarMutexGuard aGuard; + + // start + end nodes are treated the same. For either it's + // necessary that the target node already exists. + + RedlineMapType::iterator aFind = aRedlineMap.find(rId); + if (aRedlineMap.end() != aFind) + { + // RedlineInfo found; now set Cursor + RedlineInfo* pInfo = aFind->second; + + pInfo->bNeedsAdjustment = sal_False; + + // if now ready, insert into document + if( IsReady(pInfo) ) + { + InsertIntoDocument(pInfo); + aRedlineMap.erase(rId); + delete pInfo; + } + } + // else: can't find redline -> ignore +} + + +inline sal_Bool XMLRedlineImportHelper::IsReady(RedlineInfo* pRedline) +{ + // we can insert a redline if we have start & end, and we don't + // expect adjustments for either of these + return ( pRedline->aAnchorEnd.IsValid() && + pRedline->aAnchorStart.IsValid() && + !pRedline->bNeedsAdjustment ); +} + +void XMLRedlineImportHelper::InsertIntoDocument(RedlineInfo* pRedlineInfo) +{ + OSL_ENSURE(NULL != pRedlineInfo, "need redline info"); + OSL_ENSURE(IsReady(pRedlineInfo), "redline info not complete yet!"); + + // this method will modify the document directly -> lock SolarMutex + SolarMutexGuard aGuard; + + // Insert the Redline as described by pRedlineInfo into the + // document. If we are in insert mode, don't insert any redlines + // (and delete 'deleted' inline redlines) + + // get the document (from one of the positions) + SwDoc* pDoc = pRedlineInfo->aAnchorStart.GetDoc(); + + if (!pDoc) + { + OSL_TRACE("XMLRedlineImportHelper::InsertIntoDocument: " + "no SwDoc => cannot insert redline."); + return; + } + + // now create the PaM for the redline + SwPaM aPaM(pDoc->GetNodes().GetEndOfContent()); + pRedlineInfo->aAnchorStart.CopyPositionInto(*aPaM.GetPoint(), *pDoc); + aPaM.SetMark(); + pRedlineInfo->aAnchorEnd.CopyPositionInto(*aPaM.GetPoint(), *pDoc); + + // collapse PaM if (start == end) + if (*aPaM.GetPoint() == *aPaM.GetMark()) + { + aPaM.DeleteMark(); + } + + + // cover three cases: + // 1) empty redlines (no range, no content) + // 2) check for: + // a) bIgnoreRedline (e.g. insert mode) + // b) illegal PaM range (CheckNodesRange()) + // 3) normal case: insert redline + if( !aPaM.HasMark() && (pRedlineInfo->pContentIndex == NULL) ) + { + // these redlines have no function, and will thus be ignored (just as + // in sw3io), so no action here + } + else if ( bIgnoreRedlines || + !CheckNodesRange( aPaM.GetPoint()->nNode, + aPaM.GetMark()->nNode, + sal_True ) ) + { + // ignore redline (e.g. file loaded in insert mode): + // delete 'deleted' redlines and forget about the whole thing + if (nsRedlineType_t::REDLINE_DELETE == pRedlineInfo->eType) + { + pDoc->DeleteRange(aPaM); + // And what about the "deleted nodes"? + // They have to be deleted as well (#i80689)! + if( bIgnoreRedlines && pRedlineInfo->pContentIndex != NULL ) + { + SwNodeIndex aIdx( *pRedlineInfo->pContentIndex ); + const SwNode* pEnd = aIdx.GetNode().EndOfSectionNode(); + if( pEnd ) + { + SwNodeIndex aEnd( *pEnd, 1 ); + SwPaM aDel( aIdx, aEnd ); + pDoc->DeleteRange(aDel); + } + } + } + } + else + { + // regular file loading: insert redline + + // create redline (using pRedlineData which gets copied in SwRedline()) + SwRedlineData* pRedlineData = ConvertRedline(pRedlineInfo, pDoc); + SwRedline* pRedline = + new SwRedline( pRedlineData, *aPaM.GetPoint(), sal_True, + !pRedlineInfo->bMergeLastParagraph, sal_False ); + + // set mark + if( aPaM.HasMark() ) + { + pRedline->SetMark(); + *(pRedline->GetMark()) = *aPaM.GetMark(); + } + + // set content node (if necessary) + if (NULL != pRedlineInfo->pContentIndex) + { + sal_uLong nPoint = aPaM.GetPoint()->nNode.GetIndex(); + if( nPoint < pRedlineInfo->pContentIndex->GetIndex() || + nPoint > pRedlineInfo->pContentIndex->GetNode().EndOfSectionIndex() ) + pRedline->SetContentIdx(pRedlineInfo->pContentIndex); +#if OSL_DEBUG_LEVEL > 1 + else + OSL_FAIL( "Recursive change tracking" ); +#endif + } + + // set redline mode (without doing the associated book-keeping) + pDoc->SetRedlineMode_intern(nsRedlineMode_t::REDLINE_ON); + pDoc->AppendRedline(pRedline, false); + pDoc->SetRedlineMode_intern(nsRedlineMode_t::REDLINE_NONE); + } +} + +SwRedlineData* XMLRedlineImportHelper::ConvertRedline( + RedlineInfo* pRedlineInfo, + SwDoc* pDoc) +{ + // convert info: + // 1) Author String -> Author ID (default to zero) + sal_uInt16 nAuthorId = (NULL == pDoc) ? 0 : + pDoc->InsertRedlineAuthor( pRedlineInfo->sAuthor ); + + // 2) util::DateTime -> DateTime + DateTime aDT; + aDT.SetYear( pRedlineInfo->aDateTime.Year ); + aDT.SetMonth( pRedlineInfo->aDateTime.Month ); + aDT.SetDay( pRedlineInfo->aDateTime.Day ); + aDT.SetHour( pRedlineInfo->aDateTime.Hours ); + aDT.SetMin( pRedlineInfo->aDateTime.Minutes ); + aDT.SetSec( pRedlineInfo->aDateTime.Seconds ); + aDT.Set100Sec( pRedlineInfo->aDateTime.HundredthSeconds ); + + // 3) recursively convert next redline + // ( check presence and sanity of hierarchical redline info ) + SwRedlineData* pNext = NULL; + if ( (NULL != pRedlineInfo->pNextRedline) && + (nsRedlineType_t::REDLINE_DELETE == pRedlineInfo->eType) && + (nsRedlineType_t::REDLINE_INSERT == pRedlineInfo->pNextRedline->eType) ) + { + pNext = ConvertRedline(pRedlineInfo->pNextRedline, pDoc); + } + + // create redline data + SwRedlineData* pData = new SwRedlineData(pRedlineInfo->eType, + nAuthorId, aDT, + pRedlineInfo->sComment, + pNext, // next data (if available) + NULL); // no extra data + + return pData; +} + + +void XMLRedlineImportHelper::SetShowChanges( sal_Bool bShow ) +{ + bShowChanges = bShow; +} + +void XMLRedlineImportHelper::SetRecordChanges( sal_Bool bRecord ) +{ + bRecordChanges = bRecord; +} + +void XMLRedlineImportHelper::SetProtectionKey( + const Sequence<sal_Int8> & rKey ) +{ + aProtectionKey = rKey; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |