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