diff options
Diffstat (limited to 'sc/source/core/tool/ddelink.cxx')
-rw-r--r-- | sc/source/core/tool/ddelink.cxx | 279 |
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; + } +} + + |