summaryrefslogtreecommitdiff
path: root/sc/source/core/tool/ddelink.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/core/tool/ddelink.cxx')
-rw-r--r--sc/source/core/tool/ddelink.cxx279
1 files changed, 279 insertions, 0 deletions
diff --git a/sc/source/core/tool/ddelink.cxx b/sc/source/core/tool/ddelink.cxx
new file mode 100644
index 000000000000..977161760eb0
--- /dev/null
+++ b/sc/source/core/tool/ddelink.cxx
@@ -0,0 +1,279 @@
+/*************************************************************************
+ *
+ * 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 <tools/list.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <sfx2/bindings.hxx>
+#include <svl/zforlist.hxx>
+
+#include "ddelink.hxx"
+#include "brdcst.hxx"
+#include "document.hxx"
+#include "scmatrix.hxx"
+#include "patattr.hxx"
+#include "rechead.hxx"
+#include "rangeseq.hxx"
+#include "sc.hrc"
+#include "hints.hxx"
+
+TYPEINIT2(ScDdeLink,::sfx2::SvBaseLink,SfxBroadcaster);
+
+#define DDE_TXT_ENCODING gsl_getSystemTextEncoding()
+
+BOOL ScDdeLink::bIsInUpdate = FALSE;
+
+//------------------------------------------------------------------------
+
+ScDdeLink::ScDdeLink( ScDocument* pD, const String& rA, const String& rT, const String& rI,
+ BYTE nM ) :
+ ::sfx2::SvBaseLink(sfx2::LINKUPDATE_ALWAYS,FORMAT_STRING),
+ pDoc( pD ),
+ aAppl( rA ),
+ aTopic( rT ),
+ aItem( rI ),
+ nMode( nM ),
+ bNeedUpdate( FALSE ),
+ pResult( NULL )
+{
+}
+
+__EXPORT ScDdeLink::~ScDdeLink()
+{
+ // Verbindung aufheben
+
+ // pResult is refcounted
+}
+
+ScDdeLink::ScDdeLink( ScDocument* pD, const ScDdeLink& rOther ) :
+ ::sfx2::SvBaseLink(sfx2::LINKUPDATE_ALWAYS,FORMAT_STRING),
+ pDoc ( pD ),
+ aAppl ( rOther.aAppl ),
+ aTopic ( rOther.aTopic ),
+ aItem ( rOther.aItem ),
+ nMode ( rOther.nMode ),
+ bNeedUpdate( FALSE ),
+ pResult ( NULL )
+{
+ if (rOther.pResult)
+ pResult = rOther.pResult->Clone();
+}
+
+ScDdeLink::ScDdeLink( ScDocument* pD, SvStream& rStream, ScMultipleReadHeader& rHdr ) :
+ ::sfx2::SvBaseLink(sfx2::LINKUPDATE_ALWAYS,FORMAT_STRING),
+ pDoc( pD ),
+ bNeedUpdate( FALSE ),
+ pResult( NULL )
+{
+ rHdr.StartEntry();
+
+ rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
+ rStream.ReadByteString( aAppl, eCharSet );
+ rStream.ReadByteString( aTopic, eCharSet );
+ rStream.ReadByteString( aItem, eCharSet );
+
+ BOOL bHasValue;
+ rStream >> bHasValue;
+ if ( bHasValue )
+ pResult = new ScMatrix( rStream );
+
+ if (rHdr.BytesLeft()) // neu in 388b und der 364w (RealTime-Client) Version
+ rStream >> nMode;
+ else
+ nMode = SC_DDE_DEFAULT;
+
+ rHdr.EndEntry();
+}
+
+void ScDdeLink::Store( SvStream& rStream, ScMultipleWriteHeader& rHdr ) const
+{
+ rHdr.StartEntry();
+
+ rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
+ rStream.WriteByteString( aAppl, eCharSet );
+ rStream.WriteByteString( aTopic, eCharSet );
+ rStream.WriteByteString( aItem, eCharSet );
+
+ BOOL bHasValue = ( pResult != NULL );
+ rStream << bHasValue;
+ if (bHasValue)
+ pResult->Store( rStream );
+
+ if( rStream.GetVersion() > SOFFICE_FILEFORMAT_40 ) // nicht bei 4.0 Export
+ rStream << nMode; // seit 388b
+
+ // Links mit Mode != SC_DDE_DEFAULT werden bei 4.0 Export komplett weggelassen
+ // (aus ScDocument::SaveDdeLinks)
+
+ rHdr.EndEntry();
+}
+
+void __EXPORT ScDdeLink::DataChanged( const String& rMimeType,
+ const ::com::sun::star::uno::Any & rValue )
+{
+ // wir koennen nur Strings...
+ if ( FORMAT_STRING != SotExchange::GetFormatIdFromMimeType( rMimeType ))
+ return;
+
+ String aLinkStr;
+ ScByteSequenceToString::GetString( aLinkStr, rValue, DDE_TXT_ENCODING );
+ aLinkStr.ConvertLineEnd(LINEEND_LF);
+
+ // wenn String mit Zeilenende aufhoert, streichen:
+
+ xub_StrLen nLen = aLinkStr.Len();
+ if (nLen && aLinkStr.GetChar(nLen-1) == '\n')
+ aLinkStr.Erase(nLen-1);
+
+ String aLine;
+ SCSIZE nCols = 1; // Leerstring -> eine leere Zelle
+ SCSIZE nRows = 1;
+ if (aLinkStr.Len())
+ {
+ nRows = static_cast<SCSIZE>(aLinkStr.GetTokenCount( '\n' ));
+ aLine = aLinkStr.GetToken( 0, '\n' );
+ if (aLine.Len())
+ nCols = static_cast<SCSIZE>(aLine.GetTokenCount( '\t' ));
+ }
+
+ if (!nRows || !nCols) // keine Daten
+ {
+ pResult.Clear();
+ }
+ else // Daten aufteilen
+ {
+ // Matrix immer neu anlegen, damit bIsString nicht durcheinanderkommt
+ pResult = new ScMatrix( nCols, nRows );
+
+ SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
+
+ // nMode bestimmt, wie der Text interpretiert wird (#44455#/#49783#):
+ // SC_DDE_DEFAULT - Zahlformat aus Zellvorlage "Standard"
+ // SC_DDE_ENGLISH - Standard-Zahlformat fuer English/US
+ // SC_DDE_TEXT - ohne NumberFormatter direkt als String
+ ULONG nStdFormat = 0;
+ if ( nMode == SC_DDE_DEFAULT )
+ {
+ ScPatternAttr* pDefPattern = pDoc->GetDefPattern(); // enthaelt Standard-Vorlage
+ if ( pDefPattern )
+ nStdFormat = pDefPattern->GetNumberFormat( pFormatter );
+ }
+ else if ( nMode == SC_DDE_ENGLISH )
+ nStdFormat = pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US);
+
+ String aEntry;
+ for (SCSIZE nR=0; nR<nRows; nR++)
+ {
+ aLine = aLinkStr.GetToken( (xub_StrLen) nR, '\n' );
+ for (SCSIZE nC=0; nC<nCols; nC++)
+ {
+ aEntry = aLine.GetToken( (xub_StrLen) nC, '\t' );
+ sal_uInt32 nIndex = nStdFormat;
+ double fVal;
+ if ( nMode != SC_DDE_TEXT && pFormatter->IsNumberFormat( aEntry, nIndex, fVal ) )
+ pResult->PutDouble( fVal, nC, nR );
+ else
+ pResult->PutString( aEntry, nC, nR );
+ }
+ }
+ }
+
+ // Es hat sich was getan...
+
+ if (HasListeners())
+ {
+ Broadcast( ScHint( SC_HINT_DATACHANGED, ScAddress(), NULL ) );
+ pDoc->TrackFormulas(); // muss sofort passieren
+ pDoc->StartTrackTimer();
+
+ // StartTrackTimer ruft asynchron TrackFormulas, Broadcast(FID_DATACHANGED),
+ // ResetChanged, SetModified und Invalidate(SID_SAVEDOC/SID_DOC_MODIFIED)
+ // TrackFormulas zusaetzlich nochmal sofort, damit nicht z.B. durch IdleCalc
+ // eine Formel berechnet wird, die noch im FormulaTrack steht (#61676#)
+
+ // notify Uno objects (for XRefreshListener)
+ // must be after TrackFormulas
+ //! do this asynchronously?
+ ScLinkRefreshedHint aHint;
+ aHint.SetDdeLink( aAppl, aTopic, aItem, nMode );
+ pDoc->BroadcastUno( aHint );
+ }
+}
+
+void ScDdeLink::ResetValue()
+{
+ pResult.Clear();
+
+ // Es hat sich was getan...
+ // Tracking, FID_DATACHANGED etc. passiert von aussen
+
+ if (HasListeners())
+ Broadcast( ScHint( SC_HINT_DATACHANGED, ScAddress(), NULL ) );
+}
+
+void __EXPORT ScDdeLink::ListenersGone()
+{
+ BOOL bWas = bIsInUpdate;
+ bIsInUpdate = TRUE; // Remove() kann Reschedule ausloesen??!?
+
+ ScDocument* pStackDoc = pDoc; // member pDoc can't be used after removing the link
+
+ sfx2::LinkManager* pLinkMgr = pDoc->GetLinkManager();
+ pLinkMgr->Remove( this); // deletes this
+
+ if ( !pLinkMgr->GetLinks().Count() ) // letzten geloescht ?
+ {
+ SfxBindings* pBindings = pStackDoc->GetViewBindings(); // don't use member pDoc!
+ if (pBindings)
+ pBindings->Invalidate( SID_LINKS );
+ }
+
+ bIsInUpdate = bWas;
+}
+
+void ScDdeLink::TryUpdate()
+{
+ if (bIsInUpdate)
+ bNeedUpdate = TRUE; // kann jetzt nicht ausgefuehrt werden
+ else
+ {
+ bIsInUpdate = TRUE;
+ //Application::Reschedule(); //! OS/2-Simulation
+ pDoc->IncInDdeLinkUpdate();
+ Update();
+ pDoc->DecInDdeLinkUpdate();
+ bIsInUpdate = FALSE;
+ bNeedUpdate = FALSE;
+ }
+}
+
+