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