xref: /AOO41X/main/sc/source/filter/xml/XMLChangeTrackingImportHelper.cxx (revision a9ab3c7b3d31474a75bf54404ada03e2f02464cb)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 #include "XMLChangeTrackingImportHelper.hxx"
27 #include "XMLConverter.hxx"
28 #include "cell.hxx"
29 #include "document.hxx"
30 #include "chgviset.hxx"
31 #include "rangeutl.hxx"
32 #include <tools/debug.hxx>
33 #include <tools/datetime.hxx>
34 #include <svl/zforlist.hxx>
35 #include <xmloff/xmluconv.hxx>
36 
37 #define SC_CHANGE_ID_PREFIX "ct"
38 
ScMyCellInfo()39 ScMyCellInfo::ScMyCellInfo()
40     : pCell(NULL),
41     sFormulaAddress(),
42     sFormula(),
43     sInputString(),
44     fValue(0.0),
45     nMatrixCols(0),
46     nMatrixRows(0),
47     eGrammar( formula::FormulaGrammar::GRAM_STORAGE_DEFAULT),
48     nType(NUMBERFORMAT_ALL),
49     nMatrixFlag(MM_NONE)
50 {
51 }
52 
ScMyCellInfo(ScBaseCell * pTempCell,const rtl::OUString & rFormulaAddress,const rtl::OUString & rFormula,const formula::FormulaGrammar::Grammar eTempGrammar,const rtl::OUString & rInputString,const double & rValue,const sal_uInt16 nTempType,const sal_uInt8 nTempMatrixFlag,const sal_Int32 nTempMatrixCols,const sal_Int32 nTempMatrixRows)53 ScMyCellInfo::ScMyCellInfo(ScBaseCell* pTempCell, const rtl::OUString& rFormulaAddress, const rtl::OUString& rFormula,
54             const formula::FormulaGrammar::Grammar eTempGrammar, const rtl::OUString& rInputString,
55             const double& rValue, const sal_uInt16 nTempType, const sal_uInt8 nTempMatrixFlag, const sal_Int32 nTempMatrixCols,
56             const sal_Int32 nTempMatrixRows)
57     : pCell(pTempCell),
58     sFormulaAddress(rFormulaAddress),
59     sFormula(rFormula),
60     sInputString(rInputString),
61     fValue(rValue),
62     nMatrixCols(nTempMatrixCols),
63     nMatrixRows(nTempMatrixRows),
64     eGrammar( eTempGrammar),
65     nType(nTempType),
66     nMatrixFlag(nTempMatrixFlag)
67 {
68 }
69 
~ScMyCellInfo()70 ScMyCellInfo::~ScMyCellInfo()
71 {
72     if (pCell)
73         pCell->Delete();
74 }
75 
CreateCell(ScDocument * pDoc)76 ScBaseCell* ScMyCellInfo::CreateCell(ScDocument* pDoc)
77 {
78     if (pDoc)
79     {
80         if (!pCell && sFormula.getLength() && sFormulaAddress.getLength())
81         {
82             ScAddress aPos;
83             sal_Int32 nOffset(0);
84             ScRangeStringConverter::GetAddressFromString(aPos, sFormulaAddress, pDoc, ::formula::FormulaGrammar::CONV_OOO, nOffset);
85             pCell = new ScFormulaCell(pDoc, aPos, sFormula, eGrammar, nMatrixFlag);
86             static_cast<ScFormulaCell*>(pCell)->SetMatColsRows(static_cast<SCCOL>(nMatrixCols), static_cast<SCROW>(nMatrixRows));
87         }
88 
89         if ((nType == NUMBERFORMAT_DATE || nType == NUMBERFORMAT_TIME) && sInputString.Len() == 0)
90         {
91             sal_uInt32 nFormat(0);
92             if (nType == NUMBERFORMAT_DATE)
93                 nFormat = pDoc->GetFormatTable()->GetStandardFormat( NUMBERFORMAT_DATE, ScGlobal::eLnge );
94             else if (nType == NUMBERFORMAT_TIME)
95                 nFormat = pDoc->GetFormatTable()->GetStandardFormat( NUMBERFORMAT_TIME, ScGlobal::eLnge );
96             pDoc->GetFormatTable()->GetInputLineString(fValue, nFormat, sInputString);
97         }
98     }
99 
100     return pCell ? pCell->CloneWithoutNote( *pDoc ) : 0;
101 }
102 
ScMyDeleted()103 ScMyDeleted::ScMyDeleted()
104     : pCellInfo(NULL)
105 {
106 }
107 
~ScMyDeleted()108 ScMyDeleted::~ScMyDeleted()
109 {
110     if (pCellInfo)
111         delete pCellInfo;
112 }
113 
ScMyGenerated(ScMyCellInfo * pTempCellInfo,const ScBigRange & aTempBigRange)114 ScMyGenerated::ScMyGenerated(ScMyCellInfo* pTempCellInfo, const ScBigRange& aTempBigRange)
115     : aBigRange(aTempBigRange),
116     nID(0),
117     pCellInfo(pTempCellInfo)
118 {
119 }
120 
~ScMyGenerated()121 ScMyGenerated::~ScMyGenerated()
122 {
123     if (pCellInfo)
124         delete pCellInfo;
125 }
126 
ScMyBaseAction(const ScChangeActionType nTempActionType)127 ScMyBaseAction::ScMyBaseAction(const ScChangeActionType nTempActionType)
128     : aDependencies(),
129     aDeletedList(),
130     nActionNumber(0),
131     nRejectingNumber(0),
132     nPreviousAction(0),
133     nActionType(nTempActionType),
134     nActionState(SC_CAS_VIRGIN)
135 {
136 }
137 
~ScMyBaseAction()138 ScMyBaseAction::~ScMyBaseAction()
139 {
140 }
141 
ScMyInsAction(const ScChangeActionType nActionTypeP)142 ScMyInsAction::ScMyInsAction(const ScChangeActionType nActionTypeP)
143     : ScMyBaseAction(nActionTypeP)
144 {
145 }
146 
~ScMyInsAction()147 ScMyInsAction::~ScMyInsAction()
148 {
149 }
150 
ScMyDelAction(const ScChangeActionType nActionTypeP)151 ScMyDelAction::ScMyDelAction(const ScChangeActionType nActionTypeP)
152     : ScMyBaseAction(nActionTypeP),
153     aGeneratedList(),
154     pInsCutOff(NULL),
155     aMoveCutOffs(),
156     nD(0)
157 {
158 }
159 
~ScMyDelAction()160 ScMyDelAction::~ScMyDelAction()
161 {
162     if (pInsCutOff)
163         delete pInsCutOff;
164 }
165 
ScMyMoveAction()166 ScMyMoveAction::ScMyMoveAction()
167     : ScMyBaseAction(SC_CAT_MOVE),
168     aGeneratedList(),
169     pMoveRanges(NULL)
170 {
171 }
172 
~ScMyMoveAction()173 ScMyMoveAction::~ScMyMoveAction()
174 {
175     if (pMoveRanges)
176         delete pMoveRanges;
177 }
178 
179 
ScMyContentAction()180 ScMyContentAction::ScMyContentAction()
181     : ScMyBaseAction(SC_CAT_CONTENT),
182     pCellInfo(NULL)
183 {
184 }
185 
~ScMyContentAction()186 ScMyContentAction::~ScMyContentAction()
187 {
188     if (pCellInfo)
189         delete pCellInfo;
190 }
191 
ScMyRejAction()192 ScMyRejAction::ScMyRejAction()
193     : ScMyBaseAction(SC_CAT_REJECT)
194 {
195 }
196 
~ScMyRejAction()197 ScMyRejAction::~ScMyRejAction()
198 {
199 }
200 
ScXMLChangeTrackingImportHelper()201 ScXMLChangeTrackingImportHelper::ScXMLChangeTrackingImportHelper()
202     : aUsers(),
203     aActions(),
204     pDoc(NULL),
205     pTrack(NULL),
206     pCurrentAction(NULL),
207     sIDPrefix(RTL_CONSTASCII_USTRINGPARAM(SC_CHANGE_ID_PREFIX)),
208     nMultiSpanned(0),
209     nMultiSpannedSlaveCount(0),
210     bChangeTrack(sal_False)
211 {
212     nPrefixLength = sIDPrefix.getLength();
213 }
214 
~ScXMLChangeTrackingImportHelper()215 ScXMLChangeTrackingImportHelper::~ScXMLChangeTrackingImportHelper()
216 {
217 }
218 
StartChangeAction(const ScChangeActionType nActionType)219 void ScXMLChangeTrackingImportHelper::StartChangeAction(const ScChangeActionType nActionType)
220 {
221     DBG_ASSERT(!pCurrentAction, "a not inserted action");
222     switch (nActionType)
223     {
224         case SC_CAT_INSERT_COLS:
225         case SC_CAT_INSERT_ROWS:
226         case SC_CAT_INSERT_TABS:
227         {
228             pCurrentAction = new ScMyInsAction(nActionType);
229         }
230         break;
231         case SC_CAT_DELETE_COLS:
232         case SC_CAT_DELETE_ROWS:
233         case SC_CAT_DELETE_TABS:
234         {
235             pCurrentAction = new ScMyDelAction(nActionType);
236         }
237         break;
238         case SC_CAT_MOVE:
239         {
240             pCurrentAction = new ScMyMoveAction();
241         }
242         break;
243         case SC_CAT_CONTENT:
244         {
245             pCurrentAction = new ScMyContentAction();
246         }
247         break;
248         case SC_CAT_REJECT:
249         {
250             pCurrentAction = new ScMyRejAction();
251         }
252         break;
253         default:
254         {
255             // added to avoid warnings
256         }
257     }
258 }
259 
GetIDFromString(const rtl::OUString & sID)260 sal_uInt32 ScXMLChangeTrackingImportHelper::GetIDFromString(const rtl::OUString& sID)
261 {
262     sal_uInt32 nResult(0);
263     sal_uInt32 nLength(sID.getLength());
264     if (nLength)
265     {
266         if (sID.compareTo(sIDPrefix, nPrefixLength) == 0)
267         {
268             rtl::OUString sValue(sID.copy(nPrefixLength, nLength - nPrefixLength));
269             sal_Int32 nValue;
270             SvXMLUnitConverter::convertNumber(nValue, sValue);
271             DBG_ASSERT(nValue > 0, "wrong change action ID");
272             nResult = nValue;
273         }
274         else
275         {
276             DBG_ERROR("wrong change action ID");
277         }
278     }
279     return nResult;
280 }
281 
SetActionInfo(const ScMyActionInfo & aInfo)282 void ScXMLChangeTrackingImportHelper::SetActionInfo(const ScMyActionInfo& aInfo)
283 {
284     pCurrentAction->aInfo = aInfo;
285     String aUser(aInfo.sUser);
286     StrData* pStrData = new StrData( aUser );
287     if ( !aUsers.Insert( pStrData ) )
288         delete pStrData;
289 }
290 
SetPreviousChange(const sal_uInt32 nPreviousAction,ScMyCellInfo * pCellInfo)291 void ScXMLChangeTrackingImportHelper::SetPreviousChange(const sal_uInt32 nPreviousAction,
292                             ScMyCellInfo* pCellInfo)
293 {
294     DBG_ASSERT(pCurrentAction->nActionType == SC_CAT_CONTENT, "wrong action type");
295     ScMyContentAction* pAction = static_cast<ScMyContentAction*>(pCurrentAction);
296     pAction->nPreviousAction = nPreviousAction;
297     pAction->pCellInfo = pCellInfo;
298 }
299 
SetPosition(const sal_Int32 nPosition,const sal_Int32 nCount,const sal_Int32 nTable)300 void ScXMLChangeTrackingImportHelper::SetPosition(const sal_Int32 nPosition, const sal_Int32 nCount, const sal_Int32 nTable)
301 {
302     DBG_ASSERT(((pCurrentAction->nActionType != SC_CAT_MOVE) &&
303                 (pCurrentAction->nActionType != SC_CAT_CONTENT) &&
304                 (pCurrentAction->nActionType != SC_CAT_REJECT)), "wrong action type");
305     DBG_ASSERT(nCount > 0, "wrong count");
306     switch(pCurrentAction->nActionType)
307     {
308         case SC_CAT_INSERT_COLS:
309         case SC_CAT_DELETE_COLS:
310         {
311             pCurrentAction->aBigRange.Set(nPosition, nInt32Min, nTable,
312                                         nPosition + nCount - 1, nInt32Max, nTable);
313         }
314         break;
315         case SC_CAT_INSERT_ROWS:
316         case SC_CAT_DELETE_ROWS:
317         {
318             pCurrentAction->aBigRange.Set(nInt32Min, nPosition, nTable,
319                                         nInt32Max, nPosition + nCount - 1, nTable);
320         }
321         break;
322         case SC_CAT_INSERT_TABS:
323         case SC_CAT_DELETE_TABS:
324         {
325             pCurrentAction->aBigRange.Set(nInt32Min, nInt32Min, nPosition,
326                                         nInt32Max, nInt32Max, nPosition + nCount - 1);
327         }
328         break;
329         default:
330         {
331             // added to avoid warnings
332         }
333     }
334 }
335 
AddDeleted(const sal_uInt32 nID)336 void ScXMLChangeTrackingImportHelper::AddDeleted(const sal_uInt32 nID)
337 {
338     ScMyDeleted* pDeleted = new ScMyDeleted();
339     pDeleted->nID = nID;
340     pCurrentAction->aDeletedList.push_front(pDeleted);
341 }
342 
AddDeleted(const sal_uInt32 nID,ScMyCellInfo * pCellInfo)343 void ScXMLChangeTrackingImportHelper::AddDeleted(const sal_uInt32 nID, ScMyCellInfo* pCellInfo)
344 {
345     ScMyDeleted* pDeleted = new ScMyDeleted();
346     pDeleted->nID = nID;
347     pDeleted->pCellInfo = pCellInfo;
348     pCurrentAction->aDeletedList.push_front(pDeleted);
349 }
350 
SetMultiSpanned(const sal_Int16 nTempMultiSpanned)351 void ScXMLChangeTrackingImportHelper::SetMultiSpanned(const sal_Int16 nTempMultiSpanned)
352 {
353     if (nTempMultiSpanned)
354     {
355         DBG_ASSERT(((pCurrentAction->nActionType == SC_CAT_DELETE_COLS) ||
356                     (pCurrentAction->nActionType == SC_CAT_DELETE_ROWS)), "wrong action type");
357         nMultiSpanned = nTempMultiSpanned;
358         nMultiSpannedSlaveCount = 0;
359     }
360 }
361 
SetInsertionCutOff(const sal_uInt32 nID,const sal_Int32 nPosition)362 void ScXMLChangeTrackingImportHelper::SetInsertionCutOff(const sal_uInt32 nID, const sal_Int32 nPosition)
363 {
364     if ((pCurrentAction->nActionType == SC_CAT_DELETE_COLS) ||
365         (pCurrentAction->nActionType == SC_CAT_DELETE_ROWS))
366     {
367         static_cast<ScMyDelAction*>(pCurrentAction)->pInsCutOff = new ScMyInsertionCutOff(nID, nPosition);
368     }
369     else
370     {
371         DBG_ERROR("wrong action type");
372     }
373 }
374 
AddMoveCutOff(const sal_uInt32 nID,const sal_Int32 nStartPosition,const sal_Int32 nEndPosition)375 void ScXMLChangeTrackingImportHelper::AddMoveCutOff(const sal_uInt32 nID, const sal_Int32 nStartPosition, const sal_Int32 nEndPosition)
376 {
377     if ((pCurrentAction->nActionType == SC_CAT_DELETE_COLS) ||
378         (pCurrentAction->nActionType == SC_CAT_DELETE_ROWS))
379     {
380         static_cast<ScMyDelAction*>(pCurrentAction)->aMoveCutOffs.push_front(ScMyMoveCutOff(nID, nStartPosition, nEndPosition));
381     }
382     else
383     {
384         DBG_ERROR("wrong action type");
385     }
386 }
387 
SetMoveRanges(const ScBigRange & aSourceRange,const ScBigRange & aTargetRange)388 void ScXMLChangeTrackingImportHelper::SetMoveRanges(const ScBigRange& aSourceRange, const ScBigRange& aTargetRange)
389 {
390     if (pCurrentAction->nActionType == SC_CAT_MOVE)
391     {
392         static_cast<ScMyMoveAction*>(pCurrentAction)->pMoveRanges = new ScMyMoveRanges(aSourceRange, aTargetRange);
393     }
394     else
395     {
396         DBG_ERROR("wrong action type");
397     }
398 }
399 
GetMultiSpannedRange()400 void ScXMLChangeTrackingImportHelper::GetMultiSpannedRange()
401 {
402     if ((pCurrentAction->nActionType == SC_CAT_DELETE_COLS) ||
403         (pCurrentAction->nActionType == SC_CAT_DELETE_ROWS))
404     {
405         if (nMultiSpannedSlaveCount)
406         {
407             static_cast<ScMyDelAction*>(pCurrentAction)->nD = nMultiSpannedSlaveCount;
408         }
409         ++nMultiSpannedSlaveCount;
410         if (nMultiSpannedSlaveCount >= nMultiSpanned)
411         {
412             nMultiSpanned = 0;
413             nMultiSpannedSlaveCount = 0;
414         }
415     }
416     else
417     {
418         DBG_ERROR("wrong action type");
419     }
420 }
421 
AddGenerated(ScMyCellInfo * pCellInfo,const ScBigRange & aBigRange)422 void ScXMLChangeTrackingImportHelper::AddGenerated(ScMyCellInfo* pCellInfo, const ScBigRange& aBigRange)
423 {
424     ScMyGenerated* pGenerated = new ScMyGenerated(pCellInfo, aBigRange);
425     if (pCurrentAction->nActionType == SC_CAT_MOVE)
426     {
427         static_cast<ScMyMoveAction*>(pCurrentAction)->aGeneratedList.push_back(pGenerated);
428     }
429     else if ((pCurrentAction->nActionType == SC_CAT_DELETE_COLS) ||
430         (pCurrentAction->nActionType == SC_CAT_DELETE_ROWS))
431     {
432         static_cast<ScMyDelAction*>(pCurrentAction)->aGeneratedList.push_back(pGenerated);
433     }
434     else
435     {
436         DBG_ERROR("try to insert a generated action to a wrong action");
437     }
438 }
439 
EndChangeAction()440 void ScXMLChangeTrackingImportHelper::EndChangeAction()
441 {
442     if ((pCurrentAction->nActionType == SC_CAT_DELETE_COLS) ||
443         (pCurrentAction->nActionType == SC_CAT_DELETE_ROWS))
444         GetMultiSpannedRange();
445     if (pCurrentAction && pCurrentAction->nActionNumber > 0)
446         aActions.push_back(pCurrentAction);
447     else
448     {
449         DBG_ERROR("no current action");
450     }
451     pCurrentAction = NULL;
452 }
453 
ConvertInfo(const ScMyActionInfo & aInfo,String & rUser,DateTime & aDateTime)454 void ScXMLChangeTrackingImportHelper::ConvertInfo(const ScMyActionInfo& aInfo, String& rUser, DateTime& aDateTime)
455 {
456     Date aDate(aInfo.aDateTime.Day, aInfo.aDateTime.Month, aInfo.aDateTime.Year);
457     Time aTime(aInfo.aDateTime.Hours, aInfo.aDateTime.Minutes, aInfo.aDateTime.Seconds, aInfo.aDateTime.HundredthSeconds);
458     aDateTime.SetDate( aDate.GetDate() );
459     aDateTime.SetTime( aTime.GetTime() );
460 
461     // #97286# old files didn't store 100th seconds, enable again
462     if ( aInfo.aDateTime.HundredthSeconds )
463         pTrack->SetTime100thSeconds( sal_True );
464 
465     StrData aStrData( aInfo.sUser );
466     sal_uInt16 nPos;
467     if ( pTrack->GetUserCollection().Search( &aStrData, nPos ) )
468     {
469         const StrData* pUser = static_cast<const StrData*>( pTrack->GetUserCollection().At( nPos ) );
470         if ( pUser )
471             rUser = pUser->GetString();
472         else
473             rUser = aInfo.sUser;    // shouldn't happen
474     }
475     else
476         rUser = aInfo.sUser;    // shouldn't happen
477 }
478 
CreateInsertAction(ScMyInsAction * pAction)479 ScChangeAction* ScXMLChangeTrackingImportHelper::CreateInsertAction(ScMyInsAction* pAction)
480 {
481     DateTime aDateTime( Date(0), Time(0) );
482     String aUser;
483     ConvertInfo(pAction->aInfo, aUser, aDateTime);
484 
485     String sComment (pAction->aInfo.sComment);
486 
487     ScChangeAction* pNewAction = new ScChangeActionIns(pAction->nActionNumber, pAction->nActionState, pAction->nRejectingNumber,
488         pAction->aBigRange, aUser, aDateTime, sComment, pAction->nActionType);
489     return pNewAction;
490 }
491 
CreateDeleteAction(ScMyDelAction * pAction)492 ScChangeAction* ScXMLChangeTrackingImportHelper::CreateDeleteAction(ScMyDelAction* pAction)
493 {
494     DateTime aDateTime( Date(0), Time(0) );
495     String aUser;
496     ConvertInfo(pAction->aInfo, aUser, aDateTime);
497 
498     String sComment (pAction->aInfo.sComment);
499 
500     ScChangeAction* pNewAction = new ScChangeActionDel(pAction->nActionNumber, pAction->nActionState, pAction->nRejectingNumber,
501         pAction->aBigRange, aUser, aDateTime, sComment, pAction->nActionType, pAction->nD, pTrack);
502     return pNewAction;
503 }
504 
CreateMoveAction(ScMyMoveAction * pAction)505 ScChangeAction* ScXMLChangeTrackingImportHelper::CreateMoveAction(ScMyMoveAction* pAction)
506 {
507     DBG_ASSERT(pAction->pMoveRanges, "no move ranges");
508     if (pAction->pMoveRanges)
509     {
510         DateTime aDateTime( Date(0), Time(0) );
511         String aUser;
512         ConvertInfo(pAction->aInfo, aUser, aDateTime);
513 
514         String sComment (pAction->aInfo.sComment);
515 
516         ScChangeAction* pNewAction = new ScChangeActionMove(pAction->nActionNumber, pAction->nActionState, pAction->nRejectingNumber,
517             pAction->pMoveRanges->aTargetRange, aUser, aDateTime, sComment, pAction->pMoveRanges->aSourceRange , pTrack);
518         return pNewAction;
519     }
520     return NULL;
521 }
522 
CreateRejectionAction(ScMyRejAction * pAction)523 ScChangeAction* ScXMLChangeTrackingImportHelper::CreateRejectionAction(ScMyRejAction* pAction)
524 {
525     DateTime aDateTime( Date(0), Time(0) );
526     String aUser;
527     ConvertInfo(pAction->aInfo, aUser, aDateTime);
528 
529     String sComment (pAction->aInfo.sComment);
530 
531     ScChangeAction* pNewAction = new ScChangeActionReject(pAction->nActionNumber, pAction->nActionState, pAction->nRejectingNumber,
532         pAction->aBigRange, aUser, aDateTime, sComment);
533     return pNewAction;
534 }
535 
CreateContentAction(ScMyContentAction * pAction)536 ScChangeAction* ScXMLChangeTrackingImportHelper::CreateContentAction(ScMyContentAction* pAction)
537 {
538     ScBaseCell* pCell = NULL;
539     if (pAction->pCellInfo)
540          pCell = pAction->pCellInfo->CreateCell(pDoc);
541 
542     DateTime aDateTime( Date(0), Time(0) );
543     String aUser;
544     ConvertInfo(pAction->aInfo, aUser, aDateTime);
545 
546     String sComment (pAction->aInfo.sComment);
547 
548     ScChangeAction* pNewAction = new ScChangeActionContent(pAction->nActionNumber, pAction->nActionState, pAction->nRejectingNumber,
549         pAction->aBigRange, aUser, aDateTime, sComment, pCell, pDoc, pAction->pCellInfo->sInputString);
550     return pNewAction;
551 }
552 
CreateGeneratedActions(ScMyGeneratedList & rList)553 void ScXMLChangeTrackingImportHelper::CreateGeneratedActions(ScMyGeneratedList& rList)
554 {
555     if (!rList.empty())
556     {
557         ScMyGeneratedList::iterator aItr(rList.begin());
558         ScMyGeneratedList::iterator aEndItr(rList.end());
559         while (aItr != aEndItr)
560         {
561             if( (*aItr)->nID == 0)
562             {
563                 ScBaseCell* pCell = NULL;
564                 if ((*aItr)->pCellInfo)
565                     pCell = (*aItr)->pCellInfo->CreateCell(pDoc);
566 
567                 if (pCell)
568                 {
569                     (*aItr)->nID = pTrack->AddLoadedGenerated(pCell, (*aItr)->aBigRange, (*aItr)->pCellInfo->sInputString );
570                     DBG_ASSERT((*aItr)->nID, "could not insert generated action");
571                 }
572             }
573             ++aItr;
574         }
575     }
576 }
577 
SetDeletionDependencies(ScMyDelAction * pAction,ScChangeActionDel * pDelAct)578 void ScXMLChangeTrackingImportHelper::SetDeletionDependencies(ScMyDelAction* pAction, ScChangeActionDel* pDelAct)
579 {
580     if (!pAction->aGeneratedList.empty())
581     {
582         DBG_ASSERT(((pAction->nActionType == SC_CAT_DELETE_COLS) ||
583             (pAction->nActionType == SC_CAT_DELETE_ROWS) ||
584             (pAction->nActionType == SC_CAT_DELETE_TABS)), "wrong action type");
585         if (pDelAct)
586         {
587             ScMyGeneratedList::iterator aItr(pAction->aGeneratedList.begin());
588             ScMyGeneratedList::iterator aEndItr(pAction->aGeneratedList.end());
589             while (aItr != aEndItr)
590             {
591                 DBG_ASSERT((*aItr)->nID, "a not inserted generated action");
592                 pDelAct->SetDeletedInThis((*aItr)->nID, pTrack);
593                 if (*aItr)
594                     delete *aItr;
595                 aItr = pAction->aGeneratedList.erase(aItr);
596             }
597         }
598     }
599     if (pAction->pInsCutOff)
600     {
601         DBG_ASSERT(((pAction->nActionType == SC_CAT_DELETE_COLS) ||
602             (pAction->nActionType == SC_CAT_DELETE_ROWS) ||
603             (pAction->nActionType == SC_CAT_DELETE_TABS)), "wrong action type");
604         ScChangeAction* pChangeAction = pTrack->GetAction(pAction->pInsCutOff->nID);
605         if (pChangeAction && pChangeAction->IsInsertType())
606         {
607             ScChangeActionIns* pInsAction = static_cast<ScChangeActionIns*>(pChangeAction);
608             if (pInsAction && pDelAct)
609                 pDelAct->SetCutOffInsert(pInsAction, static_cast<sal_Int16>(pAction->pInsCutOff->nPosition));
610         }
611         else
612         {
613             DBG_ERROR("no cut off insert action");
614         }
615     }
616     if (!pAction->aMoveCutOffs.empty())
617     {
618         DBG_ASSERT(((pAction->nActionType == SC_CAT_DELETE_COLS) ||
619             (pAction->nActionType == SC_CAT_DELETE_ROWS) ||
620             (pAction->nActionType == SC_CAT_DELETE_TABS)), "wrong action type");
621         ScMyMoveCutOffs::iterator aItr(pAction->aMoveCutOffs.begin());
622         ScMyMoveCutOffs::iterator aEndItr(pAction->aMoveCutOffs.end());
623         while(aItr != aEndItr)
624         {
625             ScChangeAction* pChangeAction = pTrack->GetAction(aItr->nID);
626             if (pChangeAction && (pChangeAction->GetType() == SC_CAT_MOVE))
627             {
628                 ScChangeActionMove* pMoveAction = static_cast<ScChangeActionMove*>(pChangeAction);
629                 if (pMoveAction && pDelAct)
630                     pDelAct->AddCutOffMove(pMoveAction, static_cast<sal_Int16>(aItr->nStartPosition),
631                                         static_cast<sal_Int16>(aItr->nEndPosition));
632             }
633             else
634             {
635                 DBG_ERROR("no cut off move action");
636             }
637             aItr = pAction->aMoveCutOffs.erase(aItr);
638         }
639     }
640 }
641 
SetMovementDependencies(ScMyMoveAction * pAction,ScChangeActionMove * pMoveAct)642 void ScXMLChangeTrackingImportHelper::SetMovementDependencies(ScMyMoveAction* pAction, ScChangeActionMove* pMoveAct)
643 {
644     if (!pAction->aGeneratedList.empty())
645     {
646         if (pAction->nActionType == SC_CAT_MOVE)
647         {
648             if (pMoveAct)
649             {
650                 ScMyGeneratedList::iterator aItr(pAction->aGeneratedList.begin());
651                 ScMyGeneratedList::iterator aEndItr(pAction->aGeneratedList.end());
652                 while (aItr != aEndItr)
653                 {
654                     DBG_ASSERT((*aItr)->nID, "a not inserted generated action");
655                     pMoveAct->SetDeletedInThis((*aItr)->nID, pTrack);
656                     if (*aItr)
657                         delete *aItr;
658                     aItr = pAction->aGeneratedList.erase(aItr);
659                 }
660             }
661         }
662     }
663 }
664 
SetContentDependencies(ScMyContentAction * pAction,ScChangeActionContent * pActContent)665 void ScXMLChangeTrackingImportHelper::SetContentDependencies(ScMyContentAction* pAction, ScChangeActionContent* pActContent)
666 {
667     if (pAction->nPreviousAction)
668     {
669         DBG_ASSERT(pAction->nActionType == SC_CAT_CONTENT, "wrong action type");
670         ScChangeAction* pPrevAct = pTrack->GetAction(pAction->nPreviousAction);
671         if (pPrevAct)
672         {
673             ScChangeActionContent* pPrevActContent = static_cast<ScChangeActionContent*>(pPrevAct);
674             if (pPrevActContent && pActContent)
675             {
676                 pActContent->SetPrevContent(pPrevActContent);
677                 pPrevActContent->SetNextContent(pActContent);
678                 const ScBaseCell* pOldCell = pActContent->GetOldCell();
679                 if (pOldCell)
680                 {
681                     ScBaseCell* pNewCell = pOldCell->CloneWithoutNote( *pDoc );
682                     if (pNewCell)
683                     {
684                         pPrevActContent->SetNewCell(pNewCell, pDoc, EMPTY_STRING);
685                         pPrevActContent->SetNewValue(pActContent->GetOldCell(), pDoc);
686                     }
687                 }
688             }
689         }
690     }
691 }
692 
SetDependencies(ScMyBaseAction * pAction)693 void ScXMLChangeTrackingImportHelper::SetDependencies(ScMyBaseAction* pAction)
694 {
695     ScChangeAction* pAct = pTrack->GetAction(pAction->nActionNumber);
696     if (pAct)
697     {
698         if (!pAction->aDependencies.empty())
699         {
700             ScMyDependencies::iterator aItr(pAction->aDependencies.begin());
701             ScMyDependencies::iterator aEndItr(pAction->aDependencies.end());
702             while(aItr != aEndItr)
703             {
704                 pAct->AddDependent(*aItr, pTrack);
705                 aItr = pAction->aDependencies.erase(aItr);
706             }
707         }
708         if (!pAction->aDeletedList.empty())
709         {
710             ScMyDeletedList::iterator aItr(pAction->aDeletedList.begin());
711             ScMyDeletedList::iterator aEndItr(pAction->aDeletedList.end());
712             while(aItr != aEndItr)
713             {
714                 pAct->SetDeletedInThis((*aItr)->nID, pTrack);
715                 ScChangeAction* pDeletedAct = pTrack->GetAction((*aItr)->nID);
716                 if ((pDeletedAct->GetType() == SC_CAT_CONTENT) && (*aItr)->pCellInfo)
717                 {
718                     ScChangeActionContent* pContentAct = static_cast<ScChangeActionContent*>(pDeletedAct);
719                     if (pContentAct && (*aItr)->pCellInfo)
720                     {
721                         ScBaseCell* pCell = (*aItr)->pCellInfo->CreateCell(pDoc);
722                         if (!ScBaseCell::CellEqual(pCell, pContentAct->GetNewCell()))
723                         {
724                             // #i40704# Don't overwrite SetNewCell result by calling SetNewValue,
725                             // instead pass the input string to SetNewCell.
726                             pContentAct->SetNewCell(pCell, pDoc, (*aItr)->pCellInfo->sInputString);
727                         }
728                     }
729                 }
730                 if (*aItr)
731                     delete *aItr;
732                 aItr = pAction->aDeletedList.erase(aItr);
733             }
734         }
735         if ((pAction->nActionType == SC_CAT_DELETE_COLS) ||
736             (pAction->nActionType == SC_CAT_DELETE_ROWS))
737             SetDeletionDependencies(static_cast<ScMyDelAction*>(pAction), static_cast<ScChangeActionDel*>(pAct));
738         else if (pAction->nActionType == SC_CAT_MOVE)
739             SetMovementDependencies(static_cast<ScMyMoveAction*>(pAction), static_cast<ScChangeActionMove*>(pAct));
740         else if (pAction->nActionType == SC_CAT_CONTENT)
741             SetContentDependencies(static_cast<ScMyContentAction*>(pAction), static_cast<ScChangeActionContent*>(pAct));
742     }
743     else
744     {
745         DBG_ERROR("could not find the action");
746     }
747 }
748 
SetNewCell(ScMyContentAction * pAction)749 void ScXMLChangeTrackingImportHelper::SetNewCell(ScMyContentAction* pAction)
750 {
751     ScChangeAction* pChangeAction = pTrack->GetAction(pAction->nActionNumber);
752     if (pChangeAction)
753     {
754         ScChangeActionContent* pChangeActionContent = static_cast<ScChangeActionContent*>(pChangeAction);
755         if (pChangeActionContent)
756         {
757             if (pChangeActionContent->IsTopContent() && !pChangeActionContent->IsDeletedIn())
758             {
759                 sal_Int32 nCol, nRow, nTab, nCol2, nRow2, nTab2;
760                 pAction->aBigRange.GetVars(nCol, nRow, nTab, nCol2, nRow2, nTab2);
761                 if ((nCol >= 0) && (nCol <= MAXCOL) &&
762                     (nRow >= 0) && (nRow <= MAXROW) &&
763                     (nTab >= 0) && (nTab <= MAXTAB))
764                 {
765                     ScAddress aAddress (static_cast<SCCOL>(nCol),
766                                         static_cast<SCROW>(nRow),
767                                         static_cast<SCTAB>(nTab));
768                     ScBaseCell* pCell = pDoc->GetCell(aAddress);
769                     if (pCell)
770                     {
771                         ScBaseCell* pNewCell = NULL;
772                         if (pCell->GetCellType() != CELLTYPE_FORMULA)
773                             pNewCell = pCell->CloneWithoutNote( *pDoc );
774                         else
775                         {
776                             sal_uInt8 nMatrixFlag = static_cast<ScFormulaCell*>(pCell)->GetMatrixFlag();
777                             String sFormula;
778                             // With GRAM_ODFF reference detection is faster on compilation.
779                             /* FIXME: new cell should be created with a clone
780                              * of the token array instead. Any reason why this
781                              * wasn't done? */
782                             static_cast<ScFormulaCell*>(pCell)->GetFormula(sFormula,formula::FormulaGrammar::GRAM_ODFF);
783                             rtl::OUString sOUFormula(sFormula);
784 
785                             // #i87826# [Collaboration] Rejected move destroys formulas
786                             // FIXME: adjust ScFormulaCell::GetFormula(), so that the right formula string
787                             //        is returned and no further string handling is necessary
788                             rtl::OUString sOUFormula2;
789                             if ( nMatrixFlag != MM_NONE )
790                             {
791                                 sOUFormula2 = sOUFormula.copy( 2, sOUFormula.getLength() - 3 );
792                             }
793                             else
794                             {
795                                 sOUFormula2 = sOUFormula.copy( 1, sOUFormula.getLength() - 1 );
796                             }
797 
798                             String sFormula2(sOUFormula2);
799                             pNewCell = new ScFormulaCell(pDoc, aAddress, sFormula2,formula::FormulaGrammar::GRAM_ODFF, nMatrixFlag);
800                             if (pNewCell)
801                             {
802                                 if (nMatrixFlag == MM_FORMULA)
803                                 {
804                                     SCCOL nCols;
805                                     SCROW nRows;
806                                     static_cast<ScFormulaCell*>(pCell)->GetMatColsRows(nCols, nRows);
807                                     static_cast<ScFormulaCell*>(pNewCell)->SetMatColsRows(nCols, nRows);
808                                 }
809                                 static_cast<ScFormulaCell*>(pNewCell)->SetInChangeTrack(sal_True);
810                             }
811                         }
812                         pChangeActionContent->SetNewCell(pNewCell, pDoc, EMPTY_STRING);
813                         // #i40704# don't overwrite the formula string from above with pCell's content
814                         if (pCell->GetCellType() != CELLTYPE_FORMULA)
815                             pChangeActionContent->SetNewValue(pCell, pDoc);
816                     }
817                 }
818                 else
819                 {
820                     DBG_ERROR("wrong cell position");
821                 }
822             }
823         }
824     }
825 }
826 
CreateChangeTrack(ScDocument * pTempDoc)827 void ScXMLChangeTrackingImportHelper::CreateChangeTrack(ScDocument* pTempDoc)
828 {
829     pDoc = pTempDoc;
830     if (pDoc)
831     {
832         pTrack = new ScChangeTrack(pDoc, aUsers);
833         // #97286# old files didn't store 100th seconds, disable until encountered
834         pTrack->SetTime100thSeconds( sal_False );
835 
836         ScMyActions::iterator aItr(aActions.begin());
837         ScMyActions::iterator aEndItr(aActions.end());
838         while (aItr != aEndItr)
839         {
840             ScChangeAction* pAction = NULL;
841 
842             switch ((*aItr)->nActionType)
843             {
844                 case SC_CAT_INSERT_COLS:
845                 case SC_CAT_INSERT_ROWS:
846                 case SC_CAT_INSERT_TABS:
847                 {
848                     pAction = CreateInsertAction(static_cast<ScMyInsAction*>(*aItr));
849                 }
850                 break;
851                 case SC_CAT_DELETE_COLS:
852                 case SC_CAT_DELETE_ROWS:
853                 case SC_CAT_DELETE_TABS:
854                 {
855                     ScMyDelAction* pDelAct = static_cast<ScMyDelAction*>(*aItr);
856                     pAction = CreateDeleteAction(pDelAct);
857                     CreateGeneratedActions(pDelAct->aGeneratedList);
858                 }
859                 break;
860                 case SC_CAT_MOVE:
861                 {
862                     ScMyMoveAction* pMovAct = static_cast<ScMyMoveAction*>(*aItr);
863                     pAction = CreateMoveAction(pMovAct);
864                     CreateGeneratedActions(pMovAct->aGeneratedList);
865                 }
866                 break;
867                 case SC_CAT_CONTENT:
868                 {
869                     pAction = CreateContentAction(static_cast<ScMyContentAction*>(*aItr));
870                 }
871                 break;
872                 case SC_CAT_REJECT:
873                 {
874                     pAction = CreateRejectionAction(static_cast<ScMyRejAction*>(*aItr));
875                 }
876                 break;
877                 default:
878                 {
879                     // added to avoid warnings
880                 }
881             }
882 
883             if (pAction)
884                 pTrack->AppendLoaded(pAction);
885             else
886             {
887                 DBG_ERROR("no action");
888             }
889 
890             ++aItr;
891         }
892         if (pTrack->GetLast())
893             pTrack->SetActionMax(pTrack->GetLast()->GetActionNumber());
894 
895         aItr = aActions.begin();
896         aEndItr = aActions.end();
897         while (aItr != aEndItr)
898         {
899             SetDependencies(*aItr);
900 
901             if ((*aItr)->nActionType == SC_CAT_CONTENT)
902                 ++aItr;
903             else
904             {
905                 if (*aItr)
906                     delete (*aItr);
907                 aItr = aActions.erase(aItr);
908             }
909         }
910 
911         aItr = aActions.begin();
912         aEndItr = aActions.end();
913         while (aItr != aEndItr)
914         {
915             DBG_ASSERT((*aItr)->nActionType == SC_CAT_CONTENT, "wrong action type");
916             SetNewCell(static_cast<ScMyContentAction*>(*aItr));
917             if (*aItr)
918                 delete (*aItr);
919             aItr = aActions.erase(aItr);
920         }
921         if (aProtect.getLength())
922             pTrack->SetProtection(aProtect);
923         else if (pDoc->GetChangeTrack() && pDoc->GetChangeTrack()->IsProtected())
924             pTrack->SetProtection(pDoc->GetChangeTrack()->GetProtection());
925 
926         if ( pTrack->GetLast() )
927             pTrack->SetLastSavedActionNumber(pTrack->GetLast()->GetActionNumber());
928 
929         pDoc->SetChangeTrack(pTrack);
930     }
931 }
932