update dev300-m58
[ooovba.git] / sc / source / ui / docshell / docsh3.cxx
blobe88625e1018768e261f5430a311da56916bba669
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 if (nDiffFlags & SFX_PRINTER_PRINTER)
488 if ( aDocument.GetPrinter() != pNewPrinter )
490 aDocument.SetPrinter( pNewPrinter );
491 aDocument.SetPrintOptions();
493 // MT: Use UpdateFontList: Will use Printer fonts only if needed!
495 delete pImpl->pFontList;
496 pImpl->pFontList = new FontList( pNewPrinter, Application::GetDefaultDevice() );
497 SvxFontListItem aFontListItem( pImpl->pFontList, SID_ATTR_CHAR_FONTLIST );
498 PutItem( aFontListItem );
500 CalcOutputFactor();
502 if ( SC_MOD()->GetInputOptions().GetTextWysiwyg() )
503 UpdateFontList();
505 ScModule* pScMod = SC_MOD();
506 SfxViewFrame *pFrame = SfxViewFrame::GetFirst( this );
507 while (pFrame)
509 SfxViewShell* pSh = pFrame->GetViewShell();
510 if (pSh && pSh->ISA(ScTabViewShell))
512 ScTabViewShell* pViewSh = (ScTabViewShell*)pSh;
513 ScInputHandler* pInputHdl = pScMod->GetInputHdl(pViewSh);
514 if (pInputHdl)
515 pInputHdl->UpdateRefDevice();
517 pFrame = SfxViewFrame::GetNext( *pFrame, this );
521 else if (nDiffFlags & SFX_PRINTER_JOBSETUP)
523 SfxPrinter* pOldPrinter = aDocument.GetPrinter();
524 if (pOldPrinter)
526 pOldPrinter->SetJobSetup( pNewPrinter->GetJobSetup() );
528 // #i6706# Call SetPrinter with the old printer again, so the drawing layer
529 // RefDevice is set (calling ReformatAllTextObjects and rebuilding charts),
530 // because the JobSetup (printer device settings) may affect text layout.
531 aDocument.SetPrinter( pOldPrinter );
532 CalcOutputFactor(); // also with the new settings
536 if (nDiffFlags & SFX_PRINTER_OPTIONS)
538 aDocument.SetPrintOptions(); //! aus neuem Printer ???
541 if (nDiffFlags & (SFX_PRINTER_CHG_ORIENTATION | SFX_PRINTER_CHG_SIZE))
543 String aStyle = aDocument.GetPageStyle( GetCurTab() );
544 ScStyleSheetPool* pStPl = aDocument.GetStyleSheetPool();
545 SfxStyleSheet* pStyleSheet = (SfxStyleSheet*)pStPl->Find(aStyle, SFX_STYLE_FAMILY_PAGE);
546 if (pStyleSheet)
548 SfxItemSet& rSet = pStyleSheet->GetItemSet();
550 if (nDiffFlags & SFX_PRINTER_CHG_ORIENTATION)
552 const SvxPageItem& rOldItem = (const SvxPageItem&)rSet.Get(ATTR_PAGE);
553 BOOL bWasLand = rOldItem.IsLandscape();
554 BOOL bNewLand = ( pNewPrinter->GetOrientation() == ORIENTATION_LANDSCAPE );
555 if (bNewLand != bWasLand)
557 SvxPageItem aNewItem( rOldItem );
558 aNewItem.SetLandscape( bNewLand );
559 rSet.Put( aNewItem );
561 // Groesse umdrehen
562 Size aOldSize = ((const SvxSizeItem&)rSet.Get(ATTR_PAGE_SIZE)).GetSize();
563 Size aNewSize(aOldSize.Height(),aOldSize.Width());
564 SvxSizeItem aNewSItem(ATTR_PAGE_SIZE,aNewSize);
565 rSet.Put( aNewSItem );
568 if (nDiffFlags & SFX_PRINTER_CHG_SIZE)
570 SvxSizeItem aPaperSizeItem( ATTR_PAGE_SIZE, SvxPaperInfo::GetPaperSize(pNewPrinter) );
571 rSet.Put( aPaperSizeItem );
576 PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB,PAINT_ALL);
578 return 0;
581 //---------------------------------------------------------------------
583 ScChangeAction* ScDocShell::GetChangeAction( const ScAddress& rPos )
585 ScChangeTrack* pTrack = GetDocument()->GetChangeTrack();
586 if (!pTrack)
587 return NULL;
589 SCTAB nTab = rPos.Tab();
591 const ScChangeAction* pFound = NULL;
592 const ScChangeAction* pFoundContent = NULL;
593 const ScChangeAction* pFoundMove = NULL;
594 long nModified = 0;
595 const ScChangeAction* pAction = pTrack->GetFirst();
596 while (pAction)
598 ScChangeActionType eType = pAction->GetType();
599 //! ScViewUtil::IsActionShown( *pAction, *pSettings, *pDoc )...
600 if ( pAction->IsVisible() && eType != SC_CAT_DELETE_TABS )
602 const ScBigRange& rBig = pAction->GetBigRange();
603 if ( rBig.aStart.Tab() == nTab )
605 ScRange aRange = rBig.MakeRange();
607 if ( eType == SC_CAT_DELETE_ROWS )
608 aRange.aEnd.SetRow( aRange.aStart.Row() );
609 else if ( eType == SC_CAT_DELETE_COLS )
610 aRange.aEnd.SetCol( aRange.aStart.Col() );
612 if ( aRange.In( rPos ) )
614 pFound = pAction; // der letzte gewinnt
615 switch ( pAction->GetType() )
617 case SC_CAT_CONTENT :
618 pFoundContent = pAction;
619 break;
620 case SC_CAT_MOVE :
621 pFoundMove = pAction;
622 break;
623 default:
625 // added to avoid warnings
628 ++nModified;
631 if ( pAction->GetType() == SC_CAT_MOVE )
633 ScRange aRange =
634 ((const ScChangeActionMove*)pAction)->
635 GetFromRange().MakeRange();
636 if ( aRange.In( rPos ) )
638 pFound = pAction;
639 ++nModified;
643 pAction = pAction->GetNext();
646 return (ScChangeAction*)pFound;
649 void ScDocShell::SetChangeComment( ScChangeAction* pAction, const String& rComment )
651 if (pAction)
653 pAction->SetComment( rComment );
654 //! Undo ???
655 SetDocumentModified();
657 // Dialog-Notify
658 ScChangeTrack* pTrack = GetDocument()->GetChangeTrack();
659 if (pTrack)
661 ULONG nNumber = pAction->GetActionNumber();
662 pTrack->NotifyModified( SC_CTM_CHANGE, nNumber, nNumber );
667 void ScDocShell::ExecuteChangeCommentDialog( ScChangeAction* pAction, Window* pParent,BOOL bPrevNext)
669 if (!pAction) return; // ohne Aktion ist nichts..
671 String aComment = pAction->GetComment();
672 String aAuthor = pAction->GetUser();
674 DateTime aDT = pAction->GetDateTime();
675 String aDate = ScGlobal::pLocaleData->getDate( aDT );
676 aDate += ' ';
677 aDate += ScGlobal::pLocaleData->getTime( aDT, FALSE, FALSE );
679 SfxItemSet aSet( GetPool(),
680 SID_ATTR_POSTIT_AUTHOR, SID_ATTR_POSTIT_AUTHOR,
681 SID_ATTR_POSTIT_DATE, SID_ATTR_POSTIT_DATE,
682 SID_ATTR_POSTIT_TEXT, SID_ATTR_POSTIT_TEXT,
683 0 );
685 aSet.Put( SvxPostItTextItem ( aComment, SID_ATTR_POSTIT_TEXT ) );
686 aSet.Put( SvxPostItAuthorItem( aAuthor, SID_ATTR_POSTIT_AUTHOR ) );
687 aSet.Put( SvxPostItDateItem ( aDate, SID_ATTR_POSTIT_DATE ) );
689 ScRedComDialog* pDlg = new ScRedComDialog( pParent, aSet,this,pAction,bPrevNext);
691 pDlg->Execute();
693 delete pDlg;
696 //---------------------------------------------------------------------
698 void ScDocShell::CompareDocument( ScDocument& rOtherDoc )
700 ScChangeTrack* pTrack = aDocument.GetChangeTrack();
701 if ( pTrack && pTrack->GetFirst() )
703 //! Changes vorhanden -> Nachfrage ob geloescht werden soll
706 aDocument.EndChangeTracking();
707 aDocument.StartChangeTracking();
709 String aOldUser;
710 pTrack = aDocument.GetChangeTrack();
711 if ( pTrack )
713 aOldUser = pTrack->GetUser();
715 // check if comparing to same document
717 String aThisFile;
718 const SfxMedium* pThisMed = GetMedium();
719 if (pThisMed)
720 aThisFile = pThisMed->GetName();
721 String aOtherFile;
722 SfxObjectShell* pOtherSh = rOtherDoc.GetDocumentShell();
723 if (pOtherSh)
725 const SfxMedium* pOtherMed = pOtherSh->GetMedium();
726 if (pOtherMed)
727 aOtherFile = pOtherMed->GetName();
729 BOOL bSameDoc = ( aThisFile == aOtherFile && aThisFile.Len() );
730 if ( !bSameDoc )
732 // create change actions from comparing with the name of the user
733 // who last saved the document
734 // (only if comparing different documents)
736 using namespace ::com::sun::star;
737 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
738 GetModel(), uno::UNO_QUERY_THROW);
739 uno::Reference<document::XDocumentProperties> xDocProps(
740 xDPS->getDocumentProperties());
741 DBG_ASSERT(xDocProps.is(), "no DocumentProperties");
742 String aDocUser = xDocProps->getModifiedBy();
744 if ( aDocUser.Len() )
745 pTrack->SetUser( aDocUser );
749 aDocument.CompareDocument( rOtherDoc );
751 pTrack = aDocument.GetChangeTrack();
752 if ( pTrack )
753 pTrack->SetUser( aOldUser );
755 PostPaintGridAll();
756 SetDocumentModified();
759 //---------------------------------------------------------------------
761 // Merge (Aenderungen zusammenfuehren)
763 //---------------------------------------------------------------------
765 inline BOOL lcl_Equal( const ScChangeAction* pA, const ScChangeAction* pB, BOOL bIgnore100Sec )
767 return pA && pB &&
768 pA->GetActionNumber() == pB->GetActionNumber() &&
769 pA->GetType() == pB->GetType() &&
770 pA->GetUser() == pB->GetUser() &&
771 (bIgnore100Sec ?
772 pA->GetDateTimeUTC().IsEqualIgnore100Sec( pB->GetDateTimeUTC() ) :
773 pA->GetDateTimeUTC() == pB->GetDateTimeUTC());
774 // State nicht vergleichen, falls eine alte Aenderung akzeptiert wurde
777 bool lcl_FindAction( ScDocument* pDoc, const ScChangeAction* pAction, ScDocument* pSearchDoc, const ScChangeAction* pFirstSearchAction, const ScChangeAction* pLastSearchAction, BOOL bIgnore100Sec )
779 if ( !pDoc || !pAction || !pSearchDoc || !pFirstSearchAction || !pLastSearchAction )
781 return false;
784 ULONG nLastSearchAction = pLastSearchAction->GetActionNumber();
785 const ScChangeAction* pA = pFirstSearchAction;
786 while ( pA && pA->GetActionNumber() <= nLastSearchAction )
788 if ( pAction->GetType() == pA->GetType() &&
789 pAction->GetUser() == pA->GetUser() &&
790 (bIgnore100Sec ?
791 pAction->GetDateTimeUTC().IsEqualIgnore100Sec( pA->GetDateTimeUTC() ) :
792 pAction->GetDateTimeUTC() == pA->GetDateTimeUTC() ) &&
793 pAction->GetBigRange() == pA->GetBigRange() )
795 String aActionDesc;
796 pAction->GetDescription( aActionDesc, pDoc, TRUE );
797 String aADesc;
798 pA->GetDescription( aADesc, pSearchDoc, TRUE );
799 if ( aActionDesc.Equals( aADesc ) )
801 DBG_ERROR( "lcl_FindAction(): found equal action!" );
802 return true;
805 pA = pA->GetNext();
808 return false;
811 void ScDocShell::MergeDocument( ScDocument& rOtherDoc, bool bShared, bool bCheckDuplicates, ULONG nOffset, ScChangeActionMergeMap* pMergeMap, bool bInverseMap )
813 ScTabViewShell* pViewSh = GetBestViewShell( FALSE ); //! Funktionen an die DocShell
814 if (!pViewSh)
815 return;
817 ScChangeTrack* pSourceTrack = rOtherDoc.GetChangeTrack();
818 if (!pSourceTrack)
819 return; //! nichts zu tun - Fehlermeldung?
821 ScChangeTrack* pThisTrack = aDocument.GetChangeTrack();
822 if ( !pThisTrack )
823 { // anschalten
824 aDocument.StartChangeTracking();
825 pThisTrack = aDocument.GetChangeTrack();
826 DBG_ASSERT(pThisTrack,"ChangeTracking nicht angeschaltet?");
827 if ( !bShared )
829 // #51138# visuelles RedLining einschalten
830 ScChangeViewSettings aChangeViewSet;
831 aChangeViewSet.SetShowChanges(TRUE);
832 aDocument.SetChangeViewSettings(aChangeViewSet);
836 // #97286# include 100th seconds in compare?
837 BOOL bIgnore100Sec = !pSourceTrack->IsTime100thSeconds() ||
838 !pThisTrack->IsTime100thSeconds();
840 // gemeinsame Ausgangsposition suchen
841 ULONG nFirstNewNumber = 0;
842 const ScChangeAction* pSourceAction = pSourceTrack->GetFirst();
843 const ScChangeAction* pThisAction = pThisTrack->GetFirst();
844 // skip identical actions
845 while ( lcl_Equal( pSourceAction, pThisAction, bIgnore100Sec ) )
847 nFirstNewNumber = pSourceAction->GetActionNumber() + 1;
848 pSourceAction = pSourceAction->GetNext();
849 pThisAction = pThisAction->GetNext();
851 // pSourceAction und pThisAction zeigen jetzt auf die ersten "eigenen" Aktionen
852 // Die gemeinsamen Aktionen davor interessieren ueberhaupt nicht
854 //! Abfrage, ob die Dokumente vor dem Change-Tracking gleich waren !!!
857 const ScChangeAction* pFirstMergeAction = pSourceAction;
858 const ScChangeAction* pFirstSearchAction = pThisAction;
860 // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
861 const ScChangeAction* pLastSearchAction = pThisTrack->GetLast();
863 // MergeChangeData aus den folgenden Aktionen erzeugen
864 ULONG nNewActionCount = 0;
865 const ScChangeAction* pCount = pSourceAction;
866 while ( pCount )
868 if ( bShared || !ScChangeTrack::MergeIgnore( *pCount, nFirstNewNumber ) )
869 ++nNewActionCount;
870 pCount = pCount->GetNext();
872 if (!nNewActionCount)
873 return; //! nichts zu tun - Fehlermeldung?
874 // ab hier kein return mehr
876 ScProgress aProgress( this,
877 String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("...")),
878 nNewActionCount );
880 ULONG nLastMergeAction = pSourceTrack->GetLast()->GetActionNumber();
881 // UpdateReference-Undo, gueltige Referenzen fuer den letzten gemeinsamen Zustand
882 pSourceTrack->MergePrepare( (ScChangeAction*) pFirstMergeAction, bShared );
884 // MergeChangeData an alle noch folgenden Aktionen in diesem Dokument anpassen
885 // -> Referenzen gueltig fuer dieses Dokument
886 while ( pThisAction )
888 // #i87049# [Collaboration] Conflict between delete row and insert content is not merged correctly
889 if ( !bShared || !ScChangeTrack::MergeIgnore( *pThisAction, nFirstNewNumber ) )
891 ScChangeActionType eType = pThisAction->GetType();
892 switch ( eType )
894 case SC_CAT_INSERT_COLS :
895 case SC_CAT_INSERT_ROWS :
896 case SC_CAT_INSERT_TABS :
897 pSourceTrack->AppendInsert( pThisAction->GetBigRange().MakeRange() );
898 break;
899 case SC_CAT_DELETE_COLS :
900 case SC_CAT_DELETE_ROWS :
901 case SC_CAT_DELETE_TABS :
903 const ScChangeActionDel* pDel = (const ScChangeActionDel*) pThisAction;
904 if ( pDel->IsTopDelete() && !pDel->IsTabDeleteCol() )
905 { // deleted Table enthaelt deleted Cols, die nicht
906 ULONG nStart, nEnd;
907 pSourceTrack->AppendDeleteRange(
908 pDel->GetOverAllRange().MakeRange(), NULL, nStart, nEnd );
911 break;
912 case SC_CAT_MOVE :
914 const ScChangeActionMove* pMove = (const ScChangeActionMove*) pThisAction;
915 pSourceTrack->AppendMove( pMove->GetFromRange().MakeRange(),
916 pMove->GetBigRange().MakeRange(), NULL );
918 break;
919 default:
921 // added to avoid warnings
925 pThisAction = pThisAction->GetNext();
928 LockPaint(); // #i73877# no repainting after each action
930 // MergeChangeData in das aktuelle Dokument uebernehmen
931 BOOL bHasRejected = FALSE;
932 String aOldUser = pThisTrack->GetUser();
933 pThisTrack->SetUseFixDateTime( TRUE );
934 ScMarkData& rMarkData = pViewSh->GetViewData()->GetMarkData();
935 ScMarkData aOldMarkData( rMarkData );
936 pSourceAction = pFirstMergeAction;
937 while ( pSourceAction && pSourceAction->GetActionNumber() <= nLastMergeAction )
939 bool bMergeAction = false;
940 if ( bShared )
942 if ( !bCheckDuplicates || !lcl_FindAction( &rOtherDoc, pSourceAction, &aDocument, pFirstSearchAction, pLastSearchAction, bIgnore100Sec ) )
944 bMergeAction = true;
947 else
949 if ( !ScChangeTrack::MergeIgnore( *pSourceAction, nFirstNewNumber ) )
951 bMergeAction = true;
955 if ( bMergeAction )
957 ScChangeActionType eSourceType = pSourceAction->GetType();
958 if ( !bShared && pSourceAction->IsDeletedIn() )
960 //! muss hier noch festgestellt werden, ob wirklich in
961 //! _diesem_ Dokument geloescht?
963 // liegt in einem Bereich, der in diesem Dokument geloescht wurde
964 // -> wird weggelassen
965 //! ??? Loesch-Aktion rueckgaengig machen ???
966 //! ??? Aktion irgendwo anders speichern ???
967 #ifndef PRODUCT
968 String aValue;
969 if ( eSourceType == SC_CAT_CONTENT )
970 ((const ScChangeActionContent*)pSourceAction)->GetNewString( aValue );
971 ByteString aError( aValue, gsl_getSystemTextEncoding() );
972 aError += " weggelassen";
973 DBG_ERROR( aError.GetBuffer() );
974 #endif
976 else
978 //! Datum/Autor/Kommentar der Source-Aktion uebernehmen!
980 pThisTrack->SetUser( pSourceAction->GetUser() );
981 pThisTrack->SetFixDateTimeUTC( pSourceAction->GetDateTimeUTC() );
982 ULONG nOldActionMax = pThisTrack->GetActionMax();
984 bool bExecute = true;
985 ULONG nReject = pSourceAction->GetRejectAction();
986 if ( nReject )
988 if ( bShared )
990 if ( nReject >= nFirstNewNumber )
992 nReject += nOffset;
994 ScChangeAction* pOldAction = pThisTrack->GetAction( nReject );
995 if ( pOldAction && pOldAction->IsVirgin() )
997 pThisTrack->Reject( pOldAction );
998 bHasRejected = TRUE;
999 bExecute = false;
1002 else
1004 // alte Aktion (aus den gemeinsamen) ablehnen
1005 ScChangeAction* pOldAction = pThisTrack->GetAction( nReject );
1006 if (pOldAction && pOldAction->GetState() == SC_CAS_VIRGIN)
1008 //! was passiert bei Aktionen, die in diesem Dokument accepted worden sind???
1009 //! Fehlermeldung oder was???
1010 //! oder Reject-Aenderung normal ausfuehren
1012 pThisTrack->Reject(pOldAction);
1013 bHasRejected = TRUE; // fuer Paint
1015 bExecute = false;
1019 if ( bExecute )
1021 // normal ausfuehren
1022 ScRange aSourceRange = pSourceAction->GetBigRange().MakeRange();
1023 rMarkData.SelectOneTable( aSourceRange.aStart.Tab() );
1024 switch ( eSourceType )
1026 case SC_CAT_CONTENT:
1028 //! Test, ob es ganz unten im Dokument war, dann automatisches
1029 //! Zeilen-Einfuegen ???
1031 DBG_ASSERT( aSourceRange.aStart == aSourceRange.aEnd, "huch?" );
1032 ScAddress aPos = aSourceRange.aStart;
1033 String aValue;
1034 ((const ScChangeActionContent*)pSourceAction)->GetNewString( aValue );
1035 BYTE eMatrix = MM_NONE;
1036 const ScBaseCell* pCell = ((const ScChangeActionContent*)pSourceAction)->GetNewCell();
1037 if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA )
1038 eMatrix = ((const ScFormulaCell*)pCell)->GetMatrixFlag();
1039 switch ( eMatrix )
1041 case MM_NONE :
1042 pViewSh->EnterData( aPos.Col(), aPos.Row(), aPos.Tab(), aValue );
1043 break;
1044 case MM_FORMULA :
1046 SCCOL nCols;
1047 SCROW nRows;
1048 ((const ScFormulaCell*)pCell)->GetMatColsRows( nCols, nRows );
1049 aSourceRange.aEnd.SetCol( aPos.Col() + nCols - 1 );
1050 aSourceRange.aEnd.SetRow( aPos.Row() + nRows - 1 );
1051 aValue.Erase( 0, 1 );
1052 aValue.Erase( aValue.Len()-1, 1 );
1053 GetDocFunc().EnterMatrix( aSourceRange,
1054 NULL, NULL, aValue, FALSE, FALSE,
1055 EMPTY_STRING, formula::FormulaGrammar::GRAM_DEFAULT );
1057 break;
1058 case MM_REFERENCE : // do nothing
1059 break;
1060 case MM_FAKE :
1061 DBG_WARNING( "MergeDocument: MatrixFlag MM_FAKE" );
1062 pViewSh->EnterData( aPos.Col(), aPos.Row(), aPos.Tab(), aValue );
1063 break;
1064 default:
1065 DBG_ERROR( "MergeDocument: unknown MatrixFlag" );
1068 break;
1069 case SC_CAT_INSERT_TABS :
1071 String aName;
1072 aDocument.CreateValidTabName( aName );
1073 GetDocFunc().InsertTable( aSourceRange.aStart.Tab(), aName, TRUE, FALSE );
1075 break;
1076 case SC_CAT_INSERT_ROWS:
1077 GetDocFunc().InsertCells( aSourceRange, NULL, INS_INSROWS, TRUE, FALSE );
1078 break;
1079 case SC_CAT_INSERT_COLS:
1080 GetDocFunc().InsertCells( aSourceRange, NULL, INS_INSCOLS, TRUE, FALSE );
1081 break;
1082 case SC_CAT_DELETE_TABS :
1083 GetDocFunc().DeleteTable( aSourceRange.aStart.Tab(), TRUE, FALSE );
1084 break;
1085 case SC_CAT_DELETE_ROWS:
1087 const ScChangeActionDel* pDel = (const ScChangeActionDel*) pSourceAction;
1088 if ( pDel->IsTopDelete() )
1090 aSourceRange = pDel->GetOverAllRange().MakeRange();
1091 GetDocFunc().DeleteCells( aSourceRange, NULL, DEL_DELROWS, TRUE, FALSE );
1094 break;
1095 case SC_CAT_DELETE_COLS:
1097 const ScChangeActionDel* pDel = (const ScChangeActionDel*) pSourceAction;
1098 if ( pDel->IsTopDelete() && !pDel->IsTabDeleteCol() )
1099 { // deleted Table enthaelt deleted Cols, die nicht
1100 aSourceRange = pDel->GetOverAllRange().MakeRange();
1101 GetDocFunc().DeleteCells( aSourceRange, NULL, DEL_DELCOLS, TRUE, FALSE );
1104 break;
1105 case SC_CAT_MOVE :
1107 const ScChangeActionMove* pMove = (const ScChangeActionMove*) pSourceAction;
1108 ScRange aFromRange( pMove->GetFromRange().MakeRange() );
1109 GetDocFunc().MoveBlock( aFromRange,
1110 aSourceRange.aStart, TRUE, TRUE, FALSE, FALSE );
1112 break;
1113 default:
1115 // added to avoid warnings
1119 const String& rComment = pSourceAction->GetComment();
1120 if ( rComment.Len() )
1122 ScChangeAction* pAct = pThisTrack->GetLast();
1123 if ( pAct && pAct->GetActionNumber() > nOldActionMax )
1124 pAct->SetComment( rComment );
1125 #ifndef PRODUCT
1126 else
1127 DBG_ERROR( "MergeDocument: wohin mit dem Kommentar?!?" );
1128 #endif
1131 // Referenzen anpassen
1132 pSourceTrack->MergeOwn( (ScChangeAction*) pSourceAction, nFirstNewNumber, bShared );
1134 // merge action state
1135 if ( bShared && !pSourceAction->IsRejected() )
1137 ScChangeAction* pAct = pThisTrack->GetLast();
1138 if ( pAct && pAct->GetActionNumber() > nOldActionMax )
1140 pThisTrack->MergeActionState( pAct, pSourceAction );
1144 // fill merge map
1145 if ( bShared && pMergeMap )
1147 ScChangeAction* pAct = pThisTrack->GetLast();
1148 if ( pAct && pAct->GetActionNumber() > nOldActionMax )
1150 ULONG nActionMax = pAct->GetActionNumber();
1151 ULONG nActionCount = nActionMax - nOldActionMax;
1152 ULONG nAction = nActionMax - nActionCount + 1;
1153 ULONG nSourceAction = pSourceAction->GetActionNumber() - nActionCount + 1;
1154 while ( nAction <= nActionMax )
1156 if ( bInverseMap )
1158 (*pMergeMap)[ nAction++ ] = nSourceAction++;
1160 else
1162 (*pMergeMap)[ nSourceAction++ ] = nAction++;
1168 aProgress.SetStateCountDown( --nNewActionCount );
1170 pSourceAction = pSourceAction->GetNext();
1173 rMarkData = aOldMarkData;
1174 pThisTrack->SetUser(aOldUser);
1175 pThisTrack->SetUseFixDateTime( FALSE );
1177 pSourceTrack->Clear(); //! der ist jetzt verhunzt
1179 if (bHasRejected)
1180 PostPaintGridAll(); // Reject() paintet nicht selber
1182 UnlockPaint();
1185 bool ScDocShell::MergeSharedDocument( ScDocShell* pSharedDocShell )
1187 if ( !pSharedDocShell )
1189 return false;
1192 ScChangeTrack* pThisTrack = aDocument.GetChangeTrack();
1193 if ( !pThisTrack )
1195 return false;
1198 ScDocument& rSharedDoc = *( pSharedDocShell->GetDocument() );
1199 ScChangeTrack* pSharedTrack = rSharedDoc.GetChangeTrack();
1200 if ( !pSharedTrack )
1202 return false;
1205 #if DEBUG_CHANGETRACK
1206 ::rtl::OUString aMessage = ::rtl::OUString::createFromAscii( "\nbefore merge:\n" );
1207 aMessage += pThisTrack->ToString();
1208 ::rtl::OString aMsg = ::rtl::OUStringToOString( aMessage, RTL_TEXTENCODING_UTF8 );
1209 OSL_ENSURE( false, aMsg.getStr() );
1210 //fprintf( stdout, "%s ", aMsg.getStr() );
1211 //fflush( stdout );
1212 #endif // DEBUG_CHANGETRACK
1214 // reset show changes
1215 ScChangeViewSettings aChangeViewSet;
1216 aChangeViewSet.SetShowChanges( FALSE );
1217 aDocument.SetChangeViewSettings( aChangeViewSet );
1219 // find first merge action in this document
1220 BOOL bIgnore100Sec = !pThisTrack->IsTime100thSeconds() || !pSharedTrack->IsTime100thSeconds();
1221 ScChangeAction* pThisAction = pThisTrack->GetFirst();
1222 ScChangeAction* pSharedAction = pSharedTrack->GetFirst();
1223 while ( lcl_Equal( pThisAction, pSharedAction, bIgnore100Sec ) )
1225 pThisAction = pThisAction->GetNext();
1226 pSharedAction = pSharedAction->GetNext();
1229 if ( pSharedAction )
1231 if ( pThisAction )
1233 // merge own changes into shared document
1234 ULONG nActStartShared = pSharedAction->GetActionNumber();
1235 ULONG nActEndShared = pSharedTrack->GetActionMax();
1236 ScDocument* pTmpDoc = new ScDocument;
1237 for ( sal_Int32 nIndex = 0; nIndex < aDocument.GetTableCount(); ++nIndex )
1239 String sTabName;
1240 pTmpDoc->CreateValidTabName( sTabName );
1241 pTmpDoc->InsertTab( SC_TAB_APPEND, sTabName );
1243 aDocument.GetChangeTrack()->Clone( pTmpDoc );
1244 ScChangeActionMergeMap aOwnInverseMergeMap;
1245 pSharedDocShell->MergeDocument( *pTmpDoc, true, true, 0, &aOwnInverseMergeMap, true );
1246 delete pTmpDoc;
1247 ULONG nActStartOwn = nActEndShared + 1;
1248 ULONG nActEndOwn = pSharedTrack->GetActionMax();
1250 // find conflicts
1251 ScConflictsList aConflictsList;
1252 ScConflictsFinder aFinder( pSharedTrack, nActStartShared, nActEndShared, nActStartOwn, nActEndOwn, aConflictsList );
1253 if ( aFinder.Find() )
1255 ScConflictsListHelper::TransformConflictsList( aConflictsList, NULL, &aOwnInverseMergeMap );
1256 bool bLoop = true;
1257 while ( bLoop )
1259 bLoop = false;
1260 ScConflictsDlg aDlg( GetActiveDialogParent(), GetViewData(), &rSharedDoc, aConflictsList );
1261 if ( aDlg.Execute() == RET_CANCEL )
1263 QueryBox aBox( GetActiveDialogParent(), WinBits( WB_YES_NO | WB_DEF_YES ),
1264 ScGlobal::GetRscString( STR_DOC_WILLNOTBESAVED ) );
1265 if ( aBox.Execute() == RET_YES )
1267 return false;
1269 else
1271 bLoop = true;
1277 // undo own changes in shared document
1278 pSharedTrack->Undo( nActStartOwn, nActEndOwn );
1280 // clone change track for merging into own document
1281 pTmpDoc = new ScDocument;
1282 for ( sal_Int32 nIndex = 0; nIndex < aDocument.GetTableCount(); ++nIndex )
1284 String sTabName;
1285 pTmpDoc->CreateValidTabName( sTabName );
1286 pTmpDoc->InsertTab( SC_TAB_APPEND, sTabName );
1288 pThisTrack->Clone( pTmpDoc );
1290 // undo own changes since last save in own document
1291 ULONG nStartShared = pThisAction->GetActionNumber();
1292 ScChangeAction* pAction = pThisTrack->GetLast();
1293 while ( pAction && pAction->GetActionNumber() >= nStartShared )
1295 pThisTrack->Reject( pAction, true );
1296 pAction = pAction->GetPrev();
1299 // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
1300 pThisTrack->Undo( nStartShared, pThisTrack->GetActionMax(), true );
1302 // merge shared changes into own document
1303 ScChangeActionMergeMap aSharedMergeMap;
1304 MergeDocument( rSharedDoc, true, true, 0, &aSharedMergeMap );
1305 ULONG nEndShared = pThisTrack->GetActionMax();
1307 // resolve conflicts for shared non-content actions
1308 if ( !aConflictsList.empty() )
1310 ScConflictsListHelper::TransformConflictsList( aConflictsList, &aSharedMergeMap, NULL );
1311 ScConflictsResolver aResolver( pThisTrack, aConflictsList );
1312 pAction = pThisTrack->GetAction( nEndShared );
1313 while ( pAction && pAction->GetActionNumber() >= nStartShared )
1315 aResolver.HandleAction( pAction, true /*bIsSharedAction*/,
1316 false /*bHandleContentAction*/, true /*bHandleNonContentAction*/ );
1317 pAction = pAction->GetPrev();
1320 nEndShared = pThisTrack->GetActionMax();
1322 // only show changes from shared document
1323 aChangeViewSet.SetShowChanges( TRUE );
1324 aChangeViewSet.SetShowAccepted( TRUE );
1325 aChangeViewSet.SetHasActionRange( true );
1326 aChangeViewSet.SetTheActionRange( nStartShared, nEndShared );
1327 aDocument.SetChangeViewSettings( aChangeViewSet );
1329 // merge own changes back into own document
1330 ULONG nStartOwn = nEndShared + 1;
1331 ScChangeActionMergeMap aOwnMergeMap;
1332 MergeDocument( *pTmpDoc, true, true, nEndShared - nStartShared + 1, &aOwnMergeMap );
1333 delete pTmpDoc;
1334 ULONG nEndOwn = pThisTrack->GetActionMax();
1336 // resolve conflicts for shared content actions and own actions
1337 if ( !aConflictsList.empty() )
1339 ScConflictsListHelper::TransformConflictsList( aConflictsList, NULL, &aOwnMergeMap );
1340 ScConflictsResolver aResolver( pThisTrack, aConflictsList );
1341 pAction = pThisTrack->GetAction( nEndShared );
1342 while ( pAction && pAction->GetActionNumber() >= nStartShared )
1344 aResolver.HandleAction( pAction, true /*bIsSharedAction*/,
1345 true /*bHandleContentAction*/, false /*bHandleNonContentAction*/ );
1346 pAction = pAction->GetPrev();
1349 pAction = pThisTrack->GetAction( nEndOwn );
1350 while ( pAction && pAction->GetActionNumber() >= nStartOwn )
1352 aResolver.HandleAction( pAction, false /*bIsSharedAction*/,
1353 true /*bHandleContentAction*/, true /*bHandleNonContentAction*/ );
1354 pAction = pAction->GetPrev();
1357 nEndOwn = pThisTrack->GetActionMax();
1359 else
1361 // merge shared changes into own document
1362 ULONG nStartShared = pThisTrack->GetActionMax() + 1;
1363 MergeDocument( rSharedDoc, true, true );
1364 ULONG nEndShared = pThisTrack->GetActionMax();
1366 // only show changes from shared document
1367 aChangeViewSet.SetShowChanges( TRUE );
1368 aChangeViewSet.SetShowAccepted( TRUE );
1369 aChangeViewSet.SetHasActionRange( true );
1370 aChangeViewSet.SetTheActionRange( nStartShared, nEndShared );
1371 aDocument.SetChangeViewSettings( aChangeViewSet );
1374 // update view
1375 PostPaintExtras();
1376 PostPaintGridAll();
1378 InfoBox aInfoBox( GetActiveDialogParent(), ScGlobal::GetRscString( STR_DOC_UPDATED ) );
1379 aInfoBox.Execute();
1382 #if DEBUG_CHANGETRACK
1383 aMessage = ::rtl::OUString::createFromAscii( "\nafter merge:\n" );
1384 aMessage += pThisTrack->ToString();
1385 aMsg = ::rtl::OUStringToOString( aMessage, RTL_TEXTENCODING_UTF8 );
1386 OSL_ENSURE( false, aMsg.getStr() );
1387 //fprintf( stdout, "%s ", aMsg.getStr() );
1388 //fflush( stdout );
1389 #endif // DEBUG_CHANGETRACK
1391 return ( pThisAction != NULL );