xref: /trunk/main/sc/source/core/tool/ddelink.cxx (revision cf6516809c57e1bb0a940545cca99cdad54d4ce2)
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*80e8b488SArrigo Marchiori #include <com/sun/star/document/XLinkAuthorizer.hpp>
31cdf0e10cSrcweir #include <tools/list.hxx>
32cdf0e10cSrcweir #include <sfx2/linkmgr.hxx>
33cdf0e10cSrcweir #include <sfx2/bindings.hxx>
34*80e8b488SArrigo 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*80e8b488SArrigo Marchiori     ::com::sun::star::uno::Reference< ::com::sun::star::document::XLinkAuthorizer > xLinkAuthorizer( pDoc->GetDocumentShell()->GetModel(), ::com::sun::star::uno::UNO_QUERY );
264*80e8b488SArrigo Marchiori     if ( xLinkAuthorizer.is() ) {
265*80e8b488SArrigo Marchiori         if ( !xLinkAuthorizer->authorizeLinks( aTopic ) ) {
266*80e8b488SArrigo Marchiori             return;
267*80e8b488SArrigo Marchiori         }
268*80e8b488SArrigo 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 }
282