summaryrefslogtreecommitdiff
path: root/sc/source/ui/docshell
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/ui/docshell')
-rw-r--r--sc/source/ui/docshell/arealink.cxx530
-rw-r--r--sc/source/ui/docshell/autostyl.cxx244
-rw-r--r--sc/source/ui/docshell/dbdocfun.cxx1487
-rw-r--r--sc/source/ui/docshell/dbdocimp.cxx720
-rw-r--r--sc/source/ui/docshell/docfunc.cxx4630
-rw-r--r--sc/source/ui/docshell/docsh.cxx2591
-rw-r--r--sc/source/ui/docshell/docsh2.cxx261
-rw-r--r--sc/source/ui/docshell/docsh3.cxx1391
-rw-r--r--sc/source/ui/docshell/docsh4.cxx2730
-rw-r--r--sc/source/ui/docshell/docsh5.cxx938
-rw-r--r--sc/source/ui/docshell/docsh6.cxx469
-rw-r--r--sc/source/ui/docshell/docsh7.cxx45
-rw-r--r--sc/source/ui/docshell/docsh8.cxx1098
-rw-r--r--sc/source/ui/docshell/docshimp.hxx57
-rw-r--r--sc/source/ui/docshell/editable.cxx162
-rw-r--r--sc/source/ui/docshell/externalrefmgr.cxx2378
-rw-r--r--sc/source/ui/docshell/hiranges.cxx53
-rw-r--r--sc/source/ui/docshell/impex.cxx2076
-rw-r--r--sc/source/ui/docshell/makefile.mk139
-rw-r--r--sc/source/ui/docshell/olinefun.cxx788
-rw-r--r--sc/source/ui/docshell/pagedata.cxx139
-rw-r--r--sc/source/ui/docshell/pntlock.cxx61
-rw-r--r--sc/source/ui/docshell/servobj.cxx273
-rw-r--r--sc/source/ui/docshell/sizedev.cxx77
-rw-r--r--sc/source/ui/docshell/tablink.cxx616
-rw-r--r--sc/source/ui/docshell/tpstat.cxx101
-rw-r--r--sc/source/ui/docshell/tpstat.hrc36
-rw-r--r--sc/source/ui/docshell/tpstat.src112
28 files changed, 24202 insertions, 0 deletions
diff --git a/sc/source/ui/docshell/arealink.cxx b/sc/source/ui/docshell/arealink.cxx
new file mode 100644
index 000000000000..d819785c843b
--- /dev/null
+++ b/sc/source/ui/docshell/arealink.cxx
@@ -0,0 +1,530 @@
+/*************************************************************************
+ *
+ * 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 <sfx2/app.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/fcontnr.hxx>
+#include <sfx2/sfxsids.hrc>
+#include <sfx2/linkmgr.hxx>
+#include <svl/stritem.hxx>
+#include <vcl/msgbox.hxx>
+
+#include "arealink.hxx"
+
+#include "tablink.hxx"
+#include "document.hxx"
+#include "docsh.hxx"
+#include "rangenam.hxx"
+#include "dbcolect.hxx"
+#include "undoblk.hxx"
+#include "globstr.hrc"
+#include "markdata.hxx"
+#include "hints.hxx"
+#include "filter.hxx"
+//CHINA001 #include "linkarea.hxx" // dialog
+
+#include "attrib.hxx" // raus, wenn ResetAttrib am Dokument
+#include "patattr.hxx" // raus, wenn ResetAttrib am Dokument
+#include "docpool.hxx" // raus, wenn ResetAttrib am Dokument
+
+#include "sc.hrc" //CHINA001
+#include "scabstdlg.hxx" //CHINA001
+#include "clipparam.hxx"
+
+struct AreaLink_Impl
+{
+ ScDocShell* m_pDocSh;
+ AbstractScLinkedAreaDlg* m_pDialog;
+
+ AreaLink_Impl() : m_pDocSh( NULL ), m_pDialog( NULL ) {}
+};
+
+TYPEINIT1(ScAreaLink,::sfx2::SvBaseLink);
+
+//------------------------------------------------------------------------
+
+ScAreaLink::ScAreaLink( SfxObjectShell* pShell, const String& rFile,
+ const String& rFilter, const String& rOpt,
+ const String& rArea, const ScRange& rDest,
+ ULONG nRefresh ) :
+ ::sfx2::SvBaseLink(sfx2::LINKUPDATE_ONCALL,FORMAT_FILE),
+ ScRefreshTimer ( nRefresh ),
+ pImpl ( new AreaLink_Impl() ),
+ aFileName (rFile),
+ aFilterName (rFilter),
+ aOptions (rOpt),
+ aSourceArea (rArea),
+ aDestArea (rDest),
+ bAddUndo (TRUE),
+ bInCreate (FALSE),
+ bDoInsert (TRUE)
+{
+ DBG_ASSERT(pShell->ISA(ScDocShell), "ScAreaLink mit falscher ObjectShell");
+ pImpl->m_pDocSh = static_cast< ScDocShell* >( pShell );
+ SetRefreshHandler( LINK( this, ScAreaLink, RefreshHdl ) );
+ SetRefreshControl( pImpl->m_pDocSh->GetDocument()->GetRefreshTimerControlAddress() );
+}
+
+__EXPORT ScAreaLink::~ScAreaLink()
+{
+ StopRefreshTimer();
+ delete pImpl;
+}
+
+void __EXPORT ScAreaLink::Edit(Window* pParent, const Link& /* rEndEditHdl */ )
+{
+ // use own dialog instead of SvBaseLink::Edit...
+ // DefModalDialogParent setzen, weil evtl. aus der DocShell beim ConvertFrom
+ // ein Optionen-Dialog kommt...
+
+ ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
+ DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001
+
+ AbstractScLinkedAreaDlg* pDlg = pFact->CreateScLinkedAreaDlg( pParent, RID_SCDLG_LINKAREA);
+ DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001
+ pDlg->InitFromOldLink( aFileName, aFilterName, aOptions, aSourceArea, GetRefreshDelay() );
+ pImpl->m_pDialog = pDlg;
+ pDlg->StartExecuteModal( LINK( this, ScAreaLink, AreaEndEditHdl ) );
+}
+
+void __EXPORT ScAreaLink::DataChanged( const String&,
+ const ::com::sun::star::uno::Any& )
+{
+ // bei bInCreate nichts tun, damit Update gerufen werden kann, um den Status im
+ // LinkManager zu setzen, ohne die Daten im Dokument zu aendern
+
+ if (bInCreate)
+ return;
+
+ sfx2::LinkManager* pLinkManager=pImpl->m_pDocSh->GetDocument()->GetLinkManager();
+ if (pLinkManager!=NULL)
+ {
+ String aFile;
+ String aFilter;
+ String aArea;
+ pLinkManager->GetDisplayNames( this,0,&aFile,&aArea,&aFilter);
+
+ // the file dialog returns the filter name with the application prefix
+ // -> remove prefix
+ ScDocumentLoader::RemoveAppPrefix( aFilter );
+
+ // #81155# dialog doesn't set area, so keep old one
+ if ( !aArea.Len() )
+ {
+ aArea = aSourceArea;
+
+ // adjust in dialog:
+ String aNewLinkName;
+ sfx2::MakeLnkName( aNewLinkName, NULL, aFile, aArea, &aFilter );
+ SetName( aNewLinkName );
+ }
+
+ Refresh( aFile, aFilter, aArea, GetRefreshDelay() );
+ }
+}
+
+void __EXPORT ScAreaLink::Closed()
+{
+ // Verknuepfung loeschen: Undo
+
+ ScDocument* pDoc = pImpl->m_pDocSh->GetDocument();
+ BOOL bUndo (pDoc->IsUndoEnabled());
+ if (bAddUndo && bUndo)
+ {
+ pImpl->m_pDocSh->GetUndoManager()->AddUndoAction( new ScUndoRemoveAreaLink( pImpl->m_pDocSh,
+ aFileName, aFilterName, aOptions,
+ aSourceArea, aDestArea, GetRefreshDelay() ) );
+
+ bAddUndo = FALSE; // nur einmal
+ }
+
+ SCTAB nDestTab = aDestArea.aStart.Tab();
+ if (pDoc->IsStreamValid(nDestTab))
+ pDoc->SetStreamValid(nDestTab, FALSE);
+
+ SvBaseLink::Closed();
+}
+
+void ScAreaLink::SetDestArea(const ScRange& rNew)
+{
+ aDestArea = rNew; // fuer Undo
+}
+
+void ScAreaLink::SetSource(const String& rDoc, const String& rFlt, const String& rOpt,
+ const String& rArea)
+{
+ aFileName = rDoc;
+ aFilterName = rFlt;
+ aOptions = rOpt;
+ aSourceArea = rArea;
+
+ // also update link name for dialog
+ String aNewLinkName;
+ sfx2::MakeLnkName( aNewLinkName, NULL, aFileName, aSourceArea, &aFilterName );
+ SetName( aNewLinkName );
+}
+
+BOOL ScAreaLink::IsEqual( const String& rFile, const String& rFilter, const String& rOpt,
+ const String& rSource, const ScRange& rDest ) const
+{
+ return aFileName == rFile && aFilterName == rFilter && aOptions == rOpt &&
+ aSourceArea == rSource && aDestArea.aStart == rDest.aStart;
+}
+
+// find a range with name >rAreaName< in >pSrcDoc<, return it in >rRange<
+BOOL ScAreaLink::FindExtRange( ScRange& rRange, ScDocument* pSrcDoc, const String& rAreaName )
+{
+ BOOL bFound = FALSE;
+ ScRangeName* pNames = pSrcDoc->GetRangeName();
+ USHORT nPos;
+ if (pNames) // benannte Bereiche
+ {
+ if (pNames->SearchName( rAreaName, nPos ))
+ if ( (*pNames)[nPos]->IsValidReference( rRange ) )
+ bFound = TRUE;
+ }
+ if (!bFound) // Datenbankbereiche
+ {
+ ScDBCollection* pDBColl = pSrcDoc->GetDBCollection();
+ if (pDBColl)
+ if (pDBColl->SearchName( rAreaName, nPos ))
+ {
+ SCTAB nTab;
+ SCCOL nCol1, nCol2;
+ SCROW nRow1, nRow2;
+ (*pDBColl)[nPos]->GetArea(nTab,nCol1,nRow1,nCol2,nRow2);
+ rRange = ScRange( nCol1,nRow1,nTab, nCol2,nRow2,nTab );
+ bFound = TRUE;
+ }
+ }
+ if (!bFound) // direct reference (range or cell)
+ {
+ ScAddress::Details aDetails(pSrcDoc->GetAddressConvention(), 0, 0);
+ if ( rRange.ParseAny( rAreaName, pSrcDoc, aDetails ) & SCA_VALID )
+ bFound = TRUE;
+ }
+ return bFound;
+}
+
+// ausfuehren:
+
+BOOL ScAreaLink::Refresh( const String& rNewFile, const String& rNewFilter,
+ const String& rNewArea, ULONG nNewRefresh )
+{
+ // Dokument laden - wie TabLink
+
+ if (!rNewFile.Len() || !rNewFilter.Len())
+ return FALSE;
+
+ String aNewUrl( ScGlobal::GetAbsDocName( rNewFile, pImpl->m_pDocSh ) );
+ BOOL bNewUrlName = (aNewUrl != aFileName);
+
+ const SfxFilter* pFilter = pImpl->m_pDocSh->GetFactory().GetFilterContainer()->GetFilter4FilterName(rNewFilter);
+ if (!pFilter)
+ return FALSE;
+
+ ScDocument* pDoc = pImpl->m_pDocSh->GetDocument();
+
+ BOOL bUndo (pDoc->IsUndoEnabled());
+ pDoc->SetInLinkUpdate( TRUE );
+
+ // wenn neuer Filter ausgewaehlt wurde, Optionen vergessen
+ if ( rNewFilter != aFilterName )
+ aOptions.Erase();
+
+ // ItemSet immer anlegen, damit die DocShell die Optionen setzen kann
+ SfxItemSet* pSet = new SfxAllItemSet( SFX_APP()->GetPool() );
+ if ( aOptions.Len() )
+ pSet->Put( SfxStringItem( SID_FILE_FILTEROPTIONS, aOptions ) );
+
+ SfxMedium* pMed = new SfxMedium(aNewUrl, STREAM_STD_READ, FALSE, pFilter);
+
+ ScDocShell* pSrcShell = new ScDocShell(SFX_CREATE_MODE_INTERNAL);
+//REMOVE SvEmbeddedObjectRef aRef = pSrcShell;
+ SfxObjectShellRef aRef = pSrcShell;
+ pSrcShell->DoLoad(pMed);
+
+ ScDocument* pSrcDoc = pSrcShell->GetDocument();
+
+ // Optionen koennten gesetzt worden sein
+ String aNewOpt = ScDocumentLoader::GetOptions(*pMed);
+ if (!aNewOpt.Len())
+ aNewOpt = aOptions;
+
+ // correct source range name list for web query import
+ String aTempArea;
+
+ if( rNewFilter == ScDocShell::GetWebQueryFilterName() )
+ aTempArea = ScFormatFilter::Get().GetHTMLRangeNameList( pSrcDoc, rNewArea );
+ else
+ aTempArea = rNewArea;
+
+ // find total size of source area
+ SCCOL nWidth = 0;
+ SCROW nHeight = 0;
+ xub_StrLen nTokenCnt = aTempArea.GetTokenCount( ';' );
+ xub_StrLen nStringIx = 0;
+ xub_StrLen nToken;
+
+ for( nToken = 0; nToken < nTokenCnt; nToken++ )
+ {
+ String aToken( aTempArea.GetToken( 0, ';', nStringIx ) );
+ ScRange aTokenRange;
+ if( FindExtRange( aTokenRange, pSrcDoc, aToken ) )
+ {
+ // columns: find maximum
+ nWidth = Max( nWidth, (SCCOL)(aTokenRange.aEnd.Col() - aTokenRange.aStart.Col() + 1) );
+ // rows: add row range + 1 empty row
+ nHeight += aTokenRange.aEnd.Row() - aTokenRange.aStart.Row() + 2;
+ }
+ }
+ // remove the last empty row
+ if( nHeight > 0 )
+ nHeight--;
+
+ // alte Daten loeschen / neue kopieren
+
+ ScAddress aDestPos = aDestArea.aStart;
+ SCTAB nDestTab = aDestPos.Tab();
+ ScRange aOldRange = aDestArea;
+ ScRange aNewRange = aDestArea; // alter Bereich, wenn Datei nicht gefunden o.ae.
+ if (nWidth > 0 && nHeight > 0)
+ {
+ aNewRange.aEnd.SetCol( aNewRange.aStart.Col() + nWidth - 1 );
+ aNewRange.aEnd.SetRow( aNewRange.aStart.Row() + nHeight - 1 );
+ }
+
+ //! check CanFitBlock only if bDoInsert is set?
+ BOOL bCanDo = ValidColRow( aNewRange.aEnd.Col(), aNewRange.aEnd.Row() ) &&
+ pDoc->CanFitBlock( aOldRange, aNewRange );
+ if (bCanDo)
+ {
+ ScDocShellModificator aModificator( *pImpl->m_pDocSh );
+
+ SCCOL nOldEndX = aOldRange.aEnd.Col();
+ SCROW nOldEndY = aOldRange.aEnd.Row();
+ SCCOL nNewEndX = aNewRange.aEnd.Col();
+ SCROW nNewEndY = aNewRange.aEnd.Row();
+ ScRange aMaxRange( aDestPos,
+ ScAddress(Max(nOldEndX,nNewEndX), Max(nOldEndY,nNewEndY), nDestTab) );
+
+ // Undo initialisieren
+
+ ScDocument* pUndoDoc = NULL;
+ ScDocument* pRedoDoc = NULL;
+ if ( bAddUndo && bUndo )
+ {
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ if ( bDoInsert )
+ {
+ if ( nNewEndX != nOldEndX || nNewEndY != nOldEndY ) // Bereich veraendert?
+ {
+ pUndoDoc->InitUndo( pDoc, 0, pDoc->GetTableCount()-1 );
+ pDoc->CopyToDocument( 0,0,0,MAXCOL,MAXROW,MAXTAB,
+ IDF_FORMULA, FALSE, pUndoDoc ); // alle Formeln
+ }
+ else
+ pUndoDoc->InitUndo( pDoc, nDestTab, nDestTab ); // nur Zieltabelle
+ pDoc->CopyToDocument( aOldRange, IDF_ALL & ~IDF_NOTE, FALSE, pUndoDoc );
+ }
+ else // ohne Einfuegen
+ {
+ pUndoDoc->InitUndo( pDoc, nDestTab, nDestTab ); // nur Zieltabelle
+ pDoc->CopyToDocument( aMaxRange, IDF_ALL & ~IDF_NOTE, FALSE, pUndoDoc );
+ }
+ }
+
+ // Zellen einfuegen / loeschen
+ // DeleteAreaTab loescht auch MERGE_FLAG Attribute
+
+ if (bDoInsert)
+ pDoc->FitBlock( aOldRange, aNewRange ); // incl. loeschen
+ else
+ pDoc->DeleteAreaTab( aMaxRange, IDF_ALL & ~IDF_NOTE );
+
+ // Daten kopieren
+
+ if (nWidth > 0 && nHeight > 0)
+ {
+ ScDocument aClipDoc( SCDOCMODE_CLIP );
+ ScRange aNewTokenRange( aNewRange.aStart );
+ nStringIx = 0;
+ for( nToken = 0; nToken < nTokenCnt; nToken++ )
+ {
+ String aToken( aTempArea.GetToken( 0, ';', nStringIx ) );
+ ScRange aTokenRange;
+ if( FindExtRange( aTokenRange, pSrcDoc, aToken ) )
+ {
+ SCTAB nSrcTab = aTokenRange.aStart.Tab();
+ ScMarkData aSourceMark;
+ aSourceMark.SelectOneTable( nSrcTab ); // selektieren fuer CopyToClip
+ aSourceMark.SetMarkArea( aTokenRange );
+
+ ScClipParam aClipParam(aTokenRange, false);
+ pSrcDoc->CopyToClip(aClipParam, &aClipDoc, &aSourceMark);
+
+ if ( aClipDoc.HasAttrib( 0,0,nSrcTab, MAXCOL,MAXROW,nSrcTab,
+ HASATTR_MERGED | HASATTR_OVERLAPPED ) )
+ {
+ //! ResetAttrib am Dokument !!!
+
+ ScPatternAttr aPattern( pSrcDoc->GetPool() );
+ aPattern.GetItemSet().Put( ScMergeAttr() ); // Defaults
+ aPattern.GetItemSet().Put( ScMergeFlagAttr() );
+ aClipDoc.ApplyPatternAreaTab( 0,0, MAXCOL,MAXROW, nSrcTab, aPattern );
+ }
+
+ aNewTokenRange.aEnd.SetCol( aNewTokenRange.aStart.Col() + (aTokenRange.aEnd.Col() - aTokenRange.aStart.Col()) );
+ aNewTokenRange.aEnd.SetRow( aNewTokenRange.aStart.Row() + (aTokenRange.aEnd.Row() - aTokenRange.aStart.Row()) );
+ ScMarkData aDestMark;
+ aDestMark.SelectOneTable( nDestTab );
+ aDestMark.SetMarkArea( aNewTokenRange );
+ pDoc->CopyFromClip( aNewTokenRange, aDestMark, IDF_ALL, NULL, &aClipDoc, FALSE );
+ aNewTokenRange.aStart.SetRow( aNewTokenRange.aEnd.Row() + 2 );
+ }
+ }
+ }
+ else
+ {
+ String aErr = ScGlobal::GetRscString(STR_LINKERROR);
+ pDoc->SetString( aDestPos.Col(), aDestPos.Row(), aDestPos.Tab(), aErr );
+ }
+
+ // Undo eintragen
+
+ if ( bAddUndo && bUndo)
+ {
+ pRedoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pRedoDoc->InitUndo( pDoc, nDestTab, nDestTab );
+ pDoc->CopyToDocument( aNewRange, IDF_ALL & ~IDF_NOTE, FALSE, pRedoDoc );
+
+ pImpl->m_pDocSh->GetUndoManager()->AddUndoAction(
+ new ScUndoUpdateAreaLink( pImpl->m_pDocSh,
+ aFileName, aFilterName, aOptions,
+ aSourceArea, aOldRange, GetRefreshDelay(),
+ aNewUrl, rNewFilter, aNewOpt,
+ rNewArea, aNewRange, nNewRefresh,
+ pUndoDoc, pRedoDoc, bDoInsert ) );
+ }
+
+ // neue Einstellungen merken
+
+ if ( bNewUrlName )
+ aFileName = aNewUrl;
+ if ( rNewFilter != aFilterName )
+ aFilterName = rNewFilter;
+ if ( rNewArea != aSourceArea )
+ aSourceArea = rNewArea;
+ if ( aNewOpt != aOptions )
+ aOptions = aNewOpt;
+
+ if ( aNewRange != aDestArea )
+ aDestArea = aNewRange;
+
+ if ( nNewRefresh != GetRefreshDelay() )
+ SetRefreshDelay( nNewRefresh );
+
+ SCCOL nPaintEndX = Max( aOldRange.aEnd.Col(), aNewRange.aEnd.Col() );
+ SCROW nPaintEndY = Max( aOldRange.aEnd.Row(), aNewRange.aEnd.Row() );
+
+ if ( aOldRange.aEnd.Col() != aNewRange.aEnd.Col() )
+ nPaintEndX = MAXCOL;
+ if ( aOldRange.aEnd.Row() != aNewRange.aEnd.Row() )
+ nPaintEndY = MAXROW;
+
+ if ( !pImpl->m_pDocSh->AdjustRowHeight( aDestPos.Row(), nPaintEndY, nDestTab ) )
+ pImpl->m_pDocSh->PostPaint( aDestPos.Col(),aDestPos.Row(),nDestTab,
+ nPaintEndX,nPaintEndY,nDestTab, PAINT_GRID );
+ aModificator.SetDocumentModified();
+ }
+ else
+ {
+ // CanFitBlock FALSE -> Probleme mit zusammengefassten Zellen
+ // oder Tabellengrenze erreicht!
+ //! Zellschutz ???
+
+ //! Link-Dialog muss Default-Parent setzen
+ // "kann keine Zeilen einfuegen"
+ InfoBox aBox( Application::GetDefDialogParent(),
+ ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_2 ) );
+ aBox.Execute();
+ }
+
+ // aufraeumen
+
+ aRef->DoClose();
+
+ pDoc->SetInLinkUpdate( FALSE );
+
+ if (bCanDo)
+ {
+ // notify Uno objects (for XRefreshListener)
+ //! also notify Uno objects if file name was changed!
+ ScLinkRefreshedHint aHint;
+ aHint.SetAreaLink( aDestPos );
+ pDoc->BroadcastUno( aHint );
+ }
+
+ return bCanDo;
+}
+
+
+IMPL_LINK( ScAreaLink, RefreshHdl, ScAreaLink*, EMPTYARG )
+{
+ long nRes = Refresh( aFileName, aFilterName, aSourceArea,
+ GetRefreshDelay() ) != 0;
+ return nRes;
+}
+
+IMPL_LINK( ScAreaLink, AreaEndEditHdl, void*, EMPTYARG )
+{
+ // #i76514# can't use link argument to access the dialog,
+ // because it's the ScLinkedAreaDlg, not AbstractScLinkedAreaDlg
+
+ if ( pImpl->m_pDialog && pImpl->m_pDialog->GetResult() == RET_OK )
+ {
+ aOptions = pImpl->m_pDialog->GetOptions();
+ Refresh( pImpl->m_pDialog->GetURL(), pImpl->m_pDialog->GetFilter(),
+ pImpl->m_pDialog->GetSource(), pImpl->m_pDialog->GetRefresh() );
+
+ // copy source data from members (set in Refresh) into link name for dialog
+ String aNewLinkName;
+ sfx2::MakeLnkName( aNewLinkName, NULL, aFileName, aSourceArea, &aFilterName );
+ SetName( aNewLinkName );
+ }
+ pImpl->m_pDialog = NULL; // dialog is deleted with parent
+
+ return 0;
+}
+
diff --git a/sc/source/ui/docshell/autostyl.cxx b/sc/source/ui/docshell/autostyl.cxx
new file mode 100644
index 000000000000..61683e169f02
--- /dev/null
+++ b/sc/source/ui/docshell/autostyl.cxx
@@ -0,0 +1,244 @@
+/*************************************************************************
+ *
+ * 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 <time.h>
+#include "autostyl.hxx"
+
+#include "docsh.hxx"
+#include "attrib.hxx"
+#include "sc.hrc"
+
+//==================================================================
+
+struct ScAutoStyleInitData
+{
+ ScRange aRange;
+ String aStyle1;
+ ULONG nTimeout;
+ String aStyle2;
+
+ ScAutoStyleInitData( const ScRange& rR, const String& rSt1, ULONG nT, const String& rSt2 ) :
+ aRange(rR), aStyle1(rSt1), nTimeout(nT), aStyle2(rSt2) {}
+};
+
+struct ScAutoStyleData
+{
+ ULONG nTimeout;
+ ScRange aRange;
+ String aStyle;
+
+ ScAutoStyleData( ULONG nT, const ScRange& rR, const String& rT ) :
+ nTimeout(nT), aRange(rR), aStyle(rT) {}
+};
+
+//==================================================================
+
+inline ULONG TimeNow() // Sekunden
+{
+ return (ULONG) time(0);
+}
+
+//==================================================================
+
+ScAutoStyleList::ScAutoStyleList(ScDocShell* pShell) :
+ pDocSh( pShell )
+{
+ aTimer.SetTimeoutHdl( LINK( this, ScAutoStyleList, TimerHdl ) );
+ aInitTimer.SetTimeoutHdl( LINK( this, ScAutoStyleList, InitHdl ) );
+ aInitTimer.SetTimeout( 0 );
+}
+
+ScAutoStyleList::~ScAutoStyleList()
+{
+ ULONG i;
+ ULONG nCount = aEntries.Count();
+ for (i=0; i<nCount; i++)
+ delete (ScAutoStyleData*) aEntries.GetObject(i);
+ nCount = aInitials.Count();
+ for (i=0; i<nCount; i++)
+ delete (ScAutoStyleInitData*) aInitials.GetObject(i);
+}
+
+//==================================================================
+
+// initial short delay (asynchronous call)
+
+void ScAutoStyleList::AddInitial( const ScRange& rRange, const String& rStyle1,
+ ULONG nTimeout, const String& rStyle2 )
+{
+ ScAutoStyleInitData* pNew =
+ new ScAutoStyleInitData( rRange, rStyle1, nTimeout, rStyle2 );
+ aInitials.Insert( pNew, aInitials.Count() );
+ aInitTimer.Start();
+}
+
+IMPL_LINK( ScAutoStyleList, InitHdl, Timer*, EMPTYARG )
+{
+ ULONG nCount = aInitials.Count();
+ for (ULONG i=0; i<nCount; i++)
+ {
+ ScAutoStyleInitData* pData = (ScAutoStyleInitData*) aInitials.GetObject(i);
+
+ // apply first style immediately
+ pDocSh->DoAutoStyle( pData->aRange, pData->aStyle1 );
+
+ // add second style to list
+ if ( pData->nTimeout )
+ AddEntry( pData->nTimeout, pData->aRange, pData->aStyle2 );
+
+ delete pData;
+ }
+ aInitials.Clear();
+
+ return 0;
+}
+
+//==================================================================
+
+void ScAutoStyleList::AddEntry( ULONG nTimeout, const ScRange& rRange, const String& rStyle )
+{
+ aTimer.Stop();
+ ULONG nNow = TimeNow();
+
+ // alten Eintrag loeschen
+
+ ULONG nCount = aEntries.Count();
+ ULONG i;
+ for (i=0; i<nCount; i++)
+ {
+ ScAutoStyleData* pData = (ScAutoStyleData*) aEntries.GetObject(i);
+ if (pData->aRange == rRange)
+ {
+ delete pData;
+ aEntries.Remove(i);
+ --nCount;
+ break; // nicht weitersuchen - es kann nur einen geben
+ }
+ }
+
+ // Timeouts von allen Eintraegen anpassen
+
+ if (nCount && nNow != nTimerStart)
+ {
+ DBG_ASSERT(nNow>nTimerStart, "Zeit laeuft rueckwaerts?");
+ AdjustEntries((nNow-nTimerStart)*1000);
+ }
+
+ // Einfuege-Position suchen
+
+ ULONG nPos = LIST_APPEND;
+ for (i=0; i<nCount && nPos == LIST_APPEND; i++)
+ if (nTimeout <= ((ScAutoStyleData*) aEntries.GetObject(i))->nTimeout)
+ nPos = i;
+
+ ScAutoStyleData* pNew = new ScAutoStyleData( nTimeout, rRange, rStyle );
+ aEntries.Insert( pNew, nPos );
+
+ // abgelaufene ausfuehren, Timer neu starten
+
+ ExecuteEntries();
+ StartTimer(nNow);
+}
+
+void ScAutoStyleList::AdjustEntries( ULONG nDiff ) // Millisekunden
+{
+ ULONG nCount = aEntries.Count();
+ for (ULONG i=0; i<nCount; i++)
+ {
+ ScAutoStyleData* pData = (ScAutoStyleData*) aEntries.GetObject(i);
+ if ( pData->nTimeout <= nDiff )
+ pData->nTimeout = 0; // abgelaufen
+ else
+ pData->nTimeout -= nDiff; // weiterzaehlen
+ }
+}
+
+void ScAutoStyleList::ExecuteEntries()
+{
+ ScAutoStyleData* pData;
+ while ((pData = (ScAutoStyleData*) aEntries.GetObject(0)) != NULL && pData->nTimeout == 0)
+ {
+ pDocSh->DoAutoStyle( pData->aRange, pData->aStyle ); //! oder Request ???
+
+ delete pData;
+ aEntries.Remove((ULONG)0);
+ }
+}
+
+void ScAutoStyleList::ExecuteAllNow()
+{
+ aTimer.Stop();
+
+ ULONG nCount = aEntries.Count();
+ for (ULONG i=0; i<nCount; i++)
+ {
+ ScAutoStyleData* pData = (ScAutoStyleData*) aEntries.GetObject(i);
+
+ pDocSh->DoAutoStyle( pData->aRange, pData->aStyle ); //! oder Request ???
+
+ delete pData;
+ }
+ aEntries.Clear();
+}
+
+void ScAutoStyleList::StartTimer( ULONG nNow ) // Sekunden
+{
+ // ersten Eintrag mit Timeout != 0 suchen
+
+ ULONG nPos = 0;
+ ScAutoStyleData* pData;
+ while ( (pData = (ScAutoStyleData*) aEntries.GetObject(nPos)) != NULL && pData->nTimeout == 0 )
+ ++nPos;
+
+ if (pData)
+ {
+ aTimer.SetTimeout( pData->nTimeout );
+ aTimer.Start();
+ }
+ nTimerStart = nNow;
+}
+
+IMPL_LINK( ScAutoStyleList, TimerHdl, Timer*, EMPTYARG )
+{
+ ULONG nNow = TimeNow();
+ AdjustEntries(aTimer.GetTimeout()); // eingestellte Wartezeit
+ ExecuteEntries();
+ StartTimer(nNow);
+
+ return 0;
+}
+
+
+
+
diff --git a/sc/source/ui/docshell/dbdocfun.cxx b/sc/source/ui/docshell/dbdocfun.cxx
new file mode 100644
index 000000000000..1633af000b51
--- /dev/null
+++ b/sc/source/ui/docshell/dbdocfun.cxx
@@ -0,0 +1,1487 @@
+/*************************************************************************
+ *
+ * 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 <sfx2/app.hxx>
+#include <vcl/msgbox.hxx>
+#include <vcl/waitobj.hxx>
+
+#include <com/sun/star/sdbc/XResultSet.hpp>
+
+#include "dbdocfun.hxx"
+#include "sc.hrc"
+#include "dbcolect.hxx"
+#include "undodat.hxx"
+#include "docsh.hxx"
+#include "docfunc.hxx"
+#include "globstr.hrc"
+#include "tabvwsh.hxx"
+#include "patattr.hxx"
+#include "rangenam.hxx"
+#include "olinetab.hxx"
+#include "dpobject.hxx"
+#include "dociter.hxx" // for lcl_EmptyExcept
+#include "cell.hxx" // for lcl_EmptyExcept
+#include "editable.hxx"
+#include "attrib.hxx"
+#include "drwlayer.hxx"
+#include "dpshttab.hxx"
+
+// -----------------------------------------------------------------
+
+BOOL ScDBDocFunc::AddDBRange( const String& rName, const ScRange& rRange, BOOL /* bApi */ )
+{
+
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ ScDBCollection* pDocColl = pDoc->GetDBCollection();
+ BOOL bUndo (pDoc->IsUndoEnabled());
+
+ ScDBCollection* pUndoColl = NULL;
+ if (bUndo)
+ pUndoColl = new ScDBCollection( *pDocColl );
+
+ ScDBData* pNew = new ScDBData( rName, rRange.aStart.Tab(),
+ rRange.aStart.Col(), rRange.aStart.Row(),
+ rRange.aEnd.Col(), rRange.aEnd.Row() );
+
+ // #i55926# While loading XML, formula cells only have a single string token,
+ // so CompileDBFormula would never find any name (index) tokens, and would
+ // unnecessarily loop through all cells.
+ BOOL bCompile = !pDoc->IsImportingXML();
+
+ if ( bCompile )
+ pDoc->CompileDBFormula( TRUE ); // CreateFormulaString
+ BOOL bOk = pDocColl->Insert( pNew );
+ if ( bCompile )
+ pDoc->CompileDBFormula( FALSE ); // CompileFormulaString
+
+ if (!bOk)
+ {
+ delete pNew;
+ delete pUndoColl;
+ return FALSE;
+ }
+
+ if (bUndo)
+ {
+ ScDBCollection* pRedoColl = new ScDBCollection( *pDocColl );
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDBData( &rDocShell, pUndoColl, pRedoColl ) );
+ }
+
+ aModificator.SetDocumentModified();
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
+ return TRUE;
+}
+
+BOOL ScDBDocFunc::DeleteDBRange( const String& rName, BOOL /* bApi */ )
+{
+ BOOL bDone = FALSE;
+ ScDocument* pDoc = rDocShell.GetDocument();
+ ScDBCollection* pDocColl = pDoc->GetDBCollection();
+ BOOL bUndo (pDoc->IsUndoEnabled());
+
+ USHORT nPos = 0;
+ if (pDocColl->SearchName( rName, nPos ))
+ {
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScDBCollection* pUndoColl = NULL;
+ if (bUndo)
+ pUndoColl = new ScDBCollection( *pDocColl );
+
+ pDoc->CompileDBFormula( TRUE ); // CreateFormulaString
+ pDocColl->AtFree( nPos );
+ pDoc->CompileDBFormula( FALSE ); // CompileFormulaString
+
+ if (bUndo)
+ {
+ ScDBCollection* pRedoColl = new ScDBCollection( *pDocColl );
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDBData( &rDocShell, pUndoColl, pRedoColl ) );
+ }
+
+ aModificator.SetDocumentModified();
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
+ bDone = TRUE;
+ }
+
+ return bDone;
+}
+
+BOOL ScDBDocFunc::RenameDBRange( const String& rOld, const String& rNew, BOOL /* bApi */ )
+{
+ BOOL bDone = FALSE;
+ ScDocument* pDoc = rDocShell.GetDocument();
+ ScDBCollection* pDocColl = pDoc->GetDBCollection();
+ BOOL bUndo (pDoc->IsUndoEnabled());
+
+ USHORT nPos = 0;
+ USHORT nDummy = 0;
+ if ( pDocColl->SearchName( rOld, nPos ) &&
+ !pDocColl->SearchName( rNew, nDummy ) )
+ {
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScDBData* pData = (*pDocColl)[nPos];
+ ScDBData* pNewData = new ScDBData(*pData);
+ pNewData->SetName(rNew);
+
+ ScDBCollection* pUndoColl = new ScDBCollection( *pDocColl );
+
+ pDoc->CompileDBFormula( TRUE ); // CreateFormulaString
+ pDocColl->AtFree( nPos );
+ BOOL bInserted = pDocColl->Insert( pNewData );
+ if (!bInserted) // Fehler -> alten Zustand wiederherstellen
+ {
+ delete pNewData;
+ pDoc->SetDBCollection( pUndoColl ); // gehoert dann dem Dokument
+ }
+ pDoc->CompileDBFormula( FALSE ); // CompileFormulaString
+
+ if (bInserted) // Einfuegen hat geklappt
+ {
+ if (bUndo)
+ {
+ ScDBCollection* pRedoColl = new ScDBCollection( *pDocColl );
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDBData( &rDocShell, pUndoColl, pRedoColl ) );
+ }
+ else
+ delete pUndoColl;
+
+ aModificator.SetDocumentModified();
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
+ bDone = TRUE;
+ }
+ }
+
+ return bDone;
+}
+
+BOOL ScDBDocFunc::ModifyDBData( const ScDBData& rNewData, BOOL /* bApi */ )
+{
+ BOOL bDone = FALSE;
+ ScDocument* pDoc = rDocShell.GetDocument();
+ ScDBCollection* pDocColl = pDoc->GetDBCollection();
+ BOOL bUndo (pDoc->IsUndoEnabled());
+
+ USHORT nPos = 0;
+ if (pDocColl->SearchName( rNewData.GetName(), nPos ))
+ {
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScDBData* pData = (*pDocColl)[nPos];
+
+ ScRange aOldRange, aNewRange;
+ pData->GetArea(aOldRange);
+ rNewData.GetArea(aNewRange);
+ BOOL bAreaChanged = ( aOldRange != aNewRange ); // dann muss neu compiliert werden
+
+ ScDBCollection* pUndoColl = NULL;
+ if (bUndo)
+ pUndoColl = new ScDBCollection( *pDocColl );
+
+ *pData = rNewData;
+ if (bAreaChanged)
+ pDoc->CompileDBFormula();
+
+ if (bUndo)
+ {
+ ScDBCollection* pRedoColl = new ScDBCollection( *pDocColl );
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDBData( &rDocShell, pUndoColl, pRedoColl ) );
+ }
+
+ aModificator.SetDocumentModified();
+ bDone = TRUE;
+ }
+
+ return bDone;
+}
+
+// -----------------------------------------------------------------
+
+BOOL ScDBDocFunc::RepeatDB( const String& rDBName, BOOL bRecord, BOOL bApi )
+{
+ //! auch fuer ScDBFunc::RepeatDB benutzen!
+
+ BOOL bDone = FALSE;
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+ ScDBCollection* pColl = pDoc->GetDBCollection();
+ USHORT nIndex;
+ if ( pColl && pColl->SearchName( rDBName, nIndex ) )
+ {
+ ScDBData* pDBData = (*pColl)[nIndex];
+
+ ScQueryParam aQueryParam;
+ pDBData->GetQueryParam( aQueryParam );
+ BOOL bQuery = aQueryParam.GetEntry(0).bDoQuery;
+
+ ScSortParam aSortParam;
+ pDBData->GetSortParam( aSortParam );
+ BOOL bSort = aSortParam.bDoSort[0];
+
+ ScSubTotalParam aSubTotalParam;
+ pDBData->GetSubTotalParam( aSubTotalParam );
+ BOOL bSubTotal = aSubTotalParam.bGroupActive[0] && !aSubTotalParam.bRemoveOnly;
+
+ if ( bQuery || bSort || bSubTotal )
+ {
+ BOOL bQuerySize = FALSE;
+ ScRange aOldQuery;
+ ScRange aNewQuery;
+ if (bQuery && !aQueryParam.bInplace)
+ {
+ ScDBData* pDest = pDoc->GetDBAtCursor( aQueryParam.nDestCol, aQueryParam.nDestRow,
+ aQueryParam.nDestTab, TRUE );
+ if (pDest && pDest->IsDoSize())
+ {
+ pDest->GetArea( aOldQuery );
+ bQuerySize = TRUE;
+ }
+ }
+
+ SCTAB nTab;
+ SCCOL nStartCol;
+ SCROW nStartRow;
+ SCCOL nEndCol;
+ SCROW nEndRow;
+ pDBData->GetArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow );
+
+ //! Undo nur benoetigte Daten ?
+
+ ScDocument* pUndoDoc = NULL;
+ ScOutlineTable* pUndoTab = NULL;
+ ScRangeName* pUndoRange = NULL;
+ ScDBCollection* pUndoDB = NULL;
+
+ if (bRecord)
+ {
+ SCTAB nTabCount = pDoc->GetTableCount();
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
+ if (pTable)
+ {
+ pUndoTab = new ScOutlineTable( *pTable );
+
+ // column/row state
+ SCCOLROW nOutStartCol, nOutEndCol;
+ SCCOLROW nOutStartRow, nOutEndRow;
+ pTable->GetColArray()->GetRange( nOutStartCol, nOutEndCol );
+ pTable->GetRowArray()->GetRange( nOutStartRow, nOutEndRow );
+
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, TRUE, TRUE );
+ pDoc->CopyToDocument( static_cast<SCCOL>(nOutStartCol), 0,
+ nTab, static_cast<SCCOL>(nOutEndCol), MAXROW, nTab,
+ IDF_NONE, FALSE, pUndoDoc );
+ pDoc->CopyToDocument( 0, static_cast<SCROW>(nOutStartRow),
+ nTab, MAXCOL, static_cast<SCROW>(nOutEndRow), nTab,
+ IDF_NONE, FALSE, pUndoDoc );
+ }
+ else
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, FALSE, TRUE );
+
+ // Datenbereich sichern - incl. Filter-Ergebnis
+ pDoc->CopyToDocument( 0,nStartRow,nTab, MAXCOL,nEndRow,nTab, IDF_ALL, FALSE, pUndoDoc );
+
+ // alle Formeln wegen Referenzen
+ pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1, IDF_FORMULA, FALSE, pUndoDoc );
+
+ // DB- und andere Bereiche
+ ScRangeName* pDocRange = pDoc->GetRangeName();
+ if (pDocRange->GetCount())
+ pUndoRange = new ScRangeName( *pDocRange );
+ ScDBCollection* pDocDB = pDoc->GetDBCollection();
+ if (pDocDB->GetCount())
+ pUndoDB = new ScDBCollection( *pDocDB );
+ }
+
+ if (bSort && bSubTotal)
+ {
+ // Sortieren ohne SubTotals
+
+ aSubTotalParam.bRemoveOnly = TRUE; // wird unten wieder zurueckgesetzt
+ DoSubTotals( nTab, aSubTotalParam, NULL, FALSE, bApi );
+ }
+
+ if (bSort)
+ {
+ pDBData->GetSortParam( aSortParam ); // Bereich kann sich geaendert haben
+ Sort( nTab, aSortParam, FALSE, FALSE, bApi );
+ }
+ if (bQuery)
+ {
+ pDBData->GetQueryParam( aQueryParam ); // Bereich kann sich geaendert haben
+ ScRange aAdvSource;
+ if (pDBData->GetAdvancedQuerySource(aAdvSource))
+ Query( nTab, aQueryParam, &aAdvSource, FALSE, bApi );
+ else
+ Query( nTab, aQueryParam, NULL, FALSE, bApi );
+
+ // bei nicht-inplace kann die Tabelle umgestellt worden sein
+// if ( !aQueryParam.bInplace && aQueryParam.nDestTab != nTab )
+// SetTabNo( nTab );
+ }
+ if (bSubTotal)
+ {
+ pDBData->GetSubTotalParam( aSubTotalParam ); // Bereich kann sich geaendert haben
+ aSubTotalParam.bRemoveOnly = FALSE;
+ DoSubTotals( nTab, aSubTotalParam, NULL, FALSE, bApi );
+ }
+
+ if (bRecord)
+ {
+ SCTAB nDummyTab;
+ SCCOL nDummyCol;
+ SCROW nDummyRow;
+ SCROW nNewEndRow;
+ pDBData->GetArea( nDummyTab, nDummyCol,nDummyRow, nDummyCol,nNewEndRow );
+
+ const ScRange* pOld = NULL;
+ const ScRange* pNew = NULL;
+ if (bQuerySize)
+ {
+ ScDBData* pDest = pDoc->GetDBAtCursor( aQueryParam.nDestCol, aQueryParam.nDestRow,
+ aQueryParam.nDestTab, TRUE );
+ if (pDest)
+ {
+ pDest->GetArea( aNewQuery );
+ pOld = &aOldQuery;
+ pNew = &aNewQuery;
+ }
+ }
+
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoRepeatDB( &rDocShell, nTab,
+ nStartCol, nStartRow, nEndCol, nEndRow,
+ nNewEndRow,
+ //nCurX, nCurY,
+ nStartCol, nStartRow,
+ pUndoDoc, pUndoTab,
+ pUndoRange, pUndoDB,
+ pOld, pNew ) );
+ }
+
+ rDocShell.PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab,
+ PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE );
+ bDone = TRUE;
+ }
+ else if (!bApi) // "Keine Operationen auszufuehren"
+ rDocShell.ErrorMessage(STR_MSSG_REPEATDB_0);
+ }
+
+ return bDone;
+}
+
+// -----------------------------------------------------------------
+
+BOOL ScDBDocFunc::Sort( SCTAB nTab, const ScSortParam& rSortParam,
+ BOOL bRecord, BOOL bPaint, BOOL bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+ SCTAB nSrcTab = nTab;
+ ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
+
+ ScDBData* pDBData = pDoc->GetDBAtArea( nTab, rSortParam.nCol1, rSortParam.nRow1,
+ rSortParam.nCol2, rSortParam.nRow2 );
+ if (!pDBData)
+ {
+ DBG_ERROR( "Sort: keine DBData" );
+ return FALSE;
+ }
+
+ ScDBData* pDestData = NULL;
+ ScRange aOldDest;
+ BOOL bCopy = !rSortParam.bInplace;
+ if ( bCopy && rSortParam.nDestCol == rSortParam.nCol1 &&
+ rSortParam.nDestRow == rSortParam.nRow1 && rSortParam.nDestTab == nTab )
+ bCopy = FALSE;
+ ScSortParam aLocalParam( rSortParam );
+ if ( bCopy )
+ {
+ aLocalParam.MoveToDest();
+ if ( !ValidColRow( aLocalParam.nCol2, aLocalParam.nRow2 ) )
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_PASTE_FULL);
+ return FALSE;
+ }
+
+ nTab = rSortParam.nDestTab;
+ pDestData = pDoc->GetDBAtCursor( rSortParam.nDestCol, rSortParam.nDestRow,
+ rSortParam.nDestTab, TRUE );
+ if (pDestData)
+ pDestData->GetArea(aOldDest);
+ }
+
+ ScEditableTester aTester( pDoc, nTab, aLocalParam.nCol1,aLocalParam.nRow1,
+ aLocalParam.nCol2,aLocalParam.nRow2 );
+ if (!aTester.IsEditable())
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ return FALSE;
+ }
+
+ if ( aLocalParam.bIncludePattern && pDoc->HasAttrib(
+ aLocalParam.nCol1, aLocalParam.nRow1, nTab,
+ aLocalParam.nCol2, aLocalParam.nRow2, nTab,
+ HASATTR_MERGED | HASATTR_OVERLAPPED ) )
+ {
+ // Merge-Attribute wuerden beim Sortieren durcheinanderkommen
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_SORT_ERR_MERGED);
+ return FALSE;
+ }
+
+
+ // ausfuehren
+
+ WaitObject aWait( rDocShell.GetActiveDialogParent() );
+
+ BOOL bRepeatQuery = FALSE; // bestehenden Filter wiederholen?
+ ScQueryParam aQueryParam;
+ pDBData->GetQueryParam( aQueryParam );
+ if ( aQueryParam.GetEntry(0).bDoQuery )
+ bRepeatQuery = TRUE;
+
+ if (bRepeatQuery && bCopy)
+ {
+ if ( aQueryParam.bInplace ||
+ aQueryParam.nDestCol != rSortParam.nDestCol ||
+ aQueryParam.nDestRow != rSortParam.nDestRow ||
+ aQueryParam.nDestTab != rSortParam.nDestTab ) // Query auf selben Zielbereich?
+ bRepeatQuery = FALSE;
+ }
+
+ ScUndoSort* pUndoAction = 0;
+ if ( bRecord )
+ {
+ // Referenzen ausserhalb des Bereichs werden nicht veraendert !
+
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ // Zeilenhoehen immer (wegen automatischer Anpassung)
+ //! auf ScBlockUndo umstellen
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, FALSE, TRUE );
+
+ /* #i59745# Do not copy note captions to undo document. All existing
+ caption objects will be repositioned while sorting which is tracked
+ in drawing undo. When undo is executed, the old positions will be
+ restored, and the cells with the old notes (which still refer to the
+ existing captions) will be copied back into the source document. */
+ pDoc->CopyToDocument( aLocalParam.nCol1, aLocalParam.nRow1, nTab,
+ aLocalParam.nCol2, aLocalParam.nRow2, nTab,
+ IDF_ALL|IDF_NOCAPTIONS, FALSE, pUndoDoc );
+
+ const ScRange* pR = 0;
+ if (pDestData)
+ {
+ /* #i59745# Do not copy note captions from destination range to
+ undo document. All existing caption objects will be removed
+ which is tracked in drawing undo. When undo is executed, the
+ caption objects are reinserted with drawing undo, and the cells
+ with the old notes (which still refer to the existing captions)
+ will be copied back into the source document. */
+ pDoc->CopyToDocument( aOldDest, IDF_ALL|IDF_NOCAPTIONS, FALSE, pUndoDoc );
+ pR = &aOldDest;
+ }
+
+ // Zeilenhoehen immer (wegen automatischer Anpassung)
+ //! auf ScBlockUndo umstellen
+// if (bRepeatQuery)
+ pDoc->CopyToDocument( 0, aLocalParam.nRow1, nTab, MAXCOL, aLocalParam.nRow2, nTab,
+ IDF_NONE, FALSE, pUndoDoc );
+
+ ScDBCollection* pUndoDB = NULL;
+ ScDBCollection* pDocDB = pDoc->GetDBCollection();
+ if (pDocDB->GetCount())
+ pUndoDB = new ScDBCollection( *pDocDB );
+
+ pUndoAction = new ScUndoSort( &rDocShell, nTab, rSortParam, bRepeatQuery, pUndoDoc, pUndoDB, pR );
+ rDocShell.GetUndoManager()->AddUndoAction( pUndoAction );
+
+ // #i59745# collect all drawing undo actions affecting cell note captions
+ if( pDrawLayer )
+ pDrawLayer->BeginCalcUndo();
+ }
+
+ if ( bCopy )
+ {
+ if (pDestData)
+ pDoc->DeleteAreaTab(aOldDest, IDF_CONTENTS); // Zielbereich vorher loeschen
+
+ ScRange aSource( rSortParam.nCol1,rSortParam.nRow1,nSrcTab,
+ rSortParam.nCol2,rSortParam.nRow2,nSrcTab );
+ ScAddress aDest( rSortParam.nDestCol, rSortParam.nDestRow, rSortParam.nDestTab );
+
+ rDocShell.GetDocFunc().MoveBlock( aSource, aDest, FALSE, FALSE, FALSE, TRUE );
+ }
+
+ // #105780# don't call ScDocument::Sort with an empty SortParam (may be empty here if bCopy is set)
+ if ( aLocalParam.bDoSort[0] )
+ pDoc->Sort( nTab, aLocalParam, bRepeatQuery );
+
+ BOOL bSave = TRUE;
+ if (bCopy)
+ {
+ ScSortParam aOldSortParam;
+ pDBData->GetSortParam( aOldSortParam );
+ if ( aOldSortParam.bDoSort[0] && aOldSortParam.bInplace ) // Inplace-Sortierung gemerkt?
+ {
+ bSave = FALSE;
+ aOldSortParam.nDestCol = rSortParam.nDestCol;
+ aOldSortParam.nDestRow = rSortParam.nDestRow;
+ aOldSortParam.nDestTab = rSortParam.nDestTab;
+ pDBData->SetSortParam( aOldSortParam ); // dann nur DestPos merken
+ }
+ }
+ if (bSave) // Parameter merken
+ {
+ pDBData->SetSortParam( rSortParam );
+ pDBData->SetHeader( rSortParam.bHasHeader ); //! ???
+ pDBData->SetByRow( rSortParam.bByRow ); //! ???
+ }
+
+ if (bCopy) // neuen DB-Bereich merken
+ {
+ // Tabelle umschalten von aussen (View)
+ //! SetCursor ??!?!
+
+ ScRange aDestPos( aLocalParam.nCol1, aLocalParam.nRow1, nTab,
+ aLocalParam.nCol2, aLocalParam.nRow2, nTab );
+ ScDBData* pNewData;
+ if (pDestData)
+ pNewData = pDestData; // Bereich vorhanden -> anpassen
+ else // Bereich ab Cursor/Markierung wird angelegt
+ pNewData = rDocShell.GetDBData(aDestPos, SC_DB_MAKE, TRUE );
+ if (pNewData)
+ {
+ pNewData->SetArea( nTab,
+ aLocalParam.nCol1,aLocalParam.nRow1,
+ aLocalParam.nCol2,aLocalParam.nRow2 );
+ pNewData->SetSortParam( aLocalParam );
+ pNewData->SetHeader( aLocalParam.bHasHeader ); //! ???
+ pNewData->SetByRow( aLocalParam.bByRow );
+ }
+ else
+ {
+ DBG_ERROR("Zielbereich nicht da");
+ }
+ }
+
+ ScRange aDirtyRange( aLocalParam.nCol1, aLocalParam.nRow1, nTab,
+ aLocalParam.nCol2, aLocalParam.nRow2, nTab );
+ pDoc->SetDirty( aDirtyRange );
+
+ if (bPaint)
+ {
+ USHORT nPaint = PAINT_GRID;
+ SCCOL nStartX = aLocalParam.nCol1;
+ SCROW nStartY = aLocalParam.nRow1;
+ SCCOL nEndX = aLocalParam.nCol2;
+ SCROW nEndY = aLocalParam.nRow2;
+ if ( bRepeatQuery )
+ {
+ nPaint |= PAINT_LEFT;
+ nStartX = 0;
+ nEndX = MAXCOL;
+ }
+ if (pDestData)
+ {
+ if ( nEndX < aOldDest.aEnd.Col() )
+ nEndX = aOldDest.aEnd.Col();
+ if ( nEndY < aOldDest.aEnd.Row() )
+ nEndY = aOldDest.aEnd.Row();
+ }
+ rDocShell.PostPaint( nStartX, nStartY, nTab, nEndX, nEndY, nTab, nPaint );
+ }
+
+ // AdjustRowHeight( aLocalParam.nRow1, aLocalParam.nRow2, bPaint );
+ rDocShell.AdjustRowHeight( aLocalParam.nRow1, aLocalParam.nRow2, nTab );
+
+ // #i59745# set collected drawing undo actions at sorting undo action
+ if( pUndoAction && pDrawLayer )
+ pUndoAction->SetDrawUndoAction( pDrawLayer->GetCalcUndo() );
+
+ aModificator.SetDocumentModified();
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------
+
+BOOL ScDBDocFunc::Query( SCTAB nTab, const ScQueryParam& rQueryParam,
+ const ScRange* pAdvSource, BOOL bRecord, BOOL bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+ ScDBData* pDBData = pDoc->GetDBAtArea( nTab, rQueryParam.nCol1, rQueryParam.nRow1,
+ rQueryParam.nCol2, rQueryParam.nRow2 );
+ if (!pDBData)
+ {
+ DBG_ERROR( "Query: keine DBData" );
+ return FALSE;
+ }
+
+ // Wechsel von Inplace auf nicht-Inplace, dann erst Inplace aufheben:
+ // (nur, wenn im Dialog "Persistent" ausgewaehlt ist)
+
+ if ( !rQueryParam.bInplace && pDBData->HasQueryParam() && rQueryParam.bDestPers )
+ {
+ ScQueryParam aOldQuery;
+ pDBData->GetQueryParam(aOldQuery);
+ if (aOldQuery.bInplace)
+ {
+ // alte Filterung aufheben
+
+ SCSIZE nEC = aOldQuery.GetEntryCount();
+ for (SCSIZE i=0; i<nEC; i++)
+ aOldQuery.GetEntry(i).bDoQuery = FALSE;
+ aOldQuery.bDuplicate = TRUE;
+ Query( nTab, aOldQuery, NULL, bRecord, bApi );
+ }
+ }
+
+ ScQueryParam aLocalParam( rQueryParam ); // fuer Paint / Zielbereich
+ BOOL bCopy = !rQueryParam.bInplace; // kopiert wird in Table::Query
+ ScDBData* pDestData = NULL; // Bereich, in den kopiert wird
+ BOOL bDoSize = FALSE; // Zielgroesse anpassen (einf./loeschen)
+ SCCOL nFormulaCols = 0; // nur bei bDoSize
+ BOOL bKeepFmt = FALSE;
+ ScRange aOldDest;
+ ScRange aDestTotal;
+ if ( bCopy && rQueryParam.nDestCol == rQueryParam.nCol1 &&
+ rQueryParam.nDestRow == rQueryParam.nRow1 && rQueryParam.nDestTab == nTab )
+ bCopy = FALSE;
+ SCTAB nDestTab = nTab;
+ if ( bCopy )
+ {
+ aLocalParam.MoveToDest();
+ nDestTab = rQueryParam.nDestTab;
+ if ( !ValidColRow( aLocalParam.nCol2, aLocalParam.nRow2 ) )
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_PASTE_FULL);
+ return FALSE;
+ }
+
+ ScEditableTester aTester( pDoc, nDestTab, aLocalParam.nCol1,aLocalParam.nRow1,
+ aLocalParam.nCol2,aLocalParam.nRow2);
+ if (!aTester.IsEditable())
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ return FALSE;
+ }
+
+ pDestData = pDoc->GetDBAtCursor( rQueryParam.nDestCol, rQueryParam.nDestRow,
+ rQueryParam.nDestTab, TRUE );
+ if (pDestData)
+ {
+ pDestData->GetArea( aOldDest );
+ aDestTotal=ScRange( rQueryParam.nDestCol,
+ rQueryParam.nDestRow,
+ nDestTab,
+ rQueryParam.nDestCol + rQueryParam.nCol2 - rQueryParam.nCol1,
+ rQueryParam.nDestRow + rQueryParam.nRow2 - rQueryParam.nRow1,
+ nDestTab );
+
+ bDoSize = pDestData->IsDoSize();
+ // Test, ob Formeln aufgefuellt werden muessen (nFormulaCols):
+ if ( bDoSize && aOldDest.aEnd.Col() == aDestTotal.aEnd.Col() )
+ {
+ SCCOL nTestCol = aOldDest.aEnd.Col() + 1; // neben dem Bereich
+ SCROW nTestRow = rQueryParam.nDestRow +
+ ( aLocalParam.bHasHeader ? 1 : 0 );
+ while ( nTestCol <= MAXCOL &&
+ pDoc->GetCellType(ScAddress( nTestCol, nTestRow, nTab )) == CELLTYPE_FORMULA )
+ ++nTestCol, ++nFormulaCols;
+ }
+
+ bKeepFmt = pDestData->IsKeepFmt();
+ if ( bDoSize && !pDoc->CanFitBlock( aOldDest, aDestTotal ) )
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_MSSG_DOSUBTOTALS_2); // kann keine Zeilen einfuegen
+ return FALSE;
+ }
+ }
+ }
+
+ // ausfuehren
+
+ WaitObject aWait( rDocShell.GetActiveDialogParent() );
+
+ BOOL bKeepSub = FALSE; // bestehende Teilergebnisse wiederholen?
+ ScSubTotalParam aSubTotalParam;
+ if (rQueryParam.GetEntry(0).bDoQuery) // nicht beim Aufheben
+ {
+ pDBData->GetSubTotalParam( aSubTotalParam ); // Teilergebnisse vorhanden?
+
+ if ( aSubTotalParam.bGroupActive[0] && !aSubTotalParam.bRemoveOnly )
+ bKeepSub = TRUE;
+ }
+
+ ScDocument* pUndoDoc = NULL;
+ ScDBCollection* pUndoDB = NULL;
+ const ScRange* pOld = NULL;
+
+ if ( bRecord )
+ {
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ if (bCopy)
+ {
+ pUndoDoc->InitUndo( pDoc, nDestTab, nDestTab, FALSE, TRUE );
+ pDoc->CopyToDocument( aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
+ aLocalParam.nCol2, aLocalParam.nRow2, nDestTab,
+ IDF_ALL, FALSE, pUndoDoc );
+ // Attribute sichern, falls beim Filtern mitkopiert
+
+ if (pDestData)
+ {
+ pDoc->CopyToDocument( aOldDest, IDF_ALL, FALSE, pUndoDoc );
+ pOld = &aOldDest;
+ }
+ }
+ else
+ {
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, FALSE, TRUE );
+ pDoc->CopyToDocument( 0, rQueryParam.nRow1, nTab, MAXCOL, rQueryParam.nRow2, nTab,
+ IDF_NONE, FALSE, pUndoDoc );
+ }
+
+ ScDBCollection* pDocDB = pDoc->GetDBCollection();
+ if (pDocDB->GetCount())
+ pUndoDB = new ScDBCollection( *pDocDB );
+
+ pDoc->BeginDrawUndo();
+ }
+
+ ScDocument* pAttribDoc = NULL;
+ ScRange aAttribRange;
+ if (pDestData) // Zielbereich loeschen
+ {
+ if ( bKeepFmt )
+ {
+ // kleinere der End-Spalten, Header+1 Zeile
+ aAttribRange = aOldDest;
+ if ( aAttribRange.aEnd.Col() > aDestTotal.aEnd.Col() )
+ aAttribRange.aEnd.SetCol( aDestTotal.aEnd.Col() );
+ aAttribRange.aEnd.SetRow( aAttribRange.aStart.Row() +
+ ( aLocalParam.bHasHeader ? 1 : 0 ) );
+
+ // auch fuer aufgefuellte Formeln
+ aAttribRange.aEnd.SetCol( aAttribRange.aEnd.Col() + nFormulaCols );
+
+ pAttribDoc = new ScDocument( SCDOCMODE_UNDO );
+ pAttribDoc->InitUndo( pDoc, nDestTab, nDestTab, FALSE, TRUE );
+ pDoc->CopyToDocument( aAttribRange, IDF_ATTRIB, FALSE, pAttribDoc );
+ }
+
+ if ( bDoSize )
+ pDoc->FitBlock( aOldDest, aDestTotal );
+ else
+ pDoc->DeleteAreaTab(aOldDest, IDF_ALL); // einfach loeschen
+ }
+
+ // Filtern am Dokument ausfuehren
+ SCSIZE nCount = pDoc->Query( nTab, rQueryParam, bKeepSub );
+ if (bCopy)
+ {
+ aLocalParam.nRow2 = aLocalParam.nRow1 + nCount;
+ if (!aLocalParam.bHasHeader && nCount > 0)
+ --aLocalParam.nRow2;
+
+ if ( bDoSize )
+ {
+ // auf wirklichen Ergebnis-Bereich anpassen
+ // (das hier ist immer eine Verkleinerung)
+
+ ScRange aNewDest( aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
+ aLocalParam.nCol2, aLocalParam.nRow2, nDestTab );
+ pDoc->FitBlock( aDestTotal, aNewDest, FALSE ); // FALSE - nicht loeschen
+
+ if ( nFormulaCols > 0 )
+ {
+ // Formeln ausfuellen
+ //! Undo (Query und Repeat) !!!
+
+ ScRange aNewForm( aLocalParam.nCol2+1, aLocalParam.nRow1, nDestTab,
+ aLocalParam.nCol2+nFormulaCols, aLocalParam.nRow2, nDestTab );
+ ScRange aOldForm = aNewForm;
+ aOldForm.aEnd.SetRow( aOldDest.aEnd.Row() );
+ pDoc->FitBlock( aOldForm, aNewForm, FALSE );
+
+ ScMarkData aMark;
+ aMark.SelectOneTable(nDestTab);
+ SCROW nFStartY = aLocalParam.nRow1 + ( aLocalParam.bHasHeader ? 1 : 0 );
+ pDoc->Fill( aLocalParam.nCol2+1, nFStartY,
+ aLocalParam.nCol2+nFormulaCols, nFStartY, aMark,
+ aLocalParam.nRow2 - nFStartY,
+ FILL_TO_BOTTOM, FILL_SIMPLE );
+ }
+ }
+
+ if ( pAttribDoc ) // gemerkte Attribute zurueckkopieren
+ {
+ // Header
+ if (aLocalParam.bHasHeader)
+ {
+ ScRange aHdrRange = aAttribRange;
+ aHdrRange.aEnd.SetRow( aHdrRange.aStart.Row() );
+ pAttribDoc->CopyToDocument( aHdrRange, IDF_ATTRIB, FALSE, pDoc );
+ }
+
+ // Daten
+ SCCOL nAttrEndCol = aAttribRange.aEnd.Col();
+ SCROW nAttrRow = aAttribRange.aStart.Row() + ( aLocalParam.bHasHeader ? 1 : 0 );
+ for (SCCOL nCol = aAttribRange.aStart.Col(); nCol<=nAttrEndCol; nCol++)
+ {
+ const ScPatternAttr* pSrcPattern = pAttribDoc->GetPattern(
+ nCol, nAttrRow, nDestTab );
+ DBG_ASSERT(pSrcPattern,"Pattern ist 0");
+ if (pSrcPattern)
+ pDoc->ApplyPatternAreaTab( nCol, nAttrRow, nCol, aLocalParam.nRow2,
+ nDestTab, *pSrcPattern );
+ const ScStyleSheet* pStyle = pSrcPattern->GetStyleSheet();
+ if (pStyle)
+ pDoc->ApplyStyleAreaTab( nCol, nAttrRow, nCol, aLocalParam.nRow2,
+ nDestTab, *pStyle );
+ }
+
+ delete pAttribDoc;
+ }
+ }
+
+ // speichern: Inplace immer, sonst je nach Einstellung
+ // alter Inplace-Filter ist ggf. schon aufgehoben
+
+ BOOL bSave = rQueryParam.bInplace || rQueryParam.bDestPers;
+ if (bSave) // merken
+ {
+ pDBData->SetQueryParam( rQueryParam );
+ pDBData->SetHeader( rQueryParam.bHasHeader ); //! ???
+ pDBData->SetAdvancedQuerySource( pAdvSource ); // after SetQueryParam
+ }
+
+ if (bCopy) // neuen DB-Bereich merken
+ {
+ // selektieren wird hinterher von aussen (dbfunc)
+ // momentan ueber DB-Bereich an der Zielposition, darum muss dort
+ // auf jeden Fall ein Bereich angelegt werden.
+
+ ScDBData* pNewData;
+ if (pDestData)
+ pNewData = pDestData; // Bereich vorhanden -> anpassen (immer!)
+ else // Bereich anlegen
+ pNewData = rDocShell.GetDBData(
+ ScRange( aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
+ aLocalParam.nCol2, aLocalParam.nRow2, nDestTab ),
+ SC_DB_MAKE, TRUE );
+
+ if (pNewData)
+ {
+ pNewData->SetArea( nDestTab, aLocalParam.nCol1, aLocalParam.nRow1,
+ aLocalParam.nCol2, aLocalParam.nRow2 );
+
+ // Query-Param wird am Ziel nicht mehr eingestellt, fuehrt nur zu Verwirrung
+ // und Verwechslung mit dem Query-Param am Quellbereich (#37187#)
+ }
+ else
+ {
+ DBG_ERROR("Zielbereich nicht da");
+ }
+ }
+
+ if (!bCopy)
+ pDoc->UpdatePageBreaks( nTab );
+
+ // #i23299# because of Subtotal functions, the whole rows must be set dirty
+ ScRange aDirtyRange( 0 , aLocalParam.nRow1, nDestTab,
+ MAXCOL, aLocalParam.nRow2, nDestTab );
+ pDoc->SetDirty( aDirtyRange );
+
+ if ( bRecord )
+ {
+ // create undo action after executing, because of drawing layer undo
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoQuery( &rDocShell, nTab, rQueryParam, pUndoDoc, pUndoDB,
+ pOld, bDoSize, pAdvSource ) );
+ }
+
+
+ if (bCopy)
+ {
+ SCCOL nEndX = aLocalParam.nCol2;
+ SCROW nEndY = aLocalParam.nRow2;
+ if (pDestData)
+ {
+ if ( aOldDest.aEnd.Col() > nEndX )
+ nEndX = aOldDest.aEnd.Col();
+ if ( aOldDest.aEnd.Row() > nEndY )
+ nEndY = aOldDest.aEnd.Row();
+ }
+ if (bDoSize)
+ nEndY = MAXROW;
+ rDocShell.PostPaint( aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
+ nEndX, nEndY, nDestTab, PAINT_GRID );
+ }
+ else
+ rDocShell.PostPaint( 0, rQueryParam.nRow1, nTab, MAXCOL, MAXROW, nTab,
+ PAINT_GRID | PAINT_LEFT );
+ aModificator.SetDocumentModified();
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------
+
+BOOL ScDBDocFunc::DoSubTotals( SCTAB nTab, const ScSubTotalParam& rParam,
+ const ScSortParam* pForceNewSort, BOOL bRecord, BOOL bApi )
+{
+ //! auch fuer ScDBFunc::DoSubTotals benutzen!
+ // dann bleibt aussen:
+ // - neuen Bereich (aus DBData) markieren
+ // - SelectionChanged (?)
+
+ BOOL bDo = !rParam.bRemoveOnly; // FALSE = nur loeschen
+ BOOL bRet = FALSE;
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+ ScDBData* pDBData = pDoc->GetDBAtArea( nTab, rParam.nCol1, rParam.nRow1,
+ rParam.nCol2, rParam.nRow2 );
+ if (!pDBData)
+ {
+ DBG_ERROR( "SubTotals: keine DBData" );
+ return FALSE;
+ }
+
+ ScEditableTester aTester( pDoc, nTab, 0,rParam.nRow1+1, MAXCOL,MAXROW );
+ if (!aTester.IsEditable())
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ return FALSE;
+ }
+
+ if (pDoc->HasAttrib( rParam.nCol1, rParam.nRow1+1, nTab,
+ rParam.nCol2, rParam.nRow2, nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ))
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0); // nicht in zusammengefasste einfuegen
+ return FALSE;
+ }
+
+ BOOL bOk = TRUE;
+ BOOL bDelete = FALSE;
+ if (rParam.bReplace)
+ if (pDoc->TestRemoveSubTotals( nTab, rParam ))
+ {
+ bDelete = TRUE;
+ bOk = ( MessBox( rDocShell.GetActiveDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES),
+ // "StarCalc" "Daten loeschen?"
+ ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ),
+ ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_1 ) ).Execute()
+ == RET_YES );
+ }
+
+ if (bOk)
+ {
+ WaitObject aWait( rDocShell.GetActiveDialogParent() );
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScSubTotalParam aNewParam( rParam ); // Bereichsende wird veraendert
+ ScDocument* pUndoDoc = NULL;
+ ScOutlineTable* pUndoTab = NULL;
+ ScRangeName* pUndoRange = NULL;
+ ScDBCollection* pUndoDB = NULL;
+ SCTAB nTabCount = 0; // fuer Referenz-Undo
+
+ if (bRecord) // alte Daten sichern
+ {
+ BOOL bOldFilter = bDo && rParam.bDoSort;
+
+ nTabCount = pDoc->GetTableCount();
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
+ if (pTable)
+ {
+ pUndoTab = new ScOutlineTable( *pTable );
+
+ // column/row state
+ SCCOLROW nOutStartCol, nOutEndCol;
+ SCCOLROW nOutStartRow, nOutEndRow;
+ pTable->GetColArray()->GetRange( nOutStartCol, nOutEndCol );
+ pTable->GetRowArray()->GetRange( nOutStartRow, nOutEndRow );
+
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, TRUE, TRUE );
+ pDoc->CopyToDocument( static_cast<SCCOL>(nOutStartCol), 0, nTab, static_cast<SCCOL>(nOutEndCol), MAXROW, nTab, IDF_NONE, FALSE, pUndoDoc );
+ pDoc->CopyToDocument( 0, nOutStartRow, nTab, MAXCOL, nOutEndRow, nTab, IDF_NONE, FALSE, pUndoDoc );
+ }
+ else
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, FALSE, bOldFilter );
+
+ // Datenbereich sichern - incl. Filter-Ergebnis
+ pDoc->CopyToDocument( 0,rParam.nRow1+1,nTab, MAXCOL,rParam.nRow2,nTab,
+ IDF_ALL, FALSE, pUndoDoc );
+
+ // alle Formeln wegen Referenzen
+ pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1,
+ IDF_FORMULA, FALSE, pUndoDoc );
+
+ // DB- und andere Bereiche
+ ScRangeName* pDocRange = pDoc->GetRangeName();
+ if (pDocRange->GetCount())
+ pUndoRange = new ScRangeName( *pDocRange );
+ ScDBCollection* pDocDB = pDoc->GetDBCollection();
+ if (pDocDB->GetCount())
+ pUndoDB = new ScDBCollection( *pDocDB );
+ }
+
+// pDoc->SetOutlineTable( nTab, NULL );
+ ScOutlineTable* pOut = pDoc->GetOutlineTable( nTab );
+ if (pOut)
+ pOut->GetRowArray()->RemoveAll(); // nur Zeilen-Outlines loeschen
+
+ if (rParam.bReplace)
+ pDoc->RemoveSubTotals( nTab, aNewParam );
+ BOOL bSuccess = TRUE;
+ if (bDo)
+ {
+ // Sortieren
+ if ( rParam.bDoSort || pForceNewSort )
+ {
+ pDBData->SetArea( nTab, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 );
+
+ // Teilergebnis-Felder vor die Sortierung setzen
+ // (doppelte werden weggelassen, kann darum auch wieder aufgerufen werden)
+
+ ScSortParam aOldSort;
+ pDBData->GetSortParam( aOldSort );
+ ScSortParam aSortParam( aNewParam, pForceNewSort ? *pForceNewSort : aOldSort );
+ Sort( nTab, aSortParam, FALSE, FALSE, bApi );
+ }
+
+ bSuccess = pDoc->DoSubTotals( nTab, aNewParam );
+ }
+ ScRange aDirtyRange( aNewParam.nCol1, aNewParam.nRow1, nTab,
+ aNewParam.nCol2, aNewParam.nRow2, nTab );
+ pDoc->SetDirty( aDirtyRange );
+
+ if (bRecord)
+ {
+// ScDBData* pUndoDBData = pDBData ? new ScDBData( *pDBData ) : NULL;
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoSubTotals( &rDocShell, nTab,
+ rParam, aNewParam.nRow2,
+ pUndoDoc, pUndoTab, // pUndoDBData,
+ pUndoRange, pUndoDB ) );
+ }
+
+ if (!bSuccess)
+ {
+ // "Kann keine Zeilen einfuegen"
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_MSSG_DOSUBTOTALS_2);
+ }
+
+ // merken
+ pDBData->SetSubTotalParam( aNewParam );
+ pDBData->SetArea( nTab, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 );
+ pDoc->CompileDBFormula();
+
+ rDocShell.PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab,
+ PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE );
+ aModificator.SetDocumentModified();
+
+ bRet = bSuccess;
+ }
+ return bRet;
+}
+
+//==================================================================
+
+BOOL lcl_EmptyExcept( ScDocument* pDoc, const ScRange& rRange, const ScRange& rExcept )
+{
+ ScCellIterator aIter( pDoc, rRange );
+ ScBaseCell* pCell = aIter.GetFirst();
+ while (pCell)
+ {
+ if ( !pCell->IsBlank() ) // real content?
+ {
+ if ( !rExcept.In( ScAddress( aIter.GetCol(), aIter.GetRow(), aIter.GetTab() ) ) )
+ return FALSE; // cell found
+ }
+ pCell = aIter.GetNext();
+ }
+
+ return TRUE; // nothing found - empty
+}
+
+BOOL ScDBDocFunc::DataPilotUpdate( ScDPObject* pOldObj, const ScDPObject* pNewObj,
+ BOOL bRecord, BOOL bApi, BOOL bAllowMove )
+{
+ ScDocShellModificator aModificator( rDocShell );
+ WaitObject aWait( rDocShell.GetActiveDialogParent() );
+
+ BOOL bDone = FALSE;
+ BOOL bUndoSelf = FALSE;
+ USHORT nErrId = 0;
+
+ ScDocument* pOldUndoDoc = NULL;
+ ScDocument* pNewUndoDoc = NULL;
+ ScDPObject* pUndoDPObj = NULL;
+ if ( bRecord && pOldObj )
+ pUndoDPObj = new ScDPObject( *pOldObj ); // copy old settings for undo
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+ if ( !rDocShell.IsEditable() || pDoc->GetChangeTrack() )
+ {
+ // not recorded -> disallow
+ //! different error messages?
+
+ nErrId = STR_PROTECTIONERR;
+ }
+ if ( pOldObj && !nErrId )
+ {
+ ScRange aOldOut = pOldObj->GetOutRange();
+ ScEditableTester aTester( pDoc, aOldOut );
+ if ( !aTester.IsEditable() )
+ nErrId = aTester.GetMessageId();
+ }
+ if ( pNewObj && !nErrId )
+ {
+ // at least one cell at the output position must be editable
+ // -> check in advance
+ // (start of output range in pNewObj is valid)
+
+ ScRange aNewStart( pNewObj->GetOutRange().aStart );
+ ScEditableTester aTester( pDoc, aNewStart );
+ if ( !aTester.IsEditable() )
+ nErrId = aTester.GetMessageId();
+ }
+
+ ScDPObject* pDestObj = NULL;
+ if ( !nErrId )
+ {
+ if ( pOldObj && !pNewObj )
+ {
+ // delete table
+
+ ScRange aRange = pOldObj->GetOutRange();
+ SCTAB nTab = aRange.aStart.Tab();
+
+ if ( bRecord )
+ {
+ pOldUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pOldUndoDoc->InitUndo( pDoc, nTab, nTab );
+ pDoc->CopyToDocument( aRange, IDF_ALL, FALSE, pOldUndoDoc );
+ }
+
+ pDoc->DeleteAreaTab( aRange.aStart.Col(), aRange.aStart.Row(),
+ aRange.aEnd.Col(), aRange.aEnd.Row(),
+ nTab, IDF_ALL );
+ pDoc->RemoveFlagsTab( aRange.aStart.Col(), aRange.aStart.Row(),
+ aRange.aEnd.Col(), aRange.aEnd.Row(),
+ nTab, SC_MF_AUTO );
+
+ pDoc->GetDPCollection()->FreeTable( pOldObj ); // object is deleted here
+
+ rDocShell.PostPaintGridAll(); //! only necessary parts
+ rDocShell.PostPaint( aRange.aStart.Col(), aRange.aStart.Row(), nTab,
+ aRange.aEnd.Col(), aRange.aEnd.Row(), nTab,
+ PAINT_GRID );
+ bDone = TRUE;
+ }
+ else if ( pNewObj )
+ {
+ if ( pOldObj )
+ {
+ if ( bRecord )
+ {
+ ScRange aRange = pOldObj->GetOutRange();
+ SCTAB nTab = aRange.aStart.Tab();
+ pOldUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pOldUndoDoc->InitUndo( pDoc, nTab, nTab );
+ pDoc->CopyToDocument( aRange, IDF_ALL, FALSE, pOldUndoDoc );
+ }
+
+ if ( pNewObj == pOldObj )
+ {
+ // refresh only - no settings modified
+ }
+ else
+ {
+ pNewObj->WriteSourceDataTo( *pOldObj ); // copy source data
+
+ ScDPSaveData* pData = pNewObj->GetSaveData();
+ DBG_ASSERT( pData, "no SaveData from living DPObject" );
+ if ( pData )
+ pOldObj->SetSaveData( *pData ); // copy SaveData
+ }
+
+ pDestObj = pOldObj;
+ pDestObj->SetAllowMove( bAllowMove );
+ }
+ else
+ {
+ // output range must be set at pNewObj
+
+ pDestObj = new ScDPObject( *pNewObj );
+ pDestObj->SetAlive(TRUE);
+ if ( !pDoc->GetDPCollection()->InsertNewTable(pDestObj) )
+ {
+ DBG_ERROR("cannot insert DPObject");
+ DELETEZ( pDestObj );
+ }
+ }
+ if ( pDestObj )
+ {
+ // #78541# create new database connection for "refresh"
+ // (and re-read column entry collections)
+ // so all changes take effect
+ if ( pNewObj == pOldObj && pDestObj->IsImportData() )
+ pDestObj->InvalidateSource();
+
+ pDestObj->InvalidateData(); // before getting the new output area
+
+ // make sure the table has a name (not set by dialog)
+ if ( !pDestObj->GetName().Len() )
+ pDestObj->SetName( pDoc->GetDPCollection()->CreateNewName() );
+
+ BOOL bOverflow = FALSE;
+ ScRange aNewOut = pDestObj->GetNewOutputRange( bOverflow );
+
+ //! test for overlap with other data pilot tables
+ if( pOldObj )
+ {
+ const ScSheetSourceDesc* pSheetDesc = pOldObj->GetSheetDesc();
+ if( pSheetDesc && pSheetDesc->aSourceRange.Intersects( aNewOut ) )
+ {
+ ScRange aOldRange = pOldObj->GetOutRange();
+ SCsROW nDiff = aOldRange.aStart.Row()-aNewOut.aStart.Row();
+ aNewOut.aStart.SetRow( aOldRange.aStart.Row() );
+ aNewOut.aEnd.SetRow( aNewOut.aEnd.Row()+nDiff );
+ if( !ValidRow( aNewOut.aStart.Row() ) || !ValidRow( aNewOut.aEnd.Row() ) )
+ bOverflow = TRUE;
+ }
+ }
+
+ if ( bOverflow )
+ {
+ // like with STR_PROTECTIONERR, use undo to reverse everything
+ DBG_ASSERT( bRecord, "DataPilotUpdate: can't undo" );
+ bUndoSelf = TRUE;
+ nErrId = STR_PIVOT_ERROR;
+ }
+ else
+ {
+ ScEditableTester aTester( pDoc, aNewOut );
+ if ( !aTester.IsEditable() )
+ {
+ // destination area isn't editable
+ //! reverse everything done so far, don't proceed
+
+ // quick solution: proceed to end, use undo action
+ // to reverse everything:
+ DBG_ASSERT( bRecord, "DataPilotUpdate: can't undo" );
+ bUndoSelf = TRUE;
+ nErrId = aTester.GetMessageId();
+ }
+ }
+
+ // test if new output area is empty except for old area
+ if ( !bApi )
+ {
+ BOOL bEmpty;
+ if ( pOldObj ) // OutRange of pOldObj (pDestObj) is still old area
+ bEmpty = lcl_EmptyExcept( pDoc, aNewOut, pOldObj->GetOutRange() );
+ else
+ bEmpty = pDoc->IsBlockEmpty( aNewOut.aStart.Tab(),
+ aNewOut.aStart.Col(), aNewOut.aStart.Row(),
+ aNewOut.aEnd.Col(), aNewOut.aEnd.Row() );
+
+ if ( !bEmpty )
+ {
+ QueryBox aBox( rDocShell.GetActiveDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES),
+ ScGlobal::GetRscString(STR_PIVOT_NOTEMPTY) );
+ if (aBox.Execute() == RET_NO)
+ {
+ //! like above (not editable), use undo to reverse everything
+ DBG_ASSERT( bRecord, "DataPilotUpdate: can't undo" );
+ bUndoSelf = TRUE;
+ }
+ }
+ }
+
+ if ( bRecord )
+ {
+ SCTAB nTab = aNewOut.aStart.Tab();
+ pNewUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pNewUndoDoc->InitUndo( pDoc, nTab, nTab );
+ pDoc->CopyToDocument( aNewOut, IDF_ALL, FALSE, pNewUndoDoc );
+ }
+
+ pDestObj->Output( aNewOut.aStart );
+
+ rDocShell.PostPaintGridAll(); //! only necessary parts
+ bDone = TRUE;
+ }
+ }
+ // else nothing (no old, no new)
+ }
+
+ if ( bRecord && bDone )
+ {
+ SfxUndoAction* pAction = new ScUndoDataPilot( &rDocShell,
+ pOldUndoDoc, pNewUndoDoc, pUndoDPObj, pDestObj, bAllowMove );
+ pOldUndoDoc = NULL;
+ pNewUndoDoc = NULL; // pointers are used in undo action
+ // pUndoDPObj is copied
+
+ if (bUndoSelf)
+ {
+ // use undo action to restore original state
+ //! prevent setting the document modified? (ScDocShellModificator)
+
+ pAction->Undo();
+ delete pAction;
+ bDone = FALSE;
+ }
+ else
+ rDocShell.GetUndoManager()->AddUndoAction( pAction );
+ }
+
+ delete pOldUndoDoc; // if not used for undo
+ delete pNewUndoDoc;
+ delete pUndoDPObj;
+
+ if (bDone)
+ aModificator.SetDocumentModified();
+
+ if ( nErrId && !bApi )
+ rDocShell.ErrorMessage( nErrId );
+
+ return bDone;
+}
+
+//==================================================================
+//
+// Datenbank-Import...
+
+void ScDBDocFunc::UpdateImport( const String& rTarget, const String& rDBName,
+ const String& rTableName, const String& rStatement, BOOL bNative,
+ BYTE nType, const ::com::sun::star::uno::Reference<
+ ::com::sun::star::sdbc::XResultSet >& xResultSet,
+ const SbaSelectionList* pSelection )
+{
+ // Target ist jetzt einfach der Bereichsname
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ ScDBCollection& rDBColl = *pDoc->GetDBCollection();
+ ScDBData* pData = NULL;
+ ScImportParam aImportParam;
+ BOOL bFound = FALSE;
+ USHORT nCount = rDBColl.GetCount();
+ for (USHORT i=0; i<nCount && !bFound; i++)
+ {
+ pData = rDBColl[i];
+ if (pData->GetName() == rTarget)
+ bFound = TRUE;
+ }
+ if (!bFound)
+ {
+ InfoBox aInfoBox(rDocShell.GetActiveDialogParent(),
+ ScGlobal::GetRscString( STR_TARGETNOTFOUND ) );
+ aInfoBox.Execute();
+ return;
+ }
+
+ SCTAB nTab;
+ SCCOL nDummyCol;
+ SCROW nDummyRow;
+ pData->GetArea( nTab, nDummyCol,nDummyRow,nDummyCol,nDummyRow );
+ pData->GetImportParam( aImportParam );
+
+ BOOL bSql = ( rStatement.Len() != 0 );
+
+ aImportParam.aDBName = rDBName;
+ aImportParam.bSql = bSql;
+ aImportParam.aStatement = bSql ? rStatement : rTableName;
+ aImportParam.bNative = bNative;
+ aImportParam.nType = nType;
+ aImportParam.bImport = TRUE;
+ BOOL bContinue = DoImport( nTab, aImportParam, xResultSet, pSelection, TRUE );
+
+ // DB-Operationen wiederholen
+
+ ScTabViewShell* pViewSh = rDocShell.GetBestViewShell();
+ if (pViewSh)
+ {
+ ScRange aRange;
+ pData->GetArea(aRange);
+ pViewSh->MarkRange(aRange); // selektieren
+
+ if ( bContinue ) // #41905# Fehler beim Import -> Abbruch
+ {
+ // interne Operationen, wenn welche gespeichert
+
+ if ( pData->HasQueryParam() || pData->HasSortParam() || pData->HasSubTotalParam() )
+ pViewSh->RepeatDB();
+
+ // Pivottabellen die den Bereich als Quelldaten haben
+
+ rDocShell.RefreshPivotTables(aRange);
+ }
+ }
+}
+
+
+
+
diff --git a/sc/source/ui/docshell/dbdocimp.cxx b/sc/source/ui/docshell/dbdocimp.cxx
new file mode 100644
index 000000000000..17b07099a491
--- /dev/null
+++ b/sc/source/ui/docshell/dbdocimp.cxx
@@ -0,0 +1,720 @@
+/*************************************************************************
+ *
+ * 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 <comphelper/processfactory.hxx>
+#include <comphelper/types.hxx>
+#include <vcl/msgbox.hxx>
+#include <tools/debug.hxx>
+#include <svx/dataaccessdescriptor.hxx>
+#include <sfx2/viewfrm.hxx>
+
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdb/XCompletedExecution.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XRowSet.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/frame/XDispatchProvider.hpp>
+#include <com/sun/star/frame/FrameSearchFlag.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+
+
+#include "dbdocfun.hxx"
+#include "docsh.hxx"
+#include "globstr.hrc"
+#include "scerrors.hxx"
+#include "dbcolect.hxx"
+#include "markdata.hxx"
+#include "undodat.hxx"
+#include "progress.hxx"
+#include "patattr.hxx"
+#include "docpool.hxx"
+#include "attrib.hxx"
+#include "dbdocutl.hxx"
+#include "editable.hxx"
+#include "hints.hxx"
+
+using namespace com::sun::star;
+
+#define SC_SERVICE_ROWSET "com.sun.star.sdb.RowSet"
+#define SC_SERVICE_INTHANDLER "com.sun.star.sdb.InteractionHandler"
+
+//! move to a header file?
+#define SC_DBPROP_DATASOURCENAME "DataSourceName"
+#define SC_DBPROP_COMMAND "Command"
+#define SC_DBPROP_COMMANDTYPE "CommandType"
+#define SC_DBPROP_SELECTION "Selection"
+#define SC_DBPROP_CURSOR "Cursor"
+
+// static
+void ScDBDocFunc::ShowInBeamer( const ScImportParam& rParam, SfxViewFrame* pFrame )
+{
+ // called after opening the database beamer
+
+ if ( !pFrame || !rParam.bImport )
+ return;
+
+ uno::Reference<frame::XFrame> xFrame = pFrame->GetFrame()->GetFrameInterface();
+ uno::Reference<frame::XDispatchProvider> xDP(xFrame, uno::UNO_QUERY);
+
+ uno::Reference<frame::XFrame> xBeamerFrame = xFrame->findFrame(
+ rtl::OUString::createFromAscii("_beamer"),
+ frame::FrameSearchFlag::CHILDREN);
+ if (xBeamerFrame.is())
+ {
+ uno::Reference<frame::XController> xController = xBeamerFrame->getController();
+ uno::Reference<view::XSelectionSupplier> xControllerSelection(xController, uno::UNO_QUERY);
+ if (xControllerSelection.is())
+ {
+ sal_Int32 nType = rParam.bSql ? sdb::CommandType::COMMAND :
+ ( (rParam.nType == ScDbQuery) ? sdb::CommandType::QUERY :
+ sdb::CommandType::TABLE );
+
+ ::svx::ODataAccessDescriptor aSelection;
+ aSelection.setDataSource(rtl::OUString( rParam.aDBName ));
+ aSelection[svx::daCommand] <<= rtl::OUString( rParam.aStatement );
+ aSelection[svx::daCommandType] <<= nType;
+
+ xControllerSelection->select(uno::makeAny(aSelection.createPropertyValueSequence()));
+ }
+ else
+ {
+ DBG_ERROR("no selection supplier in the beamer!");
+ }
+ }
+}
+
+// -----------------------------------------------------------------
+
+BOOL ScDBDocFunc::DoImportUno( const ScAddress& rPos,
+ const uno::Sequence<beans::PropertyValue>& aArgs )
+{
+ BOOL bDone = FALSE;
+
+ ScImportParam aImParam;
+ aImParam.nCol1 = aImParam.nCol2 = rPos.Col();
+ aImParam.nRow1 = aImParam.nRow2 = rPos.Row();
+ aImParam.bImport = TRUE;
+
+ uno::Reference<sdbc::XResultSet> xResSet;
+ uno::Sequence<uno::Any> aSelection;
+
+ rtl::OUString aStrVal;
+ const beans::PropertyValue* pPropArray = aArgs.getConstArray();
+ long nPropCount = aArgs.getLength();
+ long i;
+ for (i = 0; i < nPropCount; i++)
+ {
+ const beans::PropertyValue& rProp = pPropArray[i];
+ String aPropName = rProp.Name;
+
+ if ( aPropName.EqualsAscii( SC_DBPROP_DATASOURCENAME ))
+ {
+ if ( rProp.Value >>= aStrVal )
+ aImParam.aDBName = aStrVal;
+ }
+ else if ( aPropName.EqualsAscii( SC_DBPROP_COMMAND ))
+ {
+ if ( rProp.Value >>= aStrVal )
+ aImParam.aStatement = aStrVal;
+ }
+ else if ( aPropName.EqualsAscii( SC_DBPROP_COMMANDTYPE ))
+ {
+ sal_Int32 nType = 0;
+ if ( rProp.Value >>= nType )
+ {
+ aImParam.bSql = ( nType == sdb::CommandType::COMMAND );
+ aImParam.nType = sal::static_int_cast<BYTE>( ( nType == sdb::CommandType::QUERY ) ? ScDbQuery : ScDbTable );
+ // nType is ignored if bSql is set
+ }
+ }
+ else if ( aPropName.EqualsAscii( SC_DBPROP_SELECTION ))
+ {
+ rProp.Value >>= aSelection;
+ }
+ else if ( aPropName.EqualsAscii( SC_DBPROP_CURSOR ))
+ {
+ rProp.Value >>= xResSet;
+ }
+ }
+
+ SbaSelectionList aList;
+ long nSelLen = aSelection.getLength();
+ for (i = 0; i < nSelLen; i++)
+ {
+ sal_Int32 nEntry = 0;
+ if ( aSelection[i] >>= nEntry )
+ aList.Insert( (void*)nEntry, LIST_APPEND );
+ }
+
+ BOOL bAddrInsert = FALSE; //!???
+ if ( bAddrInsert )
+ {
+ bDone = DoImport( rPos.Tab(), aImParam, xResSet, &aList, TRUE, bAddrInsert );
+ }
+ else
+ {
+ // create database range
+ //! merge this with SID_SBA_IMPORT execute in docsh4.cxx
+
+ ScDBData* pDBData = rDocShell.GetDBData( ScRange(rPos), SC_DB_IMPORT, FALSE );
+ DBG_ASSERT(pDBData, "can't create DB data");
+ String sTarget = pDBData->GetName();
+
+ //! change UpdateImport to use only one of rTableName, rStatement
+
+ String aTableName, aStatement;
+ if ( aImParam.bSql )
+ aStatement = aImParam.aStatement;
+ else
+ aTableName = aImParam.aStatement;
+
+ UpdateImport( sTarget, aImParam.aDBName, aTableName, aStatement,
+ aImParam.bNative, aImParam.nType, xResSet, &aList );
+ bDone = TRUE;
+ }
+
+ return bDone;
+}
+
+// -----------------------------------------------------------------
+
+BOOL ScDBDocFunc::DoImport( SCTAB nTab, const ScImportParam& rParam,
+ const uno::Reference< sdbc::XResultSet >& xResultSet,
+ const SbaSelectionList* pSelection, BOOL bRecord, BOOL bAddrInsert )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+
+ ScDBData* pDBData = 0;
+ if ( !bAddrInsert )
+ {
+ pDBData = pDoc->GetDBAtArea( nTab, rParam.nCol1, rParam.nRow1,
+ rParam.nCol2, rParam.nRow2 );
+ if (!pDBData)
+ {
+ DBG_ERROR( "DoImport: no DBData" );
+ return FALSE;
+ }
+ }
+
+ Window* pWaitWin = rDocShell.GetActiveDialogParent();
+ if (pWaitWin)
+ pWaitWin->EnterWait();
+ ScDocShellModificator aModificator( rDocShell );
+
+ BOOL bSuccess = FALSE;
+ BOOL bApi = FALSE; //! pass as argument
+ BOOL bTruncated = FALSE; // for warning
+ USHORT nErrStringId = 0;
+ String aErrorMessage;
+
+ SCCOL nCol = rParam.nCol1;
+ SCROW nRow = rParam.nRow1;
+ SCCOL nEndCol = nCol; // end of resulting database area
+ SCROW nEndRow = nRow;
+ long i;
+
+ BOOL bDoSelection = FALSE;
+ BOOL bRealSelection = FALSE; // TRUE if not everything is selected
+ ULONG nListPos = 0;
+ ULONG nRowsRead = 0;
+ ULONG nListCount = 0;
+
+ // -1 is special
+ if ( pSelection && pSelection->Count() && (long)pSelection->GetObject(0) != -1L )
+ {
+ bDoSelection = TRUE;
+ nListCount = pSelection->Count();
+ }
+
+ // ImportDoc - also used for Redo
+ ScDocument* pImportDoc = new ScDocument( SCDOCMODE_UNDO );
+ pImportDoc->InitUndo( pDoc, nTab, nTab );
+ ScColumn::bDoubleAlloc = TRUE;
+
+ //
+ // get data from database into import document
+ //
+
+ try
+ {
+ // progress bar
+ // only text (title is still needed, for the cancel button)
+ ScProgress aProgress( &rDocShell, ScGlobal::GetRscString(STR_UNDO_IMPORTDATA), 0 );
+ USHORT nInserted = 0;
+
+ uno::Reference<sdbc::XRowSet> xRowSet = uno::Reference<sdbc::XRowSet>(
+ xResultSet, uno::UNO_QUERY );
+ sal_Bool bDispose = sal_False;
+ if ( !xRowSet.is() )
+ {
+ bDispose = sal_True;
+ xRowSet = uno::Reference<sdbc::XRowSet>(
+ comphelper::getProcessServiceFactory()->createInstance(
+ rtl::OUString::createFromAscii( SC_SERVICE_ROWSET ) ),
+ uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xRowProp( xRowSet, uno::UNO_QUERY );
+ DBG_ASSERT( xRowProp.is(), "can't get RowSet" );
+ if ( xRowProp.is() )
+ {
+ //
+ // set source parameters
+ //
+
+ sal_Int32 nType = rParam.bSql ? sdb::CommandType::COMMAND :
+ ( (rParam.nType == ScDbQuery) ? sdb::CommandType::QUERY :
+ sdb::CommandType::TABLE );
+ uno::Any aAny;
+
+ aAny <<= rtl::OUString( rParam.aDBName );
+ xRowProp->setPropertyValue(
+ rtl::OUString::createFromAscii(SC_DBPROP_DATASOURCENAME), aAny );
+
+ aAny <<= rtl::OUString( rParam.aStatement );
+ xRowProp->setPropertyValue(
+ rtl::OUString::createFromAscii(SC_DBPROP_COMMAND), aAny );
+
+ aAny <<= nType;
+ xRowProp->setPropertyValue(
+ rtl::OUString::createFromAscii(SC_DBPROP_COMMANDTYPE), aAny );
+
+ uno::Reference<sdb::XCompletedExecution> xExecute( xRowSet, uno::UNO_QUERY );
+ if ( xExecute.is() )
+ {
+ uno::Reference<task::XInteractionHandler> xHandler(
+ comphelper::getProcessServiceFactory()->createInstance(
+ rtl::OUString::createFromAscii( SC_SERVICE_INTHANDLER ) ),
+ uno::UNO_QUERY);
+ xExecute->executeWithCompletion( xHandler );
+ }
+ else
+ xRowSet->execute();
+ }
+ }
+ if ( xRowSet.is() )
+ {
+ //
+ // get column descriptions
+ //
+
+ long nColCount = 0;
+ uno::Reference<sdbc::XResultSetMetaData> xMeta;
+ uno::Reference<sdbc::XResultSetMetaDataSupplier> xMetaSupp( xRowSet, uno::UNO_QUERY );
+ if ( xMetaSupp.is() )
+ xMeta = xMetaSupp->getMetaData();
+ if ( xMeta.is() )
+ nColCount = xMeta->getColumnCount(); // this is the number of real columns
+
+ if ( rParam.nCol1 + nColCount - 1 > MAXCOL )
+ {
+ nColCount = 0;
+ //! error message
+ }
+
+ uno::Reference<sdbc::XRow> xRow( xRowSet, uno::UNO_QUERY );
+ if ( nColCount > 0 && xRow.is() )
+ {
+ nEndCol = (SCCOL)( rParam.nCol1 + nColCount - 1 );
+
+ uno::Sequence<sal_Int32> aColTypes( nColCount ); // column types
+ uno::Sequence<sal_Bool> aColCurr( nColCount ); // currency flag is not in types
+ sal_Int32* pTypeArr = aColTypes.getArray();
+ sal_Bool* pCurrArr = aColCurr.getArray();
+ for (i=0; i<nColCount; i++)
+ {
+ pTypeArr[i] = xMeta->getColumnType( i+1 );
+ pCurrArr[i] = xMeta->isCurrency( i+1 );
+ }
+
+ if ( !bAddrInsert ) // read column names
+ {
+ nCol = rParam.nCol1;
+ for (i=0; i<nColCount; i++)
+ {
+ pImportDoc->SetString( nCol, nRow, nTab,
+ xMeta->getColumnLabel( i+1 ) );
+ ++nCol;
+ }
+ ++nRow;
+ }
+
+ BOOL bEnd = FALSE;
+ if ( !bDoSelection )
+ xRowSet->beforeFirst();
+ while ( !bEnd )
+ {
+ // skip rows that are not selected
+ if ( !bDoSelection )
+ {
+ if ( (bEnd = !xRowSet->next()) == FALSE )
+ ++nRowsRead;
+ }
+ else
+ {
+ if (nListPos < nListCount)
+ {
+ ULONG nNextRow = (ULONG) pSelection->GetObject(nListPos);
+ if ( nRowsRead+1 < nNextRow )
+ bRealSelection = TRUE;
+ bEnd = !xRowSet->absolute(nRowsRead = nNextRow);
+ ++nListPos;
+ }
+ else
+ {
+ bRealSelection = xRowSet->next();
+ bEnd = TRUE; // more data available but not used
+ }
+ }
+
+ if ( !bEnd )
+ {
+ if ( ValidRow(nRow) )
+ {
+ nCol = rParam.nCol1;
+ for (i=0; i<nColCount; i++)
+ {
+ ScDatabaseDocUtil::PutData( pImportDoc, nCol, nRow, nTab,
+ xRow, i+1, pTypeArr[i], pCurrArr[i] );
+ ++nCol;
+ }
+ nEndRow = nRow;
+ ++nRow;
+
+ // progress bar
+
+ ++nInserted;
+ if (!(nInserted & 15))
+ {
+ String aPict = ScGlobal::GetRscString( STR_PROGRESS_IMPORT );
+ String aText = aPict.GetToken(0,'#');
+ aText += String::CreateFromInt32( nInserted );
+ aText += aPict.GetToken(1,'#');
+
+ if (!aProgress.SetStateText( 0, aText )) // stopped by user?
+ {
+ bEnd = TRUE;
+ bSuccess = FALSE;
+ nErrStringId = STR_DATABASE_ABORTED;
+ }
+ }
+ }
+ else // past the end of the spreadsheet
+ {
+ bEnd = TRUE; // don't continue
+ bTruncated = TRUE; // warning flag
+ }
+ }
+ }
+
+ bSuccess = TRUE;
+ }
+
+ if ( bDispose )
+ ::comphelper::disposeComponent( xRowSet );
+ }
+ }
+ catch ( sdbc::SQLException& rError )
+ {
+ aErrorMessage = rError.Message;
+ }
+ catch ( uno::Exception& )
+ {
+ DBG_ERROR("Unexpected exception in database");
+ }
+
+ ScColumn::bDoubleAlloc = FALSE;
+ pImportDoc->DoColResize( nTab, rParam.nCol1,nEndCol, 0 );
+
+ //
+ // test for cell protection
+ //
+
+ BOOL bKeepFormat = !bAddrInsert && pDBData->IsKeepFmt();
+ BOOL bMoveCells = !bAddrInsert && pDBData->IsDoSize();
+ SCCOL nFormulaCols = 0; // columns to be filled with formulas
+ if (bMoveCells && nEndCol == rParam.nCol2)
+ {
+ // if column count changes, formulas would become invalid anyway
+ // -> only set nFormulaCols for unchanged column count
+
+ SCCOL nTestCol = rParam.nCol2 + 1; // right of the data
+ SCROW nTestRow = rParam.nRow1 + 1; // below the title row
+ while ( nTestCol <= MAXCOL &&
+ pDoc->GetCellType(ScAddress( nTestCol, nTestRow, nTab )) == CELLTYPE_FORMULA )
+ ++nTestCol, ++nFormulaCols;
+ }
+
+ if (bSuccess)
+ {
+ // old and new range editable?
+ ScEditableTester aTester;
+ aTester.TestBlock( pDoc, nTab, rParam.nCol1,rParam.nRow1,rParam.nCol2,rParam.nRow2 );
+ aTester.TestBlock( pDoc, nTab, rParam.nCol1,rParam.nRow1,nEndCol,nEndRow );
+ if ( !aTester.IsEditable() )
+ {
+ nErrStringId = aTester.GetMessageId();
+ bSuccess = FALSE;
+ }
+ else if ( pDoc->GetChangeTrack() != NULL )
+ {
+ nErrStringId = STR_PROTECTIONERR;
+ bSuccess = FALSE;
+ }
+ }
+
+ if ( bSuccess && bMoveCells )
+ {
+ ScRange aOld( rParam.nCol1, rParam.nRow1, nTab,
+ rParam.nCol2+nFormulaCols, rParam.nRow2, nTab );
+ ScRange aNew( rParam.nCol1, rParam.nRow1, nTab,
+ nEndCol+nFormulaCols, nEndRow, nTab );
+ if (!pDoc->CanFitBlock( aOld, aNew ))
+ {
+ nErrStringId = STR_MSSG_DOSUBTOTALS_2; // can't insert cells
+ bSuccess = FALSE;
+ }
+ }
+
+ //
+ // copy data from import doc into real document
+ //
+
+ if ( bSuccess )
+ {
+ if (bKeepFormat)
+ {
+ // keep formatting of title and first data row from the document
+ // CopyToDocument also copies styles, Apply... needs separate calls
+
+ SCCOL nMinEndCol = Min( rParam.nCol2, nEndCol ); // not too much
+ nMinEndCol = sal::static_int_cast<SCCOL>( nMinEndCol + nFormulaCols ); // only if column count unchanged
+ pImportDoc->DeleteAreaTab( 0,0, MAXCOL,MAXROW, nTab, IDF_ATTRIB );
+ pDoc->CopyToDocument( rParam.nCol1, rParam.nRow1, nTab,
+ nMinEndCol, rParam.nRow1, nTab,
+ IDF_ATTRIB, FALSE, pImportDoc );
+
+ SCROW nDataStartRow = rParam.nRow1+1;
+ for (SCCOL nCopyCol=rParam.nCol1; nCopyCol<=nMinEndCol; nCopyCol++)
+ {
+ const ScPatternAttr* pSrcPattern = pDoc->GetPattern(
+ nCopyCol, nDataStartRow, nTab );
+ pImportDoc->ApplyPatternAreaTab( nCopyCol, nDataStartRow, nCopyCol, nEndRow,
+ nTab, *pSrcPattern );
+ const ScStyleSheet* pStyle = pSrcPattern->GetStyleSheet();
+ if (pStyle)
+ pImportDoc->ApplyStyleAreaTab( nCopyCol, nDataStartRow, nCopyCol, nEndRow,
+ nTab, *pStyle );
+ }
+ }
+
+ // don't set cell protection attribute if table is protected
+ if (pDoc->IsTabProtected(nTab))
+ {
+ ScPatternAttr aPattern(pImportDoc->GetPool());
+ aPattern.GetItemSet().Put( ScProtectionAttr( FALSE,FALSE,FALSE,FALSE ) );
+ pImportDoc->ApplyPatternAreaTab( 0,0,MAXCOL,MAXROW, nTab, aPattern );
+ }
+
+ //
+ // copy old data for undo
+ //
+
+ SCCOL nUndoEndCol = Max( nEndCol, rParam.nCol2 ); // rParam = old end
+ SCROW nUndoEndRow = Max( nEndRow, rParam.nRow2 );
+
+ ScDocument* pUndoDoc = NULL;
+ ScDBData* pUndoDBData = NULL;
+ if ( bRecord )
+ {
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nTab, nTab );
+
+ if ( !bAddrInsert )
+ pUndoDBData = new ScDBData( *pDBData );
+ }
+
+ ScMarkData aNewMark;
+ aNewMark.SelectOneTable( nTab );
+
+ if (bRecord)
+ {
+ // do not touch notes (ScUndoImportData does not support drawing undo)
+ sal_uInt16 nCopyFlags = IDF_ALL & ~IDF_NOTE;
+
+ // nFormulaCols is set only if column count is unchanged
+ pDoc->CopyToDocument( rParam.nCol1, rParam.nRow1, nTab,
+ nEndCol+nFormulaCols, nEndRow, nTab,
+ nCopyFlags, FALSE, pUndoDoc );
+ if ( rParam.nCol2 > nEndCol )
+ pDoc->CopyToDocument( nEndCol+1, rParam.nRow1, nTab,
+ nUndoEndCol, nUndoEndRow, nTab,
+ nCopyFlags, FALSE, pUndoDoc );
+ if ( rParam.nRow2 > nEndRow )
+ pDoc->CopyToDocument( rParam.nCol1, nEndRow+1, nTab,
+ nUndoEndCol+nFormulaCols, nUndoEndRow, nTab,
+ nCopyFlags, FALSE, pUndoDoc );
+ }
+
+ //
+ // move new data
+ //
+
+ if (bMoveCells)
+ {
+ // clear only the range without the formulas,
+ // so the formula title and first row are preserved
+
+ ScRange aDelRange( rParam.nCol1, rParam.nRow1, nTab,
+ rParam.nCol2, rParam.nRow2, nTab );
+ pDoc->DeleteAreaTab( aDelRange, IDF_ALL & ~IDF_NOTE ); // ohne die Formeln
+
+ ScRange aOld( rParam.nCol1, rParam.nRow1, nTab,
+ rParam.nCol2+nFormulaCols, rParam.nRow2, nTab );
+ ScRange aNew( rParam.nCol1, rParam.nRow1, nTab,
+ nEndCol+nFormulaCols, nEndRow, nTab );
+ pDoc->FitBlock( aOld, aNew, FALSE ); // Formeln nicht loeschen
+ }
+ else if ( nEndCol < rParam.nCol2 ) // DeleteArea calls PutInOrder
+ pDoc->DeleteArea( nEndCol+1, rParam.nRow1, rParam.nCol2, rParam.nRow2,
+ aNewMark, IDF_CONTENTS & ~IDF_NOTE );
+
+ // CopyToDocument doesn't remove contents
+ pDoc->DeleteAreaTab( rParam.nCol1, rParam.nRow1, nEndCol, nEndRow, nTab, IDF_CONTENTS & ~IDF_NOTE );
+
+ // #41216# remove each column from ImportDoc after copying to reduce memory usage
+ BOOL bOldAutoCalc = pDoc->GetAutoCalc();
+ pDoc->SetAutoCalc( FALSE ); // outside of the loop
+ for (SCCOL nCopyCol = rParam.nCol1; nCopyCol <= nEndCol; nCopyCol++)
+ {
+ pImportDoc->CopyToDocument( nCopyCol, rParam.nRow1, nTab, nCopyCol, nEndRow, nTab,
+ IDF_ALL, FALSE, pDoc );
+ pImportDoc->DeleteAreaTab( nCopyCol, rParam.nRow1, nCopyCol, nEndRow, nTab, IDF_CONTENTS );
+ pImportDoc->DoColResize( nTab, nCopyCol, nCopyCol, 0 );
+ }
+ pDoc->SetAutoCalc( bOldAutoCalc );
+
+ if (nFormulaCols > 0) // copy formulas
+ {
+ if (bKeepFormat) // formats for formulas
+ pImportDoc->CopyToDocument( nEndCol+1, rParam.nRow1, nTab,
+ nEndCol+nFormulaCols, nEndRow, nTab,
+ IDF_ATTRIB, FALSE, pDoc );
+ // fill formulas
+ ScMarkData aMark;
+ aMark.SelectOneTable(nTab);
+ pDoc->Fill( nEndCol+1, rParam.nRow1+1, nEndCol+nFormulaCols, rParam.nRow1+1,
+ aMark, nEndRow-rParam.nRow1-1, FILL_TO_BOTTOM, FILL_SIMPLE );
+ }
+
+ // if new range is smaller, clear old contents
+
+ if (!bMoveCells) // move has happened above
+ {
+ if ( rParam.nCol2 > nEndCol )
+ pDoc->DeleteArea( nEndCol+1, rParam.nRow1, rParam.nCol2, rParam.nRow2,
+ aNewMark, IDF_CONTENTS );
+ if ( rParam.nRow2 > nEndRow )
+ pDoc->DeleteArea( rParam.nCol1, nEndRow+1, rParam.nCol2, rParam.nRow2,
+ aNewMark, IDF_CONTENTS );
+ }
+
+ if( !bAddrInsert ) // update database range
+ {
+ pDBData->SetImportParam( rParam );
+ pDBData->SetHeader( TRUE );
+ pDBData->SetByRow( TRUE );
+ pDBData->SetArea( nTab, rParam.nCol1,rParam.nRow1, nEndCol,nEndRow );
+ pDBData->SetImportSelection( bRealSelection );
+ pDoc->CompileDBFormula();
+ }
+
+ if (bRecord)
+ {
+ ScDocument* pRedoDoc = pImportDoc;
+ pImportDoc = NULL;
+
+ if (nFormulaCols > 0) // include filled formulas for redo
+ pDoc->CopyToDocument( rParam.nCol1, rParam.nRow1, nTab,
+ nEndCol+nFormulaCols, nEndRow, nTab,
+ IDF_ALL & ~IDF_NOTE, FALSE, pRedoDoc );
+
+ ScDBData* pRedoDBData = pDBData ? new ScDBData( *pDBData ) : NULL;
+
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoImportData( &rDocShell, nTab,
+ rParam, nUndoEndCol, nUndoEndRow,
+ nFormulaCols,
+ pUndoDoc, pRedoDoc, pUndoDBData, pRedoDBData ) );
+ }
+
+ pDoc->SetDirty();
+ rDocShell.PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID );
+ aModificator.SetDocumentModified();
+
+ ScDBRangeRefreshedHint aHint( rParam );
+ pDoc->BroadcastUno( aHint );
+
+ if (pWaitWin)
+ pWaitWin->LeaveWait();
+
+ if ( bTruncated && !bApi ) // show warning
+ ErrorHandler::HandleError(SCWARN_IMPORT_RANGE_OVERFLOW);
+ }
+ else if ( !bApi )
+ {
+ if (pWaitWin)
+ pWaitWin->LeaveWait();
+
+ if (!aErrorMessage.Len())
+ {
+ if (!nErrStringId)
+ nErrStringId = STR_MSSG_IMPORTDATA_0;
+ aErrorMessage = ScGlobal::GetRscString( nErrStringId );
+ }
+ InfoBox aInfoBox( rDocShell.GetActiveDialogParent(), aErrorMessage );
+ aInfoBox.Execute();
+ }
+
+ delete pImportDoc;
+
+ return bSuccess;
+}
+
+
+
+
diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx
new file mode 100644
index 000000000000..cd28daa99401
--- /dev/null
+++ b/sc/source/ui/docshell/docfunc.cxx
@@ -0,0 +1,4630 @@
+/*************************************************************************
+ *
+ * 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 "scitems.hxx"
+#include <editeng/eeitem.hxx>
+
+#include <sfx2/app.hxx>
+#include <editeng/editobj.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <svx/svdundo.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/printer.hxx>
+#include <vcl/msgbox.hxx>
+#include <vcl/sound.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/waitobj.hxx>
+#include <svl/zforlist.hxx>
+#include <svl/PasswordHelper.hxx>
+
+#include <list>
+
+#include "docfunc.hxx"
+
+#include "sc.hrc"
+
+#include "arealink.hxx"
+#include "attrib.hxx"
+#include "dociter.hxx"
+#include "autoform.hxx"
+#include "cell.hxx"
+#include "detdata.hxx"
+#include "detfunc.hxx"
+#include "docpool.hxx"
+#include "docsh.hxx"
+#include "drwlayer.hxx"
+#include "editutil.hxx"
+#include "globstr.hrc"
+//CHINA001 #include "namecrea.hxx" // NAME_TOP etc.
+#include "olinetab.hxx"
+#include "patattr.hxx"
+#include "rangenam.hxx"
+#include "rangeutl.hxx"
+#include "refundo.hxx"
+#include "scresid.hxx"
+#include "stlpool.hxx"
+#include "stlsheet.hxx"
+#include "tablink.hxx"
+#include "tabvwsh.hxx"
+#include "uiitems.hxx"
+#include "undoblk.hxx"
+#include "undocell.hxx"
+#include "undodraw.hxx"
+#include "undotab.hxx"
+#include "waitoff.hxx"
+#include "sizedev.hxx"
+#include "scmod.hxx"
+#include "inputhdl.hxx"
+#include "inputwin.hxx"
+#include "editable.hxx"
+#include "compiler.hxx"
+#include "scui_def.hxx" //CHINA001
+#include "tabprotection.hxx"
+#include "clipparam.hxx"
+
+#include <memory>
+
+using namespace com::sun::star;
+using ::com::sun::star::uno::Sequence;
+
+// STATIC DATA -----------------------------------------------------------
+
+//========================================================================
+
+IMPL_LINK( ScDocFunc, NotifyDrawUndo, SdrUndoAction*, pUndoAction )
+{
+ // #i101118# if drawing layer collects the undo actions, add it there
+ ScDrawLayer* pDrawLayer = rDocShell.GetDocument()->GetDrawLayer();
+ if( pDrawLayer && pDrawLayer->IsRecording() )
+ pDrawLayer->AddCalcUndo( pUndoAction );
+ else
+ rDocShell.GetUndoManager()->AddUndoAction( new ScUndoDraw( pUndoAction, &rDocShell ) );
+ rDocShell.SetDrawModified();
+
+ // the affected sheet isn't known, so all stream positions are invalidated
+ ScDocument* pDoc = rDocShell.GetDocument();
+ SCTAB nTabCount = pDoc->GetTableCount();
+ for (SCTAB nTab=0; nTab<nTabCount; nTab++)
+ if (pDoc->IsStreamValid(nTab))
+ pDoc->SetStreamValid(nTab, FALSE);
+
+ return 0;
+}
+
+//------------------------------------------------------------------------
+
+// Zeile ueber dem Range painten (fuer Linien nach AdjustRowHeight)
+
+void lcl_PaintAbove( ScDocShell& rDocShell, const ScRange& rRange )
+{
+ SCROW nRow = rRange.aStart.Row();
+ if ( nRow > 0 )
+ {
+ SCTAB nTab = rRange.aStart.Tab(); //! alle?
+ --nRow;
+ rDocShell.PostPaint( ScRange(0,nRow,nTab, MAXCOL,nRow,nTab), PAINT_GRID );
+ }
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScDocFunc::AdjustRowHeight( const ScRange& rRange, BOOL bPaint )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if ( pDoc->IsImportingXML() )
+ {
+ // for XML import, all row heights are updated together after importing
+ return FALSE;
+ }
+ if ( !pDoc->IsAdjustHeightEnabled() )
+ {
+ return FALSE;
+ }
+
+ SCTAB nTab = rRange.aStart.Tab();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCROW nEndRow = rRange.aEnd.Row();
+
+ ScSizeDeviceProvider aProv( &rDocShell );
+ Fraction aOne(1,1);
+
+ BOOL bChanged = pDoc->SetOptimalHeight( nStartRow, nEndRow, nTab, 0, aProv.GetDevice(),
+ aProv.GetPPTX(), aProv.GetPPTY(), aOne, aOne, FALSE );
+
+ if ( bPaint && bChanged )
+ rDocShell.PostPaint( 0, nStartRow, nTab, MAXCOL, MAXROW, nTab,
+ PAINT_GRID | PAINT_LEFT );
+
+ return bChanged;
+}
+
+
+//------------------------------------------------------------------------
+
+BOOL ScDocFunc::DetectiveAddPred(const ScAddress& rPos)
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ rDocShell.MakeDrawLayer();
+ ScDocument* pDoc = rDocShell.GetDocument();
+ BOOL bUndo (pDoc->IsUndoEnabled());
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ SCCOL nCol = rPos.Col();
+ SCROW nRow = rPos.Row();
+ SCTAB nTab = rPos.Tab();
+
+ if (bUndo)
+ pModel->BeginCalcUndo();
+ BOOL bDone = ScDetectiveFunc( pDoc,nTab ).ShowPred( nCol, nRow );
+ SdrUndoGroup* pUndo = NULL;
+ if (bUndo)
+ pUndo = pModel->GetCalcUndo();
+ if (bDone)
+ {
+ ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDPRED );
+ pDoc->AddDetectiveOperation( aOperation );
+ if (bUndo)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
+ }
+ aModificator.SetDocumentModified();
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+ if (pBindings)
+ pBindings->Invalidate( SID_DETECTIVE_REFRESH );
+ }
+ else
+ delete pUndo;
+
+ return bDone;
+}
+
+BOOL ScDocFunc::DetectiveDelPred(const ScAddress& rPos)
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ BOOL bUndo(pDoc->IsUndoEnabled());
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ if (!pModel)
+ return FALSE;
+
+ ScDocShellModificator aModificator( rDocShell );
+
+ SCCOL nCol = rPos.Col();
+ SCROW nRow = rPos.Row();
+ SCTAB nTab = rPos.Tab();
+
+ if (bUndo)
+ pModel->BeginCalcUndo();
+ BOOL bDone = ScDetectiveFunc( pDoc,nTab ).DeletePred( nCol, nRow );
+ SdrUndoGroup* pUndo = NULL;
+ if (bUndo)
+ pUndo = pModel->GetCalcUndo();
+ if (bDone)
+ {
+ ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_DELPRED );
+ pDoc->AddDetectiveOperation( aOperation );
+ if (bUndo)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
+ }
+ aModificator.SetDocumentModified();
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+ if (pBindings)
+ pBindings->Invalidate( SID_DETECTIVE_REFRESH );
+ }
+ else
+ delete pUndo;
+
+ return bDone;
+}
+
+BOOL ScDocFunc::DetectiveAddSucc(const ScAddress& rPos)
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ rDocShell.MakeDrawLayer();
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ BOOL bUndo(pDoc->IsUndoEnabled());
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ SCCOL nCol = rPos.Col();
+ SCROW nRow = rPos.Row();
+ SCTAB nTab = rPos.Tab();
+
+ if (bUndo)
+ pModel->BeginCalcUndo();
+ BOOL bDone = ScDetectiveFunc( pDoc,nTab ).ShowSucc( nCol, nRow );
+ SdrUndoGroup* pUndo = NULL;
+ if (bUndo)
+ pUndo = pModel->GetCalcUndo();
+ if (bDone)
+ {
+ ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDSUCC );
+ pDoc->AddDetectiveOperation( aOperation );
+ if (bUndo)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
+ }
+ aModificator.SetDocumentModified();
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+ if (pBindings)
+ pBindings->Invalidate( SID_DETECTIVE_REFRESH );
+ }
+ else
+ delete pUndo;
+
+ return bDone;
+}
+
+BOOL ScDocFunc::DetectiveDelSucc(const ScAddress& rPos)
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ BOOL bUndo (pDoc->IsUndoEnabled());
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ if (!pModel)
+ return FALSE;
+
+ ScDocShellModificator aModificator( rDocShell );
+
+ SCCOL nCol = rPos.Col();
+ SCROW nRow = rPos.Row();
+ SCTAB nTab = rPos.Tab();
+
+ if (bUndo)
+ pModel->BeginCalcUndo();
+ BOOL bDone = ScDetectiveFunc( pDoc,nTab ).DeleteSucc( nCol, nRow );
+ SdrUndoGroup* pUndo = NULL;
+ if (bUndo)
+ pUndo = pModel->GetCalcUndo();
+ if (bDone)
+ {
+ ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_DELSUCC );
+ pDoc->AddDetectiveOperation( aOperation );
+ if (bUndo)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
+ }
+ aModificator.SetDocumentModified();
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+ if (pBindings)
+ pBindings->Invalidate( SID_DETECTIVE_REFRESH );
+ }
+ else
+ delete pUndo;
+
+ return bDone;
+}
+
+BOOL ScDocFunc::DetectiveAddError(const ScAddress& rPos)
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ rDocShell.MakeDrawLayer();
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ BOOL bUndo (pDoc->IsUndoEnabled());
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ SCCOL nCol = rPos.Col();
+ SCROW nRow = rPos.Row();
+ SCTAB nTab = rPos.Tab();
+
+ if (bUndo)
+ pModel->BeginCalcUndo();
+ BOOL bDone = ScDetectiveFunc( pDoc,nTab ).ShowError( nCol, nRow );
+ SdrUndoGroup* pUndo = NULL;
+ if (bUndo)
+ pUndo = pModel->GetCalcUndo();
+ if (bDone)
+ {
+ ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDERROR );
+ pDoc->AddDetectiveOperation( aOperation );
+ if (bUndo)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
+ }
+ aModificator.SetDocumentModified();
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+ if (pBindings)
+ pBindings->Invalidate( SID_DETECTIVE_REFRESH );
+ }
+ else
+ delete pUndo;
+
+ return bDone;
+}
+
+BOOL ScDocFunc::DetectiveMarkInvalid(SCTAB nTab)
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ rDocShell.MakeDrawLayer();
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ BOOL bUndo (pDoc->IsUndoEnabled());
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+
+ Window* pWaitWin = rDocShell.GetActiveDialogParent();
+ if (pWaitWin)
+ pWaitWin->EnterWait();
+ if (bUndo)
+ pModel->BeginCalcUndo();
+ BOOL bOverflow;
+ BOOL bDone = ScDetectiveFunc( pDoc,nTab ).MarkInvalid( bOverflow );
+ SdrUndoGroup* pUndo = NULL;
+ if (bUndo)
+ pUndo = pModel->GetCalcUndo();
+ if (pWaitWin)
+ pWaitWin->LeaveWait();
+ if (bDone)
+ {
+ if (pUndo && bUndo)
+ {
+ pUndo->SetComment( ScGlobal::GetRscString( STR_UNDO_DETINVALID ) );
+ rDocShell.GetUndoManager()->AddUndoAction( pUndo );
+ }
+ aModificator.SetDocumentModified();
+ if ( bOverflow )
+ {
+ InfoBox( NULL,
+ ScGlobal::GetRscString( STR_DETINVALID_OVERFLOW ) ).Execute();
+ }
+ }
+ else
+ delete pUndo;
+
+ return bDone;
+}
+
+BOOL ScDocFunc::DetectiveDelAll(SCTAB nTab)
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ BOOL bUndo (pDoc->IsUndoEnabled());
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ if (!pModel)
+ return FALSE;
+
+ ScDocShellModificator aModificator( rDocShell );
+
+ if (bUndo)
+ pModel->BeginCalcUndo();
+ BOOL bDone = ScDetectiveFunc( pDoc,nTab ).DeleteAll( SC_DET_DETECTIVE );
+ SdrUndoGroup* pUndo = NULL;
+ if (bUndo)
+ pUndo = pModel->GetCalcUndo();
+ if (bDone)
+ {
+ ScDetOpList* pOldList = pDoc->GetDetOpList();
+ ScDetOpList* pUndoList = NULL;
+ if (bUndo)
+ pUndoList = pOldList ? new ScDetOpList(*pOldList) : NULL;
+
+ pDoc->ClearDetectiveOperations();
+
+ if (bUndo)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDetective( &rDocShell, pUndo, NULL, pUndoList ) );
+ }
+ aModificator.SetDocumentModified();
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+ if (pBindings)
+ pBindings->Invalidate( SID_DETECTIVE_REFRESH );
+ }
+ else
+ delete pUndo;
+
+ return bDone;
+}
+
+BOOL ScDocFunc::DetectiveRefresh( BOOL bAutomatic )
+{
+ BOOL bDone = FALSE;
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ BOOL bUndo (pDoc->IsUndoEnabled());
+ ScDetOpList* pList = pDoc->GetDetOpList();
+ if ( pList && pList->Count() )
+ {
+ rDocShell.MakeDrawLayer();
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ if (bUndo)
+ pModel->BeginCalcUndo();
+
+ // Loeschen auf allen Tabellen
+
+ SCTAB nTabCount = pDoc->GetTableCount();
+ for (SCTAB nTab=0; nTab<nTabCount; nTab++)
+ ScDetectiveFunc( pDoc,nTab ).DeleteAll( SC_DET_ARROWS ); // don't remove circles
+
+ // Wiederholen
+
+ USHORT nCount = pList->Count();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ ScDetOpData* pData = (*pList)[i];
+ if (pData)
+ {
+ ScAddress aPos = pData->GetPos();
+ ScDetectiveFunc aFunc( pDoc, aPos.Tab() );
+ SCCOL nCol = aPos.Col();
+ SCROW nRow = aPos.Row();
+ switch (pData->GetOperation())
+ {
+ case SCDETOP_ADDSUCC:
+ aFunc.ShowSucc( nCol, nRow );
+ break;
+ case SCDETOP_DELSUCC:
+ aFunc.DeleteSucc( nCol, nRow );
+ break;
+ case SCDETOP_ADDPRED:
+ aFunc.ShowPred( nCol, nRow );
+ break;
+ case SCDETOP_DELPRED:
+ aFunc.DeletePred( nCol, nRow );
+ break;
+ case SCDETOP_ADDERROR:
+ aFunc.ShowError( nCol, nRow );
+ break;
+ default:
+ DBG_ERROR("falsche Op bei DetectiveRefresh");
+ }
+ }
+ }
+
+ if (bUndo)
+ {
+ SdrUndoGroup* pUndo = pModel->GetCalcUndo();
+ if (pUndo)
+ {
+ pUndo->SetComment( ScGlobal::GetRscString( STR_UNDO_DETREFRESH ) );
+ // wenn automatisch, an letzte Aktion anhaengen
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDraw( pUndo, &rDocShell ),
+ bAutomatic );
+ }
+ }
+ rDocShell.SetDrawModified();
+ bDone = TRUE;
+ }
+ return bDone;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScDocFunc::DeleteContents( const ScMarkData& rMark, USHORT nFlags,
+ BOOL bRecord, BOOL bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ if ( !rMark.IsMarked() && !rMark.IsMultiMarked() )
+ {
+ DBG_ERROR("ScDocFunc::DeleteContents ohne Markierung");
+ return FALSE;
+ }
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+
+ ScEditableTester aTester( pDoc, rMark );
+ if (!aTester.IsEditable())
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ return FALSE;
+ }
+
+ ScRange aMarkRange;
+ BOOL bSimple = FALSE;
+
+ ScMarkData aMultiMark = rMark;
+ aMultiMark.SetMarking(FALSE); // fuer MarkToMulti
+
+ ScDocument* pUndoDoc = NULL;
+ BOOL bMulti = !bSimple && aMultiMark.IsMultiMarked();
+ if (!bSimple)
+ {
+ aMultiMark.MarkToMulti();
+ aMultiMark.GetMultiMarkArea( aMarkRange );
+ }
+ ScRange aExtendedRange(aMarkRange);
+ if (!bSimple)
+ {
+ if ( pDoc->ExtendMerge( aExtendedRange, TRUE ) )
+ bMulti = FALSE;
+ }
+
+ // keine Objekte auf geschuetzten Tabellen
+ BOOL bObjects = FALSE;
+ if ( nFlags & IDF_OBJECTS )
+ {
+ bObjects = TRUE;
+ SCTAB nTabCount = pDoc->GetTableCount();
+ for (SCTAB nTab=0; nTab<nTabCount; nTab++)
+ if (aMultiMark.GetTableSelect(nTab) && pDoc->IsTabProtected(nTab))
+ bObjects = FALSE;
+ }
+
+ USHORT nExtFlags = 0; // extra flags are needed only if attributes are deleted
+ if ( nFlags & IDF_ATTRIB )
+ rDocShell.UpdatePaintExt( nExtFlags, aMarkRange );
+
+ // Reihenfolge:
+ // 1) BeginDrawUndo
+ // 2) Objekte loeschen (DrawUndo wird gefuellt)
+ // 3) Inhalte fuer Undo kopieren und Undo-Aktion anlegen
+ // 4) Inhalte loeschen
+
+ bool bDrawUndo = bObjects || (nFlags & IDF_NOTE);
+ if (bRecord && bDrawUndo)
+ pDoc->BeginDrawUndo();
+
+ if (bObjects)
+ {
+ if (bMulti)
+ pDoc->DeleteObjectsInSelection( aMultiMark );
+ else
+ pDoc->DeleteObjectsInArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
+ aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(),
+ aMultiMark );
+ }
+
+ if ( bRecord )
+ {
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, aMarkRange.aStart.Tab(), aMarkRange.aEnd.Tab() );
+
+ // bei "Format/Standard" alle Attribute kopieren, weil CopyToDocument
+ // nur mit IDF_HARDATTR zu langsam ist:
+ USHORT nUndoDocFlags = nFlags;
+ if (nFlags & IDF_ATTRIB)
+ nUndoDocFlags |= IDF_ATTRIB;
+ if (nFlags & IDF_EDITATTR) // Edit-Engine-Attribute
+ nUndoDocFlags |= IDF_STRING; // -> Zellen werden geaendert
+ if (nFlags & IDF_NOTE)
+ nUndoDocFlags |= IDF_CONTENTS; // #68795# copy all cells with their notes
+ // note captions are handled in drawing undo
+ nUndoDocFlags |= IDF_NOCAPTIONS;
+ pDoc->CopyToDocument( aExtendedRange, nUndoDocFlags, bMulti, pUndoDoc, &aMultiMark );
+ }
+
+//! HideAllCursors(); // falls Zusammenfassung aufgehoben wird
+ if (bSimple)
+ pDoc->DeleteArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
+ aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(),
+ aMultiMark, nFlags );
+ else
+ {
+ pDoc->DeleteSelection( nFlags, aMultiMark );
+// aMultiMark.MarkToSimple();
+ }
+
+ // add undo action after drawing undo is complete (objects and note captions)
+ if( bRecord )
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDeleteContents( &rDocShell, aMultiMark, aExtendedRange,
+ pUndoDoc, bMulti, nFlags, bDrawUndo ) );
+
+ if (!AdjustRowHeight( aExtendedRange ))
+ rDocShell.PostPaint( aExtendedRange, PAINT_GRID, nExtFlags );
+ else if (nExtFlags & SC_PF_LINES)
+ lcl_PaintAbove( rDocShell, aExtendedRange ); // fuer Linien ueber dem Bereich
+
+// rDocShell.UpdateOle(GetViewData()); //! an der View?
+ aModificator.SetDocumentModified();
+//! CellContentChanged();
+//! ShowAllCursors();
+
+#if 0
+ //! muss an der View bleiben !!!!
+ if ( nFlags & IDF_ATTRIB )
+ {
+ if ( nFlags & IDF_CONTENTS )
+ ForgetFormatArea();
+ else
+ StartFormatArea(); // Attribute loeschen ist auch Attributierung
+ }
+#endif
+
+ return TRUE;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScDocFunc::TransliterateText( const ScMarkData& rMark, sal_Int32 nType,
+ BOOL bRecord, BOOL bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+
+ ScEditableTester aTester( pDoc, rMark );
+ if (!aTester.IsEditable())
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ return FALSE;
+ }
+
+ ScRange aMarkRange;
+ ScMarkData aMultiMark = rMark;
+ aMultiMark.SetMarking(FALSE); // for MarkToMulti
+ aMultiMark.MarkToMulti();
+ aMultiMark.GetMultiMarkArea( aMarkRange );
+
+ if (bRecord)
+ {
+ SCTAB nStartTab = aMarkRange.aStart.Tab();
+ SCTAB nTabCount = pDoc->GetTableCount();
+
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
+ for (SCTAB i=0; i<nTabCount; i++)
+ if (i != nStartTab && rMark.GetTableSelect(i))
+ pUndoDoc->AddUndoTab( i, i );
+
+ ScRange aCopyRange = aMarkRange;
+ aCopyRange.aStart.SetTab(0);
+ aCopyRange.aEnd.SetTab(nTabCount-1);
+ pDoc->CopyToDocument( aCopyRange, IDF_CONTENTS, TRUE, pUndoDoc, &aMultiMark );
+
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoTransliterate( &rDocShell, aMultiMark, pUndoDoc, nType ) );
+ }
+
+ pDoc->TransliterateText( aMultiMark, nType );
+
+ if (!AdjustRowHeight( aMarkRange ))
+ rDocShell.PostPaint( aMarkRange, PAINT_GRID );
+
+ aModificator.SetDocumentModified();
+
+ return TRUE;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScDocFunc::SetNormalString( const ScAddress& rPos, const String& rText, BOOL bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ BOOL bUndo(pDoc->IsUndoEnabled());
+ ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
+ if (!aTester.IsEditable())
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ return FALSE;
+ }
+
+ SCTAB* pTabs = NULL;
+ ScBaseCell** ppOldCells = NULL;
+ BOOL* pHasFormat = NULL;
+ ULONG* pOldFormats = NULL;
+ ScBaseCell* pDocCell = pDoc->GetCell( rPos );
+ BOOL bEditDeleted = (pDocCell && pDocCell->GetCellType() == CELLTYPE_EDIT);
+ if (bUndo)
+ {
+ pTabs = new SCTAB[1];
+ pTabs[0] = rPos.Tab();
+ ppOldCells = new ScBaseCell*[1];
+ ppOldCells[0] = pDocCell ? pDocCell->CloneWithoutNote( *pDoc ) : 0;
+
+ pHasFormat = new BOOL[1];
+ pOldFormats = new ULONG[1];
+ const SfxPoolItem* pItem;
+ const ScPatternAttr* pPattern = pDoc->GetPattern( rPos.Col(),rPos.Row(),rPos.Tab() );
+ if ( SFX_ITEM_SET == pPattern->GetItemSet().GetItemState(
+ ATTR_VALUE_FORMAT,FALSE,&pItem) )
+ {
+ pHasFormat[0] = TRUE;
+ pOldFormats[0] = ((const SfxUInt32Item*)pItem)->GetValue();
+ }
+ else
+ pHasFormat[0] = FALSE;
+ }
+
+ pDoc->SetString( rPos.Col(), rPos.Row(), rPos.Tab(), rText );
+
+ if (bUndo)
+ {
+ // wegen ChangeTracking darf UndoAction erst nach SetString angelegt werden
+ rDocShell.GetUndoManager()->AddUndoAction(new ScUndoEnterData( &rDocShell, rPos.Col(),rPos.Row(),rPos.Tab(), 1,pTabs,
+ ppOldCells, pHasFormat, pOldFormats, rText, NULL ) );
+ }
+
+ if ( bEditDeleted || pDoc->HasAttrib( ScRange(rPos), HASATTR_NEEDHEIGHT ) )
+ AdjustRowHeight( ScRange(rPos) );
+
+ rDocShell.PostPaintCell( rPos );
+ aModificator.SetDocumentModified();
+
+ // #107160# notify input handler here the same way as in PutCell
+ if (bApi)
+ NotifyInputHandler( rPos );
+
+ return TRUE;
+}
+
+BOOL ScDocFunc::PutCell( const ScAddress& rPos, ScBaseCell* pNewCell, BOOL bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+ ScDocument* pDoc = rDocShell.GetDocument();
+ BOOL bUndo (pDoc->IsUndoEnabled());
+ BOOL bXMLLoading(pDoc->IsImportingXML());
+
+ // #i925#; it is not neccessary to test whether the cell is editable on loading a XML document
+ if (!bXMLLoading)
+ {
+ ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
+ if (!aTester.IsEditable())
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ pNewCell->Delete();
+ return FALSE;
+ }
+ }
+
+ BOOL bEditCell = ( pNewCell->GetCellType() == CELLTYPE_EDIT );
+ ScBaseCell* pDocCell = pDoc->GetCell( rPos );
+ BOOL bEditDeleted = (pDocCell && pDocCell->GetCellType() == CELLTYPE_EDIT);
+ BOOL bHeight = ( bEditDeleted || bEditCell ||
+ pDoc->HasAttrib( ScRange(rPos), HASATTR_NEEDHEIGHT ) );
+
+ ScBaseCell* pUndoCell = (bUndo && pDocCell) ? pDocCell->CloneWithoutNote( *pDoc, rPos ) : 0;
+ ScBaseCell* pRedoCell = (bUndo && pNewCell) ? pNewCell->CloneWithoutNote( *pDoc, rPos ) : 0;
+
+ pDoc->PutCell( rPos, pNewCell );
+
+ // wegen ChangeTracking darf UndoAction erst nach PutCell angelegt werden
+ if (bUndo)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoPutCell( &rDocShell, rPos, pUndoCell, pRedoCell, bHeight ) );
+ }
+
+ if (bHeight)
+ AdjustRowHeight( ScRange(rPos) );
+
+ if (!bXMLLoading)
+ rDocShell.PostPaintCell( rPos );
+
+ aModificator.SetDocumentModified();
+
+ // #i925#; it is not neccessary to notify on loading a XML document
+ // #103934#; notify editline and cell in edit mode
+ if (bApi && !bXMLLoading)
+ NotifyInputHandler( rPos );
+
+ return TRUE;
+}
+
+void ScDocFunc::NotifyInputHandler( const ScAddress& /* rPos */ )
+{
+ ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
+ if ( pViewSh && pViewSh->GetViewData()->GetDocShell() == &rDocShell )
+ {
+ ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl();
+ if ( pInputHdl )
+ {
+ sal_Bool bIsEditMode(pInputHdl->IsEditMode());
+
+ // set modified if in editmode, because so the string is not set in the InputWindow like in the cell
+ // (the cell shows the same like the InputWindow)
+ if (bIsEditMode)
+ pInputHdl->SetModified();
+ pViewSh->UpdateInputHandler(FALSE, !bIsEditMode);
+ }
+ }
+}
+
+ struct ScMyRememberItem
+ {
+ USHORT nIndex;
+ SfxItemSet aItemSet;
+
+ ScMyRememberItem(const SfxItemSet& rItemSet, USHORT nTempIndex) :
+ nIndex(nTempIndex), aItemSet(rItemSet) {}
+ };
+
+ typedef ::std::list<ScMyRememberItem*> ScMyRememberItemList;
+
+BOOL ScDocFunc::PutData( const ScAddress& rPos, ScEditEngineDefaulter& rEngine, BOOL bInterpret, BOOL bApi )
+{
+ // PutData ruft PutCell oder SetNormalString
+
+ BOOL bRet = FALSE;
+ ScDocument* pDoc = rDocShell.GetDocument();
+ ScEditAttrTester aTester( &rEngine );
+ BOOL bEditCell = aTester.NeedsObject();
+ if ( bEditCell )
+ {
+ // #i61702# With bLoseContent set, the content of rEngine isn't restored
+ // (used in loading XML, where after the removeActionLock call the API obejct's
+ // EditEngine isn't accessed again.
+ sal_Bool bLoseContent = pDoc->IsImportingXML();
+
+ sal_Bool bUpdateMode(rEngine.GetUpdateMode());
+ if (bUpdateMode)
+ rEngine.SetUpdateMode(sal_False);
+
+ ScMyRememberItemList aRememberItems;
+ ScMyRememberItem* pRememberItem = NULL;
+
+ // All paragraph attributes must be removed before calling CreateTextObject,
+ // not only alignment, so the object doesn't contain the cell attributes as
+ // paragraph attributes. Before remove the attributes store they in a list to
+ // set they back to the EditEngine.
+ USHORT nCount = rEngine.GetParagraphCount();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ const SfxItemSet& rOld = rEngine.GetParaAttribs( i );
+ if ( rOld.Count() )
+ {
+ if ( !bLoseContent )
+ {
+ pRememberItem = new ScMyRememberItem(rEngine.GetParaAttribs(i), i);
+ aRememberItems.push_back(pRememberItem);
+ }
+ rEngine.SetParaAttribs( i, SfxItemSet( *rOld.GetPool(), rOld.GetRanges() ) );
+ }
+ }
+
+ EditTextObject* pNewData = rEngine.CreateTextObject();
+ bRet = PutCell( rPos,
+ new ScEditCell( pNewData, pDoc, rEngine.GetEditTextObjectPool() ),
+ bApi );
+ delete pNewData;
+
+ // Set the paragraph attributes back to the EditEngine.
+ if (!aRememberItems.empty())
+ {
+// ScMyRememberItem* pRememberItem = NULL;
+ ScMyRememberItemList::iterator aItr = aRememberItems.begin();
+ while (aItr != aRememberItems.end())
+ {
+ pRememberItem = *aItr;
+ rEngine.SetParaAttribs(pRememberItem->nIndex, pRememberItem->aItemSet);
+ delete pRememberItem;
+ aItr = aRememberItems.erase(aItr);
+ }
+ }
+
+ // #i61702# if the content isn't accessed, there's no need to set the UpdateMode again
+ if ( bUpdateMode && !bLoseContent )
+ rEngine.SetUpdateMode(sal_True);
+ }
+ else
+ {
+ String aText = rEngine.GetText();
+ if ( bInterpret || !aText.Len() )
+ bRet = SetNormalString( rPos, aText, bApi );
+ else
+ bRet = PutCell( rPos, new ScStringCell( aText ), bApi );
+ }
+
+ if ( bRet && aTester.NeedsCellAttr() )
+ {
+ const SfxItemSet& rEditAttr = aTester.GetAttribs();
+ ScPatternAttr aPattern( pDoc->GetPool() );
+ aPattern.GetFromEditItemSet( &rEditAttr );
+ aPattern.DeleteUnchanged( pDoc->GetPattern( rPos.Col(), rPos.Row(), rPos.Tab() ) );
+ aPattern.GetItemSet().ClearItem( ATTR_HOR_JUSTIFY ); // wasn't removed above if no edit object
+ if ( aPattern.GetItemSet().Count() > 0 )
+ {
+ ScMarkData aMark;
+ aMark.SelectTable( rPos.Tab(), TRUE );
+ aMark.SetMarkArea( ScRange( rPos ) );
+ ApplyAttributes( aMark, aPattern, TRUE, bApi );
+ }
+ }
+
+ return bRet;
+}
+
+
+ScTokenArray* lcl_ScDocFunc_CreateTokenArrayXML( const String& rText, const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
+{
+ ScTokenArray* pCode = new ScTokenArray;
+ pCode->AddString( rText );
+ if( (eGrammar == formula::FormulaGrammar::GRAM_EXTERNAL) && (rFormulaNmsp.Len() > 0) )
+ pCode->AddString( rFormulaNmsp );
+ return pCode;
+}
+
+
+ScBaseCell* ScDocFunc::InterpretEnglishString( const ScAddress& rPos,
+ const String& rText, const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+ ScBaseCell* pNewCell = NULL;
+
+ if ( rText.Len() > 1 && rText.GetChar(0) == '=' )
+ {
+ ScTokenArray* pCode;
+ if ( pDoc->IsImportingXML() )
+ { // temporary formula string as string tokens
+ pCode = lcl_ScDocFunc_CreateTokenArrayXML( rText, rFormulaNmsp, eGrammar );
+ pDoc->IncXMLImportedFormulaCount( rText.Len() );
+ }
+ else
+ {
+ ScCompiler aComp( pDoc, rPos );
+ aComp.SetGrammar(eGrammar);
+ pCode = aComp.CompileString( rText );
+ }
+ pNewCell = new ScFormulaCell( pDoc, rPos, pCode, eGrammar, MM_NONE );
+ delete pCode; // Zell-ctor hat das TokenArray kopiert
+ }
+ else if ( rText.Len() > 1 && rText.GetChar(0) == '\'' )
+ {
+ // for bEnglish, "'" at the beginning is always interpreted as text
+ // marker and stripped
+ pNewCell = ScBaseCell::CreateTextCell( rText.Copy( 1 ), pDoc );
+ }
+ else // (nur) auf englisches Zahlformat testen
+ {
+ SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
+ sal_uInt32 nEnglish = pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US);
+ double fVal;
+ if ( pFormatter->IsNumberFormat( rText, nEnglish, fVal ) )
+ pNewCell = new ScValueCell( fVal );
+ else if ( rText.Len() )
+ pNewCell = ScBaseCell::CreateTextCell( rText, pDoc );
+
+ // das (englische) Zahlformat wird nicht gesetzt
+ //! passendes lokales Format suchen und setzen???
+ }
+
+ return pNewCell;
+}
+
+
+BOOL ScDocFunc::SetCellText( const ScAddress& rPos, const String& rText,
+ BOOL bInterpret, BOOL bEnglish, BOOL bApi,
+ const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
+{
+ // SetCellText ruft PutCell oder SetNormalString
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ ScBaseCell* pNewCell = NULL;
+ if ( bInterpret )
+ {
+ if ( bEnglish )
+ {
+ // code moved to own method InterpretEnglishString because it is also used in
+ // ScCellRangeObj::setFormulaArray
+
+ pNewCell = InterpretEnglishString( rPos, rText, rFormulaNmsp, eGrammar );
+ }
+ // sonst Null behalten -> SetString mit lokalen Formeln/Zahlformat
+ }
+ else if ( rText.Len() )
+ {
+ OSL_ENSURE( rFormulaNmsp.Len() == 0, "ScDocFunc::SetCellText - formula namespace, but do not interpret?" );
+ pNewCell = ScBaseCell::CreateTextCell( rText, pDoc ); // immer Text
+ }
+
+ if (pNewCell)
+ return PutCell( rPos, pNewCell, bApi );
+ else
+ return SetNormalString( rPos, rText, bApi );
+}
+
+//------------------------------------------------------------------------
+
+bool ScDocFunc::ShowNote( const ScAddress& rPos, bool bShow )
+{
+ ScDocument& rDoc = *rDocShell.GetDocument();
+ ScPostIt* pNote = rDoc.GetNote( rPos );
+ if( !pNote || (bShow == pNote->IsCaptionShown()) ) return false;
+
+ // move the caption to internal or hidden layer and create undo action
+ pNote->ShowCaption( rPos, bShow );
+ if( rDoc.IsUndoEnabled() )
+ rDocShell.GetUndoManager()->AddUndoAction( new ScUndoShowHideNote( rDocShell, rPos, bShow ) );
+
+ if (rDoc.IsStreamValid(rPos.Tab()))
+ rDoc.SetStreamValid(rPos.Tab(), FALSE);
+
+ rDocShell.SetDocumentModified();
+
+ return true;
+}
+
+//------------------------------------------------------------------------
+
+bool ScDocFunc::SetNoteText( const ScAddress& rPos, const String& rText, BOOL bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
+ if (!aTester.IsEditable())
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ return false;
+ }
+
+ String aNewText = rText;
+ aNewText.ConvertLineEnd(); //! ist das noetig ???
+
+ if( ScPostIt* pNote = (aNewText.Len() > 0) ? pDoc->GetOrCreateNote( rPos ) : pDoc->GetNote( rPos ) )
+ pNote->SetText( rPos, aNewText );
+
+ //! Undo !!!
+
+ if (pDoc->IsStreamValid(rPos.Tab()))
+ pDoc->SetStreamValid(rPos.Tab(), FALSE);
+
+ rDocShell.PostPaintCell( rPos );
+ aModificator.SetDocumentModified();
+
+ return true;
+}
+
+//------------------------------------------------------------------------
+
+bool ScDocFunc::ReplaceNote( const ScAddress& rPos, const String& rNoteText, const String* pAuthor, const String* pDate, BOOL bApi )
+{
+ bool bDone = false;
+
+ ScDocShellModificator aModificator( rDocShell );
+ ScDocument& rDoc = *rDocShell.GetDocument();
+ ScEditableTester aTester( &rDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
+ if (aTester.IsEditable())
+ {
+ ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
+ SfxUndoManager* pUndoMgr = (pDrawLayer && rDoc.IsUndoEnabled()) ? rDocShell.GetUndoManager() : 0;
+
+ ScNoteData aOldData;
+ ScPostIt* pOldNote = rDoc.ReleaseNote( rPos );
+ if( pOldNote )
+ {
+ // ensure existing caption object before draw undo tracking starts
+ pOldNote->GetOrCreateCaption( rPos );
+ // rescue note data for undo
+ aOldData = pOldNote->GetNoteData();
+ }
+
+ // collect drawing undo actions for deleting/inserting caption obejcts
+ if( pUndoMgr )
+ pDrawLayer->BeginCalcUndo();
+
+ // delete the note (creates drawing undo action for the caption object)
+ delete pOldNote;
+
+ // create new note (creates drawing undo action for the new caption object)
+ ScNoteData aNewData;
+ if( ScPostIt* pNewNote = ScNoteUtil::CreateNoteFromString( rDoc, rPos, rNoteText, false, true ) )
+ {
+ if( pAuthor ) pNewNote->SetAuthor( *pAuthor );
+ if( pDate ) pNewNote->SetDate( *pDate );
+ // rescue note data for undo
+ aNewData = pNewNote->GetNoteData();
+ }
+
+ // create the undo action
+ if( pUndoMgr && (aOldData.mpCaption || aNewData.mpCaption) )
+ pUndoMgr->AddUndoAction( new ScUndoReplaceNote( rDocShell, rPos, aOldData, aNewData, pDrawLayer->GetCalcUndo() ) );
+
+ // repaint cell (to make note marker visible)
+ rDocShell.PostPaintCell( rPos );
+
+ if (rDoc.IsStreamValid(rPos.Tab()))
+ rDoc.SetStreamValid(rPos.Tab(), FALSE);
+
+ aModificator.SetDocumentModified();
+ bDone = true;
+ }
+ else if (!bApi)
+ {
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ }
+
+ return bDone;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScDocFunc::ApplyAttributes( const ScMarkData& rMark, const ScPatternAttr& rPattern,
+ BOOL bRecord, BOOL bApi )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if ( bRecord && !pDoc->IsUndoEnabled() )
+ bRecord = FALSE;
+
+ BOOL bImportingXML = pDoc->IsImportingXML();
+ // Cell formats can still be set if the range isn't editable only because of matrix formulas.
+ // #i62483# When loading XML, the check can be skipped altogether.
+ BOOL bOnlyNotBecauseOfMatrix;
+ if ( !bImportingXML && !pDoc->IsSelectionEditable( rMark, &bOnlyNotBecauseOfMatrix )
+ && !bOnlyNotBecauseOfMatrix )
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_PROTECTIONERR);
+ return FALSE;
+ }
+
+ ScDocShellModificator aModificator( rDocShell );
+
+ //! Umrandung
+
+ ScRange aMultiRange;
+ BOOL bMulti = rMark.IsMultiMarked();
+ if ( bMulti )
+ rMark.GetMultiMarkArea( aMultiRange );
+ else
+ rMark.GetMarkArea( aMultiRange );
+
+ if ( bRecord )
+ {
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, aMultiRange.aStart.Tab(), aMultiRange.aEnd.Tab() );
+ pDoc->CopyToDocument( aMultiRange, IDF_ATTRIB, bMulti, pUndoDoc, &rMark );
+
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoSelectionAttr(
+ &rDocShell, rMark,
+ aMultiRange.aStart.Col(), aMultiRange.aStart.Row(), aMultiRange.aStart.Tab(),
+ aMultiRange.aEnd.Col(), aMultiRange.aEnd.Row(), aMultiRange.aEnd.Tab(),
+ pUndoDoc, bMulti, &rPattern ) );
+ }
+
+ // While loading XML it is not neccessary to ask HasAttrib. It needs too much time.
+ USHORT nExtFlags = 0;
+ if ( !bImportingXML )
+ rDocShell.UpdatePaintExt( nExtFlags, aMultiRange ); // content before the change
+ pDoc->ApplySelectionPattern( rPattern, rMark );
+ if ( !bImportingXML )
+ rDocShell.UpdatePaintExt( nExtFlags, aMultiRange ); // content after the change
+
+ if (!AdjustRowHeight( aMultiRange ))
+ rDocShell.PostPaint( aMultiRange, PAINT_GRID, nExtFlags );
+ else if (nExtFlags & SC_PF_LINES)
+ lcl_PaintAbove( rDocShell, aMultiRange ); // fuer Linien ueber dem Bereich
+
+ aModificator.SetDocumentModified();
+
+ return TRUE;
+}
+
+
+BOOL ScDocFunc::ApplyStyle( const ScMarkData& rMark, const String& rStyleName,
+ BOOL bRecord, BOOL bApi )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if ( bRecord && !pDoc->IsUndoEnabled() )
+ bRecord = FALSE;
+
+ BOOL bImportingXML = pDoc->IsImportingXML();
+ // Cell formats can still be set if the range isn't editable only because of matrix formulas.
+ // #i62483# When loading XML, the check can be skipped altogether.
+ BOOL bOnlyNotBecauseOfMatrix;
+ if ( !bImportingXML && !pDoc->IsSelectionEditable( rMark, &bOnlyNotBecauseOfMatrix )
+ && !bOnlyNotBecauseOfMatrix )
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_PROTECTIONERR);
+ return FALSE;
+ }
+
+ ScStyleSheet* pStyleSheet = (ScStyleSheet*) pDoc->GetStyleSheetPool()->Find(
+ rStyleName, SFX_STYLE_FAMILY_PARA );
+ if (!pStyleSheet)
+ return FALSE;
+
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScRange aMultiRange;
+ BOOL bMulti = rMark.IsMultiMarked();
+ if ( bMulti )
+ rMark.GetMultiMarkArea( aMultiRange );
+ else
+ rMark.GetMarkArea( aMultiRange );
+
+ if ( bRecord )
+ {
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ SCTAB nStartTab = aMultiRange.aStart.Tab();
+ SCTAB nTabCount = pDoc->GetTableCount();
+ pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
+ for (SCTAB i=0; i<nTabCount; i++)
+ if (i != nStartTab && rMark.GetTableSelect(i))
+ pUndoDoc->AddUndoTab( i, i );
+
+ ScRange aCopyRange = aMultiRange;
+ aCopyRange.aStart.SetTab(0);
+ aCopyRange.aEnd.SetTab(nTabCount-1);
+ pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pUndoDoc, &rMark );
+
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoSelectionStyle(
+ &rDocShell, rMark, aMultiRange, rStyleName, pUndoDoc ) );
+
+ }
+
+// BOOL bPaintExt = pDoc->HasAttrib( aMultiRange, HASATTR_PAINTEXT );
+// pDoc->ApplySelectionPattern( rPattern, rMark );
+
+ pDoc->ApplySelectionStyle( (ScStyleSheet&)*pStyleSheet, rMark );
+
+// if (!bPaintExt)
+// bPaintExt = pDoc->HasAttrib( aMultiRange, HASATTR_PAINTEXT );
+// USHORT nExtFlags = bPaintExt ? SC_PF_LINES : 0;
+ USHORT nExtFlags = 0;
+ if (!AdjustRowHeight( aMultiRange ))
+ rDocShell.PostPaint( aMultiRange, PAINT_GRID, nExtFlags );
+ else if (nExtFlags & SC_PF_LINES)
+ lcl_PaintAbove( rDocShell, aMultiRange ); // fuer Linien ueber dem Bereich
+
+ aModificator.SetDocumentModified();
+
+ return TRUE;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScDocFunc::InsertCells( const ScRange& rRange, const ScMarkData* pTabMark, InsCellCmd eCmd,
+ BOOL bRecord, BOOL bApi, BOOL bPartOfPaste )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCTAB nStartTab = rRange.aStart.Tab();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ SCTAB nEndTab = rRange.aEnd.Tab();
+
+ if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) )
+ {
+ DBG_ERROR("invalid row in InsertCells");
+ return FALSE;
+ }
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ SCTAB nTabCount = pDoc->GetTableCount();
+ SCCOL nPaintStartX = nStartCol;
+ SCROW nPaintStartY = nStartRow;
+ SCCOL nPaintEndX = nEndCol;
+ SCROW nPaintEndY = nEndRow;
+ USHORT nPaintFlags = PAINT_GRID;
+ BOOL bSuccess;
+ SCTAB i;
+
+ ScTabViewShell* pViewSh = rDocShell.GetBestViewShell(); //preserve current cursor position
+ SCCOL nCursorCol = 0;
+ SCROW nCursorRow = 0;
+ if( pViewSh )
+ {
+ nCursorCol = pViewSh->GetViewData()->GetCurX();
+ nCursorRow = pViewSh->GetViewData()->GetCurY();
+ }
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+
+ ScMarkData aMark;
+ if (pTabMark)
+ aMark = *pTabMark;
+ else
+ {
+ SCTAB nCount = 0;
+ for( i=0; i<nTabCount; i++ )
+ {
+ if( !pDoc->IsScenario(i) )
+ {
+ nCount++;
+ if( nCount == nEndTab+1 )
+ {
+ aMark.SelectTable( i, TRUE );
+ break;
+ }
+ }
+ }
+ }
+
+ ScMarkData aFullMark( aMark ); // including scenario sheets
+ for( i=0; i<nTabCount; i++ )
+ if( aMark.GetTableSelect( i ) )
+ {
+ for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
+ aFullMark.SelectTable( j, TRUE );
+ }
+
+ SCTAB nSelCount = aMark.GetSelectCount();
+
+ // zugehoerige Szenarien auch anpassen
+ // Test zusammengefasste
+
+ SCCOL nMergeTestStartX = nStartCol;
+ SCROW nMergeTestStartY = nStartRow;
+ SCCOL nMergeTestEndX = nEndCol;
+ SCROW nMergeTestEndY = nEndRow;
+
+ ScRange aExtendMergeRange( rRange );
+
+ if( rRange.aStart == rRange.aEnd && pDoc->HasAttrib(rRange, HASATTR_MERGED) )
+ {
+ pDoc->ExtendMerge( aExtendMergeRange );
+ pDoc->ExtendOverlapped( aExtendMergeRange );
+ nMergeTestEndX = aExtendMergeRange.aEnd.Col();
+ nMergeTestEndY = aExtendMergeRange.aEnd.Row();
+ nPaintEndX = nMergeTestEndX;
+ nPaintEndY = nMergeTestEndY;
+ }
+
+ if ( eCmd == INS_INSROWS )
+ {
+ nMergeTestStartX = 0;
+ nMergeTestEndX = MAXCOL;
+ }
+ if ( eCmd == INS_INSCOLS )
+ {
+ nMergeTestStartY = 0;
+ nMergeTestEndY = MAXROW;
+ }
+ if ( eCmd == INS_CELLSDOWN )
+ nMergeTestEndY = MAXROW;
+ if ( eCmd == INS_CELLSRIGHT )
+ nMergeTestEndX = MAXCOL;
+
+ BOOL bNeedRefresh = FALSE;
+
+ SCCOL nEditTestEndX = (eCmd==INS_INSCOLS) ? MAXCOL : nMergeTestEndX;
+ SCROW nEditTestEndY = (eCmd==INS_INSROWS) ? MAXROW : nMergeTestEndY;
+ ScEditableTester aTester( pDoc, nMergeTestStartX, nMergeTestStartY, nEditTestEndX, nEditTestEndY, aMark );
+ if (!aTester.IsEditable())
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ return FALSE;
+ }
+
+ WaitObject aWait( rDocShell.GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference
+
+ ScDocument* pRefUndoDoc = NULL;
+ ScRefUndoData* pUndoData = NULL;
+ if ( bRecord )
+ {
+ pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, FALSE, FALSE );
+
+ // pRefUndoDoc is filled in InsertCol / InsertRow
+
+ pUndoData = new ScRefUndoData( pDoc );
+
+ pDoc->BeginDrawUndo();
+ }
+
+ // #i8302 : we unmerge overwhelming ranges, before insertion all the actions are put in the same ListAction
+ // the patch comes from mloiseleur and maoyg
+ BOOL bInsertMerge = FALSE;
+ std::vector<ScRange> qIncreaseRange;
+ String aUndo = ScGlobal::GetRscString( STR_UNDO_INSERTCELLS );
+ if (bRecord)
+ rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
+
+ for( i=0; i<nTabCount; i++ )
+ {
+ if( aMark.GetTableSelect(i) )
+ {
+ if( pDoc->HasAttrib( nMergeTestStartX, nMergeTestStartY, i, nMergeTestEndX, nMergeTestEndY, i, HASATTR_MERGED | HASATTR_OVERLAPPED ) )
+ {
+ if (eCmd==INS_CELLSRIGHT)
+ bNeedRefresh = TRUE;
+
+ SCCOL nMergeStartX = nMergeTestStartX;
+ SCROW nMergeStartY = nMergeTestStartY;
+ SCCOL nMergeEndX = nMergeTestEndX;
+ SCROW nMergeEndY = nMergeTestEndY;
+
+ pDoc->ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i );
+ pDoc->ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i );
+
+ if(( eCmd == INS_CELLSDOWN && ( nMergeStartX != nMergeTestStartX || nMergeEndX != nMergeTestEndX )) ||
+ (eCmd == INS_CELLSRIGHT && ( nMergeStartY != nMergeTestStartY || nMergeEndY != nMergeTestEndY )) )
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0);
+ rDocShell.GetUndoManager()->LeaveListAction();
+ return FALSE;
+ }
+
+ SCCOL nTestCol = -1;
+ SCROW nTestRow1 = -1;
+ SCROW nTestRow2 = -1;
+
+ ScDocAttrIterator aTestIter( pDoc, i, nMergeTestStartX, nMergeTestStartY, nMergeTestEndX, nMergeTestEndY );
+ ScRange aExtendRange( nMergeTestStartX, nMergeTestStartY, i, nMergeTestEndX, nMergeTestEndY, i );
+ const ScPatternAttr* pPattern = NULL;
+ const ScMergeAttr* pMergeFlag = NULL;
+ const ScMergeFlagAttr* pMergeFlagAttr = NULL;
+ while ( ( pPattern = aTestIter.GetNext( nTestCol, nTestRow1, nTestRow2 ) ) != NULL )
+ {
+ pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem(ATTR_MERGE);
+ pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG);
+ INT16 nNewFlags = pMergeFlagAttr->GetValue() & ( SC_MF_HOR | SC_MF_VER );
+ if( ( pMergeFlag && pMergeFlag->IsMerged() ) || nNewFlags == SC_MF_HOR || nNewFlags == SC_MF_VER )
+ {
+ ScRange aRange( nTestCol, nTestRow1, i );
+ pDoc->ExtendOverlapped(aRange);
+ pDoc->ExtendMerge(aRange, TRUE, TRUE);
+
+ if( nTestRow1 < nTestRow2 && nNewFlags == SC_MF_HOR )
+ {
+ for( SCROW nTestRow = nTestRow1; nTestRow <= nTestRow2; nTestRow++ )
+ {
+ ScRange aTestRange( nTestCol, nTestRow, i );
+ pDoc->ExtendOverlapped( aTestRange );
+ pDoc->ExtendMerge( aTestRange, TRUE, TRUE);
+ ScRange aMergeRange( aTestRange.aStart.Col(),aTestRange.aStart.Row(), i );
+ if( !aExtendRange.In( aMergeRange ) )
+ {
+ qIncreaseRange.push_back( aTestRange );
+ bInsertMerge = TRUE;
+ }
+ }
+ }
+ else
+ {
+ ScRange aMergeRange( aRange.aStart.Col(),aRange.aStart.Row(), i );
+ if( !aExtendRange.In( aMergeRange ) )
+ {
+ qIncreaseRange.push_back( aRange );
+ }
+ bInsertMerge = TRUE;
+ }
+ }
+ }
+
+ if( bInsertMerge )
+ {
+ if( eCmd == INS_INSROWS || eCmd == INS_CELLSDOWN )
+ {
+ nStartRow = aExtendMergeRange.aStart.Row();
+ nEndRow = aExtendMergeRange.aEnd.Row();
+
+ if( eCmd == INS_CELLSDOWN )
+ nEndCol = nMergeTestEndX;
+ else
+ {
+ nStartCol = 0;
+ nEndCol = MAXCOL;
+ }
+ }
+ else if( eCmd == INS_CELLSRIGHT || eCmd == INS_INSCOLS )
+ {
+
+ nStartCol = aExtendMergeRange.aStart.Col();
+ nEndCol = aExtendMergeRange.aEnd.Col();
+ if( eCmd == INS_CELLSRIGHT )
+ {
+ nEndRow = nMergeTestEndY;
+ }
+ else
+ {
+ nStartRow = 0;
+ nEndRow = MAXROW;
+ }
+ }
+
+ if( !qIncreaseRange.empty() )
+ {
+ for( ::std::vector<ScRange>::const_iterator iIter( qIncreaseRange.begin()); iIter != qIncreaseRange.end(); iIter++ )
+ {
+ ScRange aRange( *iIter );
+ if( pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
+ {
+ UnmergeCells( aRange, TRUE, TRUE );
+ }
+ }
+ }
+ }
+ else
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0);
+ rDocShell.GetUndoManager()->LeaveListAction();
+ return FALSE;
+ }
+ }
+ }
+ }
+
+ switch (eCmd)
+ {
+ case INS_CELLSDOWN:
+ bSuccess = pDoc->InsertRow( nStartCol, 0, nEndCol, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &aFullMark );
+ nPaintEndY = MAXROW;
+ break;
+ case INS_INSROWS:
+ bSuccess = pDoc->InsertRow( 0, 0, MAXCOL, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &aFullMark );
+ nPaintStartX = 0;
+ nPaintEndX = MAXCOL;
+ nPaintEndY = MAXROW;
+ nPaintFlags |= PAINT_LEFT;
+ break;
+ case INS_CELLSRIGHT:
+ bSuccess = pDoc->InsertCol( nStartRow, 0, nEndRow, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &aFullMark );
+ nPaintEndX = MAXCOL;
+ break;
+ case INS_INSCOLS:
+ bSuccess = pDoc->InsertCol( 0, 0, MAXROW, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &aFullMark );
+ nPaintStartY = 0;
+ nPaintEndY = MAXROW;
+ nPaintEndX = MAXCOL;
+ nPaintFlags |= PAINT_TOP;
+ break;
+ default:
+ DBG_ERROR("Falscher Code beim Einfuegen");
+ bSuccess = FALSE;
+ break;
+ }
+
+ if ( bSuccess )
+ {
+ SCTAB* pTabs = NULL;
+ SCTAB* pScenarios = NULL;
+ SCTAB nUndoPos = 0;
+
+ if ( bRecord )
+ {
+ pTabs = new SCTAB[nSelCount];
+ pScenarios = new SCTAB[nSelCount];
+ nUndoPos = 0;
+ for( i=0; i<nTabCount; i++ )
+ {
+ if( aMark.GetTableSelect( i ) )
+ {
+ SCTAB nCount = 0;
+ for( SCTAB j=i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
+ nCount ++;
+
+ pScenarios[nUndoPos] = nCount;
+ pTabs[nUndoPos] = i;
+ nUndoPos ++;
+ }
+ }
+
+ if( !bInsertMerge )
+ {
+ rDocShell.GetUndoManager()->LeaveListAction();
+ }
+
+ rDocShell.GetUndoManager()->AddUndoAction( new ScUndoInsertCells(
+ &rDocShell, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ),
+ nUndoPos, pTabs, pScenarios, eCmd, pRefUndoDoc, pUndoData, bPartOfPaste ) );
+ }
+
+ // #i8302 : we remerge growing ranges, with the new part inserted
+
+ while( !qIncreaseRange.empty() )
+ {
+ ScRange aRange = qIncreaseRange.back();
+ if( !pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
+ {
+ switch (eCmd)
+ {
+ case INS_CELLSDOWN:
+ case INS_INSROWS:
+ aRange.aEnd.IncRow(static_cast<SCsCOL>(nEndRow-nStartRow+1));
+ break;
+ case INS_CELLSRIGHT:
+ case INS_INSCOLS:
+ aRange.aEnd.IncCol(static_cast<SCsCOL>(nEndCol-nStartCol+1));
+ break;
+ default:
+ break;
+ }
+ MergeCells(aRange, FALSE, TRUE, TRUE);
+ }
+ qIncreaseRange.pop_back();
+ }
+
+ if( bInsertMerge )
+ rDocShell.GetUndoManager()->LeaveListAction();
+
+ for( i=0; i<nTabCount; i++ )
+ {
+ if( aMark.GetTableSelect( i ) )
+ {
+ if (bNeedRefresh)
+ pDoc->ExtendMerge( nMergeTestStartX, nMergeTestStartY, nMergeTestEndX, nMergeTestEndY, i, TRUE );
+ else
+ pDoc->RefreshAutoFilter( nMergeTestStartX, nMergeTestStartY, nMergeTestEndX, nMergeTestEndY, i );
+
+ if ( eCmd == INS_INSROWS || eCmd == INS_INSCOLS )
+ pDoc->UpdatePageBreaks( i );
+
+ USHORT nExtFlags = 0;
+ rDocShell.UpdatePaintExt( nExtFlags, nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i );
+
+ SCTAB nScenarioCount = 0;
+
+ for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
+ nScenarioCount ++;
+
+ BOOL bAdjusted = ( eCmd == INS_INSROWS ) ? AdjustRowHeight(ScRange(0, nStartRow, i, MAXCOL, nEndRow, i+nScenarioCount )) :
+ AdjustRowHeight(ScRange(0, nPaintStartY, i, MAXCOL, nPaintEndY, i+nScenarioCount ));
+ if (bAdjusted)
+ {
+ // paint only what is not done by AdjustRowHeight
+ if (nPaintFlags & PAINT_TOP)
+ rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, PAINT_TOP );
+ }
+ else
+ rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, nPaintFlags, nExtFlags );
+ }
+ }
+ //aModificator.SetDocumentModified();
+ }
+ else
+ {
+ if( bInsertMerge )
+ {
+ while( !qIncreaseRange.empty() )
+ {
+ ScRange aRange = qIncreaseRange.back();
+ MergeCells(aRange, FALSE, TRUE, TRUE);
+ qIncreaseRange.pop_back();
+ }
+
+ if( pViewSh )
+ {
+ pViewSh->MarkRange( rRange, FALSE );
+ pViewSh->SetCursor( nCursorCol, nCursorRow );
+ }
+ }
+
+ rDocShell.GetUndoManager()->LeaveListAction();
+ SfxUndoManager* pMgr = rDocShell.GetUndoManager();
+ pMgr->RemoveLastUndoAction();
+
+ delete pRefUndoDoc;
+ delete pUndoData;
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_INSERT_FULL); // Spalte/Zeile voll
+ }
+
+ aModificator.SetDocumentModified();
+
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
+ return bSuccess;
+}
+
+BOOL ScDocFunc::DeleteCells( const ScRange& rRange, const ScMarkData* pTabMark, DelCellCmd eCmd,
+ BOOL bRecord, BOOL bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCTAB nStartTab = rRange.aStart.Tab();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ SCTAB nEndTab = rRange.aEnd.Tab();
+
+ if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) )
+ {
+ DBG_ERROR("invalid row in DeleteCells");
+ return FALSE;
+ }
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ SCTAB nTabCount = pDoc->GetTableCount();
+ SCCOL nPaintStartX = nStartCol;
+ SCROW nPaintStartY = nStartRow;
+ SCCOL nPaintEndX = nEndCol;
+ SCROW nPaintEndY = nEndRow;
+ USHORT nPaintFlags = PAINT_GRID;
+ SCTAB i;
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+
+ ScMarkData aMark;
+ if (pTabMark)
+ aMark = *pTabMark;
+ else
+ {
+ SCTAB nCount = 0;
+ for( i=0; i<nTabCount; i++ )
+ {
+ if( !pDoc->IsScenario(i) )
+ {
+ nCount++;
+ if( nCount == nEndTab+1 )
+ {
+ aMark.SelectTable( i, TRUE );
+ break;
+ }
+ }
+ }
+ }
+
+ ScMarkData aFullMark( aMark ); // including scenario sheets
+ for( i=0; i<nTabCount; i++ )
+ if( aMark.GetTableSelect( i ) )
+ {
+ for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
+ aFullMark.SelectTable( j, TRUE );
+ }
+
+ SCTAB nSelCount = aMark.GetSelectCount();
+
+ SCCOL nUndoStartX = nStartCol;
+ SCROW nUndoStartY = nStartRow;
+ SCCOL nUndoEndX = nEndCol;
+ SCROW nUndoEndY = nEndRow;
+
+ ScRange aExtendMergeRange( rRange );
+
+ if( rRange.aStart == rRange.aEnd && pDoc->HasAttrib(rRange, HASATTR_MERGED) )
+ {
+ pDoc->ExtendMerge( aExtendMergeRange );
+ pDoc->ExtendOverlapped( aExtendMergeRange );
+ nUndoEndX = aExtendMergeRange.aEnd.Col();
+ nUndoEndY = aExtendMergeRange.aEnd.Row();
+ nPaintEndX = nUndoEndX;
+ nPaintEndY = nUndoEndY;
+ }
+
+ if (eCmd==DEL_DELROWS)
+ {
+ nUndoStartX = 0;
+ nUndoEndX = MAXCOL;
+ }
+ if (eCmd==DEL_DELCOLS)
+ {
+ nUndoStartY = 0;
+ nUndoEndY = MAXROW;
+ }
+ // Test Zellschutz
+
+ SCCOL nEditTestEndX = nUndoEndX;
+ if ( eCmd==DEL_DELCOLS || eCmd==DEL_CELLSLEFT )
+ nEditTestEndX = MAXCOL;
+ SCROW nEditTestEndY = nUndoEndY;
+ if ( eCmd==DEL_DELROWS || eCmd==DEL_CELLSUP )
+ nEditTestEndY = MAXROW;
+ ScEditableTester aTester( pDoc, nUndoStartX, nUndoStartY, nEditTestEndX, nEditTestEndY, aMark );
+ if (!aTester.IsEditable())
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ return FALSE;
+ }
+
+ // Test zusammengefasste
+
+ SCCOL nMergeTestEndX = (eCmd==DEL_CELLSLEFT) ? MAXCOL : nUndoEndX;
+ SCROW nMergeTestEndY = (eCmd==DEL_CELLSUP) ? MAXROW : nUndoEndY;
+ SCCOL nExtendStartCol = nUndoStartX;
+ SCROW nExtendStartRow = nUndoStartY;
+ BOOL bNeedRefresh = FALSE;
+
+ //Issue 8302 want to be able to insert into the middle of merged cells
+ //the patch comes from maoyg
+ ::std::vector<ScRange> qDecreaseRange;
+ BOOL bDeletingMerge = FALSE;
+ String aUndo = ScGlobal::GetRscString( STR_UNDO_DELETECELLS );
+ if (bRecord)
+ rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
+
+ for( i=0; i<nTabCount; i++ )
+ {
+ if( aMark.GetTableSelect(i) )
+ {
+ if ( pDoc->HasAttrib( nUndoStartX, nUndoStartY, i, nMergeTestEndX, nMergeTestEndY, i, HASATTR_MERGED | HASATTR_OVERLAPPED ))
+ {
+ SCCOL nMergeStartX = nUndoStartX;
+ SCROW nMergeStartY = nUndoStartY;
+ SCCOL nMergeEndX = nMergeTestEndX;
+ SCROW nMergeEndY = nMergeTestEndY;
+
+ pDoc->ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i );
+ pDoc->ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i );
+ if( ( eCmd == DEL_CELLSUP && ( nMergeStartX != nUndoStartX || nMergeEndX != nMergeTestEndX))||
+ ( eCmd == DEL_CELLSLEFT && ( nMergeStartY != nUndoStartY || nMergeEndY != nMergeTestEndY)))
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_MSSG_DELETECELLS_0);
+ rDocShell.GetUndoManager()->LeaveListAction();
+ return FALSE;
+ }
+
+ nExtendStartCol = nMergeStartX;
+ nExtendStartRow = nMergeStartY;
+ SCCOL nTestCol = -1;
+ SCROW nTestRow1 = -1;
+ SCROW nTestRow2 = -1;
+
+ ScDocAttrIterator aTestIter( pDoc, i, nUndoStartX, nUndoStartY, nMergeTestEndX, nMergeTestEndY );
+ ScRange aExtendRange( nUndoStartX, nUndoStartY, i, nMergeTestEndX, nMergeTestEndY, i );
+ const ScPatternAttr* pPattern = NULL;
+ const ScMergeAttr* pMergeFlag = NULL;
+ const ScMergeFlagAttr* pMergeFlagAttr = NULL;
+ while ( ( pPattern = aTestIter.GetNext( nTestCol, nTestRow1, nTestRow2 ) ) != NULL )
+ {
+ pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem( ATTR_MERGE );
+ pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem( ATTR_MERGE_FLAG );
+ INT16 nNewFlags = pMergeFlagAttr->GetValue() & ( SC_MF_HOR | SC_MF_VER );
+ if( ( pMergeFlag && pMergeFlag->IsMerged() ) || nNewFlags == SC_MF_HOR || nNewFlags == SC_MF_VER )
+ {
+ ScRange aRange( nTestCol, nTestRow1, i );
+ pDoc->ExtendOverlapped( aRange );
+ pDoc->ExtendMerge( aRange, TRUE, TRUE );
+
+ if( nTestRow1 < nTestRow2 && nNewFlags == SC_MF_HOR )
+ {
+ for( SCROW nTestRow = nTestRow1; nTestRow <= nTestRow2; nTestRow++ )
+ {
+ ScRange aTestRange( nTestCol, nTestRow, i );
+ pDoc->ExtendOverlapped( aTestRange );
+ pDoc->ExtendMerge( aTestRange, TRUE, TRUE);
+ ScRange aMergeRange( aTestRange.aStart.Col(),aTestRange.aStart.Row(), i );
+ if( !aExtendRange.In( aMergeRange ) )
+ {
+ qDecreaseRange.push_back( aTestRange );
+ bDeletingMerge = TRUE;
+ }
+ }
+ }
+ else
+ {
+ ScRange aMergeRange( aRange.aStart.Col(),aRange.aStart.Row(), i );
+ if( !aExtendRange.In( aMergeRange ) )
+ {
+ qDecreaseRange.push_back( aRange );
+ }
+ bDeletingMerge = TRUE;
+ }
+ }
+ }
+
+ if( bDeletingMerge )
+ {
+
+ if( eCmd == DEL_DELROWS || eCmd == DEL_CELLSUP )
+ {
+ nStartRow = aExtendMergeRange.aStart.Row();
+ nEndRow = aExtendMergeRange.aEnd.Row();
+ bNeedRefresh = TRUE;
+
+ if( eCmd == DEL_CELLSUP )
+ {
+ nEndCol = aExtendMergeRange.aEnd.Col();
+ }
+ else
+ {
+ nStartCol = 0;
+ nEndCol = MAXCOL;
+ }
+ }
+ else if( eCmd == DEL_CELLSLEFT || eCmd == DEL_DELCOLS )
+ {
+
+ nStartCol = aExtendMergeRange.aStart.Col();
+ nEndCol = aExtendMergeRange.aEnd.Col();
+ if( eCmd == DEL_CELLSLEFT )
+ {
+ nEndRow = aExtendMergeRange.aEnd.Row();
+ bNeedRefresh = TRUE;
+ }
+ else
+ {
+ nStartRow = 0;
+ nEndRow = MAXROW;
+ }
+ }
+
+ if( !qDecreaseRange.empty() )
+ {
+ for( ::std::vector<ScRange>::const_iterator iIter( qDecreaseRange.begin()); iIter != qDecreaseRange.end(); iIter++ )
+ {
+ ScRange aRange( *iIter );
+ if( pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
+ {
+ UnmergeCells( aRange, TRUE, TRUE );
+ }
+ }
+ }
+ }
+ else
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_MSSG_DELETECELLS_0);
+ rDocShell.GetUndoManager()->LeaveListAction();
+ return FALSE;
+ }
+ }
+ }
+ }
+
+ //
+ // ausfuehren
+ //
+
+ WaitObject aWait( rDocShell.GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference
+
+ ScDocument* pUndoDoc = NULL;
+ ScDocument* pRefUndoDoc = NULL;
+ ScRefUndoData* pUndoData = NULL;
+ if ( bRecord )
+ {
+ // With the fix for #101329#, UpdateRef always puts cells into pRefUndoDoc at their old position,
+ // so it's no longer necessary to copy more than the deleted range into pUndoDoc.
+
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, 0, nTabCount-1, (eCmd==DEL_DELCOLS), (eCmd==DEL_DELROWS) );
+ for( i=0; i<nTabCount; i++ )
+ {
+ if( aMark.GetTableSelect( i ) )
+ {
+ SCTAB nScenarioCount = 0;
+
+ for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
+ nScenarioCount ++;
+
+ pDoc->CopyToDocument( nUndoStartX, nUndoStartY, i, nUndoEndX, nUndoEndY, i+nScenarioCount,
+ IDF_ALL | IDF_NOCAPTIONS, FALSE, pUndoDoc );
+ }
+ }
+
+ pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, FALSE, FALSE );
+
+ pUndoData = new ScRefUndoData( pDoc );
+
+ pDoc->BeginDrawUndo();
+ }
+
+ USHORT nExtFlags = 0;
+ for( i=0; i<nTabCount; i++ )
+ {
+ if( aMark.GetTableSelect( i ) )
+ rDocShell.UpdatePaintExt( nExtFlags, nStartCol, nStartRow, i, nEndCol, nEndRow, i );
+ }
+
+ BOOL bUndoOutline = FALSE;
+ switch (eCmd)
+ {
+ case DEL_CELLSUP:
+ pDoc->DeleteRow( nStartCol, 0, nEndCol, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, NULL, &aFullMark );
+ nPaintEndY = MAXROW;
+ break;
+ case DEL_DELROWS:
+ pDoc->DeleteRow( 0, 0, MAXCOL, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &bUndoOutline, &aFullMark );
+ nPaintStartX = 0;
+ nPaintEndX = MAXCOL;
+ nPaintEndY = MAXROW;
+ nPaintFlags |= PAINT_LEFT;
+ break;
+ case DEL_CELLSLEFT:
+ pDoc->DeleteCol( nStartRow, 0, nEndRow, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, NULL, &aFullMark );
+ nPaintEndX = MAXCOL;
+ break;
+ case DEL_DELCOLS:
+ pDoc->DeleteCol( 0, 0, MAXROW, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &bUndoOutline, &aFullMark );
+ nPaintStartY = 0;
+ nPaintEndY = MAXROW;
+ nPaintEndX = MAXCOL;
+ nPaintFlags |= PAINT_TOP;
+ break;
+ default:
+ DBG_ERROR("Falscher Code beim Loeschen");
+ break;
+ }
+
+ //! Test, ob Outline in Groesse geaendert
+
+ if ( bRecord )
+ {
+ for( i=0; i<nTabCount; i++ )
+ if( aFullMark.GetTableSelect( i ) )
+ pRefUndoDoc->DeleteAreaTab(nUndoStartX,nUndoStartY,nUndoEndX,nUndoEndY, i, IDF_ALL);
+
+ // alle Tabellen anlegen, damit Formeln kopiert werden koennen:
+ pUndoDoc->AddUndoTab( 0, nTabCount-1, FALSE, FALSE );
+
+ // kopieren mit bColRowFlags=FALSE (#54194#)
+ pRefUndoDoc->CopyToDocument(0,0,0,MAXCOL,MAXROW,MAXTAB,IDF_FORMULA,FALSE,pUndoDoc,NULL,FALSE);
+ delete pRefUndoDoc;
+
+ SCTAB* pTabs = new SCTAB[nSelCount];
+ SCTAB* pScenarios = new SCTAB[nSelCount];
+ SCTAB nUndoPos = 0;
+
+ for( i=0; i<nTabCount; i++ )
+ {
+ if( aMark.GetTableSelect( i ) )
+ {
+ SCTAB nCount = 0;
+ for( SCTAB j=i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
+ nCount ++;
+
+ pScenarios[nUndoPos] = nCount;
+ pTabs[nUndoPos] = i;
+ nUndoPos ++;
+ }
+ }
+
+ if( !bDeletingMerge )
+ {
+ rDocShell.GetUndoManager()->LeaveListAction();
+ }
+
+ rDocShell.GetUndoManager()->AddUndoAction( new ScUndoDeleteCells(
+ &rDocShell, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ),nUndoPos, pTabs, pScenarios,
+ eCmd, pUndoDoc, pUndoData ) );
+ }
+
+ // #i8302 want to be able to insert into the middle of merged cells
+ // the patch comes from maoyg
+
+ while( !qDecreaseRange.empty() )
+ {
+ ScRange aRange = qDecreaseRange.back();
+
+ long nDecreaseRowCount = 0;
+ long nDecreaseColCount = 0;
+ if( eCmd == DEL_CELLSUP || eCmd == DEL_DELROWS )
+ {
+ if( nStartRow >= aRange.aStart.Row() && nStartRow <= aRange.aEnd.Row() && nEndRow>= aRange.aStart.Row() && nEndRow <= aRange.aEnd.Row() )
+ nDecreaseRowCount = nEndRow-nStartRow+1;
+ else if( nStartRow >= aRange.aStart.Row() && nStartRow <= aRange.aEnd.Row() && nEndRow >= aRange.aStart.Row() && nEndRow >= aRange.aEnd.Row() )
+ nDecreaseRowCount = aRange.aEnd.Row()-nStartRow+1;
+ else if( nStartRow >= aRange.aStart.Row() && nStartRow >= aRange.aEnd.Row() && nEndRow>= aRange.aStart.Row() && nEndRow <= aRange.aEnd.Row() )
+ nDecreaseRowCount = aRange.aEnd.Row()-nEndRow+1;
+ }
+ else if( eCmd == DEL_CELLSLEFT || eCmd == DEL_DELCOLS )
+ {
+ if( nStartCol >= aRange.aStart.Col() && nStartCol <= aRange.aEnd.Col() && nEndCol>= aRange.aStart.Col() && nEndCol <= aRange.aEnd.Col() )
+ nDecreaseColCount = nEndCol-nStartCol+1;
+ else if( nStartCol >= aRange.aStart.Col() && nStartCol <= aRange.aEnd.Col() && nEndCol >= aRange.aStart.Col() && nEndCol >= aRange.aEnd.Col() )
+ nDecreaseColCount = aRange.aEnd.Col()-nStartCol+1;
+ else if( nStartCol >= aRange.aStart.Col() && nStartCol >= aRange.aEnd.Col() && nEndCol>= aRange.aStart.Col() && nEndCol <= aRange.aEnd.Col() )
+ nDecreaseColCount = aRange.aEnd.Col()-nEndCol+1;
+ }
+
+ switch (eCmd)
+ {
+ case DEL_CELLSUP:
+ case DEL_DELROWS:
+ aRange.aEnd.SetRow(static_cast<SCsCOL>( aRange.aEnd.Row()-nDecreaseRowCount));
+ break;
+ case DEL_CELLSLEFT:
+ case DEL_DELCOLS:
+ aRange.aEnd.SetCol(static_cast<SCsCOL>( aRange.aEnd.Col()-nDecreaseColCount));
+ break;
+ default:
+ break;
+ }
+
+ if( !pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
+ {
+ MergeCells( aRange, FALSE, TRUE, TRUE );
+ }
+ qDecreaseRange.pop_back();
+ }
+
+ if( bDeletingMerge )
+ rDocShell.GetUndoManager()->LeaveListAction();
+
+ if ( bNeedRefresh )
+ {
+ // #i51445# old merge flag attributes must be deleted also for single cells,
+ // not only for whole columns/rows
+
+ if ( eCmd==DEL_DELCOLS || eCmd==DEL_CELLSLEFT )
+ nMergeTestEndX = MAXCOL;
+ if ( eCmd==DEL_DELROWS || eCmd==DEL_CELLSUP )
+ nMergeTestEndY = MAXROW;
+ ScPatternAttr aPattern( pDoc->GetPool() );
+ aPattern.GetItemSet().Put( ScMergeFlagAttr() );
+
+ pDoc->ApplyPatternArea( nExtendStartCol, nExtendStartRow, nMergeTestEndX, nMergeTestEndY, aMark, aPattern );
+
+ for( i=0; i<nTabCount; i++ )
+ {
+ if( aMark.GetTableSelect( i ) )
+ {
+ SCTAB nScenarioCount = 0;
+
+ for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
+ nScenarioCount ++;
+
+ ScRange aMergedRange( nExtendStartCol, nExtendStartRow, i, nMergeTestEndX, nMergeTestEndY, i+nScenarioCount );
+ pDoc->ExtendMerge( aMergedRange, TRUE );
+ }
+ }
+ }
+
+ for( i=0; i<nTabCount; i++ )
+ {
+ if( aMark.GetTableSelect( i ) )
+ {
+ if ( eCmd == DEL_DELCOLS || eCmd == DEL_DELROWS )
+ pDoc->UpdatePageBreaks( i );
+
+ rDocShell.UpdatePaintExt( nExtFlags, nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i );
+
+ SCTAB nScenarioCount = 0;
+
+ for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
+ nScenarioCount ++;
+
+ // ganze Zeilen loeschen: nichts anpassen
+ if ( eCmd == DEL_DELROWS || !AdjustRowHeight(ScRange( 0, nPaintStartY, i, MAXCOL, nPaintEndY, i+nScenarioCount )) )
+ rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, nPaintFlags, nExtFlags );
+ else
+ {
+ // paint only what is not done by AdjustRowHeight
+ if (nExtFlags & SC_PF_LINES)
+ lcl_PaintAbove( rDocShell, ScRange( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount) );
+ if (nPaintFlags & PAINT_TOP)
+ rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, PAINT_TOP );
+ }
+ }
+ }
+ aModificator.SetDocumentModified();
+
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
+
+ return TRUE;
+}
+
+BOOL ScDocFunc::MoveBlock( const ScRange& rSource, const ScAddress& rDestPos,
+ BOOL bCut, BOOL bRecord, BOOL bPaint, BOOL bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ SCCOL nStartCol = rSource.aStart.Col();
+ SCROW nStartRow = rSource.aStart.Row();
+ SCTAB nStartTab = rSource.aStart.Tab();
+ SCCOL nEndCol = rSource.aEnd.Col();
+ SCROW nEndRow = rSource.aEnd.Row();
+ SCTAB nEndTab = rSource.aEnd.Tab();
+ SCCOL nDestCol = rDestPos.Col();
+ SCROW nDestRow = rDestPos.Row();
+ SCTAB nDestTab = rDestPos.Tab();
+
+ if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) || !ValidRow(nDestRow) )
+ {
+ DBG_ERROR("invalid row in MoveBlock");
+ return FALSE;
+ }
+
+ // zugehoerige Szenarien auch anpassen - nur wenn innerhalb einer Tabelle verschoben wird!
+ BOOL bScenariosAdded = FALSE;
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+
+ SCTAB nTabCount = pDoc->GetTableCount();
+ if ( nDestTab == nStartTab && !pDoc->IsScenario(nEndTab) )
+ while ( nEndTab+1 < nTabCount && pDoc->IsScenario(nEndTab+1) )
+ {
+ ++nEndTab;
+ bScenariosAdded = TRUE;
+ }
+
+ SCTAB nSrcTabCount = nEndTab-nStartTab+1;
+ SCTAB nDestEndTab = nDestTab+nSrcTabCount-1;
+ SCTAB nTab;
+
+ ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
+
+ ScMarkData aSourceMark;
+ for (nTab=nStartTab; nTab<=nEndTab; nTab++)
+ aSourceMark.SelectTable( nTab, TRUE ); // Source selektieren
+ aSourceMark.SetMarkArea( rSource );
+
+ ScDocShellRef aDragShellRef;
+ if ( pDoc->HasOLEObjectsInArea( rSource ) )
+ {
+ aDragShellRef = new ScDocShell; // DocShell needs a Ref immediately
+ aDragShellRef->DoInitNew(NULL);
+ }
+ ScDrawLayer::SetGlobalDrawPersist(aDragShellRef);
+
+ ScClipParam aClipParam(ScRange(nStartCol, nStartRow, 0, nEndCol, nEndRow, 0), bCut);
+ pDoc->CopyToClip(aClipParam, pClipDoc, &aSourceMark, false, bScenariosAdded, true);
+
+ ScDrawLayer::SetGlobalDrawPersist(NULL);
+
+ SCCOL nOldEndCol = nEndCol;
+ SCROW nOldEndRow = nEndRow;
+ BOOL bClipOver = FALSE;
+ for (nTab=nStartTab; nTab<=nEndTab; nTab++)
+ {
+ SCCOL nTmpEndCol = nOldEndCol;
+ SCROW nTmpEndRow = nOldEndRow;
+ if (pDoc->ExtendMerge( nStartCol, nStartRow, nTmpEndCol, nTmpEndRow, nTab ))
+ bClipOver = TRUE;
+ if ( nTmpEndCol > nEndCol ) nEndCol = nTmpEndCol;
+ if ( nTmpEndRow > nEndRow ) nEndRow = nTmpEndRow;
+ }
+
+ SCCOL nDestEndCol = nDestCol + ( nOldEndCol-nStartCol );
+ SCROW nDestEndRow = nDestRow + ( nOldEndRow-nStartRow );
+
+ SCCOL nUndoEndCol = nDestCol + ( nEndCol-nStartCol ); // erweitert im Zielblock
+ SCROW nUndoEndRow = nDestRow + ( nEndRow-nStartRow );
+
+ BOOL bIncludeFiltered = bCut;
+ if ( !bIncludeFiltered )
+ {
+ // adjust sizes to include only non-filtered rows
+
+ SCCOL nClipX;
+ SCROW nClipY;
+ pClipDoc->GetClipArea( nClipX, nClipY, FALSE );
+ SCROW nUndoAdd = nUndoEndRow - nDestEndRow;
+ nDestEndRow = nDestRow + nClipY;
+ nUndoEndRow = nDestEndRow + nUndoAdd;
+ }
+
+ if (!ValidCol(nUndoEndCol) || !ValidRow(nUndoEndRow))
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_PASTE_FULL);
+ delete pClipDoc;
+ return FALSE;
+ }
+
+ // Test auf Zellschutz
+
+ ScEditableTester aTester;
+ for (nTab=nDestTab; nTab<=nDestEndTab; nTab++)
+ aTester.TestBlock( pDoc, nTab, nDestCol,nDestRow, nUndoEndCol,nUndoEndRow );
+ if (bCut)
+ for (nTab=nStartTab; nTab<=nEndTab; nTab++)
+ aTester.TestBlock( pDoc, nTab, nStartCol,nStartRow, nEndCol,nEndRow );
+
+ if (!aTester.IsEditable())
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ delete pClipDoc;
+ return FALSE;
+ }
+
+ // Test auf zusammengefasste - beim Verschieben erst nach dem Loeschen
+
+ if (bClipOver && !bCut)
+ if (pDoc->HasAttrib( nDestCol,nDestRow,nDestTab, nUndoEndCol,nUndoEndRow,nDestEndTab,
+ HASATTR_MERGED | HASATTR_OVERLAPPED ))
+ { // "Zusammenfassen nicht verschachteln !"
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0);
+ delete pClipDoc;
+ return FALSE;
+ }
+
+ // Are there borders in the cells? (for painting)
+
+ USHORT nSourceExt = 0;
+ rDocShell.UpdatePaintExt( nSourceExt, nStartCol,nStartRow,nStartTab, nEndCol,nEndRow,nEndTab );
+ USHORT nDestExt = 0;
+ rDocShell.UpdatePaintExt( nDestExt, nDestCol,nDestRow,nDestTab, nDestEndCol,nDestEndRow,nDestEndTab );
+
+ //
+ // ausfuehren
+ //
+
+ ScDocument* pUndoDoc = NULL;
+ ScDocument* pRefUndoDoc = NULL;
+ ScRefUndoData* pUndoData = NULL;
+ if (bRecord)
+ {
+ BOOL bWholeCols = ( nStartRow == 0 && nEndRow == MAXROW );
+ BOOL bWholeRows = ( nStartCol == 0 && nEndCol == MAXCOL );
+ USHORT nUndoFlags = (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS;
+
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab, bWholeCols, bWholeRows );
+
+ if (bCut)
+ {
+ pDoc->CopyToDocument( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab,
+ nUndoFlags, FALSE, pUndoDoc );
+ pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, FALSE, FALSE );
+ }
+
+ if ( nDestTab != nStartTab )
+ pUndoDoc->AddUndoTab( nDestTab, nDestEndTab, bWholeCols, bWholeRows );
+ pDoc->CopyToDocument( nDestCol, nDestRow, nDestTab,
+ nDestEndCol, nDestEndRow, nDestEndTab,
+ nUndoFlags, FALSE, pUndoDoc );
+
+ pUndoData = new ScRefUndoData( pDoc );
+
+ pDoc->BeginDrawUndo();
+ }
+
+ BOOL bSourceHeight = FALSE; // Hoehen angepasst?
+ if (bCut)
+ {
+ ScMarkData aDelMark; // only for tables
+ for (nTab=nStartTab; nTab<=nEndTab; nTab++)
+ {
+ pDoc->DeleteAreaTab( nStartCol,nStartRow, nOldEndCol,nOldEndRow, nTab, IDF_ALL );
+ aDelMark.SelectTable( nTab, TRUE );
+ }
+ pDoc->DeleteObjectsInArea( nStartCol,nStartRow, nOldEndCol,nOldEndRow, aDelMark );
+
+ // Test auf zusammengefasste
+
+ if (bClipOver)
+ if (pDoc->HasAttrib( nDestCol,nDestRow,nDestTab,
+ nUndoEndCol,nUndoEndRow,nDestEndTab,
+ HASATTR_MERGED | HASATTR_OVERLAPPED ))
+ {
+ pDoc->CopyFromClip( rSource, aSourceMark, IDF_ALL, pRefUndoDoc, pClipDoc );
+ for (nTab=nStartTab; nTab<=nEndTab; nTab++)
+ {
+ SCCOL nTmpEndCol = nEndCol;
+ SCROW nTmpEndRow = nEndRow;
+ pDoc->ExtendMerge( nStartCol, nStartRow, nTmpEndCol, nTmpEndRow, nTab, TRUE );
+ }
+
+ // Fehlermeldung erst nach dem Wiederherstellen des Inhalts
+ if (!bApi) // "Zusammenfassen nicht verschachteln !"
+ rDocShell.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0);
+
+ delete pUndoDoc;
+ delete pRefUndoDoc;
+ delete pUndoData;
+ delete pClipDoc;
+ return FALSE;
+ }
+
+ bSourceHeight = AdjustRowHeight( rSource, FALSE );
+ }
+
+ ScRange aPasteDest( nDestCol, nDestRow, nDestTab, nDestEndCol, nDestEndRow, nDestEndTab );
+
+ ScMarkData aDestMark;
+ for (nTab=nDestTab; nTab<=nDestEndTab; nTab++)
+ aDestMark.SelectTable( nTab, TRUE ); // Destination selektieren
+ aDestMark.SetMarkArea( aPasteDest );
+
+ /* Do not copy cell notes and drawing objects here. While pasting, the
+ function ScDocument::UpdateReference() is called which calls
+ ScDrawLayer::MoveCells() which may move away inserted objects to wrong
+ positions (e.g. if source and destination range overlaps). Cell notes
+ and drawing objects are pasted below after doing all adjusting. */
+ pDoc->CopyFromClip( aPasteDest, aDestMark, IDF_ALL & ~(IDF_NOTE | IDF_OBJECTS),
+ pRefUndoDoc, pClipDoc, TRUE, FALSE, bIncludeFiltered );
+
+ // skipped rows and merged cells don't mix
+ if ( !bIncludeFiltered && pClipDoc->HasClipFilteredRows() )
+ UnmergeCells( aPasteDest, FALSE, TRUE );
+
+ VirtualDevice aVirtDev;
+ BOOL bDestHeight = AdjustRowHeight(
+ ScRange( 0,nDestRow,nDestTab, MAXCOL,nDestEndRow,nDestEndTab ),
+ FALSE );
+
+ /* Paste cell notes and drawing objects after adjusting formula references
+ and row heights. There are no cell notes or drawing objects, if the
+ clipdoc does not contain a drawing layer.
+ #i102056# Passing IDF_NOTE only would overwrite cell contents with
+ empty note cells, therefore the special modifier IDF_ADDNOTES is passed
+ here too which changes the behaviour of ScColumn::CopyFromClip() to not
+ touch existing cells. */
+ if ( pClipDoc->GetDrawLayer() )
+ pDoc->CopyFromClip( aPasteDest, aDestMark, IDF_NOTE | IDF_ADDNOTES | IDF_OBJECTS,
+ pRefUndoDoc, pClipDoc, TRUE, FALSE, bIncludeFiltered );
+
+ if (bRecord)
+ {
+ if (pRefUndoDoc)
+ {
+ // alle Tabellen anlegen, damit Formeln kopiert werden koennen:
+ pUndoDoc->AddUndoTab( 0, nTabCount-1, FALSE, FALSE );
+
+ pRefUndoDoc->DeleteArea( nDestCol, nDestRow, nDestEndCol, nDestEndRow, aSourceMark, IDF_ALL );
+ // kopieren mit bColRowFlags=FALSE (#54194#)
+ pRefUndoDoc->CopyToDocument( 0, 0, 0, MAXCOL, MAXROW, MAXTAB,
+ IDF_FORMULA, FALSE, pUndoDoc, NULL, FALSE );
+ delete pRefUndoDoc;
+ }
+
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDragDrop( &rDocShell, ScRange(
+ nStartCol, nStartRow, nStartTab,
+ nOldEndCol, nOldEndRow, nEndTab ),
+ ScAddress( nDestCol, nDestRow, nDestTab ),
+ bCut, pUndoDoc, pUndoData, bScenariosAdded ) );
+ }
+
+ SCCOL nDestPaintEndCol = nDestEndCol;
+ SCROW nDestPaintEndRow = nDestEndRow;
+ for (nTab=nDestTab; nTab<=nDestEndTab; nTab++)
+ {
+ SCCOL nTmpEndCol = nDestEndCol;
+ SCROW nTmpEndRow = nDestEndRow;
+ pDoc->ExtendMerge( nDestCol, nDestRow, nTmpEndCol, nTmpEndRow, nTab, TRUE );
+ if (nTmpEndCol > nDestPaintEndCol) nDestPaintEndCol = nTmpEndCol;
+ if (nTmpEndRow > nDestPaintEndRow) nDestPaintEndRow = nTmpEndRow;
+ }
+
+ if (bCut)
+ for (nTab=nStartTab; nTab<=nEndTab; nTab++)
+ pDoc->RefreshAutoFilter( nStartCol, nStartRow, nEndCol, nEndRow, nTab );
+
+ if (bPaint)
+ {
+ // Zielbereich:
+
+ SCCOL nPaintStartX = nDestCol;
+ SCROW nPaintStartY = nDestRow;
+ SCCOL nPaintEndX = nDestPaintEndCol;
+ SCROW nPaintEndY = nDestPaintEndRow;
+ USHORT nFlags = PAINT_GRID;
+
+ if ( nStartRow==0 && nEndRow==MAXROW ) // Breiten mitkopiert?
+ {
+ nPaintEndX = MAXCOL;
+ nPaintStartY = 0;
+ nPaintEndY = MAXROW;
+ nFlags |= PAINT_TOP;
+ }
+ if ( bDestHeight || ( nStartCol == 0 && nEndCol == MAXCOL ) )
+ {
+ nPaintEndY = MAXROW;
+ nPaintStartX = 0;
+ nPaintEndX = MAXCOL;
+ nFlags |= PAINT_LEFT;
+ }
+ if ( bScenariosAdded )
+ {
+ nPaintStartX = 0;
+ nPaintStartY = 0;
+ nPaintEndX = MAXCOL;
+ nPaintEndY = MAXROW;
+ }
+
+ rDocShell.PostPaint( nPaintStartX,nPaintStartY,nDestTab,
+ nPaintEndX,nPaintEndY,nDestEndTab, nFlags, nSourceExt | nDestExt );
+
+ if ( bCut )
+ {
+ // Quellbereich:
+
+ nPaintStartX = nStartCol;
+ nPaintStartY = nStartRow;
+ nPaintEndX = nEndCol;
+ nPaintEndY = nEndRow;
+ nFlags = PAINT_GRID;
+
+ if ( bSourceHeight )
+ {
+ nPaintEndY = MAXROW;
+ nPaintStartX = 0;
+ nPaintEndX = MAXCOL;
+ nFlags |= PAINT_LEFT;
+ }
+ if ( bScenariosAdded )
+ {
+ nPaintStartX = 0;
+ nPaintStartY = 0;
+ nPaintEndX = MAXCOL;
+ nPaintEndY = MAXROW;
+ }
+
+ rDocShell.PostPaint( nPaintStartX,nPaintStartY,nStartTab,
+ nPaintEndX,nPaintEndY,nEndTab, nFlags, nSourceExt );
+ }
+ }
+
+ aModificator.SetDocumentModified();
+
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
+
+ delete pClipDoc;
+ return TRUE;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScDocFunc::InsertTable( SCTAB nTab, const String& rName, BOOL bRecord, BOOL bApi )
+{
+ BOOL bSuccess = FALSE;
+ WaitObject aWait( rDocShell.GetActiveDialogParent() );
+
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+ if (bRecord)
+ pDoc->BeginDrawUndo(); // InsertTab erzeugt ein SdrUndoNewPage
+
+ SCTAB nTabCount = pDoc->GetTableCount();
+ BOOL bAppend = ( nTab >= nTabCount );
+ if ( bAppend )
+ nTab = nTabCount; // wichtig fuer Undo
+
+ if (pDoc->InsertTab( nTab, rName ))
+ {
+ if (bRecord)
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoInsertTab( &rDocShell, nTab, bAppend, rName));
+ // Views updaten:
+ rDocShell.Broadcast( ScTablesHint( SC_TAB_INSERTED, nTab ) );
+
+ rDocShell.PostPaintExtras();
+ aModificator.SetDocumentModified();
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
+ bSuccess = TRUE;
+ }
+ else if (!bApi)
+ rDocShell.ErrorMessage(STR_TABINSERT_ERROR);
+
+ return bSuccess;
+}
+
+BOOL ScDocFunc::DeleteTable( SCTAB nTab, BOOL bRecord, BOOL /* bApi */ )
+{
+ WaitObject aWait( rDocShell.GetActiveDialogParent() );
+
+ ScDocShellModificator aModificator( rDocShell );
+
+ BOOL bSuccess = FALSE;
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+ BOOL bWasLinked = pDoc->IsLinked(nTab);
+ ScDocument* pUndoDoc = NULL;
+ ScRefUndoData* pUndoData = NULL;
+ if (bRecord)
+ {
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ SCTAB nCount = pDoc->GetTableCount();
+
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, TRUE, TRUE ); // nur nTab mit Flags
+ pUndoDoc->AddUndoTab( 0, nCount-1 ); // alle Tabs fuer Referenzen
+
+ pDoc->CopyToDocument(0,0,nTab, MAXCOL,MAXROW,nTab, IDF_ALL,FALSE, pUndoDoc );
+ String aOldName;
+ pDoc->GetName( nTab, aOldName );
+ pUndoDoc->RenameTab( nTab, aOldName, FALSE );
+ if (bWasLinked)
+ pUndoDoc->SetLink( nTab, pDoc->GetLinkMode(nTab), pDoc->GetLinkDoc(nTab),
+ pDoc->GetLinkFlt(nTab), pDoc->GetLinkOpt(nTab),
+ pDoc->GetLinkTab(nTab),
+ pDoc->GetLinkRefreshDelay(nTab) );
+
+ if ( pDoc->IsScenario(nTab) )
+ {
+ pUndoDoc->SetScenario( nTab, TRUE );
+ String aComment;
+ Color aColor;
+ USHORT nScenFlags;
+ pDoc->GetScenarioData( nTab, aComment, aColor, nScenFlags );
+ pUndoDoc->SetScenarioData( nTab, aComment, aColor, nScenFlags );
+ BOOL bActive = pDoc->IsActiveScenario( nTab );
+ pUndoDoc->SetActiveScenario( nTab, bActive );
+ }
+ pUndoDoc->SetVisible( nTab, pDoc->IsVisible( nTab ) );
+
+ // Drawing-Layer muss sein Undo selbst in der Hand behalten !!!
+ pDoc->BeginDrawUndo(); // DeleteTab erzeugt ein SdrUndoDelPage
+
+ pUndoData = new ScRefUndoData( pDoc );
+ }
+
+ if (pDoc->DeleteTab( nTab, pUndoDoc ))
+ {
+ if (bRecord)
+ {
+ SvShorts theTabs;
+ theTabs.Insert(nTab,theTabs.Count());
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDeleteTab( &rDocShell, theTabs, pUndoDoc, pUndoData ));
+ }
+ // Views updaten:
+ rDocShell.Broadcast( ScTablesHint( SC_TAB_DELETED, nTab ) );
+
+ if (bWasLinked)
+ {
+ rDocShell.UpdateLinks(); // Link-Manager updaten
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+ if (pBindings)
+ pBindings->Invalidate(SID_LINKS);
+ }
+
+ rDocShell.PostPaintExtras();
+ aModificator.SetDocumentModified();
+
+ SfxApplication* pSfxApp = SFX_APP(); // Navigator
+ pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
+ pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
+ pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
+
+ bSuccess = TRUE;
+ }
+ else
+ {
+ delete pUndoDoc;
+ delete pUndoData;
+ }
+ return bSuccess;
+}
+
+BOOL ScDocFunc::SetTableVisible( SCTAB nTab, BOOL bVisible, BOOL bApi )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+ BOOL bUndo(pDoc->IsUndoEnabled());
+ if ( pDoc->IsVisible( nTab ) == bVisible )
+ return TRUE; // nichts zu tun - ok
+
+ if ( !pDoc->IsDocEditable() )
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_PROTECTIONERR);
+ return FALSE;
+ }
+
+ ScDocShellModificator aModificator( rDocShell );
+
+ if ( !bVisible && !pDoc->IsImportingXML() ) // #i57869# allow hiding in any order for loading
+ {
+ // nicht alle Tabellen ausblenden
+
+ USHORT nVisCount = 0;
+ SCTAB nCount = pDoc->GetTableCount();
+ for (SCTAB i=0; i<nCount; i++)
+ if (pDoc->IsVisible(i))
+ ++nVisCount;
+
+ if (nVisCount <= 1)
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_PROTECTIONERR); //! eigene Meldung?
+ return FALSE;
+ }
+ }
+
+ pDoc->SetVisible( nTab, bVisible );
+ if (bUndo)
+ rDocShell.GetUndoManager()->AddUndoAction( new ScUndoShowHideTab( &rDocShell, nTab, bVisible ) );
+
+ // Views updaten:
+ if (!bVisible)
+ rDocShell.Broadcast( ScTablesHint( SC_TAB_HIDDEN, nTab ) );
+
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
+ rDocShell.PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS);
+ aModificator.SetDocumentModified();
+
+ return TRUE;
+}
+
+BOOL ScDocFunc::SetLayoutRTL( SCTAB nTab, BOOL bRTL, BOOL /* bApi */ )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+ BOOL bUndo(pDoc->IsUndoEnabled());
+ if ( pDoc->IsLayoutRTL( nTab ) == bRTL )
+ return TRUE; // nothing to do - ok
+
+ //! protection (sheet or document?)
+
+ ScDocShellModificator aModificator( rDocShell );
+
+ pDoc->SetLayoutRTL( nTab, bRTL );
+
+ if (bUndo)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction( new ScUndoLayoutRTL( &rDocShell, nTab, bRTL ) );
+ }
+
+ rDocShell.PostPaint( 0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_ALL );
+ aModificator.SetDocumentModified();
+
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+ if (pBindings)
+ {
+ pBindings->Invalidate( FID_TAB_RTL );
+ pBindings->Invalidate( SID_ATTR_SIZE );
+ }
+
+ return TRUE;
+}
+
+//UNUSED2009-05 BOOL ScDocFunc::SetGrammar( formula::FormulaGrammar::Grammar eGrammar )
+//UNUSED2009-05 {
+//UNUSED2009-05 ScDocument* pDoc = rDocShell.GetDocument();
+//UNUSED2009-05
+//UNUSED2009-05 if ( pDoc->GetGrammar() == eGrammar )
+//UNUSED2009-05 return TRUE;
+//UNUSED2009-05
+//UNUSED2009-05 BOOL bUndo(pDoc->IsUndoEnabled());
+//UNUSED2009-05 ScDocShellModificator aModificator( rDocShell );
+//UNUSED2009-05
+//UNUSED2009-05 pDoc->SetGrammar( eGrammar );
+//UNUSED2009-05
+//UNUSED2009-05 if (bUndo)
+//UNUSED2009-05 {
+//UNUSED2009-05 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoSetGrammar( &rDocShell, eGrammar ) );
+//UNUSED2009-05 }
+//UNUSED2009-05
+//UNUSED2009-05 rDocShell.PostPaint( 0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_ALL );
+//UNUSED2009-05
+//UNUSED2009-05 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
+//UNUSED2009-05 if (NULL != pViewSh)
+//UNUSED2009-05 {
+//UNUSED2009-05 pViewSh->UpdateInputHandler( FALSE, FALSE );
+//UNUSED2009-05 }
+//UNUSED2009-05
+//UNUSED2009-05 aModificator.SetDocumentModified();
+//UNUSED2009-05
+//UNUSED2009-05 SfxBindings* pBindings = rDocShell.GetViewBindings();
+//UNUSED2009-05 if (pBindings)
+//UNUSED2009-05 {
+//UNUSED2009-05 // erAck: 2006-09-07T22:19+0200 commented out in CWS scr1c1
+//UNUSED2009-05 //pBindings->Invalidate( FID_TAB_USE_R1C1 );
+//UNUSED2009-05 }
+//UNUSED2009-05
+//UNUSED2009-05 return TRUE;
+//UNUSED2009-05 }
+
+BOOL ScDocFunc::RenameTable( SCTAB nTab, const String& rName, BOOL bRecord, BOOL bApi )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+ if ( !pDoc->IsDocEditable() )
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_PROTECTIONERR);
+ return FALSE;
+ }
+
+ ScDocShellModificator aModificator( rDocShell );
+
+ BOOL bSuccess = FALSE;
+ String sOldName;
+ pDoc->GetName(nTab, sOldName);
+ if (pDoc->RenameTab( nTab, rName ))
+ {
+ if (bRecord)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoRenameTab( &rDocShell, nTab, sOldName, rName));
+ }
+ rDocShell.PostPaintExtras();
+ aModificator.SetDocumentModified();
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
+
+ bSuccess = TRUE;
+ }
+ return bSuccess;
+}
+
+//------------------------------------------------------------------------
+
+//! SetWidthOrHeight - noch doppelt zu ViewFunc !!!!!!
+//! Probleme:
+//! - Optimale Hoehe fuer Edit-Zellen ist unterschiedlich zwischen Drucker und Bildschirm
+//! - Optimale Breite braucht Selektion, um evtl. nur selektierte Zellen zu beruecksichtigen
+
+USHORT lcl_GetOptimalColWidth( ScDocShell& rDocShell, SCCOL nCol, SCTAB nTab, BOOL bFormula )
+{
+ USHORT nTwips = 0;
+
+ ScSizeDeviceProvider aProv(&rDocShell);
+ OutputDevice* pDev = aProv.GetDevice(); // has pixel MapMode
+ double nPPTX = aProv.GetPPTX();
+ double nPPTY = aProv.GetPPTY();
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ Fraction aOne(1,1);
+ nTwips = pDoc->GetOptimalColWidth( nCol, nTab, pDev, nPPTX, nPPTY, aOne, aOne,
+ bFormula, NULL );
+
+ return nTwips;
+}
+
+BOOL ScDocFunc::SetWidthOrHeight( BOOL bWidth, SCCOLROW nRangeCnt, SCCOLROW* pRanges, SCTAB nTab,
+ ScSizeMode eMode, USHORT nSizeTwips,
+ BOOL bRecord, BOOL bApi )
+{
+ if (!nRangeCnt)
+ return TRUE;
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if ( bRecord && !pDoc->IsUndoEnabled() )
+ bRecord = FALSE;
+
+ // import into read-only document is possible
+ if ( !pDoc->IsChangeReadOnlyEnabled() && !rDocShell.IsEditable() )
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_PROTECTIONERR); //! eigene Meldung?
+ return FALSE;
+ }
+
+ BOOL bSuccess = FALSE;
+ SCCOLROW nStart = pRanges[0];
+ SCCOLROW nEnd = pRanges[2*nRangeCnt-1];
+
+ BOOL bFormula = FALSE;
+ if ( eMode == SC_SIZE_OPTIMAL )
+ {
+ //! Option "Formeln anzeigen" - woher nehmen?
+ }
+
+ ScDocument* pUndoDoc = NULL;
+ ScOutlineTable* pUndoTab = NULL;
+ SCCOLROW* pUndoRanges = NULL;
+
+ if ( bRecord )
+ {
+ pDoc->BeginDrawUndo(); // Drawing Updates
+
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ if (bWidth)
+ {
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, TRUE, FALSE );
+ pDoc->CopyToDocument( static_cast<SCCOL>(nStart), 0, nTab, static_cast<SCCOL>(nEnd), MAXROW, nTab, IDF_NONE, FALSE, pUndoDoc );
+ }
+ else
+ {
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, FALSE, TRUE );
+ pDoc->CopyToDocument( 0, static_cast<SCROW>(nStart), nTab, MAXCOL, static_cast<SCROW>(nEnd), nTab, IDF_NONE, FALSE, pUndoDoc );
+ }
+
+ pUndoRanges = new SCCOLROW[ 2*nRangeCnt ];
+ memmove( pUndoRanges, pRanges, 2*nRangeCnt*sizeof(SCCOLROW) );
+
+ ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
+ if (pTable)
+ pUndoTab = new ScOutlineTable( *pTable );
+ }
+
+ BOOL bShow = nSizeTwips > 0 || eMode != SC_SIZE_DIRECT;
+ BOOL bOutline = FALSE;
+
+ pDoc->IncSizeRecalcLevel( nTab ); // nicht fuer jede Spalte einzeln
+ for (SCCOLROW nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
+ {
+ SCCOLROW nStartNo = *(pRanges++);
+ SCCOLROW nEndNo = *(pRanges++);
+
+ if ( !bWidth ) // Hoehen immer blockweise
+ {
+ if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
+ {
+ BOOL bAll = ( eMode==SC_SIZE_OPTIMAL );
+ if (!bAll)
+ {
+ // fuer alle eingeblendeten CR_MANUALSIZE loeschen,
+ // dann SetOptimalHeight mit bShrink = FALSE
+ for (SCROW nRow=nStartNo; nRow<=nEndNo; nRow++)
+ {
+ BYTE nOld = pDoc->GetRowFlags(nRow,nTab);
+ if ( (nOld & CR_HIDDEN) == 0 && ( nOld & CR_MANUALSIZE ) )
+ pDoc->SetRowFlags( nRow, nTab, nOld & ~CR_MANUALSIZE );
+ }
+ }
+
+ ScSizeDeviceProvider aProv( &rDocShell );
+ Fraction aOne(1,1);
+ pDoc->SetOptimalHeight( nStartNo, nEndNo, nTab, 0, aProv.GetDevice(),
+ aProv.GetPPTX(), aProv.GetPPTY(), aOne, aOne, bAll );
+
+ if (bAll)
+ pDoc->ShowRows( nStartNo, nEndNo, nTab, TRUE );
+
+ // Manual-Flag wird bei bAll=TRUE schon in SetOptimalHeight gesetzt
+ // (an bei Extra-Height, sonst aus).
+ }
+ else if ( eMode==SC_SIZE_DIRECT || eMode==SC_SIZE_ORIGINAL )
+ {
+ if (nSizeTwips)
+ {
+ pDoc->SetRowHeightRange( nStartNo, nEndNo, nTab, nSizeTwips );
+ pDoc->SetManualHeight( nStartNo, nEndNo, nTab, TRUE ); // height was set manually
+ }
+ if ( eMode != SC_SIZE_ORIGINAL )
+ pDoc->ShowRows( nStartNo, nEndNo, nTab, nSizeTwips != 0 );
+ }
+ else if ( eMode==SC_SIZE_SHOW )
+ {
+ pDoc->ShowRows( nStartNo, nEndNo, nTab, TRUE );
+ }
+ }
+ else // Spaltenbreiten
+ {
+ for (SCCOL nCol=static_cast<SCCOL>(nStartNo); nCol<=static_cast<SCCOL>(nEndNo); nCol++)
+ {
+ if ( eMode != SC_SIZE_VISOPT ||
+ (pDoc->GetColFlags( nCol, nTab ) & CR_HIDDEN) == 0 )
+ {
+ USHORT nThisSize = nSizeTwips;
+
+ if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
+ nThisSize = nSizeTwips +
+ lcl_GetOptimalColWidth( rDocShell, nCol, nTab, bFormula );
+ if ( nThisSize )
+ pDoc->SetColWidth( nCol, nTab, nThisSize );
+
+ if ( eMode != SC_SIZE_ORIGINAL )
+ pDoc->ShowCol( nCol, nTab, bShow );
+ }
+ }
+ }
+
+ // adjust outlines
+
+ if ( eMode != SC_SIZE_ORIGINAL )
+ {
+ if (bWidth)
+ bOutline = bOutline || pDoc->UpdateOutlineCol(
+ static_cast<SCCOL>(nStartNo),
+ static_cast<SCCOL>(nEndNo), nTab, bShow );
+ else
+ bOutline = bOutline || pDoc->UpdateOutlineRow(
+ static_cast<SCROW>(nStartNo),
+ static_cast<SCROW>(nEndNo), nTab, bShow );
+ }
+ }
+ pDoc->DecSizeRecalcLevel( nTab ); // nicht fuer jede Spalte einzeln
+
+ if (!bOutline)
+ DELETEZ(pUndoTab);
+
+ if (bRecord)
+ {
+ ScMarkData aMark;
+ aMark.SelectOneTable( nTab );
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoWidthOrHeight( &rDocShell, aMark,
+ nStart, nTab, nEnd, nTab,
+ pUndoDoc, nRangeCnt, pUndoRanges,
+ pUndoTab, eMode, nSizeTwips, bWidth ) );
+ }
+
+ pDoc->UpdatePageBreaks( nTab );
+
+ rDocShell.PostPaint(0,0,nTab,MAXCOL,MAXROW,nTab,PAINT_ALL);
+
+ return bSuccess;
+}
+
+
+BOOL ScDocFunc::InsertPageBreak( BOOL bColumn, const ScAddress& rPos,
+ BOOL bRecord, BOOL bSetModified, BOOL /* bApi */ )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+ SCTAB nTab = rPos.Tab();
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+
+ SCCOLROW nPos = bColumn ? static_cast<SCCOLROW>(rPos.Col()) :
+ static_cast<SCCOLROW>(rPos.Row());
+ if (nPos == 0)
+ return FALSE; // erste Spalte / Zeile
+
+ BYTE nFlags = bColumn ? pDoc->GetColFlags( static_cast<SCCOL>(nPos), nTab )
+ : pDoc->GetRowFlags( static_cast<SCROW>(nPos), nTab );
+ if (nFlags & CR_MANUALBREAK)
+ return TRUE; // Umbruch schon gesetzt
+
+ if (bRecord)
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoPageBreak( &rDocShell, rPos.Col(), rPos.Row(), nTab, bColumn, TRUE ) );
+
+ nFlags |= CR_MANUALBREAK;
+ if (bColumn)
+ pDoc->SetColFlags( static_cast<SCCOL>(nPos), nTab, nFlags );
+ else
+ pDoc->SetRowFlags( static_cast<SCROW>(nPos), nTab, nFlags );
+ pDoc->UpdatePageBreaks( nTab );
+
+ if (pDoc->IsStreamValid(nTab))
+ pDoc->SetStreamValid(nTab, FALSE);
+
+ if (bColumn)
+ {
+ rDocShell.PostPaint( static_cast<SCCOL>(nPos)-1, 0, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
+ if (pBindings)
+ {
+ pBindings->Invalidate( FID_INS_COLBRK );
+ pBindings->Invalidate( FID_DEL_COLBRK );
+ }
+ }
+ else
+ {
+ rDocShell.PostPaint( 0, static_cast<SCROW>(nPos)-1, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
+ if (pBindings)
+ {
+ pBindings->Invalidate( FID_INS_ROWBRK );
+ pBindings->Invalidate( FID_DEL_ROWBRK );
+ }
+ }
+ if (pBindings)
+ pBindings->Invalidate( FID_DEL_MANUALBREAKS );
+
+ if (bSetModified)
+ aModificator.SetDocumentModified();
+
+ return TRUE;
+}
+
+BOOL ScDocFunc::RemovePageBreak( BOOL bColumn, const ScAddress& rPos,
+ BOOL bRecord, BOOL bSetModified, BOOL /* bApi */ )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+ SCTAB nTab = rPos.Tab();
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+
+ SCCOLROW nPos = bColumn ? static_cast<SCCOLROW>(rPos.Col()) :
+ static_cast<SCCOLROW>(rPos.Row());
+ BYTE nFlags = bColumn ? pDoc->GetColFlags( static_cast<SCCOL>(nPos), nTab )
+ : pDoc->GetRowFlags( static_cast<SCROW>(nPos), nTab );
+ if ((nFlags & CR_MANUALBREAK)==0)
+ return FALSE; // kein Umbruch gesetzt
+
+ if (bRecord)
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoPageBreak( &rDocShell, rPos.Col(), rPos.Row(), nTab, bColumn, FALSE ) );
+
+ nFlags &= ~CR_MANUALBREAK;
+ if (bColumn)
+ pDoc->SetColFlags( static_cast<SCCOL>(nPos), nTab, nFlags );
+ else
+ pDoc->SetRowFlags( static_cast<SCROW>(nPos), nTab, nFlags );
+ pDoc->UpdatePageBreaks( nTab );
+
+ if (pDoc->IsStreamValid(nTab))
+ pDoc->SetStreamValid(nTab, FALSE);
+
+ if (bColumn)
+ {
+ rDocShell.PostPaint( static_cast<SCCOL>(nPos)-1, 0, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
+ if (pBindings)
+ {
+ pBindings->Invalidate( FID_INS_COLBRK );
+ pBindings->Invalidate( FID_DEL_COLBRK );
+ }
+ }
+ else
+ {
+ rDocShell.PostPaint( 0, nPos-1, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
+ if (pBindings)
+ {
+ pBindings->Invalidate( FID_INS_ROWBRK );
+ pBindings->Invalidate( FID_DEL_ROWBRK );
+ }
+ }
+ if (pBindings)
+ pBindings->Invalidate( FID_DEL_MANUALBREAKS );
+
+ if (bSetModified)
+ aModificator.SetDocumentModified();
+
+ return TRUE;
+}
+
+//------------------------------------------------------------------------
+
+void ScDocFunc::ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ pDoc->SetTabProtection(nTab, &rProtect);
+ if (pDoc->IsUndoEnabled())
+ {
+ ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
+ DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScTableProtection pointer is NULL!");
+ if (pProtect)
+ {
+ ::std::auto_ptr<ScTableProtection> p(new ScTableProtection(*pProtect));
+ p->setProtected(true); // just in case ...
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoTabProtect(&rDocShell, nTab, p) );
+
+ // ownership of auto_ptr now transferred to ScUndoTabProtect.
+ }
+ }
+
+ rDocShell.PostPaintGridAll();
+ ScDocShellModificator aModificator(rDocShell);
+ aModificator.SetDocumentModified();
+}
+
+BOOL ScDocFunc::Protect( SCTAB nTab, const String& rPassword, BOOL /*bApi*/ )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if (nTab == TABLEID_DOC)
+ {
+ // document protection
+ ScDocProtection aProtection;
+ aProtection.setProtected(true);
+ aProtection.setPassword(rPassword);
+ pDoc->SetDocProtection(&aProtection);
+ if (pDoc->IsUndoEnabled())
+ {
+ ScDocProtection* pProtect = pDoc->GetDocProtection();
+ DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScDocProtection pointer is NULL!");
+ if (pProtect)
+ {
+ ::std::auto_ptr<ScDocProtection> p(new ScDocProtection(*pProtect));
+ p->setProtected(true); // just in case ...
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDocProtect(&rDocShell, p) );
+ // ownership of auto_ptr is transferred to ScUndoDocProtect.
+ }
+ }
+ }
+ else
+ {
+ // sheet protection
+
+ ScTableProtection aProtection;
+ aProtection.setProtected(true);
+ aProtection.setPassword(rPassword);
+ pDoc->SetTabProtection(nTab, &aProtection);
+ if (pDoc->IsUndoEnabled())
+ {
+ ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
+ DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScTableProtection pointer is NULL!");
+ if (pProtect)
+ {
+ ::std::auto_ptr<ScTableProtection> p(new ScTableProtection(*pProtect));
+ p->setProtected(true); // just in case ...
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoTabProtect(&rDocShell, nTab, p) );
+ // ownership of auto_ptr now transferred to ScUndoTabProtect.
+ }
+ }
+ }
+
+ rDocShell.PostPaintGridAll();
+ ScDocShellModificator aModificator( rDocShell );
+ aModificator.SetDocumentModified();
+
+ return true;
+}
+
+BOOL ScDocFunc::Unprotect( SCTAB nTab, const String& rPassword, BOOL bApi )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ if (nTab == TABLEID_DOC)
+ {
+ // document protection
+
+ ScDocProtection* pDocProtect = pDoc->GetDocProtection();
+ if (!pDocProtect || !pDocProtect->isProtected())
+ // already unprotected (should not happen)!
+ return true;
+
+ // save the protection state before unprotect (for undo).
+ ::std::auto_ptr<ScDocProtection> pProtectCopy(new ScDocProtection(*pDocProtect));
+
+ if (!pDocProtect->verifyPassword(rPassword))
+ {
+ if (!bApi)
+ {
+ InfoBox aBox( rDocShell.GetActiveDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) );
+ aBox.Execute();
+ }
+ return false;
+ }
+
+ pDoc->SetDocProtection(NULL);
+ if (pDoc->IsUndoEnabled())
+ {
+ pProtectCopy->setProtected(false);
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDocProtect(&rDocShell, pProtectCopy) );
+ // ownership of auto_ptr now transferred to ScUndoDocProtect.
+ }
+ }
+ else
+ {
+ // sheet protection
+
+ ScTableProtection* pTabProtect = pDoc->GetTabProtection(nTab);
+ if (!pTabProtect || !pTabProtect->isProtected())
+ // already unprotected (should not happen)!
+ return true;
+
+ // save the protection state before unprotect (for undo).
+ ::std::auto_ptr<ScTableProtection> pProtectCopy(new ScTableProtection(*pTabProtect));
+ if (!pTabProtect->verifyPassword(rPassword))
+ {
+ if (!bApi)
+ {
+ InfoBox aBox( rDocShell.GetActiveDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) );
+ aBox.Execute();
+ }
+ return false;
+ }
+
+ pDoc->SetTabProtection(nTab, NULL);
+ if (pDoc->IsUndoEnabled())
+ {
+ pProtectCopy->setProtected(false);
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoTabProtect(&rDocShell, nTab, pProtectCopy) );
+ // ownership of auto_ptr now transferred to ScUndoTabProtect.
+ }
+ }
+
+ rDocShell.PostPaintGridAll();
+ ScDocShellModificator aModificator( rDocShell );
+ aModificator.SetDocumentModified();
+
+ return true;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScDocFunc::ClearItems( const ScMarkData& rMark, const USHORT* pWhich, BOOL bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ BOOL bUndo (pDoc->IsUndoEnabled());
+ ScEditableTester aTester( pDoc, rMark );
+ if (!aTester.IsEditable())
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ return FALSE;
+ }
+
+ // #i12940# ClearItems is called (from setPropertyToDefault) directly with uno object's cached
+ // MarkData (GetMarkData), so rMark must be changed to multi selection for ClearSelectionItems
+ // here.
+
+ ScRange aMarkRange;
+ ScMarkData aMultiMark = rMark;
+ aMultiMark.SetMarking(FALSE); // for MarkToMulti
+ aMultiMark.MarkToMulti();
+ aMultiMark.GetMultiMarkArea( aMarkRange );
+
+// if (bRecord)
+ if (bUndo)
+ {
+ SCTAB nStartTab = aMarkRange.aStart.Tab();
+ SCTAB nEndTab = aMarkRange.aEnd.Tab();
+
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab );
+ pDoc->CopyToDocument( aMarkRange, IDF_ATTRIB, TRUE, pUndoDoc, (ScMarkData*)&aMultiMark );
+
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoClearItems( &rDocShell, aMultiMark, pUndoDoc, pWhich ) );
+ }
+
+ pDoc->ClearSelectionItems( pWhich, aMultiMark );
+
+ rDocShell.PostPaint( aMarkRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
+ aModificator.SetDocumentModified();
+
+ //! Bindings-Invalidate etc.?
+
+ return TRUE;
+}
+
+BOOL ScDocFunc::ChangeIndent( const ScMarkData& rMark, BOOL bIncrement, BOOL bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ BOOL bUndo(pDoc->IsUndoEnabled());
+ ScEditableTester aTester( pDoc, rMark );
+ if (!aTester.IsEditable())
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ return FALSE;
+ }
+
+ ScRange aMarkRange;
+ rMark.GetMultiMarkArea( aMarkRange );
+
+// if (bRecord)
+ if (bUndo)
+ {
+ SCTAB nStartTab = aMarkRange.aStart.Tab();
+ SCTAB nTabCount = pDoc->GetTableCount();
+
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
+ for (SCTAB i=0; i<nTabCount; i++)
+ if (i != nStartTab && rMark.GetTableSelect(i))
+ pUndoDoc->AddUndoTab( i, i );
+
+ ScRange aCopyRange = aMarkRange;
+ aCopyRange.aStart.SetTab(0);
+ aCopyRange.aEnd.SetTab(nTabCount-1);
+ pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, TRUE, pUndoDoc, (ScMarkData*)&rMark );
+
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoIndent( &rDocShell, rMark, pUndoDoc, bIncrement ) );
+ }
+
+ pDoc->ChangeSelectionIndent( bIncrement, rMark );
+
+ rDocShell.PostPaint( aMarkRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
+ aModificator.SetDocumentModified();
+
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+ if (pBindings)
+ {
+ pBindings->Invalidate( SID_ALIGNLEFT ); // ChangeIndent setzt auf links
+ pBindings->Invalidate( SID_ALIGNRIGHT );
+ pBindings->Invalidate( SID_ALIGNBLOCK );
+ pBindings->Invalidate( SID_ALIGNCENTERHOR );
+ // pseudo slots for Format menu
+ pBindings->Invalidate( SID_ALIGN_ANY_HDEFAULT );
+ pBindings->Invalidate( SID_ALIGN_ANY_LEFT );
+ pBindings->Invalidate( SID_ALIGN_ANY_HCENTER );
+ pBindings->Invalidate( SID_ALIGN_ANY_RIGHT );
+ pBindings->Invalidate( SID_ALIGN_ANY_JUSTIFIED );
+ }
+
+ return TRUE;
+}
+
+BOOL ScDocFunc::AutoFormat( const ScRange& rRange, const ScMarkData* pTabMark,
+ USHORT nFormatNo, BOOL bRecord, BOOL bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ BOOL bSuccess = FALSE;
+ ScDocument* pDoc = rDocShell.GetDocument();
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCTAB nStartTab = rRange.aStart.Tab();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ SCTAB nEndTab = rRange.aEnd.Tab();
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+ ScMarkData aMark;
+ if (pTabMark)
+ aMark = *pTabMark;
+ else
+ {
+ for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
+ aMark.SelectTable( nTab, TRUE );
+ }
+
+ ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat();
+ ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
+ if ( pAutoFormat && nFormatNo < pAutoFormat->GetCount() && aTester.IsEditable() )
+ {
+ WaitObject aWait( rDocShell.GetActiveDialogParent() );
+
+ BOOL bSize = (*pAutoFormat)[nFormatNo]->GetIncludeWidthHeight();
+
+ SCTAB nTabCount = pDoc->GetTableCount();
+ ScDocument* pUndoDoc = NULL;
+ if ( bRecord )
+ {
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab, bSize, bSize );
+ for (SCTAB i=0; i<nTabCount; i++)
+ if (i != nStartTab && aMark.GetTableSelect(i))
+ pUndoDoc->AddUndoTab( i, i, bSize, bSize );
+
+ ScRange aCopyRange = rRange;
+ aCopyRange.aStart.SetTab(0);
+ aCopyRange.aStart.SetTab(nTabCount-1);
+ pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, FALSE, pUndoDoc, &aMark );
+ if (bSize)
+ {
+ pDoc->CopyToDocument( nStartCol,0,0, nEndCol,MAXROW,nTabCount-1,
+ IDF_NONE, FALSE, pUndoDoc, &aMark );
+ pDoc->CopyToDocument( 0,nStartRow,0, MAXCOL,nEndRow,nTabCount-1,
+ IDF_NONE, FALSE, pUndoDoc, &aMark );
+ }
+ pDoc->BeginDrawUndo();
+ }
+
+ pDoc->AutoFormat( nStartCol, nStartRow, nEndCol, nEndRow, nFormatNo, aMark );
+
+ if (bSize)
+ {
+/* SCCOL nCols[2];
+ nCols[0] = nStartCol;
+ nCols[1] = nEndCol;
+ SCROW nRows[2];
+ nRows[0] = nStartRow;
+ nRows[1] = nEndRow;
+*/
+ SCCOLROW nCols[2] = { nStartCol, nEndCol };
+ SCCOLROW nRows[2] = { nStartRow, nEndRow };
+
+ for (SCTAB nTab=0; nTab<nTabCount; nTab++)
+ if (aMark.GetTableSelect(nTab))
+ {
+ SetWidthOrHeight( TRUE, 1,nCols, nTab, SC_SIZE_VISOPT, STD_EXTRA_WIDTH, FALSE, TRUE);
+ SetWidthOrHeight( FALSE,1,nRows, nTab, SC_SIZE_VISOPT, 0, FALSE, FALSE);
+ rDocShell.PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab,
+ PAINT_GRID | PAINT_LEFT | PAINT_TOP );
+ }
+ }
+ else
+ {
+ for (SCTAB nTab=0; nTab<nTabCount; nTab++)
+ if (aMark.GetTableSelect(nTab))
+ {
+ BOOL bAdj = AdjustRowHeight( ScRange(nStartCol, nStartRow, nTab,
+ nEndCol, nEndRow, nTab), FALSE );
+ if (bAdj)
+ rDocShell.PostPaint( 0,nStartRow,nTab, MAXCOL,MAXROW,nTab,
+ PAINT_GRID | PAINT_LEFT );
+ else
+ rDocShell.PostPaint( nStartCol, nStartRow, nTab,
+ nEndCol, nEndRow, nTab, PAINT_GRID );
+ }
+ }
+
+ if ( bRecord ) // Draw-Undo erst jetzt verfuegbar
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoAutoFormat( &rDocShell, rRange, pUndoDoc, aMark, bSize, nFormatNo ) );
+ }
+
+ aModificator.SetDocumentModified();
+ }
+ else if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+
+ return bSuccess;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScDocFunc::EnterMatrix( const ScRange& rRange, const ScMarkData* pTabMark,
+ const ScTokenArray* pTokenArray, const String& rString, BOOL bApi, BOOL bEnglish,
+ const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ BOOL bSuccess = FALSE;
+ ScDocument* pDoc = rDocShell.GetDocument();
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCTAB nStartTab = rRange.aStart.Tab();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ SCTAB nEndTab = rRange.aEnd.Tab();
+
+ BOOL bUndo(pDoc->IsUndoEnabled());
+
+ ScMarkData aMark;
+ if (pTabMark)
+ aMark = *pTabMark;
+ else
+ {
+ for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
+ aMark.SelectTable( nTab, TRUE );
+ }
+
+ ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
+ if ( aTester.IsEditable() )
+ {
+ WaitObject aWait( rDocShell.GetActiveDialogParent() );
+
+ ScDocument* pUndoDoc = NULL;
+// if (bRecord) // immer
+ if (bUndo)
+ {
+ //! auch bei Undo selektierte Tabellen beruecksichtigen
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab );
+ pDoc->CopyToDocument( rRange, IDF_ALL & ~IDF_NOTE, FALSE, pUndoDoc );
+ }
+
+ // use TokenArray if given, string (and flags) otherwise
+ if ( pTokenArray )
+ {
+ pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
+ aMark, EMPTY_STRING, pTokenArray, eGrammar);
+ }
+ else if ( pDoc->IsImportingXML() )
+ {
+ ScTokenArray* pCode = lcl_ScDocFunc_CreateTokenArrayXML( rString, rFormulaNmsp, eGrammar );
+ pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
+ aMark, EMPTY_STRING, pCode, eGrammar);
+ delete pCode;
+ pDoc->IncXMLImportedFormulaCount( rString.Len() );
+ }
+ else if (bEnglish)
+ {
+ ScCompiler aComp( pDoc, rRange.aStart);
+ aComp.SetGrammar(eGrammar);
+ ScTokenArray* pCode = aComp.CompileString( rString );
+ pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
+ aMark, EMPTY_STRING, pCode, eGrammar);
+ delete pCode;
+ }
+ else
+ pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
+ aMark, rString, NULL, eGrammar);
+
+// if (bRecord) // immer
+ if (bUndo)
+ {
+ //! auch bei Undo selektierte Tabellen beruecksichtigen
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoEnterMatrix( &rDocShell, rRange, pUndoDoc, rString ) );
+ }
+
+ // Err522 beim Paint von DDE-Formeln werden jetzt beim Interpretieren abgefangen
+ rDocShell.PostPaint( nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab, PAINT_GRID );
+ aModificator.SetDocumentModified();
+
+ bSuccess = TRUE;
+ }
+ else if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+
+ return bSuccess;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScDocFunc::TabOp( const ScRange& rRange, const ScMarkData* pTabMark,
+ const ScTabOpParam& rParam, BOOL bRecord, BOOL bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ BOOL bSuccess = FALSE;
+ ScDocument* pDoc = rDocShell.GetDocument();
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCTAB nStartTab = rRange.aStart.Tab();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ SCTAB nEndTab = rRange.aEnd.Tab();
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+
+ ScMarkData aMark;
+ if (pTabMark)
+ aMark = *pTabMark;
+ else
+ {
+ for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
+ aMark.SelectTable( nTab, TRUE );
+ }
+
+ ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
+ if ( aTester.IsEditable() )
+ {
+ WaitObject aWait( rDocShell.GetActiveDialogParent() );
+ pDoc->SetDirty( rRange );
+ if ( bRecord )
+ {
+ //! auch bei Undo selektierte Tabellen beruecksichtigen
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab );
+ pDoc->CopyToDocument( rRange, IDF_ALL & ~IDF_NOTE, FALSE, pUndoDoc );
+
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoTabOp( &rDocShell,
+ nStartCol, nStartRow, nStartTab,
+ nEndCol, nEndRow, nEndTab, pUndoDoc,
+ rParam.aRefFormulaCell,
+ rParam.aRefFormulaEnd,
+ rParam.aRefRowCell,
+ rParam.aRefColCell,
+ rParam.nMode) );
+ }
+ pDoc->InsertTableOp(rParam, nStartCol, nStartRow, nEndCol, nEndRow, aMark);
+ rDocShell.PostPaintGridAll();
+ aModificator.SetDocumentModified();
+ bSuccess = TRUE;
+ }
+ else if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+
+ return bSuccess;
+}
+
+//------------------------------------------------------------------------
+
+inline ScDirection DirFromFillDir( FillDir eDir )
+{
+ if (eDir==FILL_TO_BOTTOM)
+ return DIR_BOTTOM;
+ else if (eDir==FILL_TO_RIGHT)
+ return DIR_RIGHT;
+ else if (eDir==FILL_TO_TOP)
+ return DIR_TOP;
+ else // if (eDir==FILL_TO_LEFT)
+ return DIR_LEFT;
+}
+
+BOOL ScDocFunc::FillSimple( const ScRange& rRange, const ScMarkData* pTabMark,
+ FillDir eDir, BOOL bRecord, BOOL bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ BOOL bSuccess = FALSE;
+ ScDocument* pDoc = rDocShell.GetDocument();
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCTAB nStartTab = rRange.aStart.Tab();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ SCTAB nEndTab = rRange.aEnd.Tab();
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+
+ ScMarkData aMark;
+ if (pTabMark)
+ aMark = *pTabMark;
+ else
+ {
+ for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
+ aMark.SelectTable( nTab, TRUE );
+ }
+
+ ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
+ if ( aTester.IsEditable() )
+ {
+ WaitObject aWait( rDocShell.GetActiveDialogParent() );
+
+ ScRange aSourceArea = rRange;
+ ScRange aDestArea = rRange;
+
+ SCCOLROW nCount = 0;
+ switch (eDir)
+ {
+ case FILL_TO_BOTTOM:
+ nCount = aSourceArea.aEnd.Row()-aSourceArea.aStart.Row();
+ aSourceArea.aEnd.SetRow( aSourceArea.aStart.Row() );
+ break;
+ case FILL_TO_RIGHT:
+ nCount = aSourceArea.aEnd.Col()-aSourceArea.aStart.Col();
+ aSourceArea.aEnd.SetCol( aSourceArea.aStart.Col() );
+ break;
+ case FILL_TO_TOP:
+ nCount = aSourceArea.aEnd.Row()-aSourceArea.aStart.Row();
+ aSourceArea.aStart.SetRow( aSourceArea.aEnd.Row() );
+ break;
+ case FILL_TO_LEFT:
+ nCount = aSourceArea.aEnd.Col()-aSourceArea.aStart.Col();
+ aSourceArea.aStart.SetCol( aSourceArea.aEnd.Col() );
+ break;
+ }
+
+ ScDocument* pUndoDoc = NULL;
+ if ( bRecord )
+ {
+ SCTAB nTabCount = pDoc->GetTableCount();
+ SCTAB nDestStartTab = aDestArea.aStart.Tab();
+
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab );
+ for (SCTAB i=0; i<nTabCount; i++)
+ if (i != nDestStartTab && aMark.GetTableSelect(i))
+ pUndoDoc->AddUndoTab( i, i );
+
+ ScRange aCopyRange = aDestArea;
+ aCopyRange.aStart.SetTab(0);
+ aCopyRange.aEnd.SetTab(nTabCount-1);
+ pDoc->CopyToDocument( aCopyRange, IDF_AUTOFILL, FALSE, pUndoDoc, &aMark );
+ }
+
+ pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(),
+ aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aMark,
+ nCount, eDir, FILL_SIMPLE );
+ AdjustRowHeight(rRange);
+
+ if ( bRecord ) // Draw-Undo erst jetzt verfuegbar
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
+ eDir, FILL_SIMPLE, FILL_DAY, MAXDOUBLE, 1.0, 1e307,
+ pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) );
+ }
+
+ rDocShell.PostPaintGridAll();
+// rDocShell.PostPaintDataChanged();
+ aModificator.SetDocumentModified();
+
+ bSuccess = TRUE;
+ }
+ else if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+
+ return bSuccess;
+}
+
+BOOL ScDocFunc::FillSeries( const ScRange& rRange, const ScMarkData* pTabMark,
+ FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd,
+ double fStart, double fStep, double fMax,
+ BOOL bRecord, BOOL bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ BOOL bSuccess = FALSE;
+ ScDocument* pDoc = rDocShell.GetDocument();
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCTAB nStartTab = rRange.aStart.Tab();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ SCTAB nEndTab = rRange.aEnd.Tab();
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+
+ ScMarkData aMark;
+ if (pTabMark)
+ aMark = *pTabMark;
+ else
+ {
+ for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
+ aMark.SelectTable( nTab, TRUE );
+ }
+
+ ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
+ if ( aTester.IsEditable() )
+ {
+ WaitObject aWait( rDocShell.GetActiveDialogParent() );
+
+ ScRange aSourceArea = rRange;
+ ScRange aDestArea = rRange;
+
+ SCSIZE nCount = pDoc->GetEmptyLinesInBlock(
+ aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), aSourceArea.aStart.Tab(),
+ aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aSourceArea.aEnd.Tab(),
+ DirFromFillDir(eDir) );
+
+ // #27665# mindestens eine Zeile/Spalte als Quellbereich behalten:
+ SCSIZE nTotLines = ( eDir == FILL_TO_BOTTOM || eDir == FILL_TO_TOP ) ?
+ static_cast<SCSIZE>( aSourceArea.aEnd.Row() - aSourceArea.aStart.Row() + 1 ) :
+ static_cast<SCSIZE>( aSourceArea.aEnd.Col() - aSourceArea.aStart.Col() + 1 );
+ if ( nCount >= nTotLines )
+ nCount = nTotLines - 1;
+
+ switch (eDir)
+ {
+ case FILL_TO_BOTTOM:
+ aSourceArea.aEnd.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aEnd.Row() - nCount ) );
+ break;
+ case FILL_TO_RIGHT:
+ aSourceArea.aEnd.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aEnd.Col() - nCount ) );
+ break;
+ case FILL_TO_TOP:
+ aSourceArea.aStart.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aStart.Row() + nCount ) );
+ break;
+ case FILL_TO_LEFT:
+ aSourceArea.aStart.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aStart.Col() + nCount ) );
+ break;
+ }
+
+ ScDocument* pUndoDoc = NULL;
+ if ( bRecord )
+ {
+ SCTAB nTabCount = pDoc->GetTableCount();
+ SCTAB nDestStartTab = aDestArea.aStart.Tab();
+
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab );
+ for (SCTAB i=0; i<nTabCount; i++)
+ if (i != nDestStartTab && aMark.GetTableSelect(i))
+ pUndoDoc->AddUndoTab( i, i );
+
+ pDoc->CopyToDocument(
+ aDestArea.aStart.Col(), aDestArea.aStart.Row(), 0,
+ aDestArea.aEnd.Col(), aDestArea.aEnd.Row(), nTabCount-1,
+ IDF_AUTOFILL, FALSE, pUndoDoc, &aMark );
+ }
+
+ if (aDestArea.aStart.Col() <= aDestArea.aEnd.Col() &&
+ aDestArea.aStart.Row() <= aDestArea.aEnd.Row())
+ {
+ if ( fStart != MAXDOUBLE )
+ {
+ SCCOL nValX = (eDir == FILL_TO_LEFT) ? aDestArea.aEnd.Col() : aDestArea.aStart.Col();
+ SCROW nValY = (eDir == FILL_TO_TOP ) ? aDestArea.aEnd.Row() : aDestArea.aStart.Row();
+ SCTAB nTab = aDestArea.aStart.Tab();
+ pDoc->SetValue( nValX, nValY, nTab, fStart );
+ }
+ pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(),
+ aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aMark,
+ nCount, eDir, eCmd, eDateCmd, fStep, fMax );
+ AdjustRowHeight(rRange);
+
+ rDocShell.PostPaintGridAll();
+// rDocShell.PostPaintDataChanged();
+ aModificator.SetDocumentModified();
+ }
+
+ if ( bRecord ) // Draw-Undo erst jetzt verfuegbar
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
+ eDir, eCmd, eDateCmd, fStart, fStep, fMax,
+ pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) );
+ }
+
+ bSuccess = TRUE;
+ }
+ else if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+
+ return bSuccess;
+}
+
+BOOL ScDocFunc::FillAuto( ScRange& rRange, const ScMarkData* pTabMark,
+ FillDir eDir, ULONG nCount, BOOL bRecord, BOOL bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCTAB nStartTab = rRange.aStart.Tab();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ SCTAB nEndTab = rRange.aEnd.Tab();
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+
+ ScMarkData aMark;
+ if (pTabMark)
+ aMark = *pTabMark;
+ else
+ {
+ for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
+ aMark.SelectTable( nTab, TRUE );
+ }
+
+ ScRange aSourceArea = rRange;
+ ScRange aDestArea = rRange;
+
+ FillCmd eCmd = FILL_AUTO;
+ FillDateCmd eDateCmd = FILL_DAY;
+ double fStep = 1.0;
+ double fMax = MAXDOUBLE;
+
+ switch (eDir)
+ {
+ case FILL_TO_BOTTOM:
+ aDestArea.aEnd.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aEnd.Row() + nCount ) );
+ break;
+ case FILL_TO_TOP:
+ if (nCount > sal::static_int_cast<ULONG>( aSourceArea.aStart.Row() ))
+ {
+ DBG_ERROR("FillAuto: Row < 0");
+ nCount = aSourceArea.aStart.Row();
+ }
+ aDestArea.aStart.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aStart.Row() - nCount ) );
+ break;
+ case FILL_TO_RIGHT:
+ aDestArea.aEnd.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aEnd.Col() + nCount ) );
+ break;
+ case FILL_TO_LEFT:
+ if (nCount > sal::static_int_cast<ULONG>( aSourceArea.aStart.Col() ))
+ {
+ DBG_ERROR("FillAuto: Col < 0");
+ nCount = aSourceArea.aStart.Col();
+ }
+ aDestArea.aStart.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aStart.Col() - nCount ) );
+ break;
+ default:
+ DBG_ERROR("Falsche Richtung bei FillAuto");
+ break;
+ }
+
+ // Zellschutz testen
+ //! Quellbereich darf geschuetzt sein !!!
+ //! aber kein Matrixfragment enthalten !!!
+
+ ScEditableTester aTester( pDoc, aDestArea );
+ if ( !aTester.IsEditable() )
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ return FALSE;
+ }
+
+ if ( pDoc->HasSelectedBlockMatrixFragment( nStartCol, nStartRow,
+ nEndCol, nEndRow, aMark ) )
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_MATRIXFRAGMENTERR);
+ return FALSE;
+ }
+
+ WaitObject aWait( rDocShell.GetActiveDialogParent() );
+
+ ScDocument* pUndoDoc = NULL;
+ if ( bRecord )
+ {
+ SCTAB nTabCount = pDoc->GetTableCount();
+ SCTAB nDestStartTab = aDestArea.aStart.Tab();
+
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab );
+ for (SCTAB i=0; i<nTabCount; i++)
+ if (i != nDestStartTab && aMark.GetTableSelect(i))
+ pUndoDoc->AddUndoTab( i, i );
+
+ // do not clone note captions in undo document
+ pDoc->CopyToDocument(
+ aDestArea.aStart.Col(), aDestArea.aStart.Row(), 0,
+ aDestArea.aEnd.Col(), aDestArea.aEnd.Row(), nTabCount-1,
+ IDF_AUTOFILL, FALSE, pUndoDoc, &aMark );
+ }
+
+ pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(),
+ aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aMark,
+ nCount, eDir, eCmd, eDateCmd, fStep, fMax );
+
+ AdjustRowHeight(aDestArea);
+
+ if ( bRecord ) // Draw-Undo erst jetzt verfuegbar
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
+ eDir, eCmd, eDateCmd, MAXDOUBLE, fStep, fMax,
+ pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) );
+ }
+
+ rDocShell.PostPaintGridAll();
+// rDocShell.PostPaintDataChanged();
+ aModificator.SetDocumentModified();
+
+ rRange = aDestArea; // Zielbereich zurueckgeben (zum Markieren)
+ return TRUE;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScDocFunc::MergeCells( const ScRange& rRange, BOOL bContents, BOOL bRecord, BOOL bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ SCTAB nTab = rRange.aStart.Tab();
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+
+ ScEditableTester aTester( pDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow );
+ if (!aTester.IsEditable())
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ return FALSE;
+ }
+
+ if ( nStartCol == nEndCol && nStartRow == nEndRow )
+ {
+ // nichts zu tun
+ return TRUE;
+ }
+
+ if ( pDoc->HasAttrib( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab,
+ HASATTR_MERGED | HASATTR_OVERLAPPED ) )
+ {
+ // "Zusammenfassen nicht verschachteln !"
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_MSSG_MERGECELLS_0);
+ return FALSE;
+ }
+
+ BOOL bNeedContents = bContents &&
+ ( !pDoc->IsBlockEmpty( nTab, nStartCol,nStartRow+1, nStartCol,nEndRow, true ) ||
+ !pDoc->IsBlockEmpty( nTab, nStartCol+1,nStartRow, nEndCol,nEndRow, true ) );
+
+ ScDocument* pUndoDoc = 0;
+ if (bRecord)
+ {
+ // test if the range contains other notes which also implies that we need an undo document
+ bool bHasNotes = false;
+ for( ScAddress aPos( nStartCol, nStartRow, nTab ); !bHasNotes && (aPos.Col() <= nEndCol); aPos.IncCol() )
+ for( aPos.SetRow( nStartRow ); !bHasNotes && (aPos.Row() <= nEndRow); aPos.IncRow() )
+ bHasNotes = ((aPos.Col() != nStartCol) || (aPos.Row() != nStartRow)) && (pDoc->GetNote( aPos ) != 0);
+
+ if (bNeedContents || bHasNotes)
+ {
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nTab, nTab );
+ // note captions are collected by drawing undo
+ pDoc->CopyToDocument( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab,
+ IDF_ALL|IDF_NOCAPTIONS, FALSE, pUndoDoc );
+ }
+ if( bHasNotes )
+ pDoc->BeginDrawUndo();
+ }
+
+ if (bNeedContents)
+ pDoc->DoMergeContents( nTab, nStartCol,nStartRow, nEndCol,nEndRow );
+ pDoc->DoMerge( nTab, nStartCol,nStartRow, nEndCol,nEndRow );
+
+ if( bRecord )
+ {
+ SdrUndoGroup* pDrawUndo = pDoc->GetDrawLayer() ? pDoc->GetDrawLayer()->GetCalcUndo() : 0;
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoMerge( &rDocShell,
+ nStartCol, nStartRow, nTab,
+ nEndCol, nEndRow, nTab, bNeedContents, pUndoDoc, pDrawUndo ) );
+ }
+
+ if ( !AdjustRowHeight( ScRange( 0,nStartRow,nTab, MAXCOL,nEndRow,nTab ) ) )
+ rDocShell.PostPaint( nStartCol, nStartRow, nTab,
+ nEndCol, nEndRow, nTab, PAINT_GRID );
+ if (bNeedContents)
+ pDoc->SetDirty( rRange );
+ aModificator.SetDocumentModified();
+
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+ if (pBindings)
+ {
+ pBindings->Invalidate( FID_MERGE_ON );
+ pBindings->Invalidate( FID_MERGE_OFF );
+ pBindings->Invalidate( FID_MERGE_TOGGLE );
+ }
+
+ return TRUE;
+}
+
+BOOL ScDocFunc::UnmergeCells( const ScRange& rRange, BOOL bRecord, BOOL bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ SCTAB nTab = rRange.aStart.Tab();
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+
+ if ( pDoc->HasAttrib( rRange, HASATTR_MERGED ) )
+ {
+ ScRange aExtended = rRange;
+ pDoc->ExtendMerge( aExtended );
+ ScRange aRefresh = aExtended;
+ pDoc->ExtendOverlapped( aRefresh );
+
+ if (bRecord)
+ {
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nTab, nTab );
+ pDoc->CopyToDocument( aExtended, IDF_ATTRIB, FALSE, pUndoDoc );
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoRemoveMerge( &rDocShell, rRange, pUndoDoc ) );
+ }
+
+ const SfxPoolItem& rDefAttr = pDoc->GetPool()->GetDefaultItem( ATTR_MERGE );
+ ScPatternAttr aPattern( pDoc->GetPool() );
+ aPattern.GetItemSet().Put( rDefAttr );
+ pDoc->ApplyPatternAreaTab( rRange.aStart.Col(), rRange.aStart.Row(),
+ rRange.aEnd.Col(), rRange.aEnd.Row(), nTab,
+ aPattern );
+
+ pDoc->RemoveFlagsTab( aExtended.aStart.Col(), aExtended.aStart.Row(),
+ aExtended.aEnd.Col(), aExtended.aEnd.Row(), nTab,
+ SC_MF_HOR | SC_MF_VER );
+
+ pDoc->ExtendMerge( aRefresh, TRUE, FALSE );
+
+ if ( !AdjustRowHeight( aExtended ) )
+ rDocShell.PostPaint( aExtended, PAINT_GRID );
+ aModificator.SetDocumentModified();
+ }
+ else if (!bApi)
+ Sound::Beep(); //! FALSE zurueck???
+
+ return TRUE;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScDocFunc::ModifyRangeNames( const ScRangeName& rNewRanges, BOOL bApi )
+{
+ return SetNewRangeNames( new ScRangeName( rNewRanges ), bApi );
+}
+
+BOOL ScDocFunc::SetNewRangeNames( ScRangeName* pNewRanges, BOOL /* bApi */ ) // takes ownership of pNewRanges
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+ DBG_ASSERT( pNewRanges, "pNewRanges is 0" );
+ ScDocument* pDoc = rDocShell.GetDocument();
+ BOOL bUndo(pDoc->IsUndoEnabled());
+
+ if (bUndo)
+ {
+ ScRangeName* pOld = pDoc->GetRangeName();
+ ScRangeName* pUndoRanges = new ScRangeName(*pOld);
+ ScRangeName* pRedoRanges = new ScRangeName(*pNewRanges);
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoRangeNames( &rDocShell, pUndoRanges, pRedoRanges ) );
+ }
+
+ // #i55926# While loading XML, formula cells only have a single string token,
+ // so CompileNameFormula would never find any name (index) tokens, and would
+ // unnecessarily loop through all cells.
+ BOOL bCompile = ( !pDoc->IsImportingXML() && pDoc->GetNamedRangesLockCount() == 0 );
+
+ if ( bCompile )
+ pDoc->CompileNameFormula( TRUE ); // CreateFormulaString
+ pDoc->SetRangeName( pNewRanges ); // takes ownership
+ if ( bCompile )
+ pDoc->CompileNameFormula( FALSE ); // CompileFormulaString
+
+ aModificator.SetDocumentModified();
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
+
+ return TRUE;
+}
+
+//------------------------------------------------------------------------
+
+void ScDocFunc::CreateOneName( ScRangeName& rList,
+ SCCOL nPosX, SCROW nPosY, SCTAB nTab,
+ SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
+ BOOL& rCancel, BOOL bApi )
+{
+ if (rCancel)
+ return;
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if (!pDoc->HasValueData( nPosX, nPosY, nTab ))
+ {
+ String aName;
+ pDoc->GetString( nPosX, nPosY, nTab, aName );
+ ScRangeData::MakeValidName(aName);
+ if (aName.Len())
+ {
+ String aContent;
+ ScRange( nX1, nY1, nTab, nX2, nY2, nTab ).Format( aContent, SCR_ABS_3D, pDoc );
+
+ BOOL bInsert = FALSE;
+ USHORT nOldPos;
+ if (rList.SearchName( aName, nOldPos )) // vorhanden ?
+ {
+ ScRangeData* pOld = rList[nOldPos];
+ String aOldStr;
+ pOld->GetSymbol( aOldStr );
+ if (aOldStr != aContent)
+ {
+ if (bApi)
+ bInsert = TRUE; // per API nicht nachfragen
+ else
+ {
+ String aTemplate = ScGlobal::GetRscString( STR_CREATENAME_REPLACE );
+
+ String aMessage = aTemplate.GetToken( 0, '#' );
+ aMessage += aName;
+ aMessage += aTemplate.GetToken( 1, '#' );
+
+ short nResult = QueryBox( rDocShell.GetActiveDialogParent(),
+ WinBits(WB_YES_NO_CANCEL | WB_DEF_YES),
+ aMessage ).Execute();
+ if ( nResult == RET_YES )
+ {
+ rList.AtFree(nOldPos);
+ bInsert = TRUE;
+ }
+ else if ( nResult == RET_CANCEL )
+ rCancel = TRUE;
+ }
+ }
+ }
+ else
+ bInsert = TRUE;
+
+ if (bInsert)
+ {
+ ScRangeData* pData = new ScRangeData( pDoc, aName, aContent,
+ ScAddress( nPosX, nPosY, nTab));
+ if (!rList.Insert(pData))
+ {
+ DBG_ERROR("nanu?");
+ delete pData;
+ }
+ }
+ }
+ }
+}
+
+BOOL ScDocFunc::CreateNames( const ScRange& rRange, USHORT nFlags, BOOL bApi )
+{
+ if (!nFlags)
+ return FALSE; // war nix
+
+ ScDocShellModificator aModificator( rDocShell );
+
+ BOOL bDone = FALSE;
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ SCTAB nTab = rRange.aStart.Tab();
+ DBG_ASSERT(rRange.aEnd.Tab() == nTab, "CreateNames: mehrere Tabellen geht nicht");
+
+ BOOL bValid = TRUE;
+ if ( nFlags & ( NAME_TOP | NAME_BOTTOM ) )
+ if ( nStartRow == nEndRow )
+ bValid = FALSE;
+ if ( nFlags & ( NAME_LEFT | NAME_RIGHT ) )
+ if ( nStartCol == nEndCol )
+ bValid = FALSE;
+
+ if (bValid)
+ {
+ ScDocument* pDoc = rDocShell.GetDocument();
+ ScRangeName* pNames = pDoc->GetRangeName();
+ if (!pNames)
+ return FALSE; // soll nicht sein
+ ScRangeName aNewRanges( *pNames );
+
+ BOOL bTop = ( ( nFlags & NAME_TOP ) != 0 );
+ BOOL bLeft = ( ( nFlags & NAME_LEFT ) != 0 );
+ BOOL bBottom = ( ( nFlags & NAME_BOTTOM ) != 0 );
+ BOOL bRight = ( ( nFlags & NAME_RIGHT ) != 0 );
+
+ SCCOL nContX1 = nStartCol;
+ SCROW nContY1 = nStartRow;
+ SCCOL nContX2 = nEndCol;
+ SCROW nContY2 = nEndRow;
+
+ if ( bTop )
+ ++nContY1;
+ if ( bLeft )
+ ++nContX1;
+ if ( bBottom )
+ --nContY2;
+ if ( bRight )
+ --nContX2;
+
+ BOOL bCancel = FALSE;
+ SCCOL i;
+ SCROW j;
+
+ if ( bTop )
+ for (i=nContX1; i<=nContX2; i++)
+ CreateOneName( aNewRanges, i,nStartRow,nTab, i,nContY1,i,nContY2, bCancel, bApi );
+ if ( bLeft )
+ for (j=nContY1; j<=nContY2; j++)
+ CreateOneName( aNewRanges, nStartCol,j,nTab, nContX1,j,nContX2,j, bCancel, bApi );
+ if ( bBottom )
+ for (i=nContX1; i<=nContX2; i++)
+ CreateOneName( aNewRanges, i,nEndRow,nTab, i,nContY1,i,nContY2, bCancel, bApi );
+ if ( bRight )
+ for (j=nContY1; j<=nContY2; j++)
+ CreateOneName( aNewRanges, nEndCol,j,nTab, nContX1,j,nContX2,j, bCancel, bApi );
+
+ if ( bTop && bLeft )
+ CreateOneName( aNewRanges, nStartCol,nStartRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
+ if ( bTop && bRight )
+ CreateOneName( aNewRanges, nEndCol,nStartRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
+ if ( bBottom && bLeft )
+ CreateOneName( aNewRanges, nStartCol,nEndRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
+ if ( bBottom && bRight )
+ CreateOneName( aNewRanges, nEndCol,nEndRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
+
+ bDone = ModifyRangeNames( aNewRanges, bApi );
+
+ aModificator.SetDocumentModified();
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
+ }
+
+ return bDone;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScDocFunc::InsertNameList( const ScAddress& rStartPos, BOOL bApi )
+{
+ ScDocShellModificator aModificator( rDocShell );
+
+
+ BOOL bDone = FALSE;
+ ScDocument* pDoc = rDocShell.GetDocument();
+ const BOOL bRecord = pDoc->IsUndoEnabled();
+ SCTAB nTab = rStartPos.Tab();
+ ScDocument* pUndoDoc = NULL;
+
+ ScRangeName* pList = pDoc->GetRangeName();
+ USHORT nCount = pList->GetCount();
+ USHORT nValidCount = 0;
+ USHORT i;
+ for (i=0; i<nCount; i++)
+ {
+ ScRangeData* pData = (*pList)[i];
+ if ( !pData->HasType( RT_DATABASE ) && !pData->HasType( RT_SHARED ) )
+ ++nValidCount;
+ }
+
+ if (nValidCount)
+ {
+ SCCOL nStartCol = rStartPos.Col();
+ SCROW nStartRow = rStartPos.Row();
+ SCCOL nEndCol = nStartCol + 1;
+ SCROW nEndRow = nStartRow + static_cast<SCROW>(nValidCount) - 1;
+
+ ScEditableTester aTester( pDoc, nTab, nStartCol,nStartRow, nEndCol,nEndRow );
+ if (aTester.IsEditable())
+ {
+ if (bRecord)
+ {
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nTab, nTab );
+ pDoc->CopyToDocument( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab,
+ IDF_ALL, FALSE, pUndoDoc );
+
+ pDoc->BeginDrawUndo(); // wegen Hoehenanpassung
+ }
+
+ ScRangeData** ppSortArray = new ScRangeData* [ nValidCount ];
+ USHORT j = 0;
+ for (i=0; i<nCount; i++)
+ {
+ ScRangeData* pData = (*pList)[i];
+ if ( !pData->HasType( RT_DATABASE ) && !pData->HasType( RT_SHARED ) )
+ ppSortArray[j++] = pData;
+ }
+#ifndef ICC
+ qsort( (void*)ppSortArray, nValidCount, sizeof(ScRangeData*),
+ &ScRangeData_QsortNameCompare );
+#else
+ qsort( (void*)ppSortArray, nValidCount, sizeof(ScRangeData*),
+ ICCQsortNameCompare );
+#endif
+ String aName;
+ rtl::OUStringBuffer aContent;
+ String aFormula;
+ SCROW nOutRow = nStartRow;
+ for (j=0; j<nValidCount; j++)
+ {
+ ScRangeData* pData = ppSortArray[j];
+ pData->GetName(aName);
+ // relative Referenzen Excel-konform auf die linke Spalte anpassen:
+ pData->UpdateSymbol(aContent, ScAddress( nStartCol, nOutRow, nTab ));
+ aFormula = '=';
+ aFormula += aContent;
+ pDoc->PutCell( nStartCol,nOutRow,nTab, new ScStringCell( aName ) );
+ pDoc->PutCell( nEndCol ,nOutRow,nTab, new ScStringCell( aFormula ) );
+ ++nOutRow;
+ }
+
+ delete [] ppSortArray;
+
+ if (bRecord)
+ {
+ ScDocument* pRedoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pRedoDoc->InitUndo( pDoc, nTab, nTab );
+ pDoc->CopyToDocument( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab,
+ IDF_ALL, FALSE, pRedoDoc );
+
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoListNames( &rDocShell,
+ ScRange( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab ),
+ pUndoDoc, pRedoDoc ) );
+ }
+
+ if (!AdjustRowHeight(ScRange(0,nStartRow,nTab,MAXCOL,nEndRow,nTab)))
+ rDocShell.PostPaint( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab, PAINT_GRID );
+//! rDocShell.UpdateOle(GetViewData());
+ aModificator.SetDocumentModified();
+ bDone = TRUE;
+ }
+ else if (!bApi)
+ rDocShell.ErrorMessage(aTester.GetMessageId());
+ }
+ return bDone;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScDocFunc::ResizeMatrix( const ScRange& rOldRange, const ScAddress& rNewEnd, BOOL bApi )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+ SCCOL nStartCol = rOldRange.aStart.Col();
+ SCROW nStartRow = rOldRange.aStart.Row();
+ SCTAB nTab = rOldRange.aStart.Tab();
+
+ BOOL bUndo(pDoc->IsUndoEnabled());
+
+ BOOL bRet = FALSE;
+
+ String aFormula;
+ pDoc->GetFormula( nStartCol, nStartRow, nTab, aFormula );
+ if ( aFormula.GetChar(0) == '{' && aFormula.GetChar(aFormula.Len()-1) == '}' )
+ {
+ String aUndo = ScGlobal::GetRscString( STR_UNDO_RESIZEMATRIX );
+ if (bUndo)
+ rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
+
+ aFormula.Erase(0,1);
+ aFormula.Erase(aFormula.Len()-1,1);
+
+ ScMarkData aMark;
+ aMark.SetMarkArea( rOldRange );
+ aMark.SelectTable( nTab, TRUE );
+ ScRange aNewRange( rOldRange.aStart, rNewEnd );
+
+ if ( DeleteContents( aMark, IDF_CONTENTS, TRUE, bApi ) )
+ {
+ // GRAM_PODF_A1 for API compatibility.
+ bRet = EnterMatrix( aNewRange, &aMark, NULL, aFormula, bApi, FALSE, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 );
+ if (!bRet)
+ {
+ // versuchen, alten Zustand wiederherzustellen
+ EnterMatrix( rOldRange, &aMark, NULL, aFormula, bApi, FALSE, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 );
+ }
+ }
+
+ if (bUndo)
+ rDocShell.GetUndoManager()->LeaveListAction();
+ }
+
+ return bRet;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScDocFunc::InsertAreaLink( const String& rFile, const String& rFilter,
+ const String& rOptions, const String& rSource,
+ const ScRange& rDestRange, ULONG nRefresh,
+ BOOL bFitBlock, BOOL bApi )
+{
+ //! auch fuer ScViewFunc::InsertAreaLink benutzen!
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ BOOL bUndo (pDoc->IsUndoEnabled());
+
+ sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager();
+
+ // #i52120# if other area links exist at the same start position,
+ // remove them first (file format specifies only one link definition
+ // for a cell)
+
+ USHORT nLinkCount = pLinkManager->GetLinks().Count();
+ USHORT nRemoved = 0;
+ USHORT nLinkPos = 0;
+ while (nLinkPos<nLinkCount)
+ {
+ ::sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[nLinkPos];
+ if ( pBase->ISA(ScAreaLink) &&
+ static_cast<ScAreaLink*>(pBase)->GetDestArea().aStart == rDestRange.aStart )
+ {
+ if ( bUndo )
+ {
+ if ( !nRemoved )
+ {
+ // group all remove and the insert action
+ String aUndo = ScGlobal::GetRscString( STR_UNDO_INSERTAREALINK );
+ rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
+ }
+
+ ScAreaLink* pOldArea = static_cast<ScAreaLink*>(pBase);
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoRemoveAreaLink( &rDocShell,
+ pOldArea->GetFile(), pOldArea->GetFilter(), pOldArea->GetOptions(),
+ pOldArea->GetSource(), pOldArea->GetDestArea(), pOldArea->GetRefreshDelay() ) );
+ }
+ pLinkManager->Remove( pBase );
+ nLinkCount = pLinkManager->GetLinks().Count();
+ ++nRemoved;
+ }
+ else
+ ++nLinkPos;
+ }
+
+ String aFilterName = rFilter;
+ String aNewOptions = rOptions;
+ if (!aFilterName.Len())
+ ScDocumentLoader::GetFilterName( rFile, aFilterName, aNewOptions, TRUE, !bApi );
+
+ // remove application prefix from filter name here, so the filter options
+ // aren't reset when the filter name is changed in ScAreaLink::DataChanged
+ ScDocumentLoader::RemoveAppPrefix( aFilterName );
+
+ ScAreaLink* pLink = new ScAreaLink( &rDocShell, rFile, aFilterName,
+ aNewOptions, rSource, rDestRange, nRefresh );
+ pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, rFile, &aFilterName, &rSource );
+
+ // Undo fuer den leeren Link
+
+ if (bUndo)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction( new ScUndoInsertAreaLink( &rDocShell,
+ rFile, aFilterName, aNewOptions,
+ rSource, rDestRange, nRefresh ) );
+ if ( nRemoved )
+ rDocShell.GetUndoManager()->LeaveListAction(); // undo for link update is still separate
+ }
+
+ // Update hat sein eigenes Undo
+
+ pLink->SetDoInsert(bFitBlock); // beim ersten Update ggf. nichts einfuegen
+ pLink->Update(); // kein SetInCreate -> Update ausfuehren
+ pLink->SetDoInsert(TRUE); // Default = TRUE
+
+ SfxBindings* pBindings = rDocShell.GetViewBindings();
+ if (pBindings)
+ pBindings->Invalidate( SID_LINKS );
+
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); // Navigator
+
+ return TRUE;
+}
+
+
+
+
diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx
new file mode 100644
index 000000000000..1b4f9b677f81
--- /dev/null
+++ b/sc/source/ui/docshell/docsh.cxx
@@ -0,0 +1,2591 @@
+/*************************************************************************
+ *
+ * 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"
+// System - Includes -----------------------------------------------------
+
+
+
+#include "scitems.hxx"
+#include <editeng/eeitem.hxx>
+#include <editeng/svxenum.hxx>
+#include <svx/algitem.hxx>
+
+
+
+#include <sot/clsids.hxx>
+#include <unotools/securityoptions.hxx>
+#include <tools/stream.hxx>
+#include <tools/string.hxx>
+#include <tools/urlobj.hxx>
+#include <vcl/msgbox.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/waitobj.hxx>
+#include <svtools/ctrltool.hxx>
+#include <svtools/sfxecode.hxx>
+#include <svl/zforlist.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/dinfdlg.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/docfilt.hxx>
+#include <sfx2/fcontnr.hxx>
+#include <sfx2/evntconf.hxx>
+#include <sfx2/sfx.hrc>
+#include <sfx2/topfrm.hxx>
+#include <sfx2/objface.hxx>
+#include <svl/srchitem.hxx>
+#include <unotools/fltrcfg.hxx>
+#include <svl/documentlockfile.hxx>
+#include <svl/sharecontrolfile.hxx>
+#include <unotools/charclass.hxx>
+#include <vcl/virdev.hxx>
+#include "chgtrack.hxx"
+#include "chgviset.hxx"
+#include <sfx2/request.hxx>
+#include <com/sun/star/document/UpdateDocMode.hpp>
+
+
+#include "scabstdlg.hxx" //CHINA001
+#include <sot/formats.hxx>
+#define SOT_FORMATSTR_ID_STARCALC_30 SOT_FORMATSTR_ID_STARCALC
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "cell.hxx"
+#include "global.hxx"
+#include "filter.hxx"
+#include "scmod.hxx"
+#include "tabvwsh.hxx"
+#include "docfunc.hxx"
+#include "imoptdlg.hxx"
+#include "impex.hxx"
+#include "scresid.hxx"
+#include "sc.hrc"
+#include "globstr.hrc"
+#include "scerrors.hxx"
+#include "brdcst.hxx"
+#include "stlpool.hxx"
+#include "autostyl.hxx"
+#include "attrib.hxx"
+#include "asciiopt.hxx"
+#include "waitoff.hxx"
+#include "docpool.hxx" // LoadCompleted
+#include "progress.hxx"
+#include "pntlock.hxx"
+#include "collect.hxx"
+#include "docuno.hxx"
+#include "appoptio.hxx"
+#include "detdata.hxx"
+#include "printfun.hxx"
+#include "dociter.hxx"
+#include "cellform.hxx"
+#include "chartlis.hxx"
+#include "hints.hxx"
+#include "xmlwrap.hxx"
+#include "drwlayer.hxx"
+#include "refreshtimer.hxx"
+#include "dbcolect.hxx"
+#include "scextopt.hxx"
+#include "compiler.hxx"
+#include "cfgids.hxx"
+#include "warnpassword.hxx"
+#include "optsolver.hxx"
+#include "sheetdata.hxx"
+#include "tabprotection.hxx"
+
+#include "docsh.hxx"
+#include "docshimp.hxx"
+#include <rtl/logfile.hxx>
+
+#include <comphelper/processfactory.hxx>
+#include <basic/sbstar.hxx>
+#include <basic/basmgr.hxx>
+using namespace com::sun::star;
+
+// STATIC DATA -----------------------------------------------------------
+
+// Stream-Namen im Storage
+
+const sal_Char __FAR_DATA ScDocShell::pStarCalcDoc[] = STRING_SCSTREAM; // "StarCalcDocument"
+const sal_Char __FAR_DATA ScDocShell::pStyleName[] = "SfxStyleSheets";
+
+// Filter-Namen (wie in sclib.cxx)
+
+static const sal_Char __FAR_DATA pFilterSc50[] = "StarCalc 5.0";
+//static const sal_Char __FAR_DATA pFilterSc50Temp[] = "StarCalc 5.0 Vorlage/Template";
+static const sal_Char __FAR_DATA pFilterSc40[] = "StarCalc 4.0";
+//static const sal_Char __FAR_DATA pFilterSc40Temp[] = "StarCalc 4.0 Vorlage/Template";
+static const sal_Char __FAR_DATA pFilterSc30[] = "StarCalc 3.0";
+//static const sal_Char __FAR_DATA pFilterSc30Temp[] = "StarCalc 3.0 Vorlage/Template";
+static const sal_Char __FAR_DATA pFilterSc10[] = "StarCalc 1.0";
+static const sal_Char __FAR_DATA pFilterXML[] = "StarOffice XML (Calc)";
+static const sal_Char __FAR_DATA pFilterAscii[] = "Text - txt - csv (StarCalc)";
+static const sal_Char __FAR_DATA pFilterLotus[] = "Lotus";
+static const sal_Char __FAR_DATA pFilterQPro6[] = "Quattro Pro 6.0";
+static const sal_Char __FAR_DATA pFilterExcel4[] = "MS Excel 4.0";
+static const sal_Char __FAR_DATA pFilterEx4Temp[] = "MS Excel 4.0 Vorlage/Template";
+static const sal_Char __FAR_DATA pFilterExcel5[] = "MS Excel 5.0/95";
+static const sal_Char __FAR_DATA pFilterEx5Temp[] = "MS Excel 5.0/95 Vorlage/Template";
+static const sal_Char __FAR_DATA pFilterExcel95[] = "MS Excel 95";
+static const sal_Char __FAR_DATA pFilterEx95Temp[] = "MS Excel 95 Vorlage/Template";
+static const sal_Char __FAR_DATA pFilterExcel97[] = "MS Excel 97";
+static const sal_Char __FAR_DATA pFilterEx97Temp[] = "MS Excel 97 Vorlage/Template";
+static const sal_Char __FAR_DATA pFilterEx07Xml[] = "MS Excel 2007 XML";
+static const sal_Char __FAR_DATA pFilterDBase[] = "dBase";
+static const sal_Char __FAR_DATA pFilterDif[] = "DIF";
+static const sal_Char __FAR_DATA pFilterSylk[] = "SYLK";
+static const sal_Char __FAR_DATA pFilterHtml[] = "HTML (StarCalc)";
+static const sal_Char __FAR_DATA pFilterHtmlWebQ[] = "calc_HTML_WebQuery";
+static const sal_Char __FAR_DATA pFilterRtf[] = "Rich Text Format (StarCalc)";
+
+//----------------------------------------------------------------------
+
+#define ScDocShell
+#include "scslots.hxx"
+
+
+SFX_IMPL_INTERFACE(ScDocShell,SfxObjectShell, ScResId(SCSTR_DOCSHELL))
+{
+ SFX_CHILDWINDOW_REGISTRATION( SID_HYPERLINK_INSERT );
+}
+
+// GlobalName der aktuellen Version:
+SFX_IMPL_OBJECTFACTORY( ScDocShell, SvGlobalName(SO3_SC_CLASSID), SFXOBJECTSHELL_STD_NORMAL, "scalc" )
+
+TYPEINIT1( ScDocShell, SfxObjectShell ); // SfxInPlaceObject: kein Type-Info ?
+
+//------------------------------------------------------------------
+
+void __EXPORT ScDocShell::FillClass( SvGlobalName* pClassName,
+ sal_uInt32* pFormat,
+ String* /* pAppName */,
+ String* pFullTypeName,
+ String* pShortTypeName,
+ sal_Int32 nFileFormat,
+ sal_Bool bTemplate /* = sal_False */) const
+{
+ if ( nFileFormat == SOFFICE_FILEFORMAT_60 )
+ {
+ *pClassName = SvGlobalName( SO3_SC_CLASSID_60 );
+ *pFormat = SOT_FORMATSTR_ID_STARCALC_60;
+ *pFullTypeName = String( ScResId( SCSTR_LONG_SCDOC_NAME ) );
+ *pShortTypeName = String( ScResId( SCSTR_SHORT_SCDOC_NAME ) );
+ }
+ else if ( nFileFormat == SOFFICE_FILEFORMAT_8 )
+ {
+ *pClassName = SvGlobalName( SO3_SC_CLASSID_60 );
+ *pFormat = bTemplate ? SOT_FORMATSTR_ID_STARCALC_8_TEMPLATE : SOT_FORMATSTR_ID_STARCALC_8;
+ *pFullTypeName = String( RTL_CONSTASCII_USTRINGPARAM("calc8") );
+ *pShortTypeName = String( ScResId( SCSTR_SHORT_SCDOC_NAME ) );
+ }
+ else
+ {
+ DBG_ERROR("wat fuer ne Version?");
+ }
+}
+
+//------------------------------------------------------------------
+
+void ScDocShell::DoEnterHandler()
+{
+ ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
+ if (pViewSh)
+ if (pViewSh->GetViewData()->GetDocShell() == this)
+ SC_MOD()->InputEnterHandler();
+}
+
+//------------------------------------------------------------------
+
+SCTAB ScDocShell::GetSaveTab()
+{
+ SCTAB nTab = 0;
+ ScTabViewShell* pSh = GetBestViewShell();
+ if (pSh)
+ {
+ const ScMarkData& rMark = pSh->GetViewData()->GetMarkData();
+ for ( nTab = 0; nTab <= MAXTAB; nTab++ ) // erste markierte Tabelle
+ if ( rMark.GetTableSelect( nTab ) )
+ break;
+ }
+ return nTab;
+}
+
+sal_uInt16 ScDocShell::GetHiddenInformationState( sal_uInt16 nStates )
+{
+ // get global state like HIDDENINFORMATION_DOCUMENTVERSIONS
+ sal_uInt16 nState = SfxObjectShell::GetHiddenInformationState( nStates );
+
+ if ( nStates & HIDDENINFORMATION_RECORDEDCHANGES )
+ {
+ if ( aDocument.GetChangeTrack() && aDocument.GetChangeTrack()->GetFirst() )
+ nState |= HIDDENINFORMATION_RECORDEDCHANGES;
+ }
+ if ( nStates & HIDDENINFORMATION_NOTES )
+ {
+ SCTAB nTableCount = aDocument.GetTableCount();
+ SCTAB nTable = 0;
+ sal_Bool bFound(sal_False);
+ while ( nTable < nTableCount && !bFound )
+ {
+ ScCellIterator aCellIter( &aDocument, 0,0, nTable, MAXCOL,MAXROW, nTable );
+ for( ScBaseCell* pCell = aCellIter.GetFirst(); pCell && !bFound; pCell = aCellIter.GetNext() )
+ if (pCell->HasNote())
+ bFound = sal_True;
+ nTable++;
+ }
+
+ if (bFound)
+ nState |= HIDDENINFORMATION_NOTES;
+ }
+
+ return nState;
+}
+
+void ScDocShell::BeforeXMLLoading()
+{
+ aDocument.DisableIdle( TRUE );
+
+ // prevent unnecessary broadcasts and updates
+ DBG_ASSERT(pModificator == NULL, "The Modificator should not exist");
+ pModificator = new ScDocShellModificator( *this );
+
+ aDocument.SetImportingXML( TRUE );
+ aDocument.EnableExecuteLink( false ); // #i101304# to be safe, prevent nested loading from external references
+ aDocument.EnableUndo( FALSE );
+ // prevent unnecessary broadcasts and "half way listeners"
+ aDocument.SetInsertingFromOtherDoc( TRUE );
+
+ if (GetCreateMode() != SFX_CREATE_MODE_ORGANIZER)
+ ScColumn::bDoubleAlloc = sal_True;
+}
+
+void ScDocShell::AfterXMLLoading(sal_Bool bRet)
+{
+ if (GetCreateMode() != SFX_CREATE_MODE_ORGANIZER)
+ {
+ UpdateLinks();
+ // don't prevent establishing of listeners anymore
+ aDocument.SetInsertingFromOtherDoc( FALSE );
+ if ( bRet )
+ {
+ ScChartListenerCollection* pChartListener = aDocument.GetChartListenerCollection();
+ if (pChartListener)
+ pChartListener->UpdateDirtyCharts();
+
+ // #95582#; set the table names of linked tables to the new path
+ SCTAB nTabCount = aDocument.GetTableCount();
+ for (SCTAB i = 0; i < nTabCount; ++i)
+ {
+ if (aDocument.IsLinked( i ))
+ {
+ String aName;
+ aDocument.GetName(i, aName);
+ String aLinkTabName = aDocument.GetLinkTab(i);
+ xub_StrLen nLinkTabNameLength = aLinkTabName.Len();
+ xub_StrLen nNameLength = aName.Len();
+ if (nLinkTabNameLength < nNameLength)
+ {
+
+ // remove the quottes on begin and end of the docname and restore the escaped quotes
+ const sal_Unicode* pNameBuffer = aName.GetBuffer();
+ if ( *pNameBuffer == '\'' && // all docnames have to have a ' character on the first pos
+ ScGlobal::UnicodeStrChr( pNameBuffer, SC_COMPILER_FILE_TAB_SEP ) )
+ {
+ rtl::OUStringBuffer aDocURLBuffer;
+ BOOL bQuote = TRUE; // Dokumentenname ist immer quoted
+ ++pNameBuffer;
+ while ( bQuote && *pNameBuffer )
+ {
+ if ( *pNameBuffer == '\'' && *(pNameBuffer-1) != '\\' )
+ bQuote = FALSE;
+ else if( !(*pNameBuffer == '\\' && *(pNameBuffer+1) == '\'') )
+ aDocURLBuffer.append(*pNameBuffer); // falls escaped Quote: nur Quote in den Namen
+ ++pNameBuffer;
+ }
+
+
+ if( *pNameBuffer == SC_COMPILER_FILE_TAB_SEP ) // after the last quote of the docname should be the # char
+ {
+ xub_StrLen nIndex = nNameLength - nLinkTabNameLength;
+ INetURLObject aINetURLObject(aDocURLBuffer.makeStringAndClear());
+ if( aName.Equals(aLinkTabName, nIndex, nLinkTabNameLength) &&
+ (aName.GetChar(nIndex - 1) == '#') && // before the table name should be the # char
+ !aINetURLObject.HasError()) // the docname should be a valid URL
+ {
+ aName = ScGlobal::GetDocTabName( aDocument.GetLinkDoc( i ), aDocument.GetLinkTab( i ) );
+ aDocument.RenameTab(i, aName, TRUE, TRUE);
+ }
+ // else; nothing has to happen, because it is a user given name
+ }
+ // else; nothing has to happen, because it is a user given name
+ }
+ // else; nothing has to happen, because it is a user given name
+ }
+ // else; nothing has to happen, because it is a user given name
+ }
+ }
+ }
+ ScColumn::bDoubleAlloc = sal_False;
+ }
+ else
+ aDocument.SetInsertingFromOtherDoc( FALSE );
+ // add vba globals ( if they are availabl )
+ uno::Any aGlobs;
+ uno::Sequence< uno::Any > aArgs(1);
+ aArgs[ 0 ] <<= GetModel();
+ aGlobs <<= ::comphelper::getProcessServiceFactory()->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.excel.Globals" ) ), aArgs );
+ GetBasicManager()->SetGlobalUNOConstant( "VBAGlobals", aGlobs );
+ // Fake ThisComponent being setup by Activate ( which is a view
+ // related thing ),
+ // a) if another document is opened then in theory ThisComponent
+ // will be reset as before,
+ // b) when this document is 'really' Activated then ThisComponent
+ // again will be set as before
+ // The only wrinkle seems if this document is loaded 'InVisible'
+ // but.. I don't see that this is possible from the vba API
+ // I could be wrong though
+ // There may be implications setting the current component
+ // too early :-/ so I will just manually set the Basic Variables
+ BasicManager* pAppMgr = SFX_APP()->GetBasicManager();
+ if ( pAppMgr )
+ pAppMgr->SetGlobalUNOConstant( "ThisExcelDoc", aArgs[ 0 ] );
+
+ aDocument.SetImportingXML( FALSE );
+ aDocument.EnableExecuteLink( true );
+ aDocument.EnableUndo( TRUE );
+ bIsEmpty = FALSE;
+
+ if (pModificator)
+ {
+ delete pModificator;
+ pModificator = NULL;
+ }
+ else
+ {
+ DBG_ERROR("The Modificator should exist");
+ }
+
+ aDocument.DisableIdle( FALSE );
+}
+
+BOOL ScDocShell::LoadXML( SfxMedium* pLoadMedium, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStor )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "sb99857", "ScDocShell::LoadXML" );
+
+ // MacroCallMode is no longer needed, state is kept in SfxObjectShell now
+
+ // no Seek(0) here - always loading from storage, GetInStream must not be called
+
+ BeforeXMLLoading();
+
+ // #i62677# BeforeXMLLoading is also called from ScXMLImport::startDocument when invoked
+ // from an external component. The XMLFromWrapper flag is only set here, when called
+ // through ScDocShell.
+ aDocument.SetXMLFromWrapper( TRUE );
+
+ ScXMLImportWrapper aImport( aDocument, pLoadMedium, xStor );
+
+ sal_Bool bRet(sal_False);
+ ErrCode nError = ERRCODE_NONE;
+ if (GetCreateMode() != SFX_CREATE_MODE_ORGANIZER)
+ bRet = aImport.Import(sal_False, nError);
+ else
+ bRet = aImport.Import(sal_True, nError);
+
+ if ( nError )
+ pLoadMedium->SetError( nError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+
+ aDocument.SetXMLFromWrapper( FALSE );
+ AfterXMLLoading(bRet);
+
+ //! row heights...
+
+ return bRet;
+}
+
+BOOL ScDocShell::SaveXML( SfxMedium* pSaveMedium, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStor )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "sb99857", "ScDocShell::SaveXML" );
+
+ aDocument.DisableIdle( TRUE );
+
+ ScXMLImportWrapper aImport( aDocument, pSaveMedium, xStor );
+ sal_Bool bRet(sal_False);
+ if (GetCreateMode() != SFX_CREATE_MODE_ORGANIZER)
+ bRet = aImport.Export(sal_False);
+ else
+ bRet = aImport.Export(sal_True);
+
+ aDocument.DisableIdle( FALSE );
+
+ return bRet;
+}
+
+BOOL __EXPORT ScDocShell::Load( SfxMedium& rMedium )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::Load" );
+
+ ScRefreshTimerProtector( aDocument.GetRefreshTimerControlAddress() );
+
+ // only the latin script language is loaded
+ // -> initialize the others from options (before loading)
+ InitOptions();
+
+ GetUndoManager()->Clear();
+
+ BOOL bRet = SfxObjectShell::Load( rMedium );
+ if( bRet )
+ {
+ if (GetMedium())
+ {
+ SFX_ITEMSET_ARG( rMedium.GetItemSet(), pUpdateDocItem, SfxUInt16Item, SID_UPDATEDOCMODE, sal_False);
+ nCanUpdate = pUpdateDocItem ? pUpdateDocItem->GetValue() : com::sun::star::document::UpdateDocMode::NO_UPDATE;
+ }
+
+ {
+ // prepare a valid document for XML filter
+ // (for ConvertFrom, InitNew is called before)
+ aDocument.MakeTable(0);
+ aDocument.GetStyleSheetPool()->CreateStandardStyles();
+ aDocument.UpdStlShtPtrsFrmNms();
+
+ bRet = LoadXML( &rMedium, NULL );
+ }
+ }
+
+ if (!bRet && !rMedium.GetError())
+ rMedium.SetError( SVSTREAM_FILEFORMAT_ERROR, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+
+ if (rMedium.GetError())
+ SetError( rMedium.GetError(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+
+ InitItems();
+ CalcOutputFactor();
+
+ // #73762# invalidate eventually temporary table areas
+ if ( bRet )
+ aDocument.InvalidateTableArea();
+
+ bIsEmpty = FALSE;
+ FinishedLoading( SFX_LOADED_MAINDOCUMENT | SFX_LOADED_IMAGES );
+ return bRet;
+}
+
+
+void __EXPORT ScDocShell::Notify( SfxBroadcaster&, const SfxHint& rHint )
+{
+ if (rHint.ISA(SfxSimpleHint)) // ohne Parameter
+ {
+ ULONG nSlot = ((const SfxSimpleHint&)rHint).GetId();
+ switch ( nSlot )
+ {
+ case SFX_HINT_TITLECHANGED:
+ aDocument.SetName( SfxShell::GetName() );
+ // RegisterNewTargetNames gibts nicht mehr
+ SFX_APP()->Broadcast(SfxSimpleHint( SC_HINT_DOCNAME_CHANGED )); // Navigator
+ break;
+ }
+ }
+ else if (rHint.ISA(SfxStyleSheetHint)) // Vorlagen geaendert
+ NotifyStyle((const SfxStyleSheetHint&) rHint);
+ else if (rHint.ISA(ScAutoStyleHint))
+ {
+ //! direct call for AutoStyles
+
+ // this is called synchronously from ScInterpreter::ScStyle,
+ // modifying the document must be asynchronous
+ // (handled by AddInitial)
+
+ ScAutoStyleHint& rStlHint = (ScAutoStyleHint&)rHint;
+ ScRange aRange = rStlHint.GetRange();
+ String aName1 = rStlHint.GetStyle1();
+ String aName2 = rStlHint.GetStyle2();
+ UINT32 nTimeout = rStlHint.GetTimeout();
+
+ if (!pAutoStyleList)
+ pAutoStyleList = new ScAutoStyleList(this);
+ pAutoStyleList->AddInitial( aRange, aName1, nTimeout, aName2 );
+ }
+ else if ( rHint.ISA( SfxEventHint ) )
+ {
+ ULONG nEventId = ((SfxEventHint&)rHint).GetEventId();
+ switch ( nEventId )
+ {
+ case SFX_EVENT_LOADFINISHED:
+ {
+ // the readonly documents should not be opened in shared mode
+ if ( HasSharedXMLFlagSet() && !SC_MOD()->IsInSharedDocLoading() && !IsReadOnly() )
+ {
+ if ( SwitchToShared( sal_True, sal_False ) )
+ {
+ ScViewData* pViewData = GetViewData();
+ ScTabView* pTabView = ( pViewData ? dynamic_cast< ScTabView* >( pViewData->GetView() ) : NULL );
+ if ( pTabView )
+ {
+ pTabView->UpdateLayerLocks();
+ }
+ }
+ else
+ {
+ // switching to shared mode has failed, the document should be opened readonly
+ // TODO/LATER: And error message should be shown here probably
+ SetReadOnlyUI( sal_True );
+ }
+ }
+ }
+ break;
+ case SFX_EVENT_VIEWCREATED:
+ {
+ if ( IsDocShared() && !SC_MOD()->IsInSharedDocLoading() )
+ {
+ ScAppOptions aAppOptions = SC_MOD()->GetAppOptions();
+ if ( aAppOptions.GetShowSharedDocumentWarning() )
+ {
+ WarningBox aBox( GetActiveDialogParent(), WinBits( WB_OK ),
+ ScGlobal::GetRscString( STR_SHARED_DOC_WARNING ) );
+ aBox.SetDefaultCheckBoxText();
+ aBox.Execute();
+ BOOL bChecked = aBox.GetCheckBoxState();
+ if ( bChecked )
+ {
+ aAppOptions.SetShowSharedDocumentWarning( !bChecked );
+ SC_MOD()->SetAppOptions( aAppOptions );
+ }
+ }
+ }
+ }
+ break;
+ case SFX_EVENT_SAVEDOC:
+ {
+ if ( IsDocShared() && !SC_MOD()->IsInSharedDocSaving() )
+ {
+ bool bSuccess = false;
+ bool bRetry = true;
+ while ( bRetry )
+ {
+ bRetry = false;
+ uno::Reference< frame::XModel > xModel;
+ try
+ {
+ // load shared file
+ xModel.set( LoadSharedDocument(), uno::UNO_QUERY_THROW );
+ uno::Reference< util::XCloseable > xCloseable( xModel, uno::UNO_QUERY_THROW );
+
+ // check if shared flag is set in shared file
+ bool bShared = false;
+ ScModelObj* pDocObj = ScModelObj::getImplementation( xModel );
+ ScDocShell* pSharedDocShell = ( pDocObj ? dynamic_cast< ScDocShell* >( pDocObj->GetObjectShell() ) : NULL );
+ if ( pSharedDocShell )
+ {
+ bShared = pSharedDocShell->HasSharedXMLFlagSet();
+ }
+
+ // #i87870# check if shared status was disabled and enabled again
+ bool bOwnEntry = false;
+ bool bEntriesNotAccessible = false;
+ try
+ {
+ ::svt::ShareControlFile aControlFile( GetSharedFileURL() );
+ bOwnEntry = aControlFile.HasOwnEntry();
+ }
+ catch ( uno::Exception& )
+ {
+ bEntriesNotAccessible = true;
+ }
+
+ if ( bShared && bOwnEntry )
+ {
+ uno::Reference< frame::XStorable > xStorable( xModel, uno::UNO_QUERY_THROW );
+
+ if ( xStorable->isReadonly() )
+ {
+ xCloseable->close( sal_True );
+
+ String aUserName( ScGlobal::GetRscString( STR_UNKNOWN_USER ) );
+ bool bNoLockAccess = false;
+ try
+ {
+ ::svt::DocumentLockFile aLockFile( GetSharedFileURL() );
+ uno::Sequence< ::rtl::OUString > aData = aLockFile.GetLockData();
+ if ( aData.getLength() > LOCKFILE_SYSUSERNAME_ID )
+ {
+ if ( aData[LOCKFILE_OOOUSERNAME_ID].getLength() > 0 )
+ {
+ aUserName = aData[LOCKFILE_OOOUSERNAME_ID];
+ }
+ else if ( aData[LOCKFILE_SYSUSERNAME_ID].getLength() > 0 )
+ {
+ aUserName = aData[LOCKFILE_SYSUSERNAME_ID];
+ }
+ }
+ }
+ catch ( uno::Exception& )
+ {
+ bNoLockAccess = true;
+ }
+
+ if ( bNoLockAccess )
+ {
+ // TODO/LATER: in future an error regarding impossibility to open file for writing could be shown
+ ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
+ }
+ else
+ {
+ String aMessage( ScGlobal::GetRscString( STR_FILE_LOCKED_SAVE_LATER ) );
+ aMessage.SearchAndReplaceAscii( "%1", aUserName );
+
+ WarningBox aBox( GetActiveDialogParent(), WinBits( WB_RETRY_CANCEL | WB_DEF_RETRY ), aMessage );
+ if ( aBox.Execute() == RET_RETRY )
+ {
+ bRetry = true;
+ }
+ }
+ }
+ else
+ {
+ // merge changes from shared file into temp file
+ bool bSaveToShared = false;
+ if ( pSharedDocShell )
+ {
+ bSaveToShared = MergeSharedDocument( pSharedDocShell );
+ }
+
+ // close shared file
+ xCloseable->close( sal_True );
+
+ // TODO: keep file lock on shared file
+
+ // store to shared file
+ if ( bSaveToShared )
+ {
+ bool bChangedViewSettings = false;
+ ScChangeViewSettings* pChangeViewSet = aDocument.GetChangeViewSettings();
+ if ( pChangeViewSet && pChangeViewSet->ShowChanges() )
+ {
+ pChangeViewSet->SetShowChanges( FALSE );
+ pChangeViewSet->SetShowAccepted( FALSE );
+ aDocument.SetChangeViewSettings( *pChangeViewSet );
+ bChangedViewSettings = true;
+ }
+
+ uno::Reference< frame::XStorable > xStor( GetModel(), uno::UNO_QUERY_THROW );
+ // TODO/LATER: More entries from the MediaDescriptor might be interesting for the merge
+ uno::Sequence< beans::PropertyValue > aValues(1);
+ aValues[0].Name = ::rtl::OUString::createFromAscii( "FilterName" );
+ aValues[0].Value <<= ::rtl::OUString( GetMedium()->GetFilter()->GetFilterName() );
+
+ SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pPasswordItem, SfxStringItem, SID_PASSWORD, sal_False);
+ if ( pPasswordItem && pPasswordItem->GetValue().Len() )
+ {
+ aValues.realloc( 2 );
+ aValues[1].Name = ::rtl::OUString::createFromAscii( "Password" );
+ aValues[1].Value <<= ::rtl::OUString( pPasswordItem->GetValue() );
+ }
+
+ SC_MOD()->SetInSharedDocSaving( true );
+ xStor->storeToURL( GetSharedFileURL(), aValues );
+ SC_MOD()->SetInSharedDocSaving( false );
+
+ if ( bChangedViewSettings )
+ {
+ pChangeViewSet->SetShowChanges( TRUE );
+ pChangeViewSet->SetShowAccepted( TRUE );
+ aDocument.SetChangeViewSettings( *pChangeViewSet );
+ }
+ }
+
+ bSuccess = true;
+ GetUndoManager()->Clear();
+ }
+ }
+ else
+ {
+ xCloseable->close( sal_True );
+
+ if ( bEntriesNotAccessible )
+ {
+ // TODO/LATER: in future an error regarding impossibility to write to share control file could be shown
+ ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
+ }
+ else
+ {
+ WarningBox aBox( GetActiveDialogParent(), WinBits( WB_OK ),
+ ScGlobal::GetRscString( STR_DOC_NOLONGERSHARED ) );
+ aBox.Execute();
+
+ SfxBindings* pBindings = GetViewBindings();
+ if ( pBindings )
+ {
+ pBindings->ExecuteSynchron( SID_SAVEASDOC );
+ }
+ }
+ }
+ }
+ catch ( uno::Exception& )
+ {
+ DBG_ERROR( "SFX_EVENT_SAVEDOC: caught exception\n" );
+ SC_MOD()->SetInSharedDocSaving( false );
+
+ try
+ {
+ uno::Reference< util::XCloseable > xClose( xModel, uno::UNO_QUERY_THROW );
+ xClose->close( sal_True );
+ }
+ catch ( uno::Exception& )
+ {
+ }
+ }
+ }
+
+ if ( !bSuccess )
+ SetError( ERRCODE_IO_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); // this error code will produce no error message, but will break the further saving process
+ }
+ }
+ break;
+ case SFX_EVENT_SAVEDOCDONE:
+ {
+ if ( IsDocShared() && !SC_MOD()->IsInSharedDocSaving() )
+ {
+ }
+ UseSheetSaveEntries(); // use positions from saved file for next saving
+ }
+ break;
+ case SFX_EVENT_SAVEASDOCDONE:
+ // new positions are used after "save" and "save as", but not "save to"
+ UseSheetSaveEntries(); // use positions from saved file for next saving
+ break;
+ default:
+ {
+ }
+ break;
+ }
+ }
+}
+
+ // Inhalte fuer Organizer laden
+
+
+BOOL __EXPORT ScDocShell::LoadFrom( SfxMedium& rMedium )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::LoadFrom" );
+
+ ScRefreshTimerProtector( aDocument.GetRefreshTimerControlAddress() );
+
+ WaitObject aWait( GetActiveDialogParent() );
+
+ BOOL bRet = FALSE;
+
+ if (GetMedium())
+ {
+ SFX_ITEMSET_ARG( rMedium.GetItemSet(), pUpdateDocItem, SfxUInt16Item, SID_UPDATEDOCMODE, sal_False);
+ nCanUpdate = pUpdateDocItem ? pUpdateDocItem->GetValue() : com::sun::star::document::UpdateDocMode::NO_UPDATE;
+ }
+
+ // until loading/saving only the styles in XML is implemented,
+ // load the whole file
+ bRet = LoadXML( &rMedium, NULL );
+ InitItems();
+
+ SfxObjectShell::LoadFrom( rMedium );
+
+ return bRet;
+}
+
+
+BOOL __EXPORT ScDocShell::ConvertFrom( SfxMedium& rMedium )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::ConvertFrom" );
+
+ BOOL bRet = FALSE; // FALSE heisst Benutzerabbruch !!
+ // bei Fehler: Fehler am Stream setzen!!
+
+ ScRefreshTimerProtector( aDocument.GetRefreshTimerControlAddress() );
+
+ GetUndoManager()->Clear();
+
+ // ob nach dem Import optimale Spaltenbreiten gesetzt werden sollen
+ BOOL bSetColWidths = FALSE;
+ BOOL bSetSimpleTextColWidths = FALSE;
+ BOOL bSimpleColWidth[MAXCOLCOUNT];
+ memset( bSimpleColWidth, 1, (MAXCOLCOUNT) * sizeof(BOOL) );
+ ScRange aColWidthRange;
+ // ob nach dem Import optimale Zeilenhoehen gesetzt werden sollen
+ BOOL bSetRowHeights = FALSE;
+
+ aConvFilterName.Erase(); //@ #BugId 54198
+
+ // Alle Filter brauchen die komplette Datei am Stueck (nicht asynchron),
+ // darum vorher per CreateFileStream dafuer sorgen, dass die komplette
+ // Datei uebertragen wird.
+ rMedium.GetPhysicalName(); //! CreateFileStream direkt rufen, wenn verfuegbar
+
+ SFX_ITEMSET_ARG( rMedium.GetItemSet(), pUpdateDocItem, SfxUInt16Item, SID_UPDATEDOCMODE, sal_False);
+ nCanUpdate = pUpdateDocItem ? pUpdateDocItem->GetValue() : com::sun::star::document::UpdateDocMode::NO_UPDATE;
+
+ const SfxFilter* pFilter = rMedium.GetFilter();
+ if (pFilter)
+ {
+ String aFltName = pFilter->GetFilterName();
+
+ aConvFilterName=aFltName; //@ #BugId 54198
+
+ BOOL bCalc3 = ( aFltName.EqualsAscii(pFilterSc30) );
+ BOOL bCalc4 = ( aFltName.EqualsAscii(pFilterSc40) );
+ if (!bCalc3 && !bCalc4)
+ aDocument.SetInsertingFromOtherDoc( TRUE );
+
+ if (aFltName.EqualsAscii(pFilterXML))
+ bRet = LoadXML( &rMedium, NULL );
+ else if (aFltName.EqualsAscii(pFilterSc10))
+ {
+ SvStream* pStream = rMedium.GetInStream();
+ if (pStream)
+ {
+ FltError eError = ScFormatFilter::Get().ScImportStarCalc10( *pStream, &aDocument );
+ if (eError != eERR_OK)
+ {
+ if (!GetError())
+ SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
+ }
+ else
+ bRet = TRUE;
+ }
+ }
+ else if (aFltName.EqualsAscii(pFilterLotus))
+ {
+ String sItStr;
+ SfxItemSet* pSet = rMedium.GetItemSet();
+ const SfxPoolItem* pItem;
+ if ( pSet && SFX_ITEM_SET ==
+ pSet->GetItemState( SID_FILE_FILTEROPTIONS, TRUE, &pItem ) )
+ {
+ sItStr = ((const SfxStringItem*)pItem)->GetValue();
+ }
+
+ if (sItStr.Len() == 0)
+ {
+ // default for lotus import (from API without options):
+ // IBM_437 encoding
+ sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_IBM_437 );
+ }
+
+ ScColumn::bDoubleAlloc = TRUE;
+ FltError eError = ScFormatFilter::Get().ScImportLotus123( rMedium, &aDocument,
+ ScGlobal::GetCharsetValue(sItStr));
+ ScColumn::bDoubleAlloc = FALSE;
+ if (eError != eERR_OK)
+ {
+ if (!GetError())
+ SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
+
+ if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
+ bRet = TRUE;
+ }
+ else
+ bRet = TRUE;
+ bSetColWidths = TRUE;
+ bSetRowHeights = TRUE;
+ }
+ else if ( aFltName.EqualsAscii(pFilterExcel4) || aFltName.EqualsAscii(pFilterExcel5) ||
+ aFltName.EqualsAscii(pFilterExcel95) || aFltName.EqualsAscii(pFilterExcel97) ||
+ aFltName.EqualsAscii(pFilterEx4Temp) || aFltName.EqualsAscii(pFilterEx5Temp) ||
+ aFltName.EqualsAscii(pFilterEx95Temp) || aFltName.EqualsAscii(pFilterEx97Temp) )
+ {
+ EXCIMPFORMAT eFormat = EIF_AUTO;
+ if ( aFltName.EqualsAscii(pFilterExcel4) || aFltName.EqualsAscii(pFilterEx4Temp) )
+ eFormat = EIF_BIFF_LE4;
+ else if ( aFltName.EqualsAscii(pFilterExcel5) || aFltName.EqualsAscii(pFilterExcel95) ||
+ aFltName.EqualsAscii(pFilterEx5Temp) || aFltName.EqualsAscii(pFilterEx95Temp) )
+ eFormat = EIF_BIFF5;
+ else if ( aFltName.EqualsAscii(pFilterExcel97) || aFltName.EqualsAscii(pFilterEx97Temp) )
+ eFormat = EIF_BIFF8;
+
+ MakeDrawLayer(); //! im Filter
+ CalcOutputFactor(); // #93255# prepare update of row height
+ ScColumn::bDoubleAlloc = TRUE;
+ FltError eError = ScFormatFilter::Get().ScImportExcel( rMedium, &aDocument, eFormat );
+ ScColumn::bDoubleAlloc = FALSE;
+ aDocument.UpdateFontCharSet();
+ if ( aDocument.IsChartListenerCollectionNeedsUpdate() )
+ aDocument.UpdateChartListenerCollection(); //! fuer alle Importe?
+
+ // #75299# all graphics objects must have names
+ aDocument.EnsureGraphicNames();
+
+ if (eError == SCWARN_IMPORT_RANGE_OVERFLOW)
+ {
+ if (!GetError())
+ SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
+ bRet = TRUE;
+ }
+ else if (eError != eERR_OK)
+ {
+ if (!GetError())
+ SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
+ }
+ else
+ bRet = TRUE;
+
+ // #93255# update of row height done inside of Excel filter to speed up chart import
+// bSetRowHeights = TRUE; // #75357# optimal row heights must be updated
+ }
+ else if (aFltName.EqualsAscii(pFilterAscii))
+ {
+ SfxItemSet* pSet = rMedium.GetItemSet();
+ const SfxPoolItem* pItem;
+ ScAsciiOptions aOptions;
+ BOOL bOptInit = FALSE;
+
+ if ( pSet && SFX_ITEM_SET ==
+ pSet->GetItemState( SID_FILE_FILTEROPTIONS, TRUE, &pItem ) )
+ {
+ aOptions.ReadFromString( ((const SfxStringItem*)pItem)->GetValue() );
+ bOptInit = TRUE;
+ }
+
+ if ( !bOptInit )
+ {
+ // default for ascii import (from API without options):
+ // ISO8859-1/MS_1252 encoding, comma, double quotes
+
+ aOptions.SetCharSet( RTL_TEXTENCODING_MS_1252 );
+ aOptions.SetFieldSeps( (sal_Unicode) ',' );
+ aOptions.SetTextSep( (sal_Unicode) '"' );
+ }
+
+ FltError eError = eERR_OK;
+ BOOL bOverflow = FALSE;
+
+ if( ! rMedium.IsStorage() )
+ {
+ ScImportExport aImpEx( &aDocument );
+ aImpEx.SetExtOptions( aOptions );
+
+ SvStream* pInStream = rMedium.GetInStream();
+ if (pInStream)
+ {
+ pInStream->SetStreamCharSet( aOptions.GetCharSet() );
+ pInStream->Seek( 0 );
+ bRet = aImpEx.ImportStream( *pInStream, rMedium.GetBaseURL() );
+ eError = bRet ? eERR_OK : SCERR_IMPORT_CONNECT;
+ aDocument.StartAllListeners();
+ aDocument.SetDirty();
+ bOverflow = aImpEx.IsOverflow();
+ }
+ else
+ {
+ DBG_ERROR( "No Stream" );
+ }
+ }
+
+ if (eError != eERR_OK)
+ {
+ if (!GetError())
+ SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
+ }
+ else if ( bOverflow )
+ {
+ if (!GetError())
+ SetError(SCWARN_IMPORT_RANGE_OVERFLOW, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
+ }
+ bSetColWidths = TRUE;
+ bSetSimpleTextColWidths = TRUE;
+ }
+ else if (aFltName.EqualsAscii(pFilterDBase))
+ {
+ String sItStr;
+ SfxItemSet* pSet = rMedium.GetItemSet();
+ const SfxPoolItem* pItem;
+ if ( pSet && SFX_ITEM_SET ==
+ pSet->GetItemState( SID_FILE_FILTEROPTIONS, TRUE, &pItem ) )
+ {
+ sItStr = ((const SfxStringItem*)pItem)->GetValue();
+ }
+
+ if (sItStr.Len() == 0)
+ {
+ // default for dBase import (from API without options):
+ // IBM_850 encoding
+
+ sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_IBM_850 );
+ }
+
+ ULONG eError = DBaseImport( rMedium.GetPhysicalName(),
+ ScGlobal::GetCharsetValue(sItStr), bSimpleColWidth );
+
+ if (eError != eERR_OK)
+ {
+ if (!GetError())
+ SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
+ bRet = ( eError == SCWARN_IMPORT_RANGE_OVERFLOW );
+ }
+ else
+ bRet = TRUE;
+
+ aColWidthRange.aStart.SetRow( 1 ); // Spaltenheader nicht
+ bSetColWidths = TRUE;
+ bSetSimpleTextColWidths = TRUE;
+ // Memo-Felder fuehren zu einem bSimpleColWidth[nCol]==FALSE
+ for ( SCCOL nCol=0; nCol <= MAXCOL && !bSetRowHeights; nCol++ )
+ {
+ if ( !bSimpleColWidth[nCol] )
+ bSetRowHeights = TRUE;
+ }
+ }
+ else if (aFltName.EqualsAscii(pFilterDif))
+ {
+ SvStream* pStream = rMedium.GetInStream();
+ if (pStream)
+ {
+ FltError eError;
+ String sItStr;
+ SfxItemSet* pSet = rMedium.GetItemSet();
+ const SfxPoolItem* pItem;
+ if ( pSet && SFX_ITEM_SET ==
+ pSet->GetItemState( SID_FILE_FILTEROPTIONS, TRUE, &pItem ) )
+ {
+ sItStr = ((const SfxStringItem*)pItem)->GetValue();
+ }
+
+ if (sItStr.Len() == 0)
+ {
+ // default for DIF import (from API without options):
+ // ISO8859-1/MS_1252 encoding
+
+ sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_MS_1252 );
+ }
+
+ eError = ScFormatFilter::Get().ScImportDif( *pStream, &aDocument, ScAddress(0,0,0),
+ ScGlobal::GetCharsetValue(sItStr));
+ if (eError != eERR_OK)
+ {
+ if (!GetError())
+ SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
+
+ if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
+ bRet = TRUE;
+ }
+ else
+ bRet = TRUE;
+ }
+ bSetColWidths = TRUE;
+ bSetSimpleTextColWidths = TRUE;
+ bSetRowHeights = TRUE;
+ }
+ else if (aFltName.EqualsAscii(pFilterSylk))
+ {
+ FltError eError = SCERR_IMPORT_UNKNOWN;
+ if( !rMedium.IsStorage() )
+ {
+ ScImportExport aImpEx( &aDocument );
+
+ SvStream* pInStream = rMedium.GetInStream();
+ if (pInStream)
+ {
+ pInStream->Seek( 0 );
+ bRet = aImpEx.ImportStream( *pInStream, rMedium.GetBaseURL(), SOT_FORMATSTR_ID_SYLK );
+ eError = bRet ? eERR_OK : SCERR_IMPORT_UNKNOWN;
+ aDocument.StartAllListeners();
+ aDocument.SetDirty();
+ }
+ else
+ {
+ DBG_ERROR( "No Stream" );
+ }
+ }
+
+ if ( eError != eERR_OK && !GetError() )
+ SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
+ bSetColWidths = TRUE;
+ bSetSimpleTextColWidths = TRUE;
+ bSetRowHeights = TRUE;
+ }
+ else if (aFltName.EqualsAscii(pFilterQPro6))
+ {
+ ScColumn::bDoubleAlloc = TRUE;
+ FltError eError = ScFormatFilter::Get().ScImportQuattroPro( rMedium, &aDocument);
+ ScColumn::bDoubleAlloc = FALSE;
+ if (eError != eERR_OK)
+ {
+ if (!GetError())
+ SetError( eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+ if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
+ bRet = TRUE;
+ }
+ else
+ bRet = TRUE;
+ // TODO: Filter should set column widths. Not doing it here, it may
+ // result in very narrow or wide columns, depending on content.
+ // Setting row heights makes cells with font size attribution or
+ // wrapping enabled look nicer..
+ bSetRowHeights = TRUE;
+ }
+ else if (aFltName.EqualsAscii(pFilterRtf))
+ {
+ FltError eError = SCERR_IMPORT_UNKNOWN;
+ if( !rMedium.IsStorage() )
+ {
+ SvStream* pInStream = rMedium.GetInStream();
+ if (pInStream)
+ {
+ pInStream->Seek( 0 );
+ ScRange aRange;
+ eError = ScFormatFilter::Get().ScImportRTF( *pInStream, rMedium.GetBaseURL(), &aDocument, aRange );
+ if (eError != eERR_OK)
+ {
+ if (!GetError())
+ SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
+
+ if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
+ bRet = TRUE;
+ }
+ else
+ bRet = TRUE;
+ aDocument.StartAllListeners();
+ aDocument.SetDirty();
+ bSetColWidths = TRUE;
+ bSetRowHeights = TRUE;
+ }
+ else
+ {
+ DBG_ERROR( "No Stream" );
+ }
+ }
+
+ if ( eError != eERR_OK && !GetError() )
+ SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
+ }
+ else if (aFltName.EqualsAscii(pFilterHtml) || aFltName.EqualsAscii(pFilterHtmlWebQ))
+ {
+ FltError eError = SCERR_IMPORT_UNKNOWN;
+ BOOL bWebQuery = aFltName.EqualsAscii(pFilterHtmlWebQ);
+ if( !rMedium.IsStorage() )
+ {
+ SvStream* pInStream = rMedium.GetInStream();
+ if (pInStream)
+ {
+ pInStream->Seek( 0 );
+ ScRange aRange;
+ // HTML macht eigenes ColWidth/RowHeight
+ CalcOutputFactor();
+ eError = ScFormatFilter::Get().ScImportHTML( *pInStream, rMedium.GetBaseURL(), &aDocument, aRange,
+ GetOutputFactor(), !bWebQuery );
+ if (eError != eERR_OK)
+ {
+ if (!GetError())
+ SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
+
+ if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
+ bRet = TRUE;
+ }
+ else
+ bRet = TRUE;
+ aDocument.StartAllListeners();
+ aDocument.SetDirty();
+ }
+ else
+ {
+ DBG_ERROR( "No Stream" );
+ }
+ }
+
+ if ( eError != eERR_OK && !GetError() )
+ SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
+ }
+ else
+ {
+ if (!GetError())
+ SetError(SCERR_IMPORT_NI, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
+ }
+
+ if (!bCalc3)
+ aDocument.SetInsertingFromOtherDoc( FALSE );
+ }
+ else
+ {
+ DBG_ERROR("Kein Filter bei ConvertFrom");
+ }
+
+ InitItems();
+ CalcOutputFactor();
+ if ( bRet && (bSetColWidths || bSetRowHeights) )
+ { // Spaltenbreiten/Zeilenhoehen anpassen, Basis 100% Zoom
+ Fraction aZoom( 1, 1 );
+ double nPPTX = ScGlobal::nScreenPPTX * (double) aZoom
+ / GetOutputFactor(); // Faktor ist Drucker zu Bildschirm
+ double nPPTY = ScGlobal::nScreenPPTY * (double) aZoom;
+ VirtualDevice aVirtDev;
+ // all sheets (for Excel import)
+ SCTAB nTabCount = aDocument.GetTableCount();
+ for (SCTAB nTab=0; nTab<nTabCount; nTab++)
+ {
+ SCCOL nEndCol;
+ SCROW nEndRow;
+ aDocument.GetCellArea( nTab, nEndCol, nEndRow );
+ aColWidthRange.aEnd.SetCol( nEndCol );
+ aColWidthRange.aEnd.SetRow( nEndRow );
+ ScMarkData aMark;
+ aMark.SetMarkArea( aColWidthRange );
+ aMark.MarkToMulti();
+ // Reihenfolge erst Breite dann Hoehe ist wichtig (vergl. hund.rtf)
+ if ( bSetColWidths )
+ {
+ for ( SCCOL nCol=0; nCol <= nEndCol; nCol++ )
+ {
+ USHORT nWidth = aDocument.GetOptimalColWidth(
+ nCol, nTab, &aVirtDev, nPPTX, nPPTY, aZoom, aZoom, FALSE, &aMark,
+ (bSetSimpleTextColWidths && bSimpleColWidth[nCol]) );
+ aDocument.SetColWidth( nCol, nTab,
+ nWidth + (USHORT)ScGlobal::nLastColWidthExtra );
+ }
+ }
+// if ( bSetRowHeights )
+// {
+// // nExtra must be 0
+// aDocument.SetOptimalHeight( 0, nEndRow, nTab, 0, &aVirtDev,
+// nPPTX, nPPTY, aZoom, aZoom, FALSE );
+// }
+ }
+ if ( bSetRowHeights )
+ UpdateAllRowHeights(); // with vdev or printer, depending on configuration
+ }
+ FinishedLoading( SFX_LOADED_MAINDOCUMENT | SFX_LOADED_IMAGES );
+
+ // #73762# invalidate eventually temporary table areas
+ if ( bRet )
+ aDocument.InvalidateTableArea();
+
+ bIsEmpty = FALSE;
+
+ return bRet;
+}
+
+
+ScDocShell::PrepareSaveGuard::PrepareSaveGuard( ScDocShell& rDocShell )
+ : mrDocShell( rDocShell)
+{
+ // DoEnterHandler not here (because of AutoSave), is in ExecuteSave.
+
+ ScChartListenerCollection* pCharts = mrDocShell.aDocument.GetChartListenerCollection();
+ if (pCharts)
+ pCharts->UpdateDirtyCharts(); // Charts to be updated.
+ mrDocShell.aDocument.StopTemporaryChartLock();
+ if (mrDocShell.pAutoStyleList)
+ mrDocShell.pAutoStyleList->ExecuteAllNow(); // Execute template timeouts now.
+ if (mrDocShell.aDocument.HasExternalRefManager())
+ {
+ ScExternalRefManager* pRefMgr = mrDocShell.aDocument.GetExternalRefManager();
+ if (pRefMgr && pRefMgr->hasExternalData())
+ {
+ pRefMgr->setAllCacheTableReferencedStati( false);
+ mrDocShell.aDocument.MarkUsedExternalReferences(); // Mark tables of external references to be written.
+ }
+ }
+ if (mrDocShell.GetCreateMode()== SFX_CREATE_MODE_STANDARD)
+ mrDocShell.SfxObjectShell::SetVisArea( Rectangle() ); // "Normally" worked on => no VisArea.
+}
+
+ScDocShell::PrepareSaveGuard::~PrepareSaveGuard()
+{
+ if (mrDocShell.aDocument.HasExternalRefManager())
+ {
+ ScExternalRefManager* pRefMgr = mrDocShell.aDocument.GetExternalRefManager();
+ if (pRefMgr && pRefMgr->hasExternalData())
+ {
+ // Prevent accidental data loss due to lack of knowledge.
+ pRefMgr->setAllCacheTableReferencedStati( true);
+ }
+ }
+}
+
+
+BOOL __EXPORT ScDocShell::Save()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::Save" );
+
+ ScRefreshTimerProtector( aDocument.GetRefreshTimerControlAddress() );
+
+ PrepareSaveGuard aPrepareGuard( *this);
+
+ // wait cursor is handled with progress bar
+ BOOL bRet = SfxObjectShell::Save();
+ if( bRet )
+ bRet = SaveXML( GetMedium(), NULL );
+ return bRet;
+}
+
+
+BOOL __EXPORT ScDocShell::SaveAs( SfxMedium& rMedium )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::SaveAs" );
+
+#if ENABLE_SHEET_PROTECTION
+ ScTabViewShell* pViewShell = GetBestViewShell();
+ if (pViewShell && ScPassHashHelper::needsPassHashRegen(aDocument, PASSHASH_OOO))
+ {
+ if (!pViewShell->ExecuteRetypePassDlg(PASSHASH_OOO))
+ // password re-type cancelled. Don't save the document.
+ return false;
+ }
+#endif
+
+ ScRefreshTimerProtector( aDocument.GetRefreshTimerControlAddress() );
+
+ PrepareSaveGuard aPrepareGuard( *this);
+
+ // wait cursor is handled with progress bar
+ BOOL bRet = SfxObjectShell::SaveAs( rMedium );
+ if( bRet )
+ bRet = SaveXML( &rMedium, NULL );
+
+ return bRet;
+}
+
+
+BOOL __EXPORT ScDocShell::IsInformationLost()
+{
+/*
+ const SfxFilter *pFilt = GetMedium()->GetFilter();
+ BOOL bRet = pFilt && pFilt->IsAlienFormat() && bNoInformLost;
+ if (bNoInformLost) // nur einmal!!
+ bNoInformLost = FALSE;
+ return bRet;
+*/
+ //!!! bei Gelegenheit ein korrekte eigene Behandlung einbauen
+
+ return SfxObjectShell::IsInformationLost();
+}
+
+
+// Xcl-like column width measured in characters of standard font.
+xub_StrLen lcl_ScDocShell_GetColWidthInChars( USHORT nWidth )
+{
+ // double fColScale = 1.0;
+ double f = nWidth;
+ f *= 1328.0 / 25.0;
+ f += 90.0;
+ f *= 1.0 / 23.0;
+ // f /= fColScale * 256.0;
+ f /= 256.0;
+
+ return xub_StrLen( f );
+}
+
+
+void lcl_ScDocShell_GetFixedWidthString( String& rStr, const ScDocument& rDoc,
+ SCTAB nTab, SCCOL nCol, BOOL bValue, SvxCellHorJustify eHorJust )
+{
+ xub_StrLen nLen = lcl_ScDocShell_GetColWidthInChars(
+ rDoc.GetColWidth( nCol, nTab ) );
+ if ( nLen < rStr.Len() )
+ {
+ if ( bValue )
+ rStr.AssignAscii( "###" );
+ rStr.Erase( nLen );
+ }
+ if ( nLen > rStr.Len() )
+ {
+ if ( bValue && eHorJust == SVX_HOR_JUSTIFY_STANDARD )
+ eHorJust = SVX_HOR_JUSTIFY_RIGHT;
+ switch ( eHorJust )
+ {
+ case SVX_HOR_JUSTIFY_RIGHT:
+ {
+ String aTmp;
+ aTmp.Fill( nLen - rStr.Len() );
+ rStr.Insert( aTmp, 0 );
+ }
+ break;
+ case SVX_HOR_JUSTIFY_CENTER:
+ {
+ xub_StrLen nLen2 = (nLen - rStr.Len()) / 2;
+ String aTmp;
+ aTmp.Fill( nLen2 );
+ rStr.Insert( aTmp, 0 );
+ rStr.Expand( nLen );
+ }
+ break;
+ default:
+ rStr.Expand( nLen );
+ }
+ }
+}
+
+
+void lcl_ScDocShell_WriteEmptyFixedWidthString( SvStream& rStream,
+ const ScDocument& rDoc, SCTAB nTab, SCCOL nCol )
+{
+ String aString;
+ lcl_ScDocShell_GetFixedWidthString( aString, rDoc, nTab, nCol, FALSE,
+ SVX_HOR_JUSTIFY_STANDARD );
+ rStream.WriteUnicodeOrByteText( aString );
+}
+
+
+void ScDocShell::AsciiSave( SvStream& rStream, const ScImportOptions& rAsciiOpt )
+{
+ sal_Unicode cDelim = rAsciiOpt.nFieldSepCode;
+ sal_Unicode cStrDelim = rAsciiOpt.nTextSepCode;
+ CharSet eCharSet = rAsciiOpt.eCharSet;
+ BOOL bFixedWidth = rAsciiOpt.bFixedWidth;
+ BOOL bSaveAsShown = rAsciiOpt.bSaveAsShown;
+
+ CharSet eOldCharSet = rStream.GetStreamCharSet();
+ rStream.SetStreamCharSet( eCharSet );
+ USHORT nOldNumberFormatInt = rStream.GetNumberFormatInt();
+ ByteString aStrDelimEncoded; // only used if not Unicode
+ UniString aStrDelimDecoded; // only used if context encoding
+ BOOL bContextOrNotAsciiEncoding;
+ if ( eCharSet == RTL_TEXTENCODING_UNICODE )
+ {
+ rStream.StartWritingUnicodeText();
+ bContextOrNotAsciiEncoding = FALSE;
+ }
+ else
+ {
+ aStrDelimEncoded = ByteString( cStrDelim, eCharSet );
+ rtl_TextEncodingInfo aInfo;
+ aInfo.StructSize = sizeof(aInfo);
+ if ( rtl_getTextEncodingInfo( eCharSet, &aInfo ) )
+ {
+ bContextOrNotAsciiEncoding =
+ (((aInfo.Flags & RTL_TEXTENCODING_INFO_CONTEXT) != 0) ||
+ ((aInfo.Flags & RTL_TEXTENCODING_INFO_ASCII) == 0));
+ if ( bContextOrNotAsciiEncoding )
+ aStrDelimDecoded = String( aStrDelimEncoded, eCharSet );
+ }
+ else
+ bContextOrNotAsciiEncoding = FALSE;
+ }
+
+ SCCOL nStartCol = 0;
+ SCROW nStartRow = 0;
+ SCTAB nTab = GetSaveTab();
+ SCCOL nEndCol;
+ SCROW nEndRow;
+ aDocument.GetCellArea( nTab, nEndCol, nEndRow );
+
+ ScProgress aProgress( this, ScGlobal::GetRscString( STR_SAVE_DOC ), nEndRow );
+
+ String aString;
+
+ ScTabViewShell* pViewSh = PTR_CAST(ScTabViewShell, SfxViewShell::Current());
+ const ScViewOptions& rOpt = (pViewSh)
+ ? pViewSh->GetViewData()->GetOptions()
+ : aDocument.GetViewOptions();
+ BOOL bShowFormulas = rOpt.GetOption( VOPT_FORMULAS );
+ BOOL bTabProtect = aDocument.IsTabProtected( nTab );
+
+ SCCOL nCol;
+ SCROW nRow;
+ SCCOL nNextCol = nStartCol;
+ SCROW nNextRow = nStartRow;
+ SCCOL nEmptyCol;
+ SCROW nEmptyRow;
+ SvNumberFormatter& rFormatter = *aDocument.GetFormatTable();
+
+ ScHorizontalCellIterator aIter( &aDocument, nTab, nStartCol, nStartRow,
+ nEndCol, nEndRow );
+ ScBaseCell* pCell;
+ while ( ( pCell = aIter.GetNext( nCol, nRow ) ) != NULL )
+ {
+ BOOL bProgress = FALSE; // only upon line change
+ if ( nNextRow < nRow )
+ { // empty rows or/and empty columns up to end of row
+ bProgress = TRUE;
+ for ( nEmptyCol = nNextCol; nEmptyCol < nEndCol; nEmptyCol++ )
+ { // remaining columns of last row
+ if ( bFixedWidth )
+ lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
+ aDocument, nTab, nEmptyCol );
+ else if ( cDelim != 0 )
+ rStream.WriteUniOrByteChar( cDelim );
+ }
+ endlub( rStream );
+ nNextRow++;
+ for ( nEmptyRow = nNextRow; nEmptyRow < nRow; nEmptyRow++ )
+ { // completely empty rows
+ for ( nEmptyCol = nStartCol; nEmptyCol < nEndCol; nEmptyCol++ )
+ {
+ if ( bFixedWidth )
+ lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
+ aDocument, nTab, nEmptyCol );
+ else if ( cDelim != 0 )
+ rStream.WriteUniOrByteChar( cDelim );
+ }
+ endlub( rStream );
+ }
+ for ( nEmptyCol = nStartCol; nEmptyCol < nCol; nEmptyCol++ )
+ { // empty columns at beginning of row
+ if ( bFixedWidth )
+ lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
+ aDocument, nTab, nEmptyCol );
+ else if ( cDelim != 0 )
+ rStream.WriteUniOrByteChar( cDelim );
+ }
+ nNextRow = nRow;
+ }
+ else if ( nNextCol < nCol )
+ { // empty columns in same row
+ for ( nEmptyCol = nNextCol; nEmptyCol < nCol; nEmptyCol++ )
+ { // columns in between
+ if ( bFixedWidth )
+ lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
+ aDocument, nTab, nEmptyCol );
+ else if ( cDelim != 0 )
+ rStream.WriteUniOrByteChar( cDelim );
+ }
+ }
+ if ( nCol == nEndCol )
+ {
+ bProgress = TRUE;
+ nNextCol = nStartCol;
+ nNextRow = nRow + 1;
+ }
+ else
+ nNextCol = nCol + 1;
+
+ CellType eType = pCell->GetCellType();
+ if ( bTabProtect )
+ {
+ const ScProtectionAttr* pProtAttr =
+ (const ScProtectionAttr*) aDocument.GetAttr(
+ nCol, nRow, nTab, ATTR_PROTECTION );
+ if ( pProtAttr->GetHideCell() ||
+ ( eType == CELLTYPE_FORMULA && bShowFormulas &&
+ pProtAttr->GetHideFormula() ) )
+ eType = CELLTYPE_NONE; // hide
+ }
+ BOOL bString;
+ switch ( eType )
+ {
+ case CELLTYPE_NOTE:
+ case CELLTYPE_NONE:
+ aString.Erase();
+ bString = FALSE;
+ break;
+ case CELLTYPE_FORMULA :
+ {
+ USHORT nErrCode;
+ if ( bShowFormulas )
+ {
+ ((ScFormulaCell*)pCell)->GetFormula( aString );
+ bString = TRUE;
+ }
+ else if ( ( nErrCode = ((ScFormulaCell*)pCell)->GetErrCode() ) != 0 )
+ {
+ aString = ScGlobal::GetErrorString( nErrCode );
+ bString = TRUE;
+ }
+ else if ( ((ScFormulaCell*)pCell)->IsValue() )
+ {
+ sal_uInt32 nFormat;
+ aDocument.GetNumberFormat( nCol, nRow, nTab, nFormat );
+ if ( bFixedWidth || bSaveAsShown )
+ {
+ Color* pDummy;
+ ScCellFormat::GetString( pCell, nFormat, aString, &pDummy, rFormatter );
+ bString = bSaveAsShown && rFormatter.IsTextFormat( nFormat);
+ }
+ else
+ {
+ ScCellFormat::GetInputString( pCell, nFormat, aString, rFormatter );
+ bString = FALSE;
+ }
+ }
+ else
+ {
+ if ( bSaveAsShown )
+ {
+ sal_uInt32 nFormat;
+ aDocument.GetNumberFormat( nCol, nRow, nTab, nFormat );
+ Color* pDummy;
+ ScCellFormat::GetString( pCell, nFormat, aString, &pDummy, rFormatter );
+ }
+ else
+ ((ScFormulaCell*)pCell)->GetString( aString );
+ bString = TRUE;
+ }
+ }
+ break;
+ case CELLTYPE_STRING :
+ if ( bSaveAsShown )
+ {
+ sal_uInt32 nFormat;
+ aDocument.GetNumberFormat( nCol, nRow, nTab, nFormat );
+ Color* pDummy;
+ ScCellFormat::GetString( pCell, nFormat, aString, &pDummy, rFormatter );
+ }
+ else
+ ((ScStringCell*)pCell)->GetString( aString );
+ bString = TRUE;
+ break;
+ case CELLTYPE_EDIT :
+ {
+ const EditTextObject* pObj;
+ static_cast<const ScEditCell*>(pCell)->GetData( pObj);
+ EditEngine& rEngine = aDocument.GetEditEngine();
+ rEngine.SetText( *pObj);
+ aString = rEngine.GetText(); // including LF
+ bString = TRUE;
+ }
+ break;
+ case CELLTYPE_VALUE :
+ {
+ sal_uInt32 nFormat;
+ aDocument.GetNumberFormat( nCol, nRow, nTab, nFormat );
+ if ( bFixedWidth || bSaveAsShown )
+ {
+ Color* pDummy;
+ ScCellFormat::GetString( pCell, nFormat, aString, &pDummy, rFormatter );
+ bString = bSaveAsShown && rFormatter.IsTextFormat( nFormat);
+ }
+ else
+ {
+ ScCellFormat::GetInputString( pCell, nFormat, aString, rFormatter );
+ bString = FALSE;
+ }
+ }
+ break;
+ default:
+ DBG_ERROR( "ScDocShell::AsciiSave: unknown CellType" );
+ aString.Erase();
+ bString = FALSE;
+ }
+
+ if ( bFixedWidth )
+ {
+ SvxCellHorJustify eHorJust = (SvxCellHorJustify)
+ ((const SvxHorJustifyItem*) aDocument.GetAttr( nCol, nRow,
+ nTab, ATTR_HOR_JUSTIFY ))->GetValue();
+ lcl_ScDocShell_GetFixedWidthString( aString, aDocument, nTab, nCol,
+ !bString, eHorJust );
+ rStream.WriteUnicodeOrByteText( aString );
+ }
+ else
+ {
+ if (!bString && cStrDelim != 0 && aString.Len() > 0)
+ {
+ sal_Unicode c = aString.GetChar(0);
+ bString = (c == cStrDelim || c == ' ' ||
+ aString.GetChar( aString.Len()-1) == ' ' ||
+ aString.Search( cStrDelim) != STRING_NOTFOUND);
+ if (!bString && cDelim != 0)
+ bString = (aString.Search( cDelim) != STRING_NOTFOUND);
+ }
+ if ( bString )
+ {
+ if ( cStrDelim != 0 ) //@ BugId 55355
+ {
+ if ( eCharSet == RTL_TEXTENCODING_UNICODE )
+ {
+ xub_StrLen nPos = aString.Search( cStrDelim );
+ while ( nPos != STRING_NOTFOUND )
+ {
+ aString.Insert( cStrDelim, nPos );
+ nPos = aString.Search( cStrDelim, nPos+2 );
+ }
+ rStream.WriteUniOrByteChar( cStrDelim, eCharSet );
+ rStream.WriteUnicodeText( aString );
+ rStream.WriteUniOrByteChar( cStrDelim, eCharSet );
+ }
+ else
+ {
+ // #105549# This is nasty. The Unicode to byte encoding
+ // may convert typographical quotation marks to ASCII
+ // quotation marks, which may interfer with the delimiter,
+ // so we have to escape delimiters after the string has
+ // been encoded. Since this may happen also with UTF-8
+ // encoded typographical quotation marks if such was
+ // specified as a delimiter we have to check for the full
+ // encoded delimiter string, not just one character.
+ // Now for RTL_TEXTENCODING_ISO_2022_... and similar brain
+ // dead encodings where one code point (and especially a
+ // low ASCII value) may represent different characters, we
+ // have to convert forth and back and forth again. Same for
+ // UTF-7 since it is a context sensitive encoding too.
+
+ if ( bContextOrNotAsciiEncoding )
+ {
+ // to byte encoding
+ ByteString aStrEnc( aString, eCharSet );
+ // back to Unicode
+ UniString aStrDec( aStrEnc, eCharSet );
+ // search on re-decoded string
+ xub_StrLen nPos = aStrDec.Search( aStrDelimDecoded );
+ while ( nPos != STRING_NOTFOUND )
+ {
+ aStrDec.Insert( aStrDelimDecoded, nPos );
+ nPos = aStrDec.Search( aStrDelimDecoded,
+ nPos+1+aStrDelimDecoded.Len() );
+ }
+ // write byte re-encoded
+ rStream.WriteUniOrByteChar( cStrDelim, eCharSet );
+ rStream.WriteUnicodeOrByteText( aStrDec, eCharSet );
+ rStream.WriteUniOrByteChar( cStrDelim, eCharSet );
+ }
+ else
+ {
+ ByteString aStrEnc( aString, eCharSet );
+ // search on encoded string
+ xub_StrLen nPos = aStrEnc.Search( aStrDelimEncoded );
+ while ( nPos != STRING_NOTFOUND )
+ {
+ aStrEnc.Insert( aStrDelimEncoded, nPos );
+ nPos = aStrEnc.Search( aStrDelimEncoded,
+ nPos+1+aStrDelimEncoded.Len() );
+ }
+ // write byte encoded
+ rStream.Write( aStrDelimEncoded.GetBuffer(),
+ aStrDelimEncoded.Len() );
+ rStream.Write( aStrEnc.GetBuffer(), aStrEnc.Len() );
+ rStream.Write( aStrDelimEncoded.GetBuffer(),
+ aStrDelimEncoded.Len() );
+ }
+ }
+ }
+ else
+ rStream.WriteUnicodeOrByteText( aString );
+ }
+ else
+ rStream.WriteUnicodeOrByteText( aString );
+ }
+
+ if( nCol < nEndCol )
+ {
+ if(cDelim!=0) //@ BugId 55355
+ rStream.WriteUniOrByteChar( cDelim );
+ }
+ else
+ endlub( rStream );
+
+ if ( bProgress )
+ aProgress.SetStateOnPercent( nRow );
+ }
+
+ // write out empty if requested
+ if ( nNextRow <= nEndRow )
+ {
+ for ( nEmptyCol = nNextCol; nEmptyCol < nEndCol; nEmptyCol++ )
+ { // remaining empty columns of last row
+ if ( bFixedWidth )
+ lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
+ aDocument, nTab, nEmptyCol );
+ else if ( cDelim != 0 )
+ rStream.WriteUniOrByteChar( cDelim );
+ }
+ endlub( rStream );
+ nNextRow++;
+ }
+ for ( nEmptyRow = nNextRow; nEmptyRow <= nEndRow; nEmptyRow++ )
+ { // entire empty rows
+ for ( nEmptyCol = nStartCol; nEmptyCol < nEndCol; nEmptyCol++ )
+ {
+ if ( bFixedWidth )
+ lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
+ aDocument, nTab, nEmptyCol );
+ else if ( cDelim != 0 )
+ rStream.WriteUniOrByteChar( cDelim );
+ }
+ endlub( rStream );
+ }
+
+ rStream.SetStreamCharSet( eOldCharSet );
+ rStream.SetNumberFormatInt( nOldNumberFormatInt );
+}
+
+BOOL __EXPORT ScDocShell::ConvertTo( SfxMedium &rMed )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::ConvertTo" );
+
+ ScRefreshTimerProtector( aDocument.GetRefreshTimerControlAddress() );
+
+ // #i6500# don't call DoEnterHandler here (doesn't work with AutoSave),
+ // it's already in ExecuteSave (as for Save and SaveAs)
+
+ if (pAutoStyleList)
+ pAutoStyleList->ExecuteAllNow(); // Vorlagen-Timeouts jetzt ausfuehren
+ if (GetCreateMode()== SFX_CREATE_MODE_STANDARD)
+ SfxObjectShell::SetVisArea( Rectangle() ); // normal bearbeitet -> keine VisArea
+
+ DBG_ASSERT( rMed.GetFilter(), "Filter == 0" );
+
+ BOOL bRet = FALSE;
+ String aFltName = rMed.GetFilter()->GetFilterName();
+
+/*
+ if (aFltName.EqualsAscii(pFilterLotus))
+ {
+ SvStream* pStream = rMed.GetOutStream();
+ if (pStream)
+ {
+ FltError eError = ScFormatFilter::Get().ScExportLotus123( *pStream, &aDocument, ExpWK1,
+ CHARSET_IBMPC_437 );
+ bRet = eError == eERR_OK;
+ }
+ }
+ else
+*/
+ if (aFltName.EqualsAscii(pFilterXML))
+ {
+ //TODO/LATER: this shouldn't happen!
+ DBG_ERROR("XML filter in ConvertFrom?!");
+ bRet = SaveXML( &rMed, NULL );
+ }
+ else if (aFltName.EqualsAscii(pFilterExcel5) || aFltName.EqualsAscii(pFilterExcel95) ||
+ aFltName.EqualsAscii(pFilterExcel97) || aFltName.EqualsAscii(pFilterEx5Temp) ||
+ aFltName.EqualsAscii(pFilterEx95Temp) || aFltName.EqualsAscii(pFilterEx97Temp) ||
+ aFltName.EqualsAscii(pFilterEx07Xml))
+ {
+ WaitObject aWait( GetActiveDialogParent() );
+
+ bool bDoSave = true;
+ if( ScTabViewShell* pViewShell = GetBestViewShell() )
+ {
+ ScExtDocOptions* pExtDocOpt = aDocument.GetExtDocOptions();
+ if( !pExtDocOpt )
+ aDocument.SetExtDocOptions( pExtDocOpt = new ScExtDocOptions );
+ pViewShell->GetViewData()->WriteExtOptions( *pExtDocOpt );
+
+ /* #115980# #i104990# If the imported document contains a medium
+ password, determine if we can save it, otherwise ask the users
+ whether they want to save without it. */
+ if( !::sfx2::CheckMSPasswordCapabilityForExport( aFltName ) )
+ {
+ SfxItemSet* pItemSet = rMed.GetItemSet();
+ const SfxPoolItem* pItem = 0;
+ if( pItemSet && pItemSet->GetItemState( SID_PASSWORD, sal_True, &pItem ) == SFX_ITEM_SET )
+ {
+ bDoSave = ScWarnPassword::WarningOnPassword( rMed );
+ // #i42858# remove password from medium (warn only one time)
+ if( bDoSave )
+ pItemSet->ClearItem( SID_PASSWORD );
+ }
+ }
+
+#if ENABLE_SHEET_PROTECTION
+ if( bDoSave )
+ {
+ bool bNeedRetypePassDlg = ScPassHashHelper::needsPassHashRegen( aDocument, PASSHASH_XL );
+ bDoSave = !bNeedRetypePassDlg || pViewShell->ExecuteRetypePassDlg( PASSHASH_XL );
+ }
+#endif
+ }
+
+ if( bDoSave )
+ {
+ ExportFormatExcel eFormat = ExpBiff5;
+ if( aFltName.EqualsAscii( pFilterExcel97 ) || aFltName.EqualsAscii( pFilterEx97Temp ) )
+ eFormat = ExpBiff8;
+ if( aFltName.EqualsAscii( pFilterEx07Xml ) )
+ eFormat = Exp2007Xml;
+ FltError eError = ScFormatFilter::Get().ScExportExcel5( rMed, &aDocument, eFormat, RTL_TEXTENCODING_MS_1252 );
+
+ if( eError && !GetError() )
+ SetError( eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+
+ // don't return false for warnings
+ bRet = ((eError & ERRCODE_WARNING_MASK) == ERRCODE_WARNING_MASK) || (eError == eERR_OK);
+ }
+ else
+ {
+ // export aborted, i.e. "Save without password" warning
+ SetError( ERRCODE_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+ }
+ }
+ else if (aFltName.EqualsAscii(pFilterAscii))
+ {
+ SvStream* pStream = rMed.GetOutStream();
+ if (pStream)
+ {
+ String sItStr;
+ SfxItemSet* pSet = rMed.GetItemSet();
+ const SfxPoolItem* pItem;
+ if ( pSet && SFX_ITEM_SET ==
+ pSet->GetItemState( SID_FILE_FILTEROPTIONS, TRUE, &pItem ) )
+ {
+ sItStr = ((const SfxStringItem*)pItem)->GetValue();
+ }
+
+ if ( sItStr.Len() == 0 )
+ {
+ // default for ascii export (from API without options):
+ // ISO8859-1/MS_1252 encoding, comma, double quotes
+
+ ScImportOptions aDefOptions( ',', '"', RTL_TEXTENCODING_MS_1252 );
+ sItStr = aDefOptions.BuildString();
+ }
+
+ WaitObject aWait( GetActiveDialogParent() );
+ ScImportOptions aOptions( sItStr );
+ AsciiSave( *pStream, aOptions );
+ bRet = TRUE;
+
+ if (aDocument.GetTableCount() > 1)
+ if (!rMed.GetError())
+ rMed.SetError(SCWARN_EXPORT_ASCII, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
+ }
+ }
+ else if (aFltName.EqualsAscii(pFilterDBase))
+ {
+ String sCharSet;
+ SfxItemSet* pSet = rMed.GetItemSet();
+ const SfxPoolItem* pItem;
+ if ( pSet && SFX_ITEM_SET ==
+ pSet->GetItemState( SID_FILE_FILTEROPTIONS, TRUE, &pItem ) )
+ {
+ sCharSet = ((const SfxStringItem*)pItem)->GetValue();
+ }
+
+ if (sCharSet.Len() == 0)
+ {
+ // default for dBase export (from API without options):
+ // IBM_850 encoding
+
+ sCharSet = ScGlobal::GetCharsetString( RTL_TEXTENCODING_IBM_850 );
+ }
+
+ WaitObject aWait( GetActiveDialogParent() );
+// HACK damit Sba geoffnetes TempFile ueberschreiben kann
+ rMed.CloseOutStream();
+ BOOL bHasMemo = FALSE;
+
+ ULONG eError = DBaseExport( rMed.GetPhysicalName(),
+ ScGlobal::GetCharsetValue(sCharSet), bHasMemo );
+
+ if ( eError != eERR_OK && (eError & ERRCODE_WARNING_MASK) )
+ {
+//! if ( !rMed.GetError() )
+//! rMed.SetError( eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+ eError = eERR_OK;
+ }
+//! else if ( aDocument.GetTableCount() > 1 && !rMed.GetError() )
+//! rMed.SetError( SCWARN_EXPORT_ASCII, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+
+ INetURLObject aTmpFile( rMed.GetPhysicalName(), INET_PROT_FILE );
+ if ( bHasMemo )
+ aTmpFile.setExtension( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("dbt")) );
+ if ( eError != eERR_OK )
+ {
+ if (!GetError())
+ SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
+ if ( bHasMemo && IsDocument( aTmpFile ) )
+ KillFile( aTmpFile );
+ }
+ else
+ {
+ bRet = TRUE;
+ if ( bHasMemo )
+ {
+ SfxStringItem* pNameItem =
+ (SfxStringItem*) rMed.GetItemSet()->GetItem( SID_FILE_NAME );
+ INetURLObject aDbtFile( pNameItem->GetValue(), INET_PROT_FILE );
+ aDbtFile.setExtension( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("dbt")) );
+ if ( IsDocument( aDbtFile ) && !KillFile( aDbtFile ) )
+ bRet = FALSE;
+ if ( bRet && !MoveFile( aTmpFile, aDbtFile ) )
+ bRet = FALSE;
+ if ( !bRet )
+ {
+ KillFile( aTmpFile );
+ if ( !GetError() )
+ SetError( SCERR_EXPORT_DATA, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+ }
+ }
+ }
+ }
+ else if (aFltName.EqualsAscii(pFilterDif))
+ {
+ SvStream* pStream = rMed.GetOutStream();
+ if (pStream)
+ {
+ String sItStr;
+ SfxItemSet* pSet = rMed.GetItemSet();
+ const SfxPoolItem* pItem;
+ if ( pSet && SFX_ITEM_SET ==
+ pSet->GetItemState( SID_FILE_FILTEROPTIONS, TRUE, &pItem ) )
+ {
+ sItStr = ((const SfxStringItem*)pItem)->GetValue();
+ }
+
+ if (sItStr.Len() == 0)
+ {
+ // default for DIF export (from API without options):
+ // ISO8859-1/MS_1252 encoding
+
+ sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_MS_1252 );
+ }
+
+ WaitObject aWait( GetActiveDialogParent() );
+ ScFormatFilter::Get().ScExportDif( *pStream, &aDocument, ScAddress(0,0,0),
+ ScGlobal::GetCharsetValue(sItStr) );
+ bRet = TRUE;
+
+ if (aDocument.GetTableCount() > 1)
+ if (!rMed.GetError())
+ rMed.SetError(SCWARN_EXPORT_ASCII, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
+ }
+ }
+ else if (aFltName.EqualsAscii(pFilterSylk))
+ {
+ SvStream* pStream = rMed.GetOutStream();
+ if ( pStream )
+ {
+ WaitObject aWait( GetActiveDialogParent() );
+
+ SCCOL nEndCol;
+ SCROW nEndRow;
+ aDocument.GetCellArea( 0, nEndCol, nEndRow );
+ ScRange aRange( 0,0,0, nEndCol,nEndRow,0 );
+
+ ScImportExport aImExport( &aDocument, aRange );
+ aImExport.SetFormulas( TRUE );
+ bRet = aImExport.ExportStream( *pStream, rMed.GetBaseURL( true ), SOT_FORMATSTR_ID_SYLK );
+ }
+ }
+ else if (aFltName.EqualsAscii(pFilterHtml))
+ {
+ SvStream* pStream = rMed.GetOutStream();
+ if ( pStream )
+ {
+ WaitObject aWait( GetActiveDialogParent() );
+ ScImportExport aImExport( &aDocument );
+ aImExport.SetStreamPath( rMed.GetName() );
+ bRet = aImExport.ExportStream( *pStream, rMed.GetBaseURL( true ), SOT_FORMATSTR_ID_HTML );
+ if ( bRet && aImExport.GetNonConvertibleChars().Len() )
+ SetError( *new StringErrorInfo(
+ SCWARN_EXPORT_NONCONVERTIBLE_CHARS,
+ aImExport.GetNonConvertibleChars(),
+ ERRCODE_BUTTON_OK | ERRCODE_MSG_INFO ), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+ }
+ }
+ else
+ {
+ if (GetError())
+ SetError(SCERR_IMPORT_NI, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+ }
+ return bRet;
+}
+
+
+BOOL __EXPORT ScDocShell::SaveCompleted( const uno::Reference < embed::XStorage >& xStor )
+{
+ return SfxObjectShell::SaveCompleted( xStor );
+}
+
+
+BOOL __EXPORT ScDocShell::DoSaveCompleted( SfxMedium * pNewStor )
+{
+ BOOL bRet = SfxObjectShell::DoSaveCompleted( pNewStor );
+
+ // SC_HINT_DOC_SAVED fuer Wechsel ReadOnly -> Read/Write
+ Broadcast( SfxSimpleHint( SC_HINT_DOC_SAVED ) );
+ return bRet;
+}
+
+
+USHORT __EXPORT ScDocShell::PrepareClose( BOOL bUI, BOOL bForBrowsing )
+{
+ if(SC_MOD()->GetCurRefDlgId()>0)
+ {
+ SfxViewFrame* pFrame = SfxViewFrame::GetFirst( this, TYPE(SfxTopViewFrame) );
+ if( pFrame )
+ {
+ SfxViewShell* p = pFrame->GetViewShell();
+ ScTabViewShell* pViewSh = PTR_CAST(ScTabViewShell,p);
+ if(pViewSh!=NULL)
+ {
+ Window *pWin=pViewSh->GetWindow();
+ if(pWin!=NULL) pWin->GrabFocus();
+ }
+ }
+
+ return FALSE;
+ }
+ if ( aDocument.IsInLinkUpdate() || aDocument.IsInInterpreter() )
+ {
+ ErrorMessage(STR_CLOSE_ERROR_LINK);
+ return FALSE;
+ }
+
+ DoEnterHandler();
+
+ USHORT nRet = SfxObjectShell::PrepareClose( bUI, bForBrowsing );
+ if (nRet == TRUE) // TRUE = schliessen
+ aDocument.DisableIdle(TRUE); // nicht mehr drin rumpfuschen !!!
+
+ return nRet;
+}
+
+void ScDocShell::PrepareReload()
+{
+ SfxObjectShell::PrepareReload(); // tut nichts?
+
+ // Das Disconnect von DDE-Links kann Reschedule ausloesen.
+ // Wenn die DDE-Links erst im Dokument-dtor geloescht werden, kann beim Reload
+ // aus diesem Reschedule das DDE-Link-Update fuer das neue Dokument ausgeloest
+ // werden. Dabei verklemmt sicht dann irgendwas.
+ // -> Beim Reload die DDE-Links des alten Dokuments vorher disconnecten
+
+ aDocument.DisconnectDdeLinks();
+}
+
+
+String ScDocShell::GetOwnFilterName() // static
+{
+ return String::CreateFromAscii(pFilterSc50);
+}
+
+String ScDocShell::GetWebQueryFilterName() // static
+{
+ return String::CreateFromAscii(pFilterHtmlWebQ);
+}
+
+String ScDocShell::GetAsciiFilterName() // static
+{
+ return String::CreateFromAscii(pFilterAscii);
+}
+
+String ScDocShell::GetLotusFilterName() // static
+{
+ return String::CreateFromAscii(pFilterLotus);
+}
+
+String ScDocShell::GetDBaseFilterName() // static
+{
+ return String::CreateFromAscii(pFilterDBase);
+}
+
+String ScDocShell::GetDifFilterName() // static
+{
+ return String::CreateFromAscii(pFilterDif);
+}
+
+BOOL ScDocShell::HasAutomaticTableName( const String& rFilter ) // static
+{
+ // TRUE for those filters that keep the default table name
+ // (which is language specific)
+
+ return rFilter.EqualsAscii( pFilterAscii )
+ || rFilter.EqualsAscii( pFilterLotus )
+ || rFilter.EqualsAscii( pFilterExcel4 )
+ || rFilter.EqualsAscii( pFilterEx4Temp )
+ || rFilter.EqualsAscii( pFilterDBase )
+ || rFilter.EqualsAscii( pFilterDif )
+ || rFilter.EqualsAscii( pFilterSylk )
+ || rFilter.EqualsAscii( pFilterHtml )
+ || rFilter.EqualsAscii( pFilterRtf );
+}
+
+//==================================================================
+
+#define __SCDOCSHELL_INIT \
+ aDocument ( SCDOCMODE_DOCUMENT, this ), \
+ aDdeTextFmt(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("TEXT"))), \
+ nPrtToScreenFactor( 1.0 ), \
+ pImpl ( new DocShell_Impl ), \
+ bHeaderOn ( TRUE ), \
+ bFooterOn ( TRUE ), \
+ bNoInformLost ( TRUE ), \
+ bIsEmpty ( TRUE ), \
+ bIsInUndo ( FALSE ), \
+ bDocumentModifiedPending( FALSE ), \
+ nDocumentLock ( 0 ), \
+ nCanUpdate (com::sun::star::document::UpdateDocMode::ACCORDING_TO_CONFIG), \
+ bUpdateEnabled ( TRUE ), \
+ pOldAutoDBRange ( NULL ), \
+ pDocHelper ( NULL ), \
+ pAutoStyleList ( NULL ), \
+ pPaintLockData ( NULL ), \
+ pOldJobSetup ( NULL ), \
+ pSolverSaveData ( NULL ), \
+ pSheetSaveData ( NULL ), \
+ pModificator ( NULL )
+
+//------------------------------------------------------------------
+
+ScDocShell::ScDocShell( const ScDocShell& rShell )
+ : SvRefBase(),
+ SotObject(),
+ SfxObjectShell( rShell.GetCreateMode() ),
+ SfxListener(),
+ __SCDOCSHELL_INIT
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::ScDocShell" );
+
+ SetPool( &SC_MOD()->GetPool() );
+
+ bIsInplace = rShell.bIsInplace;
+
+ pDocFunc = new ScDocFunc(*this);
+
+ // SetBaseModel needs exception handling
+ ScModelObj::CreateAndSet( this );
+
+ StartListening(*this);
+ SfxStyleSheetPool* pStlPool = aDocument.GetStyleSheetPool();
+ if (pStlPool)
+ StartListening(*pStlPool);
+
+ GetPageOnFromPageStyleSet( NULL, 0, bHeaderOn, bFooterOn );
+ SetHelpId( HID_SCSHELL_DOCSH );
+
+ // InitItems und CalcOutputFactor werden jetzt nach bei Load/ConvertFrom/InitNew gerufen
+}
+
+//------------------------------------------------------------------
+
+ScDocShell::ScDocShell( SfxObjectCreateMode eMode, const bool _bScriptSupport )
+ : SfxObjectShell( eMode ),
+ __SCDOCSHELL_INIT
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::ScDocShell" );
+
+ SetPool( &SC_MOD()->GetPool() );
+
+ bIsInplace = (eMode == SFX_CREATE_MODE_EMBEDDED);
+ // wird zurueckgesetzt, wenn nicht inplace
+
+ pDocFunc = new ScDocFunc(*this);
+
+ if ( !_bScriptSupport )
+ SetHasNoBasic();
+
+ // SetBaseModel needs exception handling
+ ScModelObj::CreateAndSet( this );
+
+ StartListening(*this);
+ SfxStyleSheetPool* pStlPool = aDocument.GetStyleSheetPool();
+ if (pStlPool)
+ StartListening(*pStlPool);
+ SetHelpId( HID_SCSHELL_DOCSH );
+
+ aDocument.GetDBCollection()->SetRefreshHandler(
+ LINK( this, ScDocShell, RefreshDBDataHdl ) );
+
+ // InitItems und CalcOutputFactor werden jetzt nach bei Load/ConvertFrom/InitNew gerufen
+}
+
+//------------------------------------------------------------------
+
+__EXPORT ScDocShell::~ScDocShell()
+{
+ ResetDrawObjectShell(); // #55570# falls der Drawing-Layer noch versucht, darauf zuzugreifen
+
+ SfxStyleSheetPool* pStlPool = aDocument.GetStyleSheetPool();
+ if (pStlPool)
+ EndListening(*pStlPool);
+ EndListening(*this);
+
+ delete pAutoStyleList;
+
+ SfxApplication *pSfxApp = SFX_APP();
+ if ( pSfxApp->GetDdeService() ) // DDE vor Dokument loeschen
+ pSfxApp->RemoveDdeTopic( this );
+
+ delete pDocFunc;
+ delete aDocument.mpUndoManager;
+ aDocument.mpUndoManager = 0;
+ delete pImpl;
+
+ delete pPaintLockData;
+
+ delete pOldJobSetup; // gesetzt nur bei Fehler in StartJob()
+
+ delete pSolverSaveData;
+ delete pSheetSaveData;
+ delete pOldAutoDBRange;
+
+ if (pModificator)
+ {
+ DBG_ERROR("The Modificator should not exist");
+ delete pModificator;
+ }
+}
+
+//------------------------------------------------------------------
+
+SfxUndoManager* __EXPORT ScDocShell::GetUndoManager()
+{
+ return aDocument.GetUndoManager();
+}
+
+void ScDocShell::SetModified( BOOL bModified )
+{
+ if ( SfxObjectShell::IsEnableSetModified() )
+ {
+ SfxObjectShell::SetModified( bModified );
+ Broadcast( SfxSimpleHint( SFX_HINT_DOCCHANGED ) );
+ }
+}
+
+
+void ScDocShell::SetDocumentModified( BOOL bIsModified /* = TRUE */ )
+{
+ // BroadcastUno muss auch mit pPaintLockData sofort passieren
+ //! auch bei SetDrawModified, wenn Drawing angebunden ist
+ //! dann eigener Hint???
+
+ if ( pPaintLockData && bIsModified )
+ {
+ //! BCA_BRDCST_ALWAYS etc. also needed here?
+ aDocument.BroadcastUno( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
+
+ pPaintLockData->SetModified(); // spaeter...
+ return;
+ }
+
+ SetDrawModified( bIsModified );
+
+ if ( bIsModified )
+ {
+ if ( aDocument.IsAutoCalcShellDisabled() )
+ SetDocumentModifiedPending( TRUE );
+ else
+ {
+ SetDocumentModifiedPending( FALSE );
+ aDocument.InvalidateStyleSheetUsage();
+ aDocument.InvalidateTableArea();
+ aDocument.InvalidateLastTableOpParams();
+ aDocument.Broadcast( SC_HINT_DATACHANGED, BCA_BRDCST_ALWAYS, NULL );
+ if ( aDocument.IsForcedFormulaPending() && aDocument.GetAutoCalc() )
+ aDocument.CalcFormulaTree( TRUE );
+ PostDataChanged();
+
+ // Detective AutoUpdate:
+ // Update if formulas were modified (DetectiveDirty) or the list contains
+ // "Trace Error" entries (#75362# - Trace Error can look completely different
+ // after changes to non-formula cells).
+
+ ScDetOpList* pList = aDocument.GetDetOpList();
+ if ( pList && ( aDocument.IsDetectiveDirty() || pList->HasAddError() ) &&
+ pList->Count() && !IsInUndo() && SC_MOD()->GetAppOptions().GetDetectiveAuto() )
+ {
+ GetDocFunc().DetectiveRefresh(TRUE); // TRUE = caused by automatic update
+ }
+ aDocument.SetDetectiveDirty(FALSE); // always reset, also if not refreshed
+ }
+
+ // #b6697848# notify UNO objects after BCA_BRDCST_ALWAYS etc.
+ aDocument.BroadcastUno( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
+ }
+}
+
+// SetDrawModified - ohne Formel-Update
+// (Drawing muss auch beim normalen SetDocumentModified upgedated werden,
+// z.B. bei Tabelle loeschen etc.)
+
+void ScDocShell::SetDrawModified( BOOL bIsModified /* = TRUE */ )
+{
+ BOOL bUpdate = ( bIsModified != IsModified() );
+
+ SetModified( bIsModified );
+
+ SfxBindings* pBindings = GetViewBindings();
+ if (bUpdate)
+ {
+ if (pBindings)
+ {
+ pBindings->Invalidate( SID_SAVEDOC );
+ pBindings->Invalidate( SID_DOC_MODIFIED );
+ }
+ }
+
+ if (bIsModified)
+ {
+ if (pBindings)
+ {
+ // #i105960# Undo etc used to be volatile.
+ // They always have to be invalidated, including drawing layer or row height changes
+ // (but not while pPaintLockData is set).
+ pBindings->Invalidate( SID_UNDO );
+ pBindings->Invalidate( SID_REDO );
+ pBindings->Invalidate( SID_REPEAT );
+ }
+
+ if ( aDocument.IsChartListenerCollectionNeedsUpdate() )
+ {
+ aDocument.UpdateChartListenerCollection();
+ SFX_APP()->Broadcast(SfxSimpleHint( SC_HINT_DRAW_CHANGED )); // Navigator
+ }
+ SC_MOD()->AnythingChanged();
+ }
+}
+
+void ScDocShell::SetInUndo(BOOL bSet)
+{
+ bIsInUndo = bSet;
+}
+
+
+void ScDocShell::GetDocStat( ScDocStat& rDocStat )
+{
+ SfxPrinter* pPrinter = GetPrinter();
+
+ aDocument.GetDocStat( rDocStat );
+ rDocStat.nPageCount = 0;
+
+ if ( pPrinter )
+ for ( SCTAB i=0; i<rDocStat.nTableCount; i++ )
+ rDocStat.nPageCount = sal::static_int_cast<USHORT>( rDocStat.nPageCount +
+ (USHORT) ScPrintFunc( this, pPrinter, i ).GetTotalPages() );
+}
+
+
+SfxDocumentInfoDialog* __EXPORT ScDocShell::CreateDocumentInfoDialog(
+ Window *pParent, const SfxItemSet &rSet )
+{
+ SfxDocumentInfoDialog* pDlg = new SfxDocumentInfoDialog( pParent, rSet );
+ ScDocShell* pDocSh = PTR_CAST(ScDocShell,SfxObjectShell::Current());
+
+ //nur mit Statistik, wenn dieses Doc auch angezeigt wird, nicht
+ //aus dem Doc-Manager
+
+ if( pDocSh == this )
+ {
+ ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
+ DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001
+ ::CreateTabPage ScDocStatPageCreate = pFact->GetTabPageCreatorFunc( RID_SCPAGE_STAT );
+ DBG_ASSERT(ScDocStatPageCreate, "Tabpage create fail!");//CHINA001
+ pDlg->AddTabPage( 42,
+ ScGlobal::GetRscString( STR_DOC_STAT ),
+ ScDocStatPageCreate,
+ NULL);
+//CHINA001 pDlg->AddTabPage( 42,
+//CHINA001 ScGlobal::GetRscString( STR_DOC_STAT ),
+//CHINA001 ScDocStatPage::Create,
+//CHINA001 NULL );
+ }
+ return pDlg;
+}
+
+Window* ScDocShell::GetActiveDialogParent()
+{
+ ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
+ if ( pViewSh )
+ return pViewSh->GetDialogParent();
+ else
+ return Application::GetDefDialogParent();
+}
+
+void ScDocShell::SetSolverSaveData( const ScOptSolverSave& rData )
+{
+ delete pSolverSaveData;
+ pSolverSaveData = new ScOptSolverSave( rData );
+}
+
+ScSheetSaveData* ScDocShell::GetSheetSaveData()
+{
+ if (!pSheetSaveData)
+ pSheetSaveData = new ScSheetSaveData;
+
+ return pSheetSaveData;
+}
+
+void ScDocShell::UseSheetSaveEntries()
+{
+ if (pSheetSaveData)
+ {
+ pSheetSaveData->UseSaveEntries(); // use positions from saved file for next saving
+
+ bool bHasEntries = false;
+ SCTAB nTabCount = aDocument.GetTableCount();
+ SCTAB nTab;
+ for (nTab = 0; nTab < nTabCount; ++nTab)
+ if (pSheetSaveData->HasStreamPos(nTab))
+ bHasEntries = true;
+
+ if (!bHasEntries)
+ {
+ // if no positions were set (for example, export to other format),
+ // reset all "valid" flags
+
+ for (nTab = 0; nTab < nTabCount; ++nTab)
+ if (aDocument.IsStreamValid(nTab))
+ aDocument.SetStreamValid(nTab, FALSE);
+ }
+ }
+}
+
+// --- ScDocShellModificator ------------------------------------------
+
+ScDocShellModificator::ScDocShellModificator( ScDocShell& rDS )
+ :
+ rDocShell( rDS ),
+ aProtector( rDS.GetDocument()->GetRefreshTimerControlAddress() )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+ bAutoCalcShellDisabled = pDoc->IsAutoCalcShellDisabled();
+ bIdleDisabled = pDoc->IsIdleDisabled();
+ pDoc->SetAutoCalcShellDisabled( TRUE );
+ pDoc->DisableIdle( TRUE );
+}
+
+
+ScDocShellModificator::~ScDocShellModificator()
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+ pDoc->SetAutoCalcShellDisabled( bAutoCalcShellDisabled );
+ if ( !bAutoCalcShellDisabled && rDocShell.IsDocumentModifiedPending() )
+ rDocShell.SetDocumentModified(); // last one shuts off the lights
+ pDoc->DisableIdle( bIdleDisabled );
+}
+
+
+void ScDocShellModificator::SetDocumentModified()
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if ( !pDoc->IsImportingXML() )
+ {
+ // AutoCalcShellDisabled temporaer restaurieren
+ BOOL bDisabled = pDoc->IsAutoCalcShellDisabled();
+ pDoc->SetAutoCalcShellDisabled( bAutoCalcShellDisabled );
+ rDocShell.SetDocumentModified();
+ pDoc->SetAutoCalcShellDisabled( bDisabled );
+ }
+ else
+ {
+ // uno broadcast is necessary for api to work
+ // -> must also be done during xml import
+ pDoc->BroadcastUno( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
+ }
+}
+
+//<!--Added by PengYunQuan for Validity Cell Range Picker
+sal_Bool ScDocShell::AcceptStateUpdate() const
+{
+ if( SfxObjectShell::AcceptStateUpdate() )
+ return sal_True;
+
+ if( SC_MOD()->Find1RefWindow( SFX_APP()->GetTopWindow() ) )
+ return sal_True;
+
+ return sal_False;
+}
+//-->Added by PengYunQuan for Validity Cell Range Picker
diff --git a/sc/source/ui/docshell/docsh2.cxx b/sc/source/ui/docshell/docsh2.cxx
new file mode 100644
index 000000000000..4b76c18edbe6
--- /dev/null
+++ b/sc/source/ui/docshell/docsh2.cxx
@@ -0,0 +1,261 @@
+/*************************************************************************
+ *
+ * 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 <svx/svdpage.hxx>
+
+
+#include <svx/xtable.hxx>
+
+#include "scitems.hxx"
+#include <tools/gen.hxx>
+#include <svtools/ctrltool.hxx>
+#include <editeng/flstitem.hxx>
+#include <svx/drawitem.hxx>
+#include <sfx2/printer.hxx>
+#include <svl/smplhint.hxx>
+#include <svx/svditer.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/svdoole2.hxx>
+#include <vcl/svapp.hxx>
+#include <svl/asiancfg.hxx>
+#include <editeng/forbiddencharacterstable.hxx>
+#include <editeng/unolingu.hxx>
+#include <rtl/logfile.hxx>
+
+#include <comphelper/processfactory.hxx>
+#include <basic/sbstar.hxx>
+#include <basic/basmgr.hxx>
+#include <sfx2/app.hxx>
+
+// INCLUDE ---------------------------------------------------------------
+/*
+#include <svdrwetc.hxx>
+#include <svdrwobx.hxx>
+#include <sostor.hxx>
+*/
+#include "drwlayer.hxx"
+#include "stlpool.hxx"
+#include "docsh.hxx"
+#include "docshimp.hxx"
+#include "docfunc.hxx"
+#include "sc.hrc"
+
+using namespace com::sun::star;
+
+//------------------------------------------------------------------
+
+BOOL __EXPORT ScDocShell::InitNew( const uno::Reference < embed::XStorage >& xStor )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::InitNew" );
+
+ BOOL bRet = SfxObjectShell::InitNew( xStor );
+
+ aDocument.MakeTable(0);
+ // zusaetzliche Tabellen werden von der ersten View angelegt,
+ // wenn bIsEmpty dann noch TRUE ist
+
+ if( bRet )
+ {
+ Size aSize( (long) ( STD_COL_WIDTH * HMM_PER_TWIPS * OLE_STD_CELLS_X ),
+ (long) ( ScGlobal::nStdRowHeight * HMM_PER_TWIPS * OLE_STD_CELLS_Y ) );
+ // hier muss auch der Start angepasst werden
+ SetVisAreaOrSize( Rectangle( Point(), aSize ), TRUE );
+ }
+
+ aDocument.SetDrawDefaults(); // drawing layer defaults that are set only in InitNew
+
+ // InitOptions sets the document languages, must be called before CreateStandardStyles
+ InitOptions();
+
+ aDocument.GetStyleSheetPool()->CreateStandardStyles();
+ aDocument.UpdStlShtPtrsFrmNms();
+
+ // SetDocumentModified ist in Load/InitNew nicht mehr erlaubt!
+
+ InitItems();
+ CalcOutputFactor();
+ uno::Any aGlobs;
+ uno::Sequence< uno::Any > aArgs(1);
+ aArgs[ 0 ] <<= GetModel();
+ aGlobs <<= ::comphelper::getProcessServiceFactory()->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.excel.Globals" ) ), aArgs );
+ GetBasicManager()->SetGlobalUNOConstant( "VBAGlobals", aGlobs );
+ // Fake ThisComponent being setup by Activate ( which is a view
+ // related thing ),
+ // a) if another document is opened then in theory ThisComponent
+ // will be reset as before,
+ // b) when this document is 'really' Activated then ThisComponent
+ // again will be set as before
+ // The only wrinkle seems if this document is loaded 'InVisible'
+ // but.. I don't see that this is possible from the vba API
+ // I could be wrong though
+ // There may be implications setting the current component
+ // too early :-/ so I will just manually set the Basic Variables
+ BasicManager* pAppMgr = SFX_APP()->GetBasicManager();
+ if ( pAppMgr )
+ pAppMgr->SetGlobalUNOConstant( "ThisExcelDoc", aArgs[ 0 ] );
+
+ return bRet;
+}
+
+//------------------------------------------------------------------
+
+BOOL ScDocShell::IsEmpty() const
+{
+ return bIsEmpty;
+}
+
+
+void ScDocShell::SetEmpty(BOOL bSet)
+{
+ bIsEmpty = bSet;
+}
+
+//------------------------------------------------------------------
+
+void ScDocShell::InitItems()
+{
+ // AllItemSet fuer Controller mit benoetigten Items fuellen:
+
+ // if ( pImpl->pFontList )
+ // delete pImpl->pFontList;
+
+ // Druck-Optionen werden beim Drucken und evtl. in GetPrinter gesetzt
+
+ // pImpl->pFontList = new FontList( GetPrinter(), Application::GetDefaultDevice() );
+ //PutItem( SvxFontListItem( pImpl->pFontList, SID_ATTR_CHAR_FONTLIST ) );
+ UpdateFontList();
+
+ ScDrawLayer* pDrawLayer = aDocument.GetDrawLayer();
+ if (pDrawLayer)
+ {
+ PutItem( SvxColorTableItem ( pDrawLayer->GetColorTable(), SID_COLOR_TABLE ) );
+ PutItem( SvxGradientListItem( pDrawLayer->GetGradientList(), SID_GRADIENT_LIST ) );
+ PutItem( SvxHatchListItem ( pDrawLayer->GetHatchList(), SID_HATCH_LIST ) );
+ PutItem( SvxBitmapListItem ( pDrawLayer->GetBitmapList(), SID_BITMAP_LIST ) );
+ PutItem( SvxDashListItem ( pDrawLayer->GetDashList(), SID_DASH_LIST ) );
+ PutItem( SvxLineEndListItem ( pDrawLayer->GetLineEndList(), SID_LINEEND_LIST ) );
+
+ // andere Anpassungen nach dem Anlegen des DrawLayers
+
+ pDrawLayer->SetNotifyUndoActionHdl( LINK( pDocFunc, ScDocFunc, NotifyDrawUndo ) );
+
+ //if (SfxObjectShell::HasSbxObject())
+ pDrawLayer->UpdateBasic(); // DocShell-Basic in DrawPages setzen
+ }
+ else
+ {
+ // always use global color table instead of local copy
+ PutItem( SvxColorTableItem( XColorTable::GetStdColorTable(), SID_COLOR_TABLE ) );
+ }
+
+ if ( !aDocument.GetForbiddenCharacters().isValid() ||
+ !aDocument.IsValidAsianCompression() || !aDocument.IsValidAsianKerning() )
+ {
+ // get settings from SvxAsianConfig
+ SvxAsianConfig aAsian( sal_False );
+
+ if ( !aDocument.GetForbiddenCharacters().isValid() )
+ {
+ // set forbidden characters if necessary
+ uno::Sequence<lang::Locale> aLocales = aAsian.GetStartEndCharLocales();
+ if (aLocales.getLength())
+ {
+ vos::ORef<SvxForbiddenCharactersTable> xForbiddenTable =
+ new SvxForbiddenCharactersTable( aDocument.GetServiceManager() );
+
+ const lang::Locale* pLocales = aLocales.getConstArray();
+ for (sal_Int32 i = 0; i < aLocales.getLength(); i++)
+ {
+ i18n::ForbiddenCharacters aForbidden;
+ aAsian.GetStartEndChars( pLocales[i], aForbidden.beginLine, aForbidden.endLine );
+ LanguageType eLang = SvxLocaleToLanguage(pLocales[i]);
+ //pDoc->SetForbiddenCharacters( eLang, aForbidden );
+
+ xForbiddenTable->SetForbiddenCharacters( eLang, aForbidden );
+ }
+
+ aDocument.SetForbiddenCharacters( xForbiddenTable );
+ }
+ }
+
+ if ( !aDocument.IsValidAsianCompression() )
+ {
+ // set compression mode from configuration if not already set (e.g. XML import)
+ aDocument.SetAsianCompression( sal::static_int_cast<BYTE>( aAsian.GetCharDistanceCompression() ) );
+ }
+
+ if ( !aDocument.IsValidAsianKerning() )
+ {
+ // set asian punctuation kerning from configuration if not already set (e.g. XML import)
+ aDocument.SetAsianKerning( !aAsian.IsKerningWesternTextOnly() ); // reversed
+ }
+ }
+}
+
+//------------------------------------------------------------------
+
+void ScDocShell::ResetDrawObjectShell()
+{
+ ScDrawLayer* pDrawLayer = aDocument.GetDrawLayer();
+ if (pDrawLayer)
+ pDrawLayer->SetObjectShell( NULL );
+}
+
+//------------------------------------------------------------------
+
+void __EXPORT ScDocShell::Activate()
+{
+}
+
+
+void __EXPORT ScDocShell::Deactivate()
+{
+}
+
+//------------------------------------------------------------------
+
+
+ScDrawLayer* ScDocShell::MakeDrawLayer()
+{
+ ScDrawLayer* pDrawLayer = aDocument.GetDrawLayer();
+ if (!pDrawLayer)
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::MakeDrawLayer" );
+
+ aDocument.InitDrawLayer(this);
+ pDrawLayer = aDocument.GetDrawLayer();
+ InitItems(); // incl. Undo und Basic
+ Broadcast( SfxSimpleHint( SC_HINT_DRWLAYER_NEW ) );
+ if (nDocumentLock)
+ pDrawLayer->setLock(TRUE);
+ }
+ return pDrawLayer;
+}
diff --git a/sc/source/ui/docshell/docsh3.cxx b/sc/source/ui/docshell/docsh3.cxx
new file mode 100644
index 000000000000..7ff714c2cbdd
--- /dev/null
+++ b/sc/source/ui/docshell/docsh3.cxx
@@ -0,0 +1,1391 @@
+/*************************************************************************
+ *
+ * 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"
+
+#if DEBUG_CHANGETRACK
+#include <stdio.h>
+#endif // DEBUG_CHANGETRACK
+
+
+//------------------------------------------------------------------
+
+//
+// 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, USHORT nPart,
+ USHORT 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.
+ USHORT 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, USHORT nPart, USHORT 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( USHORT& 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( USHORT& 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(BOOL bDoc)
+{
+ if ( !pPaintLockData )
+ pPaintLockData = new ScPaintLockData(0); //! Modus...
+ pPaintLockData->IncLevel(bDoc);
+}
+
+void ScDocShell::UnlockPaint_Impl(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)
+ {
+ USHORT nParts = pPaint->GetParts();
+ ULONG nCount = xRangeList->Count();
+ for ( ULONG i=0; i<nCount; i++ )
+ {
+ //! nExtFlags ???
+ ScRange aRange = *xRangeList->GetObject(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
+ {
+ DBG_ERROR("UnlockPaint ohne LockPaint");
+ }
+}
+
+void ScDocShell::LockDocument_Impl(USHORT nNew)
+{
+ if (!nDocumentLock)
+ {
+ ScDrawLayer* pDrawLayer = aDocument.GetDrawLayer();
+ if (pDrawLayer)
+ pDrawLayer->setLock(TRUE);
+ }
+ nDocumentLock = nNew;
+}
+
+void ScDocShell::UnlockDocument_Impl(USHORT nNew)
+{
+ nDocumentLock = nNew;
+ if (!nDocumentLock)
+ {
+ ScDrawLayer* pDrawLayer = aDocument.GetDrawLayer();
+ if (pDrawLayer)
+ pDrawLayer->setLock(FALSE);
+ }
+}
+
+USHORT ScDocShell::GetLockCount() const
+{
+ return nDocumentLock;
+}
+
+void ScDocShell::SetLockCount(USHORT nNew)
+{
+ if (nNew) // setzen
+ {
+ if ( !pPaintLockData )
+ pPaintLockData = new ScPaintLockData(0); //! Modus...
+ pPaintLockData->SetLevel(nNew-1, TRUE);
+ LockDocument_Impl(nNew);
+ }
+ else if (pPaintLockData) // loeschen
+ {
+ pPaintLockData->SetLevel(0, TRUE); // bei Unlock sofort ausfuehren
+ UnlockPaint_Impl(TRUE); // jetzt
+ UnlockDocument_Impl(0);
+ }
+}
+
+void ScDocShell::LockPaint()
+{
+ LockPaint_Impl(FALSE);
+}
+
+void ScDocShell::UnlockPaint()
+{
+ UnlockPaint_Impl(FALSE);
+}
+
+void ScDocShell::LockDocument()
+{
+ LockPaint_Impl(TRUE);
+ LockDocument_Impl(nDocumentLock + 1);
+}
+
+void ScDocShell::UnlockDocument()
+{
+ if (nDocumentLock)
+ {
+ UnlockPaint_Impl(TRUE);
+ UnlockDocument_Impl(nDocumentLock - 1);
+ }
+ else
+ {
+ DBG_ERROR("UnlockDocument without LockDocument");
+ }
+}
+
+//------------------------------------------------------------------
+
+void ScDocShell::SetInplace( BOOL bInplace )
+{
+ if (bIsInplace != bInplace)
+ {
+ bIsInplace = bInplace;
+ CalcOutputFactor();
+ }
+}
+
+void ScDocShell::CalcOutputFactor()
+{
+ if (bIsInplace)
+ {
+ nPrtToScreenFactor = 1.0; // passt sonst nicht zur inaktiven Darstellung
+ return;
+ }
+
+ 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
+ {
+ DBG_ERROR("GetTextSize gibt 0 ??");
+ nPrtToScreenFactor = 1.0;
+ }
+}
+
+double ScDocShell::GetOutputFactor() const
+{
+ return nPrtToScreenFactor;
+}
+
+//---------------------------------------------------------------------
+
+void ScDocShell::InitOptions() // Fortsetzung von InitNew (CLOOKs)
+{
+ // Einstellungen aus dem SpellCheckCfg kommen in Doc- und ViewOptions
+
+ USHORT nDefLang, nCjkLang, nCtlLang;
+ 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<USHORT>( ::utl::MiscCfg().GetYear2000() ) );
+
+ 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(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 ); // FALSE or TRUE???
+ SvxFontListItem aFontListItem( pImpl->pFontList, SID_ATTR_CHAR_FONTLIST );
+ PutItem( aFontListItem );
+
+ CalcOutputFactor();
+}
+
+OutputDevice* ScDocShell::GetRefDevice()
+{
+ return aDocument.GetRefDevice();
+}
+
+USHORT ScDocShell::SetPrinter( SfxPrinter* pNewPrinter, USHORT 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);
+ BOOL bWasLand = rOldItem.IsLandscape();
+ 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;
+ const ScChangeAction* pFoundContent = NULL;
+ const ScChangeAction* pFoundMove = 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
+ switch ( pAction->GetType() )
+ {
+ case SC_CAT_CONTENT :
+ pFoundContent = pAction;
+ break;
+ case SC_CAT_MOVE :
+ pFoundMove = pAction;
+ break;
+ default:
+ {
+ // added to avoid warnings
+ }
+ }
+ ++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)
+ {
+ ULONG nNumber = pAction->GetActionNumber();
+ pTrack->NotifyModified( SC_CTM_CHANGE, nNumber, nNumber );
+ }
+ }
+}
+
+void ScDocShell::ExecuteChangeCommentDialog( ScChangeAction* pAction, Window* pParent,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();
+ }
+ 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 BOOL lcl_Equal( const ScChangeAction* pA, const ScChangeAction* pB, 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, BOOL bIgnore100Sec )
+{
+ if ( !pDoc || !pAction || !pSearchDoc || !pFirstSearchAction || !pLastSearchAction )
+ {
+ return false;
+ }
+
+ 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, TRUE );
+ String aADesc;
+ pA->GetDescription( aADesc, pSearchDoc, TRUE );
+ if ( aActionDesc.Equals( aADesc ) )
+ {
+ DBG_ERROR( "lcl_FindAction(): found equal action!" );
+ return true;
+ }
+ }
+ pA = pA->GetNext();
+ }
+
+ return false;
+}
+
+void ScDocShell::MergeDocument( ScDocument& rOtherDoc, bool bShared, bool bCheckDuplicates, 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 )
+ {
+ // #51138# visuelles RedLining einschalten
+ ScChangeViewSettings aChangeViewSet;
+ aChangeViewSet.SetShowChanges(TRUE);
+ aDocument.SetChangeViewSettings(aChangeViewSet);
+ }
+ }
+
+ // #97286# include 100th seconds in compare?
+ BOOL bIgnore100Sec = !pSourceTrack->IsTime100thSeconds() ||
+ !pThisTrack->IsTime100thSeconds();
+
+ // gemeinsame Ausgangsposition suchen
+ 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
+ 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 );
+
+ 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
+ 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
+ BOOL bHasRejected = FALSE;
+ String 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, &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";
+ DBG_ERROR( aError.GetBuffer() );
+#endif
+ }
+ else
+ {
+ //! Datum/Autor/Kommentar der Source-Aktion uebernehmen!
+
+ pThisTrack->SetUser( pSourceAction->GetUser() );
+ pThisTrack->SetFixDateTimeUTC( pSourceAction->GetDateTimeUTC() );
+ ULONG nOldActionMax = pThisTrack->GetActionMax();
+
+ bool bExecute = true;
+ 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 = 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 = 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 );
+ BYTE 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:
+ DBG_ERROR( "MergeDocument: unknown MatrixFlag" );
+ }
+ }
+ break;
+ case SC_CAT_INSERT_TABS :
+ {
+ String aName;
+ aDocument.CreateValidTabName( aName );
+ GetDocFunc().InsertTable( aSourceRange.aStart.Tab(), aName, TRUE, FALSE );
+ }
+ break;
+ case SC_CAT_INSERT_ROWS:
+ GetDocFunc().InsertCells( aSourceRange, NULL, INS_INSROWS, TRUE, FALSE );
+ break;
+ case SC_CAT_INSERT_COLS:
+ GetDocFunc().InsertCells( aSourceRange, NULL, INS_INSCOLS, TRUE, FALSE );
+ break;
+ case SC_CAT_DELETE_TABS :
+ GetDocFunc().DeleteTable( aSourceRange.aStart.Tab(), 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, TRUE, FALSE );
+ }
+ }
+ 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, TRUE, FALSE );
+ }
+ }
+ break;
+ case SC_CAT_MOVE :
+ {
+ const ScChangeActionMove* pMove = (const ScChangeActionMove*) pSourceAction;
+ ScRange aFromRange( pMove->GetFromRange().MakeRange() );
+ GetDocFunc().MoveBlock( aFromRange,
+ aSourceRange.aStart, TRUE, 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
+ DBG_ERROR( "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 )
+ {
+ ULONG nActionMax = pAct->GetActionNumber();
+ ULONG nActionCount = nActionMax - nOldActionMax;
+ ULONG nAction = nActionMax - nActionCount + 1;
+ 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;
+ }
+
+#if DEBUG_CHANGETRACK
+ ::rtl::OUString aMessage = ::rtl::OUString::createFromAscii( "\nbefore merge:\n" );
+ aMessage += pThisTrack->ToString();
+ ::rtl::OString aMsg = ::rtl::OUStringToOString( aMessage, RTL_TEXTENCODING_UTF8 );
+ OSL_ENSURE( false, aMsg.getStr() );
+ //fprintf( stdout, "%s ", aMsg.getStr() );
+ //fflush( stdout );
+#endif // DEBUG_CHANGETRACK
+
+ // reset show changes
+ ScChangeViewSettings aChangeViewSet;
+ aChangeViewSet.SetShowChanges( FALSE );
+ aDocument.SetChangeViewSettings( aChangeViewSet );
+
+ // find first merge action in this document
+ 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
+ ULONG nActStartShared = pSharedAction->GetActionNumber();
+ 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;
+ ULONG nActStartOwn = nActEndShared + 1;
+ 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
+ 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 );
+ 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( TRUE );
+ aChangeViewSet.SetShowAccepted( TRUE );
+ aChangeViewSet.SetHasActionRange( true );
+ aChangeViewSet.SetTheActionRange( nStartShared, nEndShared );
+ aDocument.SetChangeViewSettings( aChangeViewSet );
+
+ // merge own changes back into own document
+ ULONG nStartOwn = nEndShared + 1;
+ ScChangeActionMergeMap aOwnMergeMap;
+ MergeDocument( *pTmpDoc, true, true, nEndShared - nStartShared + 1, &aOwnMergeMap );
+ delete pTmpDoc;
+ 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
+ ULONG nStartShared = pThisTrack->GetActionMax() + 1;
+ MergeDocument( rSharedDoc, true, true );
+ ULONG nEndShared = pThisTrack->GetActionMax();
+
+ // only show changes from shared document
+ aChangeViewSet.SetShowChanges( TRUE );
+ aChangeViewSet.SetShowAccepted( 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();
+ }
+
+#if DEBUG_CHANGETRACK
+ aMessage = ::rtl::OUString::createFromAscii( "\nafter merge:\n" );
+ aMessage += pThisTrack->ToString();
+ aMsg = ::rtl::OUStringToOString( aMessage, RTL_TEXTENCODING_UTF8 );
+ OSL_ENSURE( false, aMsg.getStr() );
+ //fprintf( stdout, "%s ", aMsg.getStr() );
+ //fflush( stdout );
+#endif // DEBUG_CHANGETRACK
+
+ return ( pThisAction != NULL );
+}
diff --git a/sc/source/ui/docshell/docsh4.cxx b/sc/source/ui/docshell/docsh4.cxx
new file mode 100644
index 000000000000..97403008915d
--- /dev/null
+++ b/sc/source/ui/docshell/docsh4.cxx
@@ -0,0 +1,2730 @@
+/*************************************************************************
+ *
+ * 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 <com/sun/star/embed/XEmbeddedObject.hpp>
+#include <com/sun/star/frame/XComponentLoader.hpp>
+
+
+using namespace ::com::sun::star;
+
+// INCLUDE ---------------------------------------------------------------
+#if STLPORT_VERSION>=321
+#include <math.h> // prevent conflict between exception and std::exception
+#endif
+
+#include "scitems.hxx"
+#include <sfx2/fcontnr.hxx>
+#include <editeng/eeitem.hxx>
+
+#include <sfx2/app.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/docfilt.hxx>
+#include <svtools/ehdl.hxx>
+#include <basic/sbxcore.hxx>
+#include <sfx2/printer.hxx>
+#include <sfx2/request.hxx>
+#include <svtools/sfxecode.hxx>
+#include <sfx2/topfrm.hxx>
+#include <svx/ofaitem.hxx>
+#include <sot/formats.hxx>
+#include <svtools/printdlg.hxx>
+#include <svl/whiter.hxx>
+#include <vcl/msgbox.hxx>
+#include <vcl/waitobj.hxx>
+#include <tools/multisel.hxx>
+#include <svx/drawitem.hxx>
+#include <svx/fmview.hxx>
+#include <svx/pageitem.hxx>
+#include <svx/svditer.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/fmshell.hxx>
+#include <sfx2/passwd.hxx>
+#include <sfx2/filedlghelper.hxx>
+#include <sfx2/docinsert.hxx>
+#include <svl/PasswordHelper.hxx>
+#include <svl/documentlockfile.hxx>
+#include <svl/sharecontrolfile.hxx>
+
+#include <comphelper/processfactory.hxx>
+#include "docuno.hxx"
+
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include "docsh.hxx"
+#include "docshimp.hxx"
+#include "docfunc.hxx"
+#include "sc.hrc"
+#include "stlsheet.hxx"
+#include "stlpool.hxx"
+#include "appoptio.hxx"
+#include "globstr.hrc"
+#include "global.hxx"
+//CHINA001 #include "styledlg.hxx"
+//CHINA001 #include "hfedtdlg.hxx"
+#include "dbdocfun.hxx"
+#include "printfun.hxx" // DrawToDev
+#include "viewdata.hxx"
+#include "tabvwsh.hxx"
+#include "impex.hxx"
+#include "attrib.hxx"
+//CHINA001 #include "corodlg.hxx"
+#include "undodat.hxx"
+#include "autostyl.hxx"
+#include "undocell.hxx"
+#include "undotab.hxx"
+#include "inputhdl.hxx"
+#include "dbcolect.hxx"
+#include "servobj.hxx"
+#include "rangenam.hxx"
+#include "scmod.hxx"
+//CHINA001 #include "scendlg.hxx"
+#include "chgviset.hxx"
+#include "reffact.hxx"
+#include "chartlis.hxx"
+#include "waitoff.hxx"
+#include "tablink.hxx" // ScDocumentLoader statics
+#include "drwlayer.hxx"
+#include "docoptio.hxx"
+#include "undostyl.hxx"
+#include "rangeseq.hxx"
+#include "chgtrack.hxx"
+#include "printopt.hxx"
+#include <com/sun/star/document/UpdateDocMode.hpp>
+#include "scresid.hxx" //add by CHINA001
+#include "scabstdlg.hxx" //CHINA001
+#include "externalrefmgr.hxx"
+
+#include "sharedocdlg.hxx"
+#include "conditio.hxx"
+
+//------------------------------------------------------------------
+
+#define IS_SHARE_HEADER(set) \
+ ((SfxBoolItem&) \
+ ((SvxSetItem&)(set).Get(ATTR_PAGE_HEADERSET)).GetItemSet(). \
+ Get(ATTR_PAGE_SHARED)).GetValue()
+
+#define IS_SHARE_FOOTER(set) \
+ ((SfxBoolItem&) \
+ ((SvxSetItem&)(set).Get(ATTR_PAGE_FOOTERSET)).GetItemSet(). \
+ Get(ATTR_PAGE_SHARED)).GetValue()
+
+#define IS_AVAILABLE(WhichId,ppItem) \
+ (pReqArgs->GetItemState((WhichId), TRUE, ppItem ) == SFX_ITEM_SET)
+
+#define SC_PREVIEW_SIZE_X 10000
+#define SC_PREVIEW_SIZE_Y 12400
+
+
+//------------------------------------------------------------------
+
+void ScDocShell::Execute( SfxRequest& rReq )
+{
+ // SID_SC_RANGE (Range),
+ // SID_SC_CELLTEXT (CellText),
+ // SID_SC_CELLS (Cells) - removed (old Basic)
+
+ const SfxItemSet* pReqArgs = rReq.GetArgs();
+ SfxBindings* pBindings = GetViewBindings();
+ BOOL bUndo (aDocument.IsUndoEnabled());
+
+ USHORT nSlot = rReq.GetSlot();
+ switch ( nSlot )
+ {
+ case SID_SC_SETTEXT:
+ {
+ const SfxPoolItem* pColItem;
+ const SfxPoolItem* pRowItem;
+ const SfxPoolItem* pTabItem;
+ const SfxPoolItem* pTextItem;
+ if( pReqArgs && IS_AVAILABLE( FN_PARAM_1, &pColItem ) &&
+ IS_AVAILABLE( FN_PARAM_2, &pRowItem ) &&
+ IS_AVAILABLE( FN_PARAM_3, &pTabItem ) &&
+ IS_AVAILABLE( SID_SC_SETTEXT, &pTextItem ) )
+ {
+ // Parameter sind 1-based !!!
+ SCCOL nCol = ((SfxInt16Item*)pColItem)->GetValue() - 1;
+ SCROW nRow = ((SfxInt32Item*)pRowItem)->GetValue() - 1;
+ SCTAB nTab = ((SfxInt16Item*)pTabItem)->GetValue() - 1;
+
+ SCTAB nTabCount = aDocument.GetTableCount();
+ if ( ValidCol(nCol) && ValidRow(nRow) && ValidTab(nTab,nTabCount) )
+ {
+ if ( aDocument.IsBlockEditable( nTab, nCol,nRow, nCol, nRow ) )
+ {
+ String aVal = ((const SfxStringItem*)pTextItem)->GetValue();
+ aDocument.SetString( nCol, nRow, nTab, aVal );
+
+ PostPaintCell( nCol, nRow, nTab );
+ SetDocumentModified();
+
+ rReq.Done();
+ break;
+ }
+ else // geschuetzte Zelle
+ {
+ SbxBase::SetError( SbxERR_BAD_PARAMETER ); //! welchen Fehler ?
+ break;
+ }
+ }
+ }
+ SbxBase::SetError( SbxERR_NO_OBJECT );
+ }
+ break;
+
+
+ // SID_SBA_QRY_CHANGETARGET gibts nicht mehr - auch in idl raus
+
+ case SID_SBA_IMPORT:
+ {
+ if (pReqArgs)
+ {
+ const sal_Unicode cSbaSep = 11; // Trennzeichen
+
+ const SfxPoolItem* pItem;
+ String sSbaData, sTarget;
+ if ( pReqArgs->GetItemState( nSlot, TRUE, &pItem ) == SFX_ITEM_SET )
+ sSbaData = ((const SfxStringItem*)pItem)->GetValue();
+ if ( pReqArgs->GetItemState( FN_PARAM_1, TRUE, &pItem ) == SFX_ITEM_SET )
+ sTarget = ((const SfxStringItem*)pItem)->GetValue();
+
+ BOOL bIsNewArea = TRUE; // Default TRUE (keine Nachfrage)
+ if ( pReqArgs->GetItemState( FN_PARAM_2, TRUE, &pItem ) == SFX_ITEM_SET )
+ bIsNewArea = ((const SfxBoolItem*)pItem)->GetValue();
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::sdbc::XResultSet > xResultSet;
+ if ( pReqArgs->GetItemState( FN_PARAM_3, FALSE, &pItem ) == SFX_ITEM_SET && pItem )
+ xResultSet.set(((const SfxUsrAnyItem*)pItem)->GetValue(),::com::sun::star::uno::UNO_QUERY);
+
+ String sDBName = sSbaData.GetToken(0,cSbaSep); // Datenbankname
+ String sDBTable = sSbaData.GetToken(1,cSbaSep); // Tabellen- oder Query-Name
+ String sTabFlag = sSbaData.GetToken(2,cSbaSep);
+ String sDBSql = sSbaData.GetToken(3,cSbaSep); // SQL im Klartext
+
+ BYTE nType = ScDbTable; // "0" oder "1"
+ if ( sTabFlag.EqualsAscii("0") ) // "0" = Query, "1" = Table (Default)
+ nType = ScDbQuery;
+
+ SbaSelectionListRef pSelectionList = new SbaSelectionList;
+ xub_StrLen nCount = sSbaData.GetTokenCount(cSbaSep);
+
+ for (xub_StrLen i = 4; i < nCount; i++)
+ {
+ String aSelItem = sSbaData.GetToken(i,cSbaSep);
+ if (aSelItem.Len())
+ {
+ void *pPtr = (void*)aSelItem.ToInt32();
+ pSelectionList->Insert( pPtr, LIST_APPEND );
+ }
+ }
+
+ // bei Bedarf neuen Datenbankbereich anlegen
+ BOOL bMakeArea = FALSE;
+ if (bIsNewArea)
+ {
+ ScDBCollection* pDBColl = aDocument.GetDBCollection();
+ USHORT nDummy;
+ if ( !pDBColl || !pDBColl->SearchName( sTarget, nDummy ) )
+ {
+ ScAddress aPos;
+ if ( aPos.Parse( sTarget, &aDocument, aDocument.GetAddressConvention() ) & SCA_VALID )
+ {
+ bMakeArea = TRUE;
+ if (bUndo)
+ {
+ String aStrImport = ScGlobal::GetRscString( STR_UNDO_IMPORTDATA );
+ GetUndoManager()->EnterListAction( aStrImport, aStrImport );
+ }
+
+ ScDBData* pDBData = GetDBData( ScRange(aPos), SC_DB_IMPORT, FALSE );
+ DBG_ASSERT(pDBData, "kann DB-Daten nicht anlegen");
+ sTarget = pDBData->GetName();
+ }
+ }
+ }
+
+ // nachfragen, bevor alter DB-Bereich ueberschrieben wird
+ BOOL bDo = TRUE;
+ if (!bIsNewArea)
+ {
+ String aTemplate = ScGlobal::GetRscString( STR_IMPORT_REPLACE );
+ String aMessage = aTemplate.GetToken( 0, '#' );
+ aMessage += sTarget;
+ aMessage += aTemplate.GetToken( 1, '#' );
+
+ QueryBox aBox( 0, WinBits(WB_YES_NO | WB_DEF_YES), aMessage );
+ bDo = ( aBox.Execute() == RET_YES );
+ }
+
+ if (bDo)
+ {
+ ScDBDocFunc(*this).UpdateImport( sTarget, sDBName,
+ sDBTable, sDBSql, TRUE, nType, xResultSet,
+ pSelectionList );
+ rReq.Done();
+
+ // UpdateImport aktualisiert auch die internen Operationen
+ }
+ else
+ rReq.Ignore();
+
+ if ( bMakeArea && bUndo)
+ GetUndoManager()->LeaveListAction();
+ }
+ else
+ {
+ DBG_ERROR( "arguments expected" );
+ }
+ }
+ break;
+
+ case SID_CHART_SOURCE:
+ case SID_CHART_ADDSOURCE:
+ if (pReqArgs)
+ {
+ ScDocument* pDoc = GetDocument();
+// BOOL bUndo (pDoc->IsUndoEnabled());
+ const SfxPoolItem* pItem;
+ String aChartName, aRangeName;
+
+ ScRange aSingleRange;
+ ScRangeListRef aRangeListRef;
+ BOOL bMultiRange = FALSE;
+
+ BOOL bColHeaders = TRUE;
+ BOOL bRowHeaders = TRUE;
+ BOOL bColInit = FALSE;
+ BOOL bRowInit = FALSE;
+ BOOL bAddRange = (nSlot == SID_CHART_ADDSOURCE);
+
+ if( IS_AVAILABLE( SID_CHART_NAME, &pItem ) )
+ aChartName = ((const SfxStringItem*)pItem)->GetValue();
+
+ if( IS_AVAILABLE( SID_CHART_SOURCE, &pItem ) )
+ aRangeName = ((const SfxStringItem*)pItem)->GetValue();
+
+ if( IS_AVAILABLE( FN_PARAM_1, &pItem ) )
+ {
+ bColHeaders = ((const SfxBoolItem*)pItem)->GetValue();
+ bColInit = TRUE;
+ }
+ if( IS_AVAILABLE( FN_PARAM_2, &pItem ) )
+ {
+ bRowHeaders = ((const SfxBoolItem*)pItem)->GetValue();
+ bRowInit = TRUE;
+ }
+
+ ScAddress::Details aDetails(pDoc->GetAddressConvention(), 0, 0);
+ BOOL bValid = ( aSingleRange.ParseAny( aRangeName, pDoc, aDetails ) & SCA_VALID ) != 0;
+ if (!bValid)
+ {
+ aRangeListRef = new ScRangeList;
+ aRangeListRef->Parse( aRangeName, pDoc );
+ if ( aRangeListRef->Count() )
+ {
+ bMultiRange = TRUE;
+ aSingleRange = *aRangeListRef->GetObject(0); // fuer Header
+ bValid = TRUE;
+ }
+ else
+ aRangeListRef.Clear();
+ }
+
+ ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
+ if (pViewSh && bValid && aChartName.Len() != 0 )
+ {
+ Window* pParent = pViewSh->GetDialogParent();
+
+ SCCOL nCol1 = aSingleRange.aStart.Col();
+ SCROW nRow1 = aSingleRange.aStart.Row();
+ SCCOL nCol2 = aSingleRange.aEnd.Col();
+ SCROW nRow2 = aSingleRange.aEnd.Row();
+ SCTAB nTab = aSingleRange.aStart.Tab();
+
+ //! immer oder gar nicht begrenzen ???
+ if (!bMultiRange)
+ aDocument.LimitChartArea( nTab, nCol1,nRow1, nCol2,nRow2 );
+
+ // Dialog fuer Spalten/Zeilenkoepfe
+ BOOL bOk = TRUE;
+ if ( !bAddRange && ( !bColInit || !bRowInit ) )
+ {
+ // Spalten/Zeilenkoepfe testen wie in chartarr
+ if (!bColInit)
+ {
+ for (SCCOL i=nCol1; i<=nCol2 && bColHeaders; i++)
+ if (aDocument.HasValueData( i, nRow1, nTab ))
+ bColHeaders = FALSE;
+ }
+ if (!bRowInit)
+ {
+ for (SCROW i=nRow1; i<=nRow2 && bRowHeaders; i++)
+ if (aDocument.HasValueData( nCol1, i, nTab ))
+ bRowHeaders = FALSE;
+ }
+
+ //CHINA001 ScColRowLabelDlg aDlg( pParent, bRowHeaders, bColHeaders );
+ ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
+ DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001
+
+ AbstractScColRowLabelDlg* pDlg = pFact->CreateScColRowLabelDlg( pParent, RID_SCDLG_CHARTCOLROW, bRowHeaders, bColHeaders);
+ DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001
+ if ( pDlg->Execute() == RET_OK ) //CHINA001 if ( aDlg.Execute() == RET_OK )
+ {
+ bColHeaders = pDlg->IsRow(); //CHINA001 bColHeaders = aDlg.IsRow(); // Spaltenkoepfe = 1. Zeile
+ bRowHeaders = pDlg->IsCol(); //CHINA001 bRowHeaders = aDlg.IsCol();
+
+ rReq.AppendItem(SfxBoolItem(FN_PARAM_1, bColHeaders));
+ rReq.AppendItem(SfxBoolItem(FN_PARAM_2, bRowHeaders));
+ }
+ else
+ bOk = FALSE;
+ delete pDlg; //CHINA001
+ }
+
+ if (bOk) // ausfuehren
+ {
+ if (bMultiRange)
+ {
+ if (bUndo)
+ {
+ GetUndoManager()->AddUndoAction(
+ new ScUndoChartData( this, aChartName, aRangeListRef,
+ bColHeaders, bRowHeaders, bAddRange ) );
+ }
+ aDocument.UpdateChartArea( aChartName, aRangeListRef,
+ bColHeaders, bRowHeaders, bAddRange );
+ }
+ else
+ {
+ ScRange aNewRange( nCol1,nRow1,nTab, nCol2,nRow2,nTab );
+ if (bUndo)
+ {
+ GetUndoManager()->AddUndoAction(
+ new ScUndoChartData( this, aChartName, aNewRange,
+ bColHeaders, bRowHeaders, bAddRange ) );
+ }
+ aDocument.UpdateChartArea( aChartName, aNewRange,
+ bColHeaders, bRowHeaders, bAddRange );
+ }
+ }
+ }
+ else
+ {
+ DBG_ERROR("UpdateChartArea: keine ViewShell oder falsche Daten");
+ }
+ rReq.Done();
+ }
+ else
+ {
+ DBG_ERROR("SID_CHART_SOURCE ohne Argumente");
+ }
+ break;
+
+ case FID_AUTO_CALC:
+ {
+ BOOL bNewVal;
+ const SfxPoolItem* pItem;
+ if ( pReqArgs && SFX_ITEM_SET == pReqArgs->GetItemState( nSlot, TRUE, &pItem ) )
+ bNewVal = ((const SfxBoolItem*)pItem)->GetValue();
+ else
+ bNewVal = !aDocument.GetAutoCalc(); // Toggle fuer Menue
+ aDocument.SetAutoCalc( bNewVal );
+ SetDocumentModified();
+ if (pBindings)
+ {
+ pBindings->Invalidate( FID_AUTO_CALC );
+// pBindings->Invalidate( FID_RECALC ); // jetzt immer enabled
+ }
+ rReq.AppendItem( SfxBoolItem( FID_AUTO_CALC, bNewVal ) );
+ rReq.Done();
+ }
+ break;
+ case FID_RECALC:
+ DoRecalc( rReq.IsAPI() );
+ rReq.Done();
+ break;
+ case FID_HARD_RECALC:
+ DoHardRecalc( rReq.IsAPI() );
+ rReq.Done();
+ break;
+ case SID_UPDATETABLINKS:
+ {
+ ScDocument* pDoc = GetDocument();
+
+ ScLkUpdMode nSet=pDoc->GetLinkMode();
+
+ USHORT nDlgRet=RET_NO;
+ if(nSet==LM_UNKNOWN)
+ {
+ ScAppOptions aAppOptions=SC_MOD()->GetAppOptions();
+ nSet=aAppOptions.GetLinkMode();
+ }
+
+ if (nCanUpdate == com::sun::star::document::UpdateDocMode::NO_UPDATE)
+ nSet = LM_NEVER;
+ else if (nCanUpdate == com::sun::star::document::UpdateDocMode::QUIET_UPDATE &&
+ nSet == LM_ON_DEMAND)
+ nSet = LM_NEVER;
+ else if (nCanUpdate == com::sun::star::document::UpdateDocMode::FULL_UPDATE)
+ nSet = LM_ALWAYS;
+
+ if(nSet==LM_ON_DEMAND)
+ {
+ QueryBox aBox( GetActiveDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES),
+ ScGlobal::GetRscString(STR_RELOAD_TABLES) );
+
+ nDlgRet=aBox.Execute();
+ }
+
+ if (nDlgRet == RET_YES || nSet==LM_ALWAYS)
+ {
+ ReloadTabLinks();
+ aDocument.UpdateExternalRefLinks();
+ aDocument.UpdateDdeLinks();
+ aDocument.UpdateAreaLinks();
+
+ //! Test, ob Fehler
+ rReq.Done();
+ }
+ else
+ rReq.Ignore();
+ }
+ break;
+
+ case SID_REIMPORT_AFTER_LOAD:
+ {
+ // wird nach dem Laden aufgerufen, wenn DB-Bereiche mit
+ // weggelassenen Daten enthalten sind
+
+ BOOL bDone = FALSE;
+ ScDBCollection* pDBColl = aDocument.GetDBCollection();
+
+ if ((nCanUpdate != com::sun::star::document::UpdateDocMode::NO_UPDATE) &&
+ (nCanUpdate != com::sun::star::document::UpdateDocMode::QUIET_UPDATE))
+ {
+ ScRange aRange;
+ ScTabViewShell* pViewSh = GetBestViewShell();
+ DBG_ASSERT(pViewSh,"SID_REIMPORT_AFTER_LOAD: keine View");
+ if (pViewSh && pDBColl)
+ {
+ QueryBox aBox( GetActiveDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES),
+ ScGlobal::GetRscString(STR_REIMPORT_AFTER_LOAD) );
+ if (aBox.Execute() == RET_YES)
+ {
+ for (USHORT i=0; i<pDBColl->GetCount(); i++)
+ {
+ ScDBData* pDBData = (*pDBColl)[i];
+ if ( pDBData->IsStripData() &&
+ pDBData->HasImportParam() && !pDBData->HasImportSelection() )
+ {
+ pDBData->GetArea(aRange);
+ pViewSh->MarkRange(aRange);
+
+ // Import und interne Operationen wie SID_REFRESH_DBAREA
+ // (Abfrage auf Import hier nicht noetig)
+
+ ScImportParam aImportParam;
+ pDBData->GetImportParam( aImportParam );
+ BOOL bContinue = pViewSh->ImportData( aImportParam );
+ pDBData->SetImportParam( aImportParam );
+
+ // markieren (Groesse kann sich geaendert haben)
+ pDBData->GetArea(aRange);
+ pViewSh->MarkRange(aRange);
+
+ if ( bContinue ) // #41905# Fehler beim Import -> Abbruch
+ {
+ // interne Operationen, wenn welche gespeichert
+
+ if ( pDBData->HasQueryParam() || pDBData->HasSortParam() ||
+ pDBData->HasSubTotalParam() )
+ pViewSh->RepeatDB();
+
+ // Pivottabellen die den Bereich als Quelldaten haben
+
+ RefreshPivotTables(aRange);
+ }
+ }
+ }
+ bDone = TRUE;
+ }
+ }
+ }
+
+ if ( !bDone && pDBColl )
+ {
+ // wenn nicht, dann aber die abhaengigen Formeln updaten
+ //! auch fuer einzelne Bereiche, die nicht aktualisiert werden koennen
+
+ aDocument.CalcAll(); //! nur die abhaengigen
+ PostDataChanged();
+ }
+
+ if (bDone)
+ rReq.Done();
+ else
+ rReq.Ignore();
+ }
+ break;
+
+
+ case SID_AUTO_STYLE:
+ DBG_ERROR("use ScAutoStyleHint instead of SID_AUTO_STYLE");
+ break;
+
+ case SID_GET_COLORTABLE:
+ {
+ // passende ColorTable ist per PutItem gesetzt worden
+ SvxColorTableItem* pColItem = (SvxColorTableItem*)GetItem(SID_COLOR_TABLE);
+ XColorTable* pTable = pColItem->GetColorTable();
+ rReq.SetReturnValue(OfaPtrItem(SID_GET_COLORTABLE, pTable));
+ }
+ break;
+
+ case FID_CHG_RECORD:
+ {
+ ScDocument* pDoc = GetDocument();
+ if(pDoc!=NULL)
+ {
+ // get argument (recorded macro)
+ SFX_REQUEST_ARG( rReq, pItem, SfxBoolItem, FID_CHG_RECORD, sal_False );
+ BOOL bDo = TRUE;
+
+ // xmlsec05/06:
+ // getting real parent window when called from Security-Options TP
+ Window* pParent = NULL;
+ const SfxPoolItem* pParentItem;
+ if( pReqArgs && SFX_ITEM_SET == pReqArgs->GetItemState( SID_ATTR_PARENTWINDOW, FALSE, &pParentItem ) )
+ pParent = ( Window* ) ( ( const OfaPtrItem* ) pParentItem )->GetValue();
+
+ // desired state
+ ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
+ BOOL bActivateTracking = (pChangeTrack == 0); // toggle
+ if ( pItem )
+ bActivateTracking = pItem->GetValue(); // from argument
+
+ if ( !bActivateTracking )
+ {
+ if ( !pItem )
+ {
+ // no dialog on playing the macro
+ WarningBox aBox( pParent ? pParent : GetActiveDialogParent(),
+ WinBits(WB_YES_NO | WB_DEF_NO),
+ ScGlobal::GetRscString( STR_END_REDLINING ) );
+ bDo = ( aBox.Execute() == RET_YES );
+ }
+
+ if ( bDo )
+ {
+ if ( pChangeTrack->IsProtected() )
+ bDo = ExecuteChangeProtectionDialog( NULL );
+ if ( bDo )
+ {
+ pDoc->EndChangeTracking();
+ PostPaintGridAll();
+ }
+ }
+ }
+ else
+ {
+ pDoc->StartChangeTracking();
+ ScChangeViewSettings aChangeViewSet;
+ aChangeViewSet.SetShowChanges(TRUE);
+ pDoc->SetChangeViewSettings(aChangeViewSet);
+ }
+
+ if ( bDo )
+ {
+ // update "accept changes" dialog
+ //! notify all views
+ SfxViewFrame* pViewFrm = SfxViewFrame::Current();
+ if ( pViewFrm && pViewFrm->HasChildWindow(FID_CHG_ACCEPT) )
+ {
+ SfxChildWindow* pChild = pViewFrm->GetChildWindow(FID_CHG_ACCEPT);
+ if (pChild)
+ {
+ ((ScAcceptChgDlgWrapper*)pChild)->ReInitDlg();
+ }
+ }
+
+ // Slots invalidieren
+ if (pBindings)
+ pBindings->InvalidateAll(FALSE);
+ if ( !pItem )
+ rReq.AppendItem( SfxBoolItem( FID_CHG_RECORD, bActivateTracking ) );
+ rReq.Done();
+ }
+ else
+ rReq.Ignore();
+ }
+ }
+ break;
+
+ case SID_CHG_PROTECT :
+ {
+ Window* pParent = NULL;
+ const SfxPoolItem* pParentItem;
+ if( pReqArgs && SFX_ITEM_SET == pReqArgs->GetItemState( SID_ATTR_PARENTWINDOW, FALSE, &pParentItem ) )
+ pParent = ( Window* ) ( ( const OfaPtrItem* ) pParentItem )->GetValue();
+ if ( ExecuteChangeProtectionDialog( pParent ) )
+ {
+ rReq.Done();
+ SetDocumentModified();
+ }
+ else
+ rReq.Ignore();
+ }
+ break;
+
+ case SID_DOCUMENT_MERGE:
+ case SID_DOCUMENT_COMPARE:
+ {
+ BOOL bDo = TRUE;
+ ScChangeTrack* pChangeTrack = aDocument.GetChangeTrack();
+ if ( pChangeTrack && !pImpl->bIgnoreLostRedliningWarning )
+ {
+ if ( nSlot == SID_DOCUMENT_COMPARE )
+ { //! old changes trace will be lost
+ WarningBox aBox( GetActiveDialogParent(),
+ WinBits(WB_YES_NO | WB_DEF_NO),
+ ScGlobal::GetRscString( STR_END_REDLINING ) );
+ if( aBox.Execute() == RET_YES )
+ bDo = ExecuteChangeProtectionDialog( NULL, TRUE );
+ else
+ bDo = FALSE;
+ }
+ else // merge might reject some actions
+ bDo = ExecuteChangeProtectionDialog( NULL, TRUE );
+ }
+ if ( !bDo )
+ {
+ rReq.Ignore();
+ break;
+ }
+ SfxApplication* pApp = SFX_APP();
+ const SfxPoolItem* pItem;
+ SfxMedium* pMed = NULL;
+ if ( pReqArgs &&
+ pReqArgs->GetItemState( SID_FILE_NAME, TRUE, &pItem ) == SFX_ITEM_SET &&
+ pItem->ISA(SfxStringItem) )
+ {
+ String aFileName = ((const SfxStringItem*)pItem)->GetValue();
+
+ String aFilterName;
+ if ( pReqArgs->GetItemState( SID_FILTER_NAME, TRUE, &pItem ) == SFX_ITEM_SET &&
+ pItem->ISA(SfxStringItem) )
+ {
+ aFilterName = ((const SfxStringItem*)pItem)->GetValue();
+ }
+ String aOptions;
+ if ( pReqArgs->GetItemState( SID_FILE_FILTEROPTIONS, TRUE, &pItem ) == SFX_ITEM_SET &&
+ pItem->ISA(SfxStringItem) )
+ {
+ aOptions = ((const SfxStringItem*)pItem)->GetValue();
+ }
+ short nVersion = 0;
+ if ( pReqArgs->GetItemState( SID_VERSION, TRUE, &pItem ) == SFX_ITEM_SET &&
+ pItem->ISA(SfxInt16Item) )
+ {
+ nVersion = ((const SfxInt16Item*)pItem)->GetValue();
+ }
+
+ // kein Filter angegeben -> Detection
+ if ( !aFilterName.Len() )
+ ScDocumentLoader::GetFilterName( aFileName, aFilterName, aOptions, TRUE, FALSE );
+
+ // filter name from dialog contains application prefix,
+ // GetFilter needs name without the prefix.
+ ScDocumentLoader::RemoveAppPrefix( aFilterName );
+
+ const SfxFilter* pFilter = ScDocShell::Factory().GetFilterContainer()->GetFilter4FilterName( aFilterName );
+ SfxItemSet* pSet = new SfxAllItemSet( pApp->GetPool() );
+ if ( aOptions.Len() )
+ pSet->Put( SfxStringItem( SID_FILE_FILTEROPTIONS, aOptions ) );
+ if ( nVersion != 0 )
+ pSet->Put( SfxInt16Item( SID_VERSION, nVersion ) );
+ pMed = new SfxMedium( aFileName, STREAM_STD_READ, FALSE, pFilter, pSet );
+ }
+ else
+ {
+ // start file dialog asynchronous
+ pImpl->bIgnoreLostRedliningWarning = true;
+ delete pImpl->pRequest;
+ pImpl->pRequest = new SfxRequest( rReq );
+ delete pImpl->pDocInserter;
+ pImpl->pDocInserter = new ::sfx2::DocumentInserter(
+ 0, String::CreateFromAscii( ScDocShell::Factory().GetShortName() ), 0 );
+ pImpl->pDocInserter->StartExecuteModal( LINK( this, ScDocShell, DialogClosedHdl ) );
+ return ;
+ }
+
+ if ( pMed ) // nun wirklich ausfuehren...
+ {
+ SfxErrorContext aEc( ERRCTX_SFX_OPENDOC, pMed->GetName() );
+
+ ScDocShell* pOtherDocSh = new ScDocShell;
+ SfxObjectShellRef aDocShTablesRef = pOtherDocSh;
+ pOtherDocSh->DoLoad( pMed );
+ ULONG nErr = pOtherDocSh->GetErrorCode();
+ if (nErr)
+ ErrorHandler::HandleError( nErr ); // auch Warnings
+
+ if ( !pOtherDocSh->GetError() ) // nur Errors
+ {
+ BOOL bHadTrack = ( aDocument.GetChangeTrack() != NULL );
+ ULONG nStart = 0;
+ if ( nSlot == SID_DOCUMENT_MERGE && pChangeTrack )
+ {
+ nStart = pChangeTrack->GetActionMax() + 1;
+ }
+
+ if ( nSlot == SID_DOCUMENT_COMPARE )
+ CompareDocument( *pOtherDocSh->GetDocument() );
+ else
+ MergeDocument( *pOtherDocSh->GetDocument() );
+
+ // show "accept changes" dialog
+ //! get view for this document!
+ if ( !IsDocShared() )
+ {
+ SfxViewFrame* pViewFrm = SfxViewFrame::Current();
+ if ( pViewFrm )
+ {
+ pViewFrm->ShowChildWindow( ScAcceptChgDlgWrapper::GetChildWindowId(), TRUE ); //@51669
+ }
+ if ( pBindings )
+ {
+ pBindings->Invalidate( FID_CHG_ACCEPT );
+ }
+ }
+
+ rReq.SetReturnValue( SfxInt32Item( nSlot, 0 ) ); //! ???????
+ rReq.Done();
+
+ if (!bHadTrack) // neu eingeschaltet -> auch anzeigen
+ {
+ ScChangeViewSettings* pOldSet = aDocument.GetChangeViewSettings();
+ if ( !pOldSet || !pOldSet->ShowChanges() )
+ {
+ ScChangeViewSettings aChangeViewSet;
+ aChangeViewSet.SetShowChanges(TRUE);
+ aDocument.SetChangeViewSettings(aChangeViewSet);
+ }
+ }
+ else if ( nSlot == SID_DOCUMENT_MERGE && IsDocShared() && pChangeTrack )
+ {
+ ULONG nEnd = pChangeTrack->GetActionMax();
+ if ( nEnd >= nStart )
+ {
+ // only show changes from merged document
+ ScChangeViewSettings aChangeViewSet;
+ aChangeViewSet.SetShowChanges( TRUE );
+ aChangeViewSet.SetShowAccepted( TRUE );
+ aChangeViewSet.SetHasActionRange( true );
+ aChangeViewSet.SetTheActionRange( nStart, nEnd );
+ aDocument.SetChangeViewSettings( aChangeViewSet );
+
+ // update view
+ PostPaintExtras();
+ PostPaintGridAll();
+ }
+ }
+ }
+ pOtherDocSh->DoClose(); // delete passiert mit der Ref
+ }
+ }
+ break;
+
+ case SID_DELETE_SCENARIO:
+ if (pReqArgs)
+ {
+ const SfxPoolItem* pItem;
+ if ( pReqArgs->GetItemState( nSlot, TRUE, &pItem ) == SFX_ITEM_SET )
+ {
+ if ( pItem->ISA(SfxStringItem) )
+ {
+ String aName = ((const SfxStringItem*)pItem)->GetValue();
+ SCTAB nTab;
+ if (aDocument.GetTable( aName, nTab ))
+ {
+ // DeleteTable von viewfunc nach docfunc verschieben!
+
+ ScTabViewShell* pSh = GetBestViewShell();
+ if ( pSh )
+ {
+ //! SetTabNo in DeleteTable weglassen?
+ SCTAB nDispTab = pSh->GetViewData()->GetTabNo();
+ pSh->DeleteTable( nTab );
+ pSh->SetTabNo(nDispTab);
+ rReq.Done();
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case SID_EDIT_SCENARIO:
+ {
+ const SfxPoolItem* pItem;
+ if ( pReqArgs->GetItemState( nSlot, TRUE, &pItem ) == SFX_ITEM_SET )
+ {
+ if ( pItem->ISA(SfxStringItem) )
+ {
+ String aName = ((const SfxStringItem*)pItem)->GetValue();
+ SCTAB nTab;
+ if (aDocument.GetTable( aName, nTab ))
+ {
+ if (aDocument.IsScenario(nTab))
+ {
+ String aComment;
+ Color aColor;
+ USHORT nFlags;
+ aDocument.GetScenarioData( nTab, aComment, aColor, nFlags );
+
+ // Determine if the Sheet that the Scenario was created on
+ // is protected. But first we need to find that Sheet.
+ // Rewind back to the actual sheet.
+ SCTAB nActualTab = nTab;
+ do
+ {
+ nActualTab--;
+ }
+ while(aDocument.IsScenario(nActualTab));
+ BOOL bSheetProtected = aDocument.IsTabProtected(nActualTab);
+
+ //! anderen Titel am Dialog setzen
+//CHINA001 ScNewScenarioDlg* pNewDlg =
+//CHINA001 new ScNewScenarioDlg( GetActiveDialogParent(), aName, TRUE, bSheetProtected);
+ ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
+ DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001
+
+ AbstractScNewScenarioDlg* pNewDlg = pFact->CreateScNewScenarioDlg( GetActiveDialogParent(), aName, RID_SCDLG_NEWSCENARIO, TRUE,bSheetProtected);
+ DBG_ASSERT(pNewDlg, "Dialog create fail!");//CHINA001
+ pNewDlg->SetScenarioData( aName, aComment, aColor, nFlags );
+ if ( pNewDlg->Execute() == RET_OK )
+ {
+ pNewDlg->GetScenarioData( aName, aComment, aColor, nFlags );
+ ModifyScenario( nTab, aName, aComment, aColor, nFlags );
+ rReq.Done();
+ }
+ delete pNewDlg;
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case SID_ATTR_YEAR2000 :
+ {
+ const SfxPoolItem* pItem;
+ if ( pReqArgs->GetItemState( nSlot, TRUE, &pItem ) == SFX_ITEM_SET )
+ {
+ if ( pItem->ISA(SfxUInt16Item) )
+ {
+ UINT16 nY2k = ((SfxUInt16Item*)pItem)->GetValue();
+ // immer an den DocOptions setzen, damit das auch fuer SO50
+ // gespeichert wird (und alle Abfragen bisher auch darauf laufen).
+ // SetDocOptions propagiert das an den NumberFormatter
+ ScDocOptions aDocOpt( aDocument.GetDocOptions() );
+ aDocOpt.SetYear2000( nY2k );
+ aDocument.SetDocOptions( aDocOpt );
+ // die FormShell soll es mitbekommen
+ ScTabViewShell* pSh = GetBestViewShell();
+ if ( pSh )
+ {
+ FmFormShell* pFSh = pSh->GetFormShell();
+ if ( pFSh )
+ pFSh->SetY2KState( nY2k );
+ }
+ }
+ }
+ }
+ break;
+
+ case SID_SHARE_DOC:
+ {
+ ScViewData* pViewData = GetViewData();
+ if ( !pViewData )
+ {
+ rReq.Ignore();
+ break;
+ }
+
+ ScShareDocumentDlg aDlg( GetActiveDialogParent(), pViewData );
+ if ( aDlg.Execute() == RET_OK )
+ {
+ bool bSetShared = aDlg.IsShareDocumentChecked();
+ if ( bSetShared != static_cast< bool >( IsDocShared() ) )
+ {
+ if ( bSetShared )
+ {
+ bool bContinue = true;
+ if ( HasName() )
+ {
+ QueryBox aBox( GetActiveDialogParent(), WinBits( WB_YES_NO | WB_DEF_YES ),
+ ScGlobal::GetRscString( STR_DOC_WILLBESAVED ) );
+ if ( aBox.Execute() == RET_NO )
+ {
+ bContinue = false;
+ }
+ }
+ if ( bContinue )
+ {
+ EnableSharedSettings( true );
+
+ SC_MOD()->SetInSharedDocSaving( true );
+ if ( !SwitchToShared( sal_True, sal_True ) )
+ {
+ // TODO/LATER: what should be done in case the switch has failed?
+ // for example in case the user has cancelled the saveAs operation
+ }
+
+ SC_MOD()->SetInSharedDocSaving( false );
+
+ InvalidateName();
+ GetUndoManager()->Clear();
+
+ ScTabView* pTabView = dynamic_cast< ScTabView* >( pViewData->GetView() );
+ if ( pTabView )
+ {
+ pTabView->UpdateLayerLocks();
+ }
+ }
+ }
+ else
+ {
+ uno::Reference< frame::XModel > xModel;
+ try
+ {
+ // load shared file
+ xModel.set( LoadSharedDocument(), uno::UNO_QUERY_THROW );
+ uno::Reference< util::XCloseable > xCloseable( xModel, uno::UNO_QUERY_THROW );
+
+ // check if shared flag is set in shared file
+ bool bShared = false;
+ ScModelObj* pDocObj = ScModelObj::getImplementation( xModel );
+ if ( pDocObj )
+ {
+ ScDocShell* pDocShell = dynamic_cast< ScDocShell* >( pDocObj->GetEmbeddedObject() );
+ if ( pDocShell )
+ {
+ bShared = pDocShell->HasSharedXMLFlagSet();
+ }
+ }
+
+ // #i87870# check if shared status was disabled and enabled again
+ bool bOwnEntry = false;
+ try
+ {
+ ::svt::ShareControlFile aControlFile( GetSharedFileURL() );
+ bOwnEntry = aControlFile.HasOwnEntry();
+ }
+ catch ( uno::Exception& )
+ {
+ }
+
+ if ( bShared && bOwnEntry )
+ {
+ uno::Reference< frame::XStorable > xStorable( xModel, uno::UNO_QUERY_THROW );
+ if ( xStorable->isReadonly() )
+ {
+ xCloseable->close( sal_True );
+
+ String aUserName( ScGlobal::GetRscString( STR_UNKNOWN_USER ) );
+ try
+ {
+ ::svt::DocumentLockFile aLockFile( GetSharedFileURL() );
+ uno::Sequence< ::rtl::OUString > aData = aLockFile.GetLockData();
+ if ( aData.getLength() > LOCKFILE_SYSUSERNAME_ID )
+ {
+ if ( aData[LOCKFILE_OOOUSERNAME_ID].getLength() > 0 )
+ {
+ aUserName = aData[LOCKFILE_OOOUSERNAME_ID];
+ }
+ else if ( aData[LOCKFILE_SYSUSERNAME_ID].getLength() > 0 )
+ {
+ aUserName = aData[LOCKFILE_SYSUSERNAME_ID];
+ }
+ }
+ }
+ catch ( uno::Exception& )
+ {
+ }
+ String aMessage( ScGlobal::GetRscString( STR_FILE_LOCKED_TRY_LATER ) );
+ aMessage.SearchAndReplaceAscii( "%1", aUserName );
+
+ WarningBox aBox( GetActiveDialogParent(), WinBits( WB_OK ), aMessage );
+ aBox.Execute();
+ }
+ else
+ {
+ WarningBox aBox( GetActiveDialogParent(), WinBits( WB_YES_NO | WB_DEF_YES ),
+ ScGlobal::GetRscString( STR_DOC_DISABLESHARED ) );
+ if ( aBox.Execute() == RET_YES )
+ {
+ xCloseable->close( sal_True );
+
+ if ( !SwitchToShared( sal_False, sal_True ) )
+ {
+ // TODO/LATER: what should be done in case the switch has failed?
+ // for example in case the user has cancelled the saveAs operation
+ }
+
+ EnableSharedSettings( false );
+
+ if ( pBindings )
+ {
+ pBindings->ExecuteSynchron( SID_SAVEDOC );
+ }
+
+ ScTabView* pTabView = dynamic_cast< ScTabView* >( pViewData->GetView() );
+ if ( pTabView )
+ {
+ pTabView->UpdateLayerLocks();
+ }
+ }
+ else
+ {
+ xCloseable->close( sal_True );
+ }
+ }
+ }
+ else
+ {
+ xCloseable->close( sal_True );
+ WarningBox aBox( GetActiveDialogParent(), WinBits( WB_OK ),
+ ScGlobal::GetRscString( STR_DOC_NOLONGERSHARED ) );
+ aBox.Execute();
+ }
+ }
+ catch ( uno::Exception& )
+ {
+ DBG_ERROR( "SID_SHARE_DOC: caught exception\n" );
+ SC_MOD()->SetInSharedDocSaving( false );
+
+ try
+ {
+ uno::Reference< util::XCloseable > xClose( xModel, uno::UNO_QUERY_THROW );
+ xClose->close( sal_True );
+ }
+ catch ( uno::Exception& )
+ {
+ }
+ }
+ }
+ }
+ }
+ rReq.Done();
+ }
+ break;
+
+ default:
+ {
+ // kleiner (?) Hack -> forward der Slots an TabViewShell
+ ScTabViewShell* pSh = GetBestViewShell();
+ if ( pSh )
+ pSh->Execute( rReq );
+ else
+ SbxBase::SetError( SbxERR_NO_ACTIVE_OBJECT );
+ }
+ }
+}
+
+
+//------------------------------------------------------------------
+
+BOOL ScDocShell::ExecuteChangeProtectionDialog( Window* _pParent, BOOL bJustQueryIfProtected )
+{
+ BOOL bDone = FALSE;
+ ScChangeTrack* pChangeTrack = aDocument.GetChangeTrack();
+ if ( pChangeTrack )
+ {
+ BOOL bProtected = pChangeTrack->IsProtected();
+ if ( bJustQueryIfProtected && !bProtected )
+ return TRUE;
+
+ String aTitle( ScResId( bProtected ? SCSTR_CHG_UNPROTECT : SCSTR_CHG_PROTECT ) );
+ String aText( ScResId( SCSTR_PASSWORD ) );
+ String aPassword;
+
+ SfxPasswordDialog* pDlg = new SfxPasswordDialog(
+ _pParent ? _pParent : GetActiveDialogParent(), &aText );
+ pDlg->SetText( aTitle );
+ pDlg->SetMinLen( 1 );
+ pDlg->SetHelpId( SID_CHG_PROTECT );
+ pDlg->SetEditHelpId( HID_CHG_PROTECT );
+ if ( !bProtected )
+ pDlg->ShowExtras( SHOWEXTRAS_CONFIRM );
+ if ( pDlg->Execute() == RET_OK )
+ aPassword = pDlg->GetPassword();
+ delete pDlg;
+
+ if ( aPassword.Len() )
+ {
+ if ( bProtected )
+ {
+ if ( SvPasswordHelper::CompareHashPassword(pChangeTrack->GetProtection(), aPassword) )
+ {
+ if ( bJustQueryIfProtected )
+ bDone = TRUE;
+ else
+ pChangeTrack->SetProtection(
+ com::sun::star::uno::Sequence< sal_Int8 > (0) );
+ }
+ else
+ {
+ InfoBox aBox( GetActiveDialogParent(),
+ String( ScResId( SCSTR_WRONGPASSWORD ) ) );
+ aBox.Execute();
+ }
+ }
+ else
+ {
+ com::sun::star::uno::Sequence< sal_Int8 > aPass;
+ SvPasswordHelper::GetHashPassword( aPass, aPassword );
+ pChangeTrack->SetProtection( aPass );
+ }
+ if ( bProtected != pChangeTrack->IsProtected() )
+ {
+ // update "accept changes" dialog
+ //! notify all views
+ SfxViewFrame* pViewFrm = SfxViewFrame::Current();
+ if ( pViewFrm && pViewFrm->HasChildWindow( FID_CHG_ACCEPT ) )
+ {
+ SfxChildWindow* pChild = pViewFrm->GetChildWindow( FID_CHG_ACCEPT );
+ if ( pChild )
+ ((ScAcceptChgDlgWrapper*)pChild)->ReInitDlg();
+ }
+ bDone = TRUE;
+ }
+ }
+ }
+ else if ( bJustQueryIfProtected )
+ bDone = TRUE;
+ return bDone;
+}
+
+
+//------------------------------------------------------------------
+
+void ScDocShell::DoRecalc( BOOL bApi )
+{
+ BOOL bDone = FALSE;
+ ScTabViewShell* pSh = GetBestViewShell();
+ if ( pSh )
+ {
+ ScInputHandler* pHdl = SC_MOD()->GetInputHdl(pSh);
+ if ( pHdl && pHdl->IsInputMode() && pHdl->IsFormulaMode() && !bApi )
+ {
+ pHdl->FormulaPreview(); // Teilergebnis als QuickHelp
+ bDone = TRUE;
+ }
+ else
+ {
+ pSh->UpdateInputLine(); // InputEnterHandler
+ pSh->UpdateInputHandler();
+ }
+ }
+ if (!bDone) // sonst Dokument neu berechnen
+ {
+ WaitObject aWaitObj( GetActiveDialogParent() );
+ aDocument.CalcFormulaTree();
+ if ( pSh )
+ pSh->UpdateCharts(TRUE);
+
+ aDocument.BroadcastUno( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
+
+ // #47939# Wenn es Charts gibt, dann alles painten, damit nicht
+ // PostDataChanged und die Charts nacheinander kommen und Teile
+ // doppelt gepainted werden.
+
+ ScChartListenerCollection* pCharts = aDocument.GetChartListenerCollection();
+ if ( pCharts && pCharts->GetCount() )
+ PostPaintGridAll();
+ else
+ PostDataChanged();
+ }
+}
+
+void ScDocShell::DoHardRecalc( BOOL /* bApi */ )
+{
+ WaitObject aWaitObj( GetActiveDialogParent() );
+ ScTabViewShell* pSh = GetBestViewShell();
+ if ( pSh )
+ {
+ pSh->UpdateInputLine(); // InputEnterHandler
+ pSh->UpdateInputHandler();
+ }
+ aDocument.CalcAll();
+ GetDocFunc().DetectiveRefresh(); // erzeugt eigenes Undo
+ if ( pSh )
+ pSh->UpdateCharts(TRUE);
+
+ // CalcAll doesn't broadcast value changes, so SC_HINT_CALCALL is broadcasted globally
+ // in addition to SFX_HINT_DATACHANGED.
+ aDocument.BroadcastUno( SfxSimpleHint( SC_HINT_CALCALL ) );
+ aDocument.BroadcastUno( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
+
+ // use hard recalc also to disable stream-copying of all sheets
+ // (somewhat consistent with charts)
+ SCTAB nTabCount = aDocument.GetTableCount();
+ for (SCTAB nTab=0; nTab<nTabCount; nTab++)
+ if (aDocument.IsStreamValid(nTab))
+ aDocument.SetStreamValid(nTab, FALSE);
+
+ PostPaintGridAll();
+}
+
+//------------------------------------------------------------------
+
+void ScDocShell::DoAutoStyle( const ScRange& rRange, const String& rStyle )
+{
+ ScStyleSheetPool* pStylePool = aDocument.GetStyleSheetPool();
+ ScStyleSheet* pStyleSheet =
+ pStylePool->FindCaseIns( rStyle, SFX_STYLE_FAMILY_PARA );
+ if (!pStyleSheet)
+ pStyleSheet = (ScStyleSheet*)
+ pStylePool->Find( ScGlobal::GetRscString(STR_STYLENAME_STANDARD), SFX_STYLE_FAMILY_PARA );
+ if (pStyleSheet)
+ {
+ DBG_ASSERT(rRange.aStart.Tab() == rRange.aEnd.Tab(),
+ "DoAutoStyle mit mehreren Tabellen");
+ SCTAB nTab = rRange.aStart.Tab();
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ aDocument.ApplyStyleAreaTab( nStartCol, nStartRow, nEndCol, nEndRow, nTab, *pStyleSheet );
+ aDocument.ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow, nTab );
+ PostPaint( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, PAINT_GRID );
+ }
+}
+
+//------------------------------------------------------------------
+
+void ScDocShell::NotifyStyle( const SfxStyleSheetHint& rHint )
+{
+ USHORT nId = rHint.GetHint();
+ const SfxStyleSheetBase* pStyle = rHint.GetStyleSheet();
+ if (!pStyle)
+ return;
+
+ if ( pStyle->GetFamily() == SFX_STYLE_FAMILY_PAGE )
+ {
+ if ( nId == SFX_STYLESHEET_MODIFIED )
+ {
+ ScDocShellModificator aModificator( *this );
+
+ String aNewName = pStyle->GetName();
+ String aOldName = aNewName;
+ BOOL bExtended = rHint.ISA(SfxStyleSheetHintExtended); // Name geaendert?
+ if (bExtended)
+ aOldName = ((SfxStyleSheetHintExtended&)rHint).GetOldName();
+
+ if ( aNewName != aOldName )
+ aDocument.RenamePageStyleInUse( aOldName, aNewName );
+
+ SCTAB nTabCount = aDocument.GetTableCount();
+ for (SCTAB nTab=0; nTab<nTabCount; nTab++)
+ if (aDocument.GetPageStyle(nTab) == aNewName) // schon auf neu angepasst
+ {
+ aDocument.PageStyleModified( nTab, aNewName );
+ ScPrintFunc aPrintFunc( this, GetPrinter(), nTab );
+ aPrintFunc.UpdatePages();
+ }
+
+ aModificator.SetDocumentModified();
+
+ if (bExtended)
+ {
+ SfxBindings* pBindings = GetViewBindings();
+ if (pBindings)
+ {
+ pBindings->Invalidate( SID_STATUS_PAGESTYLE );
+ pBindings->Invalidate( SID_STYLE_FAMILY4 );
+ pBindings->Invalidate( FID_RESET_PRINTZOOM );
+ pBindings->Invalidate( SID_ATTR_PARA_LEFT_TO_RIGHT );
+ pBindings->Invalidate( SID_ATTR_PARA_RIGHT_TO_LEFT );
+ }
+ }
+ }
+ }
+ else if ( pStyle->GetFamily() == SFX_STYLE_FAMILY_PARA )
+ {
+ if ( nId == SFX_STYLESHEET_MODIFIED)
+ {
+ String aNewName = pStyle->GetName();
+ String aOldName = aNewName;
+ BOOL bExtended = rHint.ISA(SfxStyleSheetHintExtended);
+ if (bExtended)
+ aOldName = ((SfxStyleSheetHintExtended&)rHint).GetOldName();
+ if ( aNewName != aOldName )
+ {
+ ScConditionalFormatList* pList = aDocument.GetCondFormList();
+ if (pList)
+ pList->RenameCellStyle( aOldName,aNewName );
+ }
+ }
+ }
+
+ // alles andere geht ueber Slots...
+}
+
+// wie in printfun.cxx
+#define ZOOM_MIN 10
+
+void ScDocShell::SetPrintZoom( SCTAB nTab, USHORT nScale, USHORT nPages )
+{
+ BOOL bUndo(aDocument.IsUndoEnabled());
+ String aStyleName = aDocument.GetPageStyle( nTab );
+ ScStyleSheetPool* pStylePool = aDocument.GetStyleSheetPool();
+ SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, SFX_STYLE_FAMILY_PAGE );
+ DBG_ASSERT( pStyleSheet, "PageStyle not found" );
+ if ( pStyleSheet )
+ {
+ ScDocShellModificator aModificator( *this );
+
+ SfxItemSet& rSet = pStyleSheet->GetItemSet();
+ if (bUndo)
+ {
+ USHORT nOldScale = ((const SfxUInt16Item&)rSet.Get(ATTR_PAGE_SCALE)).GetValue();
+ USHORT nOldPages = ((const SfxUInt16Item&)rSet.Get(ATTR_PAGE_SCALETOPAGES)).GetValue();
+ GetUndoManager()->AddUndoAction( new ScUndoPrintZoom(
+ this, nTab, nOldScale, nOldPages, nScale, nPages ) );
+ }
+
+ rSet.Put( SfxUInt16Item( ATTR_PAGE_SCALE, nScale ) );
+ rSet.Put( SfxUInt16Item( ATTR_PAGE_SCALETOPAGES, nPages ) );
+
+ ScPrintFunc aPrintFunc( this, GetPrinter(), nTab );
+ aPrintFunc.UpdatePages();
+ aModificator.SetDocumentModified();
+
+ SfxBindings* pBindings = GetViewBindings();
+ if (pBindings)
+ pBindings->Invalidate( FID_RESET_PRINTZOOM );
+ }
+}
+
+BOOL ScDocShell::AdjustPrintZoom( const ScRange& rRange )
+{
+ BOOL bChange = FALSE;
+ SCTAB nTab = rRange.aStart.Tab();
+
+ String aStyleName = aDocument.GetPageStyle( nTab );
+ ScStyleSheetPool* pStylePool = aDocument.GetStyleSheetPool();
+ SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, SFX_STYLE_FAMILY_PAGE );
+ DBG_ASSERT( pStyleSheet, "PageStyle not found" );
+ if ( pStyleSheet )
+ {
+ SfxItemSet& rSet = pStyleSheet->GetItemSet();
+ BOOL bHeaders = ((const SfxBoolItem&)rSet.Get(ATTR_PAGE_HEADERS)).GetValue();
+ USHORT nOldScale = ((const SfxUInt16Item&)rSet.Get(ATTR_PAGE_SCALE)).GetValue();
+ USHORT nOldPages = ((const SfxUInt16Item&)rSet.Get(ATTR_PAGE_SCALETOPAGES)).GetValue();
+ const ScRange* pRepeatCol = aDocument.GetRepeatColRange( nTab );
+ const ScRange* pRepeatRow = aDocument.GetRepeatRowRange( nTab );
+
+ // benoetigte Skalierung fuer Selektion ausrechnen
+
+ USHORT nNewScale = nOldScale;
+
+ long nBlkTwipsX = 0;
+ if (bHeaders)
+ nBlkTwipsX += (long) PRINT_HEADER_WIDTH;
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ if ( pRepeatCol && nStartCol >= pRepeatCol->aStart.Col() )
+ {
+ for (SCCOL i=pRepeatCol->aStart.Col(); i<=pRepeatCol->aEnd.Col(); i++ )
+ nBlkTwipsX += aDocument.GetColWidth( i, nTab );
+ if ( nStartCol <= pRepeatCol->aEnd.Col() )
+ nStartCol = pRepeatCol->aEnd.Col() + 1;
+ }
+ // legacy compilers' own scope for i
+ {
+ for ( SCCOL i=nStartCol; i<=nEndCol; i++ )
+ nBlkTwipsX += aDocument.GetColWidth( i, nTab );
+ }
+
+ long nBlkTwipsY = 0;
+ if (bHeaders)
+ nBlkTwipsY += (long) PRINT_HEADER_HEIGHT;
+ SCROW nStartRow = rRange.aStart.Row();
+ SCROW nEndRow = rRange.aEnd.Row();
+ if ( pRepeatRow && nStartRow >= pRepeatRow->aStart.Row() )
+ {
+ nBlkTwipsY += aDocument.FastGetRowHeight( pRepeatRow->aStart.Row(),
+ pRepeatRow->aEnd.Row(), nTab );
+ if ( nStartRow <= pRepeatRow->aEnd.Row() )
+ nStartRow = pRepeatRow->aEnd.Row() + 1;
+ }
+ nBlkTwipsY += aDocument.FastGetRowHeight( nStartRow, nEndRow, nTab );
+
+ Size aPhysPage;
+ long nHdr, nFtr;
+ ScPrintFunc aOldPrFunc( this, GetPrinter(), nTab );
+ aOldPrFunc.GetScaleData( aPhysPage, nHdr, nFtr );
+ nBlkTwipsY += nHdr + nFtr;
+
+ if ( nBlkTwipsX == 0 ) // #100639# hidden columns/rows may lead to 0
+ nBlkTwipsX = 1;
+ if ( nBlkTwipsY == 0 )
+ nBlkTwipsY = 1;
+
+ long nNeeded = Min( aPhysPage.Width() * 100 / nBlkTwipsX,
+ aPhysPage.Height() * 100 / nBlkTwipsY );
+ if ( nNeeded < ZOOM_MIN )
+ nNeeded = ZOOM_MIN; // Begrenzung
+ if ( nNeeded < (long) nNewScale )
+ nNewScale = (USHORT) nNeeded;
+
+ bChange = ( nNewScale != nOldScale || nOldPages != 0 );
+ if ( bChange )
+ SetPrintZoom( nTab, nNewScale, 0 );
+ }
+ return bChange;
+}
+
+void ScDocShell::PageStyleModified( const String& rStyleName, BOOL bApi )
+{
+ ScDocShellModificator aModificator( *this );
+
+ BOOL bWarn = FALSE;
+
+ SCTAB nTabCount = aDocument.GetTableCount();
+ SCTAB nUseTab = MAXTAB+1;
+ for (SCTAB nTab=0; nTab<nTabCount && nUseTab>MAXTAB; nTab++)
+ if ( aDocument.GetPageStyle(nTab) == rStyleName &&
+ ( !bApi || aDocument.GetPageSize(nTab).Width() ) )
+ nUseTab = nTab;
+ // bei bApi nur, wenn Umbrueche schon angezeigt
+
+ if (ValidTab(nUseTab)) // nicht verwendet -> nichts zu tun
+ {
+ ScPrintFunc aPrintFunc( this, GetPrinter(), nUseTab ); //! ohne CountPages auskommen
+ if (!aPrintFunc.UpdatePages()) // setzt Umbrueche auf allen Tabs
+ bWarn = TRUE;
+
+ if (bWarn && !bApi)
+ {
+ ScWaitCursorOff aWaitOff( GetActiveDialogParent() );
+ InfoBox aInfoBox(GetActiveDialogParent(),
+ ScGlobal::GetRscString(STR_PRINT_INVALID_AREA));
+ aInfoBox.Execute();
+ }
+ }
+
+ aModificator.SetDocumentModified();
+
+ SfxBindings* pBindings = GetViewBindings();
+ if (pBindings)
+ {
+ pBindings->Invalidate( FID_RESET_PRINTZOOM );
+ pBindings->Invalidate( SID_ATTR_PARA_LEFT_TO_RIGHT );
+ pBindings->Invalidate( SID_ATTR_PARA_RIGHT_TO_LEFT );
+ }
+}
+
+void ScDocShell::ExecutePageStyle( SfxViewShell& rCaller,
+ SfxRequest& rReq,
+ SCTAB nCurTab )
+{
+ const SfxItemSet* pReqArgs = rReq.GetArgs();
+
+ switch ( rReq.GetSlot() )
+ {
+ case SID_STATUS_PAGESTYLE: // Click auf StatusBar-Control
+ case SID_FORMATPAGE:
+ {
+ if ( pReqArgs != NULL )
+ {
+ }
+ else if ( pReqArgs == NULL )
+ {
+ BOOL bUndo(aDocument.IsUndoEnabled());
+ String aOldName = aDocument.GetPageStyle( nCurTab );
+ ScStyleSheetPool* pStylePool = aDocument.GetStyleSheetPool();
+ SfxStyleSheetBase* pStyleSheet
+ = pStylePool->Find( aOldName, SFX_STYLE_FAMILY_PAGE );
+
+ DBG_ASSERT( pStyleSheet, "PageStyle not found! :-/" );
+
+ if ( pStyleSheet )
+ {
+ ScStyleSaveData aOldData;
+ if (bUndo)
+ aOldData.InitFromStyle( pStyleSheet );
+
+ SfxItemSet& rStyleSet = pStyleSheet->GetItemSet();
+
+//CHINA001 ScStyleDlg* pDlg = new ScStyleDlg( GetActiveDialogParent(),
+//CHINA001 *pStyleSheet,
+//CHINA001 RID_SCDLG_STYLES_PAGE );
+//CHINA001
+ ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
+ DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001
+
+ SfxAbstractTabDialog* pDlg = pFact->CreateScStyleDlg( GetActiveDialogParent(), *pStyleSheet, RID_SCDLG_STYLES_PAGE, RID_SCDLG_STYLES_PAGE );
+ DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001
+
+ if ( pDlg->Execute() == RET_OK )
+ {
+ const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
+
+ WaitObject aWait( GetActiveDialogParent() );
+
+ String aNewName = pStyleSheet->GetName();
+ if ( aNewName != aOldName &&
+ aDocument.RenamePageStyleInUse( aOldName, aNewName ) )
+ {
+ SfxBindings* pBindings = GetViewBindings();
+ if (pBindings)
+ {
+ pBindings->Invalidate( SID_STATUS_PAGESTYLE );
+ pBindings->Invalidate( FID_RESET_PRINTZOOM );
+ }
+ }
+
+ if ( pOutSet )
+ aDocument.ModifyStyleSheet( *pStyleSheet, *pOutSet );
+
+ // merken fuer GetState():
+ GetPageOnFromPageStyleSet( &rStyleSet, nCurTab, bHeaderOn, bFooterOn );
+ rCaller.GetViewFrame()->GetBindings().Invalidate( SID_HFEDIT );
+
+ ScStyleSaveData aNewData;
+ aNewData.InitFromStyle( pStyleSheet );
+ if (bUndo)
+ {
+ GetUndoManager()->AddUndoAction(
+ new ScUndoModifyStyle( this, SFX_STYLE_FAMILY_PAGE,
+ aOldData, aNewData ) );
+ }
+
+ PageStyleModified( aNewName, FALSE );
+ rReq.Done();
+ }
+ delete pDlg;
+
+ rStyleSet.ClearItem( ATTR_PAGE_PAPERTRAY );
+ }
+ }
+ }
+ break;
+
+ case SID_HFEDIT:
+ {
+ if ( pReqArgs != NULL )
+ {
+ }
+ else if ( pReqArgs == NULL )
+ {
+ String aStr( aDocument.GetPageStyle( nCurTab ) );
+
+ ScStyleSheetPool* pStylePool
+ = aDocument.GetStyleSheetPool();
+
+ SfxStyleSheetBase* pStyleSheet
+ = pStylePool->Find( aStr, SFX_STYLE_FAMILY_PAGE );
+
+ DBG_ASSERT( pStyleSheet, "PageStyle not found! :-/" );
+
+ if ( pStyleSheet )
+ {
+ SfxItemSet& rStyleSet = pStyleSheet->GetItemSet();
+
+ SvxPageUsage eUsage =
+ SvxPageUsage( ((const SvxPageItem&)
+ rStyleSet.Get( ATTR_PAGE )).
+ GetPageUsage() );
+ BOOL bShareHeader = IS_SHARE_HEADER(rStyleSet);
+ BOOL bShareFooter = IS_SHARE_FOOTER(rStyleSet);
+ USHORT nResId = 0;
+
+ switch ( eUsage )
+ {
+ case SVX_PAGE_LEFT:
+ case SVX_PAGE_RIGHT:
+ {
+ if ( bHeaderOn && bFooterOn )
+ nResId = RID_SCDLG_HFEDIT;
+ else if ( SVX_PAGE_RIGHT == eUsage )
+ {
+ if ( !bHeaderOn && bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_RIGHTFOOTER;
+ else if ( bHeaderOn && !bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_RIGHTHEADER;
+ }
+ else
+ {
+ // #69193a# respect "shared" setting
+ if ( !bHeaderOn && bFooterOn )
+ nResId = bShareFooter ?
+ RID_SCDLG_HFEDIT_RIGHTFOOTER :
+ RID_SCDLG_HFEDIT_LEFTFOOTER;
+ else if ( bHeaderOn && !bFooterOn )
+ nResId = bShareHeader ?
+ RID_SCDLG_HFEDIT_RIGHTHEADER :
+ RID_SCDLG_HFEDIT_LEFTHEADER;
+ }
+ }
+ break;
+
+ case SVX_PAGE_MIRROR:
+ case SVX_PAGE_ALL:
+ default:
+ {
+ if ( !bShareHeader && !bShareFooter )
+ {
+ if ( bHeaderOn && bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_ALL;
+ else if ( !bHeaderOn && bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_FOOTER;
+ else if ( bHeaderOn && !bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_HEADER;
+ }
+ else if ( bShareHeader && bShareFooter )
+ {
+ if ( bHeaderOn && bFooterOn )
+ nResId = RID_SCDLG_HFEDIT;
+ else
+ {
+ if ( !bHeaderOn && bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_RIGHTFOOTER;
+ else if ( bHeaderOn && !bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_RIGHTHEADER;
+ }
+ }
+ else if ( !bShareHeader && bShareFooter )
+ {
+ if ( bHeaderOn && bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_SFTR;
+ else if ( !bHeaderOn && bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_RIGHTFOOTER;
+ else if ( bHeaderOn && !bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_HEADER;
+ }
+ else if ( bShareHeader && !bShareFooter )
+ {
+ if ( bHeaderOn && bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_SHDR;
+ else if ( !bHeaderOn && bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_FOOTER;
+ else if ( bHeaderOn && !bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_RIGHTHEADER;
+ }
+ }
+ }
+
+//CHINA001 ScHFEditDlg* pDlg
+//CHINA001 = new ScHFEditDlg( SFX_APP()->GetViewFrame(),
+//CHINA001 GetActiveDialogParent(),
+//CHINA001 rStyleSet,
+//CHINA001 aStr,
+//CHINA001 nResId );
+//CHINA001
+ ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
+ DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001
+
+ SfxAbstractTabDialog* pDlg = pFact->CreateScHFEditDlg( SfxViewFrame::Current(),
+ GetActiveDialogParent(),
+ rStyleSet,
+ aStr,
+ RID_SCDLG_HFEDIT, nResId);
+ DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001
+ if ( pDlg->Execute() == RET_OK )
+ {
+ const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
+
+ if ( pOutSet )
+ aDocument.ModifyStyleSheet( *pStyleSheet, *pOutSet );
+
+ SetDocumentModified();
+ rReq.Done();
+ }
+ delete pDlg;
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void ScDocShell::GetStatePageStyle( SfxViewShell& /* rCaller */,
+ SfxItemSet& rSet,
+ SCTAB nCurTab )
+{
+ SfxWhichIter aIter(rSet);
+ USHORT nWhich = aIter.FirstWhich();
+ while ( nWhich )
+ {
+ switch (nWhich)
+ {
+ case SID_STATUS_PAGESTYLE:
+ rSet.Put( SfxStringItem( nWhich, aDocument.GetPageStyle( nCurTab ) ) );
+ break;
+
+ case SID_HFEDIT:
+ {
+ String aStr = aDocument.GetPageStyle( nCurTab );
+ ScStyleSheetPool* pStylePool = aDocument.GetStyleSheetPool();
+ SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStr, SFX_STYLE_FAMILY_PAGE );
+
+ DBG_ASSERT( pStyleSheet, "PageStyle not found! :-/" );
+
+ if ( pStyleSheet )
+ {
+ SfxItemSet& rStyleSet = pStyleSheet->GetItemSet();
+
+ GetPageOnFromPageStyleSet( &rStyleSet, nCurTab, bHeaderOn, bFooterOn );
+
+ if ( !bHeaderOn && !bFooterOn )
+ rSet.DisableItem( nWhich );
+ }
+ }
+ break;
+ }
+
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void lcl_GetPrintData( ScDocShell* pDocShell /*in*/,
+ ScDocument* pDocument /*in*/, SfxPrinter* pPrinter /*in*/,
+ PrintDialog* pPrintDialog /*in*/, bool bForceSelected /*in*/,
+ ScMarkData* pMarkData /*inout*/, bool& rbHasOptions /*out*/,
+ ScPrintOptions& rOptions /*out*/, bool& rbAllTabs /*out*/,
+ long& rnTotalPages /*out*/, long aPageArr[] /*out*/,
+ MultiSelection& rPageRanges /*out*/, ScRange** ppMarkedRange /*out*/ )
+{
+ // get settings from print options sub-dialog
+ const SfxItemSet& rOptionSet = pPrinter->GetOptions();
+ const SfxPoolItem* pItem;
+ rbHasOptions = ( rOptionSet.GetItemState( SID_SCPRINTOPTIONS, FALSE, &pItem ) == SFX_ITEM_SET );
+ if ( rbHasOptions )
+ {
+ rOptions = ((const ScTpPrintItem*)pItem)->GetPrintOptions();
+ }
+ else
+ {
+ // use configuration
+ rOptions = SC_MOD()->GetPrintOptions();
+ }
+
+ // update all pending row heights with a single progress bar,
+ // instead of a separate progress for each sheet from ScPrintFunc
+ pDocShell->UpdatePendingRowHeights( MAXTAB, true );
+
+ // get number of total pages
+ rnTotalPages = 0;
+ SCTAB nTabCount = pDocument->GetTableCount();
+ for ( SCTAB nTab = 0; nTab < nTabCount; ++nTab )
+ {
+ ScPrintFunc aPrintFunc( pDocShell, pPrinter, nTab, 0, 0, NULL, &rOptions );
+ long nThisTab = aPrintFunc.GetTotalPages();
+ aPageArr[nTab] = nThisTab;
+ rnTotalPages += nThisTab;
+ }
+
+ rPageRanges.SetTotalRange( Range( 0, RANGE_MAX ) );
+ rPageRanges.Select( Range( 1, rnTotalPages ) );
+
+ rbAllTabs = ( pPrintDialog ? ( pPrintDialog->GetCheckedSheetRange() == PRINTSHEETS_ALL ) : SC_MOD()->GetPrintOptions().GetAllSheets() );
+ if ( bForceSelected )
+ {
+ rbAllTabs = false;
+ }
+
+ if ( ( pPrintDialog && pPrintDialog->GetCheckedSheetRange() == PRINTSHEETS_SELECTED_CELLS ) || bForceSelected )
+ {
+ if ( pMarkData && ( pMarkData->IsMarked() || pMarkData->IsMultiMarked() ) )
+ {
+ pMarkData->MarkToMulti();
+ *ppMarkedRange = new ScRange;
+ pMarkData->GetMultiMarkArea( **ppMarkedRange );
+ pMarkData->MarkToSimple();
+ }
+ }
+
+ PrintDialogRange eDlgOption = pPrintDialog ? pPrintDialog->GetCheckedRange() : PRINTDIALOG_ALL;
+ if ( eDlgOption == PRINTDIALOG_RANGE )
+ {
+ rPageRanges = MultiSelection( pPrintDialog->GetRangeText() );
+ }
+
+ // get number of total pages if selection
+ if ( !rbAllTabs )
+ {
+ rnTotalPages = 0;
+ for ( SCTAB nTab = 0; nTab < nTabCount; ++nTab )
+ {
+ if ( *ppMarkedRange ) // selected range is used instead of print ranges -> page count is different
+ {
+ ScPrintFunc aPrintFunc( pDocShell, pPrinter, nTab, 0, 0, *ppMarkedRange, &rOptions );
+ aPageArr[nTab] = aPrintFunc.GetTotalPages();
+ }
+ if ( !pMarkData || pMarkData->GetTableSelect( nTab ) )
+ {
+ rnTotalPages += aPageArr[nTab];
+ }
+ }
+ if ( eDlgOption == PRINTDIALOG_ALL || bForceSelected )
+ {
+ rPageRanges.Select( Range( 1, rnTotalPages ) );
+ }
+ }
+}
+
+bool ScDocShell::CheckPrint( PrintDialog* pPrintDialog, ScMarkData* pMarkData, bool bForceSelected, bool bIsAPI )
+{
+ SfxPrinter* pPrinter = GetPrinter();
+ if ( !pPrinter )
+ {
+ return false;
+ }
+
+ bool bHasOptions = false;
+ ScPrintOptions aOptions;
+ bool bAllTabs = true;
+ long nTotalPages = 0;
+ long aPageArr[MAXTABCOUNT]; // pages per sheet
+ MultiSelection aPageRanges; // pages to print
+ ScRange* pMarkedRange = NULL;
+
+ lcl_GetPrintData( this, &aDocument, pPrinter, pPrintDialog, bForceSelected,
+ pMarkData, bHasOptions, aOptions, bAllTabs, nTotalPages,
+ aPageArr, aPageRanges, &pMarkedRange );
+
+ delete pMarkedRange;
+
+ if ( nTotalPages == 0 )
+ {
+ if ( !bIsAPI )
+ {
+ WarningBox aWarningBox( GetActiveDialogParent(), WinBits( WB_OK ),
+ String( ScResId( STR_PRINT_NOTHING ) ) );
+ aWarningBox.Execute();
+ }
+ return false;
+ }
+
+ return true;
+}
+
+void ScDocShell::PreparePrint( PrintDialog* pPrintDialog, ScMarkData* pMarkData )
+{
+ SfxPrinter* pPrinter = GetPrinter();
+ if ( !pPrinter )
+ {
+ return;
+ }
+
+ delete pOldJobSetup; // gesetzt nur bei Fehler in StartJob()
+ pOldJobSetup = new ScJobSetup( pPrinter ); // Einstellungen merken
+
+ // Einstellungen fuer die erste gedruckte Seite muessen hier (vor StartJob) gesetzt werden
+ //! Selection etc. mit Print() zusammenfassen !!!
+ //! Seiten nur einmal zaehlen
+
+ bool bHasOptions = false;
+ ScPrintOptions aOptions;
+ bool bAllTabs = true;
+ long nTotalPages = 0;
+ long aPageArr[MAXTABCOUNT]; // pages per sheet
+ MultiSelection aPageRanges; // pages to print
+ ScRange* pMarkedRange = NULL;
+
+ lcl_GetPrintData( this, &aDocument, pPrinter, pPrintDialog, false,
+ pMarkData, bHasOptions, aOptions, bAllTabs, nTotalPages,
+ aPageArr, aPageRanges, &pMarkedRange );
+
+ BOOL bFound = FALSE; // erste Seite gefunden
+ long nTabStart = 0;
+ SCTAB nTabCount = aDocument.GetTableCount();
+ for ( SCTAB nTab=0; nTab<nTabCount && !bFound; nTab++ )
+ {
+ if ( bAllTabs || !pMarkData || pMarkData->GetTableSelect( nTab ) )
+ {
+ long nNext = nTabStart + aPageArr[nTab];
+ BOOL bSelected = FALSE;
+ for (long nP=nTabStart+1; nP<=nNext; nP++) // 1-basiert
+ if (aPageRanges.IsSelected( nP )) // eine Seite von dieser Tabelle selektiert?
+ bSelected = TRUE;
+
+ if (bSelected)
+ {
+ ScPrintFunc aPrintFunc( this, pPrinter, nTab );
+
+ aPrintFunc.ApplyPrintSettings(); // dann Settings fuer diese Tabelle
+ bFound = TRUE;
+ }
+ nTabStart = nNext;
+ }
+ }
+
+ delete pMarkedRange;
+}
+
+BOOL lcl_HasTransparent( ScDocument* pDoc, SCTAB nTab, const ScRange* pRange )
+{
+ BOOL bFound = FALSE;
+ ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
+ if (pDrawLayer)
+ {
+ SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
+ DBG_ASSERT(pPage,"Page ?");
+ if (pPage)
+ {
+ Rectangle aMMRect;
+ if ( pRange )
+ aMMRect = pDoc->GetMMRect( pRange->aStart.Col(), pRange->aStart.Row(),
+ pRange->aEnd.Col(), pRange->aEnd.Row(), nTab );
+
+ SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
+ SdrObject* pObject = aIter.Next();
+ while (pObject && !bFound)
+ {
+ if (pObject->IsTransparent())
+ {
+ if ( pRange )
+ {
+ Rectangle aObjRect = pObject->GetLogicRect();
+ if ( aObjRect.IsOver( aMMRect ) )
+ bFound = TRUE;
+ }
+ else
+ bFound = TRUE;
+ }
+
+ pObject = aIter.Next();
+ }
+ }
+ }
+
+ return bFound;
+}
+
+void ScDocShell::Print( SfxProgress& rProgress, PrintDialog* pPrintDialog,
+ ScMarkData* pMarkData, Window* pDialogParent, BOOL bForceSelected, BOOL bIsAPI )
+{
+ SfxPrinter* pPrinter = GetPrinter();
+ if ( !pPrinter )
+ {
+ return;
+ }
+
+ bool bHasOptions = false;
+ ScPrintOptions aOptions;
+ bool bAllTabs = true;
+ long nTotalPages = 0;
+ long aPageArr[MAXTABCOUNT]; // pages per sheet
+ MultiSelection aPageRanges; // pages to print
+ ScRange* pMarkedRange = NULL;
+
+ lcl_GetPrintData( this, &aDocument, pPrinter, pPrintDialog, bForceSelected,
+ pMarkData, bHasOptions, aOptions, bAllTabs, nTotalPages,
+ aPageArr, aPageRanges, &pMarkedRange );
+
+ USHORT nCollateCopies = 1;
+ if ( pPrintDialog && pPrintDialog->IsCollateEnabled() && pPrintDialog->IsCollateChecked() )
+ nCollateCopies = pPrintDialog->GetCopyCount();
+
+ // test if printed range contains transparent objects
+
+ BOOL bHasTransp = FALSE;
+ BOOL bAnyPrintRanges = aDocument.HasPrintRange();
+ ScStyleSheetPool* pStylePool = aDocument.GetStyleSheetPool();
+ SCTAB nTabCount = aDocument.GetTableCount();
+ for ( SCTAB nTab=0; nTab<nTabCount && !bHasTransp; nTab++ )
+ {
+ if ( bAllTabs || !pMarkData || pMarkData->GetTableSelect( nTab ) )
+ {
+ SfxStyleSheetBase* pStyleSheet = pStylePool->Find(
+ aDocument.GetPageStyle( nTab ), SFX_STYLE_FAMILY_PAGE );
+ if ( pStyleSheet )
+ {
+ const SfxItemSet& rSet = pStyleSheet->GetItemSet();
+ if ( ((const ScViewObjectModeItem&)rSet.Get(ATTR_PAGE_CHARTS)).GetValue() == VOBJ_MODE_SHOW ||
+ ((const ScViewObjectModeItem&)rSet.Get(ATTR_PAGE_OBJECTS)).GetValue() == VOBJ_MODE_SHOW ||
+ ((const ScViewObjectModeItem&)rSet.Get(ATTR_PAGE_DRAWINGS)).GetValue() == VOBJ_MODE_SHOW )
+ {
+ if ( pMarkedRange )
+ bHasTransp = bHasTransp || lcl_HasTransparent( &aDocument, nTab, pMarkedRange );
+ else if ( aDocument.GetPrintRangeCount(nTab) )
+ {
+ USHORT nRangeCount = aDocument.GetPrintRangeCount(nTab);
+ for (USHORT i=0; i<nRangeCount; i++)
+ bHasTransp = bHasTransp ||
+ lcl_HasTransparent( &aDocument, nTab, aDocument.GetPrintRange( nTab, i ) );
+ }
+ else if (!bAnyPrintRanges || aDocument.IsPrintEntireSheet(nTab))
+ bHasTransp = bHasTransp || lcl_HasTransparent( &aDocument, nTab, NULL );
+ }
+ }
+ }
+ }
+
+ BOOL bContinue = pPrinter->InitJob( pDialogParent, !bIsAPI && bHasTransp );
+
+ if ( bContinue )
+ {
+ for ( USHORT n=0; n<nCollateCopies; n++ )
+ {
+ long nTabStart = 0;
+ long nDisplayStart = 0;
+ long nAttrPage = 1;
+ long nPrinted = 0;
+
+ for ( SCTAB nTab=0; nTab<nTabCount; nTab++ )
+ {
+ if ( bAllTabs || !pMarkData || pMarkData->GetTableSelect( nTab ) )
+ {
+ FmFormView* pDrawView = NULL;
+ Rectangle aFull( 0, 0, LONG_MAX, LONG_MAX );
+
+ // #114135#
+ ScDrawLayer* pModel = aDocument.GetDrawLayer(); // ist nicht NULL
+
+ if(pModel)
+ {
+ pDrawView = new FmFormView( pModel, pPrinter );
+ pDrawView->ShowSdrPage(pDrawView->GetModel()->GetPage(nTab));
+ pDrawView->SetPrintPreview( TRUE );
+ }
+
+ ScPrintFunc aPrintFunc( this, pPrinter, nTab, nAttrPage, nTotalPages, pMarkedRange, &aOptions );
+ aPrintFunc.SetDrawView( pDrawView );
+ nPrinted += aPrintFunc.DoPrint( aPageRanges, nTabStart, nDisplayStart, TRUE, &rProgress, NULL );
+
+ nTabStart += aPageArr[nTab];
+ if ( aDocument.NeedPageResetAfterTab(nTab) )
+ nDisplayStart = 0;
+ else
+ nDisplayStart += aPageArr[nTab];
+ nAttrPage = aPrintFunc.GetFirstPageNo(); // behalten oder aus Vorlage
+
+ delete pDrawView;
+ }
+ }
+
+ if ( n+1 < nCollateCopies &&
+ (pPrinter->GetDuplexMode() == DUPLEX_SHORTEDGE || pPrinter->GetDuplexMode() == DUPLEX_LONGEDGE) &&
+ ( nPrinted % 2 ) == 1 )
+ {
+ // #105584# when several collated copies are printed in duplex mode, and there is
+ // an odd number of pages, print an empty page between copies, so the first page of
+ // the second copy isn't printed on the back of the last page of the first copy.
+ // (same as in Writer ViewShell::Prt)
+
+ // FIXME: needs to be adapted to XRenderable interface
+ #if 0
+ pPrinter->StartPage();
+ pPrinter->EndPage();
+ #endif
+ }
+ }
+ }
+
+ delete pMarkedRange;
+
+ if (pOldJobSetup)
+ {
+ pPrinter->SetOrientation( pOldJobSetup->eOrientation );
+ pPrinter->SetPaperBin ( pOldJobSetup->nPaperBin );
+ pPrinter->SetPaper ( pOldJobSetup->ePaper );
+
+ if ( PAPER_USER == pOldJobSetup->ePaper )
+ {
+ pPrinter->SetMapMode( pOldJobSetup->aUserMapMode );
+ pPrinter->SetPaperSizeUser( pOldJobSetup->aUserSize );
+ }
+
+ delete pOldJobSetup;
+ pOldJobSetup = NULL;
+ }
+
+ if ( bHasOptions )
+ {
+ // remove PrintOptions from printer ItemSet,
+ // so next time the options from the configuration are used
+
+ SfxItemSet aSet( pPrinter->GetOptions() );
+ aSet.ClearItem( SID_SCPRINTOPTIONS );
+ pPrinter->SetOptions( aSet );
+ }
+
+ PostPaintGridAll(); //! nur wenn geaendert
+}
+
+void ScDocShell::GetState( SfxItemSet &rSet )
+{
+ SfxWhichIter aIter(rSet);
+ USHORT nWhich = aIter.FirstWhich();
+ while ( nWhich )
+ {
+ switch (nWhich)
+ {
+ case FID_AUTO_CALC:
+ if ( (BOOL) aDocument.GetHardRecalcState() )
+ rSet.DisableItem( nWhich );
+ else
+ rSet.Put( SfxBoolItem( nWhich, aDocument.GetAutoCalc() ) );
+ break;
+
+ case FID_CHG_RECORD:
+ if ( IsDocShared() )
+ rSet.DisableItem( nWhich );
+ else
+ rSet.Put( SfxBoolItem( nWhich,
+ aDocument.GetChangeTrack() != NULL ) );
+ break;
+
+ case SID_CHG_PROTECT:
+ {
+ ScChangeTrack* pChangeTrack = aDocument.GetChangeTrack();
+ if ( pChangeTrack && !IsDocShared() )
+ rSet.Put( SfxBoolItem( nWhich,
+ pChangeTrack->IsProtected() ) );
+ else
+ rSet.DisableItem( nWhich );
+ }
+ break;
+
+ case SID_DOCUMENT_COMPARE:
+ {
+ if ( IsDocShared() )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ }
+ break;
+
+ // Wenn eine Formel editiert wird, muss FID_RECALC auf jeden Fall enabled sein.
+ // Recalc fuer das Doc war mal wegen #29898# disabled, wenn AutoCalc an war,
+ // ist jetzt wegen #41540# aber auch immer enabled.
+// case FID_RECALC:
+// if ( aDocument.GetAutoCalc() )
+// rSet.DisableItem( nWhich );
+// break;
+
+ case SID_TABLES_COUNT:
+ rSet.Put( SfxInt16Item( nWhich, aDocument.GetTableCount() ) );
+ break;
+
+ case SID_ATTR_YEAR2000 :
+ rSet.Put( SfxUInt16Item( nWhich,
+ aDocument.GetDocOptions().GetYear2000() ) );
+ break;
+
+ case SID_SHARE_DOC:
+ {
+ if ( IsReadOnly() )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ }
+ break;
+
+ default:
+ {
+ }
+ break;
+ }
+
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void ScDocShell::GetSbxState( SfxItemSet &rSet )
+{
+ // SID_SC_SELECTION (Selection),
+ // SID_SC_ACTIVECELL (ActiveCell),
+ // SID_SC_ACTIVETAB (ActiveTable),
+ // SID_TABLES_GET (Tables),
+ // SID_PIVOT_GET (DataPilotTables) - removed (old Basic)
+
+ //
+ // Wenn hier Slots von der View-Shell executed werden, muss auch der
+ // GetState weitergeleitet werden!
+ //
+
+ ScTabViewShell* pVisibleSh = GetBestViewShell(); // sichtbare View
+ if ( pVisibleSh )
+ pVisibleSh->GetState( rSet );
+}
+
+void __EXPORT ScDocShell::Draw( OutputDevice* pDev, const JobSetup & /* rSetup */, USHORT nAspect )
+{
+// bIsOle = TRUE; // jetzt ueber den CreateMode
+
+ SCTAB nVisTab = aDocument.GetVisibleTab();
+ if (!aDocument.HasTable(nVisTab))
+ return;
+
+ ULONG nOldLayoutMode = pDev->GetLayoutMode();
+ pDev->SetLayoutMode( TEXT_LAYOUT_DEFAULT ); // even if it's the same, to get the metafile action
+
+ if ( nAspect == ASPECT_THUMBNAIL )
+ {
+ Rectangle aBoundRect = GetVisArea( ASPECT_THUMBNAIL );
+ ScViewData aTmpData( this, NULL );
+ aTmpData.SetTabNo(nVisTab);
+ aDocument.SnapVisArea( aBoundRect );
+ aTmpData.SetScreen( aBoundRect );
+ ScPrintFunc::DrawToDev( &aDocument, pDev, 1.0, aBoundRect, &aTmpData, TRUE );
+ }
+ else
+ {
+ Rectangle aBoundRect = SfxObjectShell::GetVisArea();
+ ScViewData aTmpData( this, NULL );
+ aTmpData.SetTabNo(nVisTab);
+ aDocument.SnapVisArea( aBoundRect );
+ aTmpData.SetScreen( aBoundRect );
+ ScPrintFunc::DrawToDev( &aDocument, pDev, 1.0, aBoundRect, &aTmpData, TRUE );
+ }
+
+ pDev->SetLayoutMode( nOldLayoutMode );
+}
+
+Rectangle __EXPORT ScDocShell::GetVisArea( USHORT nAspect ) const
+{
+ SfxObjectCreateMode eShellMode = GetCreateMode();
+ if ( eShellMode == SFX_CREATE_MODE_ORGANIZER )
+ {
+ // ohne Inhalte wissen wir auch nicht, wie gross die Inhalte sind
+ // leeres Rechteck zurueckgeben, das wird dann nach dem Laden berechnet
+ return Rectangle();
+ }
+
+ if( nAspect == ASPECT_THUMBNAIL )
+ {
+// Rectangle aArea( 0,0, 3175,3175 ); // 120x120 Pixel in 1:1
+ Rectangle aArea( 0,0, SC_PREVIEW_SIZE_X,SC_PREVIEW_SIZE_Y );
+ BOOL bNegativePage = aDocument.IsNegativePage( aDocument.GetVisibleTab() );
+ if ( bNegativePage )
+ ScDrawLayer::MirrorRectRTL( aArea );
+ aDocument.SnapVisArea( aArea );
+ return aArea;
+ }
+ else if( nAspect == ASPECT_CONTENT && eShellMode != SFX_CREATE_MODE_EMBEDDED )
+ {
+ // Visarea holen wie nach Load
+
+ SCTAB nVisTab = aDocument.GetVisibleTab();
+ if (!aDocument.HasTable(nVisTab))
+ {
+ nVisTab = 0;
+ ((ScDocShell*)this)->aDocument.SetVisibleTab(nVisTab);
+ }
+ SCCOL nStartCol;
+ SCROW nStartRow;
+ aDocument.GetDataStart( nVisTab, nStartCol, nStartRow );
+ SCCOL nEndCol;
+ SCROW nEndRow;
+ aDocument.GetPrintArea( nVisTab, nEndCol, nEndRow );
+ if (nStartCol>nEndCol)
+ nStartCol = nEndCol;
+ if (nStartRow>nEndRow)
+ nStartRow = nEndRow;
+ Rectangle aNewArea = ((ScDocument&)aDocument)
+ .GetMMRect( nStartCol,nStartRow, nEndCol,nEndRow, nVisTab );
+ //TODO/LATER: different methods for setting VisArea?!
+ ((ScDocShell*)this)->SfxObjectShell::SetVisArea( aNewArea );
+ return aNewArea;
+ }
+ else
+ return SfxObjectShell::GetVisArea( nAspect );
+}
+
+void ScDocShell::GetPageOnFromPageStyleSet( const SfxItemSet* pStyleSet,
+ SCTAB nCurTab,
+ BOOL& rbHeader,
+ BOOL& rbFooter )
+{
+ if ( !pStyleSet )
+ {
+ ScStyleSheetPool* pStylePool = aDocument.GetStyleSheetPool();
+ SfxStyleSheetBase* pStyleSheet = pStylePool->
+ Find( aDocument.GetPageStyle( nCurTab ),
+ SFX_STYLE_FAMILY_PAGE );
+
+ DBG_ASSERT( pStyleSheet, "PageStyle not found! :-/" );
+
+ if ( pStyleSheet )
+ pStyleSet = &pStyleSheet->GetItemSet();
+ else
+ rbHeader = rbFooter = FALSE;
+ }
+
+ DBG_ASSERT( pStyleSet, "PageStyle-Set not found! :-(" );
+
+ //--------------------------------------------------------------------
+
+ const SvxSetItem* pSetItem = NULL;
+ const SfxItemSet* pSet = NULL;
+
+ pSetItem = (const SvxSetItem*) &pStyleSet->Get( ATTR_PAGE_HEADERSET );
+ pSet = &pSetItem->GetItemSet();
+ rbHeader = ((const SfxBoolItem&)pSet->Get(ATTR_PAGE_ON)).GetValue();
+
+ pSetItem = (const SvxSetItem*) &pStyleSet->Get( ATTR_PAGE_FOOTERSET );
+ pSet = &pSetItem->GetItemSet();
+ rbFooter = ((const SfxBoolItem&)pSet->Get(ATTR_PAGE_ON)).GetValue();
+}
+
+long __EXPORT ScDocShell::DdeGetData( const String& rItem,
+ const String& rMimeType,
+ ::com::sun::star::uno::Any & rValue )
+{
+ if( FORMAT_STRING == SotExchange::GetFormatIdFromMimeType( rMimeType ) )
+ {
+ if( rItem.EqualsIgnoreCaseAscii( "Format" ) )
+ {
+ ByteString aFmtByte( aDdeTextFmt, gsl_getSystemTextEncoding() );
+ rValue <<= ::com::sun::star::uno::Sequence< sal_Int8 >(
+ (sal_Int8*)aFmtByte.GetBuffer(),
+ aFmtByte.Len() + 1 );
+ return 1;
+ }
+ ScImportExport aObj( &aDocument, rItem );
+ if ( !aObj.IsRef() )
+ return 0; // ungueltiger Bereich
+
+ if( aDdeTextFmt.GetChar(0) == 'F' )
+ aObj.SetFormulas( TRUE );
+ if( aDdeTextFmt.EqualsAscii( "SYLK" ) ||
+ aDdeTextFmt.EqualsAscii( "FSYLK" ) )
+ {
+ ByteString aData;
+ if( aObj.ExportByteString( aData, gsl_getSystemTextEncoding(),
+ SOT_FORMATSTR_ID_SYLK ) )
+ {
+ rValue <<= ::com::sun::star::uno::Sequence< sal_Int8 >(
+ (sal_Int8*)aData.GetBuffer(),
+ aData.Len() + 1 );
+ return 1;
+ }
+ else
+ return 0;
+ }
+ if( aDdeTextFmt.EqualsAscii( "CSV" ) ||
+ aDdeTextFmt.EqualsAscii( "FCSV" ) )
+ aObj.SetSeparator( ',' );
+ aObj.SetExportTextOptions( ScExportTextOptions( ScExportTextOptions::ToSpace, 0, false ) );
+ return aObj.ExportData( rMimeType, rValue ) ? 1 : 0;
+ }
+
+ ScImportExport aObj( &aDocument, rItem );
+ aObj.SetExportTextOptions( ScExportTextOptions( ScExportTextOptions::ToSpace, 0, false ) );
+ if( aObj.IsRef() )
+ return aObj.ExportData( rMimeType, rValue ) ? 1 : 0;
+ return 0;
+}
+
+long __EXPORT ScDocShell::DdeSetData( const String& rItem,
+ const String& rMimeType,
+ const ::com::sun::star::uno::Any & rValue )
+{
+ if( FORMAT_STRING == SotExchange::GetFormatIdFromMimeType( rMimeType ))
+ {
+ if( rItem.EqualsIgnoreCaseAscii( "Format" ) )
+ {
+ if ( ScByteSequenceToString::GetString( aDdeTextFmt, rValue, gsl_getSystemTextEncoding() ) )
+ {
+ aDdeTextFmt.ToUpperAscii();
+ return 1;
+ }
+ return 0;
+ }
+ ScImportExport aObj( &aDocument, rItem );
+ if( aDdeTextFmt.GetChar(0) == 'F' )
+ aObj.SetFormulas( TRUE );
+ if( aDdeTextFmt.EqualsAscii( "SYLK" ) ||
+ aDdeTextFmt.EqualsAscii( "FSYLK" ) )
+ {
+ String aData;
+ if ( ScByteSequenceToString::GetString( aData, rValue, gsl_getSystemTextEncoding() ) )
+ {
+ return aObj.ImportString( aData, SOT_FORMATSTR_ID_SYLK ) ? 1 : 0;
+ }
+ return 0;
+ }
+ if( aDdeTextFmt.EqualsAscii( "CSV" ) ||
+ aDdeTextFmt.EqualsAscii( "FCSV" ) )
+ aObj.SetSeparator( ',' );
+ return aObj.ImportData( rMimeType, rValue ) ? 1 : 0;
+ }
+ ScImportExport aObj( &aDocument, rItem );
+ if( aObj.IsRef() )
+ return aObj.ImportData( rMimeType, rValue ) ? 1 : 0;
+ return 0;
+}
+
+::sfx2::SvLinkSource* __EXPORT ScDocShell::DdeCreateLinkSource( const String& rItem )
+{
+ // only check for valid item string - range is parsed again in ScServerObject ctor
+
+ // named range?
+ String aPos = rItem;
+ ScRangeName* pRange = aDocument.GetRangeName();
+ if( pRange )
+ {
+ USHORT nPos;
+ if( pRange->SearchName( aPos, nPos ) )
+ {
+ ScRangeData* pData = (*pRange)[ nPos ];
+ if( pData->HasType( RT_REFAREA )
+ || pData->HasType( RT_ABSAREA )
+ || pData->HasType( RT_ABSPOS ) )
+ pData->GetSymbol( aPos ); // continue with the name's contents
+ }
+ }
+
+ // Address in DDE function must be always parsed as CONV_OOO so that it
+ // would always work regardless of current address convension. We do this
+ // because the address item in a DDE entry is *not* normalized when saved
+ // into ODF.
+ ScRange aRange;
+ bool bValid = ( (aRange.Parse(aPos, &aDocument, formula::FormulaGrammar::CONV_OOO ) & SCA_VALID) ||
+ (aRange.aStart.Parse(aPos, &aDocument, formula::FormulaGrammar::CONV_OOO) & SCA_VALID) );
+
+ ScServerObject* pObj = NULL; // NULL = error
+ if ( bValid )
+ pObj = new ScServerObject( this, rItem );
+
+ // GetLinkManager()->InsertServer() is in the ScServerObject ctor
+
+ return pObj;
+}
+
+//------------------------------------------------------------------
+
+ScViewData* ScDocShell::GetViewData()
+{
+ SfxViewShell* pCur = SfxViewShell::Current();
+ ScTabViewShell* pViewSh = PTR_CAST(ScTabViewShell,pCur);
+ return pViewSh ? pViewSh->GetViewData() : NULL;
+}
+
+//------------------------------------------------------------------
+
+SCTAB ScDocShell::GetCurTab()
+{
+ //! this must be made non-static and use a ViewShell from this document!
+
+ ScViewData* pViewData = GetViewData();
+
+ return pViewData ? pViewData->GetTabNo() : static_cast<SCTAB>(0);
+}
+
+ScTabViewShell* ScDocShell::GetBestViewShell( BOOL bOnlyVisible )
+{
+ ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
+ // falsches Doc?
+ if( pViewSh && pViewSh->GetViewData()->GetDocShell() != this )
+ pViewSh = NULL;
+ if( !pViewSh )
+ {
+ // 1. ViewShell suchen
+ SfxViewFrame* pFrame = SfxViewFrame::GetFirst( this, TYPE(SfxTopViewFrame), bOnlyVisible );
+ if( pFrame )
+ {
+ SfxViewShell* p = pFrame->GetViewShell();
+ pViewSh = PTR_CAST(ScTabViewShell,p);
+ }
+ }
+ return pViewSh;
+}
+
+SfxBindings* ScDocShell::GetViewBindings()
+{
+ // used to invalidate slots after changes to this document
+
+ SfxViewShell* pViewSh = GetBestViewShell();
+ if (pViewSh)
+ return &pViewSh->GetViewFrame()->GetBindings();
+ else
+ return NULL;
+}
+
+//------------------------------------------------------------------
+
+ScDocShell* ScDocShell::GetShellByNum( USHORT nDocNo ) // static
+{
+ ScDocShell* pFound = NULL;
+ SfxObjectShell* pShell = SfxObjectShell::GetFirst();
+ USHORT nShellCnt = 0;
+
+ while ( pShell && !pFound )
+ {
+ if ( pShell->Type() == TYPE(ScDocShell) )
+ {
+ if ( nShellCnt == nDocNo )
+ pFound = (ScDocShell*) pShell;
+ else
+ ++nShellCnt;
+ }
+ pShell = SfxObjectShell::GetNext( *pShell );
+ }
+
+ return pFound;
+}
+
+//------------------------------------------------------------------
+
+IMPL_LINK( ScDocShell, DialogClosedHdl, sfx2::FileDialogHelper*, _pFileDlg )
+{
+ DBG_ASSERT( _pFileDlg, "ScDocShell::DialogClosedHdl(): no file dialog" );
+ DBG_ASSERT( pImpl->pDocInserter, "ScDocShell::DialogClosedHdl(): no document inserter" );
+
+ if ( ERRCODE_NONE == _pFileDlg->GetError() )
+ {
+ USHORT nSlot = pImpl->pRequest->GetSlot();
+ SfxMedium* pMed = pImpl->pDocInserter->CreateMedium();
+ // #i87094# If a .odt was selected pMed is NULL.
+ if (pMed)
+ {
+ pImpl->pRequest->AppendItem( SfxStringItem( SID_FILE_NAME, pMed->GetName() ) );
+ if ( SID_DOCUMENT_COMPARE == nSlot )
+ {
+ if ( pMed->GetFilter() )
+ pImpl->pRequest->AppendItem(
+ SfxStringItem( SID_FILTER_NAME, pMed->GetFilter()->GetFilterName() ) );
+ String sOptions = ScDocumentLoader::GetOptions( *pMed );
+ if ( sOptions.Len() > 0 )
+ pImpl->pRequest->AppendItem( SfxStringItem( SID_FILE_FILTEROPTIONS, sOptions ) );
+ }
+ const SfxPoolItem* pItem = NULL;
+ SfxItemSet* pSet = pMed->GetItemSet();
+ if ( pSet &&
+ pSet->GetItemState( SID_VERSION, TRUE, &pItem ) == SFX_ITEM_SET &&
+ pItem->ISA( SfxInt16Item ) )
+ {
+ pImpl->pRequest->AppendItem( *pItem );
+ }
+
+ Execute( *(pImpl->pRequest) );
+ }
+ }
+
+ pImpl->bIgnoreLostRedliningWarning = false;
+ return 0;
+}
+
+//------------------------------------------------------------------
+
+void ScDocShell::EnableSharedSettings( bool bEnable )
+{
+ SetDocumentModified();
+
+ if ( bEnable )
+ {
+ aDocument.EndChangeTracking();
+ aDocument.StartChangeTracking();
+
+ // hide accept or reject changes dialog
+ USHORT nId = ScAcceptChgDlgWrapper::GetChildWindowId();
+ SfxViewFrame* pViewFrame = SfxViewFrame::Current();
+ if ( pViewFrame && pViewFrame->HasChildWindow( nId ) )
+ {
+ pViewFrame->ToggleChildWindow( nId );
+ SfxBindings* pBindings = GetViewBindings();
+ if ( pBindings )
+ {
+ pBindings->Invalidate( FID_CHG_ACCEPT );
+ }
+ }
+ }
+ else
+ {
+ aDocument.EndChangeTracking();
+ }
+
+ ScChangeViewSettings aChangeViewSet;
+ aChangeViewSet.SetShowChanges( FALSE );
+ aDocument.SetChangeViewSettings( aChangeViewSet );
+}
+
+uno::Reference< frame::XModel > ScDocShell::LoadSharedDocument()
+{
+ uno::Reference< frame::XModel > xModel;
+ try
+ {
+ SC_MOD()->SetInSharedDocLoading( true );
+ uno::Reference< lang::XMultiServiceFactory > xFactory(
+ ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW );
+ uno::Reference< frame::XComponentLoader > xLoader(
+ xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ) ) ),
+ uno::UNO_QUERY_THROW );
+ uno::Sequence < beans::PropertyValue > aArgs( 1 );
+ aArgs[0].Name = ::rtl::OUString::createFromAscii( "Hidden" );
+ aArgs[0].Value <<= sal_True;
+
+ if ( GetMedium() )
+ {
+ SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pPasswordItem, SfxStringItem, SID_PASSWORD, sal_False);
+ if ( pPasswordItem && pPasswordItem->GetValue().Len() )
+ {
+ aArgs.realloc( 2 );
+ aArgs[1].Name = ::rtl::OUString::createFromAscii( "Password" );
+ aArgs[1].Value <<= ::rtl::OUString( pPasswordItem->GetValue() );
+ }
+ }
+
+ xModel.set(
+ xLoader->loadComponentFromURL( GetSharedFileURL(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_blank" ) ), 0, aArgs ),
+ uno::UNO_QUERY_THROW );
+ SC_MOD()->SetInSharedDocLoading( false );
+ }
+ catch ( uno::Exception& )
+ {
+ DBG_ERROR( "ScDocShell::LoadSharedDocument(): caught exception\n" );
+ SC_MOD()->SetInSharedDocLoading( false );
+ try
+ {
+ uno::Reference< util::XCloseable > xClose( xModel, uno::UNO_QUERY_THROW );
+ xClose->close( sal_True );
+ return uno::Reference< frame::XModel >();
+ }
+ catch ( uno::Exception& )
+ {
+ return uno::Reference< frame::XModel >();
+ }
+ }
+ return xModel;
+}
diff --git a/sc/source/ui/docshell/docsh5.cxx b/sc/source/ui/docshell/docsh5.cxx
new file mode 100644
index 000000000000..6fa6a5ac7863
--- /dev/null
+++ b/sc/source/ui/docshell/docsh5.cxx
@@ -0,0 +1,938 @@
+/*************************************************************************
+ *
+ * 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"
+
+// System - Includes -----------------------------------------------------
+
+
+
+
+#include "scitems.hxx"
+#include <vcl/svapp.hxx>
+#include <vcl/msgbox.hxx>
+#include <vcl/waitobj.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/bindings.hxx>
+#include <svl/smplhint.hxx>
+
+#include <com/sun/star/sdbc/XResultSet.hpp>
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "docsh.hxx"
+#include "global.hxx"
+#include "globstr.hrc"
+#include "undodat.hxx"
+#include "undotab.hxx"
+#include "undoblk.hxx"
+//#include "pivot.hxx"
+#include "dpobject.hxx"
+#include "dpshttab.hxx"
+#include "dbdocfun.hxx"
+#include "consoli.hxx"
+#include "dbcolect.hxx"
+#include "olinetab.hxx"
+#include "patattr.hxx"
+#include "attrib.hxx"
+#include "docpool.hxx"
+#include "uiitems.hxx"
+#include "sc.hrc"
+#include "waitoff.hxx"
+#include "sizedev.hxx"
+
+// ---------------------------------------------------------------------------
+
+//
+// ehemalige viewfunc/dbfunc Methoden
+//
+
+void ScDocShell::ErrorMessage( USHORT nGlobStrId )
+{
+ //! StopMarking an der (aktiven) View?
+
+ Window* pParent = GetActiveDialogParent();
+ ScWaitCursorOff aWaitOff( pParent );
+ BOOL bFocus = pParent && pParent->HasFocus();
+
+ if(nGlobStrId==STR_PROTECTIONERR)
+ {
+ if(IsReadOnly())
+ {
+ nGlobStrId=STR_READONLYERR;
+ }
+ }
+
+ InfoBox aBox( pParent, ScGlobal::GetRscString( nGlobStrId ) );
+ aBox.Execute();
+ if (bFocus)
+ pParent->GrabFocus();
+}
+
+BOOL ScDocShell::IsEditable() const
+{
+ // import into read-only document is possible - must be extended if other filters use api
+
+ return !IsReadOnly() || aDocument.IsImportingXML();
+}
+
+void ScDocShell::DBAreaDeleted( SCTAB nTab, SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW /* nY2 */ )
+{
+ ScDocShellModificator aModificator( *this );
+ aDocument.RemoveFlagsTab( nX1, nY1, nX2, nY1, nTab, SC_MF_AUTO );
+ PostPaint( nX1, nY1, nTab, nX2, nY1, nTab, PAINT_GRID );
+ // No SetDocumentModified, as the unnamed database range might have to be restored later.
+ // The UNO hint is broadcast directly instead, to keep UNO objects in valid state.
+ aDocument.BroadcastUno( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
+}
+
+ScDBData* lcl_GetDBNearCursor( ScDBCollection* pColl, SCCOL nCol, SCROW nRow, SCTAB nTab )
+{
+ //! nach document/dbcolect verschieben
+
+ if (!pColl)
+ return NULL;
+
+ ScDBData* pNoNameData = NULL;
+ ScDBData* pNearData = NULL;
+ USHORT nCount = pColl->GetCount();
+ String aNoName = ScGlobal::GetRscString( STR_DB_NONAME );
+ SCTAB nAreaTab;
+ SCCOL nStartCol, nEndCol;
+ SCROW nStartRow, nEndRow;
+ for (USHORT i = 0; i < nCount; i++)
+ {
+ ScDBData* pDB = (*pColl)[i];
+ pDB->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow );
+ if ( nTab == nAreaTab && nCol+1 >= nStartCol && nCol <= nEndCol+1 &&
+ nRow+1 >= nStartRow && nRow <= nEndRow+1 )
+ {
+ if ( pDB->GetName() == aNoName )
+ pNoNameData = pDB;
+ else if ( nCol < nStartCol || nCol > nEndCol || nRow < nStartRow || nRow > nEndRow )
+ {
+ if (!pNearData)
+ pNearData = pDB; // ersten angrenzenden Bereich merken
+ }
+ else
+ return pDB; // nicht "unbenannt" und Cursor steht wirklich drin
+ }
+ }
+ if (pNearData)
+ return pNearData; // angrenzender, wenn nichts direkt getroffen
+ return pNoNameData; // "unbenannt" nur zurueck, wenn sonst nichts gefunden
+}
+
+ScDBData* ScDocShell::GetDBData( const ScRange& rMarked, ScGetDBMode eMode, BOOL bForceMark )
+{
+ SCCOL nCol = rMarked.aStart.Col();
+ SCROW nRow = rMarked.aStart.Row();
+ SCTAB nTab = rMarked.aStart.Tab();
+
+ SCCOL nStartCol = nCol;
+ SCROW nStartRow = nRow;
+ SCTAB nStartTab = nTab;
+ SCCOL nEndCol = rMarked.aEnd.Col();
+ SCROW nEndRow = rMarked.aEnd.Row();
+ SCTAB nEndTab = rMarked.aEnd.Tab();
+
+ // Wegen #49655# nicht einfach GetDBAtCursor: Der zusammenhaengende Datenbereich
+ // fuer "unbenannt" (GetDataArea) kann neben dem Cursor legen, also muss auch ein
+ // benannter DB-Bereich dort gesucht werden.
+
+ ScDBData* pData = aDocument.GetDBAtArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow );
+ if (!pData)
+ pData = lcl_GetDBNearCursor( aDocument.GetDBCollection(), nCol, nRow, nTab );
+
+ BOOL bSelected = ( bForceMark || rMarked.aStart != rMarked.aEnd );
+
+ BOOL bUseThis = FALSE;
+ if (pData)
+ {
+ // Bereich nehmen, wenn nichts anderes markiert
+
+ SCTAB nDummy;
+ SCCOL nOldCol1;
+ SCROW nOldRow1;
+ SCCOL nOldCol2;
+ SCROW nOldRow2;
+ pData->GetArea( nDummy, nOldCol1,nOldRow1, nOldCol2,nOldRow2 );
+ BOOL bIsNoName = ( pData->GetName() == ScGlobal::GetRscString( STR_DB_NONAME ) );
+
+ if (!bSelected)
+ {
+ bUseThis = TRUE;
+ if ( bIsNoName && eMode == SC_DB_MAKE )
+ {
+ // wenn nichts markiert, "unbenannt" auf zusammenhaengenden Bereich anpassen
+ nStartCol = nCol;
+ nStartRow = nRow;
+ nEndCol = nStartCol;
+ nEndRow = nStartRow;
+ aDocument.GetDataArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow, FALSE );
+ if ( nOldCol1 != nStartCol || nOldCol2 != nEndCol || nOldRow1 != nStartRow )
+ bUseThis = FALSE; // passt gar nicht
+ else if ( nOldRow2 != nEndRow )
+ {
+ // Bereich auf neue End-Zeile erweitern
+ pData->SetArea( nTab, nOldCol1,nOldRow1, nOldCol2,nEndRow );
+ }
+ }
+ }
+ else
+ {
+ if ( nOldCol1 == nStartCol && nOldRow1 == nStartRow &&
+ nOldCol2 == nEndCol && nOldRow2 == nEndRow ) // genau markiert?
+ bUseThis = TRUE;
+ else
+ bUseThis = FALSE; // immer Markierung nehmen (Bug 11964)
+ }
+
+ // fuer Import nie "unbenannt" nehmen
+
+ if ( bUseThis && eMode == SC_DB_IMPORT && bIsNoName )
+ bUseThis = FALSE;
+ }
+
+ if ( bUseThis )
+ {
+ pData->GetArea( nStartTab, nStartCol,nStartRow, nEndCol,nEndRow );
+ nEndTab = nStartTab;
+ }
+ else if ( eMode == SC_DB_OLD )
+ {
+ pData = NULL; // nichts gefunden
+ nStartCol = nEndCol = nCol;
+ nStartRow = nEndRow = nRow;
+ nStartTab = nEndTab = nTab;
+// bMark = FALSE; // nichts zu markieren
+ }
+ else
+ {
+ if ( bSelected )
+ {
+// bMark = FALSE;
+ }
+ else
+ { // zusammenhaengender Bereich
+ nStartCol = nCol;
+ nStartRow = nRow;
+ nEndCol = nStartCol;
+ nEndRow = nStartRow;
+ aDocument.GetDataArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow, FALSE );
+ }
+
+ BOOL bHasHeader = aDocument.HasColHeader( nStartCol,nStartRow, nEndCol,nEndRow, nTab );
+
+ ScDBData* pNoNameData;
+ USHORT nNoNameIndex;
+ ScDBCollection* pColl = aDocument.GetDBCollection();
+ if ( eMode != SC_DB_IMPORT &&
+ pColl->SearchName( ScGlobal::GetRscString( STR_DB_NONAME ), nNoNameIndex ) )
+ {
+ pNoNameData = (*pColl)[nNoNameIndex];
+
+ if ( !pOldAutoDBRange )
+ {
+ // store the old unnamed database range with its settings for undo
+ // (store at the first change, get the state before all changes)
+ pOldAutoDBRange = new ScDBData( *pNoNameData );
+ }
+
+ SCCOL nOldX1; // alten Bereich sauber wegnehmen
+ SCROW nOldY1; //! (UNDO ???)
+ SCCOL nOldX2;
+ SCROW nOldY2;
+ SCTAB nOldTab;
+ pNoNameData->GetArea( nOldTab, nOldX1, nOldY1, nOldX2, nOldY2 );
+ DBAreaDeleted( nOldTab, nOldX1, nOldY1, nOldX2, nOldY2 );
+
+ pNoNameData->SetSortParam( ScSortParam() ); // Parameter zuruecksetzen
+ pNoNameData->SetQueryParam( ScQueryParam() );
+ pNoNameData->SetSubTotalParam( ScSubTotalParam() );
+
+ pNoNameData->SetArea( nTab, nStartCol,nStartRow, nEndCol,nEndRow ); // neu setzen
+ pNoNameData->SetByRow( TRUE );
+ pNoNameData->SetHeader( bHasHeader );
+ pNoNameData->SetAutoFilter( FALSE );
+ }
+ else
+ {
+ ScDBCollection* pUndoColl = NULL;
+
+ String aNewName;
+ if (eMode==SC_DB_IMPORT)
+ {
+ aDocument.CompileDBFormula( TRUE ); // CreateFormulaString
+ pUndoColl = new ScDBCollection( *pColl ); // Undo fuer Import1-Bereich
+
+ String aImport = ScGlobal::GetRscString( STR_DBNAME_IMPORT );
+ long nCount = 0;
+ USHORT nDummy;
+ do
+ {
+ ++nCount;
+ aNewName = aImport;
+ aNewName += String::CreateFromInt32( nCount );
+ }
+ while (pColl->SearchName( aNewName, nDummy ));
+ }
+ else
+ aNewName = ScGlobal::GetRscString( STR_DB_NONAME );
+ pNoNameData = new ScDBData( aNewName, nTab,
+ nStartCol,nStartRow, nEndCol,nEndRow,
+ TRUE, bHasHeader );
+ pColl->Insert( pNoNameData );
+
+ if ( pUndoColl )
+ {
+ aDocument.CompileDBFormula( FALSE ); // CompileFormulaString
+
+ ScDBCollection* pRedoColl = new ScDBCollection( *pColl );
+ GetUndoManager()->AddUndoAction( new ScUndoDBData( this, pUndoColl, pRedoColl ) );
+ }
+
+ // neuen Bereich am Sba anmelden nicht mehr noetig
+
+ // "Import1" etc am Navigator bekanntmachen
+ if (eMode==SC_DB_IMPORT)
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
+ }
+ pData = pNoNameData;
+ }
+
+// if (bMark)
+// MarkRange( ScRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab ), FALSE );
+
+ return pData;
+}
+
+ScDBData* ScDocShell::GetOldAutoDBRange()
+{
+ ScDBData* pRet = pOldAutoDBRange;
+ pOldAutoDBRange = NULL;
+ return pRet; // has to be deleted by caller!
+}
+
+void ScDocShell::CancelAutoDBRange()
+{
+ // called when dialog is cancelled
+ if ( pOldAutoDBRange )
+ {
+ USHORT nNoNameIndex;
+ ScDBCollection* pColl = aDocument.GetDBCollection();
+ if ( pColl->SearchName( ScGlobal::GetRscString( STR_DB_NONAME ), nNoNameIndex ) )
+ {
+ ScDBData* pNoNameData = (*pColl)[nNoNameIndex];
+
+ SCCOL nRangeX1;
+ SCROW nRangeY1;
+ SCCOL nRangeX2;
+ SCROW nRangeY2;
+ SCTAB nRangeTab;
+ pNoNameData->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 );
+ DBAreaDeleted( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 );
+
+ *pNoNameData = *pOldAutoDBRange; // restore old settings
+
+ if ( pOldAutoDBRange->HasAutoFilter() )
+ {
+ // restore AutoFilter buttons
+ pOldAutoDBRange->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 );
+ aDocument.ApplyFlagsTab( nRangeX1, nRangeY1, nRangeX2, nRangeY1, nRangeTab, SC_MF_AUTO );
+ PostPaint( nRangeX1, nRangeY1, nRangeTab, nRangeX2, nRangeY1, nRangeTab, PAINT_GRID );
+ }
+ }
+
+ delete pOldAutoDBRange;
+ pOldAutoDBRange = NULL;
+ }
+}
+
+
+ // Hoehen anpassen
+ //! mit docfunc zusammenfassen
+
+BOOL ScDocShell::AdjustRowHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab )
+{
+ ScSizeDeviceProvider aProv(this);
+ Fraction aZoom(1,1);
+ BOOL bChange = aDocument.SetOptimalHeight( nStartRow,nEndRow, nTab, 0, aProv.GetDevice(),
+ aProv.GetPPTX(),aProv.GetPPTY(), aZoom,aZoom, FALSE );
+ if (bChange)
+ PostPaint( 0,nStartRow,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID|PAINT_LEFT );
+
+ return bChange;
+}
+
+void ScDocShell::UpdateAllRowHeights( const ScMarkData* pTabMark )
+{
+ // update automatic row heights
+
+ ScSizeDeviceProvider aProv(this);
+ Fraction aZoom(1,1);
+ aDocument.UpdateAllRowHeights( aProv.GetDevice(), aProv.GetPPTX(), aProv.GetPPTY(), aZoom, aZoom, pTabMark );
+}
+
+void ScDocShell::UpdatePendingRowHeights( SCTAB nUpdateTab, bool bBefore )
+{
+ BOOL bIsUndoEnabled = aDocument.IsUndoEnabled();
+ aDocument.EnableUndo( FALSE );
+ aDocument.LockStreamValid( true ); // ignore draw page size (but not formula results)
+ if ( bBefore ) // check all sheets up to nUpdateTab
+ {
+ SCTAB nTabCount = aDocument.GetTableCount();
+ if ( nUpdateTab >= nTabCount )
+ nUpdateTab = nTabCount-1; // nUpdateTab is inclusive
+
+ ScMarkData aUpdateSheets;
+ SCTAB nTab;
+ for (nTab=0; nTab<=nUpdateTab; ++nTab)
+ if ( aDocument.IsPendingRowHeights( nTab ) )
+ aUpdateSheets.SelectTable( nTab, TRUE );
+
+ if (aUpdateSheets.GetSelectCount())
+ UpdateAllRowHeights(&aUpdateSheets); // update with a single progress bar
+
+ for (nTab=0; nTab<=nUpdateTab; ++nTab)
+ if ( aUpdateSheets.GetTableSelect( nTab ) )
+ {
+ aDocument.UpdatePageBreaks( nTab );
+ aDocument.SetPendingRowHeights( nTab, FALSE );
+ }
+ }
+ else // only nUpdateTab
+ {
+ if ( aDocument.IsPendingRowHeights( nUpdateTab ) )
+ {
+ AdjustRowHeight( 0, MAXROW, nUpdateTab );
+ aDocument.UpdatePageBreaks( nUpdateTab );
+ aDocument.SetPendingRowHeights( nUpdateTab, FALSE );
+ }
+ }
+ aDocument.LockStreamValid( false );
+ aDocument.EnableUndo( bIsUndoEnabled );
+}
+
+void ScDocShell::RefreshPivotTables( const ScRange& rSource )
+{
+ //! rename to RefreshDataPilotTables?
+
+ ScDPCollection* pColl = aDocument.GetDPCollection();
+ if ( pColl )
+ {
+ // DataPilotUpdate doesn't modify the collection order like PivotUpdate did,
+ // so a simple loop can be used.
+
+ USHORT nCount = pColl->GetCount();
+ for ( USHORT i=0; i<nCount; i++ )
+ {
+ ScDPObject* pOld = (*pColl)[i];
+ if ( pOld )
+ {
+ const ScSheetSourceDesc* pSheetDesc = pOld->GetSheetDesc();
+ if ( pSheetDesc && pSheetDesc->aSourceRange.Intersects( rSource ) )
+ {
+ ScDPObject* pNew = new ScDPObject( *pOld );
+ ScDBDocFunc aFunc( *this );
+ aFunc.DataPilotUpdate( pOld, pNew, TRUE, FALSE );
+ delete pNew; // DataPilotUpdate copies settings from "new" object
+ }
+ }
+ }
+ }
+}
+
+String lcl_GetAreaName( ScDocument* pDoc, ScArea* pArea )
+{
+ String aName;
+ BOOL bOk = FALSE;
+ ScDBData* pData = pDoc->GetDBAtArea( pArea->nTab, pArea->nColStart, pArea->nRowStart,
+ pArea->nColEnd, pArea->nRowEnd );
+ if (pData)
+ {
+ pData->GetName( aName );
+ if ( aName != ScGlobal::GetRscString( STR_DB_NONAME ) )
+ bOk = TRUE;
+ }
+
+ if (!bOk)
+ pDoc->GetName( pArea->nTab, aName );
+
+ return aName;
+}
+
+void ScDocShell::DoConsolidate( const ScConsolidateParam& rParam, BOOL bRecord )
+{
+ ScConsData aData;
+
+ USHORT nPos;
+ SCCOL nColSize = 0;
+ SCROW nRowSize = 0;
+ BOOL bErr = FALSE;
+ for (nPos=0; nPos<rParam.nDataAreaCount; nPos++)
+ {
+ ScArea* pArea = rParam.ppDataAreas[nPos];
+ nColSize = Max( nColSize, SCCOL( pArea->nColEnd - pArea->nColStart + 1 ) );
+ nRowSize = Max( nRowSize, SCROW( pArea->nRowEnd - pArea->nRowStart + 1 ) );
+
+ // Test, ob Quelldaten verschoben wuerden
+ if (rParam.bReferenceData)
+ if (pArea->nTab == rParam.nTab && pArea->nRowEnd >= rParam.nRow)
+ bErr = TRUE;
+ }
+
+ if (bErr)
+ {
+ InfoBox aBox( GetActiveDialogParent(),
+ ScGlobal::GetRscString( STR_CONSOLIDATE_ERR1 ) );
+ aBox.Execute();
+ return;
+ }
+
+ // ausfuehren
+
+ WaitObject aWait( GetActiveDialogParent() );
+ ScDocShellModificator aModificator( *this );
+
+ ScRange aOldDest;
+ ScDBData* pDestData = aDocument.GetDBAtCursor( rParam.nCol, rParam.nRow, rParam.nTab, TRUE );
+ if (pDestData)
+ pDestData->GetArea(aOldDest);
+
+ aData.SetSize( nColSize, nRowSize );
+ aData.SetFlags( rParam.eFunction, rParam.bByCol, rParam.bByRow, rParam.bReferenceData );
+ if ( rParam.bByCol || rParam.bByRow )
+ for (nPos=0; nPos<rParam.nDataAreaCount; nPos++)
+ {
+ ScArea* pArea = rParam.ppDataAreas[nPos];
+ aData.AddFields( &aDocument, pArea->nTab, pArea->nColStart, pArea->nRowStart,
+ pArea->nColEnd, pArea->nRowEnd );
+ }
+ aData.DoneFields();
+ for (nPos=0; nPos<rParam.nDataAreaCount; nPos++)
+ {
+ ScArea* pArea = rParam.ppDataAreas[nPos];
+ aData.AddData( &aDocument, pArea->nTab, pArea->nColStart, pArea->nRowStart,
+ pArea->nColEnd, pArea->nRowEnd );
+ aData.AddName( lcl_GetAreaName(&aDocument,pArea) );
+ }
+
+ aData.GetSize( nColSize, nRowSize );
+ if (bRecord && nColSize > 0 && nRowSize > 0)
+ {
+ ScDBData* pUndoData = pDestData ? new ScDBData(*pDestData) : NULL;
+
+ SCTAB nDestTab = rParam.nTab;
+ ScArea aDestArea( rParam.nTab, rParam.nCol, rParam.nRow,
+ rParam.nCol+nColSize-1, rParam.nRow+nRowSize-1 );
+ if (rParam.bByCol) ++aDestArea.nColEnd;
+ if (rParam.bByRow) ++aDestArea.nRowEnd;
+
+ if (rParam.bReferenceData)
+ {
+ SCTAB nTabCount = aDocument.GetTableCount();
+ SCROW nInsertCount = aData.GetInsertCount();
+
+ // alte Outlines
+ ScOutlineTable* pTable = aDocument.GetOutlineTable( nDestTab );
+ ScOutlineTable* pUndoTab = pTable ? new ScOutlineTable( *pTable ) : NULL;
+
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( &aDocument, 0, nTabCount-1, FALSE, TRUE );
+
+ // Zeilenstatus
+ aDocument.CopyToDocument( 0,0,nDestTab, MAXCOL,MAXROW,nDestTab,
+ IDF_NONE, FALSE, pUndoDoc );
+
+ // alle Formeln
+ aDocument.CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1,
+ IDF_FORMULA, FALSE, pUndoDoc );
+
+ // komplette Ausgangszeilen
+ aDocument.CopyToDocument( 0,aDestArea.nRowStart,nDestTab,
+ MAXCOL,aDestArea.nRowEnd,nDestTab,
+ IDF_ALL, FALSE, pUndoDoc );
+
+ // alten Ausgabebereich
+ if (pDestData)
+ aDocument.CopyToDocument( aOldDest, IDF_ALL, FALSE, pUndoDoc );
+
+ GetUndoManager()->AddUndoAction(
+ new ScUndoConsolidate( this, aDestArea, rParam, pUndoDoc,
+ TRUE, nInsertCount, pUndoTab, pUndoData ) );
+ }
+ else
+ {
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( &aDocument, aDestArea.nTab, aDestArea.nTab );
+
+ aDocument.CopyToDocument( aDestArea.nColStart, aDestArea.nRowStart, aDestArea.nTab,
+ aDestArea.nColEnd, aDestArea.nRowEnd, aDestArea.nTab,
+ IDF_ALL, FALSE, pUndoDoc );
+
+ // alten Ausgabebereich
+ if (pDestData)
+ aDocument.CopyToDocument( aOldDest, IDF_ALL, FALSE, pUndoDoc );
+
+ GetUndoManager()->AddUndoAction(
+ new ScUndoConsolidate( this, aDestArea, rParam, pUndoDoc,
+ FALSE, 0, NULL, pUndoData ) );
+ }
+ }
+
+ if (pDestData) // Zielbereich loeschen / anpassen
+ {
+ aDocument.DeleteAreaTab(aOldDest, IDF_CONTENTS);
+ pDestData->SetArea( rParam.nTab, rParam.nCol, rParam.nRow,
+ rParam.nCol + nColSize - 1, rParam.nRow + nRowSize - 1 );
+ pDestData->SetHeader( rParam.bByRow );
+ }
+
+ aData.OutputToDocument( &aDocument, rParam.nCol, rParam.nRow, rParam.nTab );
+
+ SCCOL nPaintStartCol = rParam.nCol;
+ SCROW nPaintStartRow = rParam.nRow;
+ SCCOL nPaintEndCol = nPaintStartCol + nColSize - 1;
+ SCROW nPaintEndRow = nPaintStartRow + nRowSize - 1;
+ USHORT nPaintFlags = PAINT_GRID;
+ if (rParam.bByCol)
+ ++nPaintEndRow;
+ if (rParam.bByRow)
+ ++nPaintEndCol;
+ if (rParam.bReferenceData)
+ {
+ nPaintStartCol = 0;
+ nPaintEndCol = MAXCOL;
+ nPaintEndRow = MAXROW;
+ nPaintFlags |= PAINT_LEFT | PAINT_SIZE;
+ }
+ if (pDestData)
+ {
+ if ( aOldDest.aEnd.Col() > nPaintEndCol )
+ nPaintEndCol = aOldDest.aEnd.Col();
+ if ( aOldDest.aEnd.Row() > nPaintEndRow )
+ nPaintEndRow = aOldDest.aEnd.Row();
+ }
+ PostPaint( nPaintStartCol, nPaintStartRow, rParam.nTab,
+ nPaintEndCol, nPaintEndRow, rParam.nTab, nPaintFlags );
+ aModificator.SetDocumentModified();
+}
+
+void ScDocShell::UseScenario( SCTAB nTab, const String& rName, BOOL bRecord )
+{
+ if (!aDocument.IsScenario(nTab))
+ {
+ SCTAB nTabCount = aDocument.GetTableCount();
+ SCTAB nSrcTab = SCTAB_MAX;
+ SCTAB nEndTab = nTab;
+ String aCompare;
+ while ( nEndTab+1 < nTabCount && aDocument.IsScenario(nEndTab+1) )
+ {
+ ++nEndTab;
+ if (nSrcTab > MAXTAB) // noch auf der Suche nach dem Szenario?
+ {
+ aDocument.GetName( nEndTab, aCompare );
+ if (aCompare == rName)
+ nSrcTab = nEndTab; // gefunden
+ }
+ }
+ if (ValidTab(nSrcTab))
+ {
+ if ( aDocument.TestCopyScenario( nSrcTab, nTab ) ) // Zellschutz testen
+ {
+ ScDocShellModificator aModificator( *this );
+ ScMarkData aScenMark;
+ aDocument.MarkScenario( nSrcTab, nTab, aScenMark );
+ ScRange aMultiRange;
+ aScenMark.GetMultiMarkArea( aMultiRange );
+ SCCOL nStartCol = aMultiRange.aStart.Col();
+ SCROW nStartRow = aMultiRange.aStart.Row();
+ SCCOL nEndCol = aMultiRange.aEnd.Col();
+ SCROW nEndRow = aMultiRange.aEnd.Row();
+
+ if (bRecord)
+ {
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( &aDocument, nTab,nEndTab ); // auch alle Szenarien
+ // angezeigte Tabelle:
+ aDocument.CopyToDocument( nStartCol,nStartRow,nTab,
+ nEndCol,nEndRow,nTab, IDF_ALL,TRUE, pUndoDoc, &aScenMark );
+ // Szenarien
+ for (SCTAB i=nTab+1; i<=nEndTab; i++)
+ {
+ pUndoDoc->SetScenario( i, TRUE );
+ String aComment;
+ Color aColor;
+ USHORT nScenFlags;
+ aDocument.GetScenarioData( i, aComment, aColor, nScenFlags );
+ pUndoDoc->SetScenarioData( i, aComment, aColor, nScenFlags );
+ BOOL bActive = aDocument.IsActiveScenario( i );
+ pUndoDoc->SetActiveScenario( i, bActive );
+ // Bei Zurueckkopier-Szenarios auch Inhalte
+ if ( nScenFlags & SC_SCENARIO_TWOWAY )
+ aDocument.CopyToDocument( 0,0,i, MAXCOL,MAXROW,i,
+ IDF_ALL,FALSE, pUndoDoc );
+ }
+
+ GetUndoManager()->AddUndoAction(
+ new ScUndoUseScenario( this, aScenMark,
+ ScArea( nTab,nStartCol,nStartRow,nEndCol,nEndRow ),
+ pUndoDoc, rName ) );
+ }
+
+ aDocument.CopyScenario( nSrcTab, nTab );
+ aDocument.SetDirty();
+
+ // alles painten, weil in anderen Bereichen das aktive Szenario
+ // geaendert sein kann
+ //! nur, wenn sichtbare Rahmen vorhanden?
+ PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID );
+ aModificator.SetDocumentModified();
+ }
+ else
+ {
+ InfoBox aBox(GetActiveDialogParent(),
+ ScGlobal::GetRscString( STR_PROTECTIONERR ) );
+ aBox.Execute();
+ }
+ }
+ else
+ {
+ InfoBox aBox(GetActiveDialogParent(),
+ ScGlobal::GetRscString( STR_SCENARIO_NOTFOUND ) );
+ aBox.Execute();
+ }
+ }
+ else
+ {
+ DBG_ERROR( "UseScenario auf Szenario-Blatt" );
+ }
+}
+
+void ScDocShell::ModifyScenario( SCTAB nTab, const String& rName, const String& rComment,
+ const Color& rColor, USHORT nFlags )
+{
+ // Undo
+ String aOldName;
+ aDocument.GetName( nTab, aOldName );
+ String aOldComment;
+ Color aOldColor;
+ USHORT nOldFlags;
+ aDocument.GetScenarioData( nTab, aOldComment, aOldColor, nOldFlags );
+ GetUndoManager()->AddUndoAction(
+ new ScUndoScenarioFlags( this, nTab,
+ aOldName, rName, aOldComment, rComment,
+ aOldColor, rColor, nOldFlags, nFlags ) );
+
+ // ausfuehren
+ ScDocShellModificator aModificator( *this );
+ aDocument.RenameTab( nTab, rName );
+ aDocument.SetScenarioData( nTab, rComment, rColor, nFlags );
+ PostPaintGridAll();
+ aModificator.SetDocumentModified();
+
+ if ( rName != aOldName )
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
+
+ SfxBindings* pBindings = GetViewBindings();
+ if (pBindings)
+ pBindings->Invalidate( SID_SELECT_SCENARIO );
+}
+
+SCTAB ScDocShell::MakeScenario( SCTAB nTab, const String& rName, const String& rComment,
+ const Color& rColor, USHORT nFlags,
+ ScMarkData& rMark, BOOL bRecord )
+{
+ rMark.MarkToMulti();
+ if (rMark.IsMultiMarked())
+ {
+ SCTAB nNewTab = nTab + 1;
+ while (aDocument.IsScenario(nNewTab))
+ ++nNewTab;
+
+ BOOL bCopyAll = ( (nFlags & SC_SCENARIO_COPYALL) != 0 );
+ const ScMarkData* pCopyMark = NULL;
+ if (!bCopyAll)
+ pCopyMark = &rMark;
+
+ ScDocShellModificator aModificator( *this );
+
+ if (bRecord)
+ aDocument.BeginDrawUndo(); // drawing layer must do its own undo actions
+
+ if (aDocument.CopyTab( nTab, nNewTab, pCopyMark ))
+ {
+ if (bRecord)
+ {
+ GetUndoManager()->AddUndoAction(
+ new ScUndoMakeScenario( this, nTab, nNewTab,
+ rName, rComment, rColor, nFlags, rMark ));
+ }
+
+ aDocument.RenameTab( nNewTab, rName, FALSE ); // ohne Formel-Update
+ aDocument.SetScenario( nNewTab, TRUE );
+ aDocument.SetScenarioData( nNewTab, rComment, rColor, nFlags );
+
+ ScMarkData aDestMark = rMark;
+ aDestMark.SelectOneTable( nNewTab );
+
+ //! auf Filter / Buttons / Merging testen !
+
+ ScPatternAttr aProtPattern( aDocument.GetPool() );
+ aProtPattern.GetItemSet().Put( ScProtectionAttr( TRUE ) );
+ aDocument.ApplyPatternAreaTab( 0,0, MAXCOL,MAXROW, nNewTab, aProtPattern );
+
+ ScPatternAttr aPattern( aDocument.GetPool() );
+ aPattern.GetItemSet().Put( ScMergeFlagAttr( SC_MF_SCENARIO ) );
+ aPattern.GetItemSet().Put( ScProtectionAttr( TRUE ) );
+ aDocument.ApplySelectionPattern( aPattern, aDestMark );
+
+ if (!bCopyAll)
+ aDocument.SetVisible( nNewTab, FALSE );
+
+ // dies ist dann das aktive Szenario
+ aDocument.CopyScenario( nNewTab, nTab, TRUE ); // TRUE - nicht aus Szenario kopieren
+
+ if (nFlags & SC_SCENARIO_SHOWFRAME)
+ PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID ); // Rahmen painten
+ PostPaintExtras(); // Tabellenreiter
+ aModificator.SetDocumentModified();
+
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
+
+ return nNewTab;
+ }
+ }
+ return nTab;
+}
+
+BOOL ScDocShell::MoveTable( SCTAB nSrcTab, SCTAB nDestTab, BOOL bCopy, BOOL bRecord )
+{
+ ScDocShellModificator aModificator( *this );
+
+ // #i92477# be consistent with ScDocFunc::InsertTable: any index past the last sheet means "append"
+ // #i101139# nDestTab must be the target position, not APPEND (for CopyTabProtection etc.)
+ if ( nDestTab >= aDocument.GetTableCount() )
+ nDestTab = aDocument.GetTableCount();
+
+ if (bCopy)
+ {
+ if (bRecord)
+ aDocument.BeginDrawUndo(); // drawing layer must do its own undo actions
+
+ if (!aDocument.CopyTab( nSrcTab, nDestTab ))
+ {
+ //! EndDrawUndo?
+ return FALSE;
+ }
+ else
+ {
+ SCTAB nAdjSource = nSrcTab;
+ if ( nDestTab <= nSrcTab )
+ ++nAdjSource; // new position of source table after CopyTab
+
+ if ( aDocument.IsTabProtected( nAdjSource ) )
+ aDocument.CopyTabProtection(nAdjSource, nDestTab);
+
+ if (bRecord)
+ {
+ SvShorts aSrcList;
+ SvShorts aDestList;
+ aSrcList.Insert(nSrcTab,0);
+ aDestList.Insert(nDestTab,0);
+ GetUndoManager()->AddUndoAction(
+ new ScUndoCopyTab( this, aSrcList, aDestList ) );
+ }
+ }
+
+ Broadcast( ScTablesHint( SC_TAB_COPIED, nSrcTab, nDestTab ) );
+ }
+ else
+ {
+ if ( aDocument.GetChangeTrack() )
+ return FALSE;
+
+ if ( nSrcTab<nDestTab && nDestTab!=SC_TAB_APPEND )
+ nDestTab--;
+
+ if ( nSrcTab == nDestTab )
+ {
+ //! allow only for api calls?
+ return TRUE; // nothing to do, but valid
+ }
+
+ if (!aDocument.MoveTab( nSrcTab, nDestTab ))
+ return FALSE;
+ else if (bRecord)
+ {
+ SvShorts aSrcList;
+ SvShorts aDestList;
+ aSrcList.Insert(nSrcTab,0);
+ aDestList.Insert(nDestTab,0);
+ GetUndoManager()->AddUndoAction(
+ new ScUndoMoveTab( this, aSrcList, aDestList ) );
+ }
+
+ Broadcast( ScTablesHint( SC_TAB_MOVED, nSrcTab, nDestTab ) );
+ }
+
+ PostPaintGridAll();
+ PostPaintExtras();
+ aModificator.SetDocumentModified();
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
+
+ return TRUE;
+}
+
+
+IMPL_LINK( ScDocShell, RefreshDBDataHdl, ScRefreshTimer*, pRefreshTimer )
+{
+ ScDBDocFunc aFunc(*this);
+
+ BOOL bContinue = TRUE;
+ ScDBData* pDBData = static_cast<ScDBData*>(pRefreshTimer);
+ ScImportParam aImportParam;
+ pDBData->GetImportParam( aImportParam );
+ if (aImportParam.bImport && !pDBData->HasImportSelection())
+ {
+ ScRange aRange;
+ pDBData->GetArea( aRange );
+ ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet> xResultSet;
+ bContinue = aFunc.DoImport( aRange.aStart.Tab(), aImportParam, xResultSet, NULL, TRUE, FALSE ); //! Api-Flag as parameter
+ // internal operations (sort, query, subtotal) only if no error
+ if (bContinue)
+ {
+ aFunc.RepeatDB( pDBData->GetName(), TRUE, TRUE );
+ RefreshPivotTables(aRange);
+ }
+ }
+
+ return bContinue != 0;
+}
+
diff --git a/sc/source/ui/docshell/docsh6.cxx b/sc/source/ui/docshell/docsh6.cxx
new file mode 100644
index 000000000000..fbb6dc8ead35
--- /dev/null
+++ b/sc/source/ui/docshell/docsh6.cxx
@@ -0,0 +1,469 @@
+/*************************************************************************
+ *
+ * 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"
+
+// System - Includes -----------------------------------------------------
+
+
+
+#ifndef PCH
+#include "scitems.hxx"
+
+#include <svx/pageitem.hxx>
+#include <vcl/virdev.hxx>
+#include <sfx2/linkmgr.hxx>
+#endif
+
+// INCLUDE ---------------------------------------------------------------
+
+//#include <svxlink.hxx>
+
+#include "docsh.hxx"
+
+#include "stlsheet.hxx"
+#include "stlpool.hxx"
+#include "global.hxx"
+#include "viewdata.hxx"
+#include "tabvwsh.hxx"
+#include "tablink.hxx"
+#include "collect.hxx"
+
+struct ScStylePair
+{
+ SfxStyleSheetBase *pSource;
+ SfxStyleSheetBase *pDest;
+};
+
+
+// STATIC DATA -----------------------------------------------------------
+
+//----------------------------------------------------------------------
+
+//
+// Ole
+//
+
+void __EXPORT ScDocShell::SetVisArea( const Rectangle & rVisArea )
+{
+ // with the SnapVisArea call in SetVisAreaOrSize, it's safe to always
+ // use both the size and position of the VisArea
+ SetVisAreaOrSize( rVisArea, TRUE );
+}
+
+void lcl_SetTopRight( Rectangle& rRect, const Point& rPos )
+{
+ Size aSize = rRect.GetSize();
+ rRect.Right() = rPos.X();
+ rRect.Left() = rPos.X() - aSize.Width() + 1;
+ rRect.Top() = rPos.Y();
+ rRect.Bottom() = rPos.Y() + aSize.Height() - 1;
+}
+
+void ScDocShell::SetVisAreaOrSize( const Rectangle& rVisArea, BOOL bModifyStart )
+{
+ BOOL bNegativePage = aDocument.IsNegativePage( aDocument.GetVisibleTab() );
+
+ Rectangle aArea = rVisArea;
+ if (bModifyStart)
+ {
+ // when loading, don't check for negative values, because the sheet orientation
+ // might be set later
+ if ( !aDocument.IsImportingXML() )
+ {
+ if ( ( bNegativePage ? (aArea.Right() > 0) : (aArea.Left() < 0) ) || aArea.Top() < 0 )
+ {
+ // VisArea start position can't be negative.
+ // Move the VisArea, otherwise only the upper left position would
+ // be changed in SnapVisArea, and the size would be wrong.
+
+ Point aNewPos( 0, Max( aArea.Top(), (long) 0 ) );
+ if ( bNegativePage )
+ {
+ aNewPos.X() = Min( aArea.Right(), (long) 0 );
+ lcl_SetTopRight( aArea, aNewPos );
+ }
+ else
+ {
+ aNewPos.X() = Max( aArea.Left(), (long) 0 );
+ aArea.SetPos( aNewPos );
+ }
+ }
+ }
+ }
+ else
+ {
+ Rectangle aOldVisArea = SfxObjectShell::GetVisArea();
+ if ( bNegativePage )
+ lcl_SetTopRight( aArea, aOldVisArea.TopRight() );
+ else
+ aArea.SetPos( aOldVisArea.TopLeft() );
+ }
+
+ // hier Position anpassen!
+
+ // #92248# when loading an ole object, the VisArea is set from the document's
+ // view settings and must be used as-is (document content may not be complete yet).
+ if ( !aDocument.IsImportingXML() )
+ aDocument.SnapVisArea( aArea );
+
+ //TODO/LATER: it's unclear which IPEnv is used here
+ /*
+ SvInPlaceEnvironment* pEnv = GetIPEnv();
+ if (pEnv)
+ {
+ Window* pWin = pEnv->GetEditWin();
+ pEnv->MakeScale( aArea.GetSize(), MAP_100TH_MM,
+ pWin->LogicToPixel( aArea.GetSize() ) );
+ } */
+
+ //TODO/LATER: formerly in SvInplaceObject
+ SfxObjectShell::SetVisArea( aArea );
+
+ if (bIsInplace) // Zoom in der InPlace View einstellen
+ {
+ ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
+ if (pViewSh)
+ {
+ if (pViewSh->GetViewData()->GetDocShell() == this)
+ pViewSh->UpdateOleZoom();
+ }
+ //else
+ // DataChanged( SvDataType() ); // fuer Zuppeln wenn nicht IP-aktiv
+ }
+
+ if (aDocument.IsEmbedded())
+ {
+ ScRange aOld;
+ aDocument.GetEmbedded( aOld);
+ aDocument.SetEmbedded( aArea );
+ ScRange aNew;
+ aDocument.GetEmbedded( aNew);
+ if (aOld != aNew)
+ PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB,PAINT_GRID);
+
+ //TODO/LATER: currently not implemented
+ //ViewChanged( ASPECT_CONTENT ); // auch im Container anzeigen
+ }
+}
+
+BOOL ScDocShell::IsOle()
+{
+ return (GetCreateMode() == SFX_CREATE_MODE_EMBEDDED);
+}
+
+void ScDocShell::UpdateOle( const ScViewData* pViewData, BOOL bSnapSize )
+{
+ // wenn's gar nicht Ole ist, kann man sich die Berechnungen sparen
+ // (VisArea wird dann beim Save wieder zurueckgesetzt)
+
+ if (GetCreateMode() == SFX_CREATE_MODE_STANDARD)
+ return;
+
+ DBG_ASSERT(pViewData,"pViewData==0 bei ScDocShell::UpdateOle");
+
+ Rectangle aOldArea = SfxObjectShell::GetVisArea();
+ Rectangle aNewArea = aOldArea;
+
+ BOOL bChange = FALSE;
+ BOOL bEmbedded = aDocument.IsEmbedded();
+ if (bEmbedded)
+ aNewArea = aDocument.GetEmbeddedRect();
+ else
+ {
+ SCTAB nTab = pViewData->GetTabNo();
+ if ( nTab != aDocument.GetVisibleTab() )
+ {
+ aDocument.SetVisibleTab( nTab );
+ bChange = TRUE;
+ }
+
+ BOOL bNegativePage = aDocument.IsNegativePage( nTab );
+ SCCOL nX = pViewData->GetPosX(SC_SPLIT_LEFT);
+ SCROW nY = pViewData->GetPosY(SC_SPLIT_BOTTOM);
+ Rectangle aMMRect = aDocument.GetMMRect( nX,nY, nX,nY, nTab );
+ if (bNegativePage)
+ lcl_SetTopRight( aNewArea, aMMRect.TopRight() );
+ else
+ aNewArea.SetPos( aMMRect.TopLeft() );
+ if (bSnapSize)
+ aDocument.SnapVisArea(aNewArea); // uses the new VisibleTab
+ }
+
+ if (aNewArea != aOldArea)
+ {
+ SetVisAreaOrSize( aNewArea, TRUE ); // hier muss auch der Start angepasst werden
+ bChange = TRUE;
+ }
+
+// if (bChange)
+// DataChanged( SvDataType() ); //! passiert auch bei SetModified
+}
+
+//
+// Style-Krempel fuer Organizer etc.
+//
+
+SfxStyleSheetBasePool* __EXPORT ScDocShell::GetStyleSheetPool()
+{
+ return (SfxStyleSheetBasePool*)aDocument.GetStyleSheetPool();
+}
+
+
+// nach dem Laden von Vorlagen aus einem anderen Dokment (LoadStyles, Insert)
+// muessen die SetItems (ATTR_PAGE_HEADERSET, ATTR_PAGE_FOOTERSET) auf den richtigen
+// Pool umgesetzt werden, bevor der Quell-Pool geloescht wird.
+
+void lcl_AdjustPool( SfxStyleSheetBasePool* pStylePool )
+{
+ pStylePool->SetSearchMask(SFX_STYLE_FAMILY_PAGE, 0xffff);
+ SfxStyleSheetBase *pStyle = pStylePool->First();
+ while ( pStyle )
+ {
+ SfxItemSet& rStyleSet = pStyle->GetItemSet();
+
+ const SfxPoolItem* pItem;
+ if (rStyleSet.GetItemState(ATTR_PAGE_HEADERSET,FALSE,&pItem) == SFX_ITEM_SET)
+ {
+ SfxItemSet& rSrcSet = ((SvxSetItem*)pItem)->GetItemSet();
+ SfxItemSet* pDestSet = new SfxItemSet(*rStyleSet.GetPool(),rSrcSet.GetRanges());
+ pDestSet->Put(rSrcSet);
+ rStyleSet.Put(SvxSetItem(ATTR_PAGE_HEADERSET,pDestSet));
+ }
+ if (rStyleSet.GetItemState(ATTR_PAGE_FOOTERSET,FALSE,&pItem) == SFX_ITEM_SET)
+ {
+ SfxItemSet& rSrcSet = ((SvxSetItem*)pItem)->GetItemSet();
+ SfxItemSet* pDestSet = new SfxItemSet(*rStyleSet.GetPool(),rSrcSet.GetRanges());
+ pDestSet->Put(rSrcSet);
+ rStyleSet.Put(SvxSetItem(ATTR_PAGE_FOOTERSET,pDestSet));
+ }
+
+ pStyle = pStylePool->Next();
+ }
+}
+
+void __EXPORT ScDocShell::LoadStyles( SfxObjectShell &rSource )
+{
+ aDocument.StylesToNames();
+
+ SfxObjectShell::LoadStyles(rSource);
+ lcl_AdjustPool( GetStyleSheetPool() ); // SetItems anpassen
+
+ aDocument.UpdStlShtPtrsFrmNms();
+
+ UpdateAllRowHeights();
+
+ // Paint
+
+ PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID | PAINT_LEFT );
+}
+
+void ScDocShell::LoadStylesArgs( ScDocShell& rSource, BOOL bReplace, BOOL bCellStyles, BOOL bPageStyles )
+{
+ // similar to LoadStyles, but with selectable behavior for XStyleLoader::loadStylesFromURL call
+
+ if ( !bCellStyles && !bPageStyles ) // nothing to do
+ return;
+
+ ScStyleSheetPool* pSourcePool = rSource.GetDocument()->GetStyleSheetPool();
+ ScStyleSheetPool* pDestPool = aDocument.GetStyleSheetPool();
+
+ SfxStyleFamily eFamily = bCellStyles ?
+ ( bPageStyles ? SFX_STYLE_FAMILY_ALL : SFX_STYLE_FAMILY_PARA ) :
+ SFX_STYLE_FAMILY_PAGE;
+ SfxStyleSheetIterator aIter( pSourcePool, eFamily );
+ USHORT nSourceCount = aIter.Count();
+ if ( nSourceCount == 0 )
+ return; // no source styles
+
+ ScStylePair* pStyles = new ScStylePair[ nSourceCount ];
+ USHORT nFound = 0;
+
+ // first create all new styles
+
+ SfxStyleSheetBase* pSourceStyle = aIter.First();
+ while (pSourceStyle)
+ {
+ String aName = pSourceStyle->GetName();
+ SfxStyleSheetBase* pDestStyle = pDestPool->Find( pSourceStyle->GetName(), pSourceStyle->GetFamily() );
+ if ( pDestStyle )
+ {
+ // touch existing styles only if replace flag is set
+ if ( bReplace )
+ {
+ pStyles[nFound].pSource = pSourceStyle;
+ pStyles[nFound].pDest = pDestStyle;
+ ++nFound;
+ }
+ }
+ else
+ {
+ pStyles[nFound].pSource = pSourceStyle;
+ pStyles[nFound].pDest = &pDestPool->Make( aName, pSourceStyle->GetFamily(), pSourceStyle->GetMask() );
+ ++nFound;
+ }
+
+ pSourceStyle = aIter.Next();
+ }
+
+ // then copy contents (after inserting all styles, for parent etc.)
+
+ for ( USHORT i = 0; i < nFound; ++i )
+ {
+ pStyles[i].pDest->GetItemSet().PutExtended(
+ pStyles[i].pSource->GetItemSet(), SFX_ITEM_DONTCARE, SFX_ITEM_DEFAULT);
+ if(pStyles[i].pSource->HasParentSupport())
+ pStyles[i].pDest->SetParent(pStyles[i].pSource->GetParent());
+ // follow is never used
+ }
+
+ lcl_AdjustPool( GetStyleSheetPool() ); // adjust SetItems
+ UpdateAllRowHeights();
+ PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID | PAINT_LEFT ); // Paint
+
+ delete[] pStyles;
+}
+
+
+BOOL __EXPORT ScDocShell::Insert( SfxObjectShell &rSource,
+ USHORT nSourceIdx1, USHORT nSourceIdx2, USHORT nSourceIdx3,
+ USHORT &nIdx1, USHORT &nIdx2, USHORT &nIdx3, USHORT &rIdxDeleted )
+{
+ BOOL bRet = SfxObjectShell::Insert( rSource, nSourceIdx1, nSourceIdx2, nSourceIdx3,
+ nIdx1, nIdx2, nIdx3, rIdxDeleted );
+ if (bRet)
+ lcl_AdjustPool( GetStyleSheetPool() ); // SetItems anpassen
+
+ return bRet;
+}
+
+void ScDocShell::UpdateLinks()
+{
+ sfx2::LinkManager* pLinkManager = aDocument.GetLinkManager();
+ ScStrCollection aNames;
+
+ // nicht mehr benutzte Links raus
+
+ USHORT nCount = pLinkManager->GetLinks().Count();
+ for (USHORT k=nCount; k>0; )
+ {
+ --k;
+ ::sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[k];
+ if (pBase->ISA(ScTableLink))
+ {
+ ScTableLink* pTabLink = (ScTableLink*)pBase;
+ if (pTabLink->IsUsed())
+ {
+ StrData* pData = new StrData(pTabLink->GetFileName());
+ if (!aNames.Insert(pData))
+ delete pData;
+ }
+ else // nicht mehr benutzt -> loeschen
+ {
+ pTabLink->SetAddUndo(TRUE);
+ pLinkManager->Remove(k);
+ }
+ }
+ }
+
+
+ // neue Links eintragen
+
+ SCTAB nTabCount = aDocument.GetTableCount();
+ for (SCTAB i=0; i<nTabCount; i++)
+ if (aDocument.IsLinked(i))
+ {
+ String aDocName = aDocument.GetLinkDoc(i);
+ String aFltName = aDocument.GetLinkFlt(i);
+ String aOptions = aDocument.GetLinkOpt(i);
+ ULONG nRefresh = aDocument.GetLinkRefreshDelay(i);
+ BOOL bThere = FALSE;
+ for (SCTAB j=0; j<i && !bThere; j++) // im Dokument mehrfach?
+ if (aDocument.IsLinked(j)
+ && aDocument.GetLinkDoc(j) == aDocName
+ && aDocument.GetLinkFlt(j) == aFltName
+ && aDocument.GetLinkOpt(j) == aOptions)
+ // Ignore refresh delay in compare, it should be the
+ // same for identical links and we don't want dupes
+ // if it ain't.
+ bThere = TRUE;
+
+ if (!bThere) // schon als Filter eingetragen?
+ {
+ StrData* pData = new StrData(aDocName);
+ if (!aNames.Insert(pData))
+ {
+ delete pData;
+ bThere = TRUE;
+ }
+ }
+ if (!bThere)
+ {
+ ScTableLink* pLink = new ScTableLink( this, aDocName, aFltName, aOptions, nRefresh );
+ pLink->SetInCreate( TRUE );
+ pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, aDocName, &aFltName );
+ pLink->Update();
+ pLink->SetInCreate( FALSE );
+ }
+ }
+}
+
+BOOL ScDocShell::ReloadTabLinks()
+{
+ sfx2::LinkManager* pLinkManager = aDocument.GetLinkManager();
+
+ BOOL bAny = FALSE;
+ USHORT nCount = pLinkManager->GetLinks().Count();
+ for (USHORT i=0; i<nCount; i++ )
+ {
+ ::sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[i];
+ if (pBase->ISA(ScTableLink))
+ {
+ ScTableLink* pTabLink = (ScTableLink*)pBase;
+// pTabLink->SetAddUndo(FALSE); //! Undo's zusammenfassen
+ pTabLink->SetPaint(FALSE); // Paint nur einmal am Ende
+ pTabLink->Update();
+ pTabLink->SetPaint(TRUE);
+// pTabLink->SetAddUndo(TRUE);
+ bAny = TRUE;
+ }
+ }
+
+ if ( bAny )
+ {
+ // Paint nur einmal
+ PostPaint( ScRange(0,0,0,MAXCOL,MAXROW,MAXTAB),
+ PAINT_GRID | PAINT_TOP | PAINT_LEFT );
+
+ SetDocumentModified();
+ }
+
+ return TRUE; //! Fehler erkennen
+}
+
+
diff --git a/sc/source/ui/docshell/docsh7.cxx b/sc/source/ui/docshell/docsh7.cxx
new file mode 100644
index 000000000000..89f082672b29
--- /dev/null
+++ b/sc/source/ui/docshell/docsh7.cxx
@@ -0,0 +1,45 @@
+/*************************************************************************
+ *
+ * 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 "docsh.hxx"
+
+//------------------------------------------------------------------
+
+void ScDocShell::GetDrawObjState( SfxItemSet & /* rSet */ )
+{
+ // SID_SC_ACTIVEOBJECT (SelectedObject) - removed (old Basic)
+}
+
+
+
diff --git a/sc/source/ui/docshell/docsh8.cxx b/sc/source/ui/docshell/docsh8.cxx
new file mode 100644
index 000000000000..b761dd75d9df
--- /dev/null
+++ b/sc/source/ui/docshell/docsh8.cxx
@@ -0,0 +1,1098 @@
+/*************************************************************************
+ *
+ * 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 <stdio.h>
+#include <tools/urlobj.hxx>
+#include <svl/converter.hxx>
+#include <svl/zforlist.hxx>
+#include <comphelper/types.hxx>
+#include <ucbhelper/content.hxx>
+#include <unotools/sharedunocomponent.hxx>
+#include <comphelper/processfactory.hxx>
+#include <svx/txenctab.hxx>
+#include <svx/dbcharsethelper.hxx>
+
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XDriver.hpp>
+#include <com/sun/star/sdbc/XDriverAccess.hpp>
+#include <com/sun/star/sdbc/XDriverManager.hpp>
+#include <com/sun/star/sdbc/XResultSetUpdate.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XRowSet.hpp>
+#include <com/sun/star/sdbc/XRowUpdate.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/sdbcx/XAppend.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbcx/XDataDefinitionSupplier.hpp>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/ucb/NameClash.hpp>
+#include <com/sun/star/ucb/TransferInfo.hpp>
+#include <com/sun/star/ucb/XCommandInfo.hpp>
+
+#include "scerrors.hxx"
+#include "docsh.hxx"
+#include "filter.hxx"
+#include "progress.hxx"
+#include "collect.hxx"
+#include "cell.hxx"
+#include "editutil.hxx"
+#include "cellform.hxx"
+#include "dbdocutl.hxx"
+#include "dociter.hxx"
+#include "globstr.hrc"
+
+using namespace com::sun::star;
+
+// -----------------------------------------------------------------------
+
+#define SC_SERVICE_ROWSET "com.sun.star.sdb.RowSet"
+#define SC_SERVICE_DRVMAN "com.sun.star.sdbc.DriverManager"
+
+//! move to a header file?
+//#define SC_DBPROP_DATASOURCENAME "DataSourceName"
+#define SC_DBPROP_ACTIVECONNECTION "ActiveConnection"
+#define SC_DBPROP_COMMAND "Command"
+#define SC_DBPROP_COMMANDTYPE "CommandType"
+
+#define SC_DBPROP_NAME "Name"
+#define SC_DBPROP_TYPE "Type"
+#define SC_DBPROP_PRECISION "Precision"
+#define SC_DBPROP_SCALE "Scale"
+
+#define SC_DBPROP_EXTENSION "Extension"
+#define SC_DBPROP_CHARSET "CharSet"
+
+#define SC_ROWCOUNT_ERROR (-1)
+
+namespace
+{
+ ULONG lcl_getDBaseConnection(uno::Reference<sdbc::XDriverManager>& _rDrvMgr,uno::Reference<sdbc::XConnection>& _rConnection,String& _rTabName,const String& rFullFileName,rtl_TextEncoding eCharSet)
+ {
+ INetURLObject aURL;
+ aURL.SetSmartProtocol( INET_PROT_FILE );
+ aURL.SetSmartURL( rFullFileName );
+ _rTabName = aURL.getBase( INetURLObject::LAST_SEGMENT, true,
+ INetURLObject::DECODE_UNAMBIGUOUS );
+ String aExtension = aURL.getExtension();
+ aURL.removeSegment();
+ aURL.removeFinalSlash();
+ String aPath = aURL.GetMainURL(INetURLObject::NO_DECODE);
+ uno::Reference<lang::XMultiServiceFactory> xFactory = comphelper::getProcessServiceFactory();
+ if (!xFactory.is()) return SCERR_EXPORT_CONNECT;
+
+ _rDrvMgr.set( xFactory->createInstance(
+ rtl::OUString::createFromAscii( SC_SERVICE_DRVMAN ) ),
+ uno::UNO_QUERY);
+ DBG_ASSERT( _rDrvMgr.is(), "can't get DriverManager" );
+ if (!_rDrvMgr.is()) return SCERR_EXPORT_CONNECT;
+
+ // get connection
+
+ String aConnUrl = String::CreateFromAscii("sdbc:dbase:");
+ aConnUrl += aPath;
+
+ svxform::ODataAccessCharsetHelper aHelper;
+ ::std::vector< rtl_TextEncoding > aEncodings;
+ aHelper.getSupportedTextEncodings( aEncodings );
+ ::std::vector< rtl_TextEncoding >::iterator aIter = ::std::find(aEncodings.begin(),aEncodings.end(),(rtl_TextEncoding) eCharSet);
+ if ( aIter == aEncodings.end() )
+ {
+ DBG_ERRORFILE( "DBaseImport: dbtools::OCharsetMap doesn't know text encoding" );
+ return SCERR_IMPORT_CONNECT;
+ } // if ( aIter == aMap.end() )
+ rtl::OUString aCharSetStr;
+ if ( RTL_TEXTENCODING_DONTKNOW != *aIter )
+ { // it's not the virtual "system charset"
+ const char* pIanaName = rtl_getMimeCharsetFromTextEncoding( *aIter );
+ OSL_ENSURE( pIanaName, "invalid mime name!" );
+ if ( pIanaName )
+ aCharSetStr = ::rtl::OUString::createFromAscii( pIanaName );
+ }
+
+ uno::Sequence<beans::PropertyValue> aProps(2);
+ aProps[0].Name = rtl::OUString::createFromAscii(SC_DBPROP_EXTENSION);
+ aProps[0].Value <<= rtl::OUString( aExtension );
+ aProps[1].Name = rtl::OUString::createFromAscii(SC_DBPROP_CHARSET);
+ aProps[1].Value <<= aCharSetStr;
+
+ _rConnection = _rDrvMgr->getConnectionWithInfo( aConnUrl, aProps );
+ return 0L;
+ }
+}
+// -----------------------------------------------------------------------
+// MoveFile/KillFile/IsDocument: similar to SfxContentHelper
+
+// static
+BOOL ScDocShell::MoveFile( const INetURLObject& rSourceObj, const INetURLObject& rDestObj )
+{
+ sal_Bool bMoveData = sal_True;
+ sal_Bool bRet = sal_True, bKillSource = sal_False;
+ if ( rSourceObj.GetProtocol() != rDestObj.GetProtocol() )
+ {
+ bMoveData = sal_False;
+ bKillSource = sal_True;
+ }
+ String aName = rDestObj.getName();
+ INetURLObject aDestPathObj = rDestObj;
+ aDestPathObj.removeSegment();
+ aDestPathObj.setFinalSlash();
+
+ try
+ {
+ ::ucbhelper::Content aDestPath( aDestPathObj.GetMainURL(INetURLObject::NO_DECODE),
+ uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () );
+ uno::Reference< ::com::sun::star::ucb::XCommandInfo > xInfo = aDestPath.getCommands();
+ rtl::OUString aTransferName = rtl::OUString::createFromAscii( "transfer" );
+ if ( xInfo->hasCommandByName( aTransferName ) )
+ {
+ aDestPath.executeCommand( aTransferName, uno::makeAny(
+ ::com::sun::star::ucb::TransferInfo( bMoveData, rSourceObj.GetMainURL(INetURLObject::NO_DECODE), aName,
+ ::com::sun::star::ucb::NameClash::ERROR ) ) );
+ }
+ else
+ {
+ DBG_ERRORFILE( "transfer command not available" );
+ }
+ }
+ catch( uno::Exception& )
+ {
+ // ucb may throw different exceptions on failure now
+ bRet = sal_False;
+ }
+
+ if ( bKillSource )
+ KillFile( rSourceObj );
+
+ return bRet;
+}
+
+
+// static
+BOOL ScDocShell::KillFile( const INetURLObject& rURL )
+{
+ sal_Bool bRet = sal_True;
+ try
+ {
+ ::ucbhelper::Content aCnt( rURL.GetMainURL(INetURLObject::NO_DECODE),
+ uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () );
+ aCnt.executeCommand( rtl::OUString::createFromAscii( "delete" ),
+ comphelper::makeBoolAny( sal_True ) );
+ }
+ catch( uno::Exception& )
+ {
+ // ucb may throw different exceptions on failure now
+ bRet = sal_False;
+ }
+
+ return bRet;
+}
+
+// static
+BOOL ScDocShell::IsDocument( const INetURLObject& rURL )
+{
+ sal_Bool bRet = sal_False;
+ try
+ {
+ ::ucbhelper::Content aCnt( rURL.GetMainURL(INetURLObject::NO_DECODE),
+ uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () );
+ bRet = aCnt.isDocument();
+ }
+ catch( uno::Exception& )
+ {
+ // ucb may throw different exceptions on failure now - warning only
+ DBG_WARNING( "Any other exception" );
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG ScDocShell::DBaseImport( const String& rFullFileName, CharSet eCharSet,
+ BOOL bSimpleColWidth[MAXCOLCOUNT] )
+{
+ ULONG nErr = eERR_OK;
+ long i;
+
+ try
+ {
+ String aTabName;
+ uno::Reference<sdbc::XDriverManager> xDrvMan;
+ uno::Reference<sdbc::XConnection> xConnection;
+ ULONG nRet = lcl_getDBaseConnection(xDrvMan,xConnection,aTabName,rFullFileName,eCharSet);
+ if ( !xConnection.is() || !xDrvMan.is() )
+ return nRet;
+ ::utl::DisposableComponent aConnectionHelper(xConnection);
+
+ long nRowCount = 0;
+ if ( nRowCount < 0 )
+ {
+ DBG_ERROR("can't get row count");
+ nRowCount = 0;
+ }
+
+ ScProgress aProgress( this, ScGlobal::GetRscString( STR_LOAD_DOC ), nRowCount );
+ uno::Reference<lang::XMultiServiceFactory> xFactory = comphelper::getProcessServiceFactory();
+ uno::Reference<sdbc::XRowSet> xRowSet( xFactory->createInstance(
+ rtl::OUString::createFromAscii( SC_SERVICE_ROWSET ) ),
+ uno::UNO_QUERY);
+ ::utl::DisposableComponent aRowSetHelper(xRowSet);
+ uno::Reference<beans::XPropertySet> xRowProp( xRowSet, uno::UNO_QUERY );
+ DBG_ASSERT( xRowProp.is(), "can't get RowSet" );
+ if (!xRowProp.is()) return SCERR_IMPORT_CONNECT;
+
+ sal_Int32 nType = sdb::CommandType::TABLE;
+ uno::Any aAny;
+
+ aAny <<= xConnection;
+ xRowProp->setPropertyValue(
+ rtl::OUString::createFromAscii(SC_DBPROP_ACTIVECONNECTION), aAny );
+
+ aAny <<= nType;
+ xRowProp->setPropertyValue(
+ rtl::OUString::createFromAscii(SC_DBPROP_COMMANDTYPE), aAny );
+
+ aAny <<= rtl::OUString( aTabName );
+ xRowProp->setPropertyValue(
+ rtl::OUString::createFromAscii(SC_DBPROP_COMMAND), aAny );
+
+ xRowSet->execute();
+
+ long nColCount = 0;
+ uno::Reference<sdbc::XResultSetMetaData> xMeta;
+ uno::Reference<sdbc::XResultSetMetaDataSupplier> xMetaSupp( xRowSet, uno::UNO_QUERY );
+ if ( xMetaSupp.is() )
+ xMeta = xMetaSupp->getMetaData();
+ if ( xMeta.is() )
+ nColCount = xMeta->getColumnCount(); // this is the number of real columns
+
+ if ( nColCount > MAXCOL+1 )
+ {
+ nColCount = MAXCOL+1;
+ nErr = SCWARN_IMPORT_RANGE_OVERFLOW; // warning
+ }
+
+ if ( nColCount > 0 )
+ aDocument.DoColResize( 0, 0, static_cast<SCCOL>(nColCount) - 1,
+ static_cast<SCSIZE>(nRowCount) + 1 );
+
+ uno::Reference<sdbc::XRow> xRow( xRowSet, uno::UNO_QUERY );
+ DBG_ASSERT( xRow.is(), "can't get Row" );
+ if (!xRow.is()) return SCERR_IMPORT_CONNECT;
+
+ // currency flag is not needed for dBase
+ uno::Sequence<sal_Int32> aColTypes( nColCount ); // column types
+ sal_Int32* pTypeArr = aColTypes.getArray();
+ for (i=0; i<nColCount; i++)
+ pTypeArr[i] = xMeta->getColumnType( i+1 );
+
+ // read column names
+ //! add type descriptions
+
+ for (i=0; i<nColCount; i++)
+ {
+ String aHeader = xMeta->getColumnLabel( i+1 );
+
+ switch ( pTypeArr[i] )
+ {
+ case sdbc::DataType::BIT:
+ aHeader.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",L" ));
+ break;
+ case sdbc::DataType::DATE:
+ aHeader.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",D" ));
+ break;
+ case sdbc::DataType::LONGVARCHAR:
+ aHeader.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",M" ));
+ break;
+ case sdbc::DataType::VARCHAR:
+ aHeader.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",C," ));
+ aHeader += String::CreateFromInt32( xMeta->getColumnDisplaySize( i+1 ) );
+ break;
+ case sdbc::DataType::DECIMAL:
+ {
+ long nPrec = xMeta->getPrecision( i+1 );
+ long nScale = xMeta->getScale( i+1 );
+ aHeader.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",N," ));
+ aHeader += String::CreateFromInt32(
+ SvDbaseConverter::ConvertPrecisionToDbase(
+ nPrec, nScale ) );
+ aHeader += ',';
+ aHeader += String::CreateFromInt32( nScale );
+ }
+ break;
+ }
+
+ aDocument.SetString( static_cast<SCCOL>(i), 0, 0, aHeader );
+ }
+
+ SCROW nRow = 1; // 0 is column titles
+ BOOL bEnd = FALSE;
+ while ( !bEnd && xRowSet->next() )
+ {
+ if ( nRow <= MAXROW )
+ {
+ SCCOL nCol = 0;
+ for (i=0; i<nColCount; i++)
+ {
+ ScDatabaseDocUtil::PutData( &aDocument, nCol, nRow, 0,
+ xRow, i+1, pTypeArr[i], FALSE,
+ &bSimpleColWidth[nCol] );
+ ++nCol;
+ }
+ ++nRow;
+ }
+ else // past the end of the spreadsheet
+ {
+ bEnd = TRUE; // don't continue
+ nErr = SCWARN_IMPORT_RANGE_OVERFLOW; // warning message
+ }
+
+ if ( nRowCount )
+ aProgress.SetStateOnPercent( nRow );
+ }
+ }
+ catch ( sdbc::SQLException& )
+ {
+ nErr = SCERR_IMPORT_CONNECT;
+ }
+ catch ( uno::Exception& )
+ {
+ DBG_ERROR("Unexpected exception in database");
+ nErr = ERRCODE_IO_GENERAL;
+ }
+
+ return nErr;
+}
+
+// -----------------------------------------------------------------------
+
+inline sal_Bool IsAsciiDigit( sal_Unicode c )
+{
+ return 0x30 <= c && c <= 0x39;
+}
+
+inline sal_Bool IsAsciiAlpha( sal_Unicode c )
+{
+ return (0x41 <= c && c <= 0x5a) || (0x61 <= c && c <= 0x7a);
+}
+
+void lcl_GetColumnTypes( ScDocShell& rDocShell,
+ const ScRange& rDataRange, BOOL bHasFieldNames,
+ rtl::OUString* pColNames, sal_Int32* pColTypes,
+ sal_Int32* pColLengths, sal_Int32* pColScales,
+ BOOL& bHasMemo, CharSet eCharSet )
+{
+ // updating of column titles didn't work in 5.2 and isn't always wanted
+ // (saving normally shouldn't modify the document)
+ //! read flag from configuration
+ BOOL bUpdateTitles = FALSE;
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ SvNumberFormatter* pNumFmt = pDoc->GetFormatTable();
+
+ SCTAB nTab = rDataRange.aStart.Tab();
+ SCCOL nFirstCol = rDataRange.aStart.Col();
+ SCROW nFirstRow = rDataRange.aStart.Row();
+ SCCOL nLastCol = rDataRange.aEnd.Col();
+ SCROW nLastRow = rDataRange.aEnd.Row();
+
+ ScStrCollection aFieldNamesCollection;
+
+ long nField = 0;
+ SCROW nFirstDataRow = ( bHasFieldNames ? nFirstRow + 1 : nFirstRow );
+ for ( SCCOL nCol = nFirstCol; nCol <= nLastCol; nCol++ )
+ {
+ BOOL bTypeDefined = FALSE;
+ BOOL bPrecDefined = FALSE;
+ sal_Int32 nFieldLen = 0;
+ sal_Int32 nPrecision = 0;
+ sal_Int32 nDbType = sdbc::DataType::SQLNULL;
+ String aFieldName, aString;
+
+ // Feldname[,Type[,Width[,Prec]]]
+ // Typ etc.: L; D; C[,W]; N[,W[,P]]
+ if ( bHasFieldNames )
+ {
+ pDoc->GetString( nCol, nFirstRow, nTab, aString );
+ aString.ToUpperAscii();
+ xub_StrLen nToken = aString.GetTokenCount( ',' );
+ if ( nToken > 1 )
+ {
+ aFieldName = aString.GetToken( 0, ',' );
+ aString.EraseAllChars( ' ' );
+ switch ( aString.GetToken( 1, ',' ).GetChar(0) )
+ {
+ case 'L' :
+ nDbType = sdbc::DataType::BIT;
+ nFieldLen = 1;
+ bTypeDefined = TRUE;
+ bPrecDefined = TRUE;
+ break;
+ case 'D' :
+ nDbType = sdbc::DataType::DATE;
+ nFieldLen = 8;
+ bTypeDefined = TRUE;
+ bPrecDefined = TRUE;
+ break;
+ case 'M' :
+ nDbType = sdbc::DataType::LONGVARCHAR;
+ nFieldLen = 10;
+ bTypeDefined = TRUE;
+ bPrecDefined = TRUE;
+ bHasMemo = TRUE;
+ break;
+ case 'C' :
+ nDbType = sdbc::DataType::VARCHAR;
+ bTypeDefined = TRUE;
+ bPrecDefined = TRUE;
+ break;
+ case 'N' :
+ nDbType = sdbc::DataType::DECIMAL;
+ bTypeDefined = TRUE;
+ break;
+ }
+ if ( bTypeDefined && !nFieldLen && nToken > 2 )
+ {
+ nFieldLen = aString.GetToken( 2, ',' ).ToInt32();
+ if ( !bPrecDefined && nToken > 3 )
+ {
+ String aTmp( aString.GetToken( 3, ',' ) );
+ if ( CharClass::isAsciiNumeric(aTmp) )
+ {
+ nPrecision = aTmp.ToInt32();
+ bPrecDefined = TRUE;
+ }
+ }
+ }
+ }
+ else
+ aFieldName = aString;
+
+ // Feldnamen pruefen und ggbf. gueltigen Feldnamen erzeugen.
+ // Erstes Zeichen muss Buchstabe sein,
+ // weitere nur alphanumerisch und Unterstrich erlaubt,
+ // "_DBASELOCK" ist reserviert (obsolet weil erstes Zeichen kein Buchstabe),
+ // keine doppelten Namen.
+ if ( !IsAsciiAlpha( aFieldName.GetChar(0) ) )
+ aFieldName.Insert( 'N', 0 );
+ String aTmpStr;
+ sal_Unicode c;
+ for ( const sal_Unicode* p = aFieldName.GetBuffer(); ( c = *p ) != 0; p++ )
+ {
+ if ( IsAsciiAlpha( c ) || IsAsciiDigit( c ) || c == '_' )
+ aTmpStr += c;
+ else
+ aTmpStr += '_';
+ }
+ aFieldName = aTmpStr;
+ if ( aFieldName.Len() > 10 )
+ aFieldName.Erase( 10 );
+ StrData* pStrData = new StrData( aFieldName );
+ if ( !aFieldNamesCollection.Insert( pStrData ) )
+ { // doppelter Feldname, numerisch erweitern
+ USHORT nSub = 1;
+ String aFixPart( aFieldName );
+ do
+ {
+ ++nSub;
+ String aVarPart = String::CreateFromInt32( nSub );
+ if ( aFixPart.Len() + aVarPart.Len() > 10 )
+ aFixPart.Erase( 10 - aVarPart.Len() );
+ aFieldName = aFixPart;
+ aFieldName += aVarPart;
+ pStrData->SetString( aFieldName );
+ } while ( !aFieldNamesCollection.Insert( pStrData ) );
+ }
+ }
+ else
+ {
+ aFieldName = 'N';
+ aFieldName += String::CreateFromInt32(nCol+1);
+ }
+
+ if ( !bTypeDefined )
+ { // Feldtyp
+ ScBaseCell* pCell;
+ pDoc->GetCell( nCol, nFirstDataRow, nTab, pCell );
+ if ( !pCell || pCell->HasStringData() )
+ nDbType = sdbc::DataType::VARCHAR;
+ else
+ {
+ sal_uInt32 nFormat;
+ pDoc->GetNumberFormat( nCol, nFirstDataRow, nTab, nFormat );
+ if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA
+ && ((nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0) )
+ {
+ nFormat = ScGlobal::GetStandardFormat(
+ ((ScFormulaCell*)pCell)->GetValue(), *pNumFmt, nFormat,
+ ((ScFormulaCell*)pCell)->GetFormatType() );
+ }
+ switch ( pNumFmt->GetType( nFormat ) )
+ {
+ case NUMBERFORMAT_LOGICAL :
+ nDbType = sdbc::DataType::BIT;
+ nFieldLen = 1;
+ break;
+ case NUMBERFORMAT_DATE :
+ nDbType = sdbc::DataType::DATE;
+ nFieldLen = 8;
+ break;
+ case NUMBERFORMAT_TIME :
+ case NUMBERFORMAT_DATETIME :
+ nDbType = sdbc::DataType::VARCHAR;
+ break;
+ default:
+ nDbType = sdbc::DataType::DECIMAL;
+ }
+ }
+ }
+ BOOL bSdbLenAdjusted = FALSE;
+ BOOL bSdbLenBad = FALSE;
+ // Feldlaenge
+ if ( nDbType == sdbc::DataType::VARCHAR && !nFieldLen )
+ { // maximale Feldbreite bestimmen
+ nFieldLen = pDoc->GetMaxStringLen( nTab, nCol, nFirstDataRow,
+ nLastRow, eCharSet );
+ if ( nFieldLen == 0 )
+ nFieldLen = 1;
+ }
+ else if ( nDbType == sdbc::DataType::DECIMAL )
+ { // maximale Feldbreite und Nachkommastellen bestimmen
+ xub_StrLen nLen;
+ USHORT nPrec;
+ nLen = pDoc->GetMaxNumberStringLen( nPrec, nTab, nCol,
+ nFirstDataRow, nLastRow );
+ // dBaseIII Limit Nachkommastellen: 15
+ if ( nPrecision > 15 )
+ nPrecision = 15;
+ if ( nPrec > 15 )
+ nPrec = 15;
+ if ( bPrecDefined && nPrecision != nPrec )
+ { // Laenge auf vorgegebene Nachkommastellen anpassen
+ if ( nPrecision )
+ nLen = sal::static_int_cast<xub_StrLen>( nLen + ( nPrecision - nPrec ) );
+ else
+ nLen -= nPrec+1; // auch den . mit raus
+ }
+ if ( nLen > nFieldLen && !bTypeDefined )
+ nFieldLen = nLen;
+ if ( !bPrecDefined )
+ nPrecision = nPrec;
+ if ( nFieldLen == 0 )
+ nFieldLen = 1;
+ else if ( nFieldLen > 19 )
+ nFieldLen = 19; // dBaseIII Limit Feldlaenge numerisch: 19
+ if ( nPrecision && nFieldLen < nPrecision + 2 )
+ nFieldLen = nPrecision + 2; // 0. muss mit reinpassen
+ // 538 MUST: Sdb internal representation adds 2 to the field length!
+ // To give the user what he wants we must substract it here.
+ //! CAVEAT! There is no way to define a numeric field with a length
+ //! of 1 and no decimals!
+ if ( nFieldLen == 1 && nPrecision == 0 )
+ bSdbLenBad = TRUE;
+ nFieldLen = SvDbaseConverter::ConvertPrecisionToOdbc( nFieldLen, nPrecision );
+ bSdbLenAdjusted = TRUE;
+ }
+ if ( nFieldLen > 254 )
+ {
+ if ( nDbType == sdbc::DataType::VARCHAR )
+ { // zu lang fuer normales Textfeld => Memofeld
+ nDbType = sdbc::DataType::LONGVARCHAR;
+ nFieldLen = 10;
+ bHasMemo = TRUE;
+ }
+ else
+ nFieldLen = 254; // dumm gelaufen..
+ }
+
+ pColNames[nField] = aFieldName;
+ pColTypes[nField] = nDbType;
+ pColLengths[nField] = nFieldLen;
+ pColScales[nField] = nPrecision;
+
+ // undo change to field length, reflect reality
+ if ( bSdbLenAdjusted )
+ {
+ nFieldLen = SvDbaseConverter::ConvertPrecisionToDbase( nFieldLen, nPrecision );
+ if ( bSdbLenBad && nFieldLen == 1 )
+ nFieldLen = 2; // THIS is reality
+ }
+ if ( bUpdateTitles )
+ { // Angabe anpassen und ausgeben
+ String aOutString = aFieldName;
+ switch ( nDbType )
+ {
+ case sdbc::DataType::BIT :
+ aOutString.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",L" ));
+ break;
+ case sdbc::DataType::DATE :
+ aOutString.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",D" ));
+ break;
+ case sdbc::DataType::LONGVARCHAR :
+ aOutString.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",M" ));
+ break;
+ case sdbc::DataType::VARCHAR :
+ aOutString.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",C," ));
+ aOutString += String::CreateFromInt32( nFieldLen );
+ break;
+ case sdbc::DataType::DECIMAL :
+ aOutString.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ",N," ));
+ aOutString += String::CreateFromInt32( nFieldLen );
+ aOutString += ',';
+ aOutString += String::CreateFromInt32( nPrecision );
+ break;
+ }
+ if ( !aOutString.EqualsIgnoreCaseAscii( aString ) )
+ {
+ pDoc->SetString( nCol, nFirstRow, nTab, aOutString );
+ rDocShell.PostPaint( nCol, nFirstRow, nTab, nCol, nFirstRow, nTab, PAINT_GRID );
+ }
+ }
+ ++nField;
+ }
+}
+
+
+inline void lcl_getLongVarCharEditString( String& rString,
+ const ScBaseCell* pCell, ScFieldEditEngine& rEditEngine )
+{
+ rEditEngine.SetText( *((const ScEditCell*)pCell)->GetData() );
+ rString = rEditEngine.GetText( LINEEND_CRLF );
+}
+
+inline void lcl_getLongVarCharString( String& rString, ScBaseCell* pCell,
+ ScDocument& rDocument, SCCOL nCol, SCROW nRow, SCTAB nTab,
+ SvNumberFormatter& rNumFmt )
+{
+ sal_uInt32 nFormat;
+ Color* pColor;
+ rDocument.GetNumberFormat( nCol, nRow, nTab, nFormat );
+ ScCellFormat::GetString( pCell, nFormat, rString, &pColor, rNumFmt );
+}
+
+
+ULONG ScDocShell::DBaseExport( const String& rFullFileName, CharSet eCharSet, BOOL& bHasMemo )
+{
+ // remove the file so the dBase driver doesn't find an invalid file
+ INetURLObject aDeleteObj( rFullFileName, INET_PROT_FILE );
+ KillFile( aDeleteObj );
+
+ ULONG nErr = eERR_OK;
+ uno::Any aAny;
+
+ SCCOL nFirstCol, nLastCol;
+ SCROW nFirstRow, nLastRow;
+ SCTAB nTab = GetSaveTab();
+ aDocument.GetDataStart( nTab, nFirstCol, nFirstRow );
+ aDocument.GetCellArea( nTab, nLastCol, nLastRow );
+ if ( nFirstCol > nLastCol )
+ nFirstCol = nLastCol;
+ if ( nFirstRow > nLastRow )
+ nFirstRow = nLastRow;
+ ScProgress aProgress( this, ScGlobal::GetRscString( STR_SAVE_DOC ),
+ nLastRow - nFirstRow );
+ SvNumberFormatter* pNumFmt = aDocument.GetFormatTable();
+
+ BOOL bHasFieldNames = TRUE;
+ for ( SCCOL nDocCol = nFirstCol; nDocCol <= nLastCol && bHasFieldNames; nDocCol++ )
+ { // nur Strings in erster Zeile => sind Feldnamen
+ if ( !aDocument.HasStringData( nDocCol, nFirstRow, nTab ) )
+ bHasFieldNames = FALSE;
+ }
+
+ long nColCount = nLastCol - nFirstCol + 1;
+ uno::Sequence<rtl::OUString> aColNames( nColCount );
+ uno::Sequence<sal_Int32> aColTypes( nColCount );
+ uno::Sequence<sal_Int32> aColLengths( nColCount );
+ uno::Sequence<sal_Int32> aColScales( nColCount );
+
+ ScRange aDataRange( nFirstCol, nFirstRow, nTab, nLastCol, nLastRow, nTab );
+ lcl_GetColumnTypes( *this, aDataRange, bHasFieldNames,
+ aColNames.getArray(), aColTypes.getArray(),
+ aColLengths.getArray(), aColScales.getArray(),
+ bHasMemo, eCharSet );
+ // also needed for exception catch
+ SCROW nDocRow = 0;
+ ScFieldEditEngine aEditEngine( aDocument.GetEditPool() );
+ String aString;
+ String aTabName;
+
+ try
+ {
+ uno::Reference<sdbc::XDriverManager> xDrvMan;
+ uno::Reference<sdbc::XConnection> xConnection;
+ ULONG nRet = lcl_getDBaseConnection(xDrvMan,xConnection,aTabName,rFullFileName,eCharSet);
+ if ( !xConnection.is() || !xDrvMan.is() )
+ return nRet;
+ ::utl::DisposableComponent aConnectionHelper(xConnection);
+
+ // get dBase driver
+ uno::Reference< sdbc::XDriverAccess> xAccess(xDrvMan,uno::UNO_QUERY);
+ uno::Reference< sdbcx::XDataDefinitionSupplier > xDDSup( xAccess->getDriverByURL( xConnection->getMetaData()->getURL() ), uno::UNO_QUERY );
+ if ( !xDDSup.is() )
+ return SCERR_EXPORT_CONNECT;
+
+ // create table
+ uno::Reference<sdbcx::XTablesSupplier> xTablesSupp =xDDSup->getDataDefinitionByConnection( xConnection );
+ DBG_ASSERT( xTablesSupp.is(), "can't get Data Definition" );
+ if (!xTablesSupp.is()) return SCERR_EXPORT_CONNECT;
+
+ uno::Reference<container::XNameAccess> xTables = xTablesSupp->getTables();
+ DBG_ASSERT( xTables.is(), "can't get Tables" );
+ if (!xTables.is()) return SCERR_EXPORT_CONNECT;
+
+ uno::Reference<sdbcx::XDataDescriptorFactory> xTablesFact( xTables, uno::UNO_QUERY );
+ DBG_ASSERT( xTablesFact.is(), "can't get tables factory" );
+ if (!xTablesFact.is()) return SCERR_EXPORT_CONNECT;
+
+ uno::Reference<sdbcx::XAppend> xTablesAppend( xTables, uno::UNO_QUERY );
+ DBG_ASSERT( xTablesAppend.is(), "can't get tables XAppend" );
+ if (!xTablesAppend.is()) return SCERR_EXPORT_CONNECT;
+
+ uno::Reference<beans::XPropertySet> xTableDesc = xTablesFact->createDataDescriptor();
+ DBG_ASSERT( xTableDesc.is(), "can't get table descriptor" );
+ if (!xTableDesc.is()) return SCERR_EXPORT_CONNECT;
+
+ aAny <<= rtl::OUString( aTabName );
+ xTableDesc->setPropertyValue( rtl::OUString::createFromAscii(SC_DBPROP_NAME), aAny );
+
+ // create columns
+
+ uno::Reference<sdbcx::XColumnsSupplier> xColumnsSupp( xTableDesc, uno::UNO_QUERY );
+ DBG_ASSERT( xColumnsSupp.is(), "can't get columns supplier" );
+ if (!xColumnsSupp.is()) return SCERR_EXPORT_CONNECT;
+
+ uno::Reference<container::XNameAccess> xColumns = xColumnsSupp->getColumns();
+ DBG_ASSERT( xColumns.is(), "can't get columns" );
+ if (!xColumns.is()) return SCERR_EXPORT_CONNECT;
+
+ uno::Reference<sdbcx::XDataDescriptorFactory> xColumnsFact( xColumns, uno::UNO_QUERY );
+ DBG_ASSERT( xColumnsFact.is(), "can't get columns factory" );
+ if (!xColumnsFact.is()) return SCERR_EXPORT_CONNECT;
+
+ uno::Reference<sdbcx::XAppend> xColumnsAppend( xColumns, uno::UNO_QUERY );
+ DBG_ASSERT( xColumnsAppend.is(), "can't get columns XAppend" );
+ if (!xColumnsAppend.is()) return SCERR_EXPORT_CONNECT;
+
+ const rtl::OUString* pColNames = aColNames.getConstArray();
+ const sal_Int32* pColTypes = aColTypes.getConstArray();
+ const sal_Int32* pColLengths = aColLengths.getConstArray();
+ const sal_Int32* pColScales = aColScales.getConstArray();
+ long nCol;
+
+ for (nCol=0; nCol<nColCount; nCol++)
+ {
+ uno::Reference<beans::XPropertySet> xColumnDesc = xColumnsFact->createDataDescriptor();
+ DBG_ASSERT( xColumnDesc.is(), "can't get column descriptor" );
+ if (!xColumnDesc.is()) return SCERR_EXPORT_CONNECT;
+
+ aAny <<= pColNames[nCol];
+ xColumnDesc->setPropertyValue( rtl::OUString::createFromAscii(SC_DBPROP_NAME), aAny );
+
+ aAny <<= pColTypes[nCol];
+ xColumnDesc->setPropertyValue( rtl::OUString::createFromAscii(SC_DBPROP_TYPE), aAny );
+
+ aAny <<= pColLengths[nCol];
+ xColumnDesc->setPropertyValue( rtl::OUString::createFromAscii(SC_DBPROP_PRECISION), aAny );
+
+ aAny <<= pColScales[nCol];
+ xColumnDesc->setPropertyValue( rtl::OUString::createFromAscii(SC_DBPROP_SCALE), aAny );
+
+ xColumnsAppend->appendByDescriptor( xColumnDesc );
+ }
+
+ xTablesAppend->appendByDescriptor( xTableDesc );
+
+ // re-open connection
+// xConnection = xDrvMan->getConnectionWithInfo( aConnUrl, aProps );
+// DBG_ASSERT( xConnection.is(), "can't get Connection" );
+// if (!xConnection.is()) return SCERR_EXPORT_CONNECT;
+
+ // get row set for writing
+ uno::Reference<lang::XMultiServiceFactory> xFactory = comphelper::getProcessServiceFactory();
+ uno::Reference<sdbc::XRowSet> xRowSet( xFactory->createInstance(
+ rtl::OUString::createFromAscii( SC_SERVICE_ROWSET ) ),
+ uno::UNO_QUERY);
+ ::utl::DisposableComponent aRowSetHelper(xRowSet);
+ uno::Reference<beans::XPropertySet> xRowProp( xRowSet, uno::UNO_QUERY );
+ DBG_ASSERT( xRowProp.is(), "can't get RowSet" );
+ if (!xRowProp.is()) return SCERR_EXPORT_CONNECT;
+
+ aAny <<= xConnection;
+ xRowProp->setPropertyValue(
+ rtl::OUString::createFromAscii(SC_DBPROP_ACTIVECONNECTION), aAny );
+
+ aAny <<= (sal_Int32) sdb::CommandType::TABLE;
+ xRowProp->setPropertyValue(
+ rtl::OUString::createFromAscii(SC_DBPROP_COMMANDTYPE), aAny );
+
+ aAny <<= rtl::OUString( aTabName );
+ xRowProp->setPropertyValue(
+ rtl::OUString::createFromAscii(SC_DBPROP_COMMAND), aAny );
+
+ xRowSet->execute();
+
+ // write data rows
+
+ uno::Reference<sdbc::XResultSetUpdate> xResultUpdate( xRowSet, uno::UNO_QUERY );
+ DBG_ASSERT( xResultUpdate.is(), "can't get XResultSetUpdate" );
+ if (!xResultUpdate.is()) return SCERR_EXPORT_CONNECT;
+
+ uno::Reference<sdbc::XRowUpdate> xRowUpdate( xRowSet, uno::UNO_QUERY );
+ DBG_ASSERT( xRowUpdate.is(), "can't get XRowUpdate" );
+ if (!xRowUpdate.is()) return SCERR_EXPORT_CONNECT;
+
+ SCROW nFirstDataRow = ( bHasFieldNames ? nFirstRow + 1 : nFirstRow );
+ double fVal;
+
+ for ( nDocRow = nFirstDataRow; nDocRow <= nLastRow; nDocRow++ )
+ {
+ xResultUpdate->moveToInsertRow();
+
+ for (nCol=0; nCol<nColCount; nCol++)
+ {
+ SCCOL nDocCol = sal::static_int_cast<SCCOL>( nFirstCol + nCol );
+
+ switch (pColTypes[nCol])
+ {
+ case sdbc::DataType::LONGVARCHAR:
+ {
+ ScBaseCell* pCell;
+ aDocument.GetCell( nDocCol, nDocRow, nTab, pCell );
+ if ( pCell && pCell->GetCellType() != CELLTYPE_NOTE )
+ {
+ if ( pCell->GetCellType() == CELLTYPE_EDIT )
+ { // #60761# Paragraphs erhalten
+ lcl_getLongVarCharEditString( aString,
+ pCell, aEditEngine);
+ }
+ else
+ {
+ lcl_getLongVarCharString( aString, pCell,
+ aDocument, nDocCol, nDocRow, nTab,
+ *pNumFmt);
+ }
+ xRowUpdate->updateString( nCol+1, aString );
+ }
+ else
+ xRowUpdate->updateNull( nCol+1 );
+ }
+ break;
+
+ case sdbc::DataType::VARCHAR:
+ aDocument.GetString( nDocCol, nDocRow, nTab, aString );
+ xRowUpdate->updateString( nCol+1, aString );
+ if ( nErr == eERR_OK && pColLengths[nCol] < aString.Len() )
+ nErr = SCWARN_EXPORT_DATALOST;
+ break;
+
+ case sdbc::DataType::DATE:
+ {
+ aDocument.GetValue( nDocCol, nDocRow, nTab, fVal );
+ // #39274# zwischen 0 Wert und 0 kein Wert unterscheiden
+ BOOL bIsNull = (fVal == 0.0);
+ if ( bIsNull )
+ bIsNull = !aDocument.HasValueData( nDocCol, nDocRow, nTab );
+ if ( bIsNull )
+ {
+ xRowUpdate->updateNull( nCol+1 );
+ if ( nErr == eERR_OK &&
+ aDocument.HasStringData( nDocCol, nDocRow, nTab ) )
+ nErr = SCWARN_EXPORT_DATALOST;
+ }
+ else
+ {
+ Date aDate = *(pNumFmt->GetNullDate()); // tools date
+ aDate += (long)fVal; //! approxfloor?
+ util::Date aUnoDate( aDate.GetDay(), aDate.GetMonth(), aDate.GetYear() );
+ xRowUpdate->updateDate( nCol+1, aUnoDate );
+ }
+ }
+ break;
+
+ case sdbc::DataType::DECIMAL:
+ case sdbc::DataType::BIT:
+ aDocument.GetValue( nDocCol, nDocRow, nTab, fVal );
+ if ( fVal == 0.0 && nErr == eERR_OK &&
+ aDocument.HasStringData( nDocCol, nDocRow, nTab ) )
+ nErr = SCWARN_EXPORT_DATALOST;
+ if ( pColTypes[nCol] == sdbc::DataType::BIT )
+ xRowUpdate->updateBoolean( nCol+1, ( fVal != 0.0 ) );
+ else
+ xRowUpdate->updateDouble( nCol+1, fVal );
+ break;
+
+ default:
+ DBG_ERROR( "ScDocShell::DBaseExport: unknown FieldType" );
+ if ( nErr == eERR_OK )
+ nErr = SCWARN_EXPORT_DATALOST;
+ aDocument.GetValue( nDocCol, nDocRow, nTab, fVal );
+ xRowUpdate->updateDouble( nCol+1, fVal );
+ }
+ }
+
+ xResultUpdate->insertRow();
+
+ //! error handling and recovery of old
+ //! ScDocShell::SbaSdbExport is still missing!
+
+ if ( !aProgress.SetStateOnPercent( nDocRow - nFirstRow ) )
+ { // UserBreak
+ nErr = SCERR_EXPORT_DATA;
+ break;
+ }
+ }
+
+ comphelper::disposeComponent( xRowSet );
+ comphelper::disposeComponent( xConnection );
+ }
+ catch ( sdbc::SQLException& aException )
+ {
+ sal_Int32 nError = aException.ErrorCode;
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "ScDocShell::DBaseExport: SQLException ErrorCode: %d, SQLState: %s, Message: %s\n",
+ (int)nError, OUStringToOString( aException.SQLState,
+ RTL_TEXTENCODING_UTF8).getStr(), OUStringToOString(
+ aException.Message, RTL_TEXTENCODING_UTF8).getStr());
+#endif
+ if (nError == 22018 || nError == 22001)
+ {
+ // SQL error 22018: Character not in target encoding.
+ // SQL error 22001: String length exceeds field width (after encoding).
+ bool bEncErr = (nError == 22018);
+ bool bIsOctetTextEncoding = rtl_isOctetTextEncoding( eCharSet);
+ DBG_ASSERT( !bEncErr || bIsOctetTextEncoding, "ScDocShell::DBaseExport: encoding error and not an octect textencoding");
+ SCCOL nDocCol = nFirstCol;
+ const sal_Int32* pColTypes = aColTypes.getConstArray();
+ const sal_Int32* pColLengths = aColLengths.getConstArray();
+ ScHorizontalCellIterator aIter( &aDocument, nTab, nFirstCol,
+ nDocRow, nLastCol, nDocRow);
+ ScBaseCell* pCell = NULL;
+ bool bTest = true;
+ while (bTest && ((pCell = aIter.GetNext( nDocCol, nDocRow)) != NULL))
+ {
+ SCCOL nCol = nDocCol - nFirstCol;
+ switch (pColTypes[nCol])
+ {
+ case sdbc::DataType::LONGVARCHAR:
+ {
+ if ( pCell->GetCellType() != CELLTYPE_NOTE )
+ {
+ if ( pCell->GetCellType() == CELLTYPE_EDIT )
+ lcl_getLongVarCharEditString( aString,
+ pCell, aEditEngine);
+ else
+ lcl_getLongVarCharString( aString,
+ pCell, aDocument, nDocCol,
+ nDocRow, nTab, *pNumFmt);
+ }
+ }
+ break;
+
+ case sdbc::DataType::VARCHAR:
+ aDocument.GetString( nDocCol, nDocRow, nTab, aString);
+ break;
+
+ // NOTE: length of DECIMAL fields doesn't need to be
+ // checked here, the database driver adjusts the field
+ // width accordingly.
+
+ default:
+ bTest = false;
+ }
+ if (bTest)
+ {
+ sal_Int32 nLen;
+ if (bIsOctetTextEncoding)
+ {
+ rtl::OUString aOUString( aString);
+ rtl::OString aOString;
+ if (!aOUString.convertToString( &aOString, eCharSet,
+ RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
+ RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))
+ {
+ bTest = false;
+ bEncErr = true;
+ }
+ nLen = aOString.getLength();
+#if OSL_DEBUG_LEVEL > 1
+ if (!bTest)
+ fprintf( stderr, "ScDocShell::DBaseExport encoding error, string with default replacements: ``%s''\n",
+ OUStringToOString( aOUString, eCharSet).getStr());
+#endif
+ }
+ else
+ nLen = aString.Len() * sizeof(sal_Unicode);
+ if (!bEncErr &&
+ pColTypes[nCol] != sdbc::DataType::LONGVARCHAR &&
+ pColLengths[nCol] < nLen)
+ {
+ bTest = false;
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "ScDocShell::DBaseExport: field width: %d, encoded length: %d\n",
+ (int)pColLengths[nCol], (int)nLen);
+#endif
+ }
+ }
+ else
+ bTest = true;
+ }
+ String sPosition( ScAddress( nDocCol, nDocRow, nTab).GetColRowString());
+ String sEncoding( SvxTextEncodingTable().GetTextString( eCharSet));
+ nErr = *new TwoStringErrorInfo( (bEncErr ? SCERR_EXPORT_ENCODING :
+ SCERR_EXPORT_FIELDWIDTH), sPosition, sEncoding,
+ ERRCODE_BUTTON_OK | ERRCODE_MSG_ERROR);
+ }
+ else if ( aException.Message.getLength() )
+ nErr = *new StringErrorInfo( (SCERR_EXPORT_SQLEXCEPTION), aException.Message, ERRCODE_BUTTON_OK | ERRCODE_MSG_ERROR);
+ else
+ nErr = SCERR_EXPORT_DATA;
+ }
+ catch ( uno::Exception& )
+ {
+ DBG_ERROR("Unexpected exception in database");
+ nErr = ERRCODE_IO_GENERAL;
+ }
+
+ return nErr;
+}
+
+
diff --git a/sc/source/ui/docshell/docshimp.hxx b/sc/source/ui/docshell/docshimp.hxx
new file mode 100644
index 000000000000..6532c46d0835
--- /dev/null
+++ b/sc/source/ui/docshell/docshimp.hxx
@@ -0,0 +1,57 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+#ifndef SC_DOCSHELLIMP_HXX
+#define SC_DOCSHELLIMP_HXX
+
+#include <svtools/ctrltool.hxx>
+#include <sfx2/docinsert.hxx>
+#include <sfx2/request.hxx>
+
+struct DocShell_Impl
+{
+ bool bIgnoreLostRedliningWarning;
+ FontList* pFontList;
+ sfx2::DocumentInserter* pDocInserter;
+ SfxRequest* pRequest;
+
+ DocShell_Impl() :
+ bIgnoreLostRedliningWarning( false )
+ , pFontList( NULL )
+ , pDocInserter( NULL )
+ , pRequest( NULL )
+ {}
+
+ ~DocShell_Impl()
+ {
+ delete pFontList;
+ delete pDocInserter;
+ delete pRequest;
+ }
+};
+
+#endif
+
diff --git a/sc/source/ui/docshell/editable.cxx b/sc/source/ui/docshell/editable.cxx
new file mode 100644
index 000000000000..d381ff067a99
--- /dev/null
+++ b/sc/source/ui/docshell/editable.cxx
@@ -0,0 +1,162 @@
+/*************************************************************************
+ *
+ * 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 "editable.hxx"
+#include "document.hxx"
+#include "viewfunc.hxx"
+#include "globstr.hrc"
+
+//------------------------------------------------------------------
+
+ScEditableTester::ScEditableTester() :
+ bIsEditable( TRUE ),
+ bOnlyMatrix( TRUE )
+{
+}
+
+ScEditableTester::ScEditableTester( ScDocument* pDoc, SCTAB nTab,
+ SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow ) :
+ bIsEditable( TRUE ),
+ bOnlyMatrix( TRUE )
+{
+ TestBlock( pDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow );
+}
+
+ScEditableTester::ScEditableTester( ScDocument* pDoc,
+ SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
+ const ScMarkData& rMark ) :
+ bIsEditable( TRUE ),
+ bOnlyMatrix( TRUE )
+{
+ TestSelectedBlock( pDoc, nStartCol, nStartRow, nEndCol, nEndRow, rMark );
+}
+
+ScEditableTester::ScEditableTester( ScDocument* pDoc, const ScRange& rRange ) :
+ bIsEditable( TRUE ),
+ bOnlyMatrix( TRUE )
+{
+ TestRange( pDoc, rRange );
+}
+
+ScEditableTester::ScEditableTester( ScDocument* pDoc, const ScMarkData& rMark ) :
+ bIsEditable( TRUE ),
+ bOnlyMatrix( TRUE )
+{
+ TestSelection( pDoc, rMark );
+}
+
+ScEditableTester::ScEditableTester( ScViewFunc* pView ) :
+ bIsEditable( TRUE ),
+ bOnlyMatrix( TRUE )
+{
+ TestView( pView );
+}
+
+//------------------------------------------------------------------
+
+void ScEditableTester::TestBlock( ScDocument* pDoc, SCTAB nTab,
+ SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow )
+{
+ if ( bIsEditable || bOnlyMatrix )
+ {
+ BOOL bThisMatrix;
+ if ( !pDoc->IsBlockEditable( nTab, nStartCol, nStartRow, nEndCol, nEndRow, &bThisMatrix ) )
+ {
+ bIsEditable = FALSE;
+ if ( !bThisMatrix )
+ bOnlyMatrix = FALSE;
+ }
+ }
+}
+
+void ScEditableTester::TestSelectedBlock( ScDocument* pDoc,
+ SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
+ const ScMarkData& rMark )
+{
+ SCTAB nTabCount = pDoc->GetTableCount();
+ for (SCTAB nTab=0; nTab<nTabCount; nTab++)
+ if (rMark.GetTableSelect(nTab))
+ TestBlock( pDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow );
+}
+
+void ScEditableTester::TestRange( ScDocument* pDoc, const ScRange& rRange )
+{
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCTAB nStartTab = rRange.aStart.Tab();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ SCTAB nEndTab = rRange.aEnd.Tab();
+ for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
+ TestBlock( pDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow );
+}
+
+void ScEditableTester::TestSelection( ScDocument* pDoc, const ScMarkData& rMark )
+{
+ if ( bIsEditable || bOnlyMatrix )
+ {
+ BOOL bThisMatrix;
+ if ( !pDoc->IsSelectionEditable( rMark, &bThisMatrix ) )
+ {
+ bIsEditable = FALSE;
+ if ( !bThisMatrix )
+ bOnlyMatrix = FALSE;
+ }
+ }
+}
+
+void ScEditableTester::TestView( ScViewFunc* pView )
+{
+ if ( bIsEditable || bOnlyMatrix )
+ {
+ BOOL bThisMatrix;
+ if ( !pView->SelectionEditable( &bThisMatrix ) )
+ {
+ bIsEditable = FALSE;
+ if ( !bThisMatrix )
+ bOnlyMatrix = FALSE;
+ }
+ }
+}
+
+//------------------------------------------------------------------
+
+USHORT ScEditableTester::GetMessageId() const
+{
+ if (bIsEditable)
+ return 0;
+ else if (bOnlyMatrix)
+ return STR_MATRIXFRAGMENTERR;
+ else
+ return STR_PROTECTIONERR;
+}
+
diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx
new file mode 100644
index 000000000000..836d6cdf98e6
--- /dev/null
+++ b/sc/source/ui/docshell/externalrefmgr.cxx
@@ -0,0 +1,2378 @@
+/*************************************************************************
+ *
+ * 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 "externalrefmgr.hxx"
+#include "document.hxx"
+#include "token.hxx"
+#include "tokenarray.hxx"
+#include "address.hxx"
+#include "tablink.hxx"
+#include "docsh.hxx"
+#include "scextopt.hxx"
+#include "rangenam.hxx"
+#include "cell.hxx"
+#include "viewdata.hxx"
+#include "tabvwsh.hxx"
+#include "sc.hrc"
+
+#include "sfx2/app.hxx"
+#include "sfx2/docfilt.hxx"
+#include "sfx2/docfile.hxx"
+#include "sfx2/fcontnr.hxx"
+#include "sfx2/sfxsids.hrc"
+#include "sfx2/objsh.hxx"
+#include "svl/broadcast.hxx"
+#include "svl/smplhint.hxx"
+#include "svl/itemset.hxx"
+#include "svl/stritem.hxx"
+#include "svl/urihelper.hxx"
+#include "svl/zformat.hxx"
+#include "sfx2/linkmgr.hxx"
+#include "tools/urlobj.hxx"
+#include "unotools/ucbhelper.hxx"
+
+#include <memory>
+#include <algorithm>
+
+using ::std::auto_ptr;
+using ::com::sun::star::uno::Any;
+using ::rtl::OUString;
+using ::std::vector;
+using ::std::find;
+using ::std::find_if;
+using ::std::distance;
+using ::std::pair;
+using ::std::list;
+using ::std::unary_function;
+using namespace formula;
+
+#define SRCDOC_LIFE_SPAN 6000 // 1 minute (in 100th of a sec)
+#define SRCDOC_SCAN_INTERVAL 1000*5 // every 5 seconds (in msec)
+
+namespace {
+
+class TabNameSearchPredicate : public unary_function<bool, ScExternalRefCache::TableName>
+{
+public:
+ explicit TabNameSearchPredicate(const String& rSearchName) :
+ maSearchName(ScGlobal::pCharClass->upper(rSearchName))
+ {
+ }
+
+ bool operator()(const ScExternalRefCache::TableName& rTabNameSet) const
+ {
+ // Ok, I'm doing case insensitive search here.
+ return rTabNameSet.maUpperName.Equals(maSearchName);
+ }
+
+private:
+ String maSearchName;
+};
+
+class FindSrcFileByName : public unary_function<ScExternalRefManager::SrcFileData, bool>
+{
+public:
+ FindSrcFileByName(const String& rMatchName) :
+ mrMatchName(rMatchName)
+ {
+ }
+
+ bool operator()(const ScExternalRefManager::SrcFileData& rSrcData) const
+ {
+ return rSrcData.maFileName.Equals(mrMatchName);
+ }
+
+private:
+ const String& mrMatchName;
+};
+
+class NotifyLinkListener : public unary_function<ScExternalRefManager::LinkListener*, void>
+{
+public:
+ NotifyLinkListener(sal_uInt16 nFileId, ScExternalRefManager::LinkUpdateType eType) :
+ mnFileId(nFileId), meType(eType) {}
+
+ NotifyLinkListener(const NotifyLinkListener& r) :
+ mnFileId(r.mnFileId), meType(r.meType) {}
+
+ void operator() (ScExternalRefManager::LinkListener* p) const
+ {
+ p->notify(mnFileId, meType);
+ }
+private:
+ sal_uInt16 mnFileId;
+ ScExternalRefManager::LinkUpdateType meType;
+};
+
+}
+
+// ============================================================================
+
+ScExternalRefCache::Table::Table()
+ : meReferenced( REFERENCED_MARKED )
+ // Prevent accidental data loss due to lack of knowledge.
+{
+}
+
+ScExternalRefCache::Table::~Table()
+{
+}
+
+void ScExternalRefCache::Table::setReferencedFlag( ScExternalRefCache::Table::ReferencedFlag eFlag )
+{
+ meReferenced = eFlag;
+}
+
+void ScExternalRefCache::Table::setReferenced( bool bReferenced )
+{
+ if (meReferenced != REFERENCED_PERMANENT)
+ meReferenced = (bReferenced ? REFERENCED_MARKED : UNREFERENCED);
+}
+
+ScExternalRefCache::Table::ReferencedFlag ScExternalRefCache::Table::getReferencedFlag() const
+{
+ return meReferenced;
+}
+
+bool ScExternalRefCache::Table::isReferenced() const
+{
+ return meReferenced != UNREFERENCED;
+}
+
+void ScExternalRefCache::Table::setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex)
+{
+ using ::std::pair;
+ RowsDataType::iterator itrRow = maRows.find(nRow);
+ if (itrRow == maRows.end())
+ {
+ // This row does not exist yet.
+ pair<RowsDataType::iterator, bool> res = maRows.insert(
+ RowsDataType::value_type(nRow, RowDataType()));
+
+ if (!res.second)
+ return;
+
+ itrRow = res.first;
+ }
+
+ // Insert this token into the specified column location. I don't need to
+ // check for existing data. Just overwrite it.
+ RowDataType& rRow = itrRow->second;
+ ScExternalRefCache::Cell aCell;
+ aCell.mxToken = pToken;
+ aCell.mnFmtIndex = nFmtIndex;
+ rRow.insert(RowDataType::value_type(nCol, aCell));
+}
+
+ScExternalRefCache::TokenRef ScExternalRefCache::Table::getCell(SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex) const
+{
+ RowsDataType::const_iterator itrTable = maRows.find(nRow);
+ if (itrTable == maRows.end())
+ {
+ // this table doesn't have the specified row.
+ return TokenRef();
+ }
+
+ const RowDataType& rRowData = itrTable->second;
+ RowDataType::const_iterator itrRow = rRowData.find(nCol);
+ if (itrRow == rRowData.end())
+ {
+ // this row doesn't have the specified column.
+ return TokenRef();
+ }
+
+ const Cell& rCell = itrRow->second;
+ if (pnFmtIndex)
+ *pnFmtIndex = rCell.mnFmtIndex;
+
+ return rCell.mxToken;
+}
+
+bool ScExternalRefCache::Table::hasRow( SCROW nRow ) const
+{
+ RowsDataType::const_iterator itrRow = maRows.find(nRow);
+ return itrRow != maRows.end();
+}
+
+void ScExternalRefCache::Table::getAllRows(vector<SCROW>& rRows) const
+{
+ vector<SCROW> aRows;
+ aRows.reserve(maRows.size());
+ RowsDataType::const_iterator itr = maRows.begin(), itrEnd = maRows.end();
+ for (; itr != itrEnd; ++itr)
+ aRows.push_back(itr->first);
+
+ // hash map is not ordered, so we need to explicitly sort it.
+ ::std::sort(aRows.begin(), aRows.end());
+ rRows.swap(aRows);
+}
+
+void ScExternalRefCache::Table::getAllCols(SCROW nRow, vector<SCCOL>& rCols) const
+{
+ RowsDataType::const_iterator itrRow = maRows.find(nRow);
+ if (itrRow == maRows.end())
+ // this table doesn't have the specified row.
+ return;
+
+ const RowDataType& rRowData = itrRow->second;
+ vector<SCCOL> aCols;
+ aCols.reserve(rRowData.size());
+ RowDataType::const_iterator itrCol = rRowData.begin(), itrColEnd = rRowData.end();
+ for (; itrCol != itrColEnd; ++itrCol)
+ aCols.push_back(itrCol->first);
+
+ // hash map is not ordered, so we need to explicitly sort it.
+ ::std::sort(aCols.begin(), aCols.end());
+ rCols.swap(aCols);
+}
+
+void ScExternalRefCache::Table::getAllNumberFormats(vector<sal_uInt32>& rNumFmts) const
+{
+ RowsDataType::const_iterator itrRow = maRows.begin(), itrRowEnd = maRows.end();
+ for (; itrRow != itrRowEnd; ++itrRow)
+ {
+ const RowDataType& rRowData = itrRow->second;
+ RowDataType::const_iterator itrCol = rRowData.begin(), itrColEnd = rRowData.end();
+ for (; itrCol != itrColEnd; ++itrCol)
+ {
+ const Cell& rCell = itrCol->second;
+ rNumFmts.push_back(rCell.mnFmtIndex);
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+ScExternalRefCache::TableName::TableName(const String& rUpper, const String& rReal) :
+ maUpperName(rUpper), maRealName(rReal)
+{
+}
+
+// ----------------------------------------------------------------------------
+
+ScExternalRefCache::CellFormat::CellFormat() :
+ mbIsSet(false), mnType(NUMBERFORMAT_ALL), mnIndex(0)
+{
+}
+
+// ----------------------------------------------------------------------------
+
+ScExternalRefCache::ScExternalRefCache()
+{
+}
+ScExternalRefCache::~ScExternalRefCache()
+{
+}
+
+const String* ScExternalRefCache::getRealTableName(sal_uInt16 nFileId, const String& rTabName) const
+{
+ DocDataType::const_iterator itrDoc = maDocs.find(nFileId);
+ if (itrDoc == maDocs.end())
+ {
+ // specified document is not cached.
+ return NULL;
+ }
+
+ const DocItem& rDoc = itrDoc->second;
+ TableNameIndexMap::const_iterator itrTabId = rDoc.maTableNameIndex.find(
+ ScGlobal::pCharClass->upper(rTabName));
+ if (itrTabId == rDoc.maTableNameIndex.end())
+ {
+ // the specified table is not in cache.
+ return NULL;
+ }
+
+ return &rDoc.maTableNames[itrTabId->second].maRealName;
+}
+
+const String* ScExternalRefCache::getRealRangeName(sal_uInt16 nFileId, const String& rRangeName) const
+{
+ DocDataType::const_iterator itrDoc = maDocs.find(nFileId);
+ if (itrDoc == maDocs.end())
+ {
+ // specified document is not cached.
+ return NULL;
+ }
+
+ const DocItem& rDoc = itrDoc->second;
+ NamePairMap::const_iterator itr = rDoc.maRealRangeNameMap.find(
+ ScGlobal::pCharClass->upper(rRangeName));
+ if (itr == rDoc.maRealRangeNameMap.end())
+ // range name not found.
+ return NULL;
+
+ return &itr->second;
+}
+
+ScExternalRefCache::TokenRef ScExternalRefCache::getCellData(
+ sal_uInt16 nFileId, const String& rTabName, SCCOL nCol, SCROW nRow,
+ bool bEmptyCellOnNull, bool bWriteEmpty, sal_uInt32* pnFmtIndex)
+{
+ DocDataType::const_iterator itrDoc = maDocs.find(nFileId);
+ if (itrDoc == maDocs.end())
+ {
+ // specified document is not cached.
+ return TokenRef();
+ }
+
+ const DocItem& rDoc = itrDoc->second;
+ TableNameIndexMap::const_iterator itrTabId = rDoc.maTableNameIndex.find(
+ ScGlobal::pCharClass->upper(rTabName));
+ if (itrTabId == rDoc.maTableNameIndex.end())
+ {
+ // the specified table is not in cache.
+ return TokenRef();
+ }
+
+ const TableTypeRef& pTableData = rDoc.maTables[itrTabId->second];
+ if (!pTableData.get())
+ {
+ // the table data is not instantiated yet.
+ return TokenRef();
+ }
+
+ TokenRef pToken = pTableData->getCell(nCol, nRow, pnFmtIndex);
+ if (!pToken && bEmptyCellOnNull)
+ {
+ pToken.reset(new ScEmptyCellToken(false, false));
+ if (bWriteEmpty)
+ pTableData->setCell(nCol, nRow, pToken);
+ }
+ return pToken;
+}
+
+ScExternalRefCache::TokenArrayRef ScExternalRefCache::getCellRangeData(
+ sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange, bool bEmptyCellOnNull, bool bWriteEmpty)
+{
+ DocDataType::iterator itrDoc = maDocs.find(nFileId);
+ if (itrDoc == maDocs.end())
+ // specified document is not cached.
+ return TokenArrayRef();
+
+ DocItem& rDoc = itrDoc->second;
+
+ TableNameIndexMap::iterator itrTabId = rDoc.maTableNameIndex.find(
+ ScGlobal::pCharClass->upper(rTabName));
+ if (itrTabId == rDoc.maTableNameIndex.end())
+ // the specified table is not in cache.
+ return TokenArrayRef();
+
+ const ScAddress& s = rRange.aStart;
+ const ScAddress& e = rRange.aEnd;
+
+ SCTAB nTab1 = s.Tab(), nTab2 = e.Tab();
+ SCCOL nCol1 = s.Col(), nCol2 = e.Col();
+ SCROW nRow1 = s.Row(), nRow2 = e.Row();
+
+ // Make sure I have all the tables cached.
+ size_t nTabFirstId = itrTabId->second;
+ size_t nTabLastId = nTabFirstId + nTab2 - nTab1;
+ if (nTabLastId >= rDoc.maTables.size())
+ // not all tables are cached.
+ return TokenArrayRef();
+
+ ScRange aCacheRange( nCol1, nRow1, static_cast<SCTAB>(nTabFirstId), nCol2, nRow2, static_cast<SCTAB>(nTabLastId));
+ RangeArrayMap::const_iterator itrRange = rDoc.maRangeArrays.find( aCacheRange);
+ if (itrRange != rDoc.maRangeArrays.end())
+ {
+ return itrRange->second;
+ }
+
+ TokenArrayRef pArray(new ScTokenArray);
+ bool bFirstTab = true;
+ for (size_t nTab = nTabFirstId; nTab <= nTabLastId; ++nTab)
+ {
+ TableTypeRef pTab = rDoc.maTables[nTab];
+ if (!pTab.get())
+ return TokenArrayRef();
+
+ ScMatrixRef xMat = new ScMatrix(
+ static_cast<SCSIZE>(nCol2-nCol1+1), static_cast<SCSIZE>(nRow2-nRow1+1));
+
+ for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
+ {
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+ {
+ TokenRef pToken = pTab->getCell(nCol, nRow);
+ if (!pToken)
+ {
+ if (bEmptyCellOnNull)
+ {
+ pToken.reset(new ScEmptyCellToken(false, false));
+ if (bWriteEmpty)
+ pTab->setCell(nCol, nRow, pToken);
+ }
+ else
+ return TokenArrayRef();
+ }
+
+ SCSIZE nC = nCol - nCol1, nR = nRow - nRow1;
+ switch (pToken->GetType())
+ {
+ case svDouble:
+ xMat->PutDouble(pToken->GetDouble(), nC, nR);
+ break;
+ case svString:
+ xMat->PutString(pToken->GetString(), nC, nR);
+ break;
+ default:
+ xMat->PutEmpty(nC, nR);
+ }
+ }
+ }
+
+ if (!bFirstTab)
+ pArray->AddOpCode(ocSep);
+
+ ScMatrix* pMat2 = xMat;
+ ScMatrixToken aToken(pMat2);
+ pArray->AddToken(aToken);
+
+ bFirstTab = false;
+ }
+ rDoc.maRangeArrays.insert( RangeArrayMap::value_type( aCacheRange, pArray));
+ return pArray;
+}
+
+ScExternalRefCache::TokenArrayRef ScExternalRefCache::getRangeNameTokens(sal_uInt16 nFileId, const String& rName)
+{
+ DocItem* pDoc = getDocItem(nFileId);
+ if (!pDoc)
+ return TokenArrayRef();
+
+ RangeNameMap& rMap = pDoc->maRangeNames;
+ RangeNameMap::const_iterator itr = rMap.find(
+ ScGlobal::pCharClass->upper(rName));
+ if (itr == rMap.end())
+ return TokenArrayRef();
+
+ return itr->second;
+}
+
+void ScExternalRefCache::setRangeNameTokens(sal_uInt16 nFileId, const String& rName, TokenArrayRef pArray)
+{
+ DocItem* pDoc = getDocItem(nFileId);
+ if (!pDoc)
+ return;
+
+ String aUpperName = ScGlobal::pCharClass->upper(rName);
+ RangeNameMap& rMap = pDoc->maRangeNames;
+ rMap.insert(RangeNameMap::value_type(aUpperName, pArray));
+ pDoc->maRealRangeNameMap.insert(NamePairMap::value_type(aUpperName, rName));
+}
+
+void ScExternalRefCache::setCellData(sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol,
+ TokenRef pToken, sal_uInt32 nFmtIndex)
+{
+ if (!isDocInitialized(nFileId))
+ return;
+
+ using ::std::pair;
+ DocItem* pDocItem = getDocItem(nFileId);
+ if (!pDocItem)
+ return;
+
+ DocItem& rDoc = *pDocItem;
+
+ // See if the table by this name already exists.
+ TableNameIndexMap::iterator itrTabName = rDoc.maTableNameIndex.find(
+ ScGlobal::pCharClass->upper(rTabName));
+ if (itrTabName == rDoc.maTableNameIndex.end())
+ // Table not found. Maybe the table name or the file id is wrong ???
+ return;
+
+ TableTypeRef& pTableData = rDoc.maTables[itrTabName->second];
+ if (!pTableData.get())
+ pTableData.reset(new Table);
+
+ pTableData->setCell(nCol, nRow, pToken, nFmtIndex);
+}
+
+void ScExternalRefCache::setCellRangeData(sal_uInt16 nFileId, const ScRange& rRange, const vector<SingleRangeData>& rData,
+ TokenArrayRef pArray)
+{
+ using ::std::pair;
+ if (rData.empty() || !isDocInitialized(nFileId))
+ // nothing to cache
+ return;
+
+ // First, get the document item for the given file ID.
+ DocItem* pDocItem = getDocItem(nFileId);
+ if (!pDocItem)
+ return;
+
+ DocItem& rDoc = *pDocItem;
+
+ // Now, find the table position of the first table to cache.
+ const String& rFirstTabName = rData.front().maTableName;
+ TableNameIndexMap::iterator itrTabName = rDoc.maTableNameIndex.find(
+ ScGlobal::pCharClass->upper(rFirstTabName));
+ if (itrTabName == rDoc.maTableNameIndex.end())
+ {
+ // table index not found.
+ return;
+ }
+
+ size_t nTabFirstId = itrTabName->second;
+ SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row();
+ SCCOL nCol1 = rRange.aStart.Col(), nCol2 = rRange.aEnd.Col();
+ vector<SingleRangeData>::const_iterator itrDataBeg = rData.begin(), itrDataEnd = rData.end();
+ for (vector<SingleRangeData>::const_iterator itrData = itrDataBeg; itrData != itrDataEnd; ++itrData)
+ {
+ size_t i = nTabFirstId + ::std::distance(itrDataBeg, itrData);
+ TableTypeRef& pTabData = rDoc.maTables[i];
+ if (!pTabData.get())
+ pTabData.reset(new Table);
+
+ for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
+ {
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+ {
+ SCSIZE nC = nCol - nCol1, nR = nRow - nRow1;
+ TokenRef pToken;
+ const ScMatrixRef& pMat = itrData->mpRangeData;
+ if (pMat->IsValue(nC, nR))
+ pToken.reset(new formula::FormulaDoubleToken(pMat->GetDouble(nC, nR)));
+ else if (pMat->IsString(nC, nR))
+ pToken.reset(new formula::FormulaStringToken(pMat->GetString(nC, nR)));
+ else
+ pToken.reset(new ScEmptyCellToken(false, false));
+
+ pTabData->setCell(nCol, nRow, pToken);
+ }
+ }
+ }
+
+ size_t nTabLastId = nTabFirstId + rRange.aEnd.Tab() - rRange.aStart.Tab();
+ ScRange aCacheRange( nCol1, nRow1, static_cast<SCTAB>(nTabFirstId), nCol2, nRow2, static_cast<SCTAB>(nTabLastId));
+ rDoc.maRangeArrays.insert( RangeArrayMap::value_type( aCacheRange, pArray));
+}
+
+bool ScExternalRefCache::isDocInitialized(sal_uInt16 nFileId)
+{
+ DocItem* pDoc = getDocItem(nFileId);
+ if (!pDoc)
+ return false;
+
+ return pDoc->mbInitFromSource;
+}
+
+static bool lcl_getTableDataIndex(const ScExternalRefCache::TableNameIndexMap& rMap, const String& rName, size_t& rIndex)
+{
+ ScExternalRefCache::TableNameIndexMap::const_iterator itr = rMap.find(rName);
+ if (itr == rMap.end())
+ return false;
+
+ rIndex = itr->second;
+ return true;
+}
+
+void ScExternalRefCache::initializeDoc(sal_uInt16 nFileId, const vector<String>& rTabNames)
+{
+ DocItem* pDoc = getDocItem(nFileId);
+ if (!pDoc)
+ return;
+
+ size_t n = rTabNames.size();
+
+ // table name list - the list must include all table names in the source
+ // document and only to be populated when loading the source document, not
+ // when loading cached data from, say, Excel XCT/CRN records.
+ vector<TableName> aNewTabNames;
+ aNewTabNames.reserve(n);
+ for (vector<String>::const_iterator itr = rTabNames.begin(), itrEnd = rTabNames.end();
+ itr != itrEnd; ++itr)
+ {
+ TableName aNameItem(ScGlobal::pCharClass->upper(*itr), *itr);
+ aNewTabNames.push_back(aNameItem);
+ }
+ pDoc->maTableNames.swap(aNewTabNames);
+
+ // data tables - preserve any existing data that may have been set during
+ // file import.
+ vector<TableTypeRef> aNewTables(n);
+ for (size_t i = 0; i < n; ++i)
+ {
+ size_t nIndex;
+ if (lcl_getTableDataIndex(pDoc->maTableNameIndex, pDoc->maTableNames[i].maUpperName, nIndex))
+ {
+ aNewTables[i] = pDoc->maTables[nIndex];
+ }
+ }
+ pDoc->maTables.swap(aNewTables);
+
+ // name index map
+ TableNameIndexMap aNewNameIndex;
+ for (size_t i = 0; i < n; ++i)
+ aNewNameIndex.insert(TableNameIndexMap::value_type(pDoc->maTableNames[i].maUpperName, i));
+ pDoc->maTableNameIndex.swap(aNewNameIndex);
+
+ pDoc->mbInitFromSource = true;
+}
+
+String ScExternalRefCache::getTableName(sal_uInt16 nFileId, size_t nCacheId) const
+{
+ if( DocItem* pDoc = getDocItem( nFileId ) )
+ if( nCacheId < pDoc->maTableNames.size() )
+ return pDoc->maTableNames[ nCacheId ].maRealName;
+ return EMPTY_STRING;
+}
+
+void ScExternalRefCache::getAllTableNames(sal_uInt16 nFileId, vector<String>& rTabNames) const
+{
+ rTabNames.clear();
+ DocItem* pDoc = getDocItem(nFileId);
+ if (!pDoc)
+ return;
+
+ size_t n = pDoc->maTableNames.size();
+ rTabNames.reserve(n);
+ for (vector<TableName>::const_iterator itr = pDoc->maTableNames.begin(), itrEnd = pDoc->maTableNames.end();
+ itr != itrEnd; ++itr)
+ rTabNames.push_back(itr->maRealName);
+}
+
+SCsTAB ScExternalRefCache::getTabSpan( sal_uInt16 nFileId, const String& rStartTabName, const String& rEndTabName ) const
+{
+ DocItem* pDoc = getDocItem(nFileId);
+ if (!pDoc)
+ return -1;
+
+ vector<TableName>::const_iterator itrBeg = pDoc->maTableNames.begin();
+ vector<TableName>::const_iterator itrEnd = pDoc->maTableNames.end();
+
+ vector<TableName>::const_iterator itrStartTab = ::std::find_if( itrBeg, itrEnd,
+ TabNameSearchPredicate( rStartTabName));
+ if (itrStartTab == itrEnd)
+ return -1;
+
+ vector<TableName>::const_iterator itrEndTab = ::std::find_if( itrBeg, itrEnd,
+ TabNameSearchPredicate( rEndTabName));
+ if (itrEndTab == itrEnd)
+ return 0;
+
+ size_t nStartDist = ::std::distance( itrBeg, itrStartTab);
+ size_t nEndDist = ::std::distance( itrBeg, itrEndTab);
+ return nStartDist <= nEndDist ? static_cast<SCsTAB>(nEndDist - nStartDist + 1) : -static_cast<SCsTAB>(nStartDist - nEndDist + 1);
+}
+
+void ScExternalRefCache::getAllNumberFormats(vector<sal_uInt32>& rNumFmts) const
+{
+ using ::std::sort;
+ using ::std::unique;
+
+ vector<sal_uInt32> aNumFmts;
+ for (DocDataType::const_iterator itrDoc = maDocs.begin(), itrDocEnd = maDocs.end();
+ itrDoc != itrDocEnd; ++itrDoc)
+ {
+ const vector<TableTypeRef>& rTables = itrDoc->second.maTables;
+ for (vector<TableTypeRef>::const_iterator itrTab = rTables.begin(), itrTabEnd = rTables.end();
+ itrTab != itrTabEnd; ++itrTab)
+ {
+ TableTypeRef pTab = *itrTab;
+ if (!pTab)
+ continue;
+
+ pTab->getAllNumberFormats(aNumFmts);
+ }
+ }
+
+ // remove duplicates.
+ sort(aNumFmts.begin(), aNumFmts.end());
+ aNumFmts.erase(unique(aNumFmts.begin(), aNumFmts.end()), aNumFmts.end());
+ rNumFmts.swap(aNumFmts);
+}
+
+bool ScExternalRefCache::hasCacheTable(sal_uInt16 nFileId, const String& rTabName) const
+{
+ DocItem* pDoc = getDocItem(nFileId);
+ if (!pDoc)
+ return false;
+
+ String aUpperName = ScGlobal::pCharClass->upper(rTabName);
+ vector<TableName>::const_iterator itrBeg = pDoc->maTableNames.begin(), itrEnd = pDoc->maTableNames.end();
+ vector<TableName>::const_iterator itr = ::std::find_if(
+ itrBeg, itrEnd, TabNameSearchPredicate(aUpperName));
+
+ return itr != itrEnd;
+}
+
+size_t ScExternalRefCache::getCacheTableCount(sal_uInt16 nFileId) const
+{
+ DocItem* pDoc = getDocItem(nFileId);
+ return pDoc ? pDoc->maTables.size() : 0;
+}
+
+bool ScExternalRefCache::setCacheDocReferenced( sal_uInt16 nFileId )
+{
+ DocItem* pDocItem = getDocItem(nFileId);
+ if (!pDocItem)
+ return areAllCacheTablesReferenced();
+
+ for (::std::vector<TableTypeRef>::iterator itrTab = pDocItem->maTables.begin();
+ itrTab != pDocItem->maTables.end(); ++itrTab)
+ {
+ if ((*itrTab).get())
+ (*itrTab)->setReferenced( true);
+ }
+ addCacheDocToReferenced( nFileId);
+ return areAllCacheTablesReferenced();
+}
+
+bool ScExternalRefCache::setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName, size_t nSheets, bool bPermanent )
+{
+ DocItem* pDoc = getDocItem(nFileId);
+ if (pDoc)
+ {
+ size_t nIndex = 0;
+ String aTabNameUpper = ScGlobal::pCharClass->upper( rTabName);
+ if (lcl_getTableDataIndex( pDoc->maTableNameIndex, aTabNameUpper, nIndex))
+ {
+ size_t nStop = ::std::min( nIndex + nSheets, pDoc->maTables.size());
+ for (size_t i = nIndex; i < nStop; ++i)
+ {
+ TableTypeRef pTab = pDoc->maTables[i];
+ if (pTab.get())
+ {
+ Table::ReferencedFlag eNewFlag = (bPermanent ?
+ Table::REFERENCED_PERMANENT :
+ Table::REFERENCED_MARKED);
+ Table::ReferencedFlag eOldFlag = pTab->getReferencedFlag();
+ if (eOldFlag != Table::REFERENCED_PERMANENT && eNewFlag != eOldFlag)
+ {
+ pTab->setReferencedFlag( eNewFlag);
+ addCacheTableToReferenced( nFileId, i);
+ }
+ }
+ }
+ }
+ }
+ return areAllCacheTablesReferenced();
+}
+
+void ScExternalRefCache::setCacheTableReferencedPermanently( sal_uInt16 nFileId, const String& rTabName, size_t nSheets )
+{
+ DocItem* pDoc = getDocItem(nFileId);
+ if (pDoc)
+ {
+ size_t nIndex = 0;
+ String aTabNameUpper = ScGlobal::pCharClass->upper( rTabName);
+ if (lcl_getTableDataIndex( pDoc->maTableNameIndex, aTabNameUpper, nIndex))
+ {
+ size_t nStop = ::std::min( nIndex + nSheets, pDoc->maTables.size());
+ for (size_t i = nIndex; i < nStop; ++i)
+ {
+ TableTypeRef pTab = pDoc->maTables[i];
+ if (pTab.get())
+ pTab->setReferencedFlag( Table::REFERENCED_PERMANENT);
+ }
+ }
+ }
+}
+
+void ScExternalRefCache::setAllCacheTableReferencedStati( bool bReferenced )
+{
+ if (bReferenced)
+ {
+ maReferenced.reset(0);
+ for (DocDataType::iterator itrDoc = maDocs.begin(); itrDoc != maDocs.end(); ++itrDoc)
+ {
+ ScExternalRefCache::DocItem& rDocItem = (*itrDoc).second;
+ for (::std::vector<TableTypeRef>::iterator itrTab = rDocItem.maTables.begin();
+ itrTab != rDocItem.maTables.end(); ++itrTab)
+ {
+ if ((*itrTab).get())
+ (*itrTab)->setReferenced( true);
+ }
+ }
+ }
+ else
+ {
+ size_t nDocs = 0;
+ for (DocDataType::const_iterator itrDoc = maDocs.begin(); itrDoc != maDocs.end(); ++itrDoc)
+ {
+ if (nDocs <= (*itrDoc).first)
+ nDocs = (*itrDoc).first + 1;
+ }
+ maReferenced.reset( nDocs);
+
+ for (DocDataType::iterator itrDoc = maDocs.begin(); itrDoc != maDocs.end(); ++itrDoc)
+ {
+ ScExternalRefCache::DocItem& rDocItem = (*itrDoc).second;
+ sal_uInt16 nFileId = (*itrDoc).first;
+ size_t nTables = rDocItem.maTables.size();
+ ReferencedStatus::DocReferenced & rDocReferenced = maReferenced.maDocs[nFileId];
+ // All referenced => non-existing tables evaluate as completed.
+ rDocReferenced.maTables.resize( nTables, true);
+ for (size_t i=0; i < nTables; ++i)
+ {
+ TableTypeRef & xTab = rDocItem.maTables[i];
+ if (xTab.get())
+ {
+ if (xTab->getReferencedFlag() == Table::REFERENCED_PERMANENT)
+ addCacheTableToReferenced( nFileId, i);
+ else
+ {
+ xTab->setReferencedFlag( Table::UNREFERENCED);
+ rDocReferenced.maTables[i] = false;
+ rDocReferenced.mbAllTablesReferenced = false;
+ // An addCacheTableToReferenced() actually may have
+ // resulted in mbAllReferenced been set. Clear it.
+ maReferenced.mbAllReferenced = false;
+ }
+ }
+ }
+ }
+ }
+}
+
+void ScExternalRefCache::addCacheTableToReferenced( sal_uInt16 nFileId, size_t nIndex )
+{
+ if (nFileId >= maReferenced.maDocs.size())
+ return;
+
+ ::std::vector<bool> & rTables = maReferenced.maDocs[nFileId].maTables;
+ size_t nTables = rTables.size();
+ if (nIndex >= nTables)
+ return;
+
+ if (!rTables[nIndex])
+ {
+ rTables[nIndex] = true;
+ size_t i = 0;
+ while (i < nTables && rTables[i])
+ ++i;
+ if (i == nTables)
+ {
+ maReferenced.maDocs[nFileId].mbAllTablesReferenced = true;
+ maReferenced.checkAllDocs();
+ }
+ }
+}
+
+void ScExternalRefCache::addCacheDocToReferenced( sal_uInt16 nFileId )
+{
+ if (nFileId >= maReferenced.maDocs.size())
+ return;
+
+ if (!maReferenced.maDocs[nFileId].mbAllTablesReferenced)
+ {
+ ::std::vector<bool> & rTables = maReferenced.maDocs[nFileId].maTables;
+ size_t nSize = rTables.size();
+ for (size_t i=0; i < nSize; ++i)
+ rTables[i] = true;
+ maReferenced.maDocs[nFileId].mbAllTablesReferenced = true;
+ maReferenced.checkAllDocs();
+ }
+}
+
+bool ScExternalRefCache::areAllCacheTablesReferenced() const
+{
+ return maReferenced.mbAllReferenced;
+}
+
+ScExternalRefCache::ReferencedStatus::ReferencedStatus() :
+ mbAllReferenced(false)
+{
+ reset(0);
+}
+
+ScExternalRefCache::ReferencedStatus::ReferencedStatus( size_t nDocs ) :
+ mbAllReferenced(false)
+{
+ reset( nDocs);
+}
+
+void ScExternalRefCache::ReferencedStatus::reset( size_t nDocs )
+{
+ if (nDocs)
+ {
+ mbAllReferenced = false;
+ DocReferencedVec aRefs( nDocs);
+ maDocs.swap( aRefs);
+ }
+ else
+ {
+ mbAllReferenced = true;
+ DocReferencedVec aRefs;
+ maDocs.swap( aRefs);
+ }
+}
+
+void ScExternalRefCache::ReferencedStatus::checkAllDocs()
+{
+ for (DocReferencedVec::const_iterator itr = maDocs.begin(); itr != maDocs.end(); ++itr)
+ {
+ if (!(*itr).mbAllTablesReferenced)
+ return;
+ }
+ mbAllReferenced = true;
+}
+
+ScExternalRefCache::TableTypeRef ScExternalRefCache::getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const
+{
+ DocItem* pDoc = getDocItem(nFileId);
+ if (!pDoc || nTabIndex >= pDoc->maTables.size())
+ return TableTypeRef();
+
+ return pDoc->maTables[nTabIndex];
+}
+
+ScExternalRefCache::TableTypeRef ScExternalRefCache::getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew, size_t* pnIndex)
+{
+ // In API, the index is transported as cached sheet ID of type sal_Int32 in
+ // sheet::SingleReference.Sheet or sheet::ComplexReference.Reference1.Sheet
+ // in a sheet::FormulaToken, choose a sensible value for N/A. Effectively
+ // being 0xffffffff
+ const size_t nNotAvailable = static_cast<size_t>( static_cast<sal_Int32>( -1));
+
+ DocItem* pDoc = getDocItem(nFileId);
+ if (!pDoc)
+ {
+ if (pnIndex) *pnIndex = nNotAvailable;
+ return TableTypeRef();
+ }
+
+ DocItem& rDoc = *pDoc;
+
+ size_t nIndex;
+ String aTabNameUpper = ScGlobal::pCharClass->upper(rTabName);
+ if (lcl_getTableDataIndex(rDoc.maTableNameIndex, aTabNameUpper, nIndex))
+ {
+ // specified table found.
+ if( pnIndex ) *pnIndex = nIndex;
+ return rDoc.maTables[nIndex];
+ }
+
+ if (!bCreateNew)
+ {
+ if (pnIndex) *pnIndex = nNotAvailable;
+ return TableTypeRef();
+ }
+
+ // Specified table doesn't exist yet. Create one.
+ nIndex = rDoc.maTables.size();
+ if( pnIndex ) *pnIndex = nIndex;
+ TableTypeRef pTab(new Table);
+ rDoc.maTables.push_back(pTab);
+ rDoc.maTableNames.push_back(TableName(aTabNameUpper, rTabName));
+ rDoc.maTableNameIndex.insert(
+ TableNameIndexMap::value_type(aTabNameUpper, nIndex));
+ return pTab;
+}
+
+void ScExternalRefCache::clearCache(sal_uInt16 nFileId)
+{
+ maDocs.erase(nFileId);
+}
+
+ScExternalRefCache::DocItem* ScExternalRefCache::getDocItem(sal_uInt16 nFileId) const
+{
+ using ::std::pair;
+ DocDataType::iterator itrDoc = maDocs.find(nFileId);
+ if (itrDoc == maDocs.end())
+ {
+ // specified document is not cached.
+ pair<DocDataType::iterator, bool> res = maDocs.insert(
+ DocDataType::value_type(nFileId, DocItem()));
+
+ if (!res.second)
+ // insertion failed.
+ return NULL;
+
+ itrDoc = res.first;
+ }
+
+ return &itrDoc->second;
+}
+
+// ============================================================================
+
+ScExternalRefLink::ScExternalRefLink(ScDocument* pDoc, sal_uInt16 nFileId, const String& rFilter) :
+ ::sfx2::SvBaseLink(::sfx2::LINKUPDATE_ONCALL, FORMAT_FILE),
+ mnFileId(nFileId),
+ maFilterName(rFilter),
+ mpDoc(pDoc),
+ mbDoRefresh(true)
+{
+}
+
+ScExternalRefLink::~ScExternalRefLink()
+{
+}
+
+void ScExternalRefLink::Closed()
+{
+ ScExternalRefManager* pMgr = mpDoc->GetExternalRefManager();
+ pMgr->breakLink(mnFileId);
+}
+
+void ScExternalRefLink::DataChanged(const String& /*rMimeType*/, const Any& /*rValue*/)
+{
+ if (!mbDoRefresh)
+ return;
+
+ String aFile, aFilter;
+ mpDoc->GetLinkManager()->GetDisplayNames(this, NULL, &aFile, NULL, &aFilter);
+ ScExternalRefManager* pMgr = mpDoc->GetExternalRefManager();
+ const String* pCurFile = pMgr->getExternalFileName(mnFileId);
+ if (!pCurFile)
+ return;
+
+ if (pCurFile->Equals(aFile))
+ {
+ // Refresh the current source document.
+ pMgr->refreshNames(mnFileId);
+ }
+ else
+ {
+ // The source document has changed.
+ ScDocShell* pDocShell = ScDocShell::GetViewData()->GetDocShell();
+ ScDocShellModificator aMod(*pDocShell);
+ pMgr->switchSrcFile(mnFileId, aFile, aFilter);
+ maFilterName = aFilter;
+ aMod.SetDocumentModified();
+ }
+}
+
+void ScExternalRefLink::Edit(Window* pParent, const Link& /*rEndEditHdl*/)
+{
+ SvBaseLink::Edit(pParent, LINK(this, ScExternalRefLink, ExternalRefEndEditHdl));
+}
+
+void ScExternalRefLink::SetDoReferesh(bool b)
+{
+ mbDoRefresh = b;
+}
+
+IMPL_LINK( ScExternalRefLink, ExternalRefEndEditHdl, ::sfx2::SvBaseLink*, EMPTYARG )
+{
+ return 0;
+}
+
+// ============================================================================
+
+static FormulaToken* lcl_convertToToken(ScBaseCell* pCell)
+{
+ if (!pCell || pCell->HasEmptyData())
+ {
+ bool bInherited = (pCell && pCell->GetCellType() == CELLTYPE_FORMULA);
+ return new ScEmptyCellToken( bInherited, false);
+ }
+
+ switch (pCell->GetCellType())
+ {
+ case CELLTYPE_EDIT:
+ {
+ String aStr;
+ static_cast<ScEditCell*>(pCell)->GetString(aStr);
+ return new formula::FormulaStringToken(aStr);
+ }
+ //break;
+ case CELLTYPE_STRING:
+ {
+ String aStr;
+ static_cast<ScStringCell*>(pCell)->GetString(aStr);
+ return new formula::FormulaStringToken(aStr);
+ }
+ //break;
+ case CELLTYPE_VALUE:
+ {
+ double fVal = static_cast<ScValueCell*>(pCell)->GetValue();
+ return new formula::FormulaDoubleToken(fVal);
+ }
+ //break;
+ case CELLTYPE_FORMULA:
+ {
+ ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
+ USHORT nError = pFCell->GetErrCode();
+ if (nError)
+ return new FormulaErrorToken( nError);
+ else if (pFCell->IsValue())
+ {
+ double fVal = pFCell->GetValue();
+ return new formula::FormulaDoubleToken(fVal);
+ }
+ else
+ {
+ String aStr;
+ pFCell->GetString(aStr);
+ return new formula::FormulaStringToken(aStr);
+ }
+ }
+ //break;
+ default:
+ DBG_ERROR("attempted to convert an unknown cell type.");
+ }
+
+ return NULL;
+}
+
+static ScTokenArray* lcl_convertToTokenArray(ScDocument* pSrcDoc, const ScRange& rRange,
+ vector<ScExternalRefCache::SingleRangeData>& rCacheData)
+{
+ const ScAddress& s = rRange.aStart;
+ const ScAddress& e = rRange.aEnd;
+
+ SCTAB nTab1 = s.Tab(), nTab2 = e.Tab();
+ SCCOL nCol1 = s.Col(), nCol2 = e.Col();
+ SCROW nRow1 = s.Row(), nRow2 = e.Row();
+
+ if (nTab2 != nTab1)
+ // For now, we don't support multi-sheet ranges intentionally because
+ // we don't have a way to express them in a single token. In the
+ // future we can introduce a new stack variable type svMatrixList with
+ // a new token type that can store a 3D matrix value and convert a 3D
+ // range to it.
+ return NULL;
+
+ auto_ptr<ScTokenArray> pArray(new ScTokenArray);
+ bool bFirstTab = true;
+ vector<ScExternalRefCache::SingleRangeData>::iterator
+ itrCache = rCacheData.begin(), itrCacheEnd = rCacheData.end();
+ for (SCTAB nTab = nTab1; nTab <= nTab2 && itrCache != itrCacheEnd; ++nTab, ++itrCache)
+ {
+ ScMatrixRef xMat = new ScMatrix(
+ static_cast<SCSIZE>(nCol2-nCol1+1),
+ static_cast<SCSIZE>(nRow2-nRow1+1));
+
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+ {
+ for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
+ {
+ SCSIZE nC = nCol - nCol1, nR = nRow - nRow1;
+ ScBaseCell* pCell;
+ pSrcDoc->GetCell(nCol, nRow, nTab, pCell);
+ if (!pCell || pCell->HasEmptyData())
+ xMat->PutEmpty(nC, nR);
+ else
+ {
+ switch (pCell->GetCellType())
+ {
+ case CELLTYPE_EDIT:
+ {
+ String aStr;
+ static_cast<ScEditCell*>(pCell)->GetString(aStr);
+ xMat->PutString(aStr, nC, nR);
+ }
+ break;
+ case CELLTYPE_STRING:
+ {
+ String aStr;
+ static_cast<ScStringCell*>(pCell)->GetString(aStr);
+ xMat->PutString(aStr, nC, nR);
+ }
+ break;
+ case CELLTYPE_VALUE:
+ {
+ double fVal = static_cast<ScValueCell*>(pCell)->GetValue();
+ xMat->PutDouble(fVal, nC, nR);
+ }
+ break;
+ case CELLTYPE_FORMULA:
+ {
+ ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
+ USHORT nError = pFCell->GetErrCode();
+ if (nError)
+ xMat->PutDouble( CreateDoubleError( nError), nC, nR);
+ else if (pFCell->IsValue())
+ {
+ double fVal = pFCell->GetValue();
+ xMat->PutDouble(fVal, nC, nR);
+ }
+ else
+ {
+ String aStr;
+ pFCell->GetString(aStr);
+ xMat->PutString(aStr, nC, nR);
+ }
+ }
+ break;
+ default:
+ DBG_ERROR("attempted to convert an unknown cell type.");
+ }
+ }
+ }
+ }
+ if (!bFirstTab)
+ pArray->AddOpCode(ocSep);
+
+ ScMatrix* pMat2 = xMat;
+ ScMatrixToken aToken(pMat2);
+ pArray->AddToken(aToken);
+
+ itrCache->mpRangeData = xMat;
+
+ bFirstTab = false;
+ }
+ return pArray.release();
+}
+
+ScExternalRefManager::ScExternalRefManager(ScDocument* pDoc) :
+ mpDoc(pDoc),
+ bInReferenceMarking(false)
+{
+ maSrcDocTimer.SetTimeoutHdl( LINK(this, ScExternalRefManager, TimeOutHdl) );
+ maSrcDocTimer.SetTimeout(SRCDOC_SCAN_INTERVAL);
+}
+
+ScExternalRefManager::~ScExternalRefManager()
+{
+ clear();
+}
+
+String ScExternalRefManager::getCacheTableName(sal_uInt16 nFileId, size_t nTabIndex) const
+{
+ return maRefCache.getTableName(nFileId, nTabIndex);
+}
+
+ScExternalRefCache::TableTypeRef ScExternalRefManager::getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const
+{
+ return maRefCache.getCacheTable(nFileId, nTabIndex);
+}
+
+ScExternalRefCache::TableTypeRef ScExternalRefManager::getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew, size_t* pnIndex)
+{
+ return maRefCache.getCacheTable(nFileId, rTabName, bCreateNew, pnIndex);
+}
+
+// ============================================================================
+
+ScExternalRefManager::RefCells::TabItem::TabItem(SCTAB nIndex) :
+ mnIndex(nIndex)
+{
+}
+
+ScExternalRefManager::RefCells::TabItem::TabItem(const TabItem& r) :
+ mnIndex(r.mnIndex),
+ maCols(r.maCols)
+{
+}
+
+ScExternalRefManager::RefCells::RefCells()
+{
+}
+
+ScExternalRefManager::RefCells::~RefCells()
+{
+}
+
+list<ScExternalRefManager::RefCells::TabItemRef>::iterator ScExternalRefManager::RefCells::getTabPos(SCTAB nTab)
+{
+ list<TabItemRef>::iterator itr = maTables.begin(), itrEnd = maTables.end();
+ for (; itr != itrEnd; ++itr)
+ if ((*itr)->mnIndex >= nTab)
+ return itr;
+ // Not found. return the end position.
+ return itrEnd;
+}
+
+void ScExternalRefManager::RefCells::insertCell(const ScAddress& rAddr)
+{
+ SCTAB nTab = rAddr.Tab();
+ SCCOL nCol = rAddr.Col();
+ SCROW nRow = rAddr.Row();
+
+ // Search by table index.
+ list<TabItemRef>::iterator itrTab = getTabPos(nTab);
+ TabItemRef xTabRef;
+ if (itrTab == maTables.end())
+ {
+ // All previous tables come before the specificed table.
+ xTabRef.reset(new TabItem(nTab));
+ maTables.push_back(xTabRef);
+ }
+ else if ((*itrTab)->mnIndex > nTab)
+ {
+ // Insert at the current iterator position.
+ xTabRef.reset(new TabItem(nTab));
+ maTables.insert(itrTab, xTabRef);
+ }
+ else if ((*itrTab)->mnIndex == nTab)
+ {
+ // The table found.
+ xTabRef = *itrTab;
+ }
+ ColSet& rCols = xTabRef->maCols;
+
+ // Then by column index.
+ ColSet::iterator itrCol = rCols.find(nCol);
+ if (itrCol == rCols.end())
+ {
+ RowSet aRows;
+ pair<ColSet::iterator, bool> r = rCols.insert(ColSet::value_type(nCol, aRows));
+ if (!r.second)
+ // column insertion failed.
+ return;
+ itrCol = r.first;
+ }
+ RowSet& rRows = itrCol->second;
+
+ // Finally, insert the row index.
+ rRows.insert(nRow);
+}
+
+void ScExternalRefManager::RefCells::removeCell(const ScAddress& rAddr)
+{
+ SCTAB nTab = rAddr.Tab();
+ SCCOL nCol = rAddr.Col();
+ SCROW nRow = rAddr.Row();
+
+ // Search by table index.
+ list<TabItemRef>::iterator itrTab = getTabPos(nTab);
+ if (itrTab == maTables.end() || (*itrTab)->mnIndex != nTab)
+ // No such table.
+ return;
+
+ ColSet& rCols = (*itrTab)->maCols;
+
+ // Then by column index.
+ ColSet::iterator itrCol = rCols.find(nCol);
+ if (itrCol == rCols.end())
+ // No such column
+ return;
+
+ RowSet& rRows = itrCol->second;
+ rRows.erase(nRow);
+}
+
+void ScExternalRefManager::RefCells::moveTable(SCTAB nOldTab, SCTAB nNewTab, bool bCopy)
+{
+ if (nOldTab == nNewTab)
+ // Nothing to do here.
+ return;
+
+ list<TabItemRef>::iterator itrOld = getTabPos(nOldTab);
+ if (itrOld == maTables.end() || (*itrOld)->mnIndex != nOldTab)
+ // No table to move or copy.
+ return;
+
+ list<TabItemRef>::iterator itrNew = getTabPos(nNewTab);
+ if (bCopy)
+ {
+ // Simply make a duplicate of the original table, insert it at the
+ // new tab position, and increment the table index for all tables
+ // that come after that inserted table.
+
+ TabItemRef xNewTab(new TabItem(*(*itrOld)));
+ xNewTab->mnIndex = nNewTab;
+ maTables.insert(itrNew, xNewTab);
+ list<TabItemRef>::iterator itr = itrNew, itrEnd = maTables.end();
+ if (itr != itrEnd) // #i99807# check that itr is not at end already
+ for (++itr; itr != itrEnd; ++itr)
+ (*itr)->mnIndex += 1;
+ }
+ else
+ {
+ if (itrOld == itrNew)
+ {
+ // No need to move the table. Just update the table index.
+ (*itrOld)->mnIndex = nNewTab;
+ return;
+ }
+
+ if (nOldTab < nNewTab)
+ {
+ // Iterate from the old tab position to the new tab position (not
+ // inclusive of the old tab itself), and decrement their tab
+ // index by one.
+ list<TabItemRef>::iterator itr = itrOld;
+ for (++itr; itr != itrNew; ++itr)
+ (*itr)->mnIndex -= 1;
+
+ // Insert a duplicate of the original table. This does not
+ // invalidate the iterators.
+ (*itrOld)->mnIndex = nNewTab - 1;
+ if (itrNew == maTables.end())
+ maTables.push_back(*itrOld);
+ else
+ maTables.insert(itrNew, *itrOld);
+
+ // Remove the original table.
+ maTables.erase(itrOld);
+ }
+ else
+ {
+ // nNewTab < nOldTab
+
+ // Iterate from the new tab position to the one before the old tab
+ // position, and increment their tab index by one.
+ list<TabItemRef>::iterator itr = itrNew;
+ for (++itr; itr != itrOld; ++itr)
+ (*itr)->mnIndex += 1;
+
+ (*itrOld)->mnIndex = nNewTab;
+ maTables.insert(itrNew, *itrOld);
+
+ // Remove the original table.
+ maTables.erase(itrOld);
+ }
+ }
+}
+
+void ScExternalRefManager::RefCells::insertTable(SCTAB nPos)
+{
+ TabItemRef xNewTab(new TabItem(nPos));
+ list<TabItemRef>::iterator itr = getTabPos(nPos);
+ if (itr == maTables.end())
+ maTables.push_back(xNewTab);
+ else
+ maTables.insert(itr, xNewTab);
+}
+
+void ScExternalRefManager::RefCells::removeTable(SCTAB nPos)
+{
+ list<TabItemRef>::iterator itr = getTabPos(nPos);
+ if (itr == maTables.end())
+ // nothing to remove.
+ return;
+
+ maTables.erase(itr);
+}
+
+void ScExternalRefManager::RefCells::refreshAllCells(ScExternalRefManager& rRefMgr)
+{
+ // Get ALL the cell positions for re-compilation.
+ for (list<TabItemRef>::iterator itrTab = maTables.begin(), itrTabEnd = maTables.end();
+ itrTab != itrTabEnd; ++itrTab)
+ {
+ SCTAB nTab = (*itrTab)->mnIndex;
+ ColSet& rCols = (*itrTab)->maCols;
+ for (ColSet::iterator itrCol = rCols.begin(), itrColEnd = rCols.end();
+ itrCol != itrColEnd; ++itrCol)
+ {
+ SCCOL nCol = itrCol->first;
+ RowSet& rRows = itrCol->second;
+ RowSet aNewRows;
+ for (RowSet::iterator itrRow = rRows.begin(), itrRowEnd = rRows.end();
+ itrRow != itrRowEnd; ++itrRow)
+ {
+ SCROW nRow = *itrRow;
+ ScAddress aCell(nCol, nRow, nTab);
+ if (rRefMgr.compileTokensByCell(aCell))
+ // This cell still contains an external refernce.
+ aNewRows.insert(nRow);
+ }
+ // Update the rows so that cells with no external references are
+ // no longer tracked.
+ rRows.swap(aNewRows);
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+ScExternalRefManager::LinkListener::LinkListener()
+{
+}
+
+ScExternalRefManager::LinkListener::~LinkListener()
+{
+}
+
+// ----------------------------------------------------------------------------
+
+void ScExternalRefManager::getAllCachedTableNames(sal_uInt16 nFileId, vector<String>& rTabNames) const
+{
+ maRefCache.getAllTableNames(nFileId, rTabNames);
+}
+
+SCsTAB ScExternalRefManager::getCachedTabSpan( sal_uInt16 nFileId, const String& rStartTabName, const String& rEndTabName ) const
+{
+ return maRefCache.getTabSpan( nFileId, rStartTabName, rEndTabName);
+}
+
+void ScExternalRefManager::getAllCachedNumberFormats(vector<sal_uInt32>& rNumFmts) const
+{
+ maRefCache.getAllNumberFormats(rNumFmts);
+}
+
+bool ScExternalRefManager::hasCacheTable(sal_uInt16 nFileId, const String& rTabName) const
+{
+ return maRefCache.hasCacheTable(nFileId, rTabName);
+}
+
+size_t ScExternalRefManager::getCacheTableCount(sal_uInt16 nFileId) const
+{
+ return maRefCache.getCacheTableCount(nFileId);
+}
+
+sal_uInt16 ScExternalRefManager::getExternalFileCount() const
+{
+ return static_cast< sal_uInt16 >( maSrcFiles.size() );
+}
+
+bool ScExternalRefManager::markUsedByLinkListeners()
+{
+ bool bAllMarked = false;
+ for (LinkListenerMap::const_iterator itr = maLinkListeners.begin();
+ itr != maLinkListeners.end() && !bAllMarked; ++itr)
+ {
+ if (!(*itr).second.empty())
+ bAllMarked = maRefCache.setCacheDocReferenced( (*itr).first);
+ /* TODO: LinkListeners should remember the table they're listening to.
+ * As is, listening to one table will mark all tables of the document
+ * being referenced. */
+ }
+ return bAllMarked;
+}
+
+bool ScExternalRefManager::setCacheDocReferenced( sal_uInt16 nFileId )
+{
+ return maRefCache.setCacheDocReferenced( nFileId);
+}
+
+bool ScExternalRefManager::setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName, size_t nSheets )
+{
+ return maRefCache.setCacheTableReferenced( nFileId, rTabName, nSheets, false);
+}
+
+void ScExternalRefManager::setCacheTableReferencedPermanently( sal_uInt16 nFileId, const String& rTabName, size_t nSheets )
+{
+ if (isInReferenceMarking())
+ // Do all maintenance work.
+ maRefCache.setCacheTableReferenced( nFileId, rTabName, nSheets, true);
+ else
+ // Set only the permanent flag.
+ maRefCache.setCacheTableReferencedPermanently( nFileId, rTabName, nSheets);
+}
+
+void ScExternalRefManager::setAllCacheTableReferencedStati( bool bReferenced )
+{
+ bInReferenceMarking = !bReferenced;
+ maRefCache.setAllCacheTableReferencedStati( bReferenced );
+}
+
+void ScExternalRefManager::storeRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScTokenArray& rArray)
+{
+ ScExternalRefCache::TokenArrayRef pArray(rArray.Clone());
+ maRefCache.setRangeNameTokens(nFileId, rName, pArray);
+}
+
+ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefToken(
+ sal_uInt16 nFileId, const String& rTabName, const ScAddress& rCell,
+ const ScAddress* pCurPos, SCTAB* pTab, ScExternalRefCache::CellFormat* pFmt)
+{
+ if (pCurPos)
+ insertRefCell(nFileId, *pCurPos);
+
+ maybeLinkExternalFile(nFileId);
+
+ if (pTab)
+ *pTab = -1;
+
+ if (pFmt)
+ pFmt->mbIsSet = false;
+
+ bool bLoading = mpDoc->IsImportingXML();
+
+ // Check if the given table name and the cell position is cached.
+ // #i101304# When loading a file, the saved cache (hidden sheet)
+ // is assumed to contain all data for the loaded formulas.
+ // No cache entries are created from empty cells in the saved sheet,
+ // so they have to be created here (bWriteEmpty parameter).
+ // Otherwise, later interpretation of the loaded formulas would
+ // load the source document even if the user didn't want to update.
+ sal_uInt32 nFmtIndex = 0;
+ ScExternalRefCache::TokenRef pToken = maRefCache.getCellData(
+ nFileId, rTabName, rCell.Col(), rCell.Row(), bLoading, bLoading, &nFmtIndex);
+ if (pToken)
+ {
+ if (pFmt)
+ {
+ short nFmtType = mpDoc->GetFormatTable()->GetType(nFmtIndex);
+ if (nFmtType != NUMBERFORMAT_UNDEFINED)
+ {
+ pFmt->mbIsSet = true;
+ pFmt->mnIndex = nFmtIndex;
+ pFmt->mnType = nFmtType;
+ }
+ }
+ return pToken;
+ }
+
+ // reference not cached. read from the source document.
+ ScDocument* pSrcDoc = getSrcDocument(nFileId);
+ if (!pSrcDoc)
+ {
+ // Source document is not reachable. Try to get data from the cache
+ // once again, but this time treat a non-cached cell as an empty cell
+ // as long as the table itself is cached.
+ pToken = maRefCache.getCellData(
+ nFileId, rTabName, rCell.Col(), rCell.Row(), true, false, &nFmtIndex);
+ return pToken;
+ }
+
+ ScBaseCell* pCell = NULL;
+ SCTAB nTab;
+ if (!pSrcDoc->GetTable(rTabName, nTab))
+ {
+ // specified table name doesn't exist in the source document.
+ return ScExternalRefCache::TokenRef();
+ }
+
+ if (pTab)
+ *pTab = nTab;
+
+ pSrcDoc->GetCell(rCell.Col(), rCell.Row(), nTab, pCell);
+ ScExternalRefCache::TokenRef pTok(lcl_convertToToken(pCell));
+
+ pSrcDoc->GetNumberFormat(rCell.Col(), rCell.Row(), nTab, nFmtIndex);
+ nFmtIndex = getMappedNumberFormat(nFileId, nFmtIndex, pSrcDoc);
+ if (pFmt)
+ {
+ short nFmtType = mpDoc->GetFormatTable()->GetType(nFmtIndex);
+ if (nFmtType != NUMBERFORMAT_UNDEFINED)
+ {
+ pFmt->mbIsSet = true;
+ pFmt->mnIndex = nFmtIndex;
+ pFmt->mnType = nFmtType;
+ }
+ }
+
+ if (!pTok.get())
+ {
+ // Generate an error for unresolvable cells.
+ pTok.reset( new FormulaErrorToken( errNoValue));
+ }
+
+ // Now, insert the token into cache table.
+ maRefCache.setCellData(nFileId, rTabName, rCell.Row(), rCell.Col(), pTok, nFmtIndex);
+ return pTok;
+}
+
+ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokens(sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange, const ScAddress* pCurPos)
+{
+ if (pCurPos)
+ insertRefCell(nFileId, *pCurPos);
+
+ maybeLinkExternalFile(nFileId);
+
+ bool bLoading = mpDoc->IsImportingXML();
+
+ // Check if the given table name and the cell position is cached.
+ // #i101304# When loading, put empty cells into cache, see getSingleRefToken.
+ ScExternalRefCache::TokenArrayRef p = maRefCache.getCellRangeData(nFileId, rTabName, rRange, bLoading, bLoading);
+ if (p.get())
+ return p;
+
+ ScDocument* pSrcDoc = getSrcDocument(nFileId);
+ if (!pSrcDoc)
+ {
+ // Source document is not reachable. Try to get data from the cache
+ // once again, but this time treat non-cached cells as empty cells as
+ // long as the table itself is cached.
+ return maRefCache.getCellRangeData(nFileId, rTabName, rRange, true, false);
+ }
+
+ SCTAB nTab1;
+ if (!pSrcDoc->GetTable(rTabName, nTab1))
+ // specified table name doesn't exist in the source document.
+ return ScExternalRefCache::TokenArrayRef();
+
+ ScRange aRange(rRange);
+ SCTAB nTabSpan = aRange.aEnd.Tab() - aRange.aStart.Tab();
+
+ vector<ScExternalRefCache::SingleRangeData> aCacheData;
+ aCacheData.reserve(nTabSpan+1);
+ aCacheData.push_back(ScExternalRefCache::SingleRangeData());
+ aCacheData.back().maTableName = ScGlobal::pCharClass->upper(rTabName);
+
+ for (SCTAB i = 1; i < nTabSpan + 1; ++i)
+ {
+ String aTabName;
+ if (!pSrcDoc->GetName(nTab1 + 1, aTabName))
+ // source document doesn't have any table by the specified name.
+ break;
+
+ aCacheData.push_back(ScExternalRefCache::SingleRangeData());
+ aCacheData.back().maTableName = ScGlobal::pCharClass->upper(aTabName);
+ }
+
+ aRange.aStart.SetTab(nTab1);
+ aRange.aEnd.SetTab(nTab1 + nTabSpan);
+
+ ScExternalRefCache::TokenArrayRef pArray;
+ pArray.reset(lcl_convertToTokenArray(pSrcDoc, aRange, aCacheData));
+
+ if (pArray)
+ // Cache these values.
+ maRefCache.setCellRangeData(nFileId, rRange, aCacheData, pArray);
+
+ return pArray;
+}
+
+ScExternalRefCache::TokenArrayRef ScExternalRefManager::getRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScAddress* pCurPos)
+{
+ if (pCurPos)
+ insertRefCell(nFileId, *pCurPos);
+
+ maybeLinkExternalFile(nFileId);
+
+ ScExternalRefCache::TokenArrayRef pArray = maRefCache.getRangeNameTokens(nFileId, rName);
+ if (pArray.get())
+ return pArray;
+
+ ScDocument* pSrcDoc = getSrcDocument(nFileId);
+ if (!pSrcDoc)
+ return ScExternalRefCache::TokenArrayRef();
+
+ ScRangeName* pExtNames = pSrcDoc->GetRangeName();
+ String aUpperName = ScGlobal::pCharClass->upper(rName);
+ USHORT n;
+ bool bRes = pExtNames->SearchNameUpper(aUpperName, n);
+ if (!bRes)
+ return ScExternalRefCache::TokenArrayRef();
+
+ ScRangeData* pRangeData = (*pExtNames)[n];
+ if (!pRangeData)
+ return ScExternalRefCache::TokenArrayRef();
+
+ // Parse all tokens in this external range data, and replace each absolute
+ // reference token with an external reference token, and cache them. Also
+ // register the source document with the link manager if it's a new
+ // source.
+
+ ScExternalRefCache::TokenArrayRef pNew(new ScTokenArray);
+
+ ScTokenArray* pCode = pRangeData->GetCode();
+ for (FormulaToken* pToken = pCode->First(); pToken; pToken = pCode->Next())
+ {
+ bool bTokenAdded = false;
+ switch (pToken->GetType())
+ {
+ case svSingleRef:
+ {
+ const ScSingleRefData& rRef = static_cast<ScToken*>(pToken)->GetSingleRef();
+ String aTabName;
+ pSrcDoc->GetName(rRef.nTab, aTabName);
+ ScExternalSingleRefToken aNewToken(nFileId, aTabName, static_cast<ScToken*>(pToken)->GetSingleRef());
+ pNew->AddToken(aNewToken);
+ bTokenAdded = true;
+ }
+ break;
+ case svDoubleRef:
+ {
+ const ScSingleRefData& rRef = static_cast<ScToken*>(pToken)->GetSingleRef();
+ String aTabName;
+ pSrcDoc->GetName(rRef.nTab, aTabName);
+ ScExternalDoubleRefToken aNewToken(nFileId, aTabName, static_cast<ScToken*>(pToken)->GetDoubleRef());
+ pNew->AddToken(aNewToken);
+ bTokenAdded = true;
+ }
+ break;
+ default:
+ ; // nothing
+ }
+
+ if (!bTokenAdded)
+ pNew->AddToken(*pToken);
+ }
+
+ // Make sure to pass the correctly-cased range name here.
+ maRefCache.setRangeNameTokens(nFileId, pRangeData->GetName(), pNew);
+ return pNew;
+}
+
+void ScExternalRefManager::refreshAllRefCells(sal_uInt16 nFileId)
+{
+ RefCellMap::iterator itrFile = maRefCells.find(nFileId);
+ if (itrFile == maRefCells.end())
+ return;
+
+ RefCells& rRefCells = itrFile->second;
+ rRefCells.refreshAllCells(*this);
+
+ ScViewData* pViewData = ScDocShell::GetViewData();
+ if (!pViewData)
+ return;
+
+ ScTabViewShell* pVShell = pViewData->GetViewShell();
+ if (!pVShell)
+ return;
+
+ // Repainting the grid also repaints the texts, but is there a better way
+ // to refresh texts?
+ pVShell->Invalidate(FID_REPAINT);
+ pVShell->PaintGrid();
+}
+
+void ScExternalRefManager::insertRefCell(sal_uInt16 nFileId, const ScAddress& rCell)
+{
+ RefCellMap::iterator itr = maRefCells.find(nFileId);
+ if (itr == maRefCells.end())
+ {
+ RefCells aRefCells;
+ pair<RefCellMap::iterator, bool> r = maRefCells.insert(
+ RefCellMap::value_type(nFileId, aRefCells));
+ if (!r.second)
+ // insertion failed.
+ return;
+
+ itr = r.first;
+ }
+ itr->second.insertCell(rCell);
+}
+
+ScDocument* ScExternalRefManager::getSrcDocument(sal_uInt16 nFileId)
+{
+ if (!mpDoc->IsExecuteLinkEnabled())
+ return NULL;
+
+ DocShellMap::iterator itrEnd = maDocShells.end();
+ DocShellMap::iterator itr = maDocShells.find(nFileId);
+
+ if (itr != itrEnd)
+ {
+ SfxObjectShell* p = itr->second.maShell;
+ itr->second.maLastAccess = Time();
+ return static_cast<ScDocShell*>(p)->GetDocument();
+ }
+
+ const String* pFile = getExternalFileName(nFileId);
+ if (!pFile)
+ // no file name associated with this ID.
+ return NULL;
+
+ String aFilter;
+ SrcShell aSrcDoc;
+ aSrcDoc.maShell = loadSrcDocument(nFileId, aFilter);
+ if (!aSrcDoc.maShell.Is())
+ {
+ // source document could not be loaded.
+ return NULL;
+ }
+
+ if (maDocShells.empty())
+ {
+ // If this is the first source document insertion, start up the timer.
+ maSrcDocTimer.Start();
+ }
+
+ maDocShells.insert(DocShellMap::value_type(nFileId, aSrcDoc));
+ SfxObjectShell* p = aSrcDoc.maShell;
+ ScDocument* pSrcDoc = static_cast<ScDocShell*>(p)->GetDocument();
+
+ SCTAB nTabCount = pSrcDoc->GetTableCount();
+ if (!maRefCache.isDocInitialized(nFileId) && nTabCount)
+ {
+ // Populate the cache with all table names in the source document.
+ vector<String> aTabNames;
+ aTabNames.reserve(nTabCount);
+ for (SCTAB i = 0; i < nTabCount; ++i)
+ {
+ String aName;
+ pSrcDoc->GetName(i, aName);
+ aTabNames.push_back(aName);
+ }
+ maRefCache.initializeDoc(nFileId, aTabNames);
+ }
+ return pSrcDoc;
+}
+
+SfxObjectShellRef ScExternalRefManager::loadSrcDocument(sal_uInt16 nFileId, String& rFilter)
+{
+ const SrcFileData* pFileData = getExternalFileData(nFileId);
+ if (!pFileData)
+ return NULL;
+
+ // Always load the document by using the path created from the relative
+ // path. If the referenced document is not there, simply exit. The
+ // original file name should be used only when the relative path is not
+ // given.
+ String aFile = pFileData->maFileName;
+ maybeCreateRealFileName(nFileId);
+ if (pFileData->maRealFileName.Len())
+ aFile = pFileData->maRealFileName;
+
+ if (!isFileLoadable(aFile))
+ return NULL;
+
+ String aOptions;
+ ScDocumentLoader::GetFilterName(aFile, rFilter, aOptions, true, false);
+ const SfxFilter* pFilter = ScDocShell::Factory().GetFilterContainer()->GetFilter4FilterName(rFilter);
+
+ if (!pFileData->maRelativeName.Len())
+ {
+ // Generate a relative file path.
+ INetURLObject aBaseURL(getOwnDocumentName());
+ aBaseURL.insertName(OUString::createFromAscii("content.xml"));
+
+ String aStr = URIHelper::simpleNormalizedMakeRelative(
+ aBaseURL.GetMainURL(INetURLObject::NO_DECODE), aFile);
+
+ setRelativeFileName(nFileId, aStr);
+ }
+
+ // Update the filter data now that we are loading it again.
+ setFilterData(nFileId, rFilter, aOptions);
+
+ SfxItemSet* pSet = new SfxAllItemSet(SFX_APP()->GetPool());
+ if (aOptions.Len())
+ pSet->Put(SfxStringItem(SID_FILE_FILTEROPTIONS, aOptions));
+
+ auto_ptr<SfxMedium> pMedium(new SfxMedium(aFile, STREAM_STD_READ, false, pFilter, pSet));
+ if (pMedium->GetError() != ERRCODE_NONE)
+ return NULL;
+
+ pMedium->UseInteractionHandler(false);
+
+ ScDocShell* pNewShell = new ScDocShell(SFX_CREATE_MODE_INTERNAL);
+ SfxObjectShellRef aRef = pNewShell;
+
+ // increment the recursive link count of the source document.
+ ScExtDocOptions* pExtOpt = mpDoc->GetExtDocOptions();
+ sal_uInt32 nLinkCount = pExtOpt ? pExtOpt->GetDocSettings().mnLinkCnt : 0;
+ ScDocument* pSrcDoc = pNewShell->GetDocument();
+ ScExtDocOptions* pExtOptNew = pSrcDoc->GetExtDocOptions();
+ if (!pExtOptNew)
+ {
+ pExtOptNew = new ScExtDocOptions;
+ pSrcDoc->SetExtDocOptions(pExtOptNew);
+ }
+ pExtOptNew->GetDocSettings().mnLinkCnt = nLinkCount + 1;
+
+ pNewShell->DoLoad(pMedium.release());
+ return aRef;
+}
+
+bool ScExternalRefManager::isFileLoadable(const String& rFile) const
+{
+ if (!rFile.Len())
+ return false;
+
+ if (isOwnDocument(rFile))
+ return false;
+
+ if (utl::UCBContentHelper::IsFolder(rFile))
+ return false;
+
+ return utl::UCBContentHelper::Exists(rFile);
+}
+
+void ScExternalRefManager::maybeLinkExternalFile(sal_uInt16 nFileId)
+{
+ if (maLinkedDocs.count(nFileId))
+ // file alerady linked, or the link has been broken.
+ return;
+
+ // Source document not linked yet. Link it now.
+ const String* pFileName = getExternalFileName(nFileId);
+ if (!pFileName)
+ return;
+
+ String aFilter, aOptions;
+ ScDocumentLoader::GetFilterName(*pFileName, aFilter, aOptions, true, false);
+ sfx2::LinkManager* pLinkMgr = mpDoc->GetLinkManager();
+ ScExternalRefLink* pLink = new ScExternalRefLink(mpDoc, nFileId, aFilter);
+ DBG_ASSERT(pFileName, "ScExternalRefManager::insertExternalFileLink: file name pointer is NULL");
+ pLinkMgr->InsertFileLink(*pLink, OBJECT_CLIENT_FILE, *pFileName, &aFilter);
+
+ pLink->SetDoReferesh(false);
+ pLink->Update();
+ pLink->SetDoReferesh(true);
+
+ maLinkedDocs.insert(LinkedDocMap::value_type(nFileId, true));
+}
+
+void ScExternalRefManager::SrcFileData::maybeCreateRealFileName(const String& rOwnDocName)
+{
+ if (!maRelativeName.Len())
+ // No relative path given. Nothing to do.
+ return;
+
+ if (maRealFileName.Len())
+ // Real file name already created. Nothing to do.
+ return;
+
+ // Formulate the absolute file path from the relative path.
+ const String& rRelPath = maRelativeName;
+ INetURLObject aBaseURL(rOwnDocName);
+ aBaseURL.insertName(OUString::createFromAscii("content.xml"));
+ bool bWasAbs = false;
+ maRealFileName = aBaseURL.smartRel2Abs(rRelPath, bWasAbs).GetMainURL(INetURLObject::NO_DECODE);
+}
+
+void ScExternalRefManager::maybeCreateRealFileName(sal_uInt16 nFileId)
+{
+ if (nFileId >= maSrcFiles.size())
+ return;
+
+ maSrcFiles[nFileId].maybeCreateRealFileName(getOwnDocumentName());
+}
+
+bool ScExternalRefManager::compileTokensByCell(const ScAddress& rCell)
+{
+ ScBaseCell* pCell;
+ mpDoc->GetCell(rCell.Col(), rCell.Row(), rCell.Tab(), pCell);
+
+ if (!pCell || pCell->GetCellType() != CELLTYPE_FORMULA)
+ return false;
+
+ ScFormulaCell* pFC = static_cast<ScFormulaCell*>(pCell);
+
+ // Check to make sure the cell really contains ocExternalRef.
+ // External names, external cell and range references all have a
+ // ocExternalRef token.
+ const ScTokenArray* pCode = pFC->GetCode();
+ if (!pCode->HasOpCode( ocExternalRef))
+ return false;
+
+ ScTokenArray* pArray = pFC->GetCode();
+ if (pArray)
+ // Clear the error code, or a cell with error won't get re-compiled.
+ pArray->SetCodeError(0);
+
+ pFC->SetCompile(true);
+ pFC->CompileTokenArray();
+ pFC->SetDirty();
+
+ return true;
+}
+
+const String& ScExternalRefManager::getOwnDocumentName() const
+{
+ SfxObjectShell* pShell = mpDoc->GetDocumentShell();
+ if (!pShell)
+ // This should not happen!
+ return EMPTY_STRING;
+
+ SfxMedium* pMed = pShell->GetMedium();
+ if (!pMed)
+ return EMPTY_STRING;
+
+ return pMed->GetName();
+}
+
+bool ScExternalRefManager::isOwnDocument(const String& rFile) const
+{
+ return getOwnDocumentName().Equals(rFile);
+}
+
+void ScExternalRefManager::convertToAbsName(String& rFile) const
+{
+ SfxObjectShell* pDocShell = mpDoc->GetDocumentShell();
+ rFile = ScGlobal::GetAbsDocName(rFile, pDocShell);
+}
+
+sal_uInt16 ScExternalRefManager::getExternalFileId(const String& rFile)
+{
+ vector<SrcFileData>::const_iterator itrBeg = maSrcFiles.begin(), itrEnd = maSrcFiles.end();
+ vector<SrcFileData>::const_iterator itr = find_if(itrBeg, itrEnd, FindSrcFileByName(rFile));
+ if (itr != itrEnd)
+ {
+ size_t nId = distance(itrBeg, itr);
+ return static_cast<sal_uInt16>(nId);
+ }
+
+ SrcFileData aData;
+ aData.maFileName = rFile;
+ maSrcFiles.push_back(aData);
+ return static_cast<sal_uInt16>(maSrcFiles.size() - 1);
+}
+
+const String* ScExternalRefManager::getExternalFileName(sal_uInt16 nFileId, bool bForceOriginal)
+{
+ if (nFileId >= maSrcFiles.size())
+ return NULL;
+
+ if (bForceOriginal)
+ return &maSrcFiles[nFileId].maFileName;
+
+ maybeCreateRealFileName(nFileId);
+
+ if (maSrcFiles[nFileId].maRealFileName.Len())
+ return &maSrcFiles[nFileId].maRealFileName;
+ else
+ return &maSrcFiles[nFileId].maFileName;
+}
+
+bool ScExternalRefManager::hasExternalFile(sal_uInt16 nFileId) const
+{
+ return nFileId < maSrcFiles.size();
+}
+
+bool ScExternalRefManager::hasExternalFile(const String& rFile) const
+{
+ vector<SrcFileData>::const_iterator itrBeg = maSrcFiles.begin(), itrEnd = maSrcFiles.end();
+ vector<SrcFileData>::const_iterator itr = find_if(itrBeg, itrEnd, FindSrcFileByName(rFile));
+ return itr != itrEnd;
+}
+
+const ScExternalRefManager::SrcFileData* ScExternalRefManager::getExternalFileData(sal_uInt16 nFileId) const
+{
+ if (nFileId >= maSrcFiles.size())
+ return NULL;
+
+ return &maSrcFiles[nFileId];
+}
+
+const String* ScExternalRefManager::getRealTableName(sal_uInt16 nFileId, const String& rTabName) const
+{
+ return maRefCache.getRealTableName(nFileId, rTabName);
+}
+
+const String* ScExternalRefManager::getRealRangeName(sal_uInt16 nFileId, const String& rRangeName) const
+{
+ return maRefCache.getRealRangeName(nFileId, rRangeName);
+}
+
+template<typename MapContainer>
+void lcl_removeByFileId(sal_uInt16 nFileId, MapContainer& rMap)
+{
+ typename MapContainer::iterator itr = rMap.find(nFileId);
+ if (itr != rMap.end())
+ rMap.erase(itr);
+}
+
+void ScExternalRefManager::refreshNames(sal_uInt16 nFileId)
+{
+ maRefCache.clearCache(nFileId);
+ lcl_removeByFileId(nFileId, maDocShells);
+
+ if (maDocShells.empty())
+ maSrcDocTimer.Stop();
+
+ // Update all cells containing names from this source document.
+ refreshAllRefCells(nFileId);
+
+ notifyAllLinkListeners(nFileId, LINK_MODIFIED);
+}
+
+void ScExternalRefManager::breakLink(sal_uInt16 nFileId)
+{
+ lcl_removeByFileId(nFileId, maDocShells);
+
+ if (maDocShells.empty())
+ maSrcDocTimer.Stop();
+
+ LinkedDocMap::iterator itr = maLinkedDocs.find(nFileId);
+ if (itr != maLinkedDocs.end())
+ itr->second = false;
+
+ notifyAllLinkListeners(nFileId, LINK_BROKEN);
+}
+
+void ScExternalRefManager::switchSrcFile(sal_uInt16 nFileId, const String& rNewFile, const String& rNewFilter)
+{
+ maSrcFiles[nFileId].maFileName = rNewFile;
+ maSrcFiles[nFileId].maRelativeName.Erase();
+ maSrcFiles[nFileId].maRealFileName.Erase();
+ if (!maSrcFiles[nFileId].maFilterName.Equals(rNewFilter))
+ {
+ // Filter type has changed.
+ maSrcFiles[nFileId].maFilterName = rNewFilter;
+ maSrcFiles[nFileId].maFilterOptions.Erase();
+ }
+ refreshNames(nFileId);
+}
+
+void ScExternalRefManager::setRelativeFileName(sal_uInt16 nFileId, const String& rRelUrl)
+{
+ if (nFileId >= maSrcFiles.size())
+ return;
+ maSrcFiles[nFileId].maRelativeName = rRelUrl;
+}
+
+void ScExternalRefManager::setFilterData(sal_uInt16 nFileId, const String& rFilterName, const String& rOptions)
+{
+ if (nFileId >= maSrcFiles.size())
+ return;
+ maSrcFiles[nFileId].maFilterName = rFilterName;
+ maSrcFiles[nFileId].maFilterOptions = rOptions;
+}
+
+void ScExternalRefManager::clear()
+{
+ DocShellMap::iterator itrEnd = maDocShells.end();
+ for (DocShellMap::iterator itr = maDocShells.begin(); itr != itrEnd; ++itr)
+ itr->second.maShell->DoClose();
+
+ maDocShells.clear();
+ maSrcDocTimer.Stop();
+}
+
+bool ScExternalRefManager::hasExternalData() const
+{
+ return !maSrcFiles.empty();
+}
+
+void ScExternalRefManager::resetSrcFileData(const String& rBaseFileUrl)
+{
+ for (vector<SrcFileData>::iterator itr = maSrcFiles.begin(), itrEnd = maSrcFiles.end();
+ itr != itrEnd; ++itr)
+ {
+ // Re-generate relative file name from the absolute file name.
+ String aAbsName = itr->maRealFileName;
+ if (!aAbsName.Len())
+ aAbsName = itr->maFileName;
+
+ itr->maRelativeName = URIHelper::simpleNormalizedMakeRelative(
+ rBaseFileUrl, aAbsName);
+ }
+}
+
+void ScExternalRefManager::updateRefCell(const ScAddress& rOldPos, const ScAddress& rNewPos, bool bCopy)
+{
+ for (RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end(); itr != itrEnd; ++itr)
+ {
+ if (!bCopy)
+ itr->second.removeCell(rOldPos);
+ itr->second.insertCell(rNewPos);
+ }
+}
+
+void ScExternalRefManager::updateRefMoveTable(SCTAB nOldTab, SCTAB nNewTab, bool bCopy)
+{
+ for (RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end(); itr != itrEnd; ++itr)
+ itr->second.moveTable(nOldTab, nNewTab, bCopy);
+}
+
+void ScExternalRefManager::updateRefInsertTable(SCTAB nPos)
+{
+ for (RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end(); itr != itrEnd; ++itr)
+ itr->second.insertTable(nPos);
+}
+
+void ScExternalRefManager::updateRefDeleteTable(SCTAB nPos)
+{
+ for (RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end(); itr != itrEnd; ++itr)
+ itr->second.removeTable(nPos);
+}
+
+void ScExternalRefManager::addLinkListener(sal_uInt16 nFileId, LinkListener* pListener)
+{
+ LinkListenerMap::iterator itr = maLinkListeners.find(nFileId);
+ if (itr == maLinkListeners.end())
+ {
+ pair<LinkListenerMap::iterator, bool> r = maLinkListeners.insert(
+ LinkListenerMap::value_type(nFileId, LinkListeners()));
+ if (!r.second)
+ {
+ DBG_ERROR("insertion of new link listener list failed");
+ return;
+ }
+
+ itr = r.first;
+ }
+
+ LinkListeners& rList = itr->second;
+ rList.insert(pListener);
+}
+
+void ScExternalRefManager::removeLinkListener(sal_uInt16 nFileId, LinkListener* pListener)
+{
+ LinkListenerMap::iterator itr = maLinkListeners.find(nFileId);
+ if (itr == maLinkListeners.end())
+ // no listeners for a specified file.
+ return;
+
+ LinkListeners& rList = itr->second;
+ rList.erase(pListener);
+
+ if (rList.empty())
+ // No more listeners for this file. Remove its entry.
+ maLinkListeners.erase(itr);
+}
+
+void ScExternalRefManager::removeLinkListener(LinkListener* pListener)
+{
+ LinkListenerMap::iterator itr = maLinkListeners.begin(), itrEnd = maLinkListeners.end();
+ for (; itr != itrEnd; ++itr)
+ itr->second.erase(pListener);
+}
+
+void ScExternalRefManager::notifyAllLinkListeners(sal_uInt16 nFileId, LinkUpdateType eType)
+{
+ LinkListenerMap::iterator itr = maLinkListeners.find(nFileId);
+ if (itr == maLinkListeners.end())
+ // no listeners for a specified file.
+ return;
+
+ LinkListeners& rList = itr->second;
+ for_each(rList.begin(), rList.end(), NotifyLinkListener(nFileId, eType));
+}
+
+void ScExternalRefManager::purgeStaleSrcDocument(sal_Int32 nTimeOut)
+{
+ DocShellMap aNewDocShells;
+ DocShellMap::iterator itr = maDocShells.begin(), itrEnd = maDocShells.end();
+ for (; itr != itrEnd; ++itr)
+ {
+ // in 100th of a second.
+ sal_Int32 nSinceLastAccess = (Time() - itr->second.maLastAccess).GetTime();
+ if (nSinceLastAccess < nTimeOut)
+ aNewDocShells.insert(*itr);
+ }
+ maDocShells.swap(aNewDocShells);
+
+ if (maDocShells.empty())
+ maSrcDocTimer.Stop();
+}
+
+sal_uInt32 ScExternalRefManager::getMappedNumberFormat(sal_uInt16 nFileId, sal_uInt32 nNumFmt, ScDocument* pSrcDoc)
+{
+ NumFmtMap::iterator itr = maNumFormatMap.find(nFileId);
+ if (itr == maNumFormatMap.end())
+ {
+ // Number formatter map is not initialized for this external document.
+ pair<NumFmtMap::iterator, bool> r = maNumFormatMap.insert(
+ NumFmtMap::value_type(nFileId, SvNumberFormatterMergeMap()));
+
+ if (!r.second)
+ // insertion failed.
+ return nNumFmt;
+
+ itr = r.first;
+ mpDoc->GetFormatTable()->MergeFormatter( *pSrcDoc->GetFormatTable());
+ SvNumberFormatterMergeMap aMap = mpDoc->GetFormatTable()->ConvertMergeTableToMap();
+ itr->second.swap(aMap);
+ }
+ const SvNumberFormatterMergeMap& rMap = itr->second;
+ SvNumberFormatterMergeMap::const_iterator itrNumFmt = rMap.find(nNumFmt);
+ if (itrNumFmt != rMap.end())
+ // mapped value found.
+ return itrNumFmt->second;
+
+ return nNumFmt;
+}
+
+IMPL_LINK(ScExternalRefManager, TimeOutHdl, AutoTimer*, pTimer)
+{
+ if (pTimer == &maSrcDocTimer)
+ purgeStaleSrcDocument(SRCDOC_LIFE_SPAN);
+
+ return 0;
+}
+
diff --git a/sc/source/ui/docshell/hiranges.cxx b/sc/source/ui/docshell/hiranges.cxx
new file mode 100644
index 000000000000..af1226216a06
--- /dev/null
+++ b/sc/source/ui/docshell/hiranges.cxx
@@ -0,0 +1,53 @@
+/*************************************************************************
+ *
+ * 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 "hiranges.hxx"
+
+//==================================================================
+
+ScHighlightRanges::ScHighlightRanges()
+{
+}
+
+ScHighlightRanges::~ScHighlightRanges()
+{
+ void* pEntry = aEntries.First();
+ while ( pEntry )
+ {
+ delete (ScHighlightEntry*) aEntries.Remove( pEntry );
+ pEntry = aEntries.Next();
+ }
+}
+
+
+
+
diff --git a/sc/source/ui/docshell/impex.cxx b/sc/source/ui/docshell/impex.cxx
new file mode 100644
index 000000000000..8fc49696ba59
--- /dev/null
+++ b/sc/source/ui/docshell/impex.cxx
@@ -0,0 +1,2076 @@
+/*************************************************************************
+ *
+ * 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"
+
+// System - Includes -----------------------------------------------------
+
+class StarBASIC;
+
+
+
+#ifndef PCH
+#include "sc.hrc"
+#define GLOBALOVERFLOW
+#endif
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <osl/endian.h>
+#include <i18npool/mslangid.hxx>
+#include <tools/list.hxx>
+#include <tools/string.hxx>
+#include <rtl/math.hxx>
+#include <svtools/htmlout.hxx>
+#include <svl/zforlist.hxx>
+#define _SVSTDARR_ULONGS
+#include <svl/svstdarr.hxx>
+#include <sot/formats.hxx>
+#include <sfx2/mieclip.hxx>
+#include <unotools/charclass.hxx>
+#include <unotools/collatorwrapper.hxx>
+#include <unotools/calendarwrapper.hxx>
+#include <com/sun/star/i18n/CalendarFieldIndex.hpp>
+#include <unotools/transliterationwrapper.hxx>
+
+#include "global.hxx"
+#include "scerrors.hxx"
+#include "docsh.hxx"
+#include "undoblk.hxx"
+#include "rangenam.hxx"
+#include "viewdata.hxx"
+#include "tabvwsh.hxx"
+#include "filter.hxx"
+#include "asciiopt.hxx"
+#include "cell.hxx"
+#include "docoptio.hxx"
+#include "progress.hxx"
+#include "scitems.hxx"
+#include "editable.hxx"
+#include "compiler.hxx"
+#include "warnbox.hxx"
+
+#include "impex.hxx"
+
+// ause
+#include "editutil.hxx"
+
+#include "globstr.hrc"
+#include <vcl/msgbox.hxx>
+#include <vcl/svapp.hxx>
+#include <osl/module.hxx>
+
+//========================================================================
+
+namespace
+{
+ const String SYLK_LF = String::CreateFromAscii("\x1b :");
+ const String DOUBLE_SEMICOLON = String::CreateFromAscii(";;");
+ const String DOUBLE_DOUBLEQUOTE = String::CreateFromAscii("\"\"");
+}
+
+enum SylkVersion
+{
+ SYLK_SCALC3, // Wrote wrongly quoted strings and unescaped semicolons.
+ SYLK_OOO32, // Correct strings, plus multiline content.
+ SYLK_OWN, // Place our new versions, if any, before this value.
+ SYLK_OTHER // Assume that aliens wrote correct strings.
+};
+
+
+// Gesamtdokument ohne Undo
+
+
+ScImportExport::ScImportExport( ScDocument* p )
+ : pDocSh( PTR_CAST(ScDocShell,p->GetDocumentShell()) ), pDoc( p ),
+ nSizeLimit( 0 ), cSep( '\t' ), cStr( '"' ),
+ bFormulas( FALSE ), bIncludeFiltered( TRUE ),
+ bAll( TRUE ), bSingle( TRUE ), bUndo( FALSE ),
+ bOverflow( FALSE ), mbApi( true ), mExportTextOptions()
+{
+ pUndoDoc = NULL;
+ pExtOptions = NULL;
+}
+
+// Insert am Punkt ohne Bereichschecks
+
+
+ScImportExport::ScImportExport( ScDocument* p, const ScAddress& rPt )
+ : pDocSh( PTR_CAST(ScDocShell,p->GetDocumentShell()) ), pDoc( p ),
+ aRange( rPt ),
+ nSizeLimit( 0 ), cSep( '\t' ), cStr( '"' ),
+ bFormulas( FALSE ), bIncludeFiltered( TRUE ),
+ bAll( FALSE ), bSingle( TRUE ), bUndo( BOOL( pDocSh != NULL ) ),
+ bOverflow( FALSE ), mbApi( true ), mExportTextOptions()
+{
+ pUndoDoc = NULL;
+ pExtOptions = NULL;
+}
+
+
+// ctor with a range is only used for export
+//! ctor with a string (and bSingle=TRUE) is also used for DdeSetData
+
+ScImportExport::ScImportExport( ScDocument* p, const ScRange& r )
+ : pDocSh( PTR_CAST(ScDocShell,p->GetDocumentShell()) ), pDoc( p ),
+ aRange( r ),
+ nSizeLimit( 0 ), cSep( '\t' ), cStr( '"' ),
+ bFormulas( FALSE ), bIncludeFiltered( TRUE ),
+ bAll( FALSE ), bSingle( FALSE ), bUndo( BOOL( pDocSh != NULL ) ),
+ bOverflow( FALSE ), mbApi( true ), mExportTextOptions()
+{
+ pUndoDoc = NULL;
+ pExtOptions = NULL;
+ // Zur Zeit nur in einer Tabelle!
+ aRange.aEnd.SetTab( aRange.aStart.Tab() );
+}
+
+// String auswerten: Entweder Bereich, Punkt oder Gesamtdoc (bei Fehler)
+// Falls eine View existiert, wird die TabNo der View entnommen!
+
+
+ScImportExport::ScImportExport( ScDocument* p, const String& rPos )
+ : pDocSh( PTR_CAST(ScDocShell,p->GetDocumentShell()) ), pDoc( p ),
+ nSizeLimit( 0 ), cSep( '\t' ), cStr( '"' ),
+ bFormulas( FALSE ), bIncludeFiltered( TRUE ),
+ bAll( FALSE ), bSingle( TRUE ), bUndo( BOOL( pDocSh != NULL ) ),
+ bOverflow( FALSE ), mbApi( true ), mExportTextOptions()
+{
+ pUndoDoc = NULL;
+ pExtOptions = NULL;
+
+ SCTAB nTab = ScDocShell::GetCurTab();
+ aRange.aStart.SetTab( nTab );
+ String aPos( rPos );
+ // Benannter Bereich?
+ ScRangeName* pRange = pDoc->GetRangeName();
+ if( pRange )
+ {
+ USHORT nPos;
+ if( pRange->SearchName( aPos, nPos ) )
+ {
+ ScRangeData* pData = (*pRange)[ nPos ];
+ if( pData->HasType( RT_REFAREA )
+ || pData->HasType( RT_ABSAREA )
+ || pData->HasType( RT_ABSPOS ) )
+ pData->GetSymbol( aPos ); // mit dem Inhalt weitertesten
+ }
+ }
+ formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention();
+ // Bereich?
+ if( aRange.Parse( aPos, pDoc, eConv ) & SCA_VALID )
+ bSingle = FALSE;
+ // Zelle?
+ else if( aRange.aStart.Parse( aPos, pDoc, eConv ) & SCA_VALID )
+ aRange.aEnd = aRange.aStart;
+ else
+ bAll = TRUE;
+}
+
+
+ScImportExport::~ScImportExport()
+{
+ delete pUndoDoc;
+ delete pExtOptions;
+}
+
+
+void ScImportExport::SetExtOptions( const ScAsciiOptions& rOpt )
+{
+ if ( pExtOptions )
+ *pExtOptions = rOpt;
+ else
+ pExtOptions = new ScAsciiOptions( rOpt );
+
+ // "normale" Optionen uebernehmen
+
+ cSep = rOpt.GetFieldSeps().GetChar(0);
+ cStr = rOpt.GetTextSep();
+}
+
+
+BOOL ScImportExport::IsFormatSupported( ULONG nFormat )
+{
+ return BOOL( nFormat == FORMAT_STRING
+ || nFormat == SOT_FORMATSTR_ID_SYLK
+ || nFormat == SOT_FORMATSTR_ID_LINK
+ || nFormat == SOT_FORMATSTR_ID_HTML
+ || nFormat == SOT_FORMATSTR_ID_HTML_SIMPLE
+ || nFormat == SOT_FORMATSTR_ID_DIF );
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+// Vorbereitung fuer Undo: Undo-Dokument erzeugen
+
+
+BOOL ScImportExport::StartPaste()
+{
+ if ( !bAll )
+ {
+ ScEditableTester aTester( pDoc, aRange );
+ if ( !aTester.IsEditable() )
+ {
+ InfoBox aInfoBox(Application::GetDefDialogParent(),
+ ScGlobal::GetRscString( aTester.GetMessageId() ) );
+ aInfoBox.Execute();
+ return FALSE;
+ }
+ }
+ if( bUndo && pDocSh && pDoc->IsUndoEnabled())
+ {
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, aRange.aStart.Tab(), aRange.aEnd.Tab() );
+ pDoc->CopyToDocument( aRange, IDF_ALL | IDF_NOCAPTIONS, FALSE, pUndoDoc );
+ }
+ return TRUE;
+}
+
+// Nachbereitung Insert: Undo/Redo-Aktionen erzeugen, Invalidate/Repaint
+
+
+void ScImportExport::EndPaste()
+{
+ BOOL bHeight = pDocSh && pDocSh->AdjustRowHeight(
+ aRange.aStart.Row(), aRange.aEnd.Row(), aRange.aStart.Tab() );
+
+ if( pUndoDoc && pDoc->IsUndoEnabled() )
+ {
+ ScDocument* pRedoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pRedoDoc->InitUndo( pDoc, aRange.aStart.Tab(), aRange.aEnd.Tab() );
+ pDoc->CopyToDocument( aRange, IDF_ALL | IDF_NOCAPTIONS, FALSE, pRedoDoc );
+ ScMarkData aDestMark;
+ aDestMark.SelectOneTable( aRange.aStart.Tab() );
+ pDocSh->GetUndoManager()->AddUndoAction(
+ new ScUndoPaste( pDocSh,
+ aRange.aStart.Col(), aRange.aStart.Row(), aRange.aStart.Tab(),
+ aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aEnd.Tab(), aDestMark,
+ pUndoDoc, pRedoDoc, IDF_ALL, NULL,NULL,NULL,NULL ) );
+ }
+ pUndoDoc = NULL;
+ if( pDocSh )
+ {
+ if (!bHeight)
+ pDocSh->PostPaint( aRange, PAINT_GRID ); // AdjustRowHeight paintet evtl. selber
+ pDocSh->SetDocumentModified();
+ }
+ ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
+ if ( pViewSh )
+ pViewSh->UpdateInputHandler();
+
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+#if 0
+BOOL ScImportExport::ImportData( SvData& rData )
+{
+ ULONG nFmt = rData.GetFormat();
+ if ( nFmt == SOT_FORMATSTR_ID_HTML_SIMPLE )
+ {
+ MSE40HTMLClipFormatObj aMSE40ClpObj;
+ if ( aMSE40ClpObj.GetData( rData ) )
+ {
+ SvStream* pStream = aMSE40ClpObj.GetStream();
+ return ImportStream( *pStream, nFmt );
+ }
+ return FALSE;
+ }
+ else
+ {
+ void* pMem;
+ ULONG nSize = rData.GetMinMemorySize();
+ rData.GetData( &pMem, TRANSFER_REFERENCE );
+ if( nFmt == FORMAT_STRING
+ || nFmt == FORMAT_RTF
+ || nFmt == SOT_FORMATSTR_ID_SYLK
+ || nFmt == SOT_FORMATSTR_ID_HTML
+ || nFmt == SOT_FORMATSTR_ID_DIF )
+ {
+ //! String? Unicode??
+
+ // Stringende ermitteln!
+ sal_Char* pBegin = (sal_Char*) pMem;
+ sal_Char* pEnd = (sal_Char*) pMem + nSize;
+
+ nSize = 0;
+ while( pBegin != pEnd && *pBegin != '\0' )
+ pBegin++, nSize++;
+ // #72909# MT says only STRING has to be zero-terminated
+ DBG_ASSERT( pBegin != pEnd || nFmt != FORMAT_STRING, "non zero-terminated String" )
+ }
+ SvMemoryStream aStrm( pMem, nSize, STREAM_READ );
+ return ImportStream( aStrm, nFmt );
+ }
+}
+
+#endif
+
+BOOL ScImportExport::ImportData( const String& /* rMimeType */,
+ const ::com::sun::star::uno::Any & /* rValue */ )
+{
+ DBG_ASSERT( !this, "Implementation is missing" );
+ return FALSE;
+}
+
+BOOL ScImportExport::ExportData( const String& rMimeType,
+ ::com::sun::star::uno::Any & rValue )
+{
+ SvMemoryStream aStrm;
+ // mba: no BaseURL for data exchange
+ if( ExportStream( aStrm, String(),
+ SotExchange::GetFormatIdFromMimeType( rMimeType ) ))
+ {
+ aStrm << (BYTE) 0;
+ rValue <<= ::com::sun::star::uno::Sequence< sal_Int8 >(
+ (sal_Int8*)aStrm.GetData(),
+ aStrm.Seek( STREAM_SEEK_TO_END ) );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+BOOL ScImportExport::ImportString( const ::rtl::OUString& rText, ULONG nFmt )
+{
+ switch ( nFmt )
+ {
+ // formats supporting unicode
+ case FORMAT_STRING :
+ {
+ ScImportStringStream aStrm( rText);
+ return ImportStream( aStrm, String(), nFmt );
+ // ImportStream must handle RTL_TEXTENCODING_UNICODE
+ }
+ //break;
+ default:
+ {
+ rtl_TextEncoding eEnc = gsl_getSystemTextEncoding();
+ ::rtl::OString aTmp( rText.getStr(), rText.getLength(), eEnc );
+ SvMemoryStream aStrm( (void*)aTmp.getStr(), aTmp.getLength() * sizeof(sal_Char), STREAM_READ );
+ aStrm.SetStreamCharSet( eEnc );
+ SetNoEndianSwap( aStrm ); //! no swapping in memory
+ return ImportStream( aStrm, String(), nFmt );
+ }
+ }
+}
+
+
+BOOL ScImportExport::ExportString( ::rtl::OUString& rText, ULONG nFmt )
+{
+ DBG_ASSERT( nFmt == FORMAT_STRING, "ScImportExport::ExportString: Unicode not supported for other formats than FORMAT_STRING" );
+ if ( nFmt != FORMAT_STRING )
+ {
+ rtl_TextEncoding eEnc = gsl_getSystemTextEncoding();
+ ByteString aTmp;
+ BOOL bOk = ExportByteString( aTmp, eEnc, nFmt );
+ rText = UniString( aTmp, eEnc );
+ return bOk;
+ }
+ // nSizeLimit not needed for OUString
+
+ SvMemoryStream aStrm;
+ aStrm.SetStreamCharSet( RTL_TEXTENCODING_UNICODE );
+ SetNoEndianSwap( aStrm ); //! no swapping in memory
+ // mba: no BaseURL for data exc
+ if( ExportStream( aStrm, String(), nFmt ) )
+ {
+ aStrm << (sal_Unicode) 0;
+ aStrm.Seek( STREAM_SEEK_TO_END );
+
+ rText = rtl::OUString( (const sal_Unicode*) aStrm.GetData() );
+ return TRUE;
+ }
+ rText = rtl::OUString();
+ return FALSE;
+
+ // ExportStream must handle RTL_TEXTENCODING_UNICODE
+}
+
+
+BOOL ScImportExport::ExportByteString( ByteString& rText, rtl_TextEncoding eEnc, ULONG nFmt )
+{
+ DBG_ASSERT( eEnc != RTL_TEXTENCODING_UNICODE, "ScImportExport::ExportByteString: Unicode not supported" );
+ if ( eEnc == RTL_TEXTENCODING_UNICODE )
+ eEnc = gsl_getSystemTextEncoding();
+
+ if (!nSizeLimit)
+ nSizeLimit = STRING_MAXLEN;
+
+ SvMemoryStream aStrm;
+ aStrm.SetStreamCharSet( eEnc );
+ SetNoEndianSwap( aStrm ); //! no swapping in memory
+ // mba: no BaseURL for data exchange
+ if( ExportStream( aStrm, String(), nFmt ) )
+ {
+ aStrm << (sal_Char) 0;
+ aStrm.Seek( STREAM_SEEK_TO_END );
+ // Sicherheits-Check:
+ if( aStrm.Tell() <= (ULONG) STRING_MAXLEN )
+ {
+ rText = (const sal_Char*) aStrm.GetData();
+ return TRUE;
+ }
+ }
+ rText.Erase();
+ return FALSE;
+}
+
+
+BOOL ScImportExport::ImportStream( SvStream& rStrm, const String& rBaseURL, ULONG nFmt )
+{
+ if( nFmt == FORMAT_STRING )
+ {
+ if( ExtText2Doc( rStrm ) ) // pExtOptions auswerten
+ return TRUE;
+ }
+ if( nFmt == SOT_FORMATSTR_ID_SYLK )
+ {
+ if( Sylk2Doc( rStrm ) )
+ return TRUE;
+ }
+ if( nFmt == SOT_FORMATSTR_ID_DIF )
+ {
+ if( Dif2Doc( rStrm ) )
+ return TRUE;
+ }
+ if( nFmt == FORMAT_RTF )
+ {
+ if( RTF2Doc( rStrm, rBaseURL ) )
+ return TRUE;
+ }
+ if( nFmt == SOT_FORMATSTR_ID_LINK )
+ return TRUE; // Link-Import?
+ if ( nFmt == SOT_FORMATSTR_ID_HTML )
+ {
+ if( HTML2Doc( rStrm, rBaseURL ) )
+ return TRUE;
+ }
+ if ( nFmt == SOT_FORMATSTR_ID_HTML_SIMPLE )
+ {
+ MSE40HTMLClipFormatObj aMSE40ClpObj; // needed to skip the header data
+ SvStream* pHTML = aMSE40ClpObj.IsValid( rStrm );
+ if ( pHTML && HTML2Doc( *pHTML, rBaseURL ) )
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+BOOL ScImportExport::ExportStream( SvStream& rStrm, const String& rBaseURL, ULONG nFmt )
+{
+ if( nFmt == FORMAT_STRING )
+ {
+ if( Doc2Text( rStrm ) )
+ return TRUE;
+ }
+ if( nFmt == SOT_FORMATSTR_ID_SYLK )
+ {
+ if( Doc2Sylk( rStrm ) )
+ return TRUE;
+ }
+ if( nFmt == SOT_FORMATSTR_ID_DIF )
+ {
+ if( Doc2Dif( rStrm ) )
+ return TRUE;
+ }
+ if( nFmt == SOT_FORMATSTR_ID_LINK && !bAll )
+ {
+ String aDocName;
+ if ( pDoc->IsClipboard() )
+ aDocName = ScGlobal::GetClipDocName();
+ else
+ {
+ SfxObjectShell* pShell = pDoc->GetDocumentShell();
+ if (pShell)
+ aDocName = pShell->GetTitle( SFX_TITLE_FULLNAME );
+ }
+
+ DBG_ASSERT( aDocName.Len(), "ClipBoard document has no name! :-/" );
+ if( aDocName.Len() )
+ {
+ String aRefName;
+ USHORT nFlags = SCA_VALID | SCA_TAB_3D;
+ if( bSingle )
+ aRange.aStart.Format( aRefName, nFlags, pDoc, pDoc->GetAddressConvention() );
+ else
+ {
+ if( aRange.aStart.Tab() != aRange.aEnd.Tab() )
+ nFlags |= SCA_TAB2_3D;
+ aRange.Format( aRefName, nFlags, pDoc );
+ }
+ String aAppName = Application::GetAppName();
+
+ WriteUnicodeOrByteString( rStrm, aAppName, TRUE );
+ WriteUnicodeOrByteString( rStrm, aDocName, TRUE );
+ WriteUnicodeOrByteString( rStrm, aRefName, TRUE );
+ if ( rStrm.GetStreamCharSet() == RTL_TEXTENCODING_UNICODE )
+ rStrm << sal_Unicode(0);
+ else
+ rStrm << sal_Char(0);
+ return BOOL( rStrm.GetError() == SVSTREAM_OK );
+ }
+ }
+ if( nFmt == SOT_FORMATSTR_ID_HTML )
+ {
+ if( Doc2HTML( rStrm, rBaseURL ) )
+ return TRUE;
+ }
+ if( nFmt == FORMAT_RTF )
+ {
+ if( Doc2RTF( rStrm ) )
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+//static
+void ScImportExport::WriteUnicodeOrByteString( SvStream& rStrm, const String& rString, BOOL bZero )
+{
+ rtl_TextEncoding eEnc = rStrm.GetStreamCharSet();
+ if ( eEnc == RTL_TEXTENCODING_UNICODE )
+ {
+ if ( !IsEndianSwap( rStrm ) )
+ rStrm.Write( rString.GetBuffer(), rString.Len() * sizeof(sal_Unicode) );
+ else
+ {
+ const sal_Unicode* p = rString.GetBuffer();
+ const sal_Unicode* const pStop = p + rString.Len();
+ while ( p < pStop )
+ {
+ rStrm << *p;
+ }
+ }
+ if ( bZero )
+ rStrm << sal_Unicode(0);
+ }
+ else
+ {
+ ByteString aByteStr( rString, eEnc );
+ rStrm << aByteStr.GetBuffer();
+ if ( bZero )
+ rStrm << sal_Char(0);
+ }
+}
+
+
+// This function could be replaced by endlub()
+// static
+void ScImportExport::WriteUnicodeOrByteEndl( SvStream& rStrm )
+{
+ if ( rStrm.GetStreamCharSet() == RTL_TEXTENCODING_UNICODE )
+ { // same as endl() but unicode
+ switch ( rStrm.GetLineDelimiter() )
+ {
+ case LINEEND_CR :
+ rStrm << sal_Unicode(_CR);
+ break;
+ case LINEEND_LF :
+ rStrm << sal_Unicode(_LF);
+ break;
+ default:
+ rStrm << sal_Unicode(_CR) << sal_Unicode(_LF);
+ }
+ }
+ else
+ endl( rStrm );
+}
+
+
+enum DoubledQuoteMode
+{
+ DQM_KEEP, // both are taken
+ DQM_ESCAPE, // escaped quote, one is taken, one ignored
+ DQM_CONCAT, // first is end, next is start, both ignored => strings combined
+ DQM_SEPARATE // end one string and begin next
+};
+
+static const sal_Unicode* lcl_ScanString( const sal_Unicode* p, String& rString,
+ sal_Unicode cStr, DoubledQuoteMode eMode )
+{
+ p++; //! jump over opening quote
+ BOOL bCont;
+ do
+ {
+ bCont = FALSE;
+ const sal_Unicode* p0 = p;
+ for( ;; )
+ {
+ if( !*p )
+ break;
+ if( *p == cStr )
+ {
+ if ( *++p != cStr )
+ break;
+ // doubled quote char
+ switch ( eMode )
+ {
+ case DQM_KEEP :
+ p++; // both for us (not breaking for-loop)
+ break;
+ case DQM_ESCAPE :
+ p++; // one for us (breaking for-loop)
+ bCont = TRUE; // and more
+ break;
+ case DQM_CONCAT :
+ if ( p0+1 < p )
+ rString.Append( p0, sal::static_int_cast<xub_StrLen>( (p-1) - p0 ) ); // first part
+ p0 = ++p; // text of next part starts here
+ break;
+ case DQM_SEPARATE :
+ // positioned on next opening quote
+ break;
+ }
+ if ( eMode == DQM_ESCAPE || eMode == DQM_SEPARATE )
+ break;
+ }
+ else
+ p++;
+ }
+ if ( p0 < p )
+ rString.Append( p0, sal::static_int_cast<xub_StrLen>( ((*p || *(p-1) == cStr) ? p-1 : p) - p0 ) );
+ } while ( bCont );
+ return p;
+}
+
+void lcl_UnescapeSylk( String & rString, SylkVersion eVersion )
+{
+ // Older versions didn't escape the semicolon.
+ // Older versions quoted the string and doubled embedded quotes, but not
+ // the semicolons, which was plain wrong.
+ if (eVersion >= SYLK_OOO32)
+ rString.SearchAndReplaceAll( DOUBLE_SEMICOLON, ';' );
+ else
+ rString.SearchAndReplaceAll( DOUBLE_DOUBLEQUOTE, '"' );
+
+ rString.SearchAndReplaceAll( SYLK_LF, _LF );
+}
+
+static const sal_Unicode* lcl_ScanSylkString( const sal_Unicode* p,
+ String& rString, SylkVersion eVersion )
+{
+ const sal_Unicode* pStartQuote = p;
+ const sal_Unicode* pEndQuote = 0;
+ while( *(++p) )
+ {
+ if( *p == '"' )
+ {
+ pEndQuote = p;
+ if (eVersion >= SYLK_OOO32)
+ {
+ if (*(p+1) == ';')
+ {
+ if (*(p+2) == ';')
+ {
+ p += 2; // escaped ';'
+ pEndQuote = 0;
+ }
+ else
+ break; // end field
+ }
+ }
+ else
+ {
+ if (*(p+1) == '"')
+ {
+ ++p; // escaped '"'
+ pEndQuote = 0;
+ }
+ else if (*(p+1) == ';')
+ break; // end field
+ }
+ }
+ }
+ if (!pEndQuote)
+ pEndQuote = p; // Take all data as string.
+ rString.Append( pStartQuote + 1, sal::static_int_cast<xub_StrLen>( pEndQuote - pStartQuote - 1 ) );
+ lcl_UnescapeSylk( rString, eVersion);
+ return p;
+}
+
+static const sal_Unicode* lcl_ScanSylkFormula( const sal_Unicode* p,
+ String& rString, SylkVersion eVersion )
+{
+ const sal_Unicode* pStart = p;
+ if (eVersion >= SYLK_OOO32)
+ {
+ while (*p)
+ {
+ if (*p == ';')
+ {
+ if (*(p+1) == ';')
+ ++p; // escaped ';'
+ else
+ break; // end field
+ }
+ ++p;
+ }
+ rString.Append( pStart, sal::static_int_cast<xub_StrLen>( p - pStart));
+ lcl_UnescapeSylk( rString, eVersion);
+ }
+ else
+ {
+ // Nasty. If in old versions the formula contained a semicolon, it was
+ // quoted and embedded quotes were doubled, but semicolons were not. If
+ // there was no semicolon, it could still contain quotes and doubled
+ // embedded quotes if it was something like ="a""b", which was saved as
+ // E"a""b" as is and has to be preserved, even if older versions
+ // couldn't even load it correctly. However, theoretically another
+ // field might follow and thus the line contain a semicolon again, such
+ // as ...;E"a""b";...
+ bool bQuoted = false;
+ if (*p == '"')
+ {
+ // May be a quoted expression or just a string constant expression
+ // with quotes.
+ while (*(++p))
+ {
+ if (*p == '"')
+ {
+ if (*(p+1) == '"')
+ ++p; // escaped '"'
+ else
+ break; // closing '"', had no ';' yet
+ }
+ else if (*p == ';')
+ {
+ bQuoted = true; // ';' within quoted expression
+ break;
+ }
+ }
+ p = pStart;
+ }
+ if (bQuoted)
+ p = lcl_ScanSylkString( p, rString, eVersion);
+ else
+ {
+ while (*p && *p != ';')
+ ++p;
+ rString.Append( pStart, sal::static_int_cast<xub_StrLen>( p - pStart));
+ }
+ }
+ return p;
+}
+
+static void lcl_DoubleEscapeChar( String& rString, sal_Unicode cStr )
+{
+ xub_StrLen n = 0;
+ while( ( n = rString.Search( cStr, n ) ) != STRING_NOTFOUND )
+ {
+ rString.Insert( cStr, n );
+ n += 2;
+ }
+}
+
+static void lcl_WriteString( SvStream& rStrm, String& rString, sal_Unicode cQuote, sal_Unicode cEsc )
+{
+ if (cEsc)
+ lcl_DoubleEscapeChar( rString, cEsc );
+
+ if (cQuote)
+ {
+ rString.Insert( cQuote, 0 );
+ rString.Append( cQuote );
+ }
+
+ ScImportExport::WriteUnicodeOrByteString( rStrm, rString );
+}
+
+inline void lcl_WriteSimpleString( SvStream& rStrm, const String& rString )
+{
+ ScImportExport::WriteUnicodeOrByteString( rStrm, rString );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+BOOL ScImportExport::Text2Doc( SvStream& rStrm )
+{
+ BOOL bOk = TRUE;
+
+ SCCOL nStartCol = aRange.aStart.Col();
+ SCROW nStartRow = aRange.aStart.Row();
+ SCCOL nEndCol = aRange.aEnd.Col();
+ SCROW nEndRow = aRange.aEnd.Row();
+ ULONG nOldPos = rStrm.Tell();
+ if ( rStrm.GetStreamCharSet() == RTL_TEXTENCODING_UNICODE )
+ rStrm.StartReadingUnicodeText();
+ BOOL bData = BOOL( !bSingle );
+ if( !bSingle)
+ bOk = StartPaste();
+
+ while( bOk )
+ {
+ ByteString aByteLine;
+ String aLine, aCell;
+ SCROW nRow = nStartRow;
+ rStrm.Seek( nOldPos );
+ for( ;; )
+ {
+ rStrm.ReadUniOrByteStringLine( aLine );
+ if( rStrm.IsEof() )
+ break;
+ SCCOL nCol = nStartCol;
+ const sal_Unicode* p = aLine.GetBuffer();
+ while( *p )
+ {
+ aCell.Erase();
+ if( *p == cStr )
+ {
+ p = lcl_ScanString( p, aCell, cStr, DQM_KEEP );
+ while( *p && *p != cSep )
+ p++;
+ if( *p )
+ p++;
+ }
+ else
+ {
+ const sal_Unicode* q = p;
+ while( *p && *p != cSep )
+ p++;
+ aCell.Assign( q, sal::static_int_cast<xub_StrLen>( p - q ) );
+ if( *p )
+ p++;
+ }
+ if (ValidCol(nCol) && ValidRow(nRow) )
+ {
+ if( bSingle )
+ {
+ if (nCol>nEndCol) nEndCol = nCol;
+ if (nRow>nEndRow) nEndRow = nRow;
+ }
+ if( bData && nCol <= nEndCol && nRow <= nEndRow )
+ pDoc->SetString( nCol, nRow, aRange.aStart.Tab(), aCell );
+ }
+ else // zuviele Spalten/Zeilen
+ bOverflow = TRUE; // beim Import Warnung ausgeben
+ ++nCol;
+ }
+ ++nRow;
+ }
+
+ if( !bData )
+ {
+ aRange.aEnd.SetCol( nEndCol );
+ aRange.aEnd.SetRow( nEndRow );
+ bOk = StartPaste();
+ bData = TRUE;
+ }
+ else
+ break;
+ }
+
+ EndPaste();
+ return bOk;
+}
+
+ //
+ // erweiterter Ascii-Import
+ //
+
+
+bool lcl_PutString( ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab,
+ const String& rStr, BYTE nColFormat,
+ ::utl::TransliterationWrapper& rTransliteration,
+ CalendarWrapper& rCalendar,
+ ::utl::TransliterationWrapper* pSecondTransliteration,
+ CalendarWrapper* pSecondCalendar )
+{
+ bool bMultiLine = false;
+ if ( nColFormat == SC_COL_SKIP || !rStr.Len() || !ValidCol(nCol) || !ValidRow(nRow) )
+ return bMultiLine;
+
+ if ( nColFormat == SC_COL_TEXT )
+ {
+ pDoc->PutCell( nCol, nRow, nTab, ScBaseCell::CreateTextCell( rStr, pDoc ) );
+ return bMultiLine;
+ }
+
+ if ( nColFormat == SC_COL_ENGLISH )
+ {
+ //! SetString mit Extra-Flag ???
+
+ SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
+ sal_uInt32 nEnglish = pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US);
+ double fVal;
+ if ( pFormatter->IsNumberFormat( rStr, nEnglish, fVal ) )
+ {
+ // Zahlformat wird nicht auf englisch gesetzt
+ pDoc->SetValue( nCol, nRow, nTab, fVal );
+ return bMultiLine;
+ }
+ // sonst weiter mit SetString
+ }
+ else if ( nColFormat != SC_COL_STANDARD ) // Datumsformate
+ {
+ const USHORT nMaxNumberParts = 7; // Y-M-D h:m:s.t
+ xub_StrLen nLen = rStr.Len();
+ xub_StrLen nStart[nMaxNumberParts];
+ xub_StrLen nEnd[nMaxNumberParts];
+
+ USHORT nDP, nMP, nYP;
+ switch ( nColFormat )
+ {
+ case SC_COL_YMD: nDP = 2; nMP = 1; nYP = 0; break;
+ case SC_COL_MDY: nDP = 1; nMP = 0; nYP = 2; break;
+ case SC_COL_DMY:
+ default: nDP = 0; nMP = 1; nYP = 2; break;
+ }
+
+ USHORT nFound = 0;
+ BOOL bInNum = FALSE;
+ for ( xub_StrLen nPos=0; nPos<nLen && (bInNum ||
+ nFound<nMaxNumberParts); nPos++ )
+ {
+ if (bInNum && nFound == 3 && nColFormat == SC_COL_YMD &&
+ nPos <= nStart[nFound]+2 && rStr.GetChar(nPos) == 'T')
+ bInNum = FALSE; // ISO-8601: YYYY-MM-DDThh:mm...
+ else if ((((!bInNum && nFound==nMP) || (bInNum && nFound==nMP+1))
+ && ScGlobal::pCharClass->isLetterNumeric( rStr, nPos))
+ || ScGlobal::pCharClass->isDigit( rStr, nPos))
+ {
+ if (!bInNum)
+ {
+ bInNum = TRUE;
+ nStart[nFound] = nPos;
+ ++nFound;
+ }
+ nEnd[nFound-1] = nPos;
+ }
+ else
+ bInNum = FALSE;
+ }
+
+ if ( nFound == 1 )
+ {
+ // try to break one number (without separators) into date fields
+
+ xub_StrLen nDateStart = nStart[0];
+ xub_StrLen nDateLen = nEnd[0] + 1 - nDateStart;
+
+ if ( nDateLen >= 5 && nDateLen <= 8 &&
+ ScGlobal::pCharClass->isNumeric( rStr.Copy( nDateStart, nDateLen ) ) )
+ {
+ // 6 digits: 2 each for day, month, year
+ // 8 digits: 4 for year, 2 each for day and month
+ // 5 or 7 digits: first field is shortened by 1
+
+ BOOL bLongYear = ( nDateLen >= 7 );
+ BOOL bShortFirst = ( nDateLen == 5 || nDateLen == 7 );
+
+ USHORT nFieldStart = nDateStart;
+ for (USHORT nPos=0; nPos<3; nPos++)
+ {
+ USHORT nFieldEnd = nFieldStart + 1; // default: 2 digits
+ if ( bLongYear && nPos == nYP )
+ nFieldEnd += 2; // 2 extra digits for long year
+ if ( bShortFirst && nPos == 0 )
+ --nFieldEnd; // first field shortened?
+
+ nStart[nPos] = nFieldStart;
+ nEnd[nPos] = nFieldEnd;
+ nFieldStart = nFieldEnd + 1;
+ }
+ nFound = 3;
+ }
+ }
+
+ if ( nFound >= 3 )
+ {
+ using namespace ::com::sun::star;
+ BOOL bSecondCal = FALSE;
+ USHORT nDay = (USHORT) rStr.Copy( nStart[nDP], nEnd[nDP]+1-nStart[nDP] ).ToInt32();
+ USHORT nYear = (USHORT) rStr.Copy( nStart[nYP], nEnd[nYP]+1-nStart[nYP] ).ToInt32();
+ String aMStr = rStr.Copy( nStart[nMP], nEnd[nMP]+1-nStart[nMP] );
+ sal_Int16 nMonth = (sal_Int16) aMStr.ToInt32();
+ if (!nMonth)
+ {
+ static const String aSeptCorrect( RTL_CONSTASCII_USTRINGPARAM( "SEPT" ) );
+ static const String aSepShortened( RTL_CONSTASCII_USTRINGPARAM( "SEP" ) );
+ uno::Sequence< i18n::CalendarItem > xMonths;
+ sal_Int32 i, nMonthCount;
+ // first test all month names from local international
+ xMonths = rCalendar.getMonths();
+ nMonthCount = xMonths.getLength();
+ for (i=0; i<nMonthCount && !nMonth; i++)
+ {
+ if ( rTransliteration.isEqual( aMStr, xMonths[i].FullName ) ||
+ rTransliteration.isEqual( aMStr, xMonths[i].AbbrevName ) )
+ nMonth = sal::static_int_cast<sal_Int16>( i+1 );
+ else if ( i == 8 && rTransliteration.isEqual( aSeptCorrect,
+ xMonths[i].AbbrevName ) &&
+ rTransliteration.isEqual( aMStr, aSepShortened ) )
+ { // #102136# correct English abbreviation is SEPT,
+ // but data mostly contains SEP only
+ nMonth = sal::static_int_cast<sal_Int16>( i+1 );
+ }
+ }
+ // if none found, then test english month names
+ if ( !nMonth && pSecondCalendar && pSecondTransliteration )
+ {
+ xMonths = pSecondCalendar->getMonths();
+ nMonthCount = xMonths.getLength();
+ for (i=0; i<nMonthCount && !nMonth; i++)
+ {
+ if ( pSecondTransliteration->isEqual( aMStr, xMonths[i].FullName ) ||
+ pSecondTransliteration->isEqual( aMStr, xMonths[i].AbbrevName ) )
+ {
+ nMonth = sal::static_int_cast<sal_Int16>( i+1 );
+ bSecondCal = TRUE;
+ }
+ else if ( i == 8 && pSecondTransliteration->isEqual(
+ aMStr, aSepShortened ) )
+ { // #102136# correct English abbreviation is SEPT,
+ // but data mostly contains SEP only
+ nMonth = sal::static_int_cast<sal_Int16>( i+1 );
+ bSecondCal = TRUE;
+ }
+ }
+ }
+ }
+
+ SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
+ if ( nYear < 100 )
+ nYear = pFormatter->ExpandTwoDigitYear( nYear );
+
+ CalendarWrapper* pCalendar = (bSecondCal ? pSecondCalendar : &rCalendar);
+ sal_Int16 nNumMonths = pCalendar->getNumberOfMonthsInYear();
+ if ( nDay && nMonth && nDay<=31 && nMonth<=nNumMonths )
+ {
+ --nMonth;
+ pCalendar->setValue( i18n::CalendarFieldIndex::DAY_OF_MONTH, nDay );
+ pCalendar->setValue( i18n::CalendarFieldIndex::MONTH, nMonth );
+ pCalendar->setValue( i18n::CalendarFieldIndex::YEAR, nYear );
+ sal_Int16 nHour, nMinute, nSecond, nMilli;
+ // #i14974# The imported value should have no fractional value, so set the
+ // time fields to zero (ICU calendar instance defaults to current date/time)
+ nHour = nMinute = nSecond = nMilli = 0;
+ if (nFound > 3)
+ nHour = (sal_Int16) rStr.Copy( nStart[3], nEnd[3]+1-nStart[3]).ToInt32();
+ if (nFound > 4)
+ nMinute = (sal_Int16) rStr.Copy( nStart[4], nEnd[4]+1-nStart[4]).ToInt32();
+ if (nFound > 5)
+ nSecond = (sal_Int16) rStr.Copy( nStart[5], nEnd[5]+1-nStart[5]).ToInt32();
+ if (nFound > 6)
+ {
+ sal_Unicode cDec = '.';
+ rtl::OUString aT( &cDec, 1);
+ aT += rStr.Copy( nStart[6], nEnd[6]+1-nStart[6]);
+ rtl_math_ConversionStatus eStatus;
+ double fV = rtl::math::stringToDouble( aT, cDec, 0, &eStatus, 0);
+ if (eStatus == rtl_math_ConversionStatus_Ok)
+ nMilli = (sal_Int16) (1000.0 * fV + 0.5);
+ }
+ pCalendar->setValue( i18n::CalendarFieldIndex::HOUR, nHour );
+ pCalendar->setValue( i18n::CalendarFieldIndex::MINUTE, nMinute );
+ pCalendar->setValue( i18n::CalendarFieldIndex::SECOND, nSecond );
+ pCalendar->setValue( i18n::CalendarFieldIndex::MILLISECOND, nMilli );
+ if ( pCalendar->isValid() )
+ {
+ double fDiff = DateTime(*pFormatter->GetNullDate()) -
+ pCalendar->getEpochStart();
+ // #i14974# must use getLocalDateTime to get the same
+ // date values as set above
+ double fDays = pCalendar->getLocalDateTime();
+ fDays -= fDiff;
+
+ LanguageType eLatin, eCjk, eCtl;
+ pDoc->GetLanguage( eLatin, eCjk, eCtl );
+ LanguageType eDocLang = eLatin; //! which language for date formats?
+
+ short nType = (nFound > 3 ? NUMBERFORMAT_DATETIME : NUMBERFORMAT_DATE);
+ ULONG nFormat = pFormatter->GetStandardFormat( nType, eDocLang );
+ // maybe there is a special format including seconds or milliseconds
+ if (nFound > 5)
+ nFormat = pFormatter->GetStandardFormat( fDays, nFormat, nType, eDocLang);
+
+ pDoc->PutCell( nCol, nRow, nTab, new ScValueCell(fDays), nFormat, FALSE );
+
+ return bMultiLine; // success
+ }
+ }
+ }
+ }
+
+ // Standard or date not determined -> SetString / EditCell
+ if( rStr.Search( _LF ) == STRING_NOTFOUND )
+ pDoc->SetString( nCol, nRow, nTab, rStr );
+ else
+ {
+ bMultiLine = true;
+ pDoc->PutCell( nCol, nRow, nTab, new ScEditCell( rStr, pDoc ) );
+ }
+ return bMultiLine;
+}
+
+
+String lcl_GetFixed( const String& rLine, xub_StrLen nStart, xub_StrLen nNext )
+{
+ xub_StrLen nLen = rLine.Len();
+ if (nNext > nLen)
+ nNext = nLen;
+ if ( nNext <= nStart )
+ return EMPTY_STRING;
+
+ const sal_Unicode* pStr = rLine.GetBuffer();
+
+ xub_StrLen nSpace = nNext;
+ while ( nSpace > nStart && pStr[nSpace-1] == ' ' )
+ --nSpace;
+
+ return rLine.Copy( nStart, nSpace-nStart );
+}
+
+BOOL ScImportExport::ExtText2Doc( SvStream& rStrm )
+{
+ if (!pExtOptions)
+ return Text2Doc( rStrm );
+
+ ULONG nOldPos = rStrm.Tell();
+ rStrm.Seek( STREAM_SEEK_TO_END );
+ ::std::auto_ptr<ScProgress> xProgress( new ScProgress( pDocSh,
+ ScGlobal::GetRscString( STR_LOAD_DOC ), rStrm.Tell() - nOldPos ));
+ rStrm.Seek( nOldPos );
+ if ( rStrm.GetStreamCharSet() == RTL_TEXTENCODING_UNICODE )
+ rStrm.StartReadingUnicodeText();
+
+ BOOL bOld = ScColumn::bDoubleAlloc;
+ ScColumn::bDoubleAlloc = TRUE;
+
+ SCCOL nStartCol = aRange.aStart.Col();
+ SCCOL nEndCol = aRange.aEnd.Col();
+ SCROW nStartRow = aRange.aStart.Row();
+ SCTAB nTab = aRange.aStart.Tab();
+
+ BOOL bFixed = pExtOptions->IsFixedLen();
+ const String& rSeps = pExtOptions->GetFieldSeps();
+ const sal_Unicode* pSeps = rSeps.GetBuffer();
+ BOOL bMerge = pExtOptions->IsMergeSeps();
+ USHORT nInfoCount = pExtOptions->GetInfoCount();
+ const xub_StrLen* pColStart = pExtOptions->GetColStart();
+ const BYTE* pColFormat = pExtOptions->GetColFormat();
+ long nSkipLines = pExtOptions->GetStartRow();
+
+ LanguageType eLatin, eCjk, eCtl;
+ pDoc->GetLanguage( eLatin, eCjk, eCtl );
+ LanguageType eDocLang = eLatin; //! which language for date formats?
+
+ // For date recognition
+ ::utl::TransliterationWrapper aTransliteration(
+ pDoc->GetServiceManager(), SC_TRANSLITERATION_IGNORECASE );
+ aTransliteration.loadModuleIfNeeded( eDocLang );
+ CalendarWrapper aCalendar( pDoc->GetServiceManager() );
+ aCalendar.loadDefaultCalendar(
+ MsLangId::convertLanguageToLocale( eDocLang ) );
+ ::utl::TransliterationWrapper* pEnglishTransliteration = NULL;
+ CalendarWrapper* pEnglishCalendar = NULL;
+ if ( eDocLang != LANGUAGE_ENGLISH_US )
+ {
+ pEnglishTransliteration = new ::utl::TransliterationWrapper (
+ pDoc->GetServiceManager(), SC_TRANSLITERATION_IGNORECASE );
+ aTransliteration.loadModuleIfNeeded( LANGUAGE_ENGLISH_US );
+ pEnglishCalendar = new CalendarWrapper ( pDoc->GetServiceManager() );
+ pEnglishCalendar->loadDefaultCalendar(
+ MsLangId::convertLanguageToLocale( LANGUAGE_ENGLISH_US ) );
+ }
+
+ String aLine, aCell;
+ USHORT i;
+ SCROW nRow = nStartRow;
+
+ while(--nSkipLines>0)
+ {
+ rStrm.ReadCsvLine( aLine, !bFixed, rSeps, cStr); // content is ignored
+ if ( rStrm.IsEof() )
+ break;
+ }
+
+ // Determine range for Undo.
+ // TODO: we don't need this during import of a file to a new sheet or
+ // document, could set bDetermineRange=false then.
+ bool bDetermineRange = true;
+
+ // Row heights don't need to be adjusted on the fly if EndPaste() is called
+ // afterwards, which happens only if bDetermineRange. This variable also
+ // survives the toggle of bDetermineRange down at the end of the do{} loop.
+ bool bRangeIsDetermined = bDetermineRange;
+
+ ULONG nOriginalStreamPos = rStrm.Tell();
+
+ do
+ {
+ for( ;; )
+ {
+ rStrm.ReadCsvLine( aLine, !bFixed, rSeps, cStr);
+ if ( rStrm.IsEof() )
+ break;
+
+ xub_StrLen nLineLen = aLine.Len();
+ SCCOL nCol = nStartCol;
+ bool bMultiLine = false;
+ if ( bFixed ) // Feste Satzlaenge
+ {
+ // Yes, the check is nCol<=MAXCOL+1, +1 because it is only an
+ // overflow if there is really data following to be put behind
+ // the last column, which doesn't happen if info is
+ // SC_COL_SKIP.
+ for ( i=0; i<nInfoCount && nCol <= MAXCOL+1; i++ )
+ {
+ if ( pColFormat[i] != SC_COL_SKIP ) // sonst auch nCol nicht hochzaehlen
+ {
+ if (nCol > MAXCOL)
+ bOverflow = TRUE; // display warning on import
+ else if (!bDetermineRange)
+ {
+ xub_StrLen nStart = pColStart[i];
+ xub_StrLen nNext = ( i+1 < nInfoCount ) ? pColStart[i+1] : nLineLen;
+ aCell = lcl_GetFixed( aLine, nStart, nNext );
+ bMultiLine |= lcl_PutString( pDoc, nCol, nRow,
+ nTab, aCell, pColFormat[i],
+ aTransliteration, aCalendar,
+ pEnglishTransliteration, pEnglishCalendar);
+ }
+ ++nCol;
+ }
+ }
+ }
+ else // Nach Trennzeichen suchen
+ {
+ SCCOL nSourceCol = 0;
+ USHORT nInfoStart = 0;
+ const sal_Unicode* p = aLine.GetBuffer();
+ // Yes, the check is nCol<=MAXCOL+1, +1 because it is only an
+ // overflow if there is really data following to be put behind
+ // the last column, which doesn't happen if info is
+ // SC_COL_SKIP.
+ while (*p && nCol <= MAXCOL+1)
+ {
+ p = ScImportExport::ScanNextFieldFromString( p, aCell, cStr, pSeps, bMerge );
+
+ BYTE nFmt = SC_COL_STANDARD;
+ for ( i=nInfoStart; i<nInfoCount; i++ )
+ {
+ if ( pColStart[i] == nSourceCol + 1 ) // pColStart ist 1-basiert
+ {
+ nFmt = pColFormat[i];
+ nInfoStart = i + 1; // ColInfos sind in Reihenfolge
+ break; // for
+ }
+ }
+ if ( nFmt != SC_COL_SKIP )
+ {
+ if (nCol > MAXCOL)
+ bOverflow = TRUE; // display warning on import
+ else if (!bDetermineRange)
+ bMultiLine |= lcl_PutString( pDoc, nCol, nRow,
+ nTab, aCell, nFmt, aTransliteration,
+ aCalendar, pEnglishTransliteration,
+ pEnglishCalendar);
+ ++nCol;
+ }
+
+ ++nSourceCol;
+ }
+ }
+ if (nEndCol < nCol)
+ nEndCol = nCol; //! points to the next free or even MAXCOL+2
+
+ if (!bDetermineRange)
+ {
+ if (bMultiLine && !bRangeIsDetermined && pDocSh)
+ pDocSh->AdjustRowHeight( nRow, nRow, nTab);
+ xProgress->SetStateOnPercent( rStrm.Tell() - nOldPos );
+ }
+ ++nRow;
+ if ( nRow > MAXROW )
+ {
+ bOverflow = TRUE; // display warning on import
+ break; // for
+ }
+ }
+ // so far nRow/nEndCol pointed to the next free
+ if (nRow > nStartRow)
+ --nRow;
+ if (nEndCol > nStartCol)
+ nEndCol = ::std::min( static_cast<SCCOL>(nEndCol - 1), MAXCOL);
+
+ if (bDetermineRange)
+ {
+ aRange.aEnd.SetCol( nEndCol );
+ aRange.aEnd.SetRow( nRow );
+
+ if ( !mbApi && nStartCol != nEndCol &&
+ !pDoc->IsBlockEmpty( nTab, nStartCol + 1, nStartRow, nEndCol, nRow ) )
+ {
+ ScReplaceWarnBox aBox( pDocSh->GetActiveDialogParent() );
+ if ( aBox.Execute() != RET_YES )
+ {
+ delete pEnglishTransliteration;
+ delete pEnglishCalendar;
+ return FALSE;
+ }
+ }
+
+ rStrm.Seek( nOriginalStreamPos );
+ nRow = nStartRow;
+ if (!StartPaste())
+ {
+ EndPaste();
+ return FALSE;
+ }
+ }
+
+ bDetermineRange = !bDetermineRange; // toggle
+ } while (!bDetermineRange);
+
+ ScColumn::bDoubleAlloc = bOld;
+ pDoc->DoColResize( nTab, nStartCol, nEndCol, 0 );
+
+ delete pEnglishTransliteration;
+ delete pEnglishCalendar;
+
+ xProgress.reset(); // make room for AdjustRowHeight progress
+ if (bRangeIsDetermined)
+ EndPaste();
+
+ return TRUE;
+}
+
+
+// static
+const sal_Unicode* ScImportExport::ScanNextFieldFromString( const sal_Unicode* p,
+ String& rField, sal_Unicode cStr, const sal_Unicode* pSeps, BOOL bMergeSeps )
+{
+ rField.Erase();
+ if ( *p == cStr ) // String in Anfuehrungszeichen
+ {
+ const sal_Unicode* p1;
+ p1 = p = lcl_ScanString( p, rField, cStr, DQM_ESCAPE );
+ while ( *p && !ScGlobal::UnicodeStrChr( pSeps, *p ) )
+ p++;
+ // Append remaining unquoted and undelimited data (dirty, dirty) to
+ // this field.
+ if (p > p1)
+ rField.Append( p1, sal::static_int_cast<xub_StrLen>( p - p1 ) );
+ if( *p )
+ p++;
+ }
+ else // bis zum Trennzeichen
+ {
+ const sal_Unicode* p0 = p;
+ while ( *p && !ScGlobal::UnicodeStrChr( pSeps, *p ) )
+ p++;
+ rField.Append( p0, sal::static_int_cast<xub_StrLen>( p - p0 ) );
+ if( *p )
+ p++;
+ }
+ if ( bMergeSeps ) // folgende Trennzeichen ueberspringen
+ {
+ while ( *p && ScGlobal::UnicodeStrChr( pSeps, *p ) )
+ p++;
+ }
+ return p;
+}
+
+ //
+ //
+ //
+
+
+BOOL ScImportExport::Doc2Text( SvStream& rStrm )
+{
+ SCCOL nCol;
+ SCROW nRow;
+ SCCOL nStartCol = aRange.aStart.Col();
+ SCROW nStartRow = aRange.aStart.Row();
+ SCCOL nEndCol = aRange.aEnd.Col();
+ SCROW nEndRow = aRange.aEnd.Row();
+ String aCell;
+ bool bConvertLF = (GetSystemLineEnd() != LINEEND_LF);
+
+ for (nRow = nStartRow; nRow <= nEndRow; nRow++)
+ {
+ if (bIncludeFiltered || !pDoc->IsFiltered( nRow, aRange.aStart.Tab() ))
+ {
+ for (nCol = nStartCol; nCol <= nEndCol; nCol++)
+ {
+ CellType eType;
+ pDoc->GetCellType( nCol, nRow, aRange.aStart.Tab(), eType );
+ switch (eType)
+ {
+ case CELLTYPE_FORMULA:
+ {
+ if (bFormulas)
+ {
+ pDoc->GetFormula( nCol, nRow, aRange.aStart.Tab(), aCell, TRUE );
+ if( aCell.Search( cSep ) != STRING_NOTFOUND )
+ lcl_WriteString( rStrm, aCell, cStr, cStr );
+ else
+ lcl_WriteSimpleString( rStrm, aCell );
+ }
+ else
+ {
+ pDoc->GetString( nCol, nRow, aRange.aStart.Tab(), aCell );
+
+ bool bMultiLineText = ( aCell.Search( _LF ) != STRING_NOTFOUND );
+ if( bMultiLineText )
+ {
+ if( mExportTextOptions.meNewlineConversion == ScExportTextOptions::ToSpace )
+ aCell.SearchAndReplaceAll( _LF, ' ' );
+ else if ( mExportTextOptions.meNewlineConversion == ScExportTextOptions::ToSystem && bConvertLF )
+ aCell.ConvertLineEnd();
+ }
+
+ if( mExportTextOptions.mcSeparatorConvertTo && cSep )
+ aCell.SearchAndReplaceAll( cSep, mExportTextOptions.mcSeparatorConvertTo );
+
+ if( mExportTextOptions.mbAddQuotes && ( aCell.Search( cSep ) != STRING_NOTFOUND ) )
+ lcl_WriteString( rStrm, aCell, cStr, cStr );
+ else
+ lcl_WriteSimpleString( rStrm, aCell );
+ }
+ }
+ break;
+ case CELLTYPE_VALUE:
+ {
+ pDoc->GetString( nCol, nRow, aRange.aStart.Tab(), aCell );
+ lcl_WriteSimpleString( rStrm, aCell );
+ }
+ break;
+ case CELLTYPE_NOTE:
+ case CELLTYPE_NONE:
+ break;
+ default:
+ {
+ pDoc->GetString( nCol, nRow, aRange.aStart.Tab(), aCell );
+
+ bool bMultiLineText = ( aCell.Search( _LF ) != STRING_NOTFOUND );
+ if( bMultiLineText )
+ {
+ if( mExportTextOptions.meNewlineConversion == ScExportTextOptions::ToSpace )
+ aCell.SearchAndReplaceAll( _LF, ' ' );
+ else if ( mExportTextOptions.meNewlineConversion == ScExportTextOptions::ToSystem && bConvertLF )
+ aCell.ConvertLineEnd();
+ }
+
+ if( mExportTextOptions.mcSeparatorConvertTo && cSep )
+ aCell.SearchAndReplaceAll( cSep, mExportTextOptions.mcSeparatorConvertTo );
+
+ if( mExportTextOptions.mbAddQuotes && ( aCell.Search( cSep ) != STRING_NOTFOUND ) )
+ lcl_WriteString( rStrm, aCell, cStr, cStr );
+ else
+ lcl_WriteSimpleString( rStrm, aCell );
+ }
+ }
+ if( nCol < nEndCol )
+ lcl_WriteSimpleString( rStrm, String(cSep) );
+ }
+// if( nRow < nEndRow )
+ WriteUnicodeOrByteEndl( rStrm );
+ if( rStrm.GetError() != SVSTREAM_OK )
+ break;
+ if( nSizeLimit && rStrm.Tell() > nSizeLimit )
+ break;
+ }
+ }
+
+ return BOOL( rStrm.GetError() == SVSTREAM_OK );
+}
+
+
+BOOL ScImportExport::Sylk2Doc( SvStream& rStrm )
+{
+ BOOL bOk = TRUE;
+ BOOL bMyDoc = FALSE;
+ SylkVersion eVersion = SYLK_OTHER;
+
+ // US-English separators for StringToDouble
+ sal_Unicode cDecSep = '.';
+ sal_Unicode cGrpSep = ',';
+
+ SCCOL nStartCol = aRange.aStart.Col();
+ SCROW nStartRow = aRange.aStart.Row();
+ SCCOL nEndCol = aRange.aEnd.Col();
+ SCROW nEndRow = aRange.aEnd.Row();
+ ULONG nOldPos = rStrm.Tell();
+ BOOL bData = BOOL( !bSingle );
+ SvULongs aFormats;
+
+ if( !bSingle)
+ bOk = StartPaste();
+
+ while( bOk )
+ {
+ String aLine;
+ String aText;
+ ByteString aByteLine;
+ SCCOL nCol = nStartCol;
+ SCROW nRow = nStartRow;
+ SCCOL nRefCol = 1;
+ SCROW nRefRow = 1;
+ rStrm.Seek( nOldPos );
+ for( ;; )
+ {
+ //! allow unicode
+ rStrm.ReadLine( aByteLine );
+ aLine = String( aByteLine, rStrm.GetStreamCharSet() );
+ if( rStrm.IsEof() )
+ break;
+ const sal_Unicode* p = aLine.GetBuffer();
+ sal_Unicode cTag = *p++;
+ if( cTag == 'C' ) // Content
+ {
+ if( *p++ != ';' )
+ return FALSE;
+ while( *p )
+ {
+ sal_Unicode ch = *p++;
+ ch = ScGlobal::ToUpperAlpha( ch );
+ switch( ch )
+ {
+ case 'X':
+ nCol = static_cast<SCCOL>(String( p ).ToInt32()) + nStartCol - 1;
+ break;
+ case 'Y':
+ nRow = String( p ).ToInt32() + nStartRow - 1;
+ break;
+ case 'C':
+ nRefCol = static_cast<SCCOL>(String( p ).ToInt32()) + nStartCol - 1;
+ break;
+ case 'R':
+ nRefRow = String( p ).ToInt32() + nStartRow - 1;
+ break;
+ case 'K':
+ {
+ if( !bSingle &&
+ ( nCol < nStartCol || nCol > nEndCol
+ || nRow < nStartRow || nRow > nEndRow
+ || nCol > MAXCOL || nRow > MAXROW ) )
+ break;
+ if( !bData )
+ {
+ if( nRow > nEndRow )
+ nEndRow = nRow;
+ if( nCol > nEndCol )
+ nEndCol = nCol;
+ break;
+ }
+ BOOL bText;
+ if( *p == '"' )
+ {
+ bText = TRUE;
+ aText.Erase();
+ p = lcl_ScanSylkString( p, aText, eVersion);
+ }
+ else
+ bText = FALSE;
+ const sal_Unicode* q = p;
+ while( *q && *q != ';' )
+ q++;
+ if ( !(*q == ';' && *(q+1) == 'I') )
+ { // don't ignore value
+ if( bText )
+ {
+ pDoc->PutCell( nCol, nRow, aRange.aStart.Tab(),
+ ScBaseCell::CreateTextCell( aText, pDoc),
+ (BOOL) TRUE);
+ }
+ else
+ {
+ double fVal = rtl_math_uStringToDouble( p,
+ aLine.GetBuffer() + aLine.Len(),
+ cDecSep, cGrpSep, NULL, NULL );
+ pDoc->SetValue( nCol, nRow, aRange.aStart.Tab(), fVal );
+ }
+ }
+ }
+ break;
+ case 'E':
+ case 'M':
+ {
+ if ( ch == 'M' )
+ {
+ if ( nRefCol < nCol )
+ nRefCol = nCol;
+ if ( nRefRow < nRow )
+ nRefRow = nRow;
+ if ( !bData )
+ {
+ if( nRefRow > nEndRow )
+ nEndRow = nRefRow;
+ if( nRefCol > nEndCol )
+ nEndCol = nRefCol;
+ }
+ }
+ if( !bMyDoc || !bData )
+ break;
+ aText = '=';
+ p = lcl_ScanSylkFormula( p, aText, eVersion);
+ ScAddress aPos( nCol, nRow, aRange.aStart.Tab() );
+ /* FIXME: do we want GRAM_ODFF_A1 instead? At the
+ * end it probably should be GRAM_ODFF_R1C1, since
+ * R1C1 is what Excel writes in SYLK. */
+ const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_PODF_A1;
+ ScCompiler aComp( pDoc, aPos);
+ aComp.SetGrammar(eGrammar);
+ ScTokenArray* pCode = aComp.CompileString( aText );
+ if ( ch == 'M' )
+ {
+ ScMarkData aMark;
+ aMark.SelectTable( aPos.Tab(), TRUE );
+ pDoc->InsertMatrixFormula( nCol, nRow, nRefCol,
+ nRefRow, aMark, EMPTY_STRING, pCode );
+ }
+ else
+ {
+ ScFormulaCell* pFCell = new ScFormulaCell(
+ pDoc, aPos, pCode, eGrammar, MM_NONE);
+ pDoc->PutCell( aPos, pFCell );
+ }
+ delete pCode; // ctor/InsertMatrixFormula did copy TokenArray
+ }
+ break;
+ }
+ while( *p && *p != ';' )
+ p++;
+ if( *p )
+ p++;
+ }
+ }
+ else if( cTag == 'F' ) // Format
+ {
+ if( *p++ != ';' )
+ return FALSE;
+ sal_Int32 nFormat = -1;
+ while( *p )
+ {
+ sal_Unicode ch = *p++;
+ ch = ScGlobal::ToUpperAlpha( ch );
+ switch( ch )
+ {
+ case 'X':
+ nCol = static_cast<SCCOL>(String( p ).ToInt32()) + nStartCol - 1;
+ break;
+ case 'Y':
+ nRow = String( p ).ToInt32() + nStartRow - 1;
+ break;
+ case 'P' :
+ if ( bData )
+ {
+ // F;P<n> sets format code of P;P<code> at
+ // current position, or at ;X;Y if specified.
+ // Note that ;X;Y may appear after ;P
+ const sal_Unicode* p0 = p;
+ while( *p && *p != ';' )
+ p++;
+ String aNumber( p0, sal::static_int_cast<xub_StrLen>( p - p0 ) );
+ nFormat = aNumber.ToInt32();
+ }
+ break;
+ }
+ while( *p && *p != ';' )
+ p++;
+ if( *p )
+ p++;
+ }
+ if ( !bData )
+ {
+ if( nRow > nEndRow )
+ nEndRow = nRow;
+ if( nCol > nEndCol )
+ nEndCol = nCol;
+ }
+ if ( 0 <= nFormat && nFormat < aFormats.Count() )
+ {
+ ULONG nKey = aFormats[(USHORT)nFormat];
+ pDoc->ApplyAttr( nCol, nRow, aRange.aStart.Tab(),
+ SfxUInt32Item( ATTR_VALUE_FORMAT, nKey ) );
+ }
+ }
+ else if( cTag == 'P' )
+ {
+ if ( bData && *p == ';' && *(p+1) == 'P' )
+ {
+ String aCode( p+2 );
+ // unescape doubled semicolons
+ xub_StrLen nPos = 0;
+ String aSemicolon( RTL_CONSTASCII_USTRINGPARAM(";;"));
+ while ( (nPos = aCode.Search( aSemicolon, nPos )) != STRING_NOTFOUND )
+ aCode.Erase( nPos++, 1 );
+ // get rid of Xcl escape characters
+ nPos = 0;
+ while ( (nPos = aCode.Search( sal_Unicode(0x1b), nPos )) != STRING_NOTFOUND )
+ aCode.Erase( nPos, 1 );
+ xub_StrLen nCheckPos;
+ short nType;
+ sal_uInt32 nKey;
+ pDoc->GetFormatTable()->PutandConvertEntry(
+ aCode, nCheckPos, nType, nKey, LANGUAGE_ENGLISH_US,
+ ScGlobal::eLnge );
+ if ( nCheckPos )
+ nKey = 0;
+ aFormats.Insert( nKey, aFormats.Count() );
+ }
+ }
+ else if( cTag == 'I' && *p == 'D' )
+ {
+ aLine.Erase( 0, 4 );
+ if (aLine.EqualsAscii( "CALCOOO32" ))
+ eVersion = SYLK_OOO32;
+ else if (aLine.EqualsAscii( "SCALC3" ))
+ eVersion = SYLK_SCALC3;
+ bMyDoc = (eVersion <= SYLK_OWN);
+ }
+ else if( cTag == 'E' ) // Ende
+ break;
+ }
+ if( !bData )
+ {
+ aRange.aEnd.SetCol( nEndCol );
+ aRange.aEnd.SetRow( nEndRow );
+ bOk = StartPaste();
+ bData = TRUE;
+ }
+ else
+ break;
+ }
+
+ EndPaste();
+ return bOk;
+}
+
+
+BOOL ScImportExport::Doc2Sylk( SvStream& rStrm )
+{
+ SCCOL nCol;
+ SCROW nRow;
+ SCCOL nStartCol = aRange.aStart.Col();
+ SCROW nStartRow = aRange.aStart.Row();
+ SCCOL nEndCol = aRange.aEnd.Col();
+ SCROW nEndRow = aRange.aEnd.Row();
+ String aCellStr;
+ String aValStr;
+ lcl_WriteSimpleString( rStrm,
+ String( RTL_CONSTASCII_USTRINGPARAM( "ID;PCALCOOO32")));
+ WriteUnicodeOrByteEndl( rStrm );
+
+ for (nRow = nStartRow; nRow <= nEndRow; nRow++)
+ {
+ for (nCol = nStartCol; nCol <= nEndCol; nCol++)
+ {
+ String aBufStr;
+ double nVal;
+ BOOL bForm = FALSE;
+ SCROW r = nRow - nStartRow + 1;
+ SCCOL c = nCol - nStartCol + 1;
+ ScBaseCell* pCell;
+ pDoc->GetCell( nCol, nRow, aRange.aStart.Tab(), pCell );
+ CellType eType = (pCell ? pCell->GetCellType() : CELLTYPE_NONE);
+ switch( eType )
+ {
+ case CELLTYPE_FORMULA:
+ bForm = bFormulas;
+ if( pDoc->HasValueData( nCol, nRow, aRange.aStart.Tab()) )
+ goto hasvalue;
+ else
+ goto hasstring;
+
+ case CELLTYPE_VALUE:
+ hasvalue:
+ pDoc->GetValue( nCol, nRow, aRange.aStart.Tab(), nVal );
+
+ aValStr = ::rtl::math::doubleToUString( nVal,
+ rtl_math_StringFormat_Automatic,
+ rtl_math_DecimalPlaces_Max, '.', TRUE );
+
+ aBufStr.AssignAscii(RTL_CONSTASCII_STRINGPARAM( "C;X" ));
+ aBufStr += String::CreateFromInt32( c );
+ aBufStr.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ";Y" ));
+ aBufStr += String::CreateFromInt32( r );
+ aBufStr.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ";K" ));
+ aBufStr += aValStr;
+ lcl_WriteSimpleString( rStrm, aBufStr );
+ goto checkformula;
+
+ case CELLTYPE_STRING:
+ case CELLTYPE_EDIT:
+ hasstring:
+ pDoc->GetString( nCol, nRow, aRange.aStart.Tab(), aCellStr );
+ aCellStr.SearchAndReplaceAll( _LF, SYLK_LF );
+
+ aBufStr.AssignAscii(RTL_CONSTASCII_STRINGPARAM( "C;X" ));
+ aBufStr += String::CreateFromInt32( c );
+ aBufStr.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ";Y" ));
+ aBufStr += String::CreateFromInt32( r );
+ aBufStr.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ";K" ));
+ lcl_WriteSimpleString( rStrm, aBufStr );
+ lcl_WriteString( rStrm, aCellStr, '"', ';' );
+
+ checkformula:
+ if( bForm )
+ {
+ const ScFormulaCell* pFCell =
+ static_cast<const ScFormulaCell*>(pCell);
+ switch ( pFCell->GetMatrixFlag() )
+ {
+ case MM_REFERENCE :
+ aCellStr.Erase();
+ break;
+ default:
+ pFCell->GetFormula( aCellStr,formula::FormulaGrammar::GRAM_PODF_A1);
+ /* FIXME: do we want GRAM_ODFF_A1 instead? At
+ * the end it probably should be
+ * GRAM_ODFF_R1C1, since R1C1 is what Excel
+ * writes in SYLK. */
+ }
+ if ( pFCell->GetMatrixFlag() != MM_NONE &&
+ aCellStr.Len() > 2 &&
+ aCellStr.GetChar(0) == '{' &&
+ aCellStr.GetChar(aCellStr.Len()-1) == '}' )
+ { // cut off matrix {} characters
+ aCellStr.Erase(aCellStr.Len()-1,1);
+ aCellStr.Erase(0,1);
+ }
+ if ( aCellStr.GetChar(0) == '=' )
+ aCellStr.Erase(0,1);
+ String aPrefix;
+ switch ( pFCell->GetMatrixFlag() )
+ {
+ case MM_FORMULA :
+ { // diff expression with 'M' M$-extension
+ SCCOL nC;
+ SCROW nR;
+ pFCell->GetMatColsRows( nC, nR );
+ nC += c - 1;
+ nR += r - 1;
+ aPrefix.AssignAscii( RTL_CONSTASCII_STRINGPARAM( ";R" ) );
+ aPrefix += String::CreateFromInt32( nR );
+ aPrefix.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ";C" ) );
+ aPrefix += String::CreateFromInt32( nC );
+ aPrefix.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ";M" ) );
+ }
+ break;
+ case MM_REFERENCE :
+ { // diff expression with 'I' M$-extension
+ ScAddress aPos;
+ pFCell->GetMatrixOrigin( aPos );
+ aPrefix.AssignAscii( RTL_CONSTASCII_STRINGPARAM( ";I;R" ) );
+ aPrefix += String::CreateFromInt32( aPos.Row() - nStartRow + 1 );
+ aPrefix.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ";C" ) );
+ aPrefix += String::CreateFromInt32( aPos.Col() - nStartCol + 1 );
+ }
+ break;
+ default:
+ // formula Expression
+ aPrefix.AssignAscii( RTL_CONSTASCII_STRINGPARAM( ";E" ) );
+ }
+ lcl_WriteSimpleString( rStrm, aPrefix );
+ if ( aCellStr.Len() )
+ lcl_WriteString( rStrm, aCellStr, 0, ';' );
+ }
+ WriteUnicodeOrByteEndl( rStrm );
+ break;
+
+ default:
+ {
+ // added to avoid warnings
+ }
+ }
+ }
+ }
+ lcl_WriteSimpleString( rStrm, String( 'E' ) );
+ WriteUnicodeOrByteEndl( rStrm );
+ return BOOL( rStrm.GetError() == SVSTREAM_OK );
+}
+
+
+BOOL ScImportExport::Doc2HTML( SvStream& rStrm, const String& rBaseURL )
+{
+ // CharSet is ignored in ScExportHTML, read from Load/Save HTML options
+ ScFormatFilter::Get().ScExportHTML( rStrm, rBaseURL, pDoc, aRange, RTL_TEXTENCODING_DONTKNOW, bAll,
+ aStreamPath, aNonConvertibleChars );
+ return BOOL( rStrm.GetError() == SVSTREAM_OK );
+}
+
+BOOL ScImportExport::Doc2RTF( SvStream& rStrm )
+{
+ // CharSet is ignored in ScExportRTF
+ ScFormatFilter::Get().ScExportRTF( rStrm, pDoc, aRange, RTL_TEXTENCODING_DONTKNOW );
+ return BOOL( rStrm.GetError() == SVSTREAM_OK );
+}
+
+
+BOOL ScImportExport::Doc2Dif( SvStream& rStrm )
+{
+ // for DIF in the clipboard, IBM_850 is always used
+ ScFormatFilter::Get().ScExportDif( rStrm, pDoc, aRange, RTL_TEXTENCODING_IBM_850 );
+ return TRUE;
+}
+
+
+BOOL ScImportExport::Dif2Doc( SvStream& rStrm )
+{
+ SCTAB nTab = aRange.aStart.Tab();
+ ScDocument* pImportDoc = new ScDocument( SCDOCMODE_UNDO );
+ pImportDoc->InitUndo( pDoc, nTab, nTab );
+
+ // for DIF in the clipboard, IBM_850 is always used
+ ScFormatFilter::Get().ScImportDif( rStrm, pImportDoc, aRange.aStart, RTL_TEXTENCODING_IBM_850 );
+
+ SCCOL nEndCol;
+ SCROW nEndRow;
+ pImportDoc->GetCellArea( nTab, nEndCol, nEndRow );
+ // #131247# if there are no cells in the imported content, nEndCol/nEndRow may be before the start
+ if ( nEndCol < aRange.aStart.Col() )
+ nEndCol = aRange.aStart.Col();
+ if ( nEndRow < aRange.aStart.Row() )
+ nEndRow = aRange.aStart.Row();
+ aRange.aEnd = ScAddress( nEndCol, nEndRow, nTab );
+
+ BOOL bOk = StartPaste();
+ if (bOk)
+ {
+ USHORT nFlags = IDF_ALL & ~IDF_STYLES;
+ pDoc->DeleteAreaTab( aRange, nFlags );
+ pImportDoc->CopyToDocument( aRange, nFlags, FALSE, pDoc );
+ EndPaste();
+ }
+
+ delete pImportDoc;
+
+ return bOk;
+}
+
+
+BOOL ScImportExport::RTF2Doc( SvStream& rStrm, const String& rBaseURL )
+{
+ ScEEAbsImport *pImp = ScFormatFilter::Get().CreateRTFImport( pDoc, aRange );
+ if (!pImp)
+ return false;
+ pImp->Read( rStrm, rBaseURL );
+ aRange = pImp->GetRange();
+
+ BOOL bOk = StartPaste();
+ if (bOk)
+ {
+ USHORT nFlags = IDF_ALL & ~IDF_STYLES;
+ pDoc->DeleteAreaTab( aRange, nFlags );
+ pImp->WriteToDocument();
+ EndPaste();
+ }
+ delete pImp;
+ return bOk;
+}
+
+
+BOOL ScImportExport::HTML2Doc( SvStream& rStrm, const String& rBaseURL )
+{
+ ScEEAbsImport *pImp = ScFormatFilter::Get().CreateHTMLImport( pDoc, rBaseURL, aRange, TRUE);
+ if (!pImp)
+ return false;
+ pImp->Read( rStrm, rBaseURL );
+ aRange = pImp->GetRange();
+
+ BOOL bOk = StartPaste();
+ if (bOk)
+ {
+ // ScHTMLImport may call ScDocument::InitDrawLayer, resulting in
+ // a Draw Layer but no Draw View -> create Draw Layer and View here
+ if (pDocSh)
+ pDocSh->MakeDrawLayer();
+
+ USHORT nFlags = IDF_ALL & ~IDF_STYLES;
+ pDoc->DeleteAreaTab( aRange, nFlags );
+ pImp->WriteToDocument();
+ EndPaste();
+ }
+ delete pImp;
+ return bOk;
+}
+
+#define RETURN_ERROR { return eERR_INTERN; }
+class ScFormatFilterMissing : public ScFormatFilterPlugin {
+ public:
+ ScFormatFilterMissing()
+ {
+ OSL_ASSERT ("Missing file filters");
+ }
+ virtual FltError ScImportLotus123( SfxMedium&, ScDocument*, CharSet ) RETURN_ERROR
+ virtual FltError ScImportQuattroPro( SfxMedium &, ScDocument * ) RETURN_ERROR
+ virtual FltError ScImportExcel( SfxMedium&, ScDocument*, const EXCIMPFORMAT ) RETURN_ERROR
+ virtual FltError ScImportStarCalc10( SvStream&, ScDocument* ) RETURN_ERROR
+ virtual FltError ScImportDif( SvStream&, ScDocument*, const ScAddress&,
+ const CharSet, UINT32 ) RETURN_ERROR
+ virtual FltError ScImportRTF( SvStream&, const String&, ScDocument*, ScRange& ) RETURN_ERROR
+ virtual FltError ScImportHTML( SvStream&, const String&, ScDocument*, ScRange&, double, BOOL ) RETURN_ERROR
+
+ virtual ScEEAbsImport *CreateRTFImport( ScDocument*, const ScRange& ) { return NULL; }
+ virtual ScEEAbsImport *CreateHTMLImport( ScDocument*, const String&, const ScRange&, BOOL ) { return NULL; }
+ virtual String GetHTMLRangeNameList( ScDocument*, const String& ) { return String(); }
+
+#if ENABLE_LOTUS123_EXPORT
+ virtual FltError ScExportLotus123( SvStream&, ScDocument*, ExportFormatLotus, CharSet ) RETURN_ERROR
+#endif
+ virtual FltError ScExportExcel5( SfxMedium&, ScDocument*, ExportFormatExcel, CharSet ) RETURN_ERROR
+ virtual FltError ScExportDif( SvStream&, ScDocument*, const ScAddress&, const CharSet, UINT32 ) RETURN_ERROR
+ virtual FltError ScExportDif( SvStream&, ScDocument*, const ScRange&, const CharSet, UINT32 ) RETURN_ERROR
+ virtual FltError ScExportHTML( SvStream&, const String&, ScDocument*, const ScRange&, const CharSet, BOOL,
+ const String&, String& ) RETURN_ERROR
+ virtual FltError ScExportRTF( SvStream&, ScDocument*, const ScRange&, const CharSet ) RETURN_ERROR
+};
+
+extern "C" { static void SAL_CALL thisModule() {} }
+typedef ScFormatFilterPlugin * (*FilterFn)(void);
+ScFormatFilterPlugin &ScFormatFilter::Get()
+{
+ static ScFormatFilterPlugin *plugin;
+
+ if (plugin != NULL)
+ return *plugin;
+
+ static ::osl::Module aModule;
+ if ( aModule.loadRelative( &thisModule,
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SVLIBRARY( "scfilt" ) ) ) ) )
+ {
+ oslGenericFunction fn = aModule.getFunctionSymbol( ::rtl::OUString::createFromAscii( "ScFilterCreate" ) );
+ if (fn != NULL)
+ plugin = reinterpret_cast<FilterFn>(fn)();
+ }
+ if (plugin == NULL)
+ plugin = new ScFormatFilterMissing();
+
+ return *plugin;
+}
diff --git a/sc/source/ui/docshell/makefile.mk b/sc/source/ui/docshell/makefile.mk
new file mode 100644
index 000000000000..99a7495b6b49
--- /dev/null
+++ b/sc/source/ui/docshell/makefile.mk
@@ -0,0 +1,139 @@
+#*************************************************************************
+#
+# 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.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+
+PRJNAME=sc
+TARGET=docshell
+LIBTARGET=no
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : scpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sc.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Files --------------------------------------------------------
+
+CXXFILES = \
+ docsh.cxx \
+ docsh2.cxx \
+ docsh3.cxx \
+ docsh4.cxx \
+ docsh5.cxx \
+ docsh6.cxx \
+ docsh7.cxx \
+ docsh8.cxx \
+ externalrefmgr.cxx \
+ tablink.cxx \
+ arealink.cxx \
+ dbdocfun.cxx \
+ dbdocimp.cxx \
+ impex.cxx \
+ docfunc.cxx \
+ olinefun.cxx \
+ servobj.cxx \
+ tpstat.cxx \
+ autostyl.cxx \
+ pagedata.cxx \
+ hiranges.cxx \
+ pntlock.cxx \
+ sizedev.cxx \
+ editable.cxx
+
+
+SLOFILES = \
+ $(SLO)$/docsh.obj \
+ $(SLO)$/docsh2.obj \
+ $(SLO)$/docsh3.obj \
+ $(SLO)$/docsh4.obj \
+ $(SLO)$/docsh5.obj \
+ $(SLO)$/docsh6.obj \
+ $(SLO)$/docsh7.obj \
+ $(SLO)$/docsh8.obj \
+ $(SLO)$/externalrefmgr.obj \
+ $(SLO)$/tablink.obj \
+ $(SLO)$/arealink.obj \
+ $(SLO)$/dbdocfun.obj \
+ $(SLO)$/dbdocimp.obj \
+ $(SLO)$/impex.obj \
+ $(SLO)$/docfunc.obj \
+ $(SLO)$/olinefun.obj \
+ $(SLO)$/servobj.obj \
+ $(SLO)$/tpstat.obj \
+ $(SLO)$/autostyl.obj \
+ $(SLO)$/pagedata.obj \
+ $(SLO)$/hiranges.obj \
+ $(SLO)$/pntlock.obj \
+ $(SLO)$/sizedev.obj \
+ $(SLO)$/editable.obj
+
+
+EXCEPTIONSFILES= \
+ $(SLO)$/docsh.obj \
+ $(SLO)$/docsh3.obj \
+ $(SLO)$/docsh4.obj \
+ $(SLO)$/docsh8.obj \
+ $(SLO)$/externalrefmgr.obj \
+ $(SLO)$/dbdocimp.obj \
+ $(SLO)$/docfunc.obj
+
+SRS1NAME=$(TARGET)
+SRC1FILES = tpstat.src
+
+LIB1TARGET = $(SLB)$/$(TARGET).lib
+
+LIB1OBJFILES = \
+ $(SLO)$/docsh.obj \
+ $(SLO)$/docsh2.obj \
+ $(SLO)$/docsh3.obj \
+ $(SLO)$/docsh4.obj \
+ $(SLO)$/docsh5.obj \
+ $(SLO)$/docsh6.obj \
+ $(SLO)$/docsh7.obj \
+ $(SLO)$/docsh8.obj \
+ $(SLO)$/externalrefmgr.obj \
+ $(SLO)$/tablink.obj \
+ $(SLO)$/arealink.obj \
+ $(SLO)$/dbdocfun.obj \
+ $(SLO)$/dbdocimp.obj \
+ $(SLO)$/impex.obj \
+ $(SLO)$/docfunc.obj \
+ $(SLO)$/olinefun.obj \
+ $(SLO)$/servobj.obj \
+ $(SLO)$/autostyl.obj \
+ $(SLO)$/pagedata.obj \
+ $(SLO)$/hiranges.obj \
+ $(SLO)$/pntlock.obj \
+ $(SLO)$/sizedev.obj \
+ $(SLO)$/editable.obj
+
+# --- Tagets -------------------------------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/sc/source/ui/docshell/olinefun.cxx b/sc/source/ui/docshell/olinefun.cxx
new file mode 100644
index 000000000000..2f42c77ed5f4
--- /dev/null
+++ b/sc/source/ui/docshell/olinefun.cxx
@@ -0,0 +1,788 @@
+/*************************************************************************
+ *
+ * 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 <vcl/sound.hxx>
+#include <sfx2/bindings.hxx>
+
+#include "olinefun.hxx"
+
+#include "docsh.hxx"
+#include "olinetab.hxx"
+#include "undodat.hxx"
+#include "globstr.hrc"
+#include "sc.hrc"
+
+
+//========================================================================
+
+void lcl_InvalidateOutliner( SfxBindings* pBindings )
+{
+ if ( pBindings )
+ {
+ pBindings->Invalidate( SID_OUTLINE_SHOW );
+ pBindings->Invalidate( SID_OUTLINE_HIDE );
+ pBindings->Invalidate( SID_OUTLINE_REMOVE );
+
+ pBindings->Invalidate( SID_STATUS_SUM ); // wegen ein-/ausblenden
+ pBindings->Invalidate( SID_ATTR_SIZE );
+ }
+}
+
+//------------------------------------------------------------------------
+
+//! PaintWidthHeight zur DocShell verschieben?
+
+void lcl_PaintWidthHeight( ScDocShell& rDocShell, SCTAB nTab,
+ BOOL bColumns, SCCOLROW nStart, SCCOLROW nEnd )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ USHORT nParts = PAINT_GRID;
+ SCCOL nStartCol = 0;
+ SCROW nStartRow = 0;
+ SCCOL nEndCol = MAXCOL; // fuer Test auf Merge
+ SCROW nEndRow = MAXROW;
+ if ( bColumns )
+ {
+ nParts |= PAINT_TOP;
+ nStartCol = static_cast<SCCOL>(nStart);
+ nEndCol = static_cast<SCCOL>(nEnd);
+ }
+ else
+ {
+ nParts |= PAINT_LEFT;
+ nStartRow = nStart;
+ nEndRow = nEnd;
+ }
+ if (pDoc->HasAttrib( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab,
+ HASATTR_MERGED | HASATTR_OVERLAPPED ))
+ {
+ nStartCol = 0;
+ nStartRow = 0;
+ }
+ rDocShell.PostPaint( nStartCol,nStartRow,nTab, MAXCOL,MAXROW,nTab, nParts );
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScOutlineDocFunc::MakeOutline( const ScRange& rRange, BOOL bColumns, BOOL bRecord, BOOL bApi )
+{
+ BOOL bSuccess = FALSE;
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ SCTAB nTab = rRange.aStart.Tab();
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+ ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab, TRUE );
+ ScOutlineTable* pUndoTab = NULL;
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+
+ if (bRecord)
+ pUndoTab = new ScOutlineTable( *pTable );
+
+ ScOutlineArray* pArray = bColumns ? pTable->GetColArray() : pTable->GetRowArray();
+
+ BOOL bRes;
+ BOOL bSize = FALSE;
+ if ( bColumns )
+ bRes = pArray->Insert( nStartCol, nEndCol, bSize );
+ else
+ bRes = pArray->Insert( nStartRow, nEndRow, bSize );
+
+ if ( bRes )
+ {
+ if (bRecord)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoMakeOutline( &rDocShell,
+ nStartCol,nStartRow,nTab,nEndCol,nEndRow,nTab,
+ pUndoTab, bColumns, TRUE ) );
+ }
+
+ if (pDoc->IsStreamValid(nTab))
+ pDoc->SetStreamValid(nTab, FALSE);
+
+ USHORT nParts = 0; // Datenbereich nicht geaendert
+ if ( bColumns )
+ nParts |= PAINT_TOP;
+ else
+ nParts |= PAINT_LEFT;
+ if ( bSize )
+ nParts |= PAINT_SIZE;
+
+ rDocShell.PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, nParts );
+ rDocShell.SetDocumentModified();
+ lcl_InvalidateOutliner( rDocShell.GetViewBindings() );
+ bSuccess = TRUE;
+ }
+ else
+ {
+ if (!bApi)
+ rDocShell.ErrorMessage(STR_MSSG_MAKEOUTLINE_0); // "Gruppierung nicht moeglich"
+ delete pUndoTab;
+ }
+
+ return bSuccess;
+}
+
+BOOL ScOutlineDocFunc::RemoveOutline( const ScRange& rRange, BOOL bColumns, BOOL bRecord, BOOL bApi )
+{
+ BOOL bDone = FALSE;
+
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ SCTAB nTab = rRange.aStart.Tab();
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+ ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
+ if (pTable)
+ {
+ ScOutlineTable* pUndoTab = NULL;
+ if (bRecord)
+ pUndoTab = new ScOutlineTable( *pTable );
+
+ ScOutlineArray* pArray = bColumns ? pTable->GetColArray() : pTable->GetRowArray();
+
+ BOOL bRes;
+ BOOL bSize = FALSE;
+ if ( bColumns )
+ bRes = pArray->Remove( nStartCol, nEndCol, bSize );
+ else
+ bRes = pArray->Remove( nStartRow, nEndRow, bSize );
+
+ if ( bRes )
+ {
+ if (bRecord)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoMakeOutline( &rDocShell,
+ nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab,
+ pUndoTab, bColumns, FALSE ) );
+ }
+
+ if (pDoc->IsStreamValid(nTab))
+ pDoc->SetStreamValid(nTab, FALSE);
+
+ USHORT nParts = 0; // Datenbereich nicht geaendert
+ if ( bColumns )
+ nParts |= PAINT_TOP;
+ else
+ nParts |= PAINT_LEFT;
+ if ( bSize )
+ nParts |= PAINT_SIZE;
+
+ rDocShell.PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, nParts );
+ rDocShell.SetDocumentModified();
+ bDone = TRUE;
+ lcl_InvalidateOutliner( rDocShell.GetViewBindings() );
+
+ // es wird nicht wieder eingeblendet -> kein UpdatePageBreaks
+ }
+ else
+ delete pUndoTab;
+ }
+
+ if (!bDone && !bApi)
+ rDocShell.ErrorMessage(STR_MSSG_REMOVEOUTLINE_0); // "Aufheben nicht moeglich"
+
+ return bDone;
+}
+
+BOOL ScOutlineDocFunc::RemoveAllOutlines( SCTAB nTab, BOOL bRecord, BOOL bApi )
+{
+ BOOL bSuccess = FALSE;
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+ ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
+ if (pTable)
+ {
+ if (bRecord)
+ {
+ SCCOLROW nCol1, nCol2, nRow1, nRow2;
+ pTable->GetColArray()->GetRange( nCol1, nCol2 );
+ pTable->GetRowArray()->GetRange( nRow1, nRow2 );
+ SCCOL nStartCol = static_cast<SCCOL>(nCol1);
+ SCROW nStartRow = nRow1;
+ SCCOL nEndCol = static_cast<SCCOL>(nCol2);
+ SCROW nEndRow = nRow2;
+
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, TRUE, TRUE );
+ pDoc->CopyToDocument( nStartCol, 0, nTab, nEndCol, MAXROW, nTab, IDF_NONE, FALSE, pUndoDoc );
+ pDoc->CopyToDocument( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab, IDF_NONE, FALSE, pUndoDoc );
+
+ ScOutlineTable* pUndoTab = new ScOutlineTable( *pTable );
+
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoRemoveAllOutlines( &rDocShell,
+ nStartCol, nStartRow, nTab,
+ nEndCol, nEndRow, nTab,
+ pUndoDoc, pUndoTab ) );
+ }
+
+ SelectLevel( nTab, TRUE, pTable->GetColArray()->GetDepth(), FALSE, FALSE, bApi );
+ SelectLevel( nTab, FALSE, pTable->GetRowArray()->GetDepth(), FALSE, FALSE, bApi );
+ pDoc->SetOutlineTable( nTab, NULL );
+
+ pDoc->UpdatePageBreaks( nTab );
+
+ if (pDoc->IsStreamValid(nTab))
+ pDoc->SetStreamValid(nTab, FALSE);
+
+ rDocShell.PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab,
+ PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE );
+ rDocShell.SetDocumentModified();
+ lcl_InvalidateOutliner( rDocShell.GetViewBindings() );
+ bSuccess = TRUE;
+ }
+ else if (!bApi)
+ Sound::Beep();
+
+ return bSuccess;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScOutlineDocFunc::AutoOutline( const ScRange& rRange, BOOL bRecord, BOOL bApi )
+{
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ SCTAB nTab = rRange.aStart.Tab();
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+ ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
+
+ ScDocument* pUndoDoc = NULL;
+ ScOutlineTable* pUndoTab = NULL;
+
+ if ( pTable )
+ {
+ if ( bRecord )
+ {
+ pUndoTab = new ScOutlineTable( *pTable );
+
+ SCCOLROW nCol1, nCol2, nRow1, nRow2;
+ pTable->GetColArray()->GetRange( nCol1, nCol2 );
+ pTable->GetRowArray()->GetRange( nRow1, nRow2 );
+ SCCOL nOutStartCol = static_cast<SCCOL>(nCol1);;
+ SCROW nOutStartRow = nRow1;
+ SCCOL nOutEndCol = static_cast<SCCOL>(nCol2);;
+ SCROW nOutEndRow = nRow2;
+
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, TRUE, TRUE );
+ pDoc->CopyToDocument( nOutStartCol, 0, nTab, nOutEndCol, MAXROW, nTab, IDF_NONE, FALSE, pUndoDoc );
+ pDoc->CopyToDocument( 0, nOutStartRow, nTab, MAXCOL, nOutEndRow, nTab, IDF_NONE, FALSE, pUndoDoc );
+ }
+
+ // einblenden
+ SelectLevel( nTab, TRUE, pTable->GetColArray()->GetDepth(), FALSE, FALSE, bApi );
+ SelectLevel( nTab, FALSE, pTable->GetRowArray()->GetDepth(), FALSE, FALSE, bApi );
+ pDoc->SetOutlineTable( nTab, NULL );
+ }
+
+ pDoc->DoAutoOutline( nStartCol,nStartRow, nEndCol,nEndRow, nTab );
+
+ if (bRecord)
+ {
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoAutoOutline( &rDocShell,
+ nStartCol, nStartRow, nTab,
+ nEndCol, nEndRow, nTab,
+ pUndoDoc, pUndoTab ) );
+ }
+
+ if (pDoc->IsStreamValid(nTab))
+ pDoc->SetStreamValid(nTab, FALSE);
+
+ rDocShell.PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_LEFT | PAINT_TOP | PAINT_SIZE );
+ rDocShell.SetDocumentModified();
+ lcl_InvalidateOutliner( rDocShell.GetViewBindings() );
+
+ return TRUE;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScOutlineDocFunc::SelectLevel( SCTAB nTab, BOOL bColumns, USHORT nLevel,
+ BOOL bRecord, BOOL bPaint, BOOL /* bApi */ )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+ ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab ); // ist schon da
+ if (!pTable)
+ return FALSE;
+ ScOutlineArray* pArray = bColumns ? pTable->GetColArray() : pTable->GetRowArray();
+ if (!pArray)
+ return FALSE;
+
+ SCCOLROW nStart, nEnd;
+ pArray->GetRange( nStart, nEnd );
+
+ if ( bRecord )
+ {
+ ScOutlineTable* pUndoTab = new ScOutlineTable( *pTable );
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ if (bColumns)
+ {
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, TRUE, FALSE );
+ pDoc->CopyToDocument( static_cast<SCCOL>(nStart), 0, nTab,
+ static_cast<SCCOL>(nEnd), MAXROW, nTab, IDF_NONE, FALSE,
+ pUndoDoc );
+ }
+ else
+ {
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, FALSE, TRUE );
+ pDoc->CopyToDocument( 0, nStart, nTab, MAXCOL, nEnd, nTab, IDF_NONE, FALSE, pUndoDoc );
+ }
+
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoOutlineLevel( &rDocShell,
+ nStart, nEnd, nTab, //! start und end berechnen
+ pUndoDoc, pUndoTab,
+ bColumns, nLevel ) );
+ }
+
+ ScSubOutlineIterator aIter( pArray ); // alle Eintraege
+ ScOutlineEntry* pEntry;
+ while ((pEntry=aIter.GetNext()) != NULL)
+ {
+ USHORT nThisLevel = aIter.LastLevel();
+ BOOL bShow = (nThisLevel < nLevel);
+ if (bShow) // einblenden
+ {
+ pEntry->SetHidden( FALSE );
+ pEntry->SetVisible( TRUE );
+ }
+ else if ( nThisLevel == nLevel ) // ausblenden
+ {
+ pEntry->SetHidden( TRUE );
+ pEntry->SetVisible( TRUE );
+ }
+ else // verdeckt
+ {
+ pEntry->SetVisible( FALSE );
+ }
+
+ SCCOLROW nThisStart = pEntry->GetStart();
+ SCCOLROW nThisEnd = pEntry->GetEnd();
+ for (SCCOLROW i=nThisStart; i<=nThisEnd; i++)
+ {
+ if ( bColumns )
+ pDoc->ShowCol( static_cast<SCCOL>(i), nTab, bShow );
+ else
+ if ( !bShow || !pDoc->IsFiltered( i,nTab ) )
+ pDoc->ShowRow( i, nTab, bShow );
+ }
+ }
+
+ pDoc->UpdatePageBreaks( nTab );
+
+ if (bPaint)
+ lcl_PaintWidthHeight( rDocShell, nTab, bColumns, nStart, nEnd );
+
+ rDocShell.SetDocumentModified();
+ lcl_InvalidateOutliner( rDocShell.GetViewBindings() );
+
+ return TRUE;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScOutlineDocFunc::ShowMarkedOutlines( const ScRange& rRange, BOOL bRecord, BOOL bApi )
+{
+ BOOL bDone = FALSE;
+
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ SCTAB nTab = rRange.aStart.Tab();
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+ ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
+
+ if (pTable)
+ {
+ ScOutlineArray* pArray;
+ ScOutlineEntry* pEntry;
+ SCCOLROW nStart;
+ SCCOLROW nEnd;
+ SCCOLROW nMin;
+ SCCOLROW nMax;
+ SCCOLROW i;
+
+ if ( bRecord )
+ {
+ ScOutlineTable* pUndoTab = new ScOutlineTable( *pTable );
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, TRUE, TRUE );
+ pDoc->CopyToDocument( nStartCol, 0, nTab, nEndCol, MAXROW, nTab, IDF_NONE, FALSE, pUndoDoc );
+ pDoc->CopyToDocument( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab, IDF_NONE, FALSE, pUndoDoc );
+
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoOutlineBlock( &rDocShell,
+ nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab,
+ pUndoDoc, pUndoTab, TRUE ) );
+ }
+
+ // Spalten
+
+ nMin=MAXCOL;
+ nMax=0;
+ pArray = pTable->GetColArray();
+ ScSubOutlineIterator aColIter( pArray );
+ while ((pEntry=aColIter.GetNext()) != NULL)
+ {
+ nStart = pEntry->GetStart();
+ nEnd = pEntry->GetEnd();
+ if ( nStart>=nStartCol && nEnd<=nEndCol )
+ {
+ pEntry->SetHidden( FALSE );
+ pEntry->SetVisible( TRUE );
+ if (nStart<nMin) nMin=nStart;
+ if (nEnd>nMax) nMax=nEnd;
+ }
+ }
+ for ( i=nMin; i<=nMax; i++ )
+ pDoc->ShowCol( static_cast<SCCOL>(i), nTab, TRUE );
+
+ // Zeilen
+
+ nMin=MAXROW;
+ nMax=0;
+ pArray = pTable->GetRowArray();
+ ScSubOutlineIterator aRowIter( pArray );
+ while ((pEntry=aRowIter.GetNext()) != NULL)
+ {
+ nStart = pEntry->GetStart();
+ nEnd = pEntry->GetEnd();
+ if ( nStart>=nStartRow && nEnd<=nEndRow )
+ {
+ pEntry->SetHidden( FALSE );
+ pEntry->SetVisible( TRUE );
+ if (nStart<nMin) nMin=nStart;
+ if (nEnd>nMax) nMax=nEnd;
+ }
+ }
+ for ( i=nMin; i<=nMax; i++ )
+ if ( !pDoc->IsFiltered( i,nTab ) ) // weggefilterte nicht einblenden
+ pDoc->ShowRow( i, nTab, TRUE );
+
+ pDoc->UpdatePageBreaks( nTab );
+
+ rDocShell.PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID | PAINT_LEFT | PAINT_TOP );
+
+ rDocShell.SetDocumentModified();
+ bDone = TRUE;
+
+ lcl_InvalidateOutliner( rDocShell.GetViewBindings() );
+ }
+
+ if (!bDone && !bApi)
+ Sound::Beep();
+
+ return bDone;
+}
+
+BOOL ScOutlineDocFunc::HideMarkedOutlines( const ScRange& rRange, BOOL bRecord, BOOL bApi )
+{
+ BOOL bDone = FALSE;
+
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ SCTAB nTab = rRange.aStart.Tab();
+
+ ScDocument* pDoc = rDocShell.GetDocument();
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+ ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
+
+ if (pTable)
+ {
+ ScOutlineEntry* pEntry;
+ USHORT nColLevel;
+ USHORT nRowLevel;
+ USHORT nCount;
+ SCCOLROW nStart;
+ SCCOLROW nEnd;
+ USHORT i;
+
+ SCCOLROW nEffStartCol = nStartCol;
+ SCCOLROW nEffEndCol = nEndCol;
+ ScOutlineArray* pColArray = pTable->GetColArray();
+ pColArray->FindTouchedLevel( nStartCol, nEndCol, nColLevel );
+ pColArray->ExtendBlock( nColLevel, nEffStartCol, nEffEndCol );
+ SCCOLROW nEffStartRow = nStartRow;
+ SCCOLROW nEffEndRow = nEndRow;
+ ScOutlineArray* pRowArray = pTable->GetRowArray();
+ pRowArray->FindTouchedLevel( nStartRow, nEndRow, nRowLevel );
+ pRowArray->ExtendBlock( nRowLevel, nEffStartRow, nEffEndRow );
+
+ if ( bRecord )
+ {
+ ScOutlineTable* pUndoTab = new ScOutlineTable( *pTable );
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, TRUE, TRUE );
+ pDoc->CopyToDocument( static_cast<SCCOL>(nEffStartCol), 0, nTab,
+ static_cast<SCCOL>(nEffEndCol), MAXROW, nTab, IDF_NONE,
+ FALSE, pUndoDoc );
+ pDoc->CopyToDocument( 0, nEffStartRow, nTab, MAXCOL, nEffEndRow, nTab, IDF_NONE, FALSE, pUndoDoc );
+
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoOutlineBlock( &rDocShell,
+ nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab,
+ pUndoDoc, pUndoTab, FALSE ) );
+ }
+
+ // Spalten
+
+ nCount = pColArray->GetCount(nColLevel);
+ for ( i=0; i<nCount; i++ )
+ {
+ pEntry = pColArray->GetEntry(nColLevel,i);
+ nStart = pEntry->GetStart();
+ nEnd = pEntry->GetEnd();
+
+ if ( static_cast<SCCOLROW>(nStartCol)<=nEnd && static_cast<SCCOLROW>(nEndCol)>=nStart )
+ HideOutline( nTab, TRUE, nColLevel, i, FALSE, FALSE, bApi );
+ }
+
+ // Zeilen
+
+ nCount = pRowArray->GetCount(nRowLevel);
+ for ( i=0; i<nCount; i++ )
+ {
+ pEntry = pRowArray->GetEntry(nRowLevel,i);
+ nStart = pEntry->GetStart();
+ nEnd = pEntry->GetEnd();
+
+ if ( nStartRow<=nEnd && nEndRow>=nStart )
+ HideOutline( nTab, FALSE, nRowLevel, i, FALSE, FALSE, bApi );
+ }
+
+ pDoc->UpdatePageBreaks( nTab );
+
+ rDocShell.PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID | PAINT_LEFT | PAINT_TOP );
+
+ rDocShell.SetDocumentModified();
+ bDone = TRUE;
+
+ lcl_InvalidateOutliner( rDocShell.GetViewBindings() );
+ }
+
+ if (!bDone && !bApi)
+ Sound::Beep();
+
+ return bDone;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScOutlineDocFunc::ShowOutline( SCTAB nTab, BOOL bColumns, USHORT nLevel, USHORT nEntry,
+ BOOL bRecord, BOOL bPaint, BOOL /* bApi */ )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+
+ ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
+ ScOutlineArray* pArray = bColumns ? pTable->GetColArray() : pTable->GetRowArray();
+ ScOutlineEntry* pEntry = pArray->GetEntry( nLevel, nEntry );
+ SCCOLROW nStart = pEntry->GetStart();
+ SCCOLROW nEnd = pEntry->GetEnd();
+
+ if ( bRecord )
+ {
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ if (bColumns)
+ {
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, TRUE, FALSE );
+ pDoc->CopyToDocument( static_cast<SCCOL>(nStart), 0, nTab,
+ static_cast<SCCOL>(nEnd), MAXROW, nTab, IDF_NONE, FALSE,
+ pUndoDoc );
+ }
+ else
+ {
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, FALSE, TRUE );
+ pDoc->CopyToDocument( 0, nStart, nTab, MAXCOL, nEnd, nTab, IDF_NONE, FALSE, pUndoDoc );
+ }
+
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDoOutline( &rDocShell,
+ nStart, nEnd, nTab, pUndoDoc, //! start und end berechnen
+ bColumns, nLevel, nEntry, TRUE ) );
+ }
+
+//! HideCursor();
+
+ pEntry->SetHidden(FALSE);
+ SCCOLROW i;
+ for ( i = nStart; i <= nEnd; i++ )
+ {
+ if ( bColumns )
+ pDoc->ShowCol( static_cast<SCCOL>(i), nTab, TRUE );
+ else
+ if ( !pDoc->IsFiltered( i,nTab ) ) // weggefilterte nicht einblenden
+ pDoc->ShowRow( i, nTab, TRUE );
+ }
+
+ ScSubOutlineIterator aIter( pArray, nLevel, nEntry );
+ while ((pEntry=aIter.GetNext()) != NULL)
+ {
+ if ( pEntry->IsHidden() )
+ {
+ SCCOLROW nSubStart = pEntry->GetStart();
+ SCCOLROW nSubEnd = pEntry->GetEnd();
+ for ( i = nSubStart; i <= nSubEnd; i++ )
+ {
+ if ( bColumns )
+ pDoc->ShowCol( static_cast<SCCOL>(i), nTab, FALSE );
+ else
+ pDoc->ShowRow( i, nTab, FALSE );
+ }
+ }
+ }
+
+ pArray->SetVisibleBelow( nLevel, nEntry, TRUE, TRUE );
+
+ pDoc->UpdatePageBreaks( nTab );
+
+ if (bPaint)
+ lcl_PaintWidthHeight( rDocShell, nTab, bColumns, nStart, nEnd );
+
+//! ShowCursor();
+ rDocShell.SetDocumentModified();
+
+//! if (bPaint)
+//! UpdateScrollBars();
+
+ lcl_InvalidateOutliner( rDocShell.GetViewBindings() );
+
+ return TRUE; //! immer ???
+}
+
+BOOL ScOutlineDocFunc::HideOutline( SCTAB nTab, BOOL bColumns, USHORT nLevel, USHORT nEntry,
+ BOOL bRecord, BOOL bPaint, BOOL /* bApi */ )
+{
+ ScDocument* pDoc = rDocShell.GetDocument();
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+
+ ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
+ ScOutlineArray* pArray = bColumns ? pTable->GetColArray() : pTable->GetRowArray();
+ ScOutlineEntry* pEntry = pArray->GetEntry( nLevel, nEntry );
+ SCCOLROW nStart = pEntry->GetStart();
+ SCCOLROW nEnd = pEntry->GetEnd();
+
+ if ( bRecord )
+ {
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ if (bColumns)
+ {
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, TRUE, FALSE );
+ pDoc->CopyToDocument( static_cast<SCCOL>(nStart), 0, nTab,
+ static_cast<SCCOL>(nEnd), MAXROW, nTab, IDF_NONE, FALSE,
+ pUndoDoc );
+ }
+ else
+ {
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, FALSE, TRUE );
+ pDoc->CopyToDocument( 0, nStart, nTab, MAXCOL, nEnd, nTab, IDF_NONE, FALSE, pUndoDoc );
+ }
+
+ rDocShell.GetUndoManager()->AddUndoAction(
+ new ScUndoDoOutline( &rDocShell,
+ nStart, nEnd, nTab, pUndoDoc,
+ bColumns, nLevel, nEntry, FALSE ) );
+ }
+
+//! HideCursor();
+
+ pEntry->SetHidden(TRUE);
+ SCCOLROW i;
+ for ( i = nStart; i <= nEnd; i++ )
+ {
+ if ( bColumns )
+ pDoc->ShowCol( static_cast<SCCOL>(i), nTab, FALSE );
+ else
+ pDoc->ShowRow( i, nTab, FALSE );
+ }
+
+ pArray->SetVisibleBelow( nLevel, nEntry, FALSE );
+
+ pDoc->UpdatePageBreaks( nTab );
+
+ if (bPaint)
+ lcl_PaintWidthHeight( rDocShell, nTab, bColumns, nStart, nEnd );
+
+//! ShowCursor();
+ rDocShell.SetDocumentModified();
+
+//! if (bPaint)
+//! UpdateScrollBars();
+
+ lcl_InvalidateOutliner( rDocShell.GetViewBindings() );
+
+ return TRUE; //! immer ???
+}
+
+
+
+
+
diff --git a/sc/source/ui/docshell/pagedata.cxx b/sc/source/ui/docshell/pagedata.cxx
new file mode 100644
index 000000000000..db55c2364305
--- /dev/null
+++ b/sc/source/ui/docshell/pagedata.cxx
@@ -0,0 +1,139 @@
+/*************************************************************************
+ *
+ * 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 <string.h>
+#include <tools/debug.hxx>
+
+
+#include "pagedata.hxx"
+
+//============================================================================
+
+ScPrintRangeData::ScPrintRangeData()
+{
+ nPagesX = nPagesY = 0;
+ pPageEndX = NULL;
+ pPageEndY = NULL;
+ bTopDown = bAutomatic = TRUE;
+ nFirstPage = 1;
+}
+
+ScPrintRangeData::~ScPrintRangeData()
+{
+ delete[] pPageEndX;
+ delete[] pPageEndY;
+}
+
+void ScPrintRangeData::SetPagesX( size_t nCount, const SCCOL* pData )
+{
+ delete[] pPageEndX;
+ if ( nCount )
+ {
+ pPageEndX = new SCCOL[nCount];
+ memcpy( pPageEndX, pData, nCount * sizeof(SCCOL) );
+ }
+ else
+ pPageEndX = NULL;
+ nPagesX = nCount;
+}
+
+void ScPrintRangeData::SetPagesY( size_t nCount, const SCROW* pData )
+{
+ delete[] pPageEndY;
+ if ( nCount )
+ {
+ pPageEndY = new SCROW[nCount];
+ memcpy( pPageEndY, pData, nCount * sizeof(SCROW) );
+ }
+ else
+ pPageEndY = NULL;
+ nPagesY = nCount;
+}
+
+//============================================================================
+
+ScPageBreakData::ScPageBreakData(size_t nMax)
+{
+ nUsed = 0;
+ if (nMax)
+ pData = new ScPrintRangeData[nMax];
+ else
+ pData = NULL;
+ nAlloc = nMax;
+}
+
+ScPageBreakData::~ScPageBreakData()
+{
+ delete[] pData;
+}
+
+ScPrintRangeData& ScPageBreakData::GetData(size_t nPos)
+{
+ DBG_ASSERT(nPos < nAlloc, "ScPageBreakData::GetData bumm");
+
+ if ( nPos >= nUsed )
+ {
+ DBG_ASSERT(nPos == nUsed, "ScPageBreakData::GetData falsche Reihenfolge");
+ nUsed = nPos+1;
+ }
+
+ return pData[nPos];
+}
+
+BOOL ScPageBreakData::IsEqual( const ScPageBreakData& rOther ) const
+{
+ if ( nUsed != rOther.nUsed )
+ return FALSE;
+
+ for (USHORT i=0; i<nUsed; i++)
+ if ( pData[i].GetPrintRange() != rOther.pData[i].GetPrintRange() )
+ return FALSE;
+
+ //! ScPrintRangeData komplett vergleichen ??
+
+ return TRUE;
+}
+
+void ScPageBreakData::AddPages()
+{
+ if ( nUsed > 1 )
+ {
+ long nPage = pData[0].GetFirstPage();
+ for (USHORT i=0; sal::static_int_cast<size_t>(i+1)<nUsed; i++)
+ {
+ nPage += ((long)pData[i].GetPagesX())*pData[i].GetPagesY();
+ pData[i+1].SetFirstPage( nPage );
+ }
+ }
+}
+
+
+
diff --git a/sc/source/ui/docshell/pntlock.cxx b/sc/source/ui/docshell/pntlock.cxx
new file mode 100644
index 000000000000..764d431f3af0
--- /dev/null
+++ b/sc/source/ui/docshell/pntlock.cxx
@@ -0,0 +1,61 @@
+/*************************************************************************
+ *
+ * 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 "pntlock.hxx"
+
+//------------------------------------------------------------------------
+
+ScPaintLockData::ScPaintLockData(USHORT nNewMode) :
+ nMode( nNewMode ),
+ nLevel( 0 ),
+ nDocLevel( 0 ),
+ nParts( 0 ),
+ bModified( FALSE )
+{
+}
+
+ScPaintLockData::~ScPaintLockData()
+{
+}
+
+void ScPaintLockData::AddRange( const ScRange& rRange, USHORT nP )
+{
+ if (!xRangeList.Is())
+ xRangeList = new ScRangeList;
+
+ xRangeList->Join( rRange );
+ nParts |= nP;
+}
+
+
+
+
diff --git a/sc/source/ui/docshell/servobj.cxx b/sc/source/ui/docshell/servobj.cxx
new file mode 100644
index 000000000000..dabe38fb8c1d
--- /dev/null
+++ b/sc/source/ui/docshell/servobj.cxx
@@ -0,0 +1,273 @@
+/*************************************************************************
+ *
+ * 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"
+// System - Includes -----------------------------------------------------
+
+
+
+#include <sot/formats.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/linkmgr.hxx>
+#include "servobj.hxx"
+#include "docsh.hxx"
+#include "impex.hxx"
+#include "brdcst.hxx"
+#include "rangenam.hxx"
+#include "sc.hrc" // SC_HINT_AREAS_CHANGED
+
+// -----------------------------------------------------------------------
+
+BOOL lcl_FillRangeFromName( ScRange& rRange, ScDocShell* pDocSh, const String& rName )
+{
+ if (pDocSh)
+ {
+ ScDocument* pDoc = pDocSh->GetDocument();
+ ScRangeName* pNames = pDoc->GetRangeName();
+ if (pNames)
+ {
+ USHORT nPos;
+ if( pNames->SearchName( rName, nPos ) )
+ {
+ ScRangeData* pData = (*pNames)[ nPos ];
+ if ( pData->IsValidReference( rRange ) )
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+ScServerObjectSvtListenerForwarder::ScServerObjectSvtListenerForwarder(
+ ScServerObject* pObjP)
+ : pObj(pObjP)
+{
+}
+
+ScServerObjectSvtListenerForwarder::~ScServerObjectSvtListenerForwarder()
+{
+ //! do NOT access pObj
+}
+
+void ScServerObjectSvtListenerForwarder::Notify( SvtBroadcaster& /* rBC */, const SfxHint& rHint)
+{
+ pObj->Notify( aBroadcaster, rHint);
+}
+
+ScServerObject::ScServerObject( ScDocShell* pShell, const String& rItem ) :
+ aForwarder( this ),
+ pDocSh( pShell ),
+ bRefreshListener( FALSE )
+{
+ // parse item string
+
+ if ( lcl_FillRangeFromName( aRange, pDocSh, rItem ) )
+ {
+ aItemStr = rItem; // must be parsed again on ref update
+ }
+ else
+ {
+ // parse ref
+ ScDocument* pDoc = pDocSh->GetDocument();
+ SCTAB nTab = pDocSh->GetCurTab();
+ aRange.aStart.SetTab( nTab );
+
+ if ( aRange.Parse( rItem, pDoc ) & SCA_VALID )
+ {
+ // area reference
+ }
+ else if ( aRange.aStart.Parse( rItem, pDoc, pDoc->GetAddressConvention() ) & SCA_VALID )
+ {
+ // cell reference
+ aRange.aEnd = aRange.aStart;
+ }
+ else
+ {
+ DBG_ERROR("ScServerObject: invalid item");
+ }
+ }
+
+ pDocSh->GetDocument()->GetLinkManager()->InsertServer( this );
+ pDocSh->GetDocument()->StartListeningArea( aRange, &aForwarder );
+
+ StartListening(*pDocSh); // um mitzubekommen, wenn die DocShell geloescht wird
+ StartListening(*SFX_APP()); // for SC_HINT_AREAS_CHANGED
+}
+
+__EXPORT ScServerObject::~ScServerObject()
+{
+ Clear();
+}
+
+void ScServerObject::Clear()
+{
+ if (pDocSh)
+ {
+ ScDocShell* pTemp = pDocSh;
+ pDocSh = NULL;
+
+ pTemp->GetDocument()->EndListeningArea( aRange, &aForwarder );
+ pTemp->GetDocument()->GetLinkManager()->RemoveServer( this );
+ EndListening(*pTemp);
+ EndListening(*SFX_APP());
+ }
+}
+
+void ScServerObject::EndListeningAll()
+{
+ aForwarder.EndListeningAll();
+ SfxListener::EndListeningAll();
+}
+
+BOOL __EXPORT ScServerObject::GetData(
+ ::com::sun::star::uno::Any & rData /*out param*/,
+ const String & rMimeType, BOOL /* bSynchron */ )
+{
+ if (!pDocSh)
+ return FALSE;
+
+ // named ranges may have changed -> update aRange
+ if ( aItemStr.Len() )
+ {
+ ScRange aNew;
+ if ( lcl_FillRangeFromName( aNew, pDocSh, aItemStr ) && aNew != aRange )
+ {
+ aRange = aNew;
+ bRefreshListener = TRUE;
+ }
+ }
+
+ if ( bRefreshListener )
+ {
+ // refresh the listeners now (this is called from a timer)
+
+ EndListeningAll();
+ pDocSh->GetDocument()->StartListeningArea( aRange, &aForwarder );
+ StartListening(*pDocSh);
+ StartListening(*SFX_APP());
+ bRefreshListener = FALSE;
+ }
+
+ String aDdeTextFmt = pDocSh->GetDdeTextFmt();
+ ScDocument* pDoc = pDocSh->GetDocument();
+
+ if( FORMAT_STRING == SotExchange::GetFormatIdFromMimeType( rMimeType ))
+ {
+ ScImportExport aObj( pDoc, aRange );
+ if( aDdeTextFmt.GetChar(0) == 'F' )
+ aObj.SetFormulas( TRUE );
+ if( aDdeTextFmt.EqualsAscii( "SYLK" ) ||
+ aDdeTextFmt.EqualsAscii( "FSYLK" ) )
+ {
+ ByteString aByteData;
+ if( aObj.ExportByteString( aByteData, gsl_getSystemTextEncoding(), SOT_FORMATSTR_ID_SYLK ) )
+ {
+ rData <<= ::com::sun::star::uno::Sequence< sal_Int8 >(
+ (sal_Int8*)aByteData.GetBuffer(),
+ aByteData.Len() + 1 );
+ return 1;
+ }
+ return 0;
+ }
+ if( aDdeTextFmt.EqualsAscii( "CSV" ) ||
+ aDdeTextFmt.EqualsAscii( "FCSV" ) )
+ aObj.SetSeparator( ',' );
+ aObj.SetExportTextOptions( ScExportTextOptions( ScExportTextOptions::ToSpace, ' ', false ) );
+ return aObj.ExportData( rMimeType, rData ) ? 1 : 0;
+ }
+
+ ScImportExport aObj( pDoc, aRange );
+ aObj.SetExportTextOptions( ScExportTextOptions( ScExportTextOptions::ToSpace, ' ', false ) );
+ if( aObj.IsRef() )
+ return aObj.ExportData( rMimeType, rData ) ? 1 : 0;
+ return 0;
+}
+
+void __EXPORT ScServerObject::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
+{
+ BOOL bDataChanged = FALSE;
+
+ // DocShell can't be tested via type info, because SFX_HINT_DYING comes from the dtor
+ if ( &rBC == pDocSh )
+ {
+ // from DocShell, only SFX_HINT_DYING is interesting
+ if ( rHint.ISA(SfxSimpleHint) && ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
+ {
+ pDocSh = NULL;
+ EndListening(*SFX_APP());
+ // don't access DocShell anymore for EndListening etc.
+ }
+ }
+ else if (rBC.ISA(SfxApplication))
+ {
+ if ( aItemStr.Len() && rHint.ISA(SfxSimpleHint) &&
+ ((const SfxSimpleHint&)rHint).GetId() == SC_HINT_AREAS_CHANGED )
+ {
+ // check if named range was modified
+ ScRange aNew;
+ if ( lcl_FillRangeFromName( aNew, pDocSh, aItemStr ) && aNew != aRange )
+ bDataChanged = TRUE;
+ }
+ }
+ else
+ {
+ // must be from Area broadcasters
+
+ const ScHint* pScHint = PTR_CAST( ScHint, &rHint );
+ if( pScHint && (pScHint->GetId() & (SC_HINT_DATACHANGED | SC_HINT_DYING)) )
+ bDataChanged = TRUE;
+ else if (rHint.ISA(ScAreaChangedHint)) // position of broadcaster changed
+ {
+ ScRange aNewRange = ((const ScAreaChangedHint&)rHint).GetRange();
+ if ( aRange != aNewRange )
+ {
+ bRefreshListener = TRUE;
+ bDataChanged = TRUE;
+ }
+ }
+ else if (rHint.ISA(SfxSimpleHint))
+ {
+ ULONG nId = ((const SfxSimpleHint&)rHint).GetId();
+ if (nId == SFX_HINT_DYING)
+ {
+ // If the range is being deleted, listening must be restarted
+ // after the deletion is complete (done in GetData)
+ bRefreshListener = TRUE;
+ bDataChanged = TRUE;
+ }
+ }
+ }
+
+ if ( bDataChanged && HasDataLinks() )
+ SvLinkSource::NotifyDataChanged();
+}
+
+
+
+
+
diff --git a/sc/source/ui/docshell/sizedev.cxx b/sc/source/ui/docshell/sizedev.cxx
new file mode 100644
index 000000000000..d89009540156
--- /dev/null
+++ b/sc/source/ui/docshell/sizedev.cxx
@@ -0,0 +1,77 @@
+/*************************************************************************
+ *
+ * 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 <sfx2/printer.hxx>
+#include <vcl/virdev.hxx>
+
+#include "sizedev.hxx"
+#include "docsh.hxx"
+#include "scmod.hxx"
+#include "inputopt.hxx"
+
+//------------------------------------------------------------------
+
+ScSizeDeviceProvider::ScSizeDeviceProvider( ScDocShell* pDocSh )
+{
+ BOOL bTextWysiwyg = SC_MOD()->GetInputOptions().GetTextWysiwyg();
+ if ( bTextWysiwyg )
+ {
+ pDevice = pDocSh->GetPrinter();
+ bOwner = FALSE;
+
+ aOldMapMode = pDevice->GetMapMode();
+ pDevice->SetMapMode( MAP_PIXEL ); // GetNeededSize needs pixel MapMode
+ // printer has right DigitLanguage already
+ }
+ else
+ {
+ pDevice = new VirtualDevice;
+ pDevice->SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
+ bOwner = TRUE;
+ }
+
+ Point aLogic = pDevice->LogicToPixel( Point(1000,1000), MAP_TWIP );
+ nPPTX = aLogic.X() / 1000.0;
+ nPPTY = aLogic.Y() / 1000.0;
+
+ if ( !bTextWysiwyg )
+ nPPTX /= pDocSh->GetOutputFactor();
+}
+
+ScSizeDeviceProvider::~ScSizeDeviceProvider()
+{
+ if (bOwner)
+ delete pDevice;
+ else
+ pDevice->SetMapMode( aOldMapMode );
+}
+
diff --git a/sc/source/ui/docshell/tablink.cxx b/sc/source/ui/docshell/tablink.cxx
new file mode 100644
index 000000000000..4d18f9f18c37
--- /dev/null
+++ b/sc/source/ui/docshell/tablink.cxx
@@ -0,0 +1,616 @@
+/*************************************************************************
+ *
+ * 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"
+#ifdef _MSC_VER
+#pragma optimize("",off)
+#endif
+
+//------------------------------------------------------------------
+
+
+
+// INCLUDE ---------------------------------------------------------
+
+#include <sfx2/sfxsids.hrc>
+#include <sfx2/app.hxx>
+#include <svl/itemset.hxx>
+#include <svl/stritem.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/docfilt.hxx>
+#include <sfx2/fcontnr.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <tools/urlobj.hxx>
+#include <unotools/transliterationwrapper.hxx>
+
+#include "tablink.hxx"
+
+#include "scextopt.hxx"
+#include "table.hxx"
+#include "document.hxx"
+#include "docsh.hxx"
+#include "globstr.hrc"
+#include "undoblk.hxx"
+#include "undotab.hxx"
+#include "global.hxx"
+#include "hints.hxx"
+#include "cell.hxx"
+#include "dociter.hxx"
+#include "formula/opcode.hxx"
+
+struct TableLink_Impl
+{
+ ScDocShell* m_pDocSh;
+ Window* m_pOldParent;
+ Link m_aEndEditLink;
+
+ TableLink_Impl() : m_pDocSh( NULL ), m_pOldParent( NULL ) {}
+};
+
+TYPEINIT1(ScTableLink, ::sfx2::SvBaseLink);
+
+//------------------------------------------------------------------------
+
+ScTableLink::ScTableLink(ScDocShell* pDocSh, const String& rFile,
+ const String& rFilter, const String& rOpt,
+ ULONG nRefresh ):
+ ::sfx2::SvBaseLink(sfx2::LINKUPDATE_ONCALL,FORMAT_FILE),
+ ScRefreshTimer( nRefresh ),
+ pImpl( new TableLink_Impl ),
+ aFileName(rFile),
+ aFilterName(rFilter),
+ aOptions(rOpt),
+ bInCreate( FALSE ),
+ bInEdit( FALSE ),
+ bAddUndo( TRUE ),
+ bDoPaint( TRUE )
+{
+ pImpl->m_pDocSh = pDocSh;
+}
+
+ScTableLink::ScTableLink(SfxObjectShell* pShell, const String& rFile,
+ const String& rFilter, const String& rOpt,
+ ULONG nRefresh ):
+ ::sfx2::SvBaseLink(sfx2::LINKUPDATE_ONCALL,FORMAT_FILE),
+ ScRefreshTimer( nRefresh ),
+ pImpl( new TableLink_Impl ),
+ aFileName(rFile),
+ aFilterName(rFilter),
+ aOptions(rOpt),
+ bInCreate( FALSE ),
+ bInEdit( FALSE ),
+ bAddUndo( TRUE ),
+ bDoPaint( TRUE )
+{
+ pImpl->m_pDocSh = static_cast< ScDocShell* >( pShell );
+ SetRefreshHandler( LINK( this, ScTableLink, RefreshHdl ) );
+ SetRefreshControl( pImpl->m_pDocSh->GetDocument()->GetRefreshTimerControlAddress() );
+}
+
+__EXPORT ScTableLink::~ScTableLink()
+{
+ // Verbindung aufheben
+
+ StopRefreshTimer();
+ String aEmpty;
+ ScDocument* pDoc = pImpl->m_pDocSh->GetDocument();
+ SCTAB nCount = pDoc->GetTableCount();
+ for (SCTAB nTab=0; nTab<nCount; nTab++)
+ if (pDoc->IsLinked(nTab) && pDoc->GetLinkDoc(nTab)==aFileName)
+ pDoc->SetLink( nTab, SC_LINK_NONE, aEmpty, aEmpty, aEmpty, aEmpty, 0 );
+ delete pImpl;
+}
+
+void __EXPORT ScTableLink::Edit( Window* pParent, const Link& rEndEditHdl )
+{
+ // DefModalDialogParent setzen, weil evtl. aus der DocShell beim ConvertFrom
+ // ein Optionen-Dialog kommt...
+
+ pImpl->m_aEndEditLink = rEndEditHdl;
+ pImpl->m_pOldParent = Application::GetDefDialogParent();
+ if (pParent)
+ Application::SetDefDialogParent(pParent);
+
+ bInEdit = TRUE;
+ SvBaseLink::Edit( pParent, LINK( this, ScTableLink, TableEndEditHdl ) );
+}
+
+void __EXPORT ScTableLink::DataChanged( const String&,
+ const ::com::sun::star::uno::Any& )
+{
+ sfx2::LinkManager* pLinkManager=pImpl->m_pDocSh->GetDocument()->GetLinkManager();
+ if (pLinkManager!=NULL)
+ {
+ String aFile;
+ String aFilter;
+ pLinkManager->GetDisplayNames( this,0,&aFile,NULL,&aFilter);
+
+ // the file dialog returns the filter name with the application prefix
+ // -> remove prefix
+ ScDocumentLoader::RemoveAppPrefix( aFilter );
+
+ if (!bInCreate)
+ Refresh( aFile, aFilter, NULL, GetRefreshDelay() ); // don't load twice
+ }
+}
+
+void __EXPORT ScTableLink::Closed()
+{
+ // Verknuepfung loeschen: Undo
+ ScDocument* pDoc = pImpl->m_pDocSh->GetDocument();
+ BOOL bUndo (pDoc->IsUndoEnabled());
+
+ if (bAddUndo && bUndo)
+ {
+ pImpl->m_pDocSh->GetUndoManager()->AddUndoAction(
+ new ScUndoRemoveLink( pImpl->m_pDocSh, aFileName ) );
+
+ bAddUndo = FALSE; // nur einmal
+ }
+
+ // Verbindung wird im dtor aufgehoben
+
+ SvBaseLink::Closed();
+}
+
+BOOL ScTableLink::IsUsed() const
+{
+ return pImpl->m_pDocSh->GetDocument()->HasLink( aFileName, aFilterName, aOptions );
+}
+
+BOOL ScTableLink::Refresh(const String& rNewFile, const String& rNewFilter,
+ const String* pNewOptions, ULONG nNewRefresh )
+{
+ // Dokument laden
+
+ if (!rNewFile.Len() || !rNewFilter.Len())
+ return FALSE;
+
+ String aNewUrl( ScGlobal::GetAbsDocName( rNewFile, pImpl->m_pDocSh ) );
+ BOOL bNewUrlName = (aNewUrl != aFileName);
+
+ const SfxFilter* pFilter = pImpl->m_pDocSh->GetFactory().GetFilterContainer()->GetFilter4FilterName(rNewFilter);
+ if (!pFilter)
+ return FALSE;
+
+ ScDocument* pDoc = pImpl->m_pDocSh->GetDocument();
+ pDoc->SetInLinkUpdate( TRUE );
+
+ BOOL bUndo(pDoc->IsUndoEnabled());
+
+ // wenn neuer Filter ausgewaehlt wurde, Optionen vergessen
+ if ( rNewFilter != aFilterName )
+ aOptions.Erase();
+ if ( pNewOptions ) // Optionen hart angegeben?
+ aOptions = *pNewOptions;
+
+ // ItemSet immer anlegen, damit die DocShell die Optionen setzen kann
+ SfxItemSet* pSet = new SfxAllItemSet( SFX_APP()->GetPool() );
+ if ( aOptions.Len() )
+ pSet->Put( SfxStringItem( SID_FILE_FILTEROPTIONS, aOptions ) );
+
+ SfxMedium* pMed = new SfxMedium(aNewUrl, STREAM_STD_READ, FALSE, pFilter, pSet);
+
+ if ( bInEdit ) // only if using the edit dialog,
+ pMed->UseInteractionHandler( TRUE ); // enable the filter options dialog
+
+ ScDocShell* pSrcShell = new ScDocShell(SFX_CREATE_MODE_INTERNAL);
+ SfxObjectShellRef aRef = pSrcShell;
+ pSrcShell->DoLoad(pMed);
+
+ // Optionen koennten gesetzt worden sein
+ String aNewOpt = ScDocumentLoader::GetOptions(*pMed);
+ if (!aNewOpt.Len())
+ aNewOpt = aOptions;
+
+ // Undo...
+
+ ScDocument* pUndoDoc = NULL;
+ BOOL bFirst = TRUE;
+ if (bAddUndo && bUndo)
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+
+ // Tabellen kopieren
+
+ ScDocShellModificator aModificator( *pImpl->m_pDocSh );
+
+ BOOL bNotFound = FALSE;
+ ScDocument* pSrcDoc = pSrcShell->GetDocument();
+
+ // #74835# from text filters that don't set the table name,
+ // use the one table regardless of link table name
+ BOOL bAutoTab = (pSrcDoc->GetTableCount() == 1) &&
+ ScDocShell::HasAutomaticTableName( rNewFilter );
+
+ SCTAB nCount = pDoc->GetTableCount();
+ for (SCTAB nTab=0; nTab<nCount; nTab++)
+ {
+ BYTE nMode = pDoc->GetLinkMode(nTab);
+ if (nMode && pDoc->GetLinkDoc(nTab)==aFileName)
+ {
+ String aTabName = pDoc->GetLinkTab(nTab);
+
+ // Undo
+
+ if (bAddUndo && bUndo)
+ {
+ if (bFirst)
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, TRUE, TRUE );
+ else
+ pUndoDoc->AddUndoTab( nTab, nTab, TRUE, TRUE );
+ bFirst = FALSE;
+ ScRange aRange(0,0,nTab,MAXCOL,MAXROW,nTab);
+ pDoc->CopyToDocument(aRange, IDF_ALL, FALSE, pUndoDoc);
+ pUndoDoc->TransferDrawPage( pDoc, nTab, nTab );
+ pUndoDoc->SetLink( nTab, nMode, aFileName, aFilterName,
+ aOptions, aTabName, GetRefreshDelay() );
+ }
+
+ // Tabellenname einer ExtDocRef anpassen
+
+ if ( bNewUrlName && nMode == SC_LINK_VALUE )
+ {
+ String aName;
+ pDoc->GetName( nTab, aName );
+ if ( ScGlobal::GetpTransliteration()->isEqual(
+ ScGlobal::GetDocTabName( aFileName, aTabName ), aName ) )
+ {
+ pDoc->RenameTab( nTab,
+ ScGlobal::GetDocTabName( aNewUrl, aTabName ),
+ FALSE, TRUE ); // kein RefUpdate, kein ValidTabName
+ }
+ }
+
+ // kopieren
+
+ SCTAB nSrcTab = 0;
+ bool bFound = false;
+ /* #i71497# check if external document is loaded successfully,
+ otherwise we may find the empty default sheet "Sheet1" in
+ pSrcDoc, even if the document does not exist. */
+ if( pMed->GetError() == 0 )
+ {
+ // no sheet name -> use first sheet
+ if ( aTabName.Len() && !bAutoTab )
+ bFound = pSrcDoc->GetTable( aTabName, nSrcTab );
+ else
+ bFound = true;
+ }
+
+ if (bFound)
+ pDoc->TransferTab( pSrcDoc, nSrcTab, nTab, FALSE, // nicht neu einfuegen
+ (nMode == SC_LINK_VALUE) ); // nur Werte?
+ else
+ {
+ pDoc->DeleteAreaTab( 0,0,MAXCOL,MAXROW, nTab, IDF_ALL );
+
+ bool bShowError = true;
+ if ( nMode == SC_LINK_VALUE )
+ {
+ // #139464# Value link (used with external references in formulas):
+ // Look for formulas that reference the sheet, and put errors in the referenced cells.
+
+ ScRangeList aErrorCells; // cells on the linked sheets that need error values
+
+ ScCellIterator aCellIter( pDoc, 0,0,0, MAXCOL,MAXROW,MAXTAB ); // all sheets
+ ScBaseCell* pCell = aCellIter.GetFirst();
+ while (pCell)
+ {
+ if (pCell->GetCellType() == CELLTYPE_FORMULA)
+ {
+ ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
+
+ ScDetectiveRefIter aRefIter( pFCell );
+ ScRange aRefRange;
+ while ( aRefIter.GetNextRef( aRefRange ) )
+ {
+ if ( aRefRange.aStart.Tab() <= nTab && aRefRange.aEnd.Tab() >= nTab )
+ {
+ // use first cell of range references (don't fill potentially large ranges)
+
+ aErrorCells.Join( ScRange( aRefRange.aStart ) );
+ }
+ }
+ }
+ pCell = aCellIter.GetNext();
+ }
+
+ ULONG nRanges = aErrorCells.Count();
+ if ( nRanges ) // found any?
+ {
+ ScTokenArray aTokenArr;
+ aTokenArr.AddOpCode( ocNotAvail );
+ aTokenArr.AddOpCode( ocOpen );
+ aTokenArr.AddOpCode( ocClose );
+ aTokenArr.AddOpCode( ocStop );
+
+ for (ULONG nPos=0; nPos<nRanges; nPos++)
+ {
+ const ScRange* pRange = aErrorCells.GetObject(nPos);
+ SCCOL nStartCol = pRange->aStart.Col();
+ SCROW nStartRow = pRange->aStart.Row();
+ SCCOL nEndCol = pRange->aEnd.Col();
+ SCROW nEndRow = pRange->aEnd.Row();
+ for (SCROW nRow=nStartRow; nRow<=nEndRow; nRow++)
+ for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++)
+ {
+ ScAddress aDestPos( nCol, nRow, nTab );
+ ScFormulaCell* pNewCell = new ScFormulaCell( pDoc, aDestPos, &aTokenArr );
+ pDoc->PutCell( aDestPos, pNewCell );
+ }
+ }
+
+ bShowError = false;
+ }
+ // if no references were found, insert error message (don't leave the sheet empty)
+ }
+
+ if ( bShowError )
+ {
+ // Normal link or no references: put error message on sheet.
+
+ pDoc->SetString( 0,0,nTab, ScGlobal::GetRscString(STR_LINKERROR) );
+ pDoc->SetString( 0,1,nTab, ScGlobal::GetRscString(STR_LINKERRORFILE) );
+ pDoc->SetString( 1,1,nTab, aNewUrl );
+ pDoc->SetString( 0,2,nTab, ScGlobal::GetRscString(STR_LINKERRORTAB) );
+ pDoc->SetString( 1,2,nTab, aTabName );
+ }
+
+ bNotFound = TRUE;
+ }
+
+ if ( bNewUrlName || rNewFilter != aFilterName ||
+ aNewOpt != aOptions || pNewOptions ||
+ nNewRefresh != GetRefreshDelay() )
+ pDoc->SetLink( nTab, nMode, aNewUrl, rNewFilter, aNewOpt,
+ aTabName, nNewRefresh );
+ }
+ }
+
+ // neue Einstellungen merken
+
+ if ( bNewUrlName )
+ aFileName = aNewUrl;
+ if ( rNewFilter != aFilterName )
+ aFilterName = rNewFilter;
+ if ( aNewOpt != aOptions )
+ aOptions = aNewOpt;
+
+ // aufraeumen
+
+// pSrcShell->DoClose();
+ aRef->DoClose();
+
+ // Undo
+
+ if (bAddUndo && bUndo)
+ pImpl->m_pDocSh->GetUndoManager()->AddUndoAction(
+ new ScUndoRefreshLink( pImpl->m_pDocSh, pUndoDoc ) );
+
+ // Paint (koennen mehrere Tabellen sein)
+
+ if (bDoPaint)
+ {
+ pImpl->m_pDocSh->PostPaint( ScRange(0,0,0,MAXCOL,MAXROW,MAXTAB),
+ PAINT_GRID | PAINT_TOP | PAINT_LEFT );
+ aModificator.SetDocumentModified();
+ }
+
+ if (bNotFound)
+ {
+ //! Fehler ausgeben ?
+ }
+
+ pDoc->SetInLinkUpdate( FALSE );
+
+ // notify Uno objects (for XRefreshListener)
+ //! also notify Uno objects if file name was changed!
+ ScLinkRefreshedHint aHint;
+ aHint.SetSheetLink( aFileName );
+ pDoc->BroadcastUno( aHint );
+
+ return TRUE;
+}
+
+IMPL_LINK( ScTableLink, RefreshHdl, ScTableLink*, EMPTYARG )
+{
+ long nRes = Refresh( aFileName, aFilterName, NULL, GetRefreshDelay() ) != 0;
+ return nRes;
+}
+
+IMPL_LINK( ScTableLink, TableEndEditHdl, ::sfx2::SvBaseLink*, pLink )
+{
+ if ( pImpl->m_aEndEditLink.IsSet() )
+ pImpl->m_aEndEditLink.Call( pLink );
+ bInEdit = FALSE;
+ Application::SetDefDialogParent( pImpl->m_pOldParent );
+ return 0;
+}
+
+// === ScDocumentLoader ==================================================
+
+String ScDocumentLoader::GetOptions( SfxMedium& rMedium ) // static
+{
+ SfxItemSet* pSet = rMedium.GetItemSet();
+ const SfxPoolItem* pItem;
+ if ( pSet && SFX_ITEM_SET == pSet->GetItemState( SID_FILE_FILTEROPTIONS, TRUE, &pItem ) )
+ return ((const SfxStringItem*)pItem)->GetValue();
+
+ return EMPTY_STRING;
+}
+
+BOOL ScDocumentLoader::GetFilterName( const String& rFileName,
+ String& rFilter, String& rOptions,
+ BOOL bWithContent, BOOL bWithInteraction ) // static
+{
+ TypeId aScType = TYPE(ScDocShell);
+ SfxObjectShell* pDocSh = SfxObjectShell::GetFirst( &aScType );
+ while ( pDocSh )
+ {
+ if ( pDocSh->HasName() )
+ {
+ SfxMedium* pMed = pDocSh->GetMedium();
+ if ( rFileName == pMed->GetName() )
+ {
+ rFilter = pMed->GetFilter()->GetFilterName();
+ rOptions = GetOptions(*pMed);
+ return TRUE;
+ }
+ }
+ pDocSh = SfxObjectShell::GetNext( *pDocSh, &aScType );
+ }
+
+ // Filter-Detection
+
+ const SfxFilter* pSfxFilter = NULL;
+ SfxMedium* pMedium = new SfxMedium( rFileName, STREAM_STD_READ, FALSE );
+ if ( pMedium->GetError() == ERRCODE_NONE )
+ {
+ if ( bWithInteraction )
+ pMedium->UseInteractionHandler(TRUE); // #i73992# no longer called from GuessFilter
+
+ SfxFilterMatcher aMatcher( String::CreateFromAscii("scalc") );
+ if( bWithContent )
+ aMatcher.GuessFilter( *pMedium, &pSfxFilter );
+ else
+ aMatcher.GuessFilterIgnoringContent( *pMedium, &pSfxFilter );
+ }
+
+ BOOL bOK = FALSE;
+ if ( pMedium->GetError() == ERRCODE_NONE )
+ {
+ if ( pSfxFilter )
+ rFilter = pSfxFilter->GetFilterName();
+ else
+ rFilter = ScDocShell::GetOwnFilterName(); // sonst Calc-Datei
+ bOK = (rFilter.Len()>0);
+ }
+
+ delete pMedium;
+ return bOK;
+}
+
+void ScDocumentLoader::RemoveAppPrefix( String& rFilterName ) // static
+{
+ String aAppPrefix = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM( STRING_SCAPP ));
+ aAppPrefix.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ": " ));
+ xub_StrLen nPreLen = aAppPrefix.Len();
+ if ( rFilterName.Copy(0,nPreLen) == aAppPrefix )
+ rFilterName.Erase(0,nPreLen);
+}
+
+ScDocumentLoader::ScDocumentLoader( const String& rFileName,
+ String& rFilterName, String& rOptions,
+ UINT32 nRekCnt, BOOL bWithInteraction ) :
+ pDocShell(0),
+ pMedium(0)
+{
+ if ( !rFilterName.Len() )
+ GetFilterName( rFileName, rFilterName, rOptions, TRUE, bWithInteraction );
+
+ const SfxFilter* pFilter = ScDocShell::Factory().GetFilterContainer()->GetFilter4FilterName( rFilterName );
+
+ // ItemSet immer anlegen, damit die DocShell die Optionen setzen kann
+ SfxItemSet* pSet = new SfxAllItemSet( SFX_APP()->GetPool() );
+ if ( rOptions.Len() )
+ pSet->Put( SfxStringItem( SID_FILE_FILTEROPTIONS, rOptions ) );
+
+ pMedium = new SfxMedium( rFileName, STREAM_STD_READ, FALSE, pFilter, pSet );
+ if ( pMedium->GetError() != ERRCODE_NONE )
+ return ;
+
+ if ( bWithInteraction )
+ pMedium->UseInteractionHandler( TRUE ); // to enable the filter options dialog
+
+ pDocShell = new ScDocShell( SFX_CREATE_MODE_INTERNAL );
+ aRef = pDocShell;
+
+ ScDocument* pDoc = pDocShell->GetDocument();
+ if( pDoc )
+ {
+ ScExtDocOptions* pExtDocOpt = pDoc->GetExtDocOptions();
+ if( !pExtDocOpt )
+ {
+ pExtDocOpt = new ScExtDocOptions;
+ pDoc->SetExtDocOptions( pExtDocOpt );
+ }
+ pExtDocOpt->GetDocSettings().mnLinkCnt = nRekCnt;
+ }
+
+ pDocShell->DoLoad( pMedium );
+
+ String aNew = GetOptions(*pMedium); // Optionen werden beim Laden per Dialog gesetzt
+ if (aNew.Len() && aNew != rOptions)
+ rOptions = aNew;
+}
+
+ScDocumentLoader::~ScDocumentLoader()
+{
+/* if ( pDocShell )
+ pDocShell->DoClose();
+*/
+ if ( aRef.Is() )
+ aRef->DoClose();
+ else if ( pMedium )
+ delete pMedium;
+}
+
+void ScDocumentLoader::ReleaseDocRef()
+{
+ if ( aRef.Is() )
+ {
+ // release reference without calling DoClose - caller must
+ // have another reference to the doc and call DoClose later
+
+ pDocShell = NULL;
+ pMedium = NULL;
+ aRef.Clear();
+ }
+}
+
+ScDocument* ScDocumentLoader::GetDocument()
+{
+ return pDocShell ? pDocShell->GetDocument() : 0;
+}
+
+BOOL ScDocumentLoader::IsError() const
+{
+ if ( pDocShell && pMedium )
+ return pMedium->GetError() != ERRCODE_NONE;
+ else
+ return TRUE;
+}
+
+String ScDocumentLoader::GetTitle() const
+{
+ if ( pDocShell )
+ return pDocShell->GetTitle();
+ else
+ return EMPTY_STRING;
+}
+
diff --git a/sc/source/ui/docshell/tpstat.cxx b/sc/source/ui/docshell/tpstat.cxx
new file mode 100644
index 000000000000..1072af30c7a1
--- /dev/null
+++ b/sc/source/ui/docshell/tpstat.cxx
@@ -0,0 +1,101 @@
+/*************************************************************************
+ *
+ * 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"
+
+#undef SC_DLLIMPLEMENTATION
+
+
+
+#include "document.hxx"
+#include "docsh.hxx"
+#include "scresid.hxx"
+#include "tpstat.hrc"
+
+#include "tpstat.hxx"
+
+
+//========================================================================
+// Dokumentinfo-Tabpage:
+//========================================================================
+
+SfxTabPage* __EXPORT ScDocStatPage::Create( Window *pParent, const SfxItemSet& rSet )
+{
+ return new ScDocStatPage( pParent, rSet );
+}
+
+//------------------------------------------------------------------------
+
+ScDocStatPage::ScDocStatPage( Window *pParent, const SfxItemSet& rSet )
+ : SfxTabPage( pParent, ScResId(RID_SCPAGE_STAT), rSet ),
+ aFlInfo ( this, ScResId( FL_INFO ) ),
+ aFtTablesLbl ( this, ScResId( FT_TABLES_LBL ) ),
+ aFtTables ( this, ScResId( FT_TABLES ) ),
+ aFtCellsLbl ( this, ScResId( FT_CELLS_LBL ) ),
+ aFtCells ( this, ScResId( FT_CELLS ) ),
+ aFtPagesLbl ( this, ScResId( FT_PAGES_LBL ) ),
+ aFtPages ( this, ScResId( FT_PAGES ) )
+{
+ ScDocShell* pDocSh = PTR_CAST( ScDocShell, SfxObjectShell::Current() );
+ ScDocStat aDocStat;
+
+ if ( pDocSh )
+ pDocSh->GetDocStat( aDocStat );
+
+ String aInfo = aFlInfo.GetText();
+ aInfo += aDocStat.aDocName;
+ aFlInfo .SetText( aInfo );
+ aFtTables .SetText( String::CreateFromInt32( aDocStat.nTableCount ) );
+ aFtCells .SetText( String::CreateFromInt32( aDocStat.nCellCount ) );
+ aFtPages .SetText( String::CreateFromInt32( aDocStat.nPageCount ) );
+
+ FreeResource();
+}
+
+//------------------------------------------------------------------------
+
+__EXPORT ScDocStatPage::~ScDocStatPage()
+{
+}
+
+//------------------------------------------------------------------------
+
+BOOL __EXPORT ScDocStatPage::FillItemSet( SfxItemSet& /* rSet */ )
+{
+ return FALSE;
+}
+
+//------------------------------------------------------------------------
+
+void __EXPORT ScDocStatPage::Reset( const SfxItemSet& /* rSet */ )
+{
+}
+
+
+
+
diff --git a/sc/source/ui/docshell/tpstat.hrc b/sc/source/ui/docshell/tpstat.hrc
new file mode 100644
index 000000000000..2b57d20f1a26
--- /dev/null
+++ b/sc/source/ui/docshell/tpstat.hrc
@@ -0,0 +1,36 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+#include "sc.hrc"
+
+#define FT_TABLES 1
+#define FT_TABLES_LBL 2
+#define FT_CELLS 3
+#define FT_CELLS_LBL 4
+#define FT_PAGES 5
+#define FT_PAGES_LBL 6
+
+#define FL_INFO 1
diff --git a/sc/source/ui/docshell/tpstat.src b/sc/source/ui/docshell/tpstat.src
new file mode 100644
index 000000000000..7226da4642c3
--- /dev/null
+++ b/sc/source/ui/docshell/tpstat.src
@@ -0,0 +1,112 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#include "tpstat.hrc"
+TabPage RID_SCPAGE_STAT
+{
+ // HelpID = HID_DOC_STAT;
+ Hide = TRUE ;
+ Size = MAP_APPFONT ( 260 , 185 ) ;
+ FixedText FT_TABLES_LBL
+ {
+ Pos = MAP_APPFONT ( 12 , 17 ) ;
+ Size = MAP_APPFONT ( 90 , 8 ) ;
+ Text [ en-US ] = "Number of sheets:" ;
+ Left = TRUE ;
+ };
+ FixedText FT_TABLES
+ {
+ Pos = MAP_APPFONT ( 108 , 17 ) ;
+ Size = MAP_APPFONT ( 27 , 8 ) ;
+ Left = TRUE ;
+ };
+ FixedText FT_CELLS_LBL
+ {
+ Pos = MAP_APPFONT ( 12 , 29 ) ;
+ Size = MAP_APPFONT ( 90 , 8 ) ;
+ Text [ en-US ] = "Number of cells:" ;
+ Left = TRUE ;
+ };
+ FixedText FT_CELLS
+ {
+ Pos = MAP_APPFONT ( 108 , 29 ) ;
+ Size = MAP_APPFONT ( 27 , 8 ) ;
+ Left = TRUE ;
+ };
+ FixedText FT_PAGES_LBL
+ {
+ Pos = MAP_APPFONT ( 12 , 41 ) ;
+ Size = MAP_APPFONT ( 90 , 8 ) ;
+ Text [ en-US ] = "Number of pages:" ;
+ Left = TRUE ;
+ };
+ FixedText FT_PAGES
+ {
+ Pos = MAP_APPFONT ( 108 , 41 ) ;
+ Size = MAP_APPFONT ( 27 , 8 ) ;
+ Left = TRUE ;
+ };
+ FixedLine FL_INFO
+ {
+ Pos = MAP_APPFONT ( 6 , 3 ) ;
+ Size = MAP_APPFONT ( 248 , 8 ) ;
+ Text [ en-US ] = "Document: " ;
+ };
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+