Bump version to 4.3-4
[LibreOffice.git] / sc / source / ui / docshell / docsh3.cxx
blob1b1f9a6c1334c8b236e0d9ffc559eb07fee92475
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
21 #include <com/sun/star/document/XDocumentProperties.hpp>
23 #include "scitems.hxx"
24 #include "rangelst.hxx"
25 #include <editeng/flstitem.hxx>
26 #include <editeng/paperinf.hxx>
27 #include <editeng/sizeitem.hxx>
28 #include <rtl/strbuf.hxx>
29 #include <sfx2/viewfrm.hxx>
30 #include <sfx2/app.hxx>
31 #include <sfx2/docfile.hxx>
32 #include <sfx2/printer.hxx>
33 #include <svx/postattr.hxx>
34 #include <unotools/misccfg.hxx>
35 #include <vcl/virdev.hxx>
36 #include <vcl/msgbox.hxx>
38 #include "docsh.hxx"
39 #include "docshimp.hxx"
40 #include "scmod.hxx"
41 #include "tabvwsh.hxx"
42 #include "viewdata.hxx"
43 #include "docpool.hxx"
44 #include "stlpool.hxx"
45 #include "patattr.hxx"
46 #include "uiitems.hxx"
47 #include "hints.hxx"
48 #include "docoptio.hxx"
49 #include "viewopti.hxx"
50 #include "pntlock.hxx"
51 #include "chgtrack.hxx"
52 #include "docfunc.hxx"
53 #include "formulacell.hxx"
54 #include "chgviset.hxx"
55 #include "progress.hxx"
56 #include "redcom.hxx"
57 #include "sc.hrc"
58 #include "inputopt.hxx"
59 #include "drwlayer.hxx"
60 #include "inputhdl.hxx"
61 #include "conflictsdlg.hxx"
62 #include "globstr.hrc"
63 #include "markdata.hxx"
64 #include <boost/scoped_ptr.hpp>
66 // Redraw - Benachrichtigungen
68 void ScDocShell::PostEditView( ScEditEngineDefaulter* pEditEngine, const ScAddress& rCursorPos )
70 // Broadcast( ScEditViewHint( pEditEngine, rCursorPos ) );
72 // Test: nur aktive ViewShell
74 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
75 if (pViewSh && pViewSh->GetViewData()->GetDocShell() == this)
77 ScEditViewHint aHint( pEditEngine, rCursorPos );
78 pViewSh->Notify( *this, aHint );
82 void ScDocShell::PostDataChanged()
84 Broadcast( SfxSimpleHint( FID_DATACHANGED ) );
85 SFX_APP()->Broadcast(SfxSimpleHint( FID_ANYDATACHANGED )); // Navigator
86 aDocument.ClearFormulaContext();
87 //! Navigator direkt benachrichtigen!
90 void ScDocShell::PostPaint( SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab,
91 SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, sal_uInt16 nPart,
92 sal_uInt16 nExtFlags )
94 ScRange aRange(nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
95 PostPaint(aRange, nPart, nExtFlags);
98 void ScDocShell::PostPaint( const ScRangeList& rRanges, sal_uInt16 nPart, sal_uInt16 nExtFlags )
100 ScRangeList aPaintRanges;
101 for (size_t i = 0, n = rRanges.size(); i < n; ++i)
103 const ScRange& rRange = *rRanges[i];
104 SCCOL nCol1 = rRange.aStart.Col(), nCol2 = rRange.aEnd.Col();
105 SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row();
106 SCTAB nTab1 = rRange.aStart.Tab(), nTab2 = rRange.aEnd.Tab();
108 if (!ValidCol(nCol1)) nCol1 = MAXCOL;
109 if (!ValidRow(nRow1)) nRow1 = MAXROW;
110 if (!ValidCol(nCol2)) nCol2 = MAXCOL;
111 if (!ValidRow(nRow2)) nRow2 = MAXROW;
113 if ( pPaintLockData )
115 // #i54081# PAINT_EXTRAS still has to be broadcast because it changes the
116 // current sheet if it's invalid. All other flags added to pPaintLockData.
117 sal_uInt16 nLockPart = nPart & ~PAINT_EXTRAS;
118 if ( nLockPart )
120 //! nExtFlags ???
121 pPaintLockData->AddRange( ScRange( nCol1, nRow1, nTab1,
122 nCol2, nRow2, nTab2 ), nLockPart );
125 nPart &= PAINT_EXTRAS; // for broadcasting
126 if (!nPart)
127 continue;
131 if (nExtFlags & SC_PF_LINES) // Platz fuer Linien beruecksichtigen
133 //! Abfrage auf versteckte Spalten/Zeilen!
134 if (nCol1>0) --nCol1;
135 if (nCol2<MAXCOL) ++nCol2;
136 if (nRow1>0) --nRow1;
137 if (nRow2<MAXROW) ++nRow2;
140 // um zusammengefasste erweitern
141 if (nExtFlags & SC_PF_TESTMERGE)
142 aDocument.ExtendMerge( nCol1, nRow1, nCol2, nRow2, nTab1 );
144 if ( nCol1 != 0 || nCol2 != MAXCOL )
146 // Extend to whole rows if SC_PF_WHOLEROWS is set, or rotated or non-left
147 // aligned cells are contained (see UpdatePaintExt).
148 // Special handling for RTL text (#i9731#) is unnecessary now with full
149 // support of right-aligned text.
151 if ( ( nExtFlags & SC_PF_WHOLEROWS ) ||
152 aDocument.HasAttrib( nCol1,nRow1,nTab1,
153 MAXCOL,nRow2,nTab2, HASATTR_ROTATE | HASATTR_RIGHTORCENTER ) )
155 nCol1 = 0;
156 nCol2 = MAXCOL;
159 aPaintRanges.Append(ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2));
162 Broadcast(ScPaintHint(aPaintRanges.Combine(), nPart));
165 void ScDocShell::PostPaintGridAll()
167 PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID );
170 void ScDocShell::PostPaintCell( SCCOL nCol, SCROW nRow, SCTAB nTab )
172 PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PAINT_GRID, SC_PF_TESTMERGE );
175 void ScDocShell::PostPaintCell( const ScAddress& rPos )
177 PostPaintCell( rPos.Col(), rPos.Row(), rPos.Tab() );
180 void ScDocShell::PostPaintExtras()
182 PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS );
185 void ScDocShell::UpdatePaintExt( sal_uInt16& rExtFlags, const ScRange& rRange )
187 if ( ( rExtFlags & SC_PF_LINES ) == 0 && aDocument.HasAttrib( rRange, HASATTR_PAINTEXT ) )
189 // If the range contains lines, shadow or conditional formats,
190 // set SC_PF_LINES to include one extra cell in all directions.
192 rExtFlags |= SC_PF_LINES;
195 if ( ( rExtFlags & SC_PF_WHOLEROWS ) == 0 &&
196 ( rRange.aStart.Col() != 0 || rRange.aEnd.Col() != MAXCOL ) &&
197 aDocument.HasAttrib( rRange, HASATTR_ROTATE | HASATTR_RIGHTORCENTER ) )
199 // If the range contains (logically) right- or center-aligned cells,
200 // or rotated cells, set SC_PF_WHOLEROWS to paint the whole rows.
201 // This test isn't needed after the cell changes, because it's also
202 // tested in PostPaint. UpdatePaintExt may later be changed to do this
203 // only if called before the changes.
205 rExtFlags |= SC_PF_WHOLEROWS;
209 void ScDocShell::UpdatePaintExt( sal_uInt16& rExtFlags, SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab,
210 SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab )
212 UpdatePaintExt( rExtFlags, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ) );
215 void ScDocShell::LockPaint_Impl(bool bDoc)
217 if ( !pPaintLockData )
218 pPaintLockData = new ScPaintLockData;
219 pPaintLockData->IncLevel(bDoc);
222 void ScDocShell::UnlockPaint_Impl(bool bDoc)
224 if ( pPaintLockData )
226 if ( pPaintLockData->GetLevel(bDoc) )
227 pPaintLockData->DecLevel(bDoc);
228 if (!pPaintLockData->GetLevel(!bDoc) && !pPaintLockData->GetLevel(bDoc))
230 // Paint jetzt ausfuehren
232 ScPaintLockData* pPaint = pPaintLockData;
233 pPaintLockData = NULL; // nicht weitersammeln
235 ScRangeListRef xRangeList = pPaint->GetRangeList();
236 if (xRangeList)
238 sal_uInt16 nParts = pPaint->GetParts();
239 for ( size_t i = 0, nCount = xRangeList->size(); i < nCount; i++ )
241 //! nExtFlags ???
242 ScRange aRange = *(*xRangeList)[i];
243 PostPaint( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aStart.Tab(),
244 aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aEnd.Tab(),
245 nParts );
249 if ( pPaint->GetModified() )
250 SetDocumentModified();
252 delete pPaint;
255 else
257 OSL_FAIL("UnlockPaint ohne LockPaint");
261 void ScDocShell::LockDocument_Impl(sal_uInt16 nNew)
263 if (!nDocumentLock)
265 ScDrawLayer* pDrawLayer = aDocument.GetDrawLayer();
266 if (pDrawLayer)
267 pDrawLayer->setLock(true);
269 nDocumentLock = nNew;
272 void ScDocShell::UnlockDocument_Impl(sal_uInt16 nNew)
274 nDocumentLock = nNew;
275 if (!nDocumentLock)
277 ScDrawLayer* pDrawLayer = aDocument.GetDrawLayer();
278 if (pDrawLayer)
279 pDrawLayer->setLock(false);
283 sal_uInt16 ScDocShell::GetLockCount() const
285 return nDocumentLock;
288 void ScDocShell::SetLockCount(sal_uInt16 nNew)
290 if (nNew) // setzen
292 if ( !pPaintLockData )
293 pPaintLockData = new ScPaintLockData;
294 pPaintLockData->SetLevel(nNew-1, true);
295 LockDocument_Impl(nNew);
297 else if (pPaintLockData) // loeschen
299 pPaintLockData->SetLevel(0, true); // bei Unlock sofort ausfuehren
300 UnlockPaint_Impl(true); // jetzt
301 UnlockDocument_Impl(0);
305 void ScDocShell::LockPaint()
307 LockPaint_Impl(false);
310 void ScDocShell::UnlockPaint()
312 UnlockPaint_Impl(false);
315 void ScDocShell::LockDocument()
317 LockPaint_Impl(true);
318 LockDocument_Impl(nDocumentLock + 1);
321 void ScDocShell::UnlockDocument()
323 if (nDocumentLock)
325 UnlockPaint_Impl(true);
326 UnlockDocument_Impl(nDocumentLock - 1);
328 else
330 OSL_FAIL("UnlockDocument without LockDocument");
334 void ScDocShell::SetInplace( bool bInplace )
336 if (bIsInplace != bInplace)
338 bIsInplace = bInplace;
339 CalcOutputFactor();
343 void ScDocShell::CalcOutputFactor()
345 if (bIsInplace)
347 nPrtToScreenFactor = 1.0; // passt sonst nicht zur inaktiven Darstellung
348 return;
351 bool bTextWysiwyg = SC_MOD()->GetInputOptions().GetTextWysiwyg();
352 if (bTextWysiwyg)
354 nPrtToScreenFactor = 1.0;
355 return;
358 OUString aTestString(
359 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890123456789");
360 long nPrinterWidth = 0;
361 long nWindowWidth = 0;
362 const ScPatternAttr* pPattern = (const ScPatternAttr*)&aDocument.GetPool()->
363 GetDefaultItem(ATTR_PATTERN);
365 Font aDefFont;
366 OutputDevice* pRefDev = GetRefDevice();
367 MapMode aOldMode = pRefDev->GetMapMode();
368 Font aOldFont = pRefDev->GetFont();
370 pRefDev->SetMapMode(MAP_PIXEL);
371 pPattern->GetFont(aDefFont, SC_AUTOCOL_BLACK, pRefDev); // font color doesn't matter here
372 pRefDev->SetFont(aDefFont);
373 nPrinterWidth = pRefDev->PixelToLogic( Size( pRefDev->GetTextWidth(aTestString), 0 ), MAP_100TH_MM ).Width();
374 pRefDev->SetFont(aOldFont);
375 pRefDev->SetMapMode(aOldMode);
377 VirtualDevice aVirtWindow( *Application::GetDefaultDevice() );
378 aVirtWindow.SetMapMode(MAP_PIXEL);
379 pPattern->GetFont(aDefFont, SC_AUTOCOL_BLACK, &aVirtWindow); // font color doesn't matter here
380 aVirtWindow.SetFont(aDefFont);
381 nWindowWidth = aVirtWindow.GetTextWidth(aTestString);
382 nWindowWidth = (long) ( nWindowWidth / ScGlobal::nScreenPPTX * HMM_PER_TWIPS );
384 if (nPrinterWidth && nWindowWidth)
385 nPrtToScreenFactor = nPrinterWidth / (double) nWindowWidth;
386 else
388 OSL_FAIL("GetTextSize gibt 0 ??");
389 nPrtToScreenFactor = 1.0;
393 double ScDocShell::GetOutputFactor() const
395 return nPrtToScreenFactor;
398 void ScDocShell::InitOptions(bool bForLoading) // called from InitNew and Load
400 // Einstellungen aus dem SpellCheckCfg kommen in Doc- und ViewOptions
402 sal_uInt16 nDefLang, nCjkLang, nCtlLang;
403 bool bAutoSpell;
404 ScModule::GetSpellSettings( nDefLang, nCjkLang, nCtlLang, bAutoSpell );
405 ScModule* pScMod = SC_MOD();
407 ScDocOptions aDocOpt = pScMod->GetDocOptions();
408 ScFormulaOptions aFormulaOpt = pScMod->GetFormulaOptions();
409 ScViewOptions aViewOpt = pScMod->GetViewOptions();
410 aDocOpt.SetAutoSpell( bAutoSpell );
412 // zweistellige Jahreszahleneingabe aus Extras->Optionen->Allgemein->Sonstiges
413 aDocOpt.SetYear2000( sal::static_int_cast<sal_uInt16>( ::utl::MiscCfg().GetYear2000() ) );
415 if (bForLoading)
417 // #i112123# No style:decimal-places attribute means automatic decimals, not the configured default,
418 // so it must not be taken from the global options.
419 // Calculation settings are handled separately in ScXMLBodyContext::EndElement.
420 aDocOpt.SetStdPrecision( SvNumberFormatter::UNLIMITED_PRECISION );
422 // fdo#78294 The default null-date if
423 // <table:null-date table:date-value='...' />
424 // is absent is 1899-12-30 regardless what the configuration is set to.
425 // Import filters may override this value.
426 aDocOpt.SetDate( 30, 12, 1899);
429 aDocument.SetDocOptions( aDocOpt );
430 aDocument.SetViewOptions( aViewOpt );
431 SetFormulaOptions( aFormulaOpt, bForLoading );
433 // Druck-Optionen werden jetzt direkt vor dem Drucken gesetzt
435 aDocument.SetLanguage( (LanguageType) nDefLang, (LanguageType) nCjkLang, (LanguageType) nCtlLang );
438 Printer* ScDocShell::GetDocumentPrinter() // fuer OLE
440 return aDocument.GetPrinter();
443 SfxPrinter* ScDocShell::GetPrinter(bool bCreateIfNotExist)
445 return aDocument.GetPrinter(bCreateIfNotExist);
448 void ScDocShell::UpdateFontList()
450 delete pImpl->pFontList;
451 // pImpl->pFontList = new FontList( GetPrinter(), Application::GetDefaultDevice() );
452 pImpl->pFontList = new FontList( GetRefDevice(), NULL, false ); // sal_False or sal_True???
453 SvxFontListItem aFontListItem( pImpl->pFontList, SID_ATTR_CHAR_FONTLIST );
454 PutItem( aFontListItem );
456 CalcOutputFactor();
459 OutputDevice* ScDocShell::GetRefDevice()
461 return aDocument.GetRefDevice();
464 sal_uInt16 ScDocShell::SetPrinter( SfxPrinter* pNewPrinter, sal_uInt16 nDiffFlags )
466 SfxPrinter *pOld = aDocument.GetPrinter( false );
467 if ( pOld && pOld->IsPrinting() )
468 return SFX_PRINTERROR_BUSY;
470 if (nDiffFlags & SFX_PRINTER_PRINTER)
472 if ( aDocument.GetPrinter() != pNewPrinter )
474 aDocument.SetPrinter( pNewPrinter );
475 aDocument.SetPrintOptions();
477 // MT: Use UpdateFontList: Will use Printer fonts only if needed!
479 delete pImpl->pFontList;
480 pImpl->pFontList = new FontList( pNewPrinter, Application::GetDefaultDevice() );
481 SvxFontListItem aFontListItem( pImpl->pFontList, SID_ATTR_CHAR_FONTLIST );
482 PutItem( aFontListItem );
484 CalcOutputFactor();
486 if ( SC_MOD()->GetInputOptions().GetTextWysiwyg() )
487 UpdateFontList();
489 ScModule* pScMod = SC_MOD();
490 SfxViewFrame *pFrame = SfxViewFrame::GetFirst( this );
491 while (pFrame)
493 SfxViewShell* pSh = pFrame->GetViewShell();
494 if (pSh && pSh->ISA(ScTabViewShell))
496 ScTabViewShell* pViewSh = (ScTabViewShell*)pSh;
497 ScInputHandler* pInputHdl = pScMod->GetInputHdl(pViewSh);
498 if (pInputHdl)
499 pInputHdl->UpdateRefDevice();
501 pFrame = SfxViewFrame::GetNext( *pFrame, this );
505 else if (nDiffFlags & SFX_PRINTER_JOBSETUP)
507 SfxPrinter* pOldPrinter = aDocument.GetPrinter();
508 if (pOldPrinter)
510 pOldPrinter->SetJobSetup( pNewPrinter->GetJobSetup() );
512 // #i6706# Call SetPrinter with the old printer again, so the drawing layer
513 // RefDevice is set (calling ReformatAllTextObjects and rebuilding charts),
514 // because the JobSetup (printer device settings) may affect text layout.
515 aDocument.SetPrinter( pOldPrinter );
516 CalcOutputFactor(); // also with the new settings
520 if (nDiffFlags & SFX_PRINTER_OPTIONS)
522 aDocument.SetPrintOptions(); //! aus neuem Printer ???
525 if (nDiffFlags & (SFX_PRINTER_CHG_ORIENTATION | SFX_PRINTER_CHG_SIZE))
527 OUString aStyle = aDocument.GetPageStyle( GetCurTab() );
528 ScStyleSheetPool* pStPl = aDocument.GetStyleSheetPool();
529 SfxStyleSheet* pStyleSheet = (SfxStyleSheet*)pStPl->Find(aStyle, SFX_STYLE_FAMILY_PAGE);
530 if (pStyleSheet)
532 SfxItemSet& rSet = pStyleSheet->GetItemSet();
534 if (nDiffFlags & SFX_PRINTER_CHG_ORIENTATION)
536 const SvxPageItem& rOldItem = (const SvxPageItem&)rSet.Get(ATTR_PAGE);
537 bool bWasLand = rOldItem.IsLandscape();
538 bool bNewLand = ( pNewPrinter->GetOrientation() == ORIENTATION_LANDSCAPE );
539 if (bNewLand != bWasLand)
541 SvxPageItem aNewItem( rOldItem );
542 aNewItem.SetLandscape( bNewLand );
543 rSet.Put( aNewItem );
545 // Groesse umdrehen
546 Size aOldSize = ((const SvxSizeItem&)rSet.Get(ATTR_PAGE_SIZE)).GetSize();
547 Size aNewSize(aOldSize.Height(),aOldSize.Width());
548 SvxSizeItem aNewSItem(ATTR_PAGE_SIZE,aNewSize);
549 rSet.Put( aNewSItem );
552 if (nDiffFlags & SFX_PRINTER_CHG_SIZE)
554 SvxSizeItem aPaperSizeItem( ATTR_PAGE_SIZE, SvxPaperInfo::GetPaperSize(pNewPrinter) );
555 rSet.Put( aPaperSizeItem );
560 PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB,PAINT_ALL);
562 return 0;
565 ScChangeAction* ScDocShell::GetChangeAction( const ScAddress& rPos )
567 ScChangeTrack* pTrack = GetDocument()->GetChangeTrack();
568 if (!pTrack)
569 return NULL;
571 SCTAB nTab = rPos.Tab();
573 const ScChangeAction* pFound = NULL;
574 long nModified = 0;
575 const ScChangeAction* pAction = pTrack->GetFirst();
576 while (pAction)
578 ScChangeActionType eType = pAction->GetType();
579 //! ScViewUtil::IsActionShown( *pAction, *pSettings, *pDoc )...
580 if ( pAction->IsVisible() && eType != SC_CAT_DELETE_TABS )
582 const ScBigRange& rBig = pAction->GetBigRange();
583 if ( rBig.aStart.Tab() == nTab )
585 ScRange aRange = rBig.MakeRange();
587 if ( eType == SC_CAT_DELETE_ROWS )
588 aRange.aEnd.SetRow( aRange.aStart.Row() );
589 else if ( eType == SC_CAT_DELETE_COLS )
590 aRange.aEnd.SetCol( aRange.aStart.Col() );
592 if ( aRange.In( rPos ) )
594 pFound = pAction; // der letzte gewinnt
595 ++nModified;
598 if ( pAction->GetType() == SC_CAT_MOVE )
600 ScRange aRange =
601 ((const ScChangeActionMove*)pAction)->
602 GetFromRange().MakeRange();
603 if ( aRange.In( rPos ) )
605 pFound = pAction;
606 ++nModified;
610 pAction = pAction->GetNext();
613 return (ScChangeAction*)pFound;
616 void ScDocShell::SetChangeComment( ScChangeAction* pAction, const OUString& rComment )
618 if (pAction)
620 pAction->SetComment( rComment );
621 //! Undo ???
622 SetDocumentModified();
624 // Dialog-Notify
625 ScChangeTrack* pTrack = GetDocument()->GetChangeTrack();
626 if (pTrack)
628 sal_uLong nNumber = pAction->GetActionNumber();
629 pTrack->NotifyModified( SC_CTM_CHANGE, nNumber, nNumber );
634 void ScDocShell::ExecuteChangeCommentDialog( ScChangeAction* pAction, Window* pParent, bool bPrevNext)
636 if (!pAction) return; // ohne Aktion ist nichts..
638 OUString aComment = pAction->GetComment();
639 OUString aAuthor = pAction->GetUser();
641 DateTime aDT = pAction->GetDateTime();
642 OUString aDate = ScGlobal::pLocaleData->getDate( aDT );
643 aDate += " ";
644 aDate += ScGlobal::pLocaleData->getTime( aDT, false, false );
646 SfxItemSet aSet( GetPool(),
647 SID_ATTR_POSTIT_AUTHOR, SID_ATTR_POSTIT_AUTHOR,
648 SID_ATTR_POSTIT_DATE, SID_ATTR_POSTIT_DATE,
649 SID_ATTR_POSTIT_TEXT, SID_ATTR_POSTIT_TEXT,
650 0 );
652 aSet.Put( SvxPostItTextItem ( aComment, SID_ATTR_POSTIT_TEXT ) );
653 aSet.Put( SvxPostItAuthorItem( aAuthor, SID_ATTR_POSTIT_AUTHOR ) );
654 aSet.Put( SvxPostItDateItem ( aDate, SID_ATTR_POSTIT_DATE ) );
656 boost::scoped_ptr<ScRedComDialog> pDlg(new ScRedComDialog( pParent, aSet,this,pAction,bPrevNext));
658 pDlg->Execute();
661 void ScDocShell::CompareDocument( ScDocument& rOtherDoc )
663 ScChangeTrack* pTrack = aDocument.GetChangeTrack();
664 if ( pTrack && pTrack->GetFirst() )
666 //! Changes vorhanden -> Nachfrage ob geloescht werden soll
669 aDocument.EndChangeTracking();
670 aDocument.StartChangeTracking();
672 OUString aOldUser;
673 pTrack = aDocument.GetChangeTrack();
674 if ( pTrack )
676 aOldUser = pTrack->GetUser();
678 // check if comparing to same document
680 OUString aThisFile;
681 const SfxMedium* pThisMed = GetMedium();
682 if (pThisMed)
683 aThisFile = pThisMed->GetName();
684 OUString aOtherFile;
685 SfxObjectShell* pOtherSh = rOtherDoc.GetDocumentShell();
686 if (pOtherSh)
688 const SfxMedium* pOtherMed = pOtherSh->GetMedium();
689 if (pOtherMed)
690 aOtherFile = pOtherMed->GetName();
692 bool bSameDoc = ( aThisFile == aOtherFile && !aThisFile.isEmpty() );
693 if ( !bSameDoc )
695 // create change actions from comparing with the name of the user
696 // who last saved the document
697 // (only if comparing different documents)
699 using namespace ::com::sun::star;
700 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
701 GetModel(), uno::UNO_QUERY_THROW);
702 uno::Reference<document::XDocumentProperties> xDocProps(
703 xDPS->getDocumentProperties());
704 OSL_ENSURE(xDocProps.is(), "no DocumentProperties");
705 OUString aDocUser = xDocProps->getModifiedBy();
707 if ( !aDocUser.isEmpty() )
708 pTrack->SetUser( aDocUser );
712 aDocument.CompareDocument( rOtherDoc );
714 pTrack = aDocument.GetChangeTrack();
715 if ( pTrack )
716 pTrack->SetUser( aOldUser );
718 PostPaintGridAll();
719 SetDocumentModified();
722 // Merge (Aenderungen zusammenfuehren)
724 static inline bool lcl_Equal( const ScChangeAction* pA, const ScChangeAction* pB, bool bIgnore100Sec )
726 return pA && pB &&
727 pA->GetActionNumber() == pB->GetActionNumber() &&
728 pA->GetType() == pB->GetType() &&
729 pA->GetUser() == pB->GetUser() &&
730 (bIgnore100Sec ?
731 pA->GetDateTimeUTC().IsEqualIgnoreNanoSec( pB->GetDateTimeUTC() ) :
732 pA->GetDateTimeUTC() == pB->GetDateTimeUTC());
733 // State nicht vergleichen, falls eine alte Aenderung akzeptiert wurde
736 static bool lcl_FindAction( ScDocument* pDoc, const ScChangeAction* pAction, ScDocument* pSearchDoc, const ScChangeAction* pFirstSearchAction, const ScChangeAction* pLastSearchAction, bool bIgnore100Sec )
738 if ( !pDoc || !pAction || !pSearchDoc || !pFirstSearchAction || !pLastSearchAction )
740 return false;
743 sal_uLong nLastSearchAction = pLastSearchAction->GetActionNumber();
744 const ScChangeAction* pA = pFirstSearchAction;
745 while ( pA && pA->GetActionNumber() <= nLastSearchAction )
747 if ( pAction->GetType() == pA->GetType() &&
748 pAction->GetUser() == pA->GetUser() &&
749 (bIgnore100Sec ?
750 pAction->GetDateTimeUTC().IsEqualIgnoreNanoSec( pA->GetDateTimeUTC() ) :
751 pAction->GetDateTimeUTC() == pA->GetDateTimeUTC() ) &&
752 pAction->GetBigRange() == pA->GetBigRange() )
754 OUString aActionDesc;
755 pAction->GetDescription(aActionDesc, pDoc, true);
756 OUString aADesc;
757 pA->GetDescription(aADesc, pSearchDoc, true);
758 if (aActionDesc.equals(aADesc))
760 OSL_FAIL( "lcl_FindAction(): found equal action!" );
761 return true;
764 pA = pA->GetNext();
767 return false;
770 void ScDocShell::MergeDocument( ScDocument& rOtherDoc, bool bShared, bool bCheckDuplicates, sal_uLong nOffset, ScChangeActionMergeMap* pMergeMap, bool bInverseMap )
772 ScTabViewShell* pViewSh = GetBestViewShell( false ); //! Funktionen an die DocShell
773 if (!pViewSh)
774 return;
776 ScChangeTrack* pSourceTrack = rOtherDoc.GetChangeTrack();
777 if (!pSourceTrack)
778 return; //! nichts zu tun - Fehlermeldung?
780 ScChangeTrack* pThisTrack = aDocument.GetChangeTrack();
781 if ( !pThisTrack )
782 { // anschalten
783 aDocument.StartChangeTracking();
784 pThisTrack = aDocument.GetChangeTrack();
785 OSL_ENSURE(pThisTrack,"ChangeTracking nicht angeschaltet?");
786 if ( !bShared )
788 // visuelles RedLining einschalten
789 ScChangeViewSettings aChangeViewSet;
790 aChangeViewSet.SetShowChanges(true);
791 aDocument.SetChangeViewSettings(aChangeViewSet);
795 // include Nano seconds in compare?
796 bool bIgnore100Sec = !pSourceTrack->IsTimeNanoSeconds() ||
797 !pThisTrack->IsTimeNanoSeconds();
799 // gemeinsame Ausgangsposition suchen
800 sal_uLong nFirstNewNumber = 0;
801 const ScChangeAction* pSourceAction = pSourceTrack->GetFirst();
802 const ScChangeAction* pThisAction = pThisTrack->GetFirst();
803 // skip identical actions
804 while ( lcl_Equal( pSourceAction, pThisAction, bIgnore100Sec ) )
806 nFirstNewNumber = pSourceAction->GetActionNumber() + 1;
807 pSourceAction = pSourceAction->GetNext();
808 pThisAction = pThisAction->GetNext();
810 // pSourceAction und pThisAction zeigen jetzt auf die ersten "eigenen" Aktionen
811 // Die gemeinsamen Aktionen davor interessieren ueberhaupt nicht
813 //! Abfrage, ob die Dokumente vor dem Change-Tracking gleich waren !!!
816 const ScChangeAction* pFirstMergeAction = pSourceAction;
817 const ScChangeAction* pFirstSearchAction = pThisAction;
819 // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
820 const ScChangeAction* pLastSearchAction = pThisTrack->GetLast();
822 // MergeChangeData aus den folgenden Aktionen erzeugen
823 sal_uLong nNewActionCount = 0;
824 const ScChangeAction* pCount = pSourceAction;
825 while ( pCount )
827 if ( bShared || !ScChangeTrack::MergeIgnore( *pCount, nFirstNewNumber ) )
828 ++nNewActionCount;
829 pCount = pCount->GetNext();
831 if (!nNewActionCount)
832 return; //! nichts zu tun - Fehlermeldung?
833 // ab hier kein return mehr
835 ScProgress aProgress( this, OUString("..."),
836 nNewActionCount );
838 sal_uLong nLastMergeAction = pSourceTrack->GetLast()->GetActionNumber();
839 // UpdateReference-Undo, gueltige Referenzen fuer den letzten gemeinsamen Zustand
840 pSourceTrack->MergePrepare( (ScChangeAction*) pFirstMergeAction, bShared );
842 // MergeChangeData an alle noch folgenden Aktionen in diesem Dokument anpassen
843 // -> Referenzen gueltig fuer dieses Dokument
844 while ( pThisAction )
846 // #i87049# [Collaboration] Conflict between delete row and insert content is not merged correctly
847 if ( !bShared || !ScChangeTrack::MergeIgnore( *pThisAction, nFirstNewNumber ) )
849 ScChangeActionType eType = pThisAction->GetType();
850 switch ( eType )
852 case SC_CAT_INSERT_COLS :
853 case SC_CAT_INSERT_ROWS :
854 case SC_CAT_INSERT_TABS :
855 pSourceTrack->AppendInsert( pThisAction->GetBigRange().MakeRange() );
856 break;
857 case SC_CAT_DELETE_COLS :
858 case SC_CAT_DELETE_ROWS :
859 case SC_CAT_DELETE_TABS :
861 const ScChangeActionDel* pDel = (const ScChangeActionDel*) pThisAction;
862 if ( pDel->IsTopDelete() && !pDel->IsTabDeleteCol() )
863 { // deleted Table enthaelt deleted Cols, die nicht
864 sal_uLong nStart, nEnd;
865 pSourceTrack->AppendDeleteRange(
866 pDel->GetOverAllRange().MakeRange(), NULL, nStart, nEnd );
869 break;
870 case SC_CAT_MOVE :
872 const ScChangeActionMove* pMove = (const ScChangeActionMove*) pThisAction;
873 pSourceTrack->AppendMove( pMove->GetFromRange().MakeRange(),
874 pMove->GetBigRange().MakeRange(), NULL );
876 break;
877 default:
879 // added to avoid warnings
883 pThisAction = pThisAction->GetNext();
886 LockPaint(); // #i73877# no repainting after each action
888 // MergeChangeData in das aktuelle Dokument uebernehmen
889 bool bHasRejected = false;
890 OUString aOldUser = pThisTrack->GetUser();
891 pThisTrack->SetUseFixDateTime( true );
892 ScMarkData& rMarkData = pViewSh->GetViewData()->GetMarkData();
893 ScMarkData aOldMarkData( rMarkData );
894 pSourceAction = pFirstMergeAction;
895 while ( pSourceAction && pSourceAction->GetActionNumber() <= nLastMergeAction )
897 bool bMergeAction = false;
898 if ( bShared )
900 if ( !bCheckDuplicates || !lcl_FindAction( &rOtherDoc, pSourceAction, &aDocument, pFirstSearchAction, pLastSearchAction, bIgnore100Sec ) )
902 bMergeAction = true;
905 else
907 if ( !ScChangeTrack::MergeIgnore( *pSourceAction, nFirstNewNumber ) )
909 bMergeAction = true;
913 if ( bMergeAction )
915 ScChangeActionType eSourceType = pSourceAction->GetType();
916 if ( !bShared && pSourceAction->IsDeletedIn() )
918 //! muss hier noch festgestellt werden, ob wirklich in
919 //! _diesem_ Dokument geloescht?
921 // liegt in einem Bereich, der in diesem Dokument geloescht wurde
922 // -> wird weggelassen
923 //! ??? Loesch-Aktion rueckgaengig machen ???
924 //! ??? Aktion irgendwo anders speichern ???
925 #if OSL_DEBUG_LEVEL > 0
926 OUString aValue;
927 if ( eSourceType == SC_CAT_CONTENT )
928 ((const ScChangeActionContent*)pSourceAction)->GetNewString( aValue, &aDocument );
929 OStringBuffer aError(OUStringToOString(aValue,
930 osl_getThreadTextEncoding()));
931 aError.append(" weggelassen");
932 OSL_FAIL( aError.getStr() );
933 #endif
935 else
937 //! Datum/Autor/Kommentar der Source-Aktion uebernehmen!
939 pThisTrack->SetUser( pSourceAction->GetUser() );
940 pThisTrack->SetFixDateTimeUTC( pSourceAction->GetDateTimeUTC() );
941 sal_uLong nOldActionMax = pThisTrack->GetActionMax();
943 bool bExecute = true;
944 sal_uLong nReject = pSourceAction->GetRejectAction();
945 if ( nReject )
947 if ( bShared )
949 if ( nReject >= nFirstNewNumber )
951 nReject += nOffset;
953 ScChangeAction* pOldAction = pThisTrack->GetAction( nReject );
954 if ( pOldAction && pOldAction->IsVirgin() )
956 pThisTrack->Reject( pOldAction );
957 bHasRejected = true;
958 bExecute = false;
961 else
963 // alte Aktion (aus den gemeinsamen) ablehnen
964 ScChangeAction* pOldAction = pThisTrack->GetAction( nReject );
965 if (pOldAction && pOldAction->GetState() == SC_CAS_VIRGIN)
967 //! was passiert bei Aktionen, die in diesem Dokument accepted worden sind???
968 //! Fehlermeldung oder was???
969 //! oder Reject-Aenderung normal ausfuehren
971 pThisTrack->Reject(pOldAction);
972 bHasRejected = true; // fuer Paint
974 bExecute = false;
978 if ( bExecute )
980 // normal ausfuehren
981 ScRange aSourceRange = pSourceAction->GetBigRange().MakeRange();
982 rMarkData.SelectOneTable( aSourceRange.aStart.Tab() );
983 switch ( eSourceType )
985 case SC_CAT_CONTENT:
987 //! Test, ob es ganz unten im Dokument war, dann automatisches
988 //! Zeilen-Einfuegen ???
990 OSL_ENSURE( aSourceRange.aStart == aSourceRange.aEnd, "huch?" );
991 ScAddress aPos = aSourceRange.aStart;
992 OUString aValue;
993 ((const ScChangeActionContent*)pSourceAction)->GetNewString( aValue, &aDocument );
994 sal_uInt8 eMatrix = MM_NONE;
995 const ScCellValue& rCell = ((const ScChangeActionContent*)pSourceAction)->GetNewCell();
996 if (rCell.meType == CELLTYPE_FORMULA)
997 eMatrix = rCell.mpFormula->GetMatrixFlag();
998 switch ( eMatrix )
1000 case MM_NONE :
1001 pViewSh->EnterData( aPos.Col(), aPos.Row(), aPos.Tab(), aValue );
1002 break;
1003 case MM_FORMULA :
1005 SCCOL nCols;
1006 SCROW nRows;
1007 rCell.mpFormula->GetMatColsRows(nCols, nRows);
1008 aSourceRange.aEnd.SetCol( aPos.Col() + nCols - 1 );
1009 aSourceRange.aEnd.SetRow( aPos.Row() + nRows - 1 );
1010 aValue = aValue.copy(1, aValue.getLength()-2); // remove the 1st and last characters.
1011 GetDocFunc().EnterMatrix( aSourceRange,
1012 NULL, NULL, aValue, false, false,
1013 EMPTY_OUSTRING, formula::FormulaGrammar::GRAM_DEFAULT );
1015 break;
1016 case MM_REFERENCE : // do nothing
1017 break;
1018 case MM_FAKE :
1019 OSL_FAIL( "MergeDocument: MatrixFlag MM_FAKE" );
1020 pViewSh->EnterData( aPos.Col(), aPos.Row(), aPos.Tab(), aValue );
1021 break;
1022 default:
1023 OSL_FAIL( "MergeDocument: unknown MatrixFlag" );
1026 break;
1027 case SC_CAT_INSERT_TABS :
1029 OUString aName;
1030 aDocument.CreateValidTabName( aName );
1031 GetDocFunc().InsertTable( aSourceRange.aStart.Tab(), aName, true, false );
1033 break;
1034 case SC_CAT_INSERT_ROWS:
1035 GetDocFunc().InsertCells( aSourceRange, NULL, INS_INSROWS, true, false );
1036 break;
1037 case SC_CAT_INSERT_COLS:
1038 GetDocFunc().InsertCells( aSourceRange, NULL, INS_INSCOLS, true, false );
1039 break;
1040 case SC_CAT_DELETE_TABS :
1041 GetDocFunc().DeleteTable( aSourceRange.aStart.Tab(), true, false );
1042 break;
1043 case SC_CAT_DELETE_ROWS:
1045 const ScChangeActionDel* pDel = (const ScChangeActionDel*) pSourceAction;
1046 if ( pDel->IsTopDelete() )
1048 aSourceRange = pDel->GetOverAllRange().MakeRange();
1049 GetDocFunc().DeleteCells( aSourceRange, NULL, DEL_DELROWS, true, false );
1051 // #i101099# [Collaboration] Changes are not correctly shown
1052 if ( bShared )
1054 ScChangeAction* pAct = pThisTrack->GetLast();
1055 if ( pAct && pAct->GetType() == eSourceType && pAct->IsDeletedIn() && !pSourceAction->IsDeletedIn() )
1057 pAct->RemoveAllDeletedIn();
1062 break;
1063 case SC_CAT_DELETE_COLS:
1065 const ScChangeActionDel* pDel = (const ScChangeActionDel*) pSourceAction;
1066 if ( pDel->IsTopDelete() && !pDel->IsTabDeleteCol() )
1067 { // deleted Table enthaelt deleted Cols, die nicht
1068 aSourceRange = pDel->GetOverAllRange().MakeRange();
1069 GetDocFunc().DeleteCells( aSourceRange, NULL, DEL_DELCOLS, true, false );
1072 break;
1073 case SC_CAT_MOVE :
1075 const ScChangeActionMove* pMove = (const ScChangeActionMove*) pSourceAction;
1076 ScRange aFromRange( pMove->GetFromRange().MakeRange() );
1077 GetDocFunc().MoveBlock( aFromRange,
1078 aSourceRange.aStart, true, true, false, false );
1080 break;
1081 default:
1083 // added to avoid warnings
1087 const OUString& rComment = pSourceAction->GetComment();
1088 if ( !rComment.isEmpty() )
1090 ScChangeAction* pAct = pThisTrack->GetLast();
1091 if ( pAct && pAct->GetActionNumber() > nOldActionMax )
1092 pAct->SetComment( rComment );
1093 else
1094 OSL_FAIL( "MergeDocument: wohin mit dem Kommentar?!?" );
1097 // Referenzen anpassen
1098 pSourceTrack->MergeOwn( (ScChangeAction*) pSourceAction, nFirstNewNumber, bShared );
1100 // merge action state
1101 if ( bShared && !pSourceAction->IsRejected() )
1103 ScChangeAction* pAct = pThisTrack->GetLast();
1104 if ( pAct && pAct->GetActionNumber() > nOldActionMax )
1106 pThisTrack->MergeActionState( pAct, pSourceAction );
1110 // fill merge map
1111 if ( bShared && pMergeMap )
1113 ScChangeAction* pAct = pThisTrack->GetLast();
1114 if ( pAct && pAct->GetActionNumber() > nOldActionMax )
1116 sal_uLong nActionMax = pAct->GetActionNumber();
1117 sal_uLong nActionCount = nActionMax - nOldActionMax;
1118 sal_uLong nAction = nActionMax - nActionCount + 1;
1119 sal_uLong nSourceAction = pSourceAction->GetActionNumber() - nActionCount + 1;
1120 while ( nAction <= nActionMax )
1122 if ( bInverseMap )
1124 (*pMergeMap)[ nAction++ ] = nSourceAction++;
1126 else
1128 (*pMergeMap)[ nSourceAction++ ] = nAction++;
1134 aProgress.SetStateCountDown( --nNewActionCount );
1136 pSourceAction = pSourceAction->GetNext();
1139 rMarkData = aOldMarkData;
1140 pThisTrack->SetUser(aOldUser);
1141 pThisTrack->SetUseFixDateTime( false );
1143 pSourceTrack->Clear(); //! der ist jetzt verhunzt
1145 if (bHasRejected)
1146 PostPaintGridAll(); // Reject() paintet nicht selber
1148 UnlockPaint();
1151 bool ScDocShell::MergeSharedDocument( ScDocShell* pSharedDocShell )
1153 if ( !pSharedDocShell )
1155 return false;
1158 ScChangeTrack* pThisTrack = aDocument.GetChangeTrack();
1159 if ( !pThisTrack )
1161 return false;
1164 ScDocument& rSharedDoc = *( pSharedDocShell->GetDocument() );
1165 ScChangeTrack* pSharedTrack = rSharedDoc.GetChangeTrack();
1166 if ( !pSharedTrack )
1168 return false;
1171 // reset show changes
1172 ScChangeViewSettings aChangeViewSet;
1173 aChangeViewSet.SetShowChanges( false );
1174 aDocument.SetChangeViewSettings( aChangeViewSet );
1176 // find first merge action in this document
1177 bool bIgnore100Sec = !pThisTrack->IsTimeNanoSeconds() || !pSharedTrack->IsTimeNanoSeconds();
1178 ScChangeAction* pThisAction = pThisTrack->GetFirst();
1179 ScChangeAction* pSharedAction = pSharedTrack->GetFirst();
1180 while ( lcl_Equal( pThisAction, pSharedAction, bIgnore100Sec ) )
1182 pThisAction = pThisAction->GetNext();
1183 pSharedAction = pSharedAction->GetNext();
1186 if ( pSharedAction )
1188 if ( pThisAction )
1190 // merge own changes into shared document
1191 sal_uLong nActStartShared = pSharedAction->GetActionNumber();
1192 sal_uLong nActEndShared = pSharedTrack->GetActionMax();
1193 ScDocument* pTmpDoc = new ScDocument;
1194 for ( sal_Int32 nIndex = 0; nIndex < aDocument.GetTableCount(); ++nIndex )
1196 OUString sTabName;
1197 pTmpDoc->CreateValidTabName( sTabName );
1198 pTmpDoc->InsertTab( SC_TAB_APPEND, sTabName );
1200 aDocument.GetChangeTrack()->Clone( pTmpDoc );
1201 ScChangeActionMergeMap aOwnInverseMergeMap;
1202 pSharedDocShell->MergeDocument( *pTmpDoc, true, true, 0, &aOwnInverseMergeMap, true );
1203 delete pTmpDoc;
1204 sal_uLong nActStartOwn = nActEndShared + 1;
1205 sal_uLong nActEndOwn = pSharedTrack->GetActionMax();
1207 // find conflicts
1208 ScConflictsList aConflictsList;
1209 ScConflictsFinder aFinder( pSharedTrack, nActStartShared, nActEndShared, nActStartOwn, nActEndOwn, aConflictsList );
1210 if ( aFinder.Find() )
1212 ScConflictsListHelper::TransformConflictsList( aConflictsList, NULL, &aOwnInverseMergeMap );
1213 bool bLoop = true;
1214 while ( bLoop )
1216 bLoop = false;
1217 ScConflictsDlg aDlg( GetActiveDialogParent(), GetViewData(), &rSharedDoc, aConflictsList );
1218 if ( aDlg.Execute() == RET_CANCEL )
1220 QueryBox aBox( GetActiveDialogParent(), WinBits( WB_YES_NO | WB_DEF_YES ),
1221 ScGlobal::GetRscString( STR_DOC_WILLNOTBESAVED ) );
1222 if ( aBox.Execute() == RET_YES )
1224 return false;
1226 else
1228 bLoop = true;
1234 // undo own changes in shared document
1235 pSharedTrack->Undo( nActStartOwn, nActEndOwn );
1237 // clone change track for merging into own document
1238 pTmpDoc = new ScDocument;
1239 for ( sal_Int32 nIndex = 0; nIndex < aDocument.GetTableCount(); ++nIndex )
1241 OUString sTabName;
1242 pTmpDoc->CreateValidTabName( sTabName );
1243 pTmpDoc->InsertTab( SC_TAB_APPEND, sTabName );
1245 pThisTrack->Clone( pTmpDoc );
1247 // undo own changes since last save in own document
1248 sal_uLong nStartShared = pThisAction->GetActionNumber();
1249 ScChangeAction* pAction = pThisTrack->GetLast();
1250 while ( pAction && pAction->GetActionNumber() >= nStartShared )
1252 pThisTrack->Reject( pAction, true );
1253 pAction = pAction->GetPrev();
1256 // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
1257 pThisTrack->Undo( nStartShared, pThisTrack->GetActionMax(), true );
1259 // merge shared changes into own document
1260 ScChangeActionMergeMap aSharedMergeMap;
1261 MergeDocument( rSharedDoc, true, true, 0, &aSharedMergeMap );
1262 sal_uLong nEndShared = pThisTrack->GetActionMax();
1264 // resolve conflicts for shared non-content actions
1265 if ( !aConflictsList.empty() )
1267 ScConflictsListHelper::TransformConflictsList( aConflictsList, &aSharedMergeMap, NULL );
1268 ScConflictsResolver aResolver( pThisTrack, aConflictsList );
1269 pAction = pThisTrack->GetAction( nEndShared );
1270 while ( pAction && pAction->GetActionNumber() >= nStartShared )
1272 aResolver.HandleAction( pAction, true /*bIsSharedAction*/,
1273 false /*bHandleContentAction*/, true /*bHandleNonContentAction*/ );
1274 pAction = pAction->GetPrev();
1277 nEndShared = pThisTrack->GetActionMax();
1279 // only show changes from shared document
1280 aChangeViewSet.SetShowChanges( true );
1281 aChangeViewSet.SetShowAccepted( true );
1282 aChangeViewSet.SetHasActionRange( true );
1283 aChangeViewSet.SetTheActionRange( nStartShared, nEndShared );
1284 aDocument.SetChangeViewSettings( aChangeViewSet );
1286 // merge own changes back into own document
1287 sal_uLong nStartOwn = nEndShared + 1;
1288 ScChangeActionMergeMap aOwnMergeMap;
1289 MergeDocument( *pTmpDoc, true, true, nEndShared - nStartShared + 1, &aOwnMergeMap );
1290 delete pTmpDoc;
1291 sal_uLong nEndOwn = pThisTrack->GetActionMax();
1293 // resolve conflicts for shared content actions and own actions
1294 if ( !aConflictsList.empty() )
1296 ScConflictsListHelper::TransformConflictsList( aConflictsList, NULL, &aOwnMergeMap );
1297 ScConflictsResolver aResolver( pThisTrack, aConflictsList );
1298 pAction = pThisTrack->GetAction( nEndShared );
1299 while ( pAction && pAction->GetActionNumber() >= nStartShared )
1301 aResolver.HandleAction( pAction, true /*bIsSharedAction*/,
1302 true /*bHandleContentAction*/, false /*bHandleNonContentAction*/ );
1303 pAction = pAction->GetPrev();
1306 pAction = pThisTrack->GetAction( nEndOwn );
1307 while ( pAction && pAction->GetActionNumber() >= nStartOwn )
1309 aResolver.HandleAction( pAction, false /*bIsSharedAction*/,
1310 true /*bHandleContentAction*/, true /*bHandleNonContentAction*/ );
1311 pAction = pAction->GetPrev();
1314 nEndOwn = pThisTrack->GetActionMax();
1316 else
1318 // merge shared changes into own document
1319 sal_uLong nStartShared = pThisTrack->GetActionMax() + 1;
1320 MergeDocument( rSharedDoc, true, true );
1321 sal_uLong nEndShared = pThisTrack->GetActionMax();
1323 // only show changes from shared document
1324 aChangeViewSet.SetShowChanges( true );
1325 aChangeViewSet.SetShowAccepted( true );
1326 aChangeViewSet.SetHasActionRange( true );
1327 aChangeViewSet.SetTheActionRange( nStartShared, nEndShared );
1328 aDocument.SetChangeViewSettings( aChangeViewSet );
1331 // update view
1332 PostPaintExtras();
1333 PostPaintGridAll();
1335 InfoBox aInfoBox( GetActiveDialogParent(), ScGlobal::GetRscString( STR_DOC_UPDATED ) );
1336 aInfoBox.Execute();
1339 return ( pThisAction != NULL );
1342 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */