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