1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ddelink.cxx,v $
10 * $Revision: 1.16.32.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 // INCLUDE ---------------------------------------------------------------
37 #include <tools/list.hxx>
38 #include <svx/linkmgr.hxx>
39 #include <sfx2/bindings.hxx>
40 #include <svtools/zforlist.hxx>
42 #include "ddelink.hxx"
44 #include "document.hxx"
45 #include "scmatrix.hxx"
46 #include "patattr.hxx"
47 #include "rechead.hxx"
48 #include "rangeseq.hxx"
52 TYPEINIT2(ScDdeLink
,::sfx2::SvBaseLink
,SfxBroadcaster
);
54 #define DDE_TXT_ENCODING gsl_getSystemTextEncoding()
56 BOOL
ScDdeLink::bIsInUpdate
= FALSE
;
58 //------------------------------------------------------------------------
60 ScDdeLink::ScDdeLink( ScDocument
* pD
, const String
& rA
, const String
& rT
, const String
& rI
,
62 ::sfx2::SvBaseLink(sfx2::LINKUPDATE_ALWAYS
,FORMAT_STRING
),
73 __EXPORT
ScDdeLink::~ScDdeLink()
75 // Verbindung aufheben
77 // pResult is refcounted
80 ScDdeLink::ScDdeLink( ScDocument
* pD
, const ScDdeLink
& rOther
) :
81 ::sfx2::SvBaseLink(sfx2::LINKUPDATE_ALWAYS
,FORMAT_STRING
),
83 aAppl ( rOther
.aAppl
),
84 aTopic ( rOther
.aTopic
),
85 aItem ( rOther
.aItem
),
86 nMode ( rOther
.nMode
),
91 pResult
= rOther
.pResult
->Clone();
94 ScDdeLink::ScDdeLink( ScDocument
* pD
, SvStream
& rStream
, ScMultipleReadHeader
& rHdr
) :
95 ::sfx2::SvBaseLink(sfx2::LINKUPDATE_ALWAYS
,FORMAT_STRING
),
102 rtl_TextEncoding eCharSet
= rStream
.GetStreamCharSet();
103 rStream
.ReadByteString( aAppl
, eCharSet
);
104 rStream
.ReadByteString( aTopic
, eCharSet
);
105 rStream
.ReadByteString( aItem
, eCharSet
);
108 rStream
>> bHasValue
;
110 pResult
= new ScMatrix( rStream
);
112 if (rHdr
.BytesLeft()) // neu in 388b und der 364w (RealTime-Client) Version
115 nMode
= SC_DDE_DEFAULT
;
120 void ScDdeLink::Store( SvStream
& rStream
, ScMultipleWriteHeader
& rHdr
) const
124 rtl_TextEncoding eCharSet
= rStream
.GetStreamCharSet();
125 rStream
.WriteByteString( aAppl
, eCharSet
);
126 rStream
.WriteByteString( aTopic
, eCharSet
);
127 rStream
.WriteByteString( aItem
, eCharSet
);
129 BOOL bHasValue
= ( pResult
!= NULL
);
130 rStream
<< bHasValue
;
132 pResult
->Store( rStream
);
134 if( rStream
.GetVersion() > SOFFICE_FILEFORMAT_40
) // nicht bei 4.0 Export
135 rStream
<< nMode
; // seit 388b
137 // Links mit Mode != SC_DDE_DEFAULT werden bei 4.0 Export komplett weggelassen
138 // (aus ScDocument::SaveDdeLinks)
143 void __EXPORT
ScDdeLink::DataChanged( const String
& rMimeType
,
144 const ::com::sun::star::uno::Any
& rValue
)
146 // wir koennen nur Strings...
147 if ( FORMAT_STRING
!= SotExchange::GetFormatIdFromMimeType( rMimeType
))
151 ScByteSequenceToString::GetString( aLinkStr
, rValue
, DDE_TXT_ENCODING
);
152 aLinkStr
.ConvertLineEnd(LINEEND_LF
);
154 // wenn String mit Zeilenende aufhoert, streichen:
156 xub_StrLen nLen
= aLinkStr
.Len();
157 if (nLen
&& aLinkStr
.GetChar(nLen
-1) == '\n')
158 aLinkStr
.Erase(nLen
-1);
161 SCSIZE nCols
= 1; // Leerstring -> eine leere Zelle
165 nRows
= static_cast<SCSIZE
>(aLinkStr
.GetTokenCount( '\n' ));
166 aLine
= aLinkStr
.GetToken( 0, '\n' );
168 nCols
= static_cast<SCSIZE
>(aLine
.GetTokenCount( '\t' ));
171 if (!nRows
|| !nCols
) // keine Daten
175 else // Daten aufteilen
177 // Matrix immer neu anlegen, damit bIsString nicht durcheinanderkommt
178 pResult
= new ScMatrix( nCols
, nRows
);
180 SvNumberFormatter
* pFormatter
= pDoc
->GetFormatTable();
182 // nMode bestimmt, wie der Text interpretiert wird (#44455#/#49783#):
183 // SC_DDE_DEFAULT - Zahlformat aus Zellvorlage "Standard"
184 // SC_DDE_ENGLISH - Standard-Zahlformat fuer English/US
185 // SC_DDE_TEXT - ohne NumberFormatter direkt als String
186 ULONG nStdFormat
= 0;
187 if ( nMode
== SC_DDE_DEFAULT
)
189 ScPatternAttr
* pDefPattern
= pDoc
->GetDefPattern(); // enthaelt Standard-Vorlage
191 nStdFormat
= pDefPattern
->GetNumberFormat( pFormatter
);
193 else if ( nMode
== SC_DDE_ENGLISH
)
194 nStdFormat
= pFormatter
->GetStandardIndex(LANGUAGE_ENGLISH_US
);
197 for (SCSIZE nR
=0; nR
<nRows
; nR
++)
199 aLine
= aLinkStr
.GetToken( (xub_StrLen
) nR
, '\n' );
200 for (SCSIZE nC
=0; nC
<nCols
; nC
++)
202 aEntry
= aLine
.GetToken( (xub_StrLen
) nC
, '\t' );
203 sal_uInt32 nIndex
= nStdFormat
;
205 if ( nMode
!= SC_DDE_TEXT
&& pFormatter
->IsNumberFormat( aEntry
, nIndex
, fVal
) )
206 pResult
->PutDouble( fVal
, nC
, nR
);
208 pResult
->PutString( aEntry
, nC
, nR
);
213 // Es hat sich was getan...
217 Broadcast( ScHint( SC_HINT_DATACHANGED
, ScAddress(), NULL
) );
218 pDoc
->TrackFormulas(); // muss sofort passieren
219 pDoc
->StartTrackTimer();
221 // StartTrackTimer ruft asynchron TrackFormulas, Broadcast(FID_DATACHANGED),
222 // ResetChanged, SetModified und Invalidate(SID_SAVEDOC/SID_DOC_MODIFIED)
223 // TrackFormulas zusaetzlich nochmal sofort, damit nicht z.B. durch IdleCalc
224 // eine Formel berechnet wird, die noch im FormulaTrack steht (#61676#)
226 // notify Uno objects (for XRefreshListener)
227 // must be after TrackFormulas
228 //! do this asynchronously?
229 ScLinkRefreshedHint aHint
;
230 aHint
.SetDdeLink( aAppl
, aTopic
, aItem
, nMode
);
231 pDoc
->BroadcastUno( aHint
);
235 void ScDdeLink::ResetValue()
239 // Es hat sich was getan...
240 // Tracking, FID_DATACHANGED etc. passiert von aussen
243 Broadcast( ScHint( SC_HINT_DATACHANGED
, ScAddress(), NULL
) );
246 void __EXPORT
ScDdeLink::ListenersGone()
248 BOOL bWas
= bIsInUpdate
;
249 bIsInUpdate
= TRUE
; // Remove() kann Reschedule ausloesen??!?
251 ScDocument
* pStackDoc
= pDoc
; // member pDoc can't be used after removing the link
253 SvxLinkManager
* pLinkMgr
= pDoc
->GetLinkManager();
254 pLinkMgr
->Remove( this); // deletes this
256 if ( !pLinkMgr
->GetLinks().Count() ) // letzten geloescht ?
258 SfxBindings
* pBindings
= pStackDoc
->GetViewBindings(); // don't use member pDoc!
260 pBindings
->Invalidate( SID_LINKS
);
266 void ScDdeLink::TryUpdate()
269 bNeedUpdate
= TRUE
; // kann jetzt nicht ausgefuehrt werden
273 //Application::Reschedule(); //! OS/2-Simulation
274 pDoc
->IncInDdeLinkUpdate();
276 pDoc
->DecInDdeLinkUpdate();