diff options
Diffstat (limited to 'sc/source/ui/docshell/docsh3.cxx')
-rw-r--r-- | sc/source/ui/docshell/docsh3.cxx | 1373 |
1 files changed, 1373 insertions, 0 deletions
diff --git a/sc/source/ui/docshell/docsh3.cxx b/sc/source/ui/docshell/docsh3.cxx new file mode 100644 index 000000000000..010c8171f9b7 --- /dev/null +++ b/sc/source/ui/docshell/docsh3.cxx @@ -0,0 +1,1373 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> +#include <com/sun/star/document/XDocumentProperties.hpp> + +#include "scitems.hxx" +#include "rangelst.hxx" +#include <editeng/flstitem.hxx> +#include <svx/pageitem.hxx> +#include <editeng/paperinf.hxx> +#include <svx/postattr.hxx> +#include <editeng/sizeitem.hxx> +#include <unotools/misccfg.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/app.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/printer.hxx> +#include <svtools/ctrltool.hxx> +#include <vcl/virdev.hxx> +#include <vcl/svapp.hxx> +#include <vcl/msgbox.hxx> +#include <unotools/localedatawrapper.hxx> + +#include "docsh.hxx" +#include "docshimp.hxx" +#include "scmod.hxx" +#include "tabvwsh.hxx" +#include "viewdata.hxx" +#include "docpool.hxx" +#include "stlpool.hxx" +#include "patattr.hxx" +#include "uiitems.hxx" +#include "hints.hxx" +#include "docoptio.hxx" +#include "viewopti.hxx" +#include "pntlock.hxx" +#include "chgtrack.hxx" +#include "docfunc.hxx" +#include "cell.hxx" +#include "chgviset.hxx" +#include "progress.hxx" +#include "redcom.hxx" +#include "sc.hrc" +#include "inputopt.hxx" +#include "drwlayer.hxx" +#include "inputhdl.hxx" +#include "conflictsdlg.hxx" +#include "globstr.hrc" + +//------------------------------------------------------------------ + +// +// Redraw - Benachrichtigungen +// + + +void ScDocShell::PostEditView( ScEditEngineDefaulter* pEditEngine, const ScAddress& rCursorPos ) +{ +// Broadcast( ScEditViewHint( pEditEngine, rCursorPos ) ); + + // Test: nur aktive ViewShell + + ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell(); + if (pViewSh && pViewSh->GetViewData()->GetDocShell() == this) + { + ScEditViewHint aHint( pEditEngine, rCursorPos ); + pViewSh->Notify( *this, aHint ); + } +} + +void ScDocShell::PostDataChanged() +{ + Broadcast( SfxSimpleHint( FID_DATACHANGED ) ); + aDocument.ResetChanged( ScRange(0,0,0,MAXCOL,MAXROW,MAXTAB) ); + + SFX_APP()->Broadcast(SfxSimpleHint( FID_ANYDATACHANGED )); // Navigator + //! Navigator direkt benachrichtigen! +} + +void ScDocShell::PostPaint( SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab, + SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, sal_uInt16 nPart, + sal_uInt16 nExtFlags ) +{ + if (!ValidCol(nStartCol)) nStartCol = MAXCOL; + if (!ValidRow(nStartRow)) nStartRow = MAXROW; + if (!ValidCol(nEndCol)) nEndCol = MAXCOL; + if (!ValidRow(nEndRow)) nEndRow = MAXROW; + + if ( pPaintLockData ) + { + // #i54081# PAINT_EXTRAS still has to be brodcast because it changes the + // current sheet if it's invalid. All other flags added to pPaintLockData. + sal_uInt16 nLockPart = nPart & ~PAINT_EXTRAS; + if ( nLockPart ) + { + //! nExtFlags ??? + pPaintLockData->AddRange( ScRange( nStartCol, nStartRow, nStartTab, + nEndCol, nEndRow, nEndTab ), nLockPart ); + } + + nPart &= PAINT_EXTRAS; // for broadcasting + if ( !nPart ) + return; + } + + + if (nExtFlags & SC_PF_LINES) // Platz fuer Linien beruecksichtigen + { + //! Abfrage auf versteckte Spalten/Zeilen! + if (nStartCol>0) --nStartCol; + if (nEndCol<MAXCOL) ++nEndCol; + if (nStartRow>0) --nStartRow; + if (nEndRow<MAXROW) ++nEndRow; + } + + // um zusammengefasste erweitern + if (nExtFlags & SC_PF_TESTMERGE) + aDocument.ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow, nStartTab ); + + if ( nStartCol != 0 || nEndCol != MAXCOL ) + { + // Extend to whole rows if SC_PF_WHOLEROWS is set, or rotated or non-left + // aligned cells are contained (see UpdatePaintExt). + // Special handling for RTL text (#i9731#) is unnecessary now with full + // support of right-aligned text. + + if ( ( nExtFlags & SC_PF_WHOLEROWS ) || + aDocument.HasAttrib( nStartCol,nStartRow,nStartTab, + MAXCOL,nEndRow,nEndTab, HASATTR_ROTATE | HASATTR_RIGHTORCENTER ) ) + { + nStartCol = 0; + nEndCol = MAXCOL; + } + } + + Broadcast( ScPaintHint( ScRange( nStartCol, nStartRow, nStartTab, + nEndCol, nEndRow, nEndTab ), nPart ) ); + + if ( nPart & PAINT_GRID ) + aDocument.ResetChanged( ScRange(nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab) ); +} + +void ScDocShell::PostPaint( const ScRange& rRange, sal_uInt16 nPart, sal_uInt16 nExtFlags ) +{ + PostPaint( rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(), + rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab(), + nPart, nExtFlags ); +} + +void ScDocShell::PostPaintGridAll() +{ + PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID ); +} + +void ScDocShell::PostPaintCell( SCCOL nCol, SCROW nRow, SCTAB nTab ) +{ + PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PAINT_GRID, SC_PF_TESTMERGE ); +} + +void ScDocShell::PostPaintCell( const ScAddress& rPos ) +{ + PostPaintCell( rPos.Col(), rPos.Row(), rPos.Tab() ); +} + +void ScDocShell::PostPaintExtras() +{ + PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS ); +} + +void ScDocShell::UpdatePaintExt( sal_uInt16& rExtFlags, const ScRange& rRange ) +{ + if ( ( rExtFlags & SC_PF_LINES ) == 0 && aDocument.HasAttrib( rRange, HASATTR_PAINTEXT ) ) + { + // If the range contains lines, shadow or conditional formats, + // set SC_PF_LINES to include one extra cell in all directions. + + rExtFlags |= SC_PF_LINES; + } + + if ( ( rExtFlags & SC_PF_WHOLEROWS ) == 0 && + ( rRange.aStart.Col() != 0 || rRange.aEnd.Col() != MAXCOL ) && + aDocument.HasAttrib( rRange, HASATTR_ROTATE | HASATTR_RIGHTORCENTER ) ) + { + // If the range contains (logically) right- or center-aligned cells, + // or rotated cells, set SC_PF_WHOLEROWS to paint the whole rows. + // This test isn't needed after the cell changes, because it's also + // tested in PostPaint. UpdatePaintExt may later be changed to do this + // only if called before the changes. + + rExtFlags |= SC_PF_WHOLEROWS; + } +} + +void ScDocShell::UpdatePaintExt( sal_uInt16& rExtFlags, SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab, + SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab ) +{ + UpdatePaintExt( rExtFlags, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ) ); +} + +//------------------------------------------------------------------ + +void ScDocShell::LockPaint_Impl(sal_Bool bDoc) +{ + if ( !pPaintLockData ) + pPaintLockData = new ScPaintLockData(0); //! Modus... + pPaintLockData->IncLevel(bDoc); +} + +void ScDocShell::UnlockPaint_Impl(sal_Bool bDoc) +{ + if ( pPaintLockData ) + { + if ( pPaintLockData->GetLevel(bDoc) ) + pPaintLockData->DecLevel(bDoc); + if (!pPaintLockData->GetLevel(!bDoc) && !pPaintLockData->GetLevel(bDoc)) + { + // Paint jetzt ausfuehren + + ScPaintLockData* pPaint = pPaintLockData; + pPaintLockData = NULL; // nicht weitersammeln + + ScRangeListRef xRangeList = pPaint->GetRangeList(); + if (xRangeList) + { + sal_uInt16 nParts = pPaint->GetParts(); + for ( size_t i = 0, nCount = xRangeList->size(); i < nCount; i++ ) + { + //! nExtFlags ??? + ScRange aRange = *(*xRangeList)[i]; + PostPaint( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aStart.Tab(), + aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aEnd.Tab(), + nParts ); + } + } + + if ( pPaint->GetModified() ) + SetDocumentModified(); + + delete pPaint; + } + } + else + { + OSL_FAIL("UnlockPaint ohne LockPaint"); + } +} + +void ScDocShell::LockDocument_Impl(sal_uInt16 nNew) +{ + if (!nDocumentLock) + { + ScDrawLayer* pDrawLayer = aDocument.GetDrawLayer(); + if (pDrawLayer) + pDrawLayer->setLock(true); + } + nDocumentLock = nNew; +} + +void ScDocShell::UnlockDocument_Impl(sal_uInt16 nNew) +{ + nDocumentLock = nNew; + if (!nDocumentLock) + { + ScDrawLayer* pDrawLayer = aDocument.GetDrawLayer(); + if (pDrawLayer) + pDrawLayer->setLock(false); + } +} + +sal_uInt16 ScDocShell::GetLockCount() const +{ + return nDocumentLock; +} + +void ScDocShell::SetLockCount(sal_uInt16 nNew) +{ + if (nNew) // setzen + { + if ( !pPaintLockData ) + pPaintLockData = new ScPaintLockData(0); //! Modus... + pPaintLockData->SetLevel(nNew-1, sal_True); + LockDocument_Impl(nNew); + } + else if (pPaintLockData) // loeschen + { + pPaintLockData->SetLevel(0, sal_True); // bei Unlock sofort ausfuehren + UnlockPaint_Impl(sal_True); // jetzt + UnlockDocument_Impl(0); + } +} + +void ScDocShell::LockPaint() +{ + LockPaint_Impl(false); +} + +void ScDocShell::UnlockPaint() +{ + UnlockPaint_Impl(false); +} + +void ScDocShell::LockDocument() +{ + LockPaint_Impl(sal_True); + LockDocument_Impl(nDocumentLock + 1); +} + +void ScDocShell::UnlockDocument() +{ + if (nDocumentLock) + { + UnlockPaint_Impl(sal_True); + UnlockDocument_Impl(nDocumentLock - 1); + } + else + { + OSL_FAIL("UnlockDocument without LockDocument"); + } +} + +//------------------------------------------------------------------ + +void ScDocShell::SetInplace( sal_Bool bInplace ) +{ + if (bIsInplace != bInplace) + { + bIsInplace = bInplace; + CalcOutputFactor(); + } +} + +void ScDocShell::CalcOutputFactor() +{ + if (bIsInplace) + { + nPrtToScreenFactor = 1.0; // passt sonst nicht zur inaktiven Darstellung + return; + } + + sal_Bool bTextWysiwyg = SC_MOD()->GetInputOptions().GetTextWysiwyg(); + if (bTextWysiwyg) + { + nPrtToScreenFactor = 1.0; + return; + } + + String aTestString = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM( + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890123456789" )); + long nPrinterWidth = 0; + long nWindowWidth = 0; + const ScPatternAttr* pPattern = (const ScPatternAttr*)&aDocument.GetPool()-> + GetDefaultItem(ATTR_PATTERN); + + Font aDefFont; + OutputDevice* pRefDev = GetRefDevice(); + MapMode aOldMode = pRefDev->GetMapMode(); + Font aOldFont = pRefDev->GetFont(); + + pRefDev->SetMapMode(MAP_PIXEL); + pPattern->GetFont(aDefFont, SC_AUTOCOL_BLACK, pRefDev); // font color doesn't matter here + pRefDev->SetFont(aDefFont); + nPrinterWidth = pRefDev->PixelToLogic( Size( pRefDev->GetTextWidth(aTestString), 0 ), MAP_100TH_MM ).Width(); + pRefDev->SetFont(aOldFont); + pRefDev->SetMapMode(aOldMode); + + VirtualDevice aVirtWindow( *Application::GetDefaultDevice() ); + aVirtWindow.SetMapMode(MAP_PIXEL); + pPattern->GetFont(aDefFont, SC_AUTOCOL_BLACK, &aVirtWindow); // font color doesn't matter here + aVirtWindow.SetFont(aDefFont); + nWindowWidth = aVirtWindow.GetTextWidth(aTestString); + nWindowWidth = (long) ( nWindowWidth / ScGlobal::nScreenPPTX * HMM_PER_TWIPS ); + + if (nPrinterWidth && nWindowWidth) + nPrtToScreenFactor = nPrinterWidth / (double) nWindowWidth; + else + { + OSL_FAIL("GetTextSize gibt 0 ??"); + nPrtToScreenFactor = 1.0; + } +} + +double ScDocShell::GetOutputFactor() const +{ + return nPrtToScreenFactor; +} + +//--------------------------------------------------------------------- + +void ScDocShell::InitOptions(bool bForLoading) // called from InitNew and Load +{ + // Einstellungen aus dem SpellCheckCfg kommen in Doc- und ViewOptions + + sal_uInt16 nDefLang, nCjkLang, nCtlLang; + sal_Bool bAutoSpell; + ScModule::GetSpellSettings( nDefLang, nCjkLang, nCtlLang, bAutoSpell ); + ScModule* pScMod = SC_MOD(); + + ScDocOptions aDocOpt = pScMod->GetDocOptions(); + ScViewOptions aViewOpt = pScMod->GetViewOptions(); + aDocOpt.SetAutoSpell( bAutoSpell ); + + // zweistellige Jahreszahleneingabe aus Extras->Optionen->Allgemein->Sonstiges + aDocOpt.SetYear2000( sal::static_int_cast<sal_uInt16>( ::utl::MiscCfg().GetYear2000() ) ); + + if (bForLoading) + { + // #i112123# No style:decimal-places attribute means automatic decimals, not the configured default, + // so it must not be taken from the global options. + // Calculation settings are handled separately in ScXMLBodyContext::EndElement. + aDocOpt.SetStdPrecision( SvNumberFormatter::UNLIMITED_PRECISION ); + } + + aDocument.SetDocOptions( aDocOpt ); + aDocument.SetViewOptions( aViewOpt ); + + // Druck-Optionen werden jetzt direkt vor dem Drucken gesetzt + + aDocument.SetLanguage( (LanguageType) nDefLang, (LanguageType) nCjkLang, (LanguageType) nCtlLang ); +} + +//--------------------------------------------------------------------- + +Printer* ScDocShell::GetDocumentPrinter() // fuer OLE +{ + return aDocument.GetPrinter(); +} + +SfxPrinter* ScDocShell::GetPrinter(sal_Bool bCreateIfNotExist) +{ + return aDocument.GetPrinter(bCreateIfNotExist); +} + +void ScDocShell::UpdateFontList() +{ + delete pImpl->pFontList; + // pImpl->pFontList = new FontList( GetPrinter(), Application::GetDefaultDevice() ); + pImpl->pFontList = new FontList( GetRefDevice(), NULL, false ); // sal_False or sal_True??? + SvxFontListItem aFontListItem( pImpl->pFontList, SID_ATTR_CHAR_FONTLIST ); + PutItem( aFontListItem ); + + CalcOutputFactor(); +} + +OutputDevice* ScDocShell::GetRefDevice() +{ + return aDocument.GetRefDevice(); +} + +sal_uInt16 ScDocShell::SetPrinter( SfxPrinter* pNewPrinter, sal_uInt16 nDiffFlags ) +{ + SfxPrinter *pOld = aDocument.GetPrinter( false ); + if ( pOld && pOld->IsPrinting() ) + return SFX_PRINTERROR_BUSY; + + if (nDiffFlags & SFX_PRINTER_PRINTER) + { + if ( aDocument.GetPrinter() != pNewPrinter ) + { + aDocument.SetPrinter( pNewPrinter ); + aDocument.SetPrintOptions(); + + // MT: Use UpdateFontList: Will use Printer fonts only if needed! + /* + delete pImpl->pFontList; + pImpl->pFontList = new FontList( pNewPrinter, Application::GetDefaultDevice() ); + SvxFontListItem aFontListItem( pImpl->pFontList, SID_ATTR_CHAR_FONTLIST ); + PutItem( aFontListItem ); + + CalcOutputFactor(); + */ + if ( SC_MOD()->GetInputOptions().GetTextWysiwyg() ) + UpdateFontList(); + + ScModule* pScMod = SC_MOD(); + SfxViewFrame *pFrame = SfxViewFrame::GetFirst( this ); + while (pFrame) + { + SfxViewShell* pSh = pFrame->GetViewShell(); + if (pSh && pSh->ISA(ScTabViewShell)) + { + ScTabViewShell* pViewSh = (ScTabViewShell*)pSh; + ScInputHandler* pInputHdl = pScMod->GetInputHdl(pViewSh); + if (pInputHdl) + pInputHdl->UpdateRefDevice(); + } + pFrame = SfxViewFrame::GetNext( *pFrame, this ); + } + } + } + else if (nDiffFlags & SFX_PRINTER_JOBSETUP) + { + SfxPrinter* pOldPrinter = aDocument.GetPrinter(); + if (pOldPrinter) + { + pOldPrinter->SetJobSetup( pNewPrinter->GetJobSetup() ); + + // #i6706# Call SetPrinter with the old printer again, so the drawing layer + // RefDevice is set (calling ReformatAllTextObjects and rebuilding charts), + // because the JobSetup (printer device settings) may affect text layout. + aDocument.SetPrinter( pOldPrinter ); + CalcOutputFactor(); // also with the new settings + } + } + + if (nDiffFlags & SFX_PRINTER_OPTIONS) + { + aDocument.SetPrintOptions(); //! aus neuem Printer ??? + } + + if (nDiffFlags & (SFX_PRINTER_CHG_ORIENTATION | SFX_PRINTER_CHG_SIZE)) + { + String aStyle = aDocument.GetPageStyle( GetCurTab() ); + ScStyleSheetPool* pStPl = aDocument.GetStyleSheetPool(); + SfxStyleSheet* pStyleSheet = (SfxStyleSheet*)pStPl->Find(aStyle, SFX_STYLE_FAMILY_PAGE); + if (pStyleSheet) + { + SfxItemSet& rSet = pStyleSheet->GetItemSet(); + + if (nDiffFlags & SFX_PRINTER_CHG_ORIENTATION) + { + const SvxPageItem& rOldItem = (const SvxPageItem&)rSet.Get(ATTR_PAGE); + sal_Bool bWasLand = rOldItem.IsLandscape(); + sal_Bool bNewLand = ( pNewPrinter->GetOrientation() == ORIENTATION_LANDSCAPE ); + if (bNewLand != bWasLand) + { + SvxPageItem aNewItem( rOldItem ); + aNewItem.SetLandscape( bNewLand ); + rSet.Put( aNewItem ); + + // Groesse umdrehen + Size aOldSize = ((const SvxSizeItem&)rSet.Get(ATTR_PAGE_SIZE)).GetSize(); + Size aNewSize(aOldSize.Height(),aOldSize.Width()); + SvxSizeItem aNewSItem(ATTR_PAGE_SIZE,aNewSize); + rSet.Put( aNewSItem ); + } + } + if (nDiffFlags & SFX_PRINTER_CHG_SIZE) + { + SvxSizeItem aPaperSizeItem( ATTR_PAGE_SIZE, SvxPaperInfo::GetPaperSize(pNewPrinter) ); + rSet.Put( aPaperSizeItem ); + } + } + } + + PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB,PAINT_ALL); + + return 0; +} + +//--------------------------------------------------------------------- + +ScChangeAction* ScDocShell::GetChangeAction( const ScAddress& rPos ) +{ + ScChangeTrack* pTrack = GetDocument()->GetChangeTrack(); + if (!pTrack) + return NULL; + + SCTAB nTab = rPos.Tab(); + + const ScChangeAction* pFound = NULL; + long nModified = 0; + const ScChangeAction* pAction = pTrack->GetFirst(); + while (pAction) + { + ScChangeActionType eType = pAction->GetType(); + //! ScViewUtil::IsActionShown( *pAction, *pSettings, *pDoc )... + if ( pAction->IsVisible() && eType != SC_CAT_DELETE_TABS ) + { + const ScBigRange& rBig = pAction->GetBigRange(); + if ( rBig.aStart.Tab() == nTab ) + { + ScRange aRange = rBig.MakeRange(); + + if ( eType == SC_CAT_DELETE_ROWS ) + aRange.aEnd.SetRow( aRange.aStart.Row() ); + else if ( eType == SC_CAT_DELETE_COLS ) + aRange.aEnd.SetCol( aRange.aStart.Col() ); + + if ( aRange.In( rPos ) ) + { + pFound = pAction; // der letzte gewinnt + ++nModified; + } + } + if ( pAction->GetType() == SC_CAT_MOVE ) + { + ScRange aRange = + ((const ScChangeActionMove*)pAction)-> + GetFromRange().MakeRange(); + if ( aRange.In( rPos ) ) + { + pFound = pAction; + ++nModified; + } + } + } + pAction = pAction->GetNext(); + } + + return (ScChangeAction*)pFound; +} + +void ScDocShell::SetChangeComment( ScChangeAction* pAction, const String& rComment ) +{ + if (pAction) + { + pAction->SetComment( rComment ); + //! Undo ??? + SetDocumentModified(); + + // Dialog-Notify + ScChangeTrack* pTrack = GetDocument()->GetChangeTrack(); + if (pTrack) + { + sal_uLong nNumber = pAction->GetActionNumber(); + pTrack->NotifyModified( SC_CTM_CHANGE, nNumber, nNumber ); + } + } +} + +void ScDocShell::ExecuteChangeCommentDialog( ScChangeAction* pAction, Window* pParent,sal_Bool bPrevNext) +{ + if (!pAction) return; // ohne Aktion ist nichts.. + + String aComment = pAction->GetComment(); + String aAuthor = pAction->GetUser(); + + DateTime aDT = pAction->GetDateTime(); + String aDate = ScGlobal::pLocaleData->getDate( aDT ); + aDate += ' '; + aDate += ScGlobal::pLocaleData->getTime( aDT, false, false ); + + SfxItemSet aSet( GetPool(), + SID_ATTR_POSTIT_AUTHOR, SID_ATTR_POSTIT_AUTHOR, + SID_ATTR_POSTIT_DATE, SID_ATTR_POSTIT_DATE, + SID_ATTR_POSTIT_TEXT, SID_ATTR_POSTIT_TEXT, + 0 ); + + aSet.Put( SvxPostItTextItem ( aComment, SID_ATTR_POSTIT_TEXT ) ); + aSet.Put( SvxPostItAuthorItem( aAuthor, SID_ATTR_POSTIT_AUTHOR ) ); + aSet.Put( SvxPostItDateItem ( aDate, SID_ATTR_POSTIT_DATE ) ); + + ScRedComDialog* pDlg = new ScRedComDialog( pParent, aSet,this,pAction,bPrevNext); + + pDlg->Execute(); + + delete pDlg; +} + +//--------------------------------------------------------------------- + +void ScDocShell::CompareDocument( ScDocument& rOtherDoc ) +{ + ScChangeTrack* pTrack = aDocument.GetChangeTrack(); + if ( pTrack && pTrack->GetFirst() ) + { + //! Changes vorhanden -> Nachfrage ob geloescht werden soll + } + + aDocument.EndChangeTracking(); + aDocument.StartChangeTracking(); + + String aOldUser; + pTrack = aDocument.GetChangeTrack(); + if ( pTrack ) + { + aOldUser = pTrack->GetUser(); + + // check if comparing to same document + + String aThisFile; + const SfxMedium* pThisMed = GetMedium(); + if (pThisMed) + aThisFile = pThisMed->GetName(); + String aOtherFile; + SfxObjectShell* pOtherSh = rOtherDoc.GetDocumentShell(); + if (pOtherSh) + { + const SfxMedium* pOtherMed = pOtherSh->GetMedium(); + if (pOtherMed) + aOtherFile = pOtherMed->GetName(); + } + sal_Bool bSameDoc = ( aThisFile == aOtherFile && aThisFile.Len() ); + if ( !bSameDoc ) + { + // create change actions from comparing with the name of the user + // who last saved the document + // (only if comparing different documents) + + using namespace ::com::sun::star; + uno::Reference<document::XDocumentPropertiesSupplier> xDPS( + GetModel(), uno::UNO_QUERY_THROW); + uno::Reference<document::XDocumentProperties> xDocProps( + xDPS->getDocumentProperties()); + DBG_ASSERT(xDocProps.is(), "no DocumentProperties"); + String aDocUser = xDocProps->getModifiedBy(); + + if ( aDocUser.Len() ) + pTrack->SetUser( aDocUser ); + } + } + + aDocument.CompareDocument( rOtherDoc ); + + pTrack = aDocument.GetChangeTrack(); + if ( pTrack ) + pTrack->SetUser( aOldUser ); + + PostPaintGridAll(); + SetDocumentModified(); +} + +//--------------------------------------------------------------------- +// +// Merge (Aenderungen zusammenfuehren) +// +//--------------------------------------------------------------------- + +inline sal_Bool lcl_Equal( const ScChangeAction* pA, const ScChangeAction* pB, sal_Bool bIgnore100Sec ) +{ + return pA && pB && + pA->GetActionNumber() == pB->GetActionNumber() && + pA->GetType() == pB->GetType() && + pA->GetUser() == pB->GetUser() && + (bIgnore100Sec ? + pA->GetDateTimeUTC().IsEqualIgnore100Sec( pB->GetDateTimeUTC() ) : + pA->GetDateTimeUTC() == pB->GetDateTimeUTC()); + // State nicht vergleichen, falls eine alte Aenderung akzeptiert wurde +} + +bool lcl_FindAction( ScDocument* pDoc, const ScChangeAction* pAction, ScDocument* pSearchDoc, const ScChangeAction* pFirstSearchAction, const ScChangeAction* pLastSearchAction, sal_Bool bIgnore100Sec ) +{ + if ( !pDoc || !pAction || !pSearchDoc || !pFirstSearchAction || !pLastSearchAction ) + { + return false; + } + + sal_uLong nLastSearchAction = pLastSearchAction->GetActionNumber(); + const ScChangeAction* pA = pFirstSearchAction; + while ( pA && pA->GetActionNumber() <= nLastSearchAction ) + { + if ( pAction->GetType() == pA->GetType() && + pAction->GetUser() == pA->GetUser() && + (bIgnore100Sec ? + pAction->GetDateTimeUTC().IsEqualIgnore100Sec( pA->GetDateTimeUTC() ) : + pAction->GetDateTimeUTC() == pA->GetDateTimeUTC() ) && + pAction->GetBigRange() == pA->GetBigRange() ) + { + String aActionDesc; + pAction->GetDescription( aActionDesc, pDoc, sal_True ); + String aADesc; + pA->GetDescription( aADesc, pSearchDoc, sal_True ); + if ( aActionDesc.Equals( aADesc ) ) + { + OSL_FAIL( "lcl_FindAction(): found equal action!" ); + return true; + } + } + pA = pA->GetNext(); + } + + return false; +} + +void ScDocShell::MergeDocument( ScDocument& rOtherDoc, bool bShared, bool bCheckDuplicates, sal_uLong nOffset, ScChangeActionMergeMap* pMergeMap, bool bInverseMap ) +{ + ScTabViewShell* pViewSh = GetBestViewShell( false ); //! Funktionen an die DocShell + if (!pViewSh) + return; + + ScChangeTrack* pSourceTrack = rOtherDoc.GetChangeTrack(); + if (!pSourceTrack) + return; //! nichts zu tun - Fehlermeldung? + + ScChangeTrack* pThisTrack = aDocument.GetChangeTrack(); + if ( !pThisTrack ) + { // anschalten + aDocument.StartChangeTracking(); + pThisTrack = aDocument.GetChangeTrack(); + DBG_ASSERT(pThisTrack,"ChangeTracking nicht angeschaltet?"); + if ( !bShared ) + { + // visuelles RedLining einschalten + ScChangeViewSettings aChangeViewSet; + aChangeViewSet.SetShowChanges(sal_True); + aDocument.SetChangeViewSettings(aChangeViewSet); + } + } + + // include 100th seconds in compare? + sal_Bool bIgnore100Sec = !pSourceTrack->IsTime100thSeconds() || + !pThisTrack->IsTime100thSeconds(); + + // gemeinsame Ausgangsposition suchen + sal_uLong nFirstNewNumber = 0; + const ScChangeAction* pSourceAction = pSourceTrack->GetFirst(); + const ScChangeAction* pThisAction = pThisTrack->GetFirst(); + // skip identical actions + while ( lcl_Equal( pSourceAction, pThisAction, bIgnore100Sec ) ) + { + nFirstNewNumber = pSourceAction->GetActionNumber() + 1; + pSourceAction = pSourceAction->GetNext(); + pThisAction = pThisAction->GetNext(); + } + // pSourceAction und pThisAction zeigen jetzt auf die ersten "eigenen" Aktionen + // Die gemeinsamen Aktionen davor interessieren ueberhaupt nicht + + //! Abfrage, ob die Dokumente vor dem Change-Tracking gleich waren !!! + + + const ScChangeAction* pFirstMergeAction = pSourceAction; + const ScChangeAction* pFirstSearchAction = pThisAction; + + // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong + const ScChangeAction* pLastSearchAction = pThisTrack->GetLast(); + + // MergeChangeData aus den folgenden Aktionen erzeugen + sal_uLong nNewActionCount = 0; + const ScChangeAction* pCount = pSourceAction; + while ( pCount ) + { + if ( bShared || !ScChangeTrack::MergeIgnore( *pCount, nFirstNewNumber ) ) + ++nNewActionCount; + pCount = pCount->GetNext(); + } + if (!nNewActionCount) + return; //! nichts zu tun - Fehlermeldung? + // ab hier kein return mehr + + ScProgress aProgress( this, + String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("...")), + nNewActionCount ); + + sal_uLong nLastMergeAction = pSourceTrack->GetLast()->GetActionNumber(); + // UpdateReference-Undo, gueltige Referenzen fuer den letzten gemeinsamen Zustand + pSourceTrack->MergePrepare( (ScChangeAction*) pFirstMergeAction, bShared ); + + // MergeChangeData an alle noch folgenden Aktionen in diesem Dokument anpassen + // -> Referenzen gueltig fuer dieses Dokument + while ( pThisAction ) + { + // #i87049# [Collaboration] Conflict between delete row and insert content is not merged correctly + if ( !bShared || !ScChangeTrack::MergeIgnore( *pThisAction, nFirstNewNumber ) ) + { + ScChangeActionType eType = pThisAction->GetType(); + switch ( eType ) + { + case SC_CAT_INSERT_COLS : + case SC_CAT_INSERT_ROWS : + case SC_CAT_INSERT_TABS : + pSourceTrack->AppendInsert( pThisAction->GetBigRange().MakeRange() ); + break; + case SC_CAT_DELETE_COLS : + case SC_CAT_DELETE_ROWS : + case SC_CAT_DELETE_TABS : + { + const ScChangeActionDel* pDel = (const ScChangeActionDel*) pThisAction; + if ( pDel->IsTopDelete() && !pDel->IsTabDeleteCol() ) + { // deleted Table enthaelt deleted Cols, die nicht + sal_uLong nStart, nEnd; + pSourceTrack->AppendDeleteRange( + pDel->GetOverAllRange().MakeRange(), NULL, nStart, nEnd ); + } + } + break; + case SC_CAT_MOVE : + { + const ScChangeActionMove* pMove = (const ScChangeActionMove*) pThisAction; + pSourceTrack->AppendMove( pMove->GetFromRange().MakeRange(), + pMove->GetBigRange().MakeRange(), NULL ); + } + break; + default: + { + // added to avoid warnings + } + } + } + pThisAction = pThisAction->GetNext(); + } + + LockPaint(); // #i73877# no repainting after each action + + // MergeChangeData in das aktuelle Dokument uebernehmen + sal_Bool bHasRejected = false; + String aOldUser = pThisTrack->GetUser(); + pThisTrack->SetUseFixDateTime( sal_True ); + ScMarkData& rMarkData = pViewSh->GetViewData()->GetMarkData(); + ScMarkData aOldMarkData( rMarkData ); + pSourceAction = pFirstMergeAction; + while ( pSourceAction && pSourceAction->GetActionNumber() <= nLastMergeAction ) + { + bool bMergeAction = false; + if ( bShared ) + { + if ( !bCheckDuplicates || !lcl_FindAction( &rOtherDoc, pSourceAction, &aDocument, pFirstSearchAction, pLastSearchAction, bIgnore100Sec ) ) + { + bMergeAction = true; + } + } + else + { + if ( !ScChangeTrack::MergeIgnore( *pSourceAction, nFirstNewNumber ) ) + { + bMergeAction = true; + } + } + + if ( bMergeAction ) + { + ScChangeActionType eSourceType = pSourceAction->GetType(); + if ( !bShared && pSourceAction->IsDeletedIn() ) + { + //! muss hier noch festgestellt werden, ob wirklich in + //! _diesem_ Dokument geloescht? + + // liegt in einem Bereich, der in diesem Dokument geloescht wurde + // -> wird weggelassen + //! ??? Loesch-Aktion rueckgaengig machen ??? + //! ??? Aktion irgendwo anders speichern ??? +#ifdef DBG_UTIL + String aValue; + if ( eSourceType == SC_CAT_CONTENT ) + ((const ScChangeActionContent*)pSourceAction)->GetNewString( aValue ); + ByteString aError( aValue, gsl_getSystemTextEncoding() ); + aError += " weggelassen"; + OSL_FAIL( aError.GetBuffer() ); +#endif + } + else + { + //! Datum/Autor/Kommentar der Source-Aktion uebernehmen! + + pThisTrack->SetUser( pSourceAction->GetUser() ); + pThisTrack->SetFixDateTimeUTC( pSourceAction->GetDateTimeUTC() ); + sal_uLong nOldActionMax = pThisTrack->GetActionMax(); + + bool bExecute = true; + sal_uLong nReject = pSourceAction->GetRejectAction(); + if ( nReject ) + { + if ( bShared ) + { + if ( nReject >= nFirstNewNumber ) + { + nReject += nOffset; + } + ScChangeAction* pOldAction = pThisTrack->GetAction( nReject ); + if ( pOldAction && pOldAction->IsVirgin() ) + { + pThisTrack->Reject( pOldAction ); + bHasRejected = sal_True; + bExecute = false; + } + } + else + { + // alte Aktion (aus den gemeinsamen) ablehnen + ScChangeAction* pOldAction = pThisTrack->GetAction( nReject ); + if (pOldAction && pOldAction->GetState() == SC_CAS_VIRGIN) + { + //! was passiert bei Aktionen, die in diesem Dokument accepted worden sind??? + //! Fehlermeldung oder was??? + //! oder Reject-Aenderung normal ausfuehren + + pThisTrack->Reject(pOldAction); + bHasRejected = sal_True; // fuer Paint + } + bExecute = false; + } + } + + if ( bExecute ) + { + // normal ausfuehren + ScRange aSourceRange = pSourceAction->GetBigRange().MakeRange(); + rMarkData.SelectOneTable( aSourceRange.aStart.Tab() ); + switch ( eSourceType ) + { + case SC_CAT_CONTENT: + { + //! Test, ob es ganz unten im Dokument war, dann automatisches + //! Zeilen-Einfuegen ??? + + DBG_ASSERT( aSourceRange.aStart == aSourceRange.aEnd, "huch?" ); + ScAddress aPos = aSourceRange.aStart; + String aValue; + ((const ScChangeActionContent*)pSourceAction)->GetNewString( aValue ); + sal_uInt8 eMatrix = MM_NONE; + const ScBaseCell* pCell = ((const ScChangeActionContent*)pSourceAction)->GetNewCell(); + if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA ) + eMatrix = ((const ScFormulaCell*)pCell)->GetMatrixFlag(); + switch ( eMatrix ) + { + case MM_NONE : + pViewSh->EnterData( aPos.Col(), aPos.Row(), aPos.Tab(), aValue ); + break; + case MM_FORMULA : + { + SCCOL nCols; + SCROW nRows; + ((const ScFormulaCell*)pCell)->GetMatColsRows( nCols, nRows ); + aSourceRange.aEnd.SetCol( aPos.Col() + nCols - 1 ); + aSourceRange.aEnd.SetRow( aPos.Row() + nRows - 1 ); + aValue.Erase( 0, 1 ); + aValue.Erase( aValue.Len()-1, 1 ); + GetDocFunc().EnterMatrix( aSourceRange, + NULL, NULL, aValue, false, false, + EMPTY_STRING, formula::FormulaGrammar::GRAM_DEFAULT ); + } + break; + case MM_REFERENCE : // do nothing + break; + case MM_FAKE : + DBG_WARNING( "MergeDocument: MatrixFlag MM_FAKE" ); + pViewSh->EnterData( aPos.Col(), aPos.Row(), aPos.Tab(), aValue ); + break; + default: + OSL_FAIL( "MergeDocument: unknown MatrixFlag" ); + } + } + break; + case SC_CAT_INSERT_TABS : + { + String aName; + aDocument.CreateValidTabName( aName ); + GetDocFunc().InsertTable( aSourceRange.aStart.Tab(), aName, sal_True, false ); + } + break; + case SC_CAT_INSERT_ROWS: + GetDocFunc().InsertCells( aSourceRange, NULL, INS_INSROWS, sal_True, false ); + break; + case SC_CAT_INSERT_COLS: + GetDocFunc().InsertCells( aSourceRange, NULL, INS_INSCOLS, sal_True, false ); + break; + case SC_CAT_DELETE_TABS : + GetDocFunc().DeleteTable( aSourceRange.aStart.Tab(), sal_True, false ); + break; + case SC_CAT_DELETE_ROWS: + { + const ScChangeActionDel* pDel = (const ScChangeActionDel*) pSourceAction; + if ( pDel->IsTopDelete() ) + { + aSourceRange = pDel->GetOverAllRange().MakeRange(); + GetDocFunc().DeleteCells( aSourceRange, NULL, DEL_DELROWS, sal_True, false ); + + // #i101099# [Collaboration] Changes are not correctly shown + if ( bShared ) + { + ScChangeAction* pAct = pThisTrack->GetLast(); + if ( pAct && pAct->GetType() == eSourceType && pAct->IsDeletedIn() && !pSourceAction->IsDeletedIn() ) + { + pAct->RemoveAllDeletedIn(); + } + } + } + } + break; + case SC_CAT_DELETE_COLS: + { + const ScChangeActionDel* pDel = (const ScChangeActionDel*) pSourceAction; + if ( pDel->IsTopDelete() && !pDel->IsTabDeleteCol() ) + { // deleted Table enthaelt deleted Cols, die nicht + aSourceRange = pDel->GetOverAllRange().MakeRange(); + GetDocFunc().DeleteCells( aSourceRange, NULL, DEL_DELCOLS, sal_True, false ); + } + } + break; + case SC_CAT_MOVE : + { + const ScChangeActionMove* pMove = (const ScChangeActionMove*) pSourceAction; + ScRange aFromRange( pMove->GetFromRange().MakeRange() ); + GetDocFunc().MoveBlock( aFromRange, + aSourceRange.aStart, sal_True, sal_True, false, false ); + } + break; + default: + { + // added to avoid warnings + } + } + } + const String& rComment = pSourceAction->GetComment(); + if ( rComment.Len() ) + { + ScChangeAction* pAct = pThisTrack->GetLast(); + if ( pAct && pAct->GetActionNumber() > nOldActionMax ) + pAct->SetComment( rComment ); +#ifdef DBG_UTIL + else + OSL_FAIL( "MergeDocument: wohin mit dem Kommentar?!?" ); +#endif + } + + // Referenzen anpassen + pSourceTrack->MergeOwn( (ScChangeAction*) pSourceAction, nFirstNewNumber, bShared ); + + // merge action state + if ( bShared && !pSourceAction->IsRejected() ) + { + ScChangeAction* pAct = pThisTrack->GetLast(); + if ( pAct && pAct->GetActionNumber() > nOldActionMax ) + { + pThisTrack->MergeActionState( pAct, pSourceAction ); + } + } + + // fill merge map + if ( bShared && pMergeMap ) + { + ScChangeAction* pAct = pThisTrack->GetLast(); + if ( pAct && pAct->GetActionNumber() > nOldActionMax ) + { + sal_uLong nActionMax = pAct->GetActionNumber(); + sal_uLong nActionCount = nActionMax - nOldActionMax; + sal_uLong nAction = nActionMax - nActionCount + 1; + sal_uLong nSourceAction = pSourceAction->GetActionNumber() - nActionCount + 1; + while ( nAction <= nActionMax ) + { + if ( bInverseMap ) + { + (*pMergeMap)[ nAction++ ] = nSourceAction++; + } + else + { + (*pMergeMap)[ nSourceAction++ ] = nAction++; + } + } + } + } + } + aProgress.SetStateCountDown( --nNewActionCount ); + } + pSourceAction = pSourceAction->GetNext(); + } + + rMarkData = aOldMarkData; + pThisTrack->SetUser(aOldUser); + pThisTrack->SetUseFixDateTime( false ); + + pSourceTrack->Clear(); //! der ist jetzt verhunzt + + if (bHasRejected) + PostPaintGridAll(); // Reject() paintet nicht selber + + UnlockPaint(); +} + +bool ScDocShell::MergeSharedDocument( ScDocShell* pSharedDocShell ) +{ + if ( !pSharedDocShell ) + { + return false; + } + + ScChangeTrack* pThisTrack = aDocument.GetChangeTrack(); + if ( !pThisTrack ) + { + return false; + } + + ScDocument& rSharedDoc = *( pSharedDocShell->GetDocument() ); + ScChangeTrack* pSharedTrack = rSharedDoc.GetChangeTrack(); + if ( !pSharedTrack ) + { + return false; + } + + // reset show changes + ScChangeViewSettings aChangeViewSet; + aChangeViewSet.SetShowChanges( false ); + aDocument.SetChangeViewSettings( aChangeViewSet ); + + // find first merge action in this document + sal_Bool bIgnore100Sec = !pThisTrack->IsTime100thSeconds() || !pSharedTrack->IsTime100thSeconds(); + ScChangeAction* pThisAction = pThisTrack->GetFirst(); + ScChangeAction* pSharedAction = pSharedTrack->GetFirst(); + while ( lcl_Equal( pThisAction, pSharedAction, bIgnore100Sec ) ) + { + pThisAction = pThisAction->GetNext(); + pSharedAction = pSharedAction->GetNext(); + } + + if ( pSharedAction ) + { + if ( pThisAction ) + { + // merge own changes into shared document + sal_uLong nActStartShared = pSharedAction->GetActionNumber(); + sal_uLong nActEndShared = pSharedTrack->GetActionMax(); + ScDocument* pTmpDoc = new ScDocument; + for ( sal_Int32 nIndex = 0; nIndex < aDocument.GetTableCount(); ++nIndex ) + { + String sTabName; + pTmpDoc->CreateValidTabName( sTabName ); + pTmpDoc->InsertTab( SC_TAB_APPEND, sTabName ); + } + aDocument.GetChangeTrack()->Clone( pTmpDoc ); + ScChangeActionMergeMap aOwnInverseMergeMap; + pSharedDocShell->MergeDocument( *pTmpDoc, true, true, 0, &aOwnInverseMergeMap, true ); + delete pTmpDoc; + sal_uLong nActStartOwn = nActEndShared + 1; + sal_uLong nActEndOwn = pSharedTrack->GetActionMax(); + + // find conflicts + ScConflictsList aConflictsList; + ScConflictsFinder aFinder( pSharedTrack, nActStartShared, nActEndShared, nActStartOwn, nActEndOwn, aConflictsList ); + if ( aFinder.Find() ) + { + ScConflictsListHelper::TransformConflictsList( aConflictsList, NULL, &aOwnInverseMergeMap ); + bool bLoop = true; + while ( bLoop ) + { + bLoop = false; + ScConflictsDlg aDlg( GetActiveDialogParent(), GetViewData(), &rSharedDoc, aConflictsList ); + if ( aDlg.Execute() == RET_CANCEL ) + { + QueryBox aBox( GetActiveDialogParent(), WinBits( WB_YES_NO | WB_DEF_YES ), + ScGlobal::GetRscString( STR_DOC_WILLNOTBESAVED ) ); + if ( aBox.Execute() == RET_YES ) + { + return false; + } + else + { + bLoop = true; + } + } + } + } + + // undo own changes in shared document + pSharedTrack->Undo( nActStartOwn, nActEndOwn ); + + // clone change track for merging into own document + pTmpDoc = new ScDocument; + for ( sal_Int32 nIndex = 0; nIndex < aDocument.GetTableCount(); ++nIndex ) + { + String sTabName; + pTmpDoc->CreateValidTabName( sTabName ); + pTmpDoc->InsertTab( SC_TAB_APPEND, sTabName ); + } + pThisTrack->Clone( pTmpDoc ); + + // undo own changes since last save in own document + sal_uLong nStartShared = pThisAction->GetActionNumber(); + ScChangeAction* pAction = pThisTrack->GetLast(); + while ( pAction && pAction->GetActionNumber() >= nStartShared ) + { + pThisTrack->Reject( pAction, true ); + pAction = pAction->GetPrev(); + } + + // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong + pThisTrack->Undo( nStartShared, pThisTrack->GetActionMax(), true ); + + // merge shared changes into own document + ScChangeActionMergeMap aSharedMergeMap; + MergeDocument( rSharedDoc, true, true, 0, &aSharedMergeMap ); + sal_uLong nEndShared = pThisTrack->GetActionMax(); + + // resolve conflicts for shared non-content actions + if ( !aConflictsList.empty() ) + { + ScConflictsListHelper::TransformConflictsList( aConflictsList, &aSharedMergeMap, NULL ); + ScConflictsResolver aResolver( pThisTrack, aConflictsList ); + pAction = pThisTrack->GetAction( nEndShared ); + while ( pAction && pAction->GetActionNumber() >= nStartShared ) + { + aResolver.HandleAction( pAction, true /*bIsSharedAction*/, + false /*bHandleContentAction*/, true /*bHandleNonContentAction*/ ); + pAction = pAction->GetPrev(); + } + } + nEndShared = pThisTrack->GetActionMax(); + + // only show changes from shared document + aChangeViewSet.SetShowChanges( sal_True ); + aChangeViewSet.SetShowAccepted( sal_True ); + aChangeViewSet.SetHasActionRange( true ); + aChangeViewSet.SetTheActionRange( nStartShared, nEndShared ); + aDocument.SetChangeViewSettings( aChangeViewSet ); + + // merge own changes back into own document + sal_uLong nStartOwn = nEndShared + 1; + ScChangeActionMergeMap aOwnMergeMap; + MergeDocument( *pTmpDoc, true, true, nEndShared - nStartShared + 1, &aOwnMergeMap ); + delete pTmpDoc; + sal_uLong nEndOwn = pThisTrack->GetActionMax(); + + // resolve conflicts for shared content actions and own actions + if ( !aConflictsList.empty() ) + { + ScConflictsListHelper::TransformConflictsList( aConflictsList, NULL, &aOwnMergeMap ); + ScConflictsResolver aResolver( pThisTrack, aConflictsList ); + pAction = pThisTrack->GetAction( nEndShared ); + while ( pAction && pAction->GetActionNumber() >= nStartShared ) + { + aResolver.HandleAction( pAction, true /*bIsSharedAction*/, + true /*bHandleContentAction*/, false /*bHandleNonContentAction*/ ); + pAction = pAction->GetPrev(); + } + + pAction = pThisTrack->GetAction( nEndOwn ); + while ( pAction && pAction->GetActionNumber() >= nStartOwn ) + { + aResolver.HandleAction( pAction, false /*bIsSharedAction*/, + true /*bHandleContentAction*/, true /*bHandleNonContentAction*/ ); + pAction = pAction->GetPrev(); + } + } + nEndOwn = pThisTrack->GetActionMax(); + } + else + { + // merge shared changes into own document + sal_uLong nStartShared = pThisTrack->GetActionMax() + 1; + MergeDocument( rSharedDoc, true, true ); + sal_uLong nEndShared = pThisTrack->GetActionMax(); + + // only show changes from shared document + aChangeViewSet.SetShowChanges( sal_True ); + aChangeViewSet.SetShowAccepted( sal_True ); + aChangeViewSet.SetHasActionRange( true ); + aChangeViewSet.SetTheActionRange( nStartShared, nEndShared ); + aDocument.SetChangeViewSettings( aChangeViewSet ); + } + + // update view + PostPaintExtras(); + PostPaintGridAll(); + + InfoBox aInfoBox( GetActiveDialogParent(), ScGlobal::GetRscString( STR_DOC_UPDATED ) ); + aInfoBox.Execute(); + } + + return ( pThisAction != NULL ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |