xref: /aoo42x/main/sc/source/core/tool/ddelink.cxx (revision b3f79822)
1*b3f79822SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*b3f79822SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*b3f79822SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*b3f79822SAndrew Rist  * distributed with this work for additional information
6*b3f79822SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*b3f79822SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*b3f79822SAndrew Rist  * "License"); you may not use this file except in compliance
9*b3f79822SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*b3f79822SAndrew Rist  *
11*b3f79822SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*b3f79822SAndrew Rist  *
13*b3f79822SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*b3f79822SAndrew Rist  * software distributed under the License is distributed on an
15*b3f79822SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b3f79822SAndrew Rist  * KIND, either express or implied.  See the License for the
17*b3f79822SAndrew Rist  * specific language governing permissions and limitations
18*b3f79822SAndrew Rist  * under the License.
19*b3f79822SAndrew Rist  *
20*b3f79822SAndrew Rist  *************************************************************/
21*b3f79822SAndrew Rist 
22*b3f79822SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sc.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir 
28cdf0e10cSrcweir 
29cdf0e10cSrcweir // INCLUDE ---------------------------------------------------------------
30cdf0e10cSrcweir #include <tools/list.hxx>
31cdf0e10cSrcweir #include <sfx2/linkmgr.hxx>
32cdf0e10cSrcweir #include <sfx2/bindings.hxx>
33cdf0e10cSrcweir #include <svl/zforlist.hxx>
34cdf0e10cSrcweir 
35cdf0e10cSrcweir #include "ddelink.hxx"
36cdf0e10cSrcweir #include "brdcst.hxx"
37cdf0e10cSrcweir #include "document.hxx"
38cdf0e10cSrcweir #include "scmatrix.hxx"
39cdf0e10cSrcweir #include "patattr.hxx"
40cdf0e10cSrcweir #include "rechead.hxx"
41cdf0e10cSrcweir #include "rangeseq.hxx"
42cdf0e10cSrcweir #include "sc.hrc"
43cdf0e10cSrcweir #include "hints.hxx"
44cdf0e10cSrcweir 
45cdf0e10cSrcweir TYPEINIT2(ScDdeLink,::sfx2::SvBaseLink,SfxBroadcaster);
46cdf0e10cSrcweir 
47cdf0e10cSrcweir #define DDE_TXT_ENCODING 	gsl_getSystemTextEncoding()
48cdf0e10cSrcweir 
49cdf0e10cSrcweir sal_Bool ScDdeLink::bIsInUpdate = sal_False;
50cdf0e10cSrcweir 
51cdf0e10cSrcweir //------------------------------------------------------------------------
52cdf0e10cSrcweir 
ScDdeLink(ScDocument * pD,const String & rA,const String & rT,const String & rI,sal_uInt8 nM)53cdf0e10cSrcweir ScDdeLink::ScDdeLink( ScDocument* pD, const String& rA, const String& rT, const String& rI,
54cdf0e10cSrcweir 						sal_uInt8 nM ) :
55cdf0e10cSrcweir     ::sfx2::SvBaseLink(sfx2::LINKUPDATE_ALWAYS,FORMAT_STRING),
56cdf0e10cSrcweir 	pDoc( pD ),
57cdf0e10cSrcweir 	aAppl( rA ),
58cdf0e10cSrcweir 	aTopic( rT ),
59cdf0e10cSrcweir 	aItem( rI ),
60cdf0e10cSrcweir 	nMode( nM ),
61cdf0e10cSrcweir 	bNeedUpdate( sal_False ),
62cdf0e10cSrcweir 	pResult( NULL )
63cdf0e10cSrcweir {
64cdf0e10cSrcweir }
65cdf0e10cSrcweir 
~ScDdeLink()66cdf0e10cSrcweir __EXPORT ScDdeLink::~ScDdeLink()
67cdf0e10cSrcweir {
68cdf0e10cSrcweir 	// Verbindung aufheben
69cdf0e10cSrcweir 
70cdf0e10cSrcweir     // pResult is refcounted
71cdf0e10cSrcweir }
72cdf0e10cSrcweir 
ScDdeLink(ScDocument * pD,const ScDdeLink & rOther)73cdf0e10cSrcweir ScDdeLink::ScDdeLink( ScDocument* pD, const ScDdeLink& rOther ) :
74cdf0e10cSrcweir     ::sfx2::SvBaseLink(sfx2::LINKUPDATE_ALWAYS,FORMAT_STRING),
75cdf0e10cSrcweir 	pDoc	( pD ),
76cdf0e10cSrcweir 	aAppl	( rOther.aAppl ),
77cdf0e10cSrcweir 	aTopic	( rOther.aTopic ),
78cdf0e10cSrcweir 	aItem	( rOther.aItem ),
79cdf0e10cSrcweir 	nMode	( rOther.nMode ),
80cdf0e10cSrcweir 	bNeedUpdate( sal_False ),
81cdf0e10cSrcweir 	pResult	( NULL )
82cdf0e10cSrcweir {
83cdf0e10cSrcweir 	if (rOther.pResult)
84cdf0e10cSrcweir 		pResult = rOther.pResult->Clone();
85cdf0e10cSrcweir }
86cdf0e10cSrcweir 
ScDdeLink(ScDocument * pD,SvStream & rStream,ScMultipleReadHeader & rHdr)87cdf0e10cSrcweir ScDdeLink::ScDdeLink( ScDocument* pD, SvStream& rStream, ScMultipleReadHeader& rHdr ) :
88cdf0e10cSrcweir     ::sfx2::SvBaseLink(sfx2::LINKUPDATE_ALWAYS,FORMAT_STRING),
89cdf0e10cSrcweir 	pDoc( pD ),
90cdf0e10cSrcweir 	bNeedUpdate( sal_False ),
91cdf0e10cSrcweir 	pResult( NULL )
92cdf0e10cSrcweir {
93cdf0e10cSrcweir 	rHdr.StartEntry();
94cdf0e10cSrcweir 
95cdf0e10cSrcweir 	rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
96cdf0e10cSrcweir 	rStream.ReadByteString( aAppl, eCharSet );
97cdf0e10cSrcweir 	rStream.ReadByteString( aTopic, eCharSet );
98cdf0e10cSrcweir 	rStream.ReadByteString( aItem, eCharSet );
99cdf0e10cSrcweir 
100cdf0e10cSrcweir 	sal_Bool bHasValue;
101cdf0e10cSrcweir 	rStream >> bHasValue;
102cdf0e10cSrcweir 	if ( bHasValue )
103cdf0e10cSrcweir 		pResult = new ScMatrix( rStream );
104cdf0e10cSrcweir 
105cdf0e10cSrcweir 	if (rHdr.BytesLeft())		// neu in 388b und der 364w (RealTime-Client) Version
106cdf0e10cSrcweir 		rStream >> nMode;
107cdf0e10cSrcweir 	else
108cdf0e10cSrcweir 		nMode = SC_DDE_DEFAULT;
109cdf0e10cSrcweir 
110cdf0e10cSrcweir 	rHdr.EndEntry();
111cdf0e10cSrcweir }
112cdf0e10cSrcweir 
Store(SvStream & rStream,ScMultipleWriteHeader & rHdr) const113cdf0e10cSrcweir void ScDdeLink::Store( SvStream& rStream, ScMultipleWriteHeader& rHdr ) const
114cdf0e10cSrcweir {
115cdf0e10cSrcweir 	rHdr.StartEntry();
116cdf0e10cSrcweir 
117cdf0e10cSrcweir 	rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
118cdf0e10cSrcweir 	rStream.WriteByteString( aAppl, eCharSet );
119cdf0e10cSrcweir 	rStream.WriteByteString( aTopic, eCharSet );
120cdf0e10cSrcweir 	rStream.WriteByteString( aItem, eCharSet );
121cdf0e10cSrcweir 
122cdf0e10cSrcweir 	sal_Bool bHasValue = ( pResult != NULL );
123cdf0e10cSrcweir 	rStream << bHasValue;
124cdf0e10cSrcweir 	if (bHasValue)
125cdf0e10cSrcweir 		pResult->Store( rStream );
126cdf0e10cSrcweir 
127cdf0e10cSrcweir 	if( rStream.GetVersion() > SOFFICE_FILEFORMAT_40 )		// nicht bei 4.0 Export
128cdf0e10cSrcweir 		rStream << nMode;									// seit 388b
129cdf0e10cSrcweir 
130cdf0e10cSrcweir 	//	Links mit Mode != SC_DDE_DEFAULT werden bei 4.0 Export komplett weggelassen
131cdf0e10cSrcweir 	//	(aus ScDocument::SaveDdeLinks)
132cdf0e10cSrcweir 
133cdf0e10cSrcweir 	rHdr.EndEntry();
134cdf0e10cSrcweir }
135cdf0e10cSrcweir 
DataChanged(const String & rMimeType,const::com::sun::star::uno::Any & rValue)136cdf0e10cSrcweir void __EXPORT ScDdeLink::DataChanged( const String& rMimeType,
137cdf0e10cSrcweir 								const ::com::sun::star::uno::Any & rValue )
138cdf0e10cSrcweir {
139cdf0e10cSrcweir 	//	wir koennen nur Strings...
140cdf0e10cSrcweir 	if ( FORMAT_STRING != SotExchange::GetFormatIdFromMimeType( rMimeType ))
141cdf0e10cSrcweir 		return;
142cdf0e10cSrcweir 
143cdf0e10cSrcweir 	String aLinkStr;
144cdf0e10cSrcweir 	ScByteSequenceToString::GetString( aLinkStr, rValue, DDE_TXT_ENCODING );
145cdf0e10cSrcweir 	aLinkStr.ConvertLineEnd(LINEEND_LF);
146cdf0e10cSrcweir 
147cdf0e10cSrcweir 	//	wenn String mit Zeilenende aufhoert, streichen:
148cdf0e10cSrcweir 
149cdf0e10cSrcweir 	xub_StrLen nLen = aLinkStr.Len();
150cdf0e10cSrcweir 	if (nLen && aLinkStr.GetChar(nLen-1) == '\n')
151cdf0e10cSrcweir 		aLinkStr.Erase(nLen-1);
152cdf0e10cSrcweir 
153cdf0e10cSrcweir 	String aLine;
154cdf0e10cSrcweir 	SCSIZE nCols = 1;		// Leerstring -> eine leere Zelle
155cdf0e10cSrcweir 	SCSIZE nRows = 1;
156cdf0e10cSrcweir 	if (aLinkStr.Len())
157cdf0e10cSrcweir 	{
158cdf0e10cSrcweir 		nRows = static_cast<SCSIZE>(aLinkStr.GetTokenCount( '\n' ));
159cdf0e10cSrcweir 		aLine = aLinkStr.GetToken( 0, '\n' );
160cdf0e10cSrcweir 		if (aLine.Len())
161cdf0e10cSrcweir 			nCols = static_cast<SCSIZE>(aLine.GetTokenCount( '\t' ));
162cdf0e10cSrcweir 	}
163cdf0e10cSrcweir 
164cdf0e10cSrcweir 	if (!nRows || !nCols)				// keine Daten
165cdf0e10cSrcweir 	{
166cdf0e10cSrcweir         pResult.Clear();
167cdf0e10cSrcweir 	}
168cdf0e10cSrcweir 	else								// Daten aufteilen
169cdf0e10cSrcweir 	{
170cdf0e10cSrcweir 		//	Matrix immer neu anlegen, damit bIsString nicht durcheinanderkommt
171cdf0e10cSrcweir 		pResult = new ScMatrix( nCols, nRows );
172cdf0e10cSrcweir 
173cdf0e10cSrcweir 		SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
174cdf0e10cSrcweir 
175cdf0e10cSrcweir 		//	nMode bestimmt, wie der Text interpretiert wird (#44455#/#49783#):
176cdf0e10cSrcweir 		//	SC_DDE_DEFAULT - Zahlformat aus Zellvorlage "Standard"
177cdf0e10cSrcweir 		//	SC_DDE_ENGLISH - Standard-Zahlformat fuer English/US
178cdf0e10cSrcweir 		//	SC_DDE_TEXT    - ohne NumberFormatter direkt als String
179cdf0e10cSrcweir 		sal_uLong nStdFormat = 0;
180cdf0e10cSrcweir 		if ( nMode == SC_DDE_DEFAULT )
181cdf0e10cSrcweir 		{
182cdf0e10cSrcweir 			ScPatternAttr* pDefPattern = pDoc->GetDefPattern();		// enthaelt Standard-Vorlage
183cdf0e10cSrcweir 			if ( pDefPattern )
184cdf0e10cSrcweir 				nStdFormat = pDefPattern->GetNumberFormat( pFormatter );
185cdf0e10cSrcweir 		}
186cdf0e10cSrcweir 		else if ( nMode == SC_DDE_ENGLISH )
187cdf0e10cSrcweir 			nStdFormat = pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US);
188cdf0e10cSrcweir 
189cdf0e10cSrcweir 		String aEntry;
190cdf0e10cSrcweir 		for (SCSIZE nR=0; nR<nRows; nR++)
191cdf0e10cSrcweir 		{
192cdf0e10cSrcweir 			aLine = aLinkStr.GetToken( (xub_StrLen) nR, '\n' );
193cdf0e10cSrcweir 			for (SCSIZE nC=0; nC<nCols; nC++)
194cdf0e10cSrcweir 			{
195cdf0e10cSrcweir 				aEntry = aLine.GetToken( (xub_StrLen) nC, '\t' );
196cdf0e10cSrcweir 				sal_uInt32 nIndex = nStdFormat;
197cdf0e10cSrcweir 				double fVal;
198cdf0e10cSrcweir 				if ( nMode != SC_DDE_TEXT && pFormatter->IsNumberFormat( aEntry, nIndex, fVal ) )
199cdf0e10cSrcweir 					pResult->PutDouble( fVal, nC, nR );
200cdf0e10cSrcweir 				else
201cdf0e10cSrcweir 					pResult->PutString( aEntry, nC, nR );
202cdf0e10cSrcweir 			}
203cdf0e10cSrcweir 		}
204cdf0e10cSrcweir 	}
205cdf0e10cSrcweir 
206cdf0e10cSrcweir 	//	Es hat sich was getan...
207cdf0e10cSrcweir 
208cdf0e10cSrcweir 	if (HasListeners())
209cdf0e10cSrcweir 	{
210cdf0e10cSrcweir 		Broadcast( ScHint( SC_HINT_DATACHANGED, ScAddress(), NULL ) );
211cdf0e10cSrcweir 		pDoc->TrackFormulas();		// muss sofort passieren
212cdf0e10cSrcweir 		pDoc->StartTrackTimer();
213cdf0e10cSrcweir 
214cdf0e10cSrcweir 		//	StartTrackTimer ruft asynchron TrackFormulas, Broadcast(FID_DATACHANGED),
215cdf0e10cSrcweir 		//	ResetChanged, SetModified und Invalidate(SID_SAVEDOC/SID_DOC_MODIFIED)
216cdf0e10cSrcweir 		//	TrackFormulas zusaetzlich nochmal sofort, damit nicht z.B. durch IdleCalc
217cdf0e10cSrcweir 		//	eine Formel berechnet wird, die noch im FormulaTrack steht (#61676#)
218cdf0e10cSrcweir 
219cdf0e10cSrcweir 		//	notify Uno objects (for XRefreshListener)
220cdf0e10cSrcweir 		//	must be after TrackFormulas
221cdf0e10cSrcweir 		//!	do this asynchronously?
222cdf0e10cSrcweir 		ScLinkRefreshedHint aHint;
223cdf0e10cSrcweir 		aHint.SetDdeLink( aAppl, aTopic, aItem, nMode );
224cdf0e10cSrcweir 		pDoc->BroadcastUno( aHint );
225cdf0e10cSrcweir 	}
226cdf0e10cSrcweir }
227cdf0e10cSrcweir 
ResetValue()228cdf0e10cSrcweir void ScDdeLink::ResetValue()
229cdf0e10cSrcweir {
230cdf0e10cSrcweir     pResult.Clear();
231cdf0e10cSrcweir 
232cdf0e10cSrcweir 	//	Es hat sich was getan...
233cdf0e10cSrcweir 	//	Tracking, FID_DATACHANGED etc. passiert von aussen
234cdf0e10cSrcweir 
235cdf0e10cSrcweir 	if (HasListeners())
236cdf0e10cSrcweir 		Broadcast( ScHint( SC_HINT_DATACHANGED, ScAddress(), NULL ) );
237cdf0e10cSrcweir }
238cdf0e10cSrcweir 
ListenersGone()239cdf0e10cSrcweir void __EXPORT ScDdeLink::ListenersGone()
240cdf0e10cSrcweir {
241cdf0e10cSrcweir 	sal_Bool bWas = bIsInUpdate;
242cdf0e10cSrcweir 	bIsInUpdate = sal_True;				// Remove() kann Reschedule ausloesen??!?
243cdf0e10cSrcweir 
244cdf0e10cSrcweir 	ScDocument* pStackDoc = pDoc;	// member pDoc can't be used after removing the link
245cdf0e10cSrcweir 
246cdf0e10cSrcweir 	sfx2::LinkManager* pLinkMgr = pDoc->GetLinkManager();
247cdf0e10cSrcweir 	pLinkMgr->Remove( this);		// deletes this
248cdf0e10cSrcweir 
249cdf0e10cSrcweir 	if ( !pLinkMgr->GetLinks().Count() )			// letzten geloescht ?
250cdf0e10cSrcweir 	{
251cdf0e10cSrcweir 		SfxBindings* pBindings = pStackDoc->GetViewBindings();		// don't use member pDoc!
252cdf0e10cSrcweir 		if (pBindings)
253cdf0e10cSrcweir 			pBindings->Invalidate( SID_LINKS );
254cdf0e10cSrcweir 	}
255cdf0e10cSrcweir 
256cdf0e10cSrcweir 	bIsInUpdate = bWas;
257cdf0e10cSrcweir }
258cdf0e10cSrcweir 
TryUpdate()259cdf0e10cSrcweir void ScDdeLink::TryUpdate()
260cdf0e10cSrcweir {
261cdf0e10cSrcweir 	if (bIsInUpdate)
262cdf0e10cSrcweir 		bNeedUpdate = sal_True;			// kann jetzt nicht ausgefuehrt werden
263cdf0e10cSrcweir 	else
264cdf0e10cSrcweir 	{
265cdf0e10cSrcweir 		bIsInUpdate = sal_True;
266cdf0e10cSrcweir 		//Application::Reschedule();	//! OS/2-Simulation
267cdf0e10cSrcweir         pDoc->IncInDdeLinkUpdate();
268cdf0e10cSrcweir 		Update();
269cdf0e10cSrcweir         pDoc->DecInDdeLinkUpdate();
270cdf0e10cSrcweir 		bIsInUpdate = sal_False;
271cdf0e10cSrcweir 		bNeedUpdate = sal_False;
272cdf0e10cSrcweir 	}
273cdf0e10cSrcweir }
274cdf0e10cSrcweir 
275cdf0e10cSrcweir 
276