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