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 // System - Includes ----------------------------------------------------- 31 32 33 34 #include <sot/formats.hxx> 35 #include <sfx2/app.hxx> 36 #include <sfx2/linkmgr.hxx> 37 #include "servobj.hxx" 38 #include "docsh.hxx" 39 #include "impex.hxx" 40 #include "brdcst.hxx" 41 #include "rangenam.hxx" 42 #include "sc.hrc" // SC_HINT_AREAS_CHANGED 43 44 // ----------------------------------------------------------------------- 45 46 sal_Bool lcl_FillRangeFromName( ScRange& rRange, ScDocShell* pDocSh, const String& rName ) 47 { 48 if (pDocSh) 49 { 50 ScDocument* pDoc = pDocSh->GetDocument(); 51 ScRangeName* pNames = pDoc->GetRangeName(); 52 if (pNames) 53 { 54 sal_uInt16 nPos; 55 if( pNames->SearchName( rName, nPos ) ) 56 { 57 ScRangeData* pData = (*pNames)[ nPos ]; 58 if ( pData->IsValidReference( rRange ) ) 59 return sal_True; 60 } 61 } 62 } 63 return sal_False; 64 } 65 66 ScServerObjectSvtListenerForwarder::ScServerObjectSvtListenerForwarder( 67 ScServerObject* pObjP) 68 : pObj(pObjP) 69 { 70 } 71 72 ScServerObjectSvtListenerForwarder::~ScServerObjectSvtListenerForwarder() 73 { 74 //! do NOT access pObj 75 } 76 77 void ScServerObjectSvtListenerForwarder::Notify( SvtBroadcaster& /* rBC */, const SfxHint& rHint) 78 { 79 pObj->Notify( aBroadcaster, rHint); 80 } 81 82 ScServerObject::ScServerObject( ScDocShell* pShell, const String& rItem ) : 83 aForwarder( this ), 84 pDocSh( pShell ), 85 bRefreshListener( sal_False ) 86 { 87 // parse item string 88 89 if ( lcl_FillRangeFromName( aRange, pDocSh, rItem ) ) 90 { 91 aItemStr = rItem; // must be parsed again on ref update 92 } 93 else 94 { 95 // parse ref 96 ScDocument* pDoc = pDocSh->GetDocument(); 97 SCTAB nTab = pDocSh->GetCurTab(); 98 aRange.aStart.SetTab( nTab ); 99 100 if ( aRange.Parse( rItem, pDoc ) & SCA_VALID ) 101 { 102 // area reference 103 } 104 else if ( aRange.aStart.Parse( rItem, pDoc, pDoc->GetAddressConvention() ) & SCA_VALID ) 105 { 106 // cell reference 107 aRange.aEnd = aRange.aStart; 108 } 109 else 110 { 111 DBG_ERROR("ScServerObject: invalid item"); 112 } 113 } 114 115 pDocSh->GetDocument()->GetLinkManager()->InsertServer( this ); 116 pDocSh->GetDocument()->StartListeningArea( aRange, &aForwarder ); 117 118 StartListening(*pDocSh); // um mitzubekommen, wenn die DocShell geloescht wird 119 StartListening(*SFX_APP()); // for SC_HINT_AREAS_CHANGED 120 } 121 122 __EXPORT ScServerObject::~ScServerObject() 123 { 124 Clear(); 125 } 126 127 void ScServerObject::Clear() 128 { 129 if (pDocSh) 130 { 131 ScDocShell* pTemp = pDocSh; 132 pDocSh = NULL; 133 134 pTemp->GetDocument()->EndListeningArea( aRange, &aForwarder ); 135 pTemp->GetDocument()->GetLinkManager()->RemoveServer( this ); 136 EndListening(*pTemp); 137 EndListening(*SFX_APP()); 138 } 139 } 140 141 void ScServerObject::EndListeningAll() 142 { 143 aForwarder.EndListeningAll(); 144 SfxListener::EndListeningAll(); 145 } 146 147 sal_Bool __EXPORT ScServerObject::GetData( 148 ::com::sun::star::uno::Any & rData /*out param*/, 149 const String & rMimeType, sal_Bool /* bSynchron */ ) 150 { 151 if (!pDocSh) 152 return sal_False; 153 154 // named ranges may have changed -> update aRange 155 if ( aItemStr.Len() ) 156 { 157 ScRange aNew; 158 if ( lcl_FillRangeFromName( aNew, pDocSh, aItemStr ) && aNew != aRange ) 159 { 160 aRange = aNew; 161 bRefreshListener = sal_True; 162 } 163 } 164 165 if ( bRefreshListener ) 166 { 167 // refresh the listeners now (this is called from a timer) 168 169 EndListeningAll(); 170 pDocSh->GetDocument()->StartListeningArea( aRange, &aForwarder ); 171 StartListening(*pDocSh); 172 StartListening(*SFX_APP()); 173 bRefreshListener = sal_False; 174 } 175 176 String aDdeTextFmt = pDocSh->GetDdeTextFmt(); 177 ScDocument* pDoc = pDocSh->GetDocument(); 178 179 if( FORMAT_STRING == SotExchange::GetFormatIdFromMimeType( rMimeType )) 180 { 181 ScImportExport aObj( pDoc, aRange ); 182 if( aDdeTextFmt.GetChar(0) == 'F' ) 183 aObj.SetFormulas( sal_True ); 184 if( aDdeTextFmt.EqualsAscii( "SYLK" ) || 185 aDdeTextFmt.EqualsAscii( "FSYLK" ) ) 186 { 187 ByteString aByteData; 188 if( aObj.ExportByteString( aByteData, gsl_getSystemTextEncoding(), SOT_FORMATSTR_ID_SYLK ) ) 189 { 190 rData <<= ::com::sun::star::uno::Sequence< sal_Int8 >( 191 (sal_Int8*)aByteData.GetBuffer(), 192 aByteData.Len() + 1 ); 193 return 1; 194 } 195 return 0; 196 } 197 if( aDdeTextFmt.EqualsAscii( "CSV" ) || 198 aDdeTextFmt.EqualsAscii( "FCSV" ) ) 199 aObj.SetSeparator( ',' ); 200 aObj.SetExportTextOptions( ScExportTextOptions( ScExportTextOptions::ToSpace, ' ', false ) ); 201 return aObj.ExportData( rMimeType, rData ) ? 1 : 0; 202 } 203 204 ScImportExport aObj( pDoc, aRange ); 205 aObj.SetExportTextOptions( ScExportTextOptions( ScExportTextOptions::ToSpace, ' ', false ) ); 206 if( aObj.IsRef() ) 207 return aObj.ExportData( rMimeType, rData ) ? 1 : 0; 208 return 0; 209 } 210 211 void __EXPORT ScServerObject::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) 212 { 213 sal_Bool bDataChanged = sal_False; 214 215 // DocShell can't be tested via type info, because SFX_HINT_DYING comes from the dtor 216 if ( &rBC == pDocSh ) 217 { 218 // from DocShell, only SFX_HINT_DYING is interesting 219 if ( rHint.ISA(SfxSimpleHint) && ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) 220 { 221 pDocSh = NULL; 222 EndListening(*SFX_APP()); 223 // don't access DocShell anymore for EndListening etc. 224 } 225 } 226 else if (rBC.ISA(SfxApplication)) 227 { 228 if ( aItemStr.Len() && rHint.ISA(SfxSimpleHint) && 229 ((const SfxSimpleHint&)rHint).GetId() == SC_HINT_AREAS_CHANGED ) 230 { 231 // check if named range was modified 232 ScRange aNew; 233 if ( lcl_FillRangeFromName( aNew, pDocSh, aItemStr ) && aNew != aRange ) 234 bDataChanged = sal_True; 235 } 236 } 237 else 238 { 239 // must be from Area broadcasters 240 241 const ScHint* pScHint = PTR_CAST( ScHint, &rHint ); 242 if( pScHint && (pScHint->GetId() & (SC_HINT_DATACHANGED | SC_HINT_DYING)) ) 243 bDataChanged = sal_True; 244 else if (rHint.ISA(ScAreaChangedHint)) // position of broadcaster changed 245 { 246 ScRange aNewRange = ((const ScAreaChangedHint&)rHint).GetRange(); 247 if ( aRange != aNewRange ) 248 { 249 bRefreshListener = sal_True; 250 bDataChanged = sal_True; 251 } 252 } 253 else if (rHint.ISA(SfxSimpleHint)) 254 { 255 sal_uLong nId = ((const SfxSimpleHint&)rHint).GetId(); 256 if (nId == SFX_HINT_DYING) 257 { 258 // If the range is being deleted, listening must be restarted 259 // after the deletion is complete (done in GetData) 260 bRefreshListener = sal_True; 261 bDataChanged = sal_True; 262 } 263 } 264 } 265 266 if ( bDataChanged && HasDataLinks() ) 267 SvLinkSource::NotifyDataChanged(); 268 } 269 270 271 272 273 274