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