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