/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
if (!m_pDocument->ValidCol(nCol1))
{
nMaxWidthAffectedHint = -1; // Hint no longer valid
nCol1 = m_pDocument->MaxCol();
} if (!m_pDocument->ValidRow(nRow1)) nRow1 = m_pDocument->MaxRow(); if (!m_pDocument->ValidCol(nCol2))
{
nMaxWidthAffectedHint = -1; // Hint no longer valid
nCol2 = m_pDocument->MaxCol();
} if (!m_pDocument->ValidRow(nRow2)) nRow2 = m_pDocument->MaxRow();
if ( m_pPaintLockData )
{ // #i54081# PaintPartFlags::Extras still has to be broadcast because it changes the // current sheet if it's invalid. All other flags added to pPaintLockData.
PaintPartFlags nLockPart = nPart & ~PaintPartFlags::Extras; if ( nLockPart != PaintPartFlags::NONE )
{ //! nExtFlags ???
m_pPaintLockData->AddRange( ScRange( nCol1, nRow1, nTab1,
nCol2, nRow2, nTab2 ), nLockPart );
}
nPart &= PaintPartFlags::Extras; // for broadcasting if (nPart == PaintPartFlags::NONE) continue;
}
if (nExtFlags & SC_PF_LINES) // respect space for lines
{ //! check for hidden columns/rows! if (nCol1 > 0)
{
nMaxWidthAffectedHint = -1; // Hint no longer valid
--nCol1;
} if (nCol2 < m_pDocument->MaxCol())
{
nMaxWidthAffectedHint = -1; // Hint no longer valid
++nCol2;
} if (nRow1>0) --nRow1; if (nRow2<m_pDocument->MaxRow()) ++nRow2;
}
// expand for the merged ones if (nExtFlags & SC_PF_TESTMERGE)
m_pDocument->ExtendMerge( nCol1, nRow1, nCol2, nRow2, nTab1 );
if ( nCol1 != 0 || nCol2 != m_pDocument->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.
void ScDocShell::UpdatePaintExt( sal_uInt16& rExtFlags, const ScRange& rRange )
{ if ( ( rExtFlags & SC_PF_LINES ) == 0 &&
m_pDocument->HasAttrib( rRange, HasAttrFlags::Lines | HasAttrFlags::Shadow | HasAttrFlags::Conditional ) )
{ // 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() != m_pDocument->MaxCol() ) &&
m_pDocument->HasAttrib( rRange, HasAttrFlags::Rotate | HasAttrFlags::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.
if (!comphelper::IsFuzzing())
{ // two-digit year entry from Tools->Options->General
aDocOpt.SetYear2000(officecfg::Office::Common::DateFormat::TwoDigitYear::get());
}
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 );
// fdo#78294 The default null-date if // <table:null-date table:date-value='...' /> // is absent is 1899-12-30 regardless what the configuration is set to. // Import filters may override this value.
aDocOpt.SetDate( 30, 12, 1899);
}
if (nDiffFlags & SfxPrinterChangeFlags::PRINTER)
{ if ( m_pDocument->GetPrinter() != pNewPrinter )
{
m_pDocument->SetPrinter( pNewPrinter );
m_pDocument->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();
*/
ScModule* pScMod = ScModule::get(); if (pScMod->GetInputOptions().GetTextWysiwyg())
UpdateFontList();
SfxViewFrame *pFrame = SfxViewFrame::GetFirst( this ); while (pFrame)
{
SfxViewShell* pSh = pFrame->GetViewShell(); if (ScTabViewShell* pViewSh = dynamic_cast<ScTabViewShell*>(pSh))
{
ScInputHandler* pInputHdl = pScMod->GetInputHdl(pViewSh); if (pInputHdl)
pInputHdl->UpdateRefDevice();
}
pFrame = SfxViewFrame::GetNext( *pFrame, this );
}
}
} elseif (nDiffFlags & SfxPrinterChangeFlags::JOBSETUP)
{
SfxPrinter* pOldPrinter = m_pDocument->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.
m_pDocument->SetPrinter( pOldPrinter );
CalcOutputFactor(); // also with the new settings
}
}
if (nDiffFlags & SfxPrinterChangeFlags::OPTIONS)
{
m_pDocument->SetPrintOptions(); //! from new printer ???
}
void ScDocShell::CompareDocument( ScDocument& rOtherDoc )
{
ScChangeTrack* pTrack = m_pDocument->GetChangeTrack(); if ( pTrack && pTrack->GetFirst() )
{ //! there are changes -> inquiry if needs to be deleted
}
OUString aThisFile; const SfxMedium* pThisMed = GetMedium(); if (pThisMed)
aThisFile = pThisMed->GetName();
OUString aOtherFile;
ScDocShell* pOtherSh = rOtherDoc.GetDocumentShell(); if (pOtherSh)
{ const SfxMedium* pOtherMed = pOtherSh->GetMedium(); if (pOtherMed)
aOtherFile = pOtherMed->GetName();
} bool bSameDoc = ( aThisFile == aOtherFile && !aThisFile.isEmpty() ); if ( !bSameDoc )
{ // create change actions from comparing with the name of the user // who last saved the document // (only if comparing different documents)
void ScDocShell::MergeDocument( ScDocument& rOtherDoc, bool bShared, bool bCheckDuplicates, sal_uLong nOffset, ScChangeActionMergeMap* pMergeMap, bool bInverseMap )
{
ScTabViewShell* pViewSh = GetBestViewShell( false ); //! functions to the DocShell if (!pViewSh) return;
ScChangeTrack* pSourceTrack = rOtherDoc.GetChangeTrack(); if (!pSourceTrack) return; //! nothing to do - error notification?
ScChangeTrack* pThisTrack = m_pDocument->GetChangeTrack(); if ( !pThisTrack )
{ // turn on
m_pDocument->StartChangeTracking();
pThisTrack = m_pDocument->GetChangeTrack();
OSL_ENSURE(pThisTrack,"ChangeTracking not enabled?"); if ( !bShared )
{ // turn on visual RedLining
ScChangeViewSettings aChangeViewSet;
aChangeViewSet.SetShowChanges(true);
m_pDocument->SetChangeViewSettings(aChangeViewSet);
}
}
// include Nano seconds in compare? bool bIgnore100Sec = !pSourceTrack->IsTimeNanoSeconds() ||
!pThisTrack->IsTimeNanoSeconds();
// find common initial position
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 and pThisAction now point to the first "own" actions // The common actions before don't interest at all
//! Inquiry if the documents where equal before the change tracking !!!
// #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong const ScChangeAction* pLastSearchAction = pThisTrack->GetLast();
// Create MergeChangeData from the following actions
sal_uLong nNewActionCount = 0; const ScChangeAction* pCount = pSourceAction; while ( pCount )
{ if ( bShared || !ScChangeTrack::MergeIgnore( *pCount, nFirstNewNumber ) )
++nNewActionCount;
pCount = pCount->GetNext();
} if (!nNewActionCount) return; //! nothing to do - error notification? // from here on no return
sal_uLong nLastMergeAction = pSourceTrack->GetLast()->GetActionNumber(); // UpdateReference-Undo, valid references for the last common state
pSourceTrack->MergePrepare( pFirstMergeAction, bShared );
// adjust MergeChangeData to all yet following actions in this document // -> references valid for this document 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( GetDocument() ) ); break; case SC_CAT_DELETE_COLS : case SC_CAT_DELETE_ROWS : case SC_CAT_DELETE_TABS :
{ const ScChangeActionDel* pDel = static_cast<const ScChangeActionDel*>(pThisAction); if ( pDel->IsTopDelete() && !pDel->IsTabDeleteCol() )
{ // deleted table contains deleted cols, which are not
sal_uLong nStart, nEnd;
pSourceTrack->AppendDeleteRange(
pDel->GetOverAllRange().MakeRange( GetDocument() ), nullptr, nStart, nEnd );
}
} break; case SC_CAT_MOVE :
{ const ScChangeActionMove* pMove = static_cast<const ScChangeActionMove*>(pThisAction);
pSourceTrack->AppendMove( pMove->GetFromRange().MakeRange( GetDocument() ),
pMove->GetBigRange().MakeRange( GetDocument() ), nullptr );
} break; default:
{ // added to avoid warnings
}
}
}
pThisAction = pThisAction->GetNext();
}
LockPaint(); // #i73877# no repainting after each action
// take over MergeChangeData into the current document bool bHasRejected = false;
OUString aOldUser = pThisTrack->GetUser();
pThisTrack->SetUseFixDateTime( 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, *m_pDocument, pFirstSearchAction, pLastSearchAction, bIgnore100Sec ) )
{
bMergeAction = true;
}
} else
{ if ( !ScChangeTrack::MergeIgnore( *pSourceAction, nFirstNewNumber ) )
{
bMergeAction = true;
}
}
if ( bMergeAction )
{
ScChangeActionType eSourceType = pSourceAction->GetType(); if ( !bShared && pSourceAction->IsDeletedIn() )
{ //! does it need to be determined yet if really deleted in //! _this_ document?
// lies in a range, which was deleted in this document // -> is omitted //! ??? revert deletion action ??? //! ??? save action somewhere else ??? #if OSL_DEBUG_LEVEL > 0
OUString aValue; if ( eSourceType == SC_CAT_CONTENT )
aValue = static_cast<const ScChangeActionContent*>(pSourceAction)->GetNewString( *m_pDocument );
SAL_WARN( "sc", aValue << " omitted"); #endif
} else
{ //! Take over date/author/comment of the source action!
if ( bExecute )
{ // execute normally
ScRange aSourceRange = pSourceAction->GetBigRange().MakeRange( GetDocument() );
rMarkData.SelectOneTable( aSourceRange.aStart.Tab() ); switch ( eSourceType )
{ case SC_CAT_CONTENT:
{ //! Test if it was at the very bottom in the document, then automatic //! row insert ???
// undo own changes in shared document
pSharedTrack->Undo( nActStartOwn, nActEndOwn );
// clone change track for merging into own document
pTmpDoc.emplace(); for ( sal_Int32 nIndex = 0; nIndex < m_pDocument->GetTableCount(); ++nIndex )
{
OUString 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();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.