2010-10-12 15:59:00 +02:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
2000-09-18 16:07:07 +00:00
|
|
|
/*************************************************************************
|
|
|
|
*
|
2008-04-10 21:11:58 +00:00
|
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
2000-09-18 16:07:07 +00:00
|
|
|
*
|
2010-02-12 15:01:35 +01:00
|
|
|
* Copyright 2000, 2010 Oracle and/or its affiliates.
|
2000-09-18 16:07:07 +00:00
|
|
|
*
|
2008-04-10 21:11:58 +00:00
|
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
2000-09-18 16:07:07 +00:00
|
|
|
*
|
2008-04-10 21:11:58 +00:00
|
|
|
* This file is part of OpenOffice.org.
|
2000-09-18 16:07:07 +00:00
|
|
|
*
|
2008-04-10 21:11:58 +00:00
|
|
|
* 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.
|
2000-09-18 16:07:07 +00:00
|
|
|
*
|
2008-04-10 21:11:58 +00:00
|
|
|
* 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).
|
2000-09-18 16:07:07 +00:00
|
|
|
*
|
2008-04-10 21:11:58 +00:00
|
|
|
* 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.
|
2000-09-18 16:07:07 +00:00
|
|
|
*
|
|
|
|
************************************************************************/
|
|
|
|
|
2006-07-21 12:38:39 +00:00
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
|
|
|
|
// INCLUDE ---------------------------------------------------------------
|
|
|
|
|
2008-02-26 13:55:32 +00:00
|
|
|
#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
|
|
|
|
#include <com/sun/star/document/XDocumentProperties.hpp>
|
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
#include "scitems.hxx"
|
|
|
|
#include "rangelst.hxx"
|
2010-01-08 18:32:51 +01:00
|
|
|
#include <editeng/flstitem.hxx>
|
|
|
|
#include <editeng/paperinf.hxx>
|
|
|
|
#include <editeng/sizeitem.hxx>
|
2011-11-10 22:11:00 +00:00
|
|
|
#include <rtl/strbuf.hxx>
|
2004-10-04 19:15:01 +00:00
|
|
|
#include <sfx2/viewfrm.hxx>
|
2004-02-03 19:30:15 +00:00
|
|
|
#include <sfx2/app.hxx>
|
2001-01-30 16:48:52 +00:00
|
|
|
#include <sfx2/docfile.hxx>
|
2000-09-18 16:07:07 +00:00
|
|
|
#include <sfx2/printer.hxx>
|
|
|
|
#include <svtools/ctrltool.hxx>
|
2011-11-10 22:11:00 +00:00
|
|
|
#include <svx/pageitem.hxx>
|
|
|
|
#include <svx/postattr.hxx>
|
|
|
|
#include <unotools/localedatawrapper.hxx>
|
|
|
|
#include <unotools/misccfg.hxx>
|
2000-09-18 16:07:07 +00:00
|
|
|
#include <vcl/virdev.hxx>
|
|
|
|
#include <vcl/svapp.hxx>
|
|
|
|
#include <vcl/msgbox.hxx>
|
2001-01-31 18:37:51 +00:00
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
#include "docsh.hxx"
|
2006-11-22 09:45:44 +00:00
|
|
|
#include "docshimp.hxx"
|
2000-09-18 16:07:07 +00:00
|
|
|
#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"
|
2001-05-11 16:09:50 +00:00
|
|
|
#include "inputopt.hxx"
|
2001-07-23 14:18:23 +00:00
|
|
|
#include "drwlayer.hxx"
|
2001-09-28 16:16:55 +00:00
|
|
|
#include "inputhdl.hxx"
|
2008-03-07 11:19:32 +00:00
|
|
|
#include "conflictsdlg.hxx"
|
|
|
|
#include "globstr.hrc"
|
2011-11-23 21:32:01 -05:00
|
|
|
#include "markdata.hxx"
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
|
|
|
//
|
|
|
|
// 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 ) );
|
|
|
|
SFX_APP()->Broadcast(SfxSimpleHint( FID_ANYDATACHANGED )); // Navigator
|
|
|
|
//! Navigator direkt benachrichtigen!
|
|
|
|
}
|
|
|
|
|
INTEGRATION: CWS rowlimit (1.16.202); FILE MERGED
2004/03/25 21:36:02 er 1.16.202.4: #i1967# use ValidCol,ValidRow,ValidTab
2004/02/13 11:33:22 er 1.16.202.3: #i1967# SCCOL,SCROW,SCTAB replace USHORT; SCsCOL,SCsROW,SCsTAB replace short
2004/02/11 13:58:37 er 1.16.202.2: RESYNC: (1.16-1.18); FILE MERGED
2004/01/14 15:50:09 er 1.16.202.1: #i1967# SCCOL,SCROW,SCTAB replace USHORT; SCsCOL,SCsROW,SCsTAB replace short
2004-06-04 10:23:53 +00:00
|
|
|
void ScDocShell::PostPaint( SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab,
|
2011-01-17 13:20:22 +01:00
|
|
|
SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, sal_uInt16 nPart,
|
|
|
|
sal_uInt16 nExtFlags )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2011-09-09 22:14:37 -04:00
|
|
|
ScRange aRange(nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
|
|
|
|
PostPaint(aRange, nPart, nExtFlags);
|
|
|
|
}
|
|
|
|
|
2011-09-09 23:02:00 -04:00
|
|
|
void ScDocShell::PostPaint( const ScRangeList& rRanges, sal_uInt16 nPart, sal_uInt16 nExtFlags )
|
2011-09-09 22:14:37 -04:00
|
|
|
{
|
2011-09-09 23:02:00 -04:00
|
|
|
ScRangeList aPaintRanges;
|
|
|
|
for (size_t i = 0, n = rRanges.size(); i < n; ++i)
|
|
|
|
{
|
|
|
|
const ScRange& rRange = *rRanges[i];
|
|
|
|
SCCOL nCol1 = rRange.aStart.Col(), nCol2 = rRange.aEnd.Col();
|
|
|
|
SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row();
|
|
|
|
SCTAB nTab1 = rRange.aStart.Tab(), nTab2 = rRange.aEnd.Tab();
|
2011-09-09 22:14:37 -04:00
|
|
|
|
2011-09-09 23:02:00 -04:00
|
|
|
if (!ValidCol(nCol1)) nCol1 = MAXCOL;
|
|
|
|
if (!ValidRow(nRow1)) nRow1 = MAXROW;
|
|
|
|
if (!ValidCol(nCol2)) nCol2 = MAXCOL;
|
|
|
|
if (!ValidRow(nRow2)) nRow2 = MAXROW;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2011-09-09 23:02:00 -04:00
|
|
|
if ( pPaintLockData )
|
2005-10-21 11:03:35 +00:00
|
|
|
{
|
2011-09-09 23:02:00 -04:00
|
|
|
// #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( nCol1, nRow1, nTab1,
|
|
|
|
nCol2, nRow2, nTab2 ), nLockPart );
|
|
|
|
}
|
|
|
|
|
|
|
|
nPart &= PAINT_EXTRAS; // for broadcasting
|
|
|
|
if (!nPart)
|
|
|
|
continue;
|
2005-10-21 11:03:35 +00:00
|
|
|
}
|
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2011-09-09 23:02:00 -04:00
|
|
|
if (nExtFlags & SC_PF_LINES) // Platz fuer Linien beruecksichtigen
|
|
|
|
{
|
|
|
|
//! Abfrage auf versteckte Spalten/Zeilen!
|
|
|
|
if (nCol1>0) --nCol1;
|
|
|
|
if (nCol2<MAXCOL) ++nCol2;
|
|
|
|
if (nRow1>0) --nRow1;
|
|
|
|
if (nRow2<MAXROW) ++nRow2;
|
|
|
|
}
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2011-09-09 23:02:00 -04:00
|
|
|
// um zusammengefasste erweitern
|
|
|
|
if (nExtFlags & SC_PF_TESTMERGE)
|
|
|
|
aDocument.ExtendMerge( nCol1, nRow1, nCol2, nRow2, nTab1 );
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2011-09-09 23:02:00 -04:00
|
|
|
if ( nCol1 != 0 || nCol2 != MAXCOL )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2011-09-09 23:02:00 -04:00
|
|
|
// 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( nCol1,nRow1,nTab1,
|
|
|
|
MAXCOL,nRow2,nTab2, HASATTR_ROTATE | HASATTR_RIGHTORCENTER ) )
|
|
|
|
{
|
|
|
|
nCol1 = 0;
|
|
|
|
nCol2 = MAXCOL;
|
|
|
|
}
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
2011-09-09 23:02:00 -04:00
|
|
|
aPaintRanges.Append(ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2));
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
2011-09-09 23:23:24 -04:00
|
|
|
Broadcast(ScPaintHint(aPaintRanges.Combine(), nPart));
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ScDocShell::PostPaintGridAll()
|
|
|
|
{
|
|
|
|
PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID );
|
|
|
|
}
|
|
|
|
|
INTEGRATION: CWS rowlimit (1.16.202); FILE MERGED
2004/03/25 21:36:02 er 1.16.202.4: #i1967# use ValidCol,ValidRow,ValidTab
2004/02/13 11:33:22 er 1.16.202.3: #i1967# SCCOL,SCROW,SCTAB replace USHORT; SCsCOL,SCsROW,SCsTAB replace short
2004/02/11 13:58:37 er 1.16.202.2: RESYNC: (1.16-1.18); FILE MERGED
2004/01/14 15:50:09 er 1.16.202.1: #i1967# SCCOL,SCROW,SCTAB replace USHORT; SCsCOL,SCsROW,SCsTAB replace short
2004-06-04 10:23:53 +00:00
|
|
|
void ScDocShell::PostPaintCell( SCCOL nCol, SCROW nRow, SCTAB nTab )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PAINT_GRID, SC_PF_TESTMERGE );
|
|
|
|
}
|
|
|
|
|
2009-03-02 14:19:13 +00:00
|
|
|
void ScDocShell::PostPaintCell( const ScAddress& rPos )
|
|
|
|
{
|
|
|
|
PostPaintCell( rPos.Col(), rPos.Row(), rPos.Tab() );
|
|
|
|
}
|
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
void ScDocShell::PostPaintExtras()
|
|
|
|
{
|
|
|
|
PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS );
|
|
|
|
}
|
|
|
|
|
2011-01-17 13:20:22 +01:00
|
|
|
void ScDocShell::UpdatePaintExt( sal_uInt16& rExtFlags, const ScRange& rRange )
|
2004-02-03 11:34:59 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-17 13:20:22 +01:00
|
|
|
void ScDocShell::UpdatePaintExt( sal_uInt16& rExtFlags, SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab,
|
INTEGRATION: CWS rowlimit (1.16.202); FILE MERGED
2004/03/25 21:36:02 er 1.16.202.4: #i1967# use ValidCol,ValidRow,ValidTab
2004/02/13 11:33:22 er 1.16.202.3: #i1967# SCCOL,SCROW,SCTAB replace USHORT; SCsCOL,SCsROW,SCsTAB replace short
2004/02/11 13:58:37 er 1.16.202.2: RESYNC: (1.16-1.18); FILE MERGED
2004/01/14 15:50:09 er 1.16.202.1: #i1967# SCCOL,SCROW,SCTAB replace USHORT; SCsCOL,SCsROW,SCsTAB replace short
2004-06-04 10:23:53 +00:00
|
|
|
SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab )
|
2004-02-03 11:34:59 +00:00
|
|
|
{
|
|
|
|
UpdatePaintExt( rExtFlags, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ) );
|
|
|
|
}
|
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
2011-01-17 13:20:22 +01:00
|
|
|
void ScDocShell::LockPaint_Impl(sal_Bool bDoc)
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2004-05-03 12:57:42 +00:00
|
|
|
if ( !pPaintLockData )
|
2000-09-18 16:07:07 +00:00
|
|
|
pPaintLockData = new ScPaintLockData(0); //! Modus...
|
2004-05-03 12:57:42 +00:00
|
|
|
pPaintLockData->IncLevel(bDoc);
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
2011-01-17 13:20:22 +01:00
|
|
|
void ScDocShell::UnlockPaint_Impl(sal_Bool bDoc)
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
if ( pPaintLockData )
|
|
|
|
{
|
2001-07-23 14:18:23 +00:00
|
|
|
if ( pPaintLockData->GetLevel(bDoc) )
|
|
|
|
pPaintLockData->DecLevel(bDoc);
|
2004-05-03 12:57:42 +00:00
|
|
|
if (!pPaintLockData->GetLevel(!bDoc) && !pPaintLockData->GetLevel(bDoc))
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
// Paint jetzt ausfuehren
|
|
|
|
|
|
|
|
ScPaintLockData* pPaint = pPaintLockData;
|
|
|
|
pPaintLockData = NULL; // nicht weitersammeln
|
|
|
|
|
|
|
|
ScRangeListRef xRangeList = pPaint->GetRangeList();
|
|
|
|
if (xRangeList)
|
|
|
|
{
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_uInt16 nParts = pPaint->GetParts();
|
2010-12-08 22:38:24 -08:00
|
|
|
for ( size_t i = 0, nCount = xRangeList->size(); i < nCount; i++ )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
//! nExtFlags ???
|
2010-12-10 16:07:50 -05:00
|
|
|
ScRange aRange = *(*xRangeList)[i];
|
2000-09-18 16:07:07 +00:00
|
|
|
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
|
2008-01-29 14:41:28 +00:00
|
|
|
{
|
2011-03-01 19:05:02 +01:00
|
|
|
OSL_FAIL("UnlockPaint ohne LockPaint");
|
2008-01-29 14:41:28 +00:00
|
|
|
}
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
2011-01-17 13:20:22 +01:00
|
|
|
void ScDocShell::LockDocument_Impl(sal_uInt16 nNew)
|
2001-07-23 14:18:23 +00:00
|
|
|
{
|
|
|
|
if (!nDocumentLock)
|
|
|
|
{
|
|
|
|
ScDrawLayer* pDrawLayer = aDocument.GetDrawLayer();
|
|
|
|
if (pDrawLayer)
|
2010-12-17 20:43:45 +00:00
|
|
|
pDrawLayer->setLock(true);
|
2001-07-23 14:18:23 +00:00
|
|
|
}
|
|
|
|
nDocumentLock = nNew;
|
|
|
|
}
|
|
|
|
|
2011-01-17 13:20:22 +01:00
|
|
|
void ScDocShell::UnlockDocument_Impl(sal_uInt16 nNew)
|
2001-07-23 14:18:23 +00:00
|
|
|
{
|
|
|
|
nDocumentLock = nNew;
|
|
|
|
if (!nDocumentLock)
|
|
|
|
{
|
|
|
|
ScDrawLayer* pDrawLayer = aDocument.GetDrawLayer();
|
|
|
|
if (pDrawLayer)
|
2010-12-17 20:43:45 +00:00
|
|
|
pDrawLayer->setLock(false);
|
2001-07-23 14:18:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_uInt16 ScDocShell::GetLockCount() const
|
2001-07-23 14:18:23 +00:00
|
|
|
{
|
|
|
|
return nDocumentLock;
|
|
|
|
}
|
|
|
|
|
2011-01-17 13:20:22 +01:00
|
|
|
void ScDocShell::SetLockCount(sal_uInt16 nNew)
|
2001-07-23 14:18:23 +00:00
|
|
|
{
|
|
|
|
if (nNew) // setzen
|
|
|
|
{
|
|
|
|
if ( !pPaintLockData )
|
|
|
|
pPaintLockData = new ScPaintLockData(0); //! Modus...
|
2011-01-17 13:20:22 +01:00
|
|
|
pPaintLockData->SetLevel(nNew-1, sal_True);
|
2001-07-23 14:18:23 +00:00
|
|
|
LockDocument_Impl(nNew);
|
|
|
|
}
|
|
|
|
else if (pPaintLockData) // loeschen
|
|
|
|
{
|
2011-01-17 13:20:22 +01:00
|
|
|
pPaintLockData->SetLevel(0, sal_True); // bei Unlock sofort ausfuehren
|
|
|
|
UnlockPaint_Impl(sal_True); // jetzt
|
2001-07-23 14:18:23 +00:00
|
|
|
UnlockDocument_Impl(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScDocShell::LockPaint()
|
|
|
|
{
|
2011-03-10 16:55:21 -05:00
|
|
|
LockPaint_Impl(false);
|
2001-07-23 14:18:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ScDocShell::UnlockPaint()
|
|
|
|
{
|
2011-03-10 16:55:21 -05:00
|
|
|
UnlockPaint_Impl(false);
|
2001-07-23 14:18:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ScDocShell::LockDocument()
|
|
|
|
{
|
2011-01-17 13:20:22 +01:00
|
|
|
LockPaint_Impl(sal_True);
|
2001-07-23 14:18:23 +00:00
|
|
|
LockDocument_Impl(nDocumentLock + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScDocShell::UnlockDocument()
|
|
|
|
{
|
|
|
|
if (nDocumentLock)
|
|
|
|
{
|
2011-01-17 13:20:22 +01:00
|
|
|
UnlockPaint_Impl(sal_True);
|
2001-08-14 17:14:53 +00:00
|
|
|
UnlockDocument_Impl(nDocumentLock - 1);
|
2001-07-23 14:18:23 +00:00
|
|
|
}
|
|
|
|
else
|
2008-01-29 14:41:28 +00:00
|
|
|
{
|
2011-03-01 19:05:02 +01:00
|
|
|
OSL_FAIL("UnlockDocument without LockDocument");
|
2008-01-29 14:41:28 +00:00
|
|
|
}
|
2001-07-23 14:18:23 +00:00
|
|
|
}
|
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
2011-01-17 13:20:22 +01:00
|
|
|
void ScDocShell::SetInplace( sal_Bool bInplace )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
if (bIsInplace != bInplace)
|
|
|
|
{
|
|
|
|
bIsInplace = bInplace;
|
|
|
|
CalcOutputFactor();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScDocShell::CalcOutputFactor()
|
|
|
|
{
|
|
|
|
if (bIsInplace)
|
|
|
|
{
|
|
|
|
nPrtToScreenFactor = 1.0; // passt sonst nicht zur inaktiven Darstellung
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_Bool bTextWysiwyg = SC_MOD()->GetInputOptions().GetTextWysiwyg();
|
2001-05-11 16:09:50 +00:00
|
|
|
if (bTextWysiwyg)
|
|
|
|
{
|
|
|
|
nPrtToScreenFactor = 1.0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
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;
|
2006-05-04 14:03:33 +00:00
|
|
|
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);
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
VirtualDevice aVirtWindow( *Application::GetDefaultDevice() );
|
|
|
|
aVirtWindow.SetMapMode(MAP_PIXEL);
|
2002-03-11 13:08:12 +00:00
|
|
|
pPattern->GetFont(aDefFont, SC_AUTOCOL_BLACK, &aVirtWindow); // font color doesn't matter here
|
2000-09-18 16:07:07 +00:00
|
|
|
aVirtWindow.SetFont(aDefFont);
|
|
|
|
nWindowWidth = aVirtWindow.GetTextWidth(aTestString);
|
|
|
|
nWindowWidth = (long) ( nWindowWidth / ScGlobal::nScreenPPTX * HMM_PER_TWIPS );
|
|
|
|
|
|
|
|
if (nPrinterWidth && nWindowWidth)
|
|
|
|
nPrtToScreenFactor = nPrinterWidth / (double) nWindowWidth;
|
|
|
|
else
|
|
|
|
{
|
2011-03-01 19:05:02 +01:00
|
|
|
OSL_FAIL("GetTextSize gibt 0 ??");
|
2000-09-18 16:07:07 +00:00
|
|
|
nPrtToScreenFactor = 1.0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
double ScDocShell::GetOutputFactor() const
|
|
|
|
{
|
|
|
|
return nPrtToScreenFactor;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
|
|
|
2010-06-04 18:59:28 +02:00
|
|
|
void ScDocShell::InitOptions(bool bForLoading) // called from InitNew and Load
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
// Einstellungen aus dem SpellCheckCfg kommen in Doc- und ViewOptions
|
|
|
|
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_uInt16 nDefLang, nCjkLang, nCtlLang;
|
|
|
|
sal_Bool bAutoSpell;
|
2008-12-15 12:01:46 +00:00
|
|
|
ScModule::GetSpellSettings( nDefLang, nCjkLang, nCtlLang, bAutoSpell );
|
2000-09-18 16:07:07 +00:00
|
|
|
ScModule* pScMod = SC_MOD();
|
|
|
|
|
|
|
|
ScDocOptions aDocOpt = pScMod->GetDocOptions();
|
2012-04-10 00:09:40 +02:00
|
|
|
ScFormulaOptions aFormulaOpt = pScMod->GetFormulaOptions();
|
2000-09-18 16:07:07 +00:00
|
|
|
ScViewOptions aViewOpt = pScMod->GetViewOptions();
|
|
|
|
aDocOpt.SetAutoSpell( bAutoSpell );
|
|
|
|
|
|
|
|
// zweistellige Jahreszahleneingabe aus Extras->Optionen->Allgemein->Sonstiges
|
2011-01-17 13:20:22 +01:00
|
|
|
aDocOpt.SetYear2000( sal::static_int_cast<sal_uInt16>( ::utl::MiscCfg().GetYear2000() ) );
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2010-06-04 18:59:28 +02:00
|
|
|
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 );
|
|
|
|
}
|
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
aDocument.SetDocOptions( aDocOpt );
|
|
|
|
aDocument.SetViewOptions( aViewOpt );
|
2012-04-10 00:09:40 +02:00
|
|
|
SetFormulaOptions( aFormulaOpt );
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
// Druck-Optionen werden jetzt direkt vor dem Drucken gesetzt
|
|
|
|
|
2000-11-26 12:56:47 +00:00
|
|
|
aDocument.SetLanguage( (LanguageType) nDefLang, (LanguageType) nCjkLang, (LanguageType) nCtlLang );
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
|
|
|
|
|
|
Printer* ScDocShell::GetDocumentPrinter() // fuer OLE
|
|
|
|
{
|
|
|
|
return aDocument.GetPrinter();
|
|
|
|
}
|
|
|
|
|
2011-01-17 13:20:22 +01:00
|
|
|
SfxPrinter* ScDocShell::GetPrinter(sal_Bool bCreateIfNotExist)
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2006-05-04 14:03:33 +00:00
|
|
|
return aDocument.GetPrinter(bCreateIfNotExist);
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ScDocShell::UpdateFontList()
|
|
|
|
{
|
2006-11-22 09:45:44 +00:00
|
|
|
delete pImpl->pFontList;
|
|
|
|
// pImpl->pFontList = new FontList( GetPrinter(), Application::GetDefaultDevice() );
|
2011-03-10 16:55:21 -05:00
|
|
|
pImpl->pFontList = new FontList( GetRefDevice(), NULL, false ); // sal_False or sal_True???
|
2006-11-22 09:45:44 +00:00
|
|
|
SvxFontListItem aFontListItem( pImpl->pFontList, SID_ATTR_CHAR_FONTLIST );
|
2000-09-18 16:07:07 +00:00
|
|
|
PutItem( aFontListItem );
|
|
|
|
|
|
|
|
CalcOutputFactor();
|
|
|
|
}
|
|
|
|
|
2006-05-04 14:03:33 +00:00
|
|
|
OutputDevice* ScDocShell::GetRefDevice()
|
|
|
|
{
|
|
|
|
return aDocument.GetRefDevice();
|
|
|
|
}
|
|
|
|
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_uInt16 ScDocShell::SetPrinter( SfxPrinter* pNewPrinter, sal_uInt16 nDiffFlags )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2011-03-10 16:55:21 -05:00
|
|
|
SfxPrinter *pOld = aDocument.GetPrinter( false );
|
2009-09-18 10:15:03 +00:00
|
|
|
if ( pOld && pOld->IsPrinting() )
|
|
|
|
return SFX_PRINTERROR_BUSY;
|
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
if (nDiffFlags & SFX_PRINTER_PRINTER)
|
|
|
|
{
|
|
|
|
if ( aDocument.GetPrinter() != pNewPrinter )
|
|
|
|
{
|
|
|
|
aDocument.SetPrinter( pNewPrinter );
|
|
|
|
aDocument.SetPrintOptions();
|
|
|
|
|
2006-05-04 14:03:33 +00:00
|
|
|
// MT: Use UpdateFontList: Will use Printer fonts only if needed!
|
|
|
|
/*
|
2006-11-22 09:45:44 +00:00
|
|
|
delete pImpl->pFontList;
|
|
|
|
pImpl->pFontList = new FontList( pNewPrinter, Application::GetDefaultDevice() );
|
|
|
|
SvxFontListItem aFontListItem( pImpl->pFontList, SID_ATTR_CHAR_FONTLIST );
|
2000-09-18 16:07:07 +00:00
|
|
|
PutItem( aFontListItem );
|
|
|
|
|
|
|
|
CalcOutputFactor();
|
2006-05-04 14:03:33 +00:00
|
|
|
*/
|
|
|
|
if ( SC_MOD()->GetInputOptions().GetTextWysiwyg() )
|
|
|
|
UpdateFontList();
|
2001-09-28 16:16:55 +00:00
|
|
|
|
|
|
|
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 );
|
|
|
|
}
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (nDiffFlags & SFX_PRINTER_JOBSETUP)
|
|
|
|
{
|
|
|
|
SfxPrinter* pOldPrinter = aDocument.GetPrinter();
|
|
|
|
if (pOldPrinter)
|
2003-03-26 17:07:02 +00:00
|
|
|
{
|
2000-09-18 16:07:07 +00:00
|
|
|
pOldPrinter->SetJobSetup( pNewPrinter->GetJobSetup() );
|
2003-03-26 17:07:02 +00:00
|
|
|
|
|
|
|
// #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
|
|
|
|
}
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_Bool bWasLand = rOldItem.IsLandscape();
|
|
|
|
sal_Bool bNewLand = ( pNewPrinter->GetOrientation() == ORIENTATION_LANDSCAPE );
|
2000-09-18 16:07:07 +00:00
|
|
|
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;
|
|
|
|
|
INTEGRATION: CWS rowlimit (1.16.202); FILE MERGED
2004/03/25 21:36:02 er 1.16.202.4: #i1967# use ValidCol,ValidRow,ValidTab
2004/02/13 11:33:22 er 1.16.202.3: #i1967# SCCOL,SCROW,SCTAB replace USHORT; SCsCOL,SCsROW,SCsTAB replace short
2004/02/11 13:58:37 er 1.16.202.2: RESYNC: (1.16-1.18); FILE MERGED
2004/01/14 15:50:09 er 1.16.202.1: #i1967# SCCOL,SCROW,SCTAB replace USHORT; SCsCOL,SCsROW,SCsTAB replace short
2004-06-04 10:23:53 +00:00
|
|
|
SCTAB nTab = rPos.Tab();
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_uLong nNumber = pAction->GetActionNumber();
|
2000-09-18 16:07:07 +00:00
|
|
|
pTrack->NotifyModified( SC_CTM_CHANGE, nNumber, nNumber );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-17 13:20:22 +01:00
|
|
|
void ScDocShell::ExecuteChangeCommentDialog( ScChangeAction* pAction, Window* pParent,sal_Bool bPrevNext)
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
if (!pAction) return; // ohne Aktion ist nichts..
|
|
|
|
|
|
|
|
String aComment = pAction->GetComment();
|
|
|
|
String aAuthor = pAction->GetUser();
|
|
|
|
|
|
|
|
DateTime aDT = pAction->GetDateTime();
|
2001-07-11 15:02:59 +00:00
|
|
|
String aDate = ScGlobal::pLocaleData->getDate( aDT );
|
2000-09-18 16:07:07 +00:00
|
|
|
aDate += ' ';
|
2011-03-10 16:55:21 -05:00
|
|
|
aDate += ScGlobal::pLocaleData->getTime( aDT, false, false );
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
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();
|
|
|
|
|
2001-01-30 16:48:52 +00:00
|
|
|
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();
|
|
|
|
}
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_Bool bSameDoc = ( aThisFile == aOtherFile && aThisFile.Len() );
|
2001-01-30 16:48:52 +00:00
|
|
|
if ( !bSameDoc )
|
|
|
|
{
|
|
|
|
// create change actions from comparing with the name of the user
|
|
|
|
// who last saved the document
|
|
|
|
// (only if comparing different documents)
|
|
|
|
|
2008-02-26 13:55:32 +00:00
|
|
|
using namespace ::com::sun::star;
|
|
|
|
uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
|
|
|
|
GetModel(), uno::UNO_QUERY_THROW);
|
|
|
|
uno::Reference<document::XDocumentProperties> xDocProps(
|
|
|
|
xDPS->getDocumentProperties());
|
2011-05-21 15:04:26 +02:00
|
|
|
OSL_ENSURE(xDocProps.is(), "no DocumentProperties");
|
2008-02-26 13:55:32 +00:00
|
|
|
String aDocUser = xDocProps->getModifiedBy();
|
|
|
|
|
2001-01-30 16:48:52 +00:00
|
|
|
if ( aDocUser.Len() )
|
|
|
|
pTrack->SetUser( aDocUser );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
aDocument.CompareDocument( rOtherDoc );
|
|
|
|
|
2001-01-30 16:48:52 +00:00
|
|
|
pTrack = aDocument.GetChangeTrack();
|
|
|
|
if ( pTrack )
|
|
|
|
pTrack->SetUser( aOldUser );
|
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
PostPaintGridAll();
|
|
|
|
SetDocumentModified();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Merge (Aenderungen zusammenfuehren)
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------
|
|
|
|
|
2011-01-17 13:20:22 +01:00
|
|
|
inline sal_Bool lcl_Equal( const ScChangeAction* pA, const ScChangeAction* pB, sal_Bool bIgnore100Sec )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
return pA && pB &&
|
2002-04-15 10:22:15 +00:00
|
|
|
pA->GetActionNumber() == pB->GetActionNumber() &&
|
|
|
|
pA->GetType() == pB->GetType() &&
|
|
|
|
pA->GetUser() == pB->GetUser() &&
|
|
|
|
(bIgnore100Sec ?
|
|
|
|
pA->GetDateTimeUTC().IsEqualIgnore100Sec( pB->GetDateTimeUTC() ) :
|
|
|
|
pA->GetDateTimeUTC() == pB->GetDateTimeUTC());
|
2000-09-18 16:07:07 +00:00
|
|
|
// State nicht vergleichen, falls eine alte Aenderung akzeptiert wurde
|
|
|
|
}
|
|
|
|
|
2011-01-17 13:20:22 +01:00
|
|
|
bool lcl_FindAction( ScDocument* pDoc, const ScChangeAction* pAction, ScDocument* pSearchDoc, const ScChangeAction* pFirstSearchAction, const ScChangeAction* pLastSearchAction, sal_Bool bIgnore100Sec )
|
2008-03-07 11:19:32 +00:00
|
|
|
{
|
2009-02-11 15:19:01 +00:00
|
|
|
if ( !pDoc || !pAction || !pSearchDoc || !pFirstSearchAction || !pLastSearchAction )
|
2008-03-07 11:19:32 +00:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_uLong nLastSearchAction = pLastSearchAction->GetActionNumber();
|
2008-03-07 11:19:32 +00:00
|
|
|
const ScChangeAction* pA = pFirstSearchAction;
|
2009-02-11 15:19:01 +00:00
|
|
|
while ( pA && pA->GetActionNumber() <= nLastSearchAction )
|
2008-03-07 11:19:32 +00:00
|
|
|
{
|
|
|
|
if ( pAction->GetType() == pA->GetType() &&
|
|
|
|
pAction->GetUser() == pA->GetUser() &&
|
|
|
|
(bIgnore100Sec ?
|
|
|
|
pAction->GetDateTimeUTC().IsEqualIgnore100Sec( pA->GetDateTimeUTC() ) :
|
|
|
|
pAction->GetDateTimeUTC() == pA->GetDateTimeUTC() ) &&
|
|
|
|
pAction->GetBigRange() == pA->GetBigRange() )
|
|
|
|
{
|
2012-02-02 23:42:34 -05:00
|
|
|
rtl::OUString aActionDesc;
|
|
|
|
pAction->GetDescription(aActionDesc, pDoc, true);
|
|
|
|
rtl::OUString aADesc;
|
|
|
|
pA->GetDescription(aADesc, pSearchDoc, true);
|
|
|
|
if (aActionDesc.equals(aADesc))
|
2008-03-07 11:19:32 +00:00
|
|
|
{
|
2011-03-01 19:05:02 +01:00
|
|
|
OSL_FAIL( "lcl_FindAction(): found equal action!" );
|
2008-03-07 11:19:32 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pA = pA->GetNext();
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-01-17 13:20:22 +01:00
|
|
|
void ScDocShell::MergeDocument( ScDocument& rOtherDoc, bool bShared, bool bCheckDuplicates, sal_uLong nOffset, ScChangeActionMergeMap* pMergeMap, bool bInverseMap )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2011-03-10 16:55:21 -05:00
|
|
|
ScTabViewShell* pViewSh = GetBestViewShell( false ); //! Funktionen an die DocShell
|
2000-09-18 16:07:07 +00:00
|
|
|
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();
|
2011-05-21 15:04:26 +02:00
|
|
|
OSL_ENSURE(pThisTrack,"ChangeTracking nicht angeschaltet?");
|
2008-03-07 11:19:32 +00:00
|
|
|
if ( !bShared )
|
|
|
|
{
|
2011-03-01 14:29:24 +01:00
|
|
|
// visuelles RedLining einschalten
|
2008-03-07 11:19:32 +00:00
|
|
|
ScChangeViewSettings aChangeViewSet;
|
2011-01-17 13:20:22 +01:00
|
|
|
aChangeViewSet.SetShowChanges(sal_True);
|
2008-03-07 11:19:32 +00:00
|
|
|
aDocument.SetChangeViewSettings(aChangeViewSet);
|
|
|
|
}
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
2011-03-01 14:29:24 +01:00
|
|
|
// include 100th seconds in compare?
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_Bool bIgnore100Sec = !pSourceTrack->IsTime100thSeconds() ||
|
2002-04-15 10:22:15 +00:00
|
|
|
!pThisTrack->IsTime100thSeconds();
|
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
// gemeinsame Ausgangsposition suchen
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_uLong nFirstNewNumber = 0;
|
2000-09-18 16:07:07 +00:00
|
|
|
const ScChangeAction* pSourceAction = pSourceTrack->GetFirst();
|
|
|
|
const ScChangeAction* pThisAction = pThisTrack->GetFirst();
|
2002-04-15 10:22:15 +00:00
|
|
|
// skip identical actions
|
|
|
|
while ( lcl_Equal( pSourceAction, pThisAction, bIgnore100Sec ) )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
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;
|
2008-03-07 11:19:32 +00:00
|
|
|
const ScChangeAction* pFirstSearchAction = pThisAction;
|
2009-02-11 15:19:01 +00:00
|
|
|
|
|
|
|
// #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
|
|
|
|
const ScChangeAction* pLastSearchAction = pThisTrack->GetLast();
|
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
// MergeChangeData aus den folgenden Aktionen erzeugen
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_uLong nNewActionCount = 0;
|
2000-09-18 16:07:07 +00:00
|
|
|
const ScChangeAction* pCount = pSourceAction;
|
|
|
|
while ( pCount )
|
|
|
|
{
|
2008-03-07 11:19:32 +00:00
|
|
|
if ( bShared || !ScChangeTrack::MergeIgnore( *pCount, nFirstNewNumber ) )
|
2000-09-18 16:07:07 +00:00
|
|
|
++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 );
|
|
|
|
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_uLong nLastMergeAction = pSourceTrack->GetLast()->GetActionNumber();
|
2000-09-18 16:07:07 +00:00
|
|
|
// UpdateReference-Undo, gueltige Referenzen fuer den letzten gemeinsamen Zustand
|
2009-02-11 15:19:01 +00:00
|
|
|
pSourceTrack->MergePrepare( (ScChangeAction*) pFirstMergeAction, bShared );
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
// MergeChangeData an alle noch folgenden Aktionen in diesem Dokument anpassen
|
|
|
|
// -> Referenzen gueltig fuer dieses Dokument
|
|
|
|
while ( pThisAction )
|
|
|
|
{
|
2008-04-15 13:12:39 +00:00
|
|
|
// #i87049# [Collaboration] Conflict between delete row and insert content is not merged correctly
|
|
|
|
if ( !bShared || !ScChangeTrack::MergeIgnore( *pThisAction, nFirstNewNumber ) )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2008-04-15 13:12:39 +00:00
|
|
|
ScChangeActionType eType = pThisAction->GetType();
|
|
|
|
switch ( eType )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2008-04-15 13:12:39 +00:00
|
|
|
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
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_uLong nStart, nEnd;
|
2008-04-15 13:12:39 +00:00
|
|
|
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
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
2007-02-27 12:07:24 +00:00
|
|
|
}
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
pThisAction = pThisAction->GetNext();
|
|
|
|
}
|
|
|
|
|
2007-02-05 10:43:39 +00:00
|
|
|
LockPaint(); // #i73877# no repainting after each action
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
// MergeChangeData in das aktuelle Dokument uebernehmen
|
2011-03-10 16:55:21 -05:00
|
|
|
sal_Bool bHasRejected = false;
|
2000-09-18 16:07:07 +00:00
|
|
|
String aOldUser = pThisTrack->GetUser();
|
2011-01-17 13:20:22 +01:00
|
|
|
pThisTrack->SetUseFixDateTime( sal_True );
|
2000-09-18 16:07:07 +00:00
|
|
|
ScMarkData& rMarkData = pViewSh->GetViewData()->GetMarkData();
|
|
|
|
ScMarkData aOldMarkData( rMarkData );
|
|
|
|
pSourceAction = pFirstMergeAction;
|
|
|
|
while ( pSourceAction && pSourceAction->GetActionNumber() <= nLastMergeAction )
|
|
|
|
{
|
2008-03-07 11:19:32 +00:00
|
|
|
bool bMergeAction = false;
|
|
|
|
if ( bShared )
|
|
|
|
{
|
2009-02-11 15:19:01 +00:00
|
|
|
if ( !bCheckDuplicates || !lcl_FindAction( &rOtherDoc, pSourceAction, &aDocument, pFirstSearchAction, pLastSearchAction, bIgnore100Sec ) )
|
2008-03-07 11:19:32 +00:00
|
|
|
{
|
|
|
|
bMergeAction = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( !ScChangeTrack::MergeIgnore( *pSourceAction, nFirstNewNumber ) )
|
|
|
|
{
|
|
|
|
bMergeAction = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( bMergeAction )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
ScChangeActionType eSourceType = pSourceAction->GetType();
|
2008-03-07 11:19:32 +00:00
|
|
|
if ( !bShared && pSourceAction->IsDeletedIn() )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
//! 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 ???
|
2011-05-21 15:04:26 +02:00
|
|
|
#if OSL_DEBUG_LEVEL > 0
|
2012-02-03 11:18:41 +01:00
|
|
|
rtl::OUString aValue;
|
2000-09-18 16:07:07 +00:00
|
|
|
if ( eSourceType == SC_CAT_CONTENT )
|
|
|
|
((const ScChangeActionContent*)pSourceAction)->GetNewString( aValue );
|
2011-11-10 22:11:00 +00:00
|
|
|
rtl::OStringBuffer aError(rtl::OUStringToOString(aValue,
|
|
|
|
osl_getThreadTextEncoding()));
|
|
|
|
aError.append(RTL_CONSTASCII_STRINGPARAM(" weggelassen"));
|
|
|
|
OSL_FAIL( aError.getStr() );
|
2000-09-18 16:07:07 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//! Datum/Autor/Kommentar der Source-Aktion uebernehmen!
|
|
|
|
|
|
|
|
pThisTrack->SetUser( pSourceAction->GetUser() );
|
|
|
|
pThisTrack->SetFixDateTimeUTC( pSourceAction->GetDateTimeUTC() );
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_uLong nOldActionMax = pThisTrack->GetActionMax();
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2008-03-07 11:19:32 +00:00
|
|
|
bool bExecute = true;
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_uLong nReject = pSourceAction->GetRejectAction();
|
2008-03-07 11:19:32 +00:00
|
|
|
if ( nReject )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2008-03-07 11:19:32 +00:00
|
|
|
if ( bShared )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2008-03-07 11:19:32 +00:00
|
|
|
if ( nReject >= nFirstNewNumber )
|
|
|
|
{
|
|
|
|
nReject += nOffset;
|
|
|
|
}
|
|
|
|
ScChangeAction* pOldAction = pThisTrack->GetAction( nReject );
|
2008-04-15 13:12:39 +00:00
|
|
|
if ( pOldAction && pOldAction->IsVirgin() )
|
2008-03-07 11:19:32 +00:00
|
|
|
{
|
|
|
|
pThisTrack->Reject( pOldAction );
|
2011-01-17 13:20:22 +01:00
|
|
|
bHasRejected = sal_True;
|
2008-03-07 11:19:32 +00:00
|
|
|
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
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2008-03-07 11:19:32 +00:00
|
|
|
pThisTrack->Reject(pOldAction);
|
2011-01-17 13:20:22 +01:00
|
|
|
bHasRejected = sal_True; // fuer Paint
|
2008-03-07 11:19:32 +00:00
|
|
|
}
|
|
|
|
bExecute = false;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
}
|
2008-03-07 11:19:32 +00:00
|
|
|
|
|
|
|
if ( bExecute )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
// 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 ???
|
|
|
|
|
2011-05-21 15:04:26 +02:00
|
|
|
OSL_ENSURE( aSourceRange.aStart == aSourceRange.aEnd, "huch?" );
|
2000-09-18 16:07:07 +00:00
|
|
|
ScAddress aPos = aSourceRange.aStart;
|
2012-02-02 21:03:58 -05:00
|
|
|
rtl::OUString aValue;
|
2000-09-18 16:07:07 +00:00
|
|
|
((const ScChangeActionContent*)pSourceAction)->GetNewString( aValue );
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_uInt8 eMatrix = MM_NONE;
|
2000-09-18 16:07:07 +00:00
|
|
|
const ScBaseCell* pCell = ((const ScChangeActionContent*)pSourceAction)->GetNewCell();
|
2002-01-21 15:27:48 +00:00
|
|
|
if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA )
|
2000-09-18 16:07:07 +00:00
|
|
|
eMatrix = ((const ScFormulaCell*)pCell)->GetMatrixFlag();
|
|
|
|
switch ( eMatrix )
|
|
|
|
{
|
|
|
|
case MM_NONE :
|
|
|
|
pViewSh->EnterData( aPos.Col(), aPos.Row(), aPos.Tab(), aValue );
|
|
|
|
break;
|
|
|
|
case MM_FORMULA :
|
|
|
|
{
|
INTEGRATION: CWS rowlimit (1.16.202); FILE MERGED
2004/03/25 21:36:02 er 1.16.202.4: #i1967# use ValidCol,ValidRow,ValidTab
2004/02/13 11:33:22 er 1.16.202.3: #i1967# SCCOL,SCROW,SCTAB replace USHORT; SCsCOL,SCsROW,SCsTAB replace short
2004/02/11 13:58:37 er 1.16.202.2: RESYNC: (1.16-1.18); FILE MERGED
2004/01/14 15:50:09 er 1.16.202.1: #i1967# SCCOL,SCROW,SCTAB replace USHORT; SCsCOL,SCsROW,SCsTAB replace short
2004-06-04 10:23:53 +00:00
|
|
|
SCCOL nCols;
|
|
|
|
SCROW nRows;
|
2000-09-18 16:07:07 +00:00
|
|
|
((const ScFormulaCell*)pCell)->GetMatColsRows( nCols, nRows );
|
|
|
|
aSourceRange.aEnd.SetCol( aPos.Col() + nCols - 1 );
|
|
|
|
aSourceRange.aEnd.SetRow( aPos.Row() + nRows - 1 );
|
2012-02-02 21:03:58 -05:00
|
|
|
aValue = aValue.copy(1, aValue.getLength()-2); // remove the 1st and last characters.
|
2008-03-06 15:12:05 +00:00
|
|
|
GetDocFunc().EnterMatrix( aSourceRange,
|
2011-03-10 16:55:21 -05:00
|
|
|
NULL, NULL, aValue, false, false,
|
2009-07-29 14:46:52 +00:00
|
|
|
EMPTY_STRING, formula::FormulaGrammar::GRAM_DEFAULT );
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MM_REFERENCE : // do nothing
|
|
|
|
break;
|
|
|
|
case MM_FAKE :
|
2011-05-21 15:04:26 +02:00
|
|
|
OSL_FAIL( "MergeDocument: MatrixFlag MM_FAKE" );
|
2000-09-18 16:07:07 +00:00
|
|
|
pViewSh->EnterData( aPos.Col(), aPos.Row(), aPos.Tab(), aValue );
|
|
|
|
break;
|
|
|
|
default:
|
2011-03-01 19:05:02 +01:00
|
|
|
OSL_FAIL( "MergeDocument: unknown MatrixFlag" );
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SC_CAT_INSERT_TABS :
|
|
|
|
{
|
2011-11-06 18:11:43 +01:00
|
|
|
rtl::OUString aName;
|
2000-09-18 16:07:07 +00:00
|
|
|
aDocument.CreateValidTabName( aName );
|
2011-03-10 16:55:21 -05:00
|
|
|
GetDocFunc().InsertTable( aSourceRange.aStart.Tab(), aName, sal_True, false );
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SC_CAT_INSERT_ROWS:
|
2011-03-10 16:55:21 -05:00
|
|
|
GetDocFunc().InsertCells( aSourceRange, NULL, INS_INSROWS, sal_True, false );
|
2000-09-18 16:07:07 +00:00
|
|
|
break;
|
|
|
|
case SC_CAT_INSERT_COLS:
|
2011-03-10 16:55:21 -05:00
|
|
|
GetDocFunc().InsertCells( aSourceRange, NULL, INS_INSCOLS, sal_True, false );
|
2000-09-18 16:07:07 +00:00
|
|
|
break;
|
|
|
|
case SC_CAT_DELETE_TABS :
|
2011-03-10 16:55:21 -05:00
|
|
|
GetDocFunc().DeleteTable( aSourceRange.aStart.Tab(), sal_True, false );
|
2000-09-18 16:07:07 +00:00
|
|
|
break;
|
|
|
|
case SC_CAT_DELETE_ROWS:
|
|
|
|
{
|
|
|
|
const ScChangeActionDel* pDel = (const ScChangeActionDel*) pSourceAction;
|
|
|
|
if ( pDel->IsTopDelete() )
|
|
|
|
{
|
|
|
|
aSourceRange = pDel->GetOverAllRange().MakeRange();
|
2011-03-10 16:55:21 -05:00
|
|
|
GetDocFunc().DeleteCells( aSourceRange, NULL, DEL_DELROWS, sal_True, false );
|
2010-01-15 15:21:56 +01:00
|
|
|
|
|
|
|
// #i101099# [Collaboration] Changes are not correctly shown
|
|
|
|
if ( bShared )
|
|
|
|
{
|
|
|
|
ScChangeAction* pAct = pThisTrack->GetLast();
|
|
|
|
if ( pAct && pAct->GetType() == eSourceType && pAct->IsDeletedIn() && !pSourceAction->IsDeletedIn() )
|
|
|
|
{
|
|
|
|
pAct->RemoveAllDeletedIn();
|
|
|
|
}
|
|
|
|
}
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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();
|
2011-03-10 16:55:21 -05:00
|
|
|
GetDocFunc().DeleteCells( aSourceRange, NULL, DEL_DELCOLS, sal_True, false );
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SC_CAT_MOVE :
|
|
|
|
{
|
|
|
|
const ScChangeActionMove* pMove = (const ScChangeActionMove*) pSourceAction;
|
|
|
|
ScRange aFromRange( pMove->GetFromRange().MakeRange() );
|
|
|
|
GetDocFunc().MoveBlock( aFromRange,
|
2011-03-10 16:55:21 -05:00
|
|
|
aSourceRange.aStart, sal_True, sal_True, false, false );
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
break;
|
2007-02-27 12:07:24 +00:00
|
|
|
default:
|
|
|
|
{
|
|
|
|
// added to avoid warnings
|
|
|
|
}
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
const String& rComment = pSourceAction->GetComment();
|
|
|
|
if ( rComment.Len() )
|
|
|
|
{
|
|
|
|
ScChangeAction* pAct = pThisTrack->GetLast();
|
2008-07-02 09:04:16 +00:00
|
|
|
if ( pAct && pAct->GetActionNumber() > nOldActionMax )
|
2000-09-18 16:07:07 +00:00
|
|
|
pAct->SetComment( rComment );
|
|
|
|
else
|
2011-03-01 19:05:02 +01:00
|
|
|
OSL_FAIL( "MergeDocument: wohin mit dem Kommentar?!?" );
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Referenzen anpassen
|
2009-02-11 15:19:01 +00:00
|
|
|
pSourceTrack->MergeOwn( (ScChangeAction*) pSourceAction, nFirstNewNumber, bShared );
|
2008-04-15 13:12:39 +00:00
|
|
|
|
|
|
|
// merge action state
|
|
|
|
if ( bShared && !pSourceAction->IsRejected() )
|
|
|
|
{
|
|
|
|
ScChangeAction* pAct = pThisTrack->GetLast();
|
2008-07-02 09:04:16 +00:00
|
|
|
if ( pAct && pAct->GetActionNumber() > nOldActionMax )
|
2008-04-15 13:12:39 +00:00
|
|
|
{
|
|
|
|
pThisTrack->MergeActionState( pAct, pSourceAction );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// fill merge map
|
|
|
|
if ( bShared && pMergeMap )
|
|
|
|
{
|
|
|
|
ScChangeAction* pAct = pThisTrack->GetLast();
|
2008-07-02 09:04:16 +00:00
|
|
|
if ( pAct && pAct->GetActionNumber() > nOldActionMax )
|
2008-04-15 13:12:39 +00:00
|
|
|
{
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_uLong nActionMax = pAct->GetActionNumber();
|
|
|
|
sal_uLong nActionCount = nActionMax - nOldActionMax;
|
|
|
|
sal_uLong nAction = nActionMax - nActionCount + 1;
|
|
|
|
sal_uLong nSourceAction = pSourceAction->GetActionNumber() - nActionCount + 1;
|
2008-07-02 09:04:16 +00:00
|
|
|
while ( nAction <= nActionMax )
|
2008-04-15 13:12:39 +00:00
|
|
|
{
|
2008-07-02 09:04:16 +00:00
|
|
|
if ( bInverseMap )
|
|
|
|
{
|
|
|
|
(*pMergeMap)[ nAction++ ] = nSourceAction++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
(*pMergeMap)[ nSourceAction++ ] = nAction++;
|
|
|
|
}
|
2008-04-15 13:12:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
aProgress.SetStateCountDown( --nNewActionCount );
|
|
|
|
}
|
|
|
|
pSourceAction = pSourceAction->GetNext();
|
|
|
|
}
|
2009-02-11 15:19:01 +00:00
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
rMarkData = aOldMarkData;
|
|
|
|
pThisTrack->SetUser(aOldUser);
|
2011-03-10 16:55:21 -05:00
|
|
|
pThisTrack->SetUseFixDateTime( false );
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
pSourceTrack->Clear(); //! der ist jetzt verhunzt
|
|
|
|
|
|
|
|
if (bHasRejected)
|
|
|
|
PostPaintGridAll(); // Reject() paintet nicht selber
|
2007-02-05 10:43:39 +00:00
|
|
|
|
|
|
|
UnlockPaint();
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
2008-04-15 13:12:39 +00:00
|
|
|
bool ScDocShell::MergeSharedDocument( ScDocShell* pSharedDocShell )
|
2008-03-07 11:19:32 +00:00
|
|
|
{
|
2008-04-15 13:12:39 +00:00
|
|
|
if ( !pSharedDocShell )
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-03-07 11:19:32 +00:00
|
|
|
ScChangeTrack* pThisTrack = aDocument.GetChangeTrack();
|
|
|
|
if ( !pThisTrack )
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2008-04-15 13:12:39 +00:00
|
|
|
ScDocument& rSharedDoc = *( pSharedDocShell->GetDocument() );
|
2008-03-07 11:19:32 +00:00
|
|
|
ScChangeTrack* pSharedTrack = rSharedDoc.GetChangeTrack();
|
|
|
|
if ( !pSharedTrack )
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2008-03-07 11:19:32 +00:00
|
|
|
// reset show changes
|
|
|
|
ScChangeViewSettings aChangeViewSet;
|
2011-03-10 16:55:21 -05:00
|
|
|
aChangeViewSet.SetShowChanges( false );
|
2008-03-07 11:19:32 +00:00
|
|
|
aDocument.SetChangeViewSettings( aChangeViewSet );
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2008-03-07 11:19:32 +00:00
|
|
|
// find first merge action in this document
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_Bool bIgnore100Sec = !pThisTrack->IsTime100thSeconds() || !pSharedTrack->IsTime100thSeconds();
|
2008-03-07 11:19:32 +00:00
|
|
|
ScChangeAction* pThisAction = pThisTrack->GetFirst();
|
|
|
|
ScChangeAction* pSharedAction = pSharedTrack->GetFirst();
|
|
|
|
while ( lcl_Equal( pThisAction, pSharedAction, bIgnore100Sec ) )
|
|
|
|
{
|
|
|
|
pThisAction = pThisAction->GetNext();
|
|
|
|
pSharedAction = pSharedAction->GetNext();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( pSharedAction )
|
|
|
|
{
|
|
|
|
if ( pThisAction )
|
|
|
|
{
|
2008-04-15 13:12:39 +00:00
|
|
|
// merge own changes into shared document
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_uLong nActStartShared = pSharedAction->GetActionNumber();
|
|
|
|
sal_uLong nActEndShared = pSharedTrack->GetActionMax();
|
2008-04-15 13:12:39 +00:00
|
|
|
ScDocument* pTmpDoc = new ScDocument;
|
|
|
|
for ( sal_Int32 nIndex = 0; nIndex < aDocument.GetTableCount(); ++nIndex )
|
|
|
|
{
|
2011-11-06 18:11:43 +01:00
|
|
|
rtl::OUString sTabName;
|
2008-04-15 13:12:39 +00:00
|
|
|
pTmpDoc->CreateValidTabName( sTabName );
|
|
|
|
pTmpDoc->InsertTab( SC_TAB_APPEND, sTabName );
|
|
|
|
}
|
|
|
|
aDocument.GetChangeTrack()->Clone( pTmpDoc );
|
|
|
|
ScChangeActionMergeMap aOwnInverseMergeMap;
|
2008-07-02 09:04:16 +00:00
|
|
|
pSharedDocShell->MergeDocument( *pTmpDoc, true, true, 0, &aOwnInverseMergeMap, true );
|
2008-04-15 13:12:39 +00:00
|
|
|
delete pTmpDoc;
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_uLong nActStartOwn = nActEndShared + 1;
|
|
|
|
sal_uLong nActEndOwn = pSharedTrack->GetActionMax();
|
2008-04-15 13:12:39 +00:00
|
|
|
|
|
|
|
// find conflicts
|
2008-03-07 11:19:32 +00:00
|
|
|
ScConflictsList aConflictsList;
|
2008-04-15 13:12:39 +00:00
|
|
|
ScConflictsFinder aFinder( pSharedTrack, nActStartShared, nActEndShared, nActStartOwn, nActEndOwn, aConflictsList );
|
2008-03-07 11:19:32 +00:00
|
|
|
if ( aFinder.Find() )
|
|
|
|
{
|
2008-04-15 13:12:39 +00:00
|
|
|
ScConflictsListHelper::TransformConflictsList( aConflictsList, NULL, &aOwnInverseMergeMap );
|
2008-03-07 11:19:32 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-15 13:12:39 +00:00
|
|
|
// 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 )
|
2008-03-07 11:19:32 +00:00
|
|
|
{
|
2011-11-06 18:11:43 +01:00
|
|
|
rtl::OUString sTabName;
|
2008-03-07 11:19:32 +00:00
|
|
|
pTmpDoc->CreateValidTabName( sTabName );
|
|
|
|
pTmpDoc->InsertTab( SC_TAB_APPEND, sTabName );
|
|
|
|
}
|
|
|
|
pThisTrack->Clone( pTmpDoc );
|
|
|
|
|
2008-04-15 13:12:39 +00:00
|
|
|
// undo own changes since last save in own document
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_uLong nStartShared = pThisAction->GetActionNumber();
|
2008-03-07 11:19:32 +00:00
|
|
|
ScChangeAction* pAction = pThisTrack->GetLast();
|
|
|
|
while ( pAction && pAction->GetActionNumber() >= nStartShared )
|
|
|
|
{
|
2009-04-24 14:37:15 +00:00
|
|
|
pThisTrack->Reject( pAction, true );
|
2008-03-07 11:19:32 +00:00
|
|
|
pAction = pAction->GetPrev();
|
|
|
|
}
|
2009-02-11 15:19:01 +00:00
|
|
|
|
|
|
|
// #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
|
|
|
|
pThisTrack->Undo( nStartShared, pThisTrack->GetActionMax(), true );
|
2008-03-07 11:19:32 +00:00
|
|
|
|
2008-04-15 13:12:39 +00:00
|
|
|
// merge shared changes into own document
|
|
|
|
ScChangeActionMergeMap aSharedMergeMap;
|
2008-07-02 09:04:16 +00:00
|
|
|
MergeDocument( rSharedDoc, true, true, 0, &aSharedMergeMap );
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_uLong nEndShared = pThisTrack->GetActionMax();
|
2008-03-07 11:19:32 +00:00
|
|
|
|
|
|
|
// resolve conflicts for shared non-content actions
|
|
|
|
if ( !aConflictsList.empty() )
|
|
|
|
{
|
2008-04-15 13:12:39 +00:00
|
|
|
ScConflictsListHelper::TransformConflictsList( aConflictsList, &aSharedMergeMap, NULL );
|
2008-03-07 11:19:32 +00:00
|
|
|
ScConflictsResolver aResolver( pThisTrack, aConflictsList );
|
2008-04-15 13:12:39 +00:00
|
|
|
pAction = pThisTrack->GetAction( nEndShared );
|
|
|
|
while ( pAction && pAction->GetActionNumber() >= nStartShared )
|
2008-03-07 11:19:32 +00:00
|
|
|
{
|
2008-04-15 13:12:39 +00:00
|
|
|
aResolver.HandleAction( pAction, true /*bIsSharedAction*/,
|
2008-03-07 11:19:32 +00:00
|
|
|
false /*bHandleContentAction*/, true /*bHandleNonContentAction*/ );
|
2008-04-15 13:12:39 +00:00
|
|
|
pAction = pAction->GetPrev();
|
2008-03-07 11:19:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
nEndShared = pThisTrack->GetActionMax();
|
|
|
|
|
|
|
|
// only show changes from shared document
|
2011-01-17 13:20:22 +01:00
|
|
|
aChangeViewSet.SetShowChanges( sal_True );
|
|
|
|
aChangeViewSet.SetShowAccepted( sal_True );
|
2008-03-07 11:19:32 +00:00
|
|
|
aChangeViewSet.SetHasActionRange( true );
|
|
|
|
aChangeViewSet.SetTheActionRange( nStartShared, nEndShared );
|
|
|
|
aDocument.SetChangeViewSettings( aChangeViewSet );
|
|
|
|
|
2008-04-15 13:12:39 +00:00
|
|
|
// merge own changes back into own document
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_uLong nStartOwn = nEndShared + 1;
|
2008-04-15 13:12:39 +00:00
|
|
|
ScChangeActionMergeMap aOwnMergeMap;
|
|
|
|
MergeDocument( *pTmpDoc, true, true, nEndShared - nStartShared + 1, &aOwnMergeMap );
|
2008-03-07 11:19:32 +00:00
|
|
|
delete pTmpDoc;
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_uLong nEndOwn = pThisTrack->GetActionMax();
|
2008-03-07 11:19:32 +00:00
|
|
|
|
|
|
|
// resolve conflicts for shared content actions and own actions
|
|
|
|
if ( !aConflictsList.empty() )
|
|
|
|
{
|
2008-04-15 13:12:39 +00:00
|
|
|
ScConflictsListHelper::TransformConflictsList( aConflictsList, NULL, &aOwnMergeMap );
|
2008-03-07 11:19:32 +00:00
|
|
|
ScConflictsResolver aResolver( pThisTrack, aConflictsList );
|
2008-04-15 13:12:39 +00:00
|
|
|
pAction = pThisTrack->GetAction( nEndShared );
|
|
|
|
while ( pAction && pAction->GetActionNumber() >= nStartShared )
|
2008-03-07 11:19:32 +00:00
|
|
|
{
|
2008-04-15 13:12:39 +00:00
|
|
|
aResolver.HandleAction( pAction, true /*bIsSharedAction*/,
|
2008-03-07 11:19:32 +00:00
|
|
|
true /*bHandleContentAction*/, false /*bHandleNonContentAction*/ );
|
2008-04-15 13:12:39 +00:00
|
|
|
pAction = pAction->GetPrev();
|
2008-03-07 11:19:32 +00:00
|
|
|
}
|
|
|
|
|
2008-04-15 13:12:39 +00:00
|
|
|
pAction = pThisTrack->GetAction( nEndOwn );
|
|
|
|
while ( pAction && pAction->GetActionNumber() >= nStartOwn )
|
2008-03-07 11:19:32 +00:00
|
|
|
{
|
2008-04-15 13:12:39 +00:00
|
|
|
aResolver.HandleAction( pAction, false /*bIsSharedAction*/,
|
2008-03-07 11:19:32 +00:00
|
|
|
true /*bHandleContentAction*/, true /*bHandleNonContentAction*/ );
|
2008-04-15 13:12:39 +00:00
|
|
|
pAction = pAction->GetPrev();
|
2008-03-07 11:19:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
nEndOwn = pThisTrack->GetActionMax();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-04-15 13:12:39 +00:00
|
|
|
// merge shared changes into own document
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_uLong nStartShared = pThisTrack->GetActionMax() + 1;
|
2008-07-02 09:04:16 +00:00
|
|
|
MergeDocument( rSharedDoc, true, true );
|
2011-01-17 13:20:22 +01:00
|
|
|
sal_uLong nEndShared = pThisTrack->GetActionMax();
|
2008-03-07 11:19:32 +00:00
|
|
|
|
|
|
|
// only show changes from shared document
|
2011-01-17 13:20:22 +01:00
|
|
|
aChangeViewSet.SetShowChanges( sal_True );
|
|
|
|
aChangeViewSet.SetShowAccepted( sal_True );
|
2008-03-07 11:19:32 +00:00
|
|
|
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 );
|
|
|
|
}
|
2010-10-12 15:59:00 +02:00
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|