Update ooo320-m1
[ooovba.git] / sc / source / ui / docshell / docsh3.cxx
blobefc44842374fd1791b6c8375e5db0cae1be2ae00
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: docsh3.cxx,v $
10 * $Revision: 1.38.52.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 // INCLUDE ---------------------------------------------------------------
38 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
39 #include <com/sun/star/document/XDocumentProperties.hpp>
41 #include "scitems.hxx"
42 #include "rangelst.hxx"
43 #include <svx/flstitem.hxx>
44 #include <svx/pageitem.hxx>
45 #include <svx/paperinf.hxx>
46 #include <svx/postattr.hxx>
47 //#include <svx/postdlg.hxx>
48 #include <svx/sizeitem.hxx>
50 #include <sfx2/viewfrm.hxx>
51 #include <sfx2/app.hxx>
52 #include <sfx2/docfile.hxx>
53 #include <svtools/misccfg.hxx>
54 #include <sfx2/printer.hxx>
55 #include <svtools/ctrltool.hxx>
56 #include <vcl/virdev.hxx>
57 #include <vcl/svapp.hxx>
58 #include <vcl/msgbox.hxx>
59 #include <unotools/localedatawrapper.hxx>
61 #include "docsh.hxx"
62 #include "docshimp.hxx"
63 #include "scmod.hxx"
64 #include "tabvwsh.hxx"
65 #include "viewdata.hxx"
66 #include "docpool.hxx"
67 #include "stlpool.hxx"
68 #include "patattr.hxx"
69 #include "uiitems.hxx"
70 #include "hints.hxx"
71 #include "docoptio.hxx"
72 #include "viewopti.hxx"
73 #include "pntlock.hxx"
74 #include "chgtrack.hxx"
75 #include "docfunc.hxx"
76 #include "cell.hxx"
77 #include "chgviset.hxx"
78 #include "progress.hxx"
79 #include "redcom.hxx"
80 #include "sc.hrc"
81 #include "inputopt.hxx"
82 #include "drwlayer.hxx"
83 #include "inputhdl.hxx"
84 #include "conflictsdlg.hxx"
85 #include "globstr.hrc"
87 #if DEBUG_CHANGETRACK
88 #include <stdio.h>
89 #endif // DEBUG_CHANGETRACK
92 //------------------------------------------------------------------
95 // Redraw - Benachrichtigungen
99 void ScDocShell::PostEditView( ScEditEngineDefaulter* pEditEngine, const ScAddress& rCursorPos )
101 // Broadcast( ScEditViewHint( pEditEngine, rCursorPos ) );
103 // Test: nur aktive ViewShell
105 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
106 if (pViewSh && pViewSh->GetViewData()->GetDocShell() == this)
108 ScEditViewHint aHint( pEditEngine, rCursorPos );
109 pViewSh->Notify( *this, aHint );
113 void ScDocShell::PostDataChanged()
115 Broadcast( SfxSimpleHint( FID_DATACHANGED ) );
116 aDocument.ResetChanged( ScRange(0,0,0,MAXCOL,MAXROW,MAXTAB) );
118 SFX_APP()->Broadcast(SfxSimpleHint( FID_ANYDATACHANGED )); // Navigator
119 //! Navigator direkt benachrichtigen!
122 void ScDocShell::PostPaint( SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab,
123 SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, USHORT nPart,
124 USHORT nExtFlags )
126 if (!ValidCol(nStartCol)) nStartCol = MAXCOL;
127 if (!ValidRow(nStartRow)) nStartRow = MAXROW;
128 if (!ValidCol(nEndCol)) nEndCol = MAXCOL;
129 if (!ValidRow(nEndRow)) nEndRow = MAXROW;
131 if ( pPaintLockData )
133 // #i54081# PAINT_EXTRAS still has to be brodcast because it changes the
134 // current sheet if it's invalid. All other flags added to pPaintLockData.
135 USHORT nLockPart = nPart & ~PAINT_EXTRAS;
136 if ( nLockPart )
138 //! nExtFlags ???
139 pPaintLockData->AddRange( ScRange( nStartCol, nStartRow, nStartTab,
140 nEndCol, nEndRow, nEndTab ), nLockPart );
143 nPart &= PAINT_EXTRAS; // for broadcasting
144 if ( !nPart )
145 return;
149 if (nExtFlags & SC_PF_LINES) // Platz fuer Linien beruecksichtigen
151 //! Abfrage auf versteckte Spalten/Zeilen!
152 if (nStartCol>0) --nStartCol;
153 if (nEndCol<MAXCOL) ++nEndCol;
154 if (nStartRow>0) --nStartRow;
155 if (nEndRow<MAXROW) ++nEndRow;
158 // um zusammengefasste erweitern
159 if (nExtFlags & SC_PF_TESTMERGE)
160 aDocument.ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow, nStartTab );
162 if ( nStartCol != 0 || nEndCol != MAXCOL )
164 // Extend to whole rows if SC_PF_WHOLEROWS is set, or rotated or non-left
165 // aligned cells are contained (see UpdatePaintExt).
166 // Special handling for RTL text (#i9731#) is unnecessary now with full
167 // support of right-aligned text.
169 if ( ( nExtFlags & SC_PF_WHOLEROWS ) ||
170 aDocument.HasAttrib( nStartCol,nStartRow,nStartTab,
171 MAXCOL,nEndRow,nEndTab, HASATTR_ROTATE | HASATTR_RIGHTORCENTER ) )
173 nStartCol = 0;
174 nEndCol = MAXCOL;
178 Broadcast( ScPaintHint( ScRange( nStartCol, nStartRow, nStartTab,
179 nEndCol, nEndRow, nEndTab ), nPart ) );
181 if ( nPart & PAINT_GRID )
182 aDocument.ResetChanged( ScRange(nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab) );
185 void ScDocShell::PostPaint( const ScRange& rRange, USHORT nPart, USHORT nExtFlags )
187 PostPaint( rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(),
188 rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab(),
189 nPart, nExtFlags );
192 void ScDocShell::PostPaintGridAll()
194 PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID );
197 void ScDocShell::PostPaintCell( SCCOL nCol, SCROW nRow, SCTAB nTab )
199 PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PAINT_GRID, SC_PF_TESTMERGE );
202 void ScDocShell::PostPaintCell( const ScAddress& rPos )
204 PostPaintCell( rPos.Col(), rPos.Row(), rPos.Tab() );
207 void ScDocShell::PostPaintExtras()
209 PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS );
212 void ScDocShell::UpdatePaintExt( USHORT& rExtFlags, const ScRange& rRange )
214 if ( ( rExtFlags & SC_PF_LINES ) == 0 && aDocument.HasAttrib( rRange, HASATTR_PAINTEXT ) )
216 // If the range contains lines, shadow or conditional formats,
217 // set SC_PF_LINES to include one extra cell in all directions.
219 rExtFlags |= SC_PF_LINES;
222 if ( ( rExtFlags & SC_PF_WHOLEROWS ) == 0 &&
223 ( rRange.aStart.Col() != 0 || rRange.aEnd.Col() != MAXCOL ) &&
224 aDocument.HasAttrib( rRange, HASATTR_ROTATE | HASATTR_RIGHTORCENTER ) )
226 // If the range contains (logically) right- or center-aligned cells,
227 // or rotated cells, set SC_PF_WHOLEROWS to paint the whole rows.
228 // This test isn't needed after the cell changes, because it's also
229 // tested in PostPaint. UpdatePaintExt may later be changed to do this
230 // only if called before the changes.
232 rExtFlags |= SC_PF_WHOLEROWS;
236 void ScDocShell::UpdatePaintExt( USHORT& rExtFlags, SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab,
237 SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab )
239 UpdatePaintExt( rExtFlags, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ) );
242 //------------------------------------------------------------------
244 void ScDocShell::LockPaint_Impl(BOOL bDoc)
246 if ( !pPaintLockData )
247 pPaintLockData = new ScPaintLockData(0); //! Modus...
248 pPaintLockData->IncLevel(bDoc);
251 void ScDocShell::UnlockPaint_Impl(BOOL bDoc)
253 if ( pPaintLockData )
255 if ( pPaintLockData->GetLevel(bDoc) )
256 pPaintLockData->DecLevel(bDoc);
257 if (!pPaintLockData->GetLevel(!bDoc) && !pPaintLockData->GetLevel(bDoc))
259 // Paint jetzt ausfuehren
261 ScPaintLockData* pPaint = pPaintLockData;
262 pPaintLockData = NULL; // nicht weitersammeln
264 ScRangeListRef xRangeList = pPaint->GetRangeList();
265 if (xRangeList)
267 USHORT nParts = pPaint->GetParts();
268 ULONG nCount = xRangeList->Count();
269 for ( ULONG i=0; i<nCount; i++ )
271 //! nExtFlags ???
272 ScRange aRange = *xRangeList->GetObject(i);
273 PostPaint( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aStart.Tab(),
274 aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aEnd.Tab(),
275 nParts );
279 if ( pPaint->GetModified() )
280 SetDocumentModified();
282 delete pPaint;
285 else
287 DBG_ERROR("UnlockPaint ohne LockPaint");
291 void ScDocShell::LockDocument_Impl(USHORT nNew)
293 if (!nDocumentLock)
295 ScDrawLayer* pDrawLayer = aDocument.GetDrawLayer();
296 if (pDrawLayer)
297 pDrawLayer->setLock(TRUE);
299 nDocumentLock = nNew;
302 void ScDocShell::UnlockDocument_Impl(USHORT nNew)
304 nDocumentLock = nNew;
305 if (!nDocumentLock)
307 ScDrawLayer* pDrawLayer = aDocument.GetDrawLayer();
308 if (pDrawLayer)
309 pDrawLayer->setLock(FALSE);
313 USHORT ScDocShell::GetLockCount() const
315 return nDocumentLock;
318 void ScDocShell::SetLockCount(USHORT nNew)
320 if (nNew) // setzen
322 if ( !pPaintLockData )
323 pPaintLockData = new ScPaintLockData(0); //! Modus...
324 pPaintLockData->SetLevel(nNew-1, TRUE);
325 LockDocument_Impl(nNew);
327 else if (pPaintLockData) // loeschen
329 pPaintLockData->SetLevel(0, TRUE); // bei Unlock sofort ausfuehren
330 UnlockPaint_Impl(TRUE); // jetzt
331 UnlockDocument_Impl(0);
335 void ScDocShell::LockPaint()
337 LockPaint_Impl(FALSE);
340 void ScDocShell::UnlockPaint()
342 UnlockPaint_Impl(FALSE);
345 void ScDocShell::LockDocument()
347 LockPaint_Impl(TRUE);
348 LockDocument_Impl(nDocumentLock + 1);
351 void ScDocShell::UnlockDocument()
353 if (nDocumentLock)
355 UnlockPaint_Impl(TRUE);
356 UnlockDocument_Impl(nDocumentLock - 1);
358 else
360 DBG_ERROR("UnlockDocument without LockDocument");
364 //------------------------------------------------------------------
366 void ScDocShell::SetInplace( BOOL bInplace )
368 if (bIsInplace != bInplace)
370 bIsInplace = bInplace;
371 CalcOutputFactor();
375 void ScDocShell::CalcOutputFactor()
377 if (bIsInplace)
379 nPrtToScreenFactor = 1.0; // passt sonst nicht zur inaktiven Darstellung
380 return;
383 BOOL bTextWysiwyg = SC_MOD()->GetInputOptions().GetTextWysiwyg();
384 if (bTextWysiwyg)
386 nPrtToScreenFactor = 1.0;
387 return;
390 String aTestString = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(
391 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890123456789" ));
392 long nPrinterWidth = 0;
393 long nWindowWidth = 0;
394 const ScPatternAttr* pPattern = (const ScPatternAttr*)&aDocument.GetPool()->
395 GetDefaultItem(ATTR_PATTERN);
397 Font aDefFont;
398 OutputDevice* pRefDev = GetRefDevice();
399 MapMode aOldMode = pRefDev->GetMapMode();
400 Font aOldFont = pRefDev->GetFont();
402 pRefDev->SetMapMode(MAP_PIXEL);
403 pPattern->GetFont(aDefFont, SC_AUTOCOL_BLACK, pRefDev); // font color doesn't matter here
404 pRefDev->SetFont(aDefFont);
405 nPrinterWidth = pRefDev->PixelToLogic( Size( pRefDev->GetTextWidth(aTestString), 0 ), MAP_100TH_MM ).Width();
406 pRefDev->SetFont(aOldFont);
407 pRefDev->SetMapMode(aOldMode);
409 VirtualDevice aVirtWindow( *Application::GetDefaultDevice() );
410 aVirtWindow.SetMapMode(MAP_PIXEL);
411 pPattern->GetFont(aDefFont, SC_AUTOCOL_BLACK, &aVirtWindow); // font color doesn't matter here
412 aVirtWindow.SetFont(aDefFont);
413 nWindowWidth = aVirtWindow.GetTextWidth(aTestString);
414 nWindowWidth = (long) ( nWindowWidth / ScGlobal::nScreenPPTX * HMM_PER_TWIPS );
416 if (nPrinterWidth && nWindowWidth)
417 nPrtToScreenFactor = nPrinterWidth / (double) nWindowWidth;
418 else
420 DBG_ERROR("GetTextSize gibt 0 ??");
421 nPrtToScreenFactor = 1.0;
425 double ScDocShell::GetOutputFactor() const
427 return nPrtToScreenFactor;
430 //---------------------------------------------------------------------
432 void ScDocShell::InitOptions() // Fortsetzung von InitNew (CLOOKs)
434 // Einstellungen aus dem SpellCheckCfg kommen in Doc- und ViewOptions
436 USHORT nDefLang, nCjkLang, nCtlLang;
437 BOOL bAutoSpell;
438 ScModule::GetSpellSettings( nDefLang, nCjkLang, nCtlLang, bAutoSpell );
439 ScModule* pScMod = SC_MOD();
441 ScDocOptions aDocOpt = pScMod->GetDocOptions();
442 ScViewOptions aViewOpt = pScMod->GetViewOptions();
443 aDocOpt.SetAutoSpell( bAutoSpell );
445 // zweistellige Jahreszahleneingabe aus Extras->Optionen->Allgemein->Sonstiges
446 aDocOpt.SetYear2000( sal::static_int_cast<USHORT>( SFX_APP()->GetMiscConfig()->GetYear2000() ) );
448 aDocument.SetDocOptions( aDocOpt );
449 aDocument.SetViewOptions( aViewOpt );
451 // Druck-Optionen werden jetzt direkt vor dem Drucken gesetzt
453 aDocument.SetLanguage( (LanguageType) nDefLang, (LanguageType) nCjkLang, (LanguageType) nCtlLang );
456 //---------------------------------------------------------------------
458 Printer* ScDocShell::GetDocumentPrinter() // fuer OLE
460 return aDocument.GetPrinter();
463 SfxPrinter* ScDocShell::GetPrinter(BOOL bCreateIfNotExist)
465 return aDocument.GetPrinter(bCreateIfNotExist);
468 void ScDocShell::UpdateFontList()
470 delete pImpl->pFontList;
471 // pImpl->pFontList = new FontList( GetPrinter(), Application::GetDefaultDevice() );
472 pImpl->pFontList = new FontList( GetRefDevice(), NULL, FALSE ); // FALSE or TRUE???
473 SvxFontListItem aFontListItem( pImpl->pFontList, SID_ATTR_CHAR_FONTLIST );
474 PutItem( aFontListItem );
476 CalcOutputFactor();
479 OutputDevice* ScDocShell::GetRefDevice()
481 return aDocument.GetRefDevice();
484 USHORT ScDocShell::SetPrinter( SfxPrinter* pNewPrinter, USHORT nDiffFlags )
486 SfxPrinter *pOld = aDocument.GetPrinter( FALSE );
487 if ( pOld && pOld->IsPrinting() )
488 return SFX_PRINTERROR_BUSY;
490 if (nDiffFlags & SFX_PRINTER_PRINTER)
492 if ( aDocument.GetPrinter() != pNewPrinter )
494 aDocument.SetPrinter( pNewPrinter );
495 aDocument.SetPrintOptions();
497 // MT: Use UpdateFontList: Will use Printer fonts only if needed!
499 delete pImpl->pFontList;
500 pImpl->pFontList = new FontList( pNewPrinter, Application::GetDefaultDevice() );
501 SvxFontListItem aFontListItem( pImpl->pFontList, SID_ATTR_CHAR_FONTLIST );
502 PutItem( aFontListItem );
504 CalcOutputFactor();
506 if ( SC_MOD()->GetInputOptions().GetTextWysiwyg() )
507 UpdateFontList();
509 ScModule* pScMod = SC_MOD();
510 SfxViewFrame *pFrame = SfxViewFrame::GetFirst( this );
511 while (pFrame)
513 SfxViewShell* pSh = pFrame->GetViewShell();
514 if (pSh && pSh->ISA(ScTabViewShell))
516 ScTabViewShell* pViewSh = (ScTabViewShell*)pSh;
517 ScInputHandler* pInputHdl = pScMod->GetInputHdl(pViewSh);
518 if (pInputHdl)
519 pInputHdl->UpdateRefDevice();
521 pFrame = SfxViewFrame::GetNext( *pFrame, this );
525 else if (nDiffFlags & SFX_PRINTER_JOBSETUP)
527 SfxPrinter* pOldPrinter = aDocument.GetPrinter();
528 if (pOldPrinter)
530 pOldPrinter->SetJobSetup( pNewPrinter->GetJobSetup() );
532 // #i6706# Call SetPrinter with the old printer again, so the drawing layer
533 // RefDevice is set (calling ReformatAllTextObjects and rebuilding charts),
534 // because the JobSetup (printer device settings) may affect text layout.
535 aDocument.SetPrinter( pOldPrinter );
536 CalcOutputFactor(); // also with the new settings
540 if (nDiffFlags & SFX_PRINTER_OPTIONS)
542 aDocument.SetPrintOptions(); //! aus neuem Printer ???
545 if (nDiffFlags & (SFX_PRINTER_CHG_ORIENTATION | SFX_PRINTER_CHG_SIZE))
547 String aStyle = aDocument.GetPageStyle( GetCurTab() );
548 ScStyleSheetPool* pStPl = aDocument.GetStyleSheetPool();
549 SfxStyleSheet* pStyleSheet = (SfxStyleSheet*)pStPl->Find(aStyle, SFX_STYLE_FAMILY_PAGE);
550 if (pStyleSheet)
552 SfxItemSet& rSet = pStyleSheet->GetItemSet();
554 if (nDiffFlags & SFX_PRINTER_CHG_ORIENTATION)
556 const SvxPageItem& rOldItem = (const SvxPageItem&)rSet.Get(ATTR_PAGE);
557 BOOL bWasLand = rOldItem.IsLandscape();
558 BOOL bNewLand = ( pNewPrinter->GetOrientation() == ORIENTATION_LANDSCAPE );
559 if (bNewLand != bWasLand)
561 SvxPageItem aNewItem( rOldItem );
562 aNewItem.SetLandscape( bNewLand );
563 rSet.Put( aNewItem );
565 // Groesse umdrehen
566 Size aOldSize = ((const SvxSizeItem&)rSet.Get(ATTR_PAGE_SIZE)).GetSize();
567 Size aNewSize(aOldSize.Height(),aOldSize.Width());
568 SvxSizeItem aNewSItem(ATTR_PAGE_SIZE,aNewSize);
569 rSet.Put( aNewSItem );
572 if (nDiffFlags & SFX_PRINTER_CHG_SIZE)
574 SvxSizeItem aPaperSizeItem( ATTR_PAGE_SIZE, SvxPaperInfo::GetPaperSize(pNewPrinter) );
575 rSet.Put( aPaperSizeItem );
580 PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB,PAINT_ALL);
582 return 0;
585 //---------------------------------------------------------------------
587 ScChangeAction* ScDocShell::GetChangeAction( const ScAddress& rPos )
589 ScChangeTrack* pTrack = GetDocument()->GetChangeTrack();
590 if (!pTrack)
591 return NULL;
593 SCTAB nTab = rPos.Tab();
595 const ScChangeAction* pFound = NULL;
596 const ScChangeAction* pFoundContent = NULL;
597 const ScChangeAction* pFoundMove = NULL;
598 long nModified = 0;
599 const ScChangeAction* pAction = pTrack->GetFirst();
600 while (pAction)
602 ScChangeActionType eType = pAction->GetType();
603 //! ScViewUtil::IsActionShown( *pAction, *pSettings, *pDoc )...
604 if ( pAction->IsVisible() && eType != SC_CAT_DELETE_TABS )
606 const ScBigRange& rBig = pAction->GetBigRange();
607 if ( rBig.aStart.Tab() == nTab )
609 ScRange aRange = rBig.MakeRange();
611 if ( eType == SC_CAT_DELETE_ROWS )
612 aRange.aEnd.SetRow( aRange.aStart.Row() );
613 else if ( eType == SC_CAT_DELETE_COLS )
614 aRange.aEnd.SetCol( aRange.aStart.Col() );
616 if ( aRange.In( rPos ) )
618 pFound = pAction; // der letzte gewinnt
619 switch ( pAction->GetType() )
621 case SC_CAT_CONTENT :
622 pFoundContent = pAction;
623 break;
624 case SC_CAT_MOVE :
625 pFoundMove = pAction;
626 break;
627 default:
629 // added to avoid warnings
632 ++nModified;
635 if ( pAction->GetType() == SC_CAT_MOVE )
637 ScRange aRange =
638 ((const ScChangeActionMove*)pAction)->
639 GetFromRange().MakeRange();
640 if ( aRange.In( rPos ) )
642 pFound = pAction;
643 ++nModified;
647 pAction = pAction->GetNext();
650 return (ScChangeAction*)pFound;
653 void ScDocShell::SetChangeComment( ScChangeAction* pAction, const String& rComment )
655 if (pAction)
657 pAction->SetComment( rComment );
658 //! Undo ???
659 SetDocumentModified();
661 // Dialog-Notify
662 ScChangeTrack* pTrack = GetDocument()->GetChangeTrack();
663 if (pTrack)
665 ULONG nNumber = pAction->GetActionNumber();
666 pTrack->NotifyModified( SC_CTM_CHANGE, nNumber, nNumber );
671 void ScDocShell::ExecuteChangeCommentDialog( ScChangeAction* pAction, Window* pParent,BOOL bPrevNext)
673 if (!pAction) return; // ohne Aktion ist nichts..
675 String aComment = pAction->GetComment();
676 String aAuthor = pAction->GetUser();
678 DateTime aDT = pAction->GetDateTime();
679 String aDate = ScGlobal::pLocaleData->getDate( aDT );
680 aDate += ' ';
681 aDate += ScGlobal::pLocaleData->getTime( aDT, FALSE, FALSE );
683 SfxItemSet aSet( GetPool(),
684 SID_ATTR_POSTIT_AUTHOR, SID_ATTR_POSTIT_AUTHOR,
685 SID_ATTR_POSTIT_DATE, SID_ATTR_POSTIT_DATE,
686 SID_ATTR_POSTIT_TEXT, SID_ATTR_POSTIT_TEXT,
687 0 );
689 aSet.Put( SvxPostItTextItem ( aComment, SID_ATTR_POSTIT_TEXT ) );
690 aSet.Put( SvxPostItAuthorItem( aAuthor, SID_ATTR_POSTIT_AUTHOR ) );
691 aSet.Put( SvxPostItDateItem ( aDate, SID_ATTR_POSTIT_DATE ) );
693 ScRedComDialog* pDlg = new ScRedComDialog( pParent, aSet,this,pAction,bPrevNext);
695 pDlg->Execute();
697 delete pDlg;
700 //---------------------------------------------------------------------
702 void ScDocShell::CompareDocument( ScDocument& rOtherDoc )
704 ScChangeTrack* pTrack = aDocument.GetChangeTrack();
705 if ( pTrack && pTrack->GetFirst() )
707 //! Changes vorhanden -> Nachfrage ob geloescht werden soll
710 aDocument.EndChangeTracking();
711 aDocument.StartChangeTracking();
713 String aOldUser;
714 pTrack = aDocument.GetChangeTrack();
715 if ( pTrack )
717 aOldUser = pTrack->GetUser();
719 // check if comparing to same document
721 String aThisFile;
722 const SfxMedium* pThisMed = GetMedium();
723 if (pThisMed)
724 aThisFile = pThisMed->GetName();
725 String aOtherFile;
726 SfxObjectShell* pOtherSh = rOtherDoc.GetDocumentShell();
727 if (pOtherSh)
729 const SfxMedium* pOtherMed = pOtherSh->GetMedium();
730 if (pOtherMed)
731 aOtherFile = pOtherMed->GetName();
733 BOOL bSameDoc = ( aThisFile == aOtherFile && aThisFile.Len() );
734 if ( !bSameDoc )
736 // create change actions from comparing with the name of the user
737 // who last saved the document
738 // (only if comparing different documents)
740 using namespace ::com::sun::star;
741 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
742 GetModel(), uno::UNO_QUERY_THROW);
743 uno::Reference<document::XDocumentProperties> xDocProps(
744 xDPS->getDocumentProperties());
745 DBG_ASSERT(xDocProps.is(), "no DocumentProperties");
746 String aDocUser = xDocProps->getModifiedBy();
748 if ( aDocUser.Len() )
749 pTrack->SetUser( aDocUser );
753 aDocument.CompareDocument( rOtherDoc );
755 pTrack = aDocument.GetChangeTrack();
756 if ( pTrack )
757 pTrack->SetUser( aOldUser );
759 PostPaintGridAll();
760 SetDocumentModified();
763 //---------------------------------------------------------------------
765 // Merge (Aenderungen zusammenfuehren)
767 //---------------------------------------------------------------------
769 inline BOOL lcl_Equal( const ScChangeAction* pA, const ScChangeAction* pB, BOOL bIgnore100Sec )
771 return pA && pB &&
772 pA->GetActionNumber() == pB->GetActionNumber() &&
773 pA->GetType() == pB->GetType() &&
774 pA->GetUser() == pB->GetUser() &&
775 (bIgnore100Sec ?
776 pA->GetDateTimeUTC().IsEqualIgnore100Sec( pB->GetDateTimeUTC() ) :
777 pA->GetDateTimeUTC() == pB->GetDateTimeUTC());
778 // State nicht vergleichen, falls eine alte Aenderung akzeptiert wurde
781 bool lcl_FindAction( ScDocument* pDoc, const ScChangeAction* pAction, ScDocument* pSearchDoc, const ScChangeAction* pFirstSearchAction, const ScChangeAction* pLastSearchAction, BOOL bIgnore100Sec )
783 if ( !pDoc || !pAction || !pSearchDoc || !pFirstSearchAction || !pLastSearchAction )
785 return false;
788 ULONG nLastSearchAction = pLastSearchAction->GetActionNumber();
789 const ScChangeAction* pA = pFirstSearchAction;
790 while ( pA && pA->GetActionNumber() <= nLastSearchAction )
792 if ( pAction->GetType() == pA->GetType() &&
793 pAction->GetUser() == pA->GetUser() &&
794 (bIgnore100Sec ?
795 pAction->GetDateTimeUTC().IsEqualIgnore100Sec( pA->GetDateTimeUTC() ) :
796 pAction->GetDateTimeUTC() == pA->GetDateTimeUTC() ) &&
797 pAction->GetBigRange() == pA->GetBigRange() )
799 String aActionDesc;
800 pAction->GetDescription( aActionDesc, pDoc, TRUE );
801 String aADesc;
802 pA->GetDescription( aADesc, pSearchDoc, TRUE );
803 if ( aActionDesc.Equals( aADesc ) )
805 DBG_ERROR( "lcl_FindAction(): found equal action!" );
806 return true;
809 pA = pA->GetNext();
812 return false;
815 void ScDocShell::MergeDocument( ScDocument& rOtherDoc, bool bShared, bool bCheckDuplicates, ULONG nOffset, ScChangeActionMergeMap* pMergeMap, bool bInverseMap )
817 ScTabViewShell* pViewSh = GetBestViewShell( FALSE ); //! Funktionen an die DocShell
818 if (!pViewSh)
819 return;
821 ScChangeTrack* pSourceTrack = rOtherDoc.GetChangeTrack();
822 if (!pSourceTrack)
823 return; //! nichts zu tun - Fehlermeldung?
825 ScChangeTrack* pThisTrack = aDocument.GetChangeTrack();
826 if ( !pThisTrack )
827 { // anschalten
828 aDocument.StartChangeTracking();
829 pThisTrack = aDocument.GetChangeTrack();
830 DBG_ASSERT(pThisTrack,"ChangeTracking nicht angeschaltet?");
831 if ( !bShared )
833 // #51138# visuelles RedLining einschalten
834 ScChangeViewSettings aChangeViewSet;
835 aChangeViewSet.SetShowChanges(TRUE);
836 aDocument.SetChangeViewSettings(aChangeViewSet);
840 // #97286# include 100th seconds in compare?
841 BOOL bIgnore100Sec = !pSourceTrack->IsTime100thSeconds() ||
842 !pThisTrack->IsTime100thSeconds();
844 // gemeinsame Ausgangsposition suchen
845 ULONG nFirstNewNumber = 0;
846 const ScChangeAction* pSourceAction = pSourceTrack->GetFirst();
847 const ScChangeAction* pThisAction = pThisTrack->GetFirst();
848 // skip identical actions
849 while ( lcl_Equal( pSourceAction, pThisAction, bIgnore100Sec ) )
851 nFirstNewNumber = pSourceAction->GetActionNumber() + 1;
852 pSourceAction = pSourceAction->GetNext();
853 pThisAction = pThisAction->GetNext();
855 // pSourceAction und pThisAction zeigen jetzt auf die ersten "eigenen" Aktionen
856 // Die gemeinsamen Aktionen davor interessieren ueberhaupt nicht
858 //! Abfrage, ob die Dokumente vor dem Change-Tracking gleich waren !!!
861 const ScChangeAction* pFirstMergeAction = pSourceAction;
862 const ScChangeAction* pFirstSearchAction = pThisAction;
864 // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
865 const ScChangeAction* pLastSearchAction = pThisTrack->GetLast();
867 // MergeChangeData aus den folgenden Aktionen erzeugen
868 ULONG nNewActionCount = 0;
869 const ScChangeAction* pCount = pSourceAction;
870 while ( pCount )
872 if ( bShared || !ScChangeTrack::MergeIgnore( *pCount, nFirstNewNumber ) )
873 ++nNewActionCount;
874 pCount = pCount->GetNext();
876 if (!nNewActionCount)
877 return; //! nichts zu tun - Fehlermeldung?
878 // ab hier kein return mehr
880 ScProgress aProgress( this,
881 String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("...")),
882 nNewActionCount );
884 ULONG nLastMergeAction = pSourceTrack->GetLast()->GetActionNumber();
885 // UpdateReference-Undo, gueltige Referenzen fuer den letzten gemeinsamen Zustand
886 pSourceTrack->MergePrepare( (ScChangeAction*) pFirstMergeAction, bShared );
888 // MergeChangeData an alle noch folgenden Aktionen in diesem Dokument anpassen
889 // -> Referenzen gueltig fuer dieses Dokument
890 while ( pThisAction )
892 // #i87049# [Collaboration] Conflict between delete row and insert content is not merged correctly
893 if ( !bShared || !ScChangeTrack::MergeIgnore( *pThisAction, nFirstNewNumber ) )
895 ScChangeActionType eType = pThisAction->GetType();
896 switch ( eType )
898 case SC_CAT_INSERT_COLS :
899 case SC_CAT_INSERT_ROWS :
900 case SC_CAT_INSERT_TABS :
901 pSourceTrack->AppendInsert( pThisAction->GetBigRange().MakeRange() );
902 break;
903 case SC_CAT_DELETE_COLS :
904 case SC_CAT_DELETE_ROWS :
905 case SC_CAT_DELETE_TABS :
907 const ScChangeActionDel* pDel = (const ScChangeActionDel*) pThisAction;
908 if ( pDel->IsTopDelete() && !pDel->IsTabDeleteCol() )
909 { // deleted Table enthaelt deleted Cols, die nicht
910 ULONG nStart, nEnd;
911 pSourceTrack->AppendDeleteRange(
912 pDel->GetOverAllRange().MakeRange(), NULL, nStart, nEnd );
915 break;
916 case SC_CAT_MOVE :
918 const ScChangeActionMove* pMove = (const ScChangeActionMove*) pThisAction;
919 pSourceTrack->AppendMove( pMove->GetFromRange().MakeRange(),
920 pMove->GetBigRange().MakeRange(), NULL );
922 break;
923 default:
925 // added to avoid warnings
929 pThisAction = pThisAction->GetNext();
932 LockPaint(); // #i73877# no repainting after each action
934 // MergeChangeData in das aktuelle Dokument uebernehmen
935 BOOL bHasRejected = FALSE;
936 String aOldUser = pThisTrack->GetUser();
937 pThisTrack->SetUseFixDateTime( TRUE );
938 ScMarkData& rMarkData = pViewSh->GetViewData()->GetMarkData();
939 ScMarkData aOldMarkData( rMarkData );
940 pSourceAction = pFirstMergeAction;
941 while ( pSourceAction && pSourceAction->GetActionNumber() <= nLastMergeAction )
943 bool bMergeAction = false;
944 if ( bShared )
946 if ( !bCheckDuplicates || !lcl_FindAction( &rOtherDoc, pSourceAction, &aDocument, pFirstSearchAction, pLastSearchAction, bIgnore100Sec ) )
948 bMergeAction = true;
951 else
953 if ( !ScChangeTrack::MergeIgnore( *pSourceAction, nFirstNewNumber ) )
955 bMergeAction = true;
959 if ( bMergeAction )
961 ScChangeActionType eSourceType = pSourceAction->GetType();
962 if ( !bShared && pSourceAction->IsDeletedIn() )
964 //! muss hier noch festgestellt werden, ob wirklich in
965 //! _diesem_ Dokument geloescht?
967 // liegt in einem Bereich, der in diesem Dokument geloescht wurde
968 // -> wird weggelassen
969 //! ??? Loesch-Aktion rueckgaengig machen ???
970 //! ??? Aktion irgendwo anders speichern ???
971 #ifndef PRODUCT
972 String aValue;
973 if ( eSourceType == SC_CAT_CONTENT )
974 ((const ScChangeActionContent*)pSourceAction)->GetNewString( aValue );
975 ByteString aError( aValue, gsl_getSystemTextEncoding() );
976 aError += " weggelassen";
977 DBG_ERROR( aError.GetBuffer() );
978 #endif
980 else
982 //! Datum/Autor/Kommentar der Source-Aktion uebernehmen!
984 pThisTrack->SetUser( pSourceAction->GetUser() );
985 pThisTrack->SetFixDateTimeUTC( pSourceAction->GetDateTimeUTC() );
986 ULONG nOldActionMax = pThisTrack->GetActionMax();
988 bool bExecute = true;
989 ULONG nReject = pSourceAction->GetRejectAction();
990 if ( nReject )
992 if ( bShared )
994 if ( nReject >= nFirstNewNumber )
996 nReject += nOffset;
998 ScChangeAction* pOldAction = pThisTrack->GetAction( nReject );
999 if ( pOldAction && pOldAction->IsVirgin() )
1001 pThisTrack->Reject( pOldAction );
1002 bHasRejected = TRUE;
1003 bExecute = false;
1006 else
1008 // alte Aktion (aus den gemeinsamen) ablehnen
1009 ScChangeAction* pOldAction = pThisTrack->GetAction( nReject );
1010 if (pOldAction && pOldAction->GetState() == SC_CAS_VIRGIN)
1012 //! was passiert bei Aktionen, die in diesem Dokument accepted worden sind???
1013 //! Fehlermeldung oder was???
1014 //! oder Reject-Aenderung normal ausfuehren
1016 pThisTrack->Reject(pOldAction);
1017 bHasRejected = TRUE; // fuer Paint
1019 bExecute = false;
1023 if ( bExecute )
1025 // normal ausfuehren
1026 ScRange aSourceRange = pSourceAction->GetBigRange().MakeRange();
1027 rMarkData.SelectOneTable( aSourceRange.aStart.Tab() );
1028 switch ( eSourceType )
1030 case SC_CAT_CONTENT:
1032 //! Test, ob es ganz unten im Dokument war, dann automatisches
1033 //! Zeilen-Einfuegen ???
1035 DBG_ASSERT( aSourceRange.aStart == aSourceRange.aEnd, "huch?" );
1036 ScAddress aPos = aSourceRange.aStart;
1037 String aValue;
1038 ((const ScChangeActionContent*)pSourceAction)->GetNewString( aValue );
1039 BYTE eMatrix = MM_NONE;
1040 const ScBaseCell* pCell = ((const ScChangeActionContent*)pSourceAction)->GetNewCell();
1041 if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA )
1042 eMatrix = ((const ScFormulaCell*)pCell)->GetMatrixFlag();
1043 switch ( eMatrix )
1045 case MM_NONE :
1046 pViewSh->EnterData( aPos.Col(), aPos.Row(), aPos.Tab(), aValue );
1047 break;
1048 case MM_FORMULA :
1050 SCCOL nCols;
1051 SCROW nRows;
1052 ((const ScFormulaCell*)pCell)->GetMatColsRows( nCols, nRows );
1053 aSourceRange.aEnd.SetCol( aPos.Col() + nCols - 1 );
1054 aSourceRange.aEnd.SetRow( aPos.Row() + nRows - 1 );
1055 aValue.Erase( 0, 1 );
1056 aValue.Erase( aValue.Len()-1, 1 );
1057 GetDocFunc().EnterMatrix( aSourceRange,
1058 NULL, NULL, aValue, FALSE, FALSE,
1059 EMPTY_STRING, formula::FormulaGrammar::GRAM_DEFAULT );
1061 break;
1062 case MM_REFERENCE : // do nothing
1063 break;
1064 case MM_FAKE :
1065 DBG_WARNING( "MergeDocument: MatrixFlag MM_FAKE" );
1066 pViewSh->EnterData( aPos.Col(), aPos.Row(), aPos.Tab(), aValue );
1067 break;
1068 default:
1069 DBG_ERROR( "MergeDocument: unknown MatrixFlag" );
1072 break;
1073 case SC_CAT_INSERT_TABS :
1075 String aName;
1076 aDocument.CreateValidTabName( aName );
1077 GetDocFunc().InsertTable( aSourceRange.aStart.Tab(), aName, TRUE, FALSE );
1079 break;
1080 case SC_CAT_INSERT_ROWS:
1081 GetDocFunc().InsertCells( aSourceRange, NULL, INS_INSROWS, TRUE, FALSE );
1082 break;
1083 case SC_CAT_INSERT_COLS:
1084 GetDocFunc().InsertCells( aSourceRange, NULL, INS_INSCOLS, TRUE, FALSE );
1085 break;
1086 case SC_CAT_DELETE_TABS :
1087 GetDocFunc().DeleteTable( aSourceRange.aStart.Tab(), TRUE, FALSE );
1088 break;
1089 case SC_CAT_DELETE_ROWS:
1091 const ScChangeActionDel* pDel = (const ScChangeActionDel*) pSourceAction;
1092 if ( pDel->IsTopDelete() )
1094 aSourceRange = pDel->GetOverAllRange().MakeRange();
1095 GetDocFunc().DeleteCells( aSourceRange, NULL, DEL_DELROWS, TRUE, FALSE );
1098 break;
1099 case SC_CAT_DELETE_COLS:
1101 const ScChangeActionDel* pDel = (const ScChangeActionDel*) pSourceAction;
1102 if ( pDel->IsTopDelete() && !pDel->IsTabDeleteCol() )
1103 { // deleted Table enthaelt deleted Cols, die nicht
1104 aSourceRange = pDel->GetOverAllRange().MakeRange();
1105 GetDocFunc().DeleteCells( aSourceRange, NULL, DEL_DELCOLS, TRUE, FALSE );
1108 break;
1109 case SC_CAT_MOVE :
1111 const ScChangeActionMove* pMove = (const ScChangeActionMove*) pSourceAction;
1112 ScRange aFromRange( pMove->GetFromRange().MakeRange() );
1113 GetDocFunc().MoveBlock( aFromRange,
1114 aSourceRange.aStart, TRUE, TRUE, FALSE, FALSE );
1116 break;
1117 default:
1119 // added to avoid warnings
1123 const String& rComment = pSourceAction->GetComment();
1124 if ( rComment.Len() )
1126 ScChangeAction* pAct = pThisTrack->GetLast();
1127 if ( pAct && pAct->GetActionNumber() > nOldActionMax )
1128 pAct->SetComment( rComment );
1129 #ifndef PRODUCT
1130 else
1131 DBG_ERROR( "MergeDocument: wohin mit dem Kommentar?!?" );
1132 #endif
1135 // Referenzen anpassen
1136 pSourceTrack->MergeOwn( (ScChangeAction*) pSourceAction, nFirstNewNumber, bShared );
1138 // merge action state
1139 if ( bShared && !pSourceAction->IsRejected() )
1141 ScChangeAction* pAct = pThisTrack->GetLast();
1142 if ( pAct && pAct->GetActionNumber() > nOldActionMax )
1144 pThisTrack->MergeActionState( pAct, pSourceAction );
1148 // fill merge map
1149 if ( bShared && pMergeMap )
1151 ScChangeAction* pAct = pThisTrack->GetLast();
1152 if ( pAct && pAct->GetActionNumber() > nOldActionMax )
1154 ULONG nActionMax = pAct->GetActionNumber();
1155 ULONG nActionCount = nActionMax - nOldActionMax;
1156 ULONG nAction = nActionMax - nActionCount + 1;
1157 ULONG nSourceAction = pSourceAction->GetActionNumber() - nActionCount + 1;
1158 while ( nAction <= nActionMax )
1160 if ( bInverseMap )
1162 (*pMergeMap)[ nAction++ ] = nSourceAction++;
1164 else
1166 (*pMergeMap)[ nSourceAction++ ] = nAction++;
1172 aProgress.SetStateCountDown( --nNewActionCount );
1174 pSourceAction = pSourceAction->GetNext();
1177 rMarkData = aOldMarkData;
1178 pThisTrack->SetUser(aOldUser);
1179 pThisTrack->SetUseFixDateTime( FALSE );
1181 pSourceTrack->Clear(); //! der ist jetzt verhunzt
1183 if (bHasRejected)
1184 PostPaintGridAll(); // Reject() paintet nicht selber
1186 UnlockPaint();
1189 bool ScDocShell::MergeSharedDocument( ScDocShell* pSharedDocShell )
1191 if ( !pSharedDocShell )
1193 return false;
1196 ScChangeTrack* pThisTrack = aDocument.GetChangeTrack();
1197 if ( !pThisTrack )
1199 return false;
1202 ScDocument& rSharedDoc = *( pSharedDocShell->GetDocument() );
1203 ScChangeTrack* pSharedTrack = rSharedDoc.GetChangeTrack();
1204 if ( !pSharedTrack )
1206 return false;
1209 #if DEBUG_CHANGETRACK
1210 ::rtl::OUString aMessage = ::rtl::OUString::createFromAscii( "\nbefore merge:\n" );
1211 aMessage += pThisTrack->ToString();
1212 ::rtl::OString aMsg = ::rtl::OUStringToOString( aMessage, RTL_TEXTENCODING_UTF8 );
1213 OSL_ENSURE( false, aMsg.getStr() );
1214 //fprintf( stdout, "%s ", aMsg.getStr() );
1215 //fflush( stdout );
1216 #endif // DEBUG_CHANGETRACK
1218 // reset show changes
1219 ScChangeViewSettings aChangeViewSet;
1220 aChangeViewSet.SetShowChanges( FALSE );
1221 aDocument.SetChangeViewSettings( aChangeViewSet );
1223 // find first merge action in this document
1224 BOOL bIgnore100Sec = !pThisTrack->IsTime100thSeconds() || !pSharedTrack->IsTime100thSeconds();
1225 ScChangeAction* pThisAction = pThisTrack->GetFirst();
1226 ScChangeAction* pSharedAction = pSharedTrack->GetFirst();
1227 while ( lcl_Equal( pThisAction, pSharedAction, bIgnore100Sec ) )
1229 pThisAction = pThisAction->GetNext();
1230 pSharedAction = pSharedAction->GetNext();
1233 if ( pSharedAction )
1235 if ( pThisAction )
1237 // merge own changes into shared document
1238 ULONG nActStartShared = pSharedAction->GetActionNumber();
1239 ULONG nActEndShared = pSharedTrack->GetActionMax();
1240 ScDocument* pTmpDoc = new ScDocument;
1241 for ( sal_Int32 nIndex = 0; nIndex < aDocument.GetTableCount(); ++nIndex )
1243 String sTabName;
1244 pTmpDoc->CreateValidTabName( sTabName );
1245 pTmpDoc->InsertTab( SC_TAB_APPEND, sTabName );
1247 aDocument.GetChangeTrack()->Clone( pTmpDoc );
1248 ScChangeActionMergeMap aOwnInverseMergeMap;
1249 pSharedDocShell->MergeDocument( *pTmpDoc, true, true, 0, &aOwnInverseMergeMap, true );
1250 delete pTmpDoc;
1251 ULONG nActStartOwn = nActEndShared + 1;
1252 ULONG nActEndOwn = pSharedTrack->GetActionMax();
1254 // find conflicts
1255 ScConflictsList aConflictsList;
1256 ScConflictsFinder aFinder( pSharedTrack, nActStartShared, nActEndShared, nActStartOwn, nActEndOwn, aConflictsList );
1257 if ( aFinder.Find() )
1259 ScConflictsListHelper::TransformConflictsList( aConflictsList, NULL, &aOwnInverseMergeMap );
1260 bool bLoop = true;
1261 while ( bLoop )
1263 bLoop = false;
1264 ScConflictsDlg aDlg( GetActiveDialogParent(), GetViewData(), &rSharedDoc, aConflictsList );
1265 if ( aDlg.Execute() == RET_CANCEL )
1267 QueryBox aBox( GetActiveDialogParent(), WinBits( WB_YES_NO | WB_DEF_YES ),
1268 ScGlobal::GetRscString( STR_DOC_WILLNOTBESAVED ) );
1269 if ( aBox.Execute() == RET_YES )
1271 return false;
1273 else
1275 bLoop = true;
1281 // undo own changes in shared document
1282 pSharedTrack->Undo( nActStartOwn, nActEndOwn );
1284 // clone change track for merging into own document
1285 pTmpDoc = new ScDocument;
1286 for ( sal_Int32 nIndex = 0; nIndex < aDocument.GetTableCount(); ++nIndex )
1288 String sTabName;
1289 pTmpDoc->CreateValidTabName( sTabName );
1290 pTmpDoc->InsertTab( SC_TAB_APPEND, sTabName );
1292 pThisTrack->Clone( pTmpDoc );
1294 // undo own changes since last save in own document
1295 ULONG nStartShared = pThisAction->GetActionNumber();
1296 ScChangeAction* pAction = pThisTrack->GetLast();
1297 while ( pAction && pAction->GetActionNumber() >= nStartShared )
1299 pThisTrack->Reject( pAction, true );
1300 pAction = pAction->GetPrev();
1303 // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
1304 pThisTrack->Undo( nStartShared, pThisTrack->GetActionMax(), true );
1306 // merge shared changes into own document
1307 ScChangeActionMergeMap aSharedMergeMap;
1308 MergeDocument( rSharedDoc, true, true, 0, &aSharedMergeMap );
1309 ULONG nEndShared = pThisTrack->GetActionMax();
1311 // resolve conflicts for shared non-content actions
1312 if ( !aConflictsList.empty() )
1314 ScConflictsListHelper::TransformConflictsList( aConflictsList, &aSharedMergeMap, NULL );
1315 ScConflictsResolver aResolver( pThisTrack, aConflictsList );
1316 pAction = pThisTrack->GetAction( nEndShared );
1317 while ( pAction && pAction->GetActionNumber() >= nStartShared )
1319 aResolver.HandleAction( pAction, true /*bIsSharedAction*/,
1320 false /*bHandleContentAction*/, true /*bHandleNonContentAction*/ );
1321 pAction = pAction->GetPrev();
1324 nEndShared = pThisTrack->GetActionMax();
1326 // only show changes from shared document
1327 aChangeViewSet.SetShowChanges( TRUE );
1328 aChangeViewSet.SetShowAccepted( TRUE );
1329 aChangeViewSet.SetHasActionRange( true );
1330 aChangeViewSet.SetTheActionRange( nStartShared, nEndShared );
1331 aDocument.SetChangeViewSettings( aChangeViewSet );
1333 // merge own changes back into own document
1334 ULONG nStartOwn = nEndShared + 1;
1335 ScChangeActionMergeMap aOwnMergeMap;
1336 MergeDocument( *pTmpDoc, true, true, nEndShared - nStartShared + 1, &aOwnMergeMap );
1337 delete pTmpDoc;
1338 ULONG nEndOwn = pThisTrack->GetActionMax();
1340 // resolve conflicts for shared content actions and own actions
1341 if ( !aConflictsList.empty() )
1343 ScConflictsListHelper::TransformConflictsList( aConflictsList, NULL, &aOwnMergeMap );
1344 ScConflictsResolver aResolver( pThisTrack, aConflictsList );
1345 pAction = pThisTrack->GetAction( nEndShared );
1346 while ( pAction && pAction->GetActionNumber() >= nStartShared )
1348 aResolver.HandleAction( pAction, true /*bIsSharedAction*/,
1349 true /*bHandleContentAction*/, false /*bHandleNonContentAction*/ );
1350 pAction = pAction->GetPrev();
1353 pAction = pThisTrack->GetAction( nEndOwn );
1354 while ( pAction && pAction->GetActionNumber() >= nStartOwn )
1356 aResolver.HandleAction( pAction, false /*bIsSharedAction*/,
1357 true /*bHandleContentAction*/, true /*bHandleNonContentAction*/ );
1358 pAction = pAction->GetPrev();
1361 nEndOwn = pThisTrack->GetActionMax();
1363 else
1365 // merge shared changes into own document
1366 ULONG nStartShared = pThisTrack->GetActionMax() + 1;
1367 MergeDocument( rSharedDoc, true, true );
1368 ULONG nEndShared = pThisTrack->GetActionMax();
1370 // only show changes from shared document
1371 aChangeViewSet.SetShowChanges( TRUE );
1372 aChangeViewSet.SetShowAccepted( TRUE );
1373 aChangeViewSet.SetHasActionRange( true );
1374 aChangeViewSet.SetTheActionRange( nStartShared, nEndShared );
1375 aDocument.SetChangeViewSettings( aChangeViewSet );
1378 // update view
1379 PostPaintExtras();
1380 PostPaintGridAll();
1382 InfoBox aInfoBox( GetActiveDialogParent(), ScGlobal::GetRscString( STR_DOC_UPDATED ) );
1383 aInfoBox.Execute();
1386 #if DEBUG_CHANGETRACK
1387 aMessage = ::rtl::OUString::createFromAscii( "\nafter merge:\n" );
1388 aMessage += pThisTrack->ToString();
1389 aMsg = ::rtl::OUStringToOString( aMessage, RTL_TEXTENCODING_UTF8 );
1390 OSL_ENSURE( false, aMsg.getStr() );
1391 //fprintf( stdout, "%s ", aMsg.getStr() );
1392 //fflush( stdout );
1393 #endif // DEBUG_CHANGETRACK
1395 return ( pThisAction != NULL );