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 <svl/smplhint.hxx> 30 #include <sfx2/linkmgr.hxx> 31 32 #include "linkuno.hxx" 33 #include "miscuno.hxx" 34 #include "convuno.hxx" 35 #include "docsh.hxx" 36 #include "docfunc.hxx" 37 #include "collect.hxx" 38 #include "tablink.hxx" 39 #include "arealink.hxx" 40 #include "unoguard.hxx" 41 #include "hints.hxx" 42 #include "unonames.hxx" 43 #include "rangeseq.hxx" 44 #include "token.hxx" 45 46 #include <vector> 47 #include <climits> 48 49 using namespace com::sun::star; 50 using namespace formula; 51 using ::com::sun::star::uno::Any; 52 using ::com::sun::star::uno::Reference; 53 using ::com::sun::star::uno::Sequence; 54 using ::com::sun::star::uno::UNO_QUERY; 55 using ::com::sun::star::uno::UNO_QUERY_THROW; 56 using ::com::sun::star::lang::IllegalArgumentException; 57 using ::com::sun::star::uno::RuntimeException; 58 using ::rtl::OUString; 59 using ::std::vector; 60 61 //------------------------------------------------------------------------ 62 63 // fuer Sheet- und Area-Links benutzt: 64 const SfxItemPropertyMapEntry* lcl_GetSheetLinkMap() 65 { 66 static SfxItemPropertyMapEntry aSheetLinkMap_Impl[] = 67 { 68 {MAP_CHAR_LEN(SC_UNONAME_FILTER), 0, &getCppuType((rtl::OUString*)0), 0, 0 }, 69 {MAP_CHAR_LEN(SC_UNONAME_FILTOPT), 0, &getCppuType((rtl::OUString*)0), 0, 0 }, 70 {MAP_CHAR_LEN(SC_UNONAME_LINKURL), 0, &getCppuType((rtl::OUString*)0), 0, 0 }, 71 {MAP_CHAR_LEN(SC_UNONAME_REFDELAY), 0, &getCppuType((sal_Int32*)0), 0, 0 }, 72 {MAP_CHAR_LEN(SC_UNONAME_REFPERIOD), 0, &getCppuType((sal_Int32*)0), 0, 0 }, 73 {0,0,0,0,0,0} 74 }; 75 return aSheetLinkMap_Impl; 76 } 77 78 //------------------------------------------------------------------------ 79 80 SV_IMPL_PTRARR( XRefreshListenerArr_Impl, XRefreshListenerPtr ); 81 82 SC_SIMPLE_SERVICE_INFO( ScAreaLinkObj, "ScAreaLinkObj", "com.sun.star.sheet.CellAreaLink" ) 83 SC_SIMPLE_SERVICE_INFO( ScAreaLinksObj, "ScAreaLinksObj", "com.sun.star.sheet.CellAreaLinks" ) 84 SC_SIMPLE_SERVICE_INFO( ScDDELinkObj, "ScDDELinkObj", "com.sun.star.sheet.DDELink" ) 85 SC_SIMPLE_SERVICE_INFO( ScDDELinksObj, "ScDDELinksObj", "com.sun.star.sheet.DDELinks" ) 86 SC_SIMPLE_SERVICE_INFO( ScSheetLinkObj, "ScSheetLinkObj", "com.sun.star.sheet.SheetLink" ) 87 SC_SIMPLE_SERVICE_INFO( ScSheetLinksObj, "ScSheetLinksObj", "com.sun.star.sheet.SheetLinks" ) 88 89 //------------------------------------------------------------------------ 90 91 ScSheetLinkObj::ScSheetLinkObj(ScDocShell* pDocSh, const String& rName) : 92 aPropSet( lcl_GetSheetLinkMap() ), 93 pDocShell( pDocSh ), 94 aFileName( rName ) 95 { 96 pDocShell->GetDocument()->AddUnoObject(*this); 97 } 98 99 ScSheetLinkObj::~ScSheetLinkObj() 100 { 101 if (pDocShell) 102 pDocShell->GetDocument()->RemoveUnoObject(*this); 103 } 104 105 void ScSheetLinkObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) 106 { 107 //! notify if links in document are changed 108 // UpdateRef is not needed here 109 110 if ( rHint.ISA( SfxSimpleHint ) ) 111 { 112 if ( ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) 113 pDocShell = NULL; // pointer is invalid 114 } 115 else if ( rHint.ISA( ScLinkRefreshedHint ) ) 116 { 117 const ScLinkRefreshedHint& rLH = (const ScLinkRefreshedHint&) rHint; 118 if ( rLH.GetLinkType() == SC_LINKREFTYPE_SHEET && rLH.GetUrl() == aFileName ) 119 Refreshed_Impl(); 120 } 121 } 122 123 ScTableLink* ScSheetLinkObj::GetLink_Impl() const 124 { 125 if (pDocShell) 126 { 127 sfx2::LinkManager* pLinkManager = pDocShell->GetDocument()->GetLinkManager(); 128 sal_uInt16 nCount = pLinkManager->GetLinks().Count(); 129 for (sal_uInt16 i=0; i<nCount; i++) 130 { 131 ::sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[i]; 132 if (pBase->ISA(ScTableLink)) 133 { 134 ScTableLink* pTabLink = (ScTableLink*)pBase; 135 if ( pTabLink->GetFileName() == aFileName ) 136 return pTabLink; 137 } 138 } 139 } 140 return NULL; // nicht gefunden 141 } 142 143 // XNamed 144 145 rtl::OUString SAL_CALL ScSheetLinkObj::getName() 146 { 147 ScUnoGuard aGuard; 148 return getFileName(); // Name ist der Dateiname (URL) 149 } 150 151 void SAL_CALL ScSheetLinkObj::setName( const rtl::OUString& aName ) 152 { 153 ScUnoGuard aGuard; 154 setFileName(aName); // Name ist der Dateiname (URL) 155 } 156 157 // XRefreshable 158 159 void SAL_CALL ScSheetLinkObj::refresh() 160 { 161 ScUnoGuard aGuard; 162 ScTableLink* pLink = GetLink_Impl(); 163 if (pLink) 164 pLink->Refresh( pLink->GetFileName(), pLink->GetFilterName(), NULL, pLink->GetRefreshDelay() ); 165 } 166 167 void SAL_CALL ScSheetLinkObj::addRefreshListener( 168 const uno::Reference<util::XRefreshListener >& xListener ) 169 { 170 ScUnoGuard aGuard; 171 uno::Reference<util::XRefreshListener>* pObj = 172 new uno::Reference<util::XRefreshListener>( xListener ); 173 aRefreshListeners.Insert( pObj, aRefreshListeners.Count() ); 174 175 // hold one additional ref to keep this object alive as long as there are listeners 176 if ( aRefreshListeners.Count() == 1 ) 177 acquire(); 178 } 179 180 void SAL_CALL ScSheetLinkObj::removeRefreshListener( 181 const uno::Reference<util::XRefreshListener >& xListener ) 182 { 183 ScUnoGuard aGuard; 184 sal_uInt16 nCount = aRefreshListeners.Count(); 185 for ( sal_uInt16 n=nCount; n--; ) 186 { 187 uno::Reference<util::XRefreshListener>* pObj = aRefreshListeners[n]; 188 if ( *pObj == xListener ) 189 { 190 aRefreshListeners.DeleteAndDestroy( n ); 191 if ( aRefreshListeners.Count() == 0 ) 192 release(); // release ref for listeners 193 break; 194 } 195 } 196 } 197 198 void ScSheetLinkObj::Refreshed_Impl() 199 { 200 lang::EventObject aEvent; 201 aEvent.Source.set((cppu::OWeakObject*)this); 202 for ( sal_uInt16 n=0; n<aRefreshListeners.Count(); n++ ) 203 (*aRefreshListeners[n])->refreshed( aEvent ); 204 } 205 206 void ScSheetLinkObj::ModifyRefreshDelay_Impl( sal_Int32 nRefresh ) 207 { 208 ScTableLink* pLink = GetLink_Impl(); 209 if( pLink ) 210 pLink->SetRefreshDelay( (sal_uLong) nRefresh ); 211 } 212 213 // XPropertySet 214 215 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScSheetLinkObj::getPropertySetInfo() 216 { 217 ScUnoGuard aGuard; 218 static uno::Reference<beans::XPropertySetInfo> aRef( 219 new SfxItemPropertySetInfo( aPropSet.getPropertyMap() )); 220 return aRef; 221 } 222 223 void SAL_CALL ScSheetLinkObj::setPropertyValue( 224 const rtl::OUString& aPropertyName, const uno::Any& aValue ) 225 { 226 ScUnoGuard aGuard; 227 String aNameString(aPropertyName); 228 rtl::OUString aValStr; 229 if ( aNameString.EqualsAscii( SC_UNONAME_LINKURL ) ) 230 { 231 if ( aValue >>= aValStr ) 232 setFileName( aValStr ); 233 } 234 else if ( aNameString.EqualsAscii( SC_UNONAME_FILTER ) ) 235 { 236 if ( aValue >>= aValStr ) 237 setFilter( aValStr ); 238 } 239 else if ( aNameString.EqualsAscii( SC_UNONAME_FILTOPT ) ) 240 { 241 if ( aValue >>= aValStr ) 242 setFilterOptions( aValStr ); 243 } 244 else if ( aNameString.EqualsAscii( SC_UNONAME_REFPERIOD ) ) 245 { 246 sal_Int32 nRefresh = 0; 247 if ( aValue >>= nRefresh ) 248 setRefreshDelay( nRefresh ); 249 } 250 else if ( aNameString.EqualsAscii( SC_UNONAME_REFDELAY ) ) 251 { 252 sal_Int32 nRefresh = 0; 253 if ( aValue >>= nRefresh ) 254 setRefreshDelay( nRefresh ); 255 } 256 } 257 258 uno::Any SAL_CALL ScSheetLinkObj::getPropertyValue( const rtl::OUString& aPropertyName ) 259 { 260 ScUnoGuard aGuard; 261 String aNameString(aPropertyName); 262 uno::Any aRet; 263 if ( aNameString.EqualsAscii( SC_UNONAME_LINKURL ) ) 264 aRet <<= getFileName(); 265 else if ( aNameString.EqualsAscii( SC_UNONAME_FILTER ) ) 266 aRet <<= getFilter(); 267 else if ( aNameString.EqualsAscii( SC_UNONAME_FILTOPT ) ) 268 aRet <<= getFilterOptions(); 269 else if ( aNameString.EqualsAscii( SC_UNONAME_REFPERIOD ) ) 270 aRet <<= getRefreshDelay(); 271 else if ( aNameString.EqualsAscii( SC_UNONAME_REFDELAY ) ) 272 aRet <<= getRefreshDelay(); 273 return aRet; 274 } 275 276 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScSheetLinkObj ) 277 278 // internal: 279 280 rtl::OUString ScSheetLinkObj::getFileName(void) const 281 { 282 ScUnoGuard aGuard; 283 return aFileName; 284 } 285 286 void ScSheetLinkObj::setFileName(const rtl::OUString& rNewName) 287 { 288 ScUnoGuard aGuard; 289 ScTableLink* pLink = GetLink_Impl(); 290 if (pLink) 291 { 292 // pLink->Refresh mit neuem Dateinamen bringt sfx2::LinkManager durcheinander 293 // darum per Hand die Tabellen umsetzen und Link per UpdateLinks neu erzeugen 294 295 String aNewStr(ScGlobal::GetAbsDocName( String(rNewName), pDocShell )); 296 297 // zuerst Tabellen umsetzen 298 299 ScDocument* pDoc = pDocShell->GetDocument(); 300 SCTAB nTabCount = pDoc->GetTableCount(); 301 for (SCTAB nTab=0; nTab<nTabCount; nTab++) 302 if ( pDoc->IsLinked(nTab) && pDoc->GetLinkDoc(nTab) == aFileName ) // alte Datei 303 pDoc->SetLink( nTab, pDoc->GetLinkMode(nTab), aNewStr, 304 pDoc->GetLinkFlt(nTab), pDoc->GetLinkOpt(nTab), 305 pDoc->GetLinkTab(nTab), 306 pDoc->GetLinkRefreshDelay(nTab) ); // nur Datei aendern 307 308 // Links updaten 309 //! Undo !!! 310 311 pLink = NULL; // wird bei UpdateLinks ungueltig 312 pDocShell->UpdateLinks(); // alter Link raus, evtl. neuen Link anlegen 313 314 // Daten kopieren 315 316 aFileName = aNewStr; 317 pLink = GetLink_Impl(); // neuer Link mit neuem Namen 318 if (pLink) 319 pLink->Update(); // inkl. Paint & Undo fuer Daten 320 } 321 } 322 323 rtl::OUString ScSheetLinkObj::getFilter(void) const 324 { 325 ScUnoGuard aGuard; 326 rtl::OUString aRet; 327 ScTableLink* pLink = GetLink_Impl(); 328 if (pLink) 329 aRet = pLink->GetFilterName(); 330 return aRet; 331 } 332 333 void ScSheetLinkObj::setFilter(const rtl::OUString& Filter) 334 { 335 ScUnoGuard aGuard; 336 ScTableLink* pLink = GetLink_Impl(); 337 if (pLink) 338 { 339 String aFilterStr(Filter); 340 pLink->Refresh( aFileName, aFilterStr, NULL, pLink->GetRefreshDelay() ); 341 } 342 } 343 344 rtl::OUString ScSheetLinkObj::getFilterOptions(void) const 345 { 346 ScUnoGuard aGuard; 347 rtl::OUString aRet; 348 ScTableLink* pLink = GetLink_Impl(); 349 if (pLink) 350 aRet = pLink->GetOptions(); 351 return aRet; 352 } 353 354 void ScSheetLinkObj::setFilterOptions(const rtl::OUString& FilterOptions) 355 { 356 ScUnoGuard aGuard; 357 ScTableLink* pLink = GetLink_Impl(); 358 if (pLink) 359 { 360 String aOptStr(FilterOptions); 361 pLink->Refresh( aFileName, pLink->GetFilterName(), &aOptStr, pLink->GetRefreshDelay() ); 362 } 363 } 364 365 sal_Int32 ScSheetLinkObj::getRefreshDelay(void) const 366 { 367 ScUnoGuard aGuard; 368 sal_Int32 nRet = 0; 369 ScTableLink* pLink = GetLink_Impl(); 370 if (pLink) 371 nRet = (sal_Int32) pLink->GetRefreshDelay(); 372 return nRet; 373 } 374 375 void ScSheetLinkObj::setRefreshDelay(sal_Int32 nRefreshDelay) 376 { 377 ScUnoGuard aGuard; 378 ModifyRefreshDelay_Impl( nRefreshDelay ); 379 } 380 381 //------------------------------------------------------------------------ 382 383 ScSheetLinksObj::ScSheetLinksObj(ScDocShell* pDocSh) : 384 pDocShell( pDocSh ) 385 { 386 pDocShell->GetDocument()->AddUnoObject(*this); 387 } 388 389 ScSheetLinksObj::~ScSheetLinksObj() 390 { 391 if (pDocShell) 392 pDocShell->GetDocument()->RemoveUnoObject(*this); 393 } 394 395 void ScSheetLinksObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) 396 { 397 // Referenz-Update interessiert hier nicht 398 399 if ( rHint.ISA( SfxSimpleHint ) && 400 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) 401 { 402 pDocShell = NULL; // ungueltig geworden 403 } 404 } 405 406 // XSheetLinks 407 408 ScSheetLinkObj* ScSheetLinksObj::GetObjectByIndex_Impl(sal_Int32 nIndex) 409 { 410 if (pDocShell) 411 { 412 sal_Int32 nCount = 0; 413 ScStrCollection aNames; // um doppelte wegzulassen 414 ScDocument* pDoc = pDocShell->GetDocument(); 415 SCTAB nTabCount = pDoc->GetTableCount(); 416 for (SCTAB nTab=0; nTab<nTabCount; nTab++) 417 if (pDoc->IsLinked(nTab)) 418 { 419 String aLinkDoc = pDoc->GetLinkDoc( nTab ); 420 StrData* pData = new StrData(aLinkDoc); 421 if (aNames.Insert(pData)) 422 { 423 if ( nCount == nIndex ) 424 return new ScSheetLinkObj( pDocShell, aLinkDoc ); 425 ++nCount; 426 } 427 else 428 delete pData; 429 } 430 } 431 return NULL; // kein Dokument oder Index zu gross 432 } 433 434 ScSheetLinkObj* ScSheetLinksObj::GetObjectByName_Impl(const rtl::OUString& aName) 435 { 436 // Name ist der Dateiname 437 438 if (pDocShell) 439 { 440 String aNameStr(aName); 441 442 ScDocument* pDoc = pDocShell->GetDocument(); 443 SCTAB nTabCount = pDoc->GetTableCount(); 444 for (SCTAB nTab=0; nTab<nTabCount; nTab++) 445 if (pDoc->IsLinked(nTab)) 446 { 447 //! case-insensitive ??? 448 String aLinkDoc = pDoc->GetLinkDoc( nTab ); 449 if ( aLinkDoc == aNameStr ) 450 return new ScSheetLinkObj( pDocShell, aNameStr ); 451 } 452 } 453 454 return NULL; 455 } 456 457 // XEnumerationAccess 458 459 uno::Reference<container::XEnumeration> SAL_CALL ScSheetLinksObj::createEnumeration() 460 { 461 ScUnoGuard aGuard; 462 return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.SheetLinksEnumeration"))); 463 } 464 465 // XIndexAccess 466 467 sal_Int32 SAL_CALL ScSheetLinksObj::getCount() 468 { 469 ScUnoGuard aGuard; 470 sal_Int32 nCount = 0; 471 if (pDocShell) 472 { 473 ScStrCollection aNames; // um doppelte wegzulassen 474 ScDocument* pDoc = pDocShell->GetDocument(); 475 SCTAB nTabCount = pDoc->GetTableCount(); 476 for (SCTAB nTab=0; nTab<nTabCount; nTab++) 477 if (pDoc->IsLinked(nTab)) 478 { 479 String aLinkDoc(pDoc->GetLinkDoc( nTab )); 480 StrData* pData = new StrData(aLinkDoc); 481 if (aNames.Insert(pData)) 482 ++nCount; 483 else 484 delete pData; 485 } 486 } 487 return nCount; 488 } 489 490 uno::Any SAL_CALL ScSheetLinksObj::getByIndex( sal_Int32 nIndex ) 491 { 492 ScUnoGuard aGuard; 493 uno::Reference<beans::XPropertySet> xLink(GetObjectByIndex_Impl(nIndex)); 494 if (xLink.is()) 495 return uno::makeAny(xLink); 496 else 497 throw lang::IndexOutOfBoundsException(); 498 // return uno::Any(); 499 } 500 501 uno::Type SAL_CALL ScSheetLinksObj::getElementType() 502 { 503 ScUnoGuard aGuard; 504 return getCppuType((uno::Reference<beans::XPropertySet>*)0); 505 } 506 507 sal_Bool SAL_CALL ScSheetLinksObj::hasElements() 508 { 509 ScUnoGuard aGuard; 510 return ( getCount() != 0 ); 511 } 512 513 uno::Any SAL_CALL ScSheetLinksObj::getByName( const rtl::OUString& aName ) 514 { 515 ScUnoGuard aGuard; 516 uno::Reference<beans::XPropertySet> xLink(GetObjectByName_Impl(aName)); 517 if (xLink.is()) 518 return uno::makeAny(xLink); 519 else 520 throw container::NoSuchElementException(); 521 // return uno::Any(); 522 } 523 524 sal_Bool SAL_CALL ScSheetLinksObj::hasByName( const rtl::OUString& aName ) 525 { 526 ScUnoGuard aGuard; 527 // Name ist der Dateiname 528 529 if (pDocShell) 530 { 531 String aNameStr(aName); 532 533 ScDocument* pDoc = pDocShell->GetDocument(); 534 SCTAB nTabCount = pDoc->GetTableCount(); 535 for (SCTAB nTab=0; nTab<nTabCount; nTab++) 536 if (pDoc->IsLinked(nTab)) 537 { 538 //! case-insensitive ??? 539 String aLinkDoc(pDoc->GetLinkDoc( nTab )); 540 if ( aLinkDoc == aNameStr ) 541 return sal_True; 542 } 543 } 544 return sal_False; 545 } 546 547 uno::Sequence<rtl::OUString> SAL_CALL ScSheetLinksObj::getElementNames() 548 { 549 ScUnoGuard aGuard; 550 // Name ist der Dateiname 551 552 if (pDocShell) 553 { 554 ScStrCollection aNames; // um doppelte wegzulassen 555 ScDocument* pDoc = pDocShell->GetDocument(); 556 SCTAB nTabCount = pDoc->GetTableCount(); 557 String aName; 558 559 sal_Int32 nLinkCount = getCount(); 560 uno::Sequence<rtl::OUString> aSeq(nLinkCount); 561 rtl::OUString* pAry = aSeq.getArray(); 562 sal_uInt16 nPos = 0; 563 for (SCTAB nTab=0; nTab<nTabCount; nTab++) 564 { 565 if (pDoc->IsLinked(nTab)) 566 { 567 String aLinkDoc(pDoc->GetLinkDoc( nTab )); 568 StrData* pData = new StrData(aLinkDoc); 569 if (aNames.Insert(pData)) 570 pAry[nPos++] = aLinkDoc; 571 else 572 delete pData; 573 } 574 } 575 DBG_ASSERT( nPos==nLinkCount, "verzaehlt" ); 576 return aSeq; 577 } 578 return uno::Sequence<rtl::OUString>(); 579 } 580 581 //------------------------------------------------------------------------ 582 583 ScAreaLink* lcl_GetAreaLink( ScDocShell* pDocShell, sal_uInt16 nPos ) 584 { 585 if (pDocShell) 586 { 587 sfx2::LinkManager* pLinkManager = pDocShell->GetDocument()->GetLinkManager(); 588 sal_uInt16 nTotalCount = pLinkManager->GetLinks().Count(); 589 sal_uInt16 nAreaCount = 0; 590 for (sal_uInt16 i=0; i<nTotalCount; i++) 591 { 592 ::sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[i]; 593 if (pBase->ISA(ScAreaLink)) 594 { 595 if ( nAreaCount == nPos ) 596 return (ScAreaLink*)pBase; 597 ++nAreaCount; 598 } 599 } 600 } 601 return NULL; // nicht gefunden 602 } 603 604 ScAreaLinkObj::ScAreaLinkObj(ScDocShell* pDocSh, sal_uInt16 nP) : 605 aPropSet( lcl_GetSheetLinkMap() ), 606 pDocShell( pDocSh ), 607 nPos( nP ) 608 { 609 pDocShell->GetDocument()->AddUnoObject(*this); 610 } 611 612 ScAreaLinkObj::~ScAreaLinkObj() 613 { 614 if (pDocShell) 615 pDocShell->GetDocument()->RemoveUnoObject(*this); 616 } 617 618 void ScAreaLinkObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) 619 { 620 //! notify if links in document are changed 621 // UpdateRef is not needed here 622 623 if ( rHint.ISA( SfxSimpleHint ) ) 624 { 625 if ( ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) 626 pDocShell = NULL; // pointer is invalid 627 } 628 else if ( rHint.ISA( ScLinkRefreshedHint ) ) 629 { 630 const ScLinkRefreshedHint& rLH = (const ScLinkRefreshedHint&) rHint; 631 if ( rLH.GetLinkType() == SC_LINKREFTYPE_AREA ) 632 { 633 // get this link to compare dest position 634 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); 635 if ( pLink && pLink->GetDestArea().aStart == rLH.GetDestPos() ) 636 Refreshed_Impl(); 637 } 638 } 639 } 640 641 // XFileLink 642 643 void ScAreaLinkObj::Modify_Impl( const rtl::OUString* pNewFile, const rtl::OUString* pNewFilter, 644 const rtl::OUString* pNewOptions, const rtl::OUString* pNewSource, 645 const table::CellRangeAddress* pNewDest ) 646 { 647 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); 648 if (pLink) 649 { 650 String aFile (pLink->GetFile()); 651 String aFilter (pLink->GetFilter()); 652 String aOptions (pLink->GetOptions()); 653 String aSource (pLink->GetSource()); 654 ScRange aDest (pLink->GetDestArea()); 655 sal_uLong nRefresh = pLink->GetRefreshDelay(); 656 657 //! Undo fuer Loeschen 658 //! Undo zusammenfassen 659 660 sfx2::LinkManager* pLinkManager = pDocShell->GetDocument()->GetLinkManager(); 661 pLinkManager->Remove( pLink ); 662 pLink = NULL; // bei Remove geloescht 663 664 sal_Bool bFitBlock = sal_True; // verschieben, wenn durch Update Groesse geaendert 665 if (pNewFile) 666 { 667 aFile = String( *pNewFile ); 668 aFile = ScGlobal::GetAbsDocName( aFile, pDocShell ); //! in InsertAreaLink? 669 } 670 if (pNewFilter) 671 aFilter = String( *pNewFilter ); 672 if (pNewOptions) 673 aOptions = String( *pNewOptions ); 674 if (pNewSource) 675 aSource = String( *pNewSource ); 676 if (pNewDest) 677 { 678 ScUnoConversion::FillScRange( aDest, *pNewDest ); 679 bFitBlock = sal_False; // neuer Bereich angegeben -> keine Inhalte verschieben 680 } 681 682 ScDocFunc aFunc(*pDocShell); 683 aFunc.InsertAreaLink( aFile, aFilter, aOptions, aSource, aDest, nRefresh, bFitBlock, sal_True ); 684 } 685 } 686 687 void ScAreaLinkObj::ModifyRefreshDelay_Impl( sal_Int32 nRefresh ) 688 { 689 ScAreaLink* pLink = lcl_GetAreaLink( pDocShell, nPos ); 690 if( pLink ) 691 pLink->SetRefreshDelay( (sal_uLong) nRefresh ); 692 } 693 694 // XRefreshable 695 696 void SAL_CALL ScAreaLinkObj::refresh() 697 { 698 ScUnoGuard aGuard; 699 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); 700 if (pLink) 701 pLink->Refresh( pLink->GetFile(), pLink->GetFilter(), pLink->GetSource(), pLink->GetRefreshDelay() ); 702 } 703 704 void SAL_CALL ScAreaLinkObj::addRefreshListener( 705 const uno::Reference<util::XRefreshListener >& xListener ) 706 { 707 ScUnoGuard aGuard; 708 uno::Reference<util::XRefreshListener>* pObj = 709 new uno::Reference<util::XRefreshListener>( xListener ); 710 aRefreshListeners.Insert( pObj, aRefreshListeners.Count() ); 711 712 // hold one additional ref to keep this object alive as long as there are listeners 713 if ( aRefreshListeners.Count() == 1 ) 714 acquire(); 715 } 716 717 void SAL_CALL ScAreaLinkObj::removeRefreshListener( 718 const uno::Reference<util::XRefreshListener >& xListener ) 719 { 720 ScUnoGuard aGuard; 721 sal_uInt16 nCount = aRefreshListeners.Count(); 722 for ( sal_uInt16 n=nCount; n--; ) 723 { 724 uno::Reference<util::XRefreshListener>* pObj = aRefreshListeners[n]; 725 if ( *pObj == xListener ) 726 { 727 aRefreshListeners.DeleteAndDestroy( n ); 728 if ( aRefreshListeners.Count() == 0 ) 729 release(); // release ref for listeners 730 break; 731 } 732 } 733 } 734 735 void ScAreaLinkObj::Refreshed_Impl() 736 { 737 lang::EventObject aEvent; 738 aEvent.Source.set((cppu::OWeakObject*)this); 739 for ( sal_uInt16 n=0; n<aRefreshListeners.Count(); n++ ) 740 (*aRefreshListeners[n])->refreshed( aEvent ); 741 } 742 743 // XPropertySet 744 745 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScAreaLinkObj::getPropertySetInfo() 746 { 747 ScUnoGuard aGuard; 748 static uno::Reference<beans::XPropertySetInfo> aRef( 749 new SfxItemPropertySetInfo( aPropSet.getPropertyMap() )); 750 return aRef; 751 } 752 753 void SAL_CALL ScAreaLinkObj::setPropertyValue( 754 const rtl::OUString& aPropertyName, const uno::Any& aValue ) 755 { 756 ScUnoGuard aGuard; 757 String aNameString(aPropertyName); 758 rtl::OUString aValStr; 759 if ( aNameString.EqualsAscii( SC_UNONAME_LINKURL ) ) 760 { 761 if ( aValue >>= aValStr ) 762 setFileName( aValStr ); 763 } 764 else if ( aNameString.EqualsAscii( SC_UNONAME_FILTER ) ) 765 { 766 if ( aValue >>= aValStr ) 767 setFilter( aValStr ); 768 } 769 else if ( aNameString.EqualsAscii( SC_UNONAME_FILTOPT ) ) 770 { 771 if ( aValue >>= aValStr ) 772 setFilterOptions( aValStr ); 773 } 774 else if ( aNameString.EqualsAscii( SC_UNONAME_REFPERIOD ) ) 775 { 776 sal_Int32 nRefresh = 0; 777 if ( aValue >>= nRefresh ) 778 setRefreshDelay( nRefresh ); 779 } 780 else if ( aNameString.EqualsAscii( SC_UNONAME_REFDELAY ) ) 781 { 782 sal_Int32 nRefresh = 0; 783 if ( aValue >>= nRefresh ) 784 setRefreshDelay( nRefresh ); 785 } 786 } 787 788 uno::Any SAL_CALL ScAreaLinkObj::getPropertyValue( const rtl::OUString& aPropertyName ) 789 { 790 ScUnoGuard aGuard; 791 String aNameString(aPropertyName); 792 uno::Any aRet; 793 if ( aNameString.EqualsAscii( SC_UNONAME_LINKURL ) ) 794 aRet <<= getFileName(); 795 else if ( aNameString.EqualsAscii( SC_UNONAME_FILTER ) ) 796 aRet <<= getFilter(); 797 else if ( aNameString.EqualsAscii( SC_UNONAME_FILTOPT ) ) 798 aRet <<= getFilterOptions(); 799 else if ( aNameString.EqualsAscii( SC_UNONAME_REFPERIOD ) ) 800 aRet <<= getRefreshDelay(); 801 else if ( aNameString.EqualsAscii( SC_UNONAME_REFDELAY ) ) 802 aRet <<= getRefreshDelay(); 803 return aRet; 804 } 805 806 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScAreaLinkObj ) 807 808 // internal: 809 810 rtl::OUString ScAreaLinkObj::getFileName(void) const 811 { 812 ScUnoGuard aGuard; 813 rtl::OUString aRet; 814 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); 815 if (pLink) 816 aRet = pLink->GetFile(); 817 return aRet; 818 } 819 820 void ScAreaLinkObj::setFileName(const rtl::OUString& rNewName) 821 { 822 ScUnoGuard aGuard; 823 Modify_Impl( &rNewName, NULL, NULL, NULL, NULL ); 824 } 825 826 rtl::OUString ScAreaLinkObj::getFilter(void) const 827 { 828 ScUnoGuard aGuard; 829 rtl::OUString aRet; 830 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); 831 if (pLink) 832 aRet = pLink->GetFilter(); 833 return aRet; 834 } 835 836 void ScAreaLinkObj::setFilter(const rtl::OUString& Filter) 837 { 838 ScUnoGuard aGuard; 839 Modify_Impl( NULL, &Filter, NULL, NULL, NULL ); 840 } 841 842 rtl::OUString ScAreaLinkObj::getFilterOptions(void) const 843 { 844 ScUnoGuard aGuard; 845 rtl::OUString aRet; 846 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); 847 if (pLink) 848 aRet = pLink->GetOptions(); 849 return aRet; 850 } 851 852 void ScAreaLinkObj::setFilterOptions(const rtl::OUString& FilterOptions) 853 { 854 ScUnoGuard aGuard; 855 Modify_Impl( NULL, NULL, &FilterOptions, NULL, NULL ); 856 } 857 858 sal_Int32 ScAreaLinkObj::getRefreshDelay(void) const 859 { 860 ScUnoGuard aGuard; 861 sal_Int32 nRet = 0; 862 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); 863 if (pLink) 864 nRet = (sal_Int32) pLink->GetRefreshDelay(); 865 return nRet; 866 } 867 868 void ScAreaLinkObj::setRefreshDelay(sal_Int32 nRefreshDelay) 869 { 870 ScUnoGuard aGuard; 871 ModifyRefreshDelay_Impl( nRefreshDelay ); 872 } 873 874 // XAreaLink 875 876 rtl::OUString SAL_CALL ScAreaLinkObj::getSourceArea() 877 { 878 ScUnoGuard aGuard; 879 rtl::OUString aRet; 880 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); 881 if (pLink) 882 aRet = pLink->GetSource(); 883 return aRet; 884 } 885 886 void SAL_CALL ScAreaLinkObj::setSourceArea( const rtl::OUString& aSourceArea ) 887 { 888 ScUnoGuard aGuard; 889 Modify_Impl( NULL, NULL, NULL, &aSourceArea, NULL ); 890 } 891 892 table::CellRangeAddress SAL_CALL ScAreaLinkObj::getDestArea() 893 { 894 ScUnoGuard aGuard; 895 table::CellRangeAddress aRet; 896 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); 897 if (pLink) 898 ScUnoConversion::FillApiRange( aRet, pLink->GetDestArea() ); 899 return aRet; 900 } 901 902 void SAL_CALL ScAreaLinkObj::setDestArea( const table::CellRangeAddress& aDestArea ) 903 { 904 ScUnoGuard aGuard; 905 Modify_Impl( NULL, NULL, NULL, NULL, &aDestArea ); 906 } 907 908 //------------------------------------------------------------------------ 909 910 ScAreaLinksObj::ScAreaLinksObj(ScDocShell* pDocSh) : 911 pDocShell( pDocSh ) 912 { 913 pDocShell->GetDocument()->AddUnoObject(*this); 914 } 915 916 ScAreaLinksObj::~ScAreaLinksObj() 917 { 918 if (pDocShell) 919 pDocShell->GetDocument()->RemoveUnoObject(*this); 920 } 921 922 void ScAreaLinksObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) 923 { 924 // Referenz-Update interessiert hier nicht 925 926 if ( rHint.ISA( SfxSimpleHint ) && 927 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) 928 { 929 pDocShell = NULL; // ungueltig geworden 930 } 931 } 932 933 // XAreaLinks 934 935 ScAreaLinkObj* ScAreaLinksObj::GetObjectByIndex_Impl(sal_Int32 nIndex) 936 { 937 if ( pDocShell && nIndex >= 0 && nIndex < getCount() ) 938 return new ScAreaLinkObj( pDocShell, (sal_uInt16)nIndex ); 939 940 return NULL; // nicht gefunden 941 } 942 943 void SAL_CALL ScAreaLinksObj::insertAtPosition( const table::CellAddress& aDestPos, 944 const rtl::OUString& aFileName, 945 const rtl::OUString& aSourceArea, 946 const rtl::OUString& aFilter, 947 const rtl::OUString& aFilterOptions ) 948 { 949 ScUnoGuard aGuard; 950 if (pDocShell) 951 { 952 String aFileStr (aFileName); 953 String aFilterStr (aFilter); 954 String aOptionStr (aFilterOptions); 955 String aSourceStr (aSourceArea); 956 ScAddress aDestAddr( (SCCOL)aDestPos.Column, (SCROW)aDestPos.Row, aDestPos.Sheet ); 957 958 aFileStr = ScGlobal::GetAbsDocName( aFileStr, pDocShell ); //! in InsertAreaLink ??? 959 960 ScDocFunc aFunc(*pDocShell); 961 aFunc.InsertAreaLink( aFileStr, aFilterStr, aOptionStr, 962 aSourceStr, ScRange(aDestAddr), 963 0, sal_False, sal_True ); // keine Inhalte verschieben 964 } 965 } 966 967 void SAL_CALL ScAreaLinksObj::removeByIndex( sal_Int32 nIndex ) 968 { 969 ScUnoGuard aGuard; 970 ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, (sal_uInt16)nIndex); 971 if (pLink) 972 { 973 //! SetAddUndo oder so 974 975 sfx2::LinkManager* pLinkManager = pDocShell->GetDocument()->GetLinkManager(); 976 pLinkManager->Remove( pLink ); 977 } 978 } 979 980 // XEnumerationAccess 981 982 uno::Reference<container::XEnumeration> SAL_CALL ScAreaLinksObj::createEnumeration() 983 { 984 ScUnoGuard aGuard; 985 return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.CellAreaLinksEnumeration"))); 986 } 987 988 // XIndexAccess 989 990 sal_Int32 SAL_CALL ScAreaLinksObj::getCount() 991 { 992 ScUnoGuard aGuard; 993 sal_Int32 nAreaCount = 0; 994 if (pDocShell) 995 { 996 sfx2::LinkManager* pLinkManager = pDocShell->GetDocument()->GetLinkManager(); 997 sal_uInt16 nTotalCount = pLinkManager->GetLinks().Count(); 998 for (sal_uInt16 i=0; i<nTotalCount; i++) 999 { 1000 ::sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[i]; 1001 if (pBase->ISA(ScAreaLink)) 1002 ++nAreaCount; 1003 } 1004 } 1005 return nAreaCount; 1006 } 1007 1008 uno::Any SAL_CALL ScAreaLinksObj::getByIndex( sal_Int32 nIndex ) 1009 { 1010 ScUnoGuard aGuard; 1011 uno::Reference<sheet::XAreaLink> xLink(GetObjectByIndex_Impl(nIndex)); 1012 if (xLink.is()) 1013 return uno::makeAny(xLink); 1014 else 1015 throw lang::IndexOutOfBoundsException(); 1016 // return uno::Any(); 1017 } 1018 1019 uno::Type SAL_CALL ScAreaLinksObj::getElementType() 1020 { 1021 ScUnoGuard aGuard; 1022 return getCppuType((uno::Reference<sheet::XAreaLink>*)0); 1023 } 1024 1025 sal_Bool SAL_CALL ScAreaLinksObj::hasElements() 1026 { 1027 ScUnoGuard aGuard; 1028 return ( getCount() != 0 ); 1029 } 1030 1031 //------------------------------------------------------------------------ 1032 1033 ScDDELinkObj::ScDDELinkObj(ScDocShell* pDocSh, const String& rA, 1034 const String& rT, const String& rI) : 1035 pDocShell( pDocSh ), 1036 aAppl( rA ), 1037 aTopic( rT ), 1038 aItem( rI ) 1039 { 1040 pDocShell->GetDocument()->AddUnoObject(*this); 1041 } 1042 1043 ScDDELinkObj::~ScDDELinkObj() 1044 { 1045 if (pDocShell) 1046 pDocShell->GetDocument()->RemoveUnoObject(*this); 1047 } 1048 1049 void ScDDELinkObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) 1050 { 1051 //! notify if links in document are changed 1052 // UpdateRef is not needed here 1053 1054 if ( rHint.ISA( SfxSimpleHint ) ) 1055 { 1056 if ( ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) 1057 pDocShell = NULL; // pointer is invalid 1058 } 1059 else if ( rHint.ISA( ScLinkRefreshedHint ) ) 1060 { 1061 const ScLinkRefreshedHint& rLH = (const ScLinkRefreshedHint&) rHint; 1062 if ( rLH.GetLinkType() == SC_LINKREFTYPE_DDE && 1063 rLH.GetDdeAppl() == aAppl && 1064 rLH.GetDdeTopic() == aTopic && 1065 rLH.GetDdeItem() == aItem ) //! mode is ignored 1066 Refreshed_Impl(); 1067 } 1068 } 1069 1070 // XNamed 1071 1072 String lcl_BuildDDEName( const String& rAppl, const String& rTopic, const String& rItem ) 1073 { 1074 // Appl|Topic!Item (wie Excel) 1075 String aRet = rAppl; 1076 aRet += '|'; 1077 aRet += rTopic; 1078 aRet += '!'; 1079 aRet += rItem; 1080 return aRet; 1081 } 1082 1083 rtl::OUString SAL_CALL ScDDELinkObj::getName() 1084 { 1085 ScUnoGuard aGuard; 1086 return lcl_BuildDDEName( aAppl, aTopic, aItem ); 1087 } 1088 1089 void SAL_CALL ScDDELinkObj::setName( const rtl::OUString& /* aName */ ) 1090 { 1091 // name can't be changed (formulas wouldn't find the link) 1092 throw uno::RuntimeException(); 1093 } 1094 1095 // XDDELink 1096 1097 rtl::OUString SAL_CALL ScDDELinkObj::getApplication() 1098 { 1099 ScUnoGuard aGuard; 1100 //! Test, ob Link noch im Dokument enthalten? 1101 1102 return aAppl; 1103 } 1104 1105 rtl::OUString SAL_CALL ScDDELinkObj::getTopic() 1106 { 1107 ScUnoGuard aGuard; 1108 //! Test, ob Link noch im Dokument enthalten? 1109 1110 return aTopic; 1111 } 1112 1113 rtl::OUString SAL_CALL ScDDELinkObj::getItem() 1114 { 1115 ScUnoGuard aGuard; 1116 //! Test, ob Link noch im Dokument enthalten? 1117 1118 return aItem; 1119 } 1120 1121 // XRefreshable 1122 1123 void SAL_CALL ScDDELinkObj::refresh() 1124 { 1125 ScUnoGuard aGuard; 1126 if (pDocShell) 1127 { 1128 ScDocument* pDoc = pDocShell->GetDocument(); 1129 (void)pDoc->UpdateDdeLink( aAppl, aTopic, aItem ); 1130 //! Fehler abfragen 1131 } 1132 } 1133 1134 void SAL_CALL ScDDELinkObj::addRefreshListener( 1135 const uno::Reference<util::XRefreshListener >& xListener ) 1136 { 1137 ScUnoGuard aGuard; 1138 uno::Reference<util::XRefreshListener>* pObj = 1139 new uno::Reference<util::XRefreshListener>( xListener ); 1140 aRefreshListeners.Insert( pObj, aRefreshListeners.Count() ); 1141 1142 // hold one additional ref to keep this object alive as long as there are listeners 1143 if ( aRefreshListeners.Count() == 1 ) 1144 acquire(); 1145 } 1146 1147 void SAL_CALL ScDDELinkObj::removeRefreshListener( 1148 const uno::Reference<util::XRefreshListener >& xListener ) 1149 { 1150 ScUnoGuard aGuard; 1151 sal_uInt16 nCount = aRefreshListeners.Count(); 1152 for ( sal_uInt16 n=nCount; n--; ) 1153 { 1154 uno::Reference<util::XRefreshListener>* pObj = aRefreshListeners[n]; 1155 if ( *pObj == xListener ) 1156 { 1157 aRefreshListeners.DeleteAndDestroy( n ); 1158 if ( aRefreshListeners.Count() == 0 ) 1159 release(); // release ref for listeners 1160 break; 1161 } 1162 } 1163 } 1164 1165 // XDDELinkResults 1166 1167 uno::Sequence< uno::Sequence< uno::Any > > ScDDELinkObj::getResults( ) 1168 { 1169 ScUnoGuard aGuard; 1170 uno::Sequence< uno::Sequence< uno::Any > > aReturn; 1171 bool bSuccess = false; 1172 1173 if ( pDocShell ) 1174 { 1175 ScDocument* pDoc = pDocShell->GetDocument(); 1176 if ( pDoc ) 1177 { 1178 sal_uInt16 nPos = 0; 1179 if ( pDoc->FindDdeLink( aAppl, aTopic, aItem, SC_DDE_IGNOREMODE, nPos ) ) 1180 { 1181 const ScMatrix* pMatrix = pDoc->GetDdeLinkResultMatrix( nPos ); 1182 if ( pMatrix ) 1183 { 1184 uno::Any aAny; 1185 if ( ScRangeToSequence::FillMixedArray( aAny, pMatrix, true ) ) 1186 { 1187 aAny >>= aReturn; 1188 } 1189 } 1190 bSuccess = true; 1191 } 1192 } 1193 } 1194 1195 if ( !bSuccess ) 1196 { 1197 throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 1198 "ScDDELinkObj::getResults: failed to get results!" ) ), 1199 uno::Reference< uno::XInterface >() ); 1200 } 1201 1202 return aReturn; 1203 } 1204 1205 void ScDDELinkObj::setResults( const uno::Sequence< uno::Sequence< uno::Any > >& aResults ) 1206 { 1207 ScUnoGuard aGuard; 1208 bool bSuccess = false; 1209 1210 if ( pDocShell ) 1211 { 1212 ScDocument* pDoc = pDocShell->GetDocument(); 1213 if ( pDoc ) 1214 { 1215 sal_uInt16 nPos = 0; 1216 if ( pDoc->FindDdeLink( aAppl, aTopic, aItem, SC_DDE_IGNOREMODE, nPos ) ) 1217 { 1218 uno::Any aAny; 1219 aAny <<= aResults; 1220 ScMatrixRef xMatrix = ScSequenceToMatrix::CreateMixedMatrix( aAny ); 1221 bSuccess = pDoc->SetDdeLinkResultMatrix( nPos, xMatrix ); 1222 } 1223 } 1224 } 1225 1226 if ( !bSuccess ) 1227 { 1228 throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 1229 "ScDDELinkObj::setResults: failed to set results!" ) ), 1230 uno::Reference< uno::XInterface >() ); 1231 } 1232 } 1233 1234 void ScDDELinkObj::Refreshed_Impl() 1235 { 1236 lang::EventObject aEvent; 1237 aEvent.Source.set((cppu::OWeakObject*)this); 1238 for ( sal_uInt16 n=0; n<aRefreshListeners.Count(); n++ ) 1239 (*aRefreshListeners[n])->refreshed( aEvent ); 1240 } 1241 1242 //------------------------------------------------------------------------ 1243 1244 ScDDELinksObj::ScDDELinksObj(ScDocShell* pDocSh) : 1245 pDocShell( pDocSh ) 1246 { 1247 pDocShell->GetDocument()->AddUnoObject(*this); 1248 } 1249 1250 ScDDELinksObj::~ScDDELinksObj() 1251 { 1252 if (pDocShell) 1253 pDocShell->GetDocument()->RemoveUnoObject(*this); 1254 } 1255 1256 void ScDDELinksObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) 1257 { 1258 // Referenz-Update interessiert hier nicht 1259 1260 if ( rHint.ISA( SfxSimpleHint ) && 1261 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) 1262 { 1263 pDocShell = NULL; // ungueltig geworden 1264 } 1265 } 1266 1267 // XDDELinks 1268 1269 ScDDELinkObj* ScDDELinksObj::GetObjectByIndex_Impl(sal_Int32 nIndex) 1270 { 1271 if (pDocShell) 1272 { 1273 String aAppl, aTopic, aItem; 1274 if ( nIndex <= USHRT_MAX && 1275 pDocShell->GetDocument()->GetDdeLinkData( (sal_uInt16)nIndex, aAppl, aTopic, aItem ) ) 1276 return new ScDDELinkObj( pDocShell, aAppl, aTopic, aItem ); 1277 } 1278 return NULL; 1279 } 1280 1281 ScDDELinkObj* ScDDELinksObj::GetObjectByName_Impl(const rtl::OUString& aName) 1282 { 1283 if (pDocShell) 1284 { 1285 String aNamStr(aName); 1286 String aAppl, aTopic, aItem; 1287 1288 ScDocument* pDoc = pDocShell->GetDocument(); 1289 sal_uInt16 nCount = pDoc->GetDdeLinkCount(); 1290 for (sal_uInt16 i=0; i<nCount; i++) 1291 { 1292 pDoc->GetDdeLinkData( i, aAppl, aTopic, aItem ); 1293 if ( lcl_BuildDDEName(aAppl, aTopic, aItem) == aNamStr ) 1294 return new ScDDELinkObj( pDocShell, aAppl, aTopic, aItem ); 1295 } 1296 } 1297 return NULL; 1298 } 1299 1300 // XEnumerationAccess 1301 1302 uno::Reference<container::XEnumeration> SAL_CALL ScDDELinksObj::createEnumeration() 1303 { 1304 ScUnoGuard aGuard; 1305 return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.DDELinksEnumeration"))); 1306 } 1307 1308 // XIndexAccess 1309 1310 sal_Int32 SAL_CALL ScDDELinksObj::getCount() 1311 { 1312 ScUnoGuard aGuard; 1313 sal_Int32 nAreaCount = 0; 1314 if (pDocShell) 1315 nAreaCount = pDocShell->GetDocument()->GetDdeLinkCount(); 1316 return nAreaCount; 1317 } 1318 1319 uno::Any SAL_CALL ScDDELinksObj::getByIndex( sal_Int32 nIndex ) 1320 { 1321 ScUnoGuard aGuard; 1322 uno::Reference<sheet::XDDELink> xLink(GetObjectByIndex_Impl(nIndex)); 1323 if (xLink.is()) 1324 return uno::makeAny(xLink); 1325 else 1326 throw lang::IndexOutOfBoundsException(); 1327 // return uno::Any(); 1328 } 1329 1330 uno::Type SAL_CALL ScDDELinksObj::getElementType() 1331 { 1332 ScUnoGuard aGuard; 1333 return getCppuType((uno::Reference<sheet::XDDELink>*)0); 1334 } 1335 1336 sal_Bool SAL_CALL ScDDELinksObj::hasElements() 1337 { 1338 ScUnoGuard aGuard; 1339 return ( getCount() != 0 ); 1340 } 1341 1342 uno::Any SAL_CALL ScDDELinksObj::getByName( const rtl::OUString& aName ) 1343 { 1344 ScUnoGuard aGuard; 1345 uno::Reference<sheet::XDDELink> xLink(GetObjectByName_Impl(aName)); 1346 if (xLink.is()) 1347 return uno::makeAny(xLink); 1348 else 1349 throw container::NoSuchElementException(); 1350 // return uno::Any(); 1351 } 1352 1353 uno::Sequence<rtl::OUString> SAL_CALL ScDDELinksObj::getElementNames() 1354 { 1355 ScUnoGuard aGuard; 1356 if (pDocShell) 1357 { 1358 String aAppl, aTopic, aItem; 1359 1360 ScDocument* pDoc = pDocShell->GetDocument(); 1361 sal_uInt16 nCount = pDoc->GetDdeLinkCount(); 1362 uno::Sequence<rtl::OUString> aSeq(nCount); 1363 rtl::OUString* pAry = aSeq.getArray(); 1364 1365 for (sal_uInt16 i=0; i<nCount; i++) 1366 { 1367 pDoc->GetDdeLinkData( i, aAppl, aTopic, aItem ); 1368 pAry[i] = lcl_BuildDDEName(aAppl, aTopic, aItem); 1369 } 1370 return aSeq; 1371 } 1372 return uno::Sequence<rtl::OUString>(); 1373 } 1374 1375 sal_Bool SAL_CALL ScDDELinksObj::hasByName( const rtl::OUString& aName ) 1376 { 1377 ScUnoGuard aGuard; 1378 if (pDocShell) 1379 { 1380 String aNamStr(aName); 1381 String aAppl, aTopic, aItem; 1382 1383 ScDocument* pDoc = pDocShell->GetDocument(); 1384 sal_uInt16 nCount = pDoc->GetDdeLinkCount(); 1385 for (sal_uInt16 i=0; i<nCount; i++) 1386 { 1387 pDoc->GetDdeLinkData( i, aAppl, aTopic, aItem ); 1388 if ( lcl_BuildDDEName(aAppl, aTopic, aItem) == aNamStr ) 1389 return sal_True; 1390 } 1391 } 1392 return sal_False; 1393 } 1394 1395 // XDDELinks 1396 1397 uno::Reference< sheet::XDDELink > ScDDELinksObj::addDDELink( 1398 const ::rtl::OUString& aApplication, const ::rtl::OUString& aTopic, 1399 const ::rtl::OUString& aItem, ::com::sun::star::sheet::DDELinkMode nMode ) 1400 { 1401 ScUnoGuard aGuard; 1402 uno::Reference< sheet::XDDELink > xLink; 1403 1404 if ( pDocShell ) 1405 { 1406 ScDocument* pDoc = pDocShell->GetDocument(); 1407 if ( pDoc ) 1408 { 1409 sal_uInt8 nMod = SC_DDE_DEFAULT; 1410 switch ( nMode ) 1411 { 1412 case sheet::DDELinkMode_DEFAULT: 1413 { 1414 nMod = SC_DDE_DEFAULT; 1415 } 1416 break; 1417 case sheet::DDELinkMode_ENGLISH: 1418 { 1419 nMod = SC_DDE_ENGLISH; 1420 } 1421 break; 1422 case sheet::DDELinkMode_TEXT: 1423 { 1424 nMod = SC_DDE_TEXT; 1425 } 1426 break; 1427 default: 1428 { 1429 } 1430 break; 1431 } 1432 1433 if ( pDoc->CreateDdeLink( aApplication, aTopic, aItem, nMod ) ) 1434 { 1435 const ::rtl::OUString aName( lcl_BuildDDEName( aApplication, aTopic, aItem ) ); 1436 xLink.set( GetObjectByName_Impl( aName ) ); 1437 } 1438 } 1439 } 1440 1441 if ( !xLink.is() ) 1442 { 1443 throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 1444 "ScDDELinksObj::addDDELink: cannot add DDE link!" ) ), 1445 uno::Reference< uno::XInterface >() ); 1446 } 1447 1448 return xLink; 1449 } 1450 1451 // ============================================================================ 1452 1453 ScExternalSheetCacheObj::ScExternalSheetCacheObj(ScExternalRefCache::TableTypeRef pTable, size_t nIndex) : 1454 mpTable(pTable), 1455 mnIndex(nIndex) 1456 { 1457 } 1458 1459 ScExternalSheetCacheObj::~ScExternalSheetCacheObj() 1460 { 1461 } 1462 1463 void SAL_CALL ScExternalSheetCacheObj::setCellValue(sal_Int32 nCol, sal_Int32 nRow, const Any& rValue) 1464 { 1465 ScUnoGuard aGuard; 1466 if (nRow < 0 || nCol < 0) 1467 throw IllegalArgumentException(); 1468 1469 ScExternalRefCache::TokenRef pToken; 1470 double fVal = 0.0; 1471 OUString aVal; 1472 if (rValue >>= fVal) 1473 pToken.reset(new FormulaDoubleToken(fVal)); 1474 else if (rValue >>= aVal) 1475 pToken.reset(new FormulaStringToken(aVal)); 1476 else 1477 // unidentified value type. 1478 return; 1479 1480 mpTable->setCell(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), pToken); 1481 } 1482 1483 Any SAL_CALL ScExternalSheetCacheObj::getCellValue(sal_Int32 nCol, sal_Int32 nRow) 1484 { 1485 ScUnoGuard aGuard; 1486 if (nRow < 0 || nCol < 0) 1487 throw IllegalArgumentException(); 1488 1489 FormulaToken* pToken = mpTable->getCell(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow)).get(); 1490 if (!pToken) 1491 throw IllegalArgumentException(); 1492 1493 Any aValue; 1494 switch (pToken->GetType()) 1495 { 1496 case svDouble: 1497 { 1498 double fVal = pToken->GetDouble(); 1499 aValue <<= fVal; 1500 } 1501 break; 1502 case svString: 1503 { 1504 OUString aVal = pToken->GetString(); 1505 aValue <<= aVal; 1506 } 1507 break; 1508 default: 1509 throw IllegalArgumentException(); 1510 } 1511 return aValue; 1512 } 1513 1514 Sequence< sal_Int32 > SAL_CALL ScExternalSheetCacheObj::getAllRows() 1515 { 1516 ScUnoGuard aGuard; 1517 vector<SCROW> aRows; 1518 mpTable->getAllRows(aRows); 1519 size_t nSize = aRows.size(); 1520 Sequence<sal_Int32> aRowsSeq(nSize); 1521 for (size_t i = 0; i < nSize; ++i) 1522 aRowsSeq[i] = aRows[i]; 1523 1524 return aRowsSeq; 1525 } 1526 1527 Sequence< sal_Int32 > SAL_CALL ScExternalSheetCacheObj::getAllColumns(sal_Int32 nRow) 1528 { 1529 ScUnoGuard aGuard; 1530 if (nRow < 0) 1531 throw IllegalArgumentException(); 1532 1533 vector<SCCOL> aCols; 1534 mpTable->getAllCols(static_cast<SCROW>(nRow), aCols); 1535 size_t nSize = aCols.size(); 1536 Sequence<sal_Int32> aColsSeq(nSize); 1537 for (size_t i = 0; i < nSize; ++i) 1538 aColsSeq[i] = aCols[i]; 1539 1540 return aColsSeq; 1541 } 1542 1543 sal_Int32 SAL_CALL ScExternalSheetCacheObj::getTokenIndex() 1544 { 1545 return static_cast< sal_Int32 >( mnIndex ); 1546 } 1547 1548 // ============================================================================ 1549 1550 ScExternalDocLinkObj::ScExternalDocLinkObj(ScExternalRefManager* pRefMgr, sal_uInt16 nFileId) : 1551 mpRefMgr(pRefMgr), mnFileId(nFileId) 1552 { 1553 } 1554 1555 ScExternalDocLinkObj::~ScExternalDocLinkObj() 1556 { 1557 } 1558 1559 Reference< sheet::XExternalSheetCache > SAL_CALL ScExternalDocLinkObj::addSheetCache( 1560 const OUString& aSheetName, sal_Bool bDynamicCache ) 1561 { 1562 ScUnoGuard aGuard; 1563 size_t nIndex = 0; 1564 ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aSheetName, true, &nIndex); 1565 if (!bDynamicCache) 1566 // Set the whole table cached to prevent access to the source document. 1567 pTable->setWholeTableCached(); 1568 1569 Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(pTable, nIndex)); 1570 return aSheetCache; 1571 } 1572 1573 Any SAL_CALL ScExternalDocLinkObj::getByName(const::rtl::OUString &aName) 1574 { 1575 ScUnoGuard aGuard; 1576 size_t nIndex = 0; 1577 ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aName, false, &nIndex); 1578 if (!pTable) 1579 throw container::NoSuchElementException(); 1580 1581 Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(pTable, nIndex)); 1582 1583 Any aAny; 1584 aAny <<= aSheetCache; 1585 return aAny; 1586 } 1587 1588 Sequence< OUString > SAL_CALL ScExternalDocLinkObj::getElementNames() 1589 { 1590 ScUnoGuard aGuard; 1591 vector<String> aTabNames; 1592 mpRefMgr->getAllCachedTableNames(mnFileId, aTabNames); 1593 1594 // #i116940# be consistent with getByName: include only table names which have a cache already 1595 vector<String> aValidNames; 1596 for (vector<String>::const_iterator aIter = aTabNames.begin(); aIter != aTabNames.end(); ++aIter) 1597 if (mpRefMgr->getCacheTable(mnFileId, *aIter, false)) 1598 aValidNames.push_back(*aIter); 1599 1600 size_t n = aValidNames.size(); 1601 Sequence<OUString> aSeq(n); 1602 for (size_t i = 0; i < n; ++i) 1603 aSeq[i] = aValidNames[i]; 1604 return aSeq; 1605 } 1606 1607 sal_Bool SAL_CALL ScExternalDocLinkObj::hasByName(const OUString &aName) 1608 { 1609 ScUnoGuard aGuard; 1610 1611 // #i116940# be consistent with getByName: allow only table names which have a cache already 1612 ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aName, false); 1613 return (pTable.get() != NULL); 1614 } 1615 1616 sal_Int32 SAL_CALL ScExternalDocLinkObj::getCount() 1617 { 1618 ScUnoGuard aGuard; 1619 1620 // #i116940# be consistent with getByName: count only table names which have a cache already 1621 return getElementNames().getLength(); 1622 } 1623 1624 Any SAL_CALL ScExternalDocLinkObj::getByIndex(sal_Int32 nApiIndex) 1625 { 1626 ScUnoGuard aGuard; 1627 1628 // #i116940# Can't use nApiIndex as index for the ref manager, because the API counts only 1629 // the entries which have a cache already. Quick solution: Use getElementNames. 1630 1631 Sequence< OUString > aNames( getElementNames() ); 1632 if (nApiIndex < 0 || nApiIndex >= aNames.getLength()) 1633 throw lang::IndexOutOfBoundsException(); 1634 1635 size_t nIndex = 0; 1636 ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aNames[nApiIndex], false, &nIndex); 1637 if (!pTable) 1638 throw lang::IndexOutOfBoundsException(); 1639 1640 Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(pTable, nIndex)); 1641 1642 Any aAny; 1643 aAny <<= aSheetCache; 1644 return aAny; 1645 } 1646 1647 Reference< container::XEnumeration > SAL_CALL ScExternalDocLinkObj::createEnumeration() 1648 { 1649 ScUnoGuard aGuard; 1650 Reference< container::XEnumeration > aRef( 1651 new ScIndexEnumeration(this, OUString::createFromAscii( 1652 "com.sun.star.sheet.ExternalDocLink"))); 1653 return aRef; 1654 } 1655 1656 uno::Type SAL_CALL ScExternalDocLinkObj::getElementType() 1657 { 1658 ScUnoGuard aGuard; 1659 return getCppuType(static_cast<Reference<sheet::XExternalDocLink>*>(0)); 1660 } 1661 1662 sal_Bool SAL_CALL ScExternalDocLinkObj::hasElements() 1663 { 1664 ScUnoGuard aGuard; 1665 1666 // #i116940# be consistent with getByName: count only table names which have a cache already 1667 return ( getElementNames().getLength() > 0 ); 1668 } 1669 1670 sal_Int32 SAL_CALL ScExternalDocLinkObj::getTokenIndex() 1671 { 1672 return static_cast<sal_Int32>(mnFileId); 1673 } 1674 1675 // ============================================================================ 1676 1677 ScExternalDocLinksObj::ScExternalDocLinksObj(ScDocShell* pDocShell) : 1678 mpDocShell(pDocShell), 1679 mpRefMgr(pDocShell->GetDocument()->GetExternalRefManager()) 1680 { 1681 } 1682 1683 ScExternalDocLinksObj::~ScExternalDocLinksObj() 1684 { 1685 } 1686 1687 Reference< sheet::XExternalDocLink > SAL_CALL ScExternalDocLinksObj::addDocLink( 1688 const OUString& aDocName ) 1689 { 1690 ScUnoGuard aGuard; 1691 sal_uInt16 nFileId = mpRefMgr->getExternalFileId(aDocName); 1692 Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpRefMgr, nFileId)); 1693 return aDocLink; 1694 } 1695 1696 Any SAL_CALL ScExternalDocLinksObj::getByName(const::rtl::OUString &aName) 1697 { 1698 ScUnoGuard aGuard; 1699 if (!mpRefMgr->hasExternalFile(aName)) 1700 throw container::NoSuchElementException(); 1701 1702 sal_uInt16 nFileId = mpRefMgr->getExternalFileId(aName); 1703 Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpRefMgr, nFileId)); 1704 1705 Any aAny; 1706 aAny <<= aDocLink; 1707 return aAny; 1708 } 1709 1710 Sequence< OUString > SAL_CALL ScExternalDocLinksObj::getElementNames() 1711 { 1712 ScUnoGuard aGuard; 1713 sal_uInt16 n = mpRefMgr->getExternalFileCount(); 1714 Sequence<OUString> aSeq(n); 1715 for (sal_uInt16 i = 0; i < n; ++i) 1716 { 1717 const String* pName = mpRefMgr->getExternalFileName(i); 1718 aSeq[i] = pName ? *pName : EMPTY_STRING; 1719 } 1720 1721 return aSeq; 1722 } 1723 1724 sal_Bool SAL_CALL ScExternalDocLinksObj::hasByName(const OUString &aName) 1725 { 1726 ScUnoGuard aGuard; 1727 return mpRefMgr->hasExternalFile(aName); 1728 } 1729 1730 sal_Int32 SAL_CALL ScExternalDocLinksObj::getCount() 1731 { 1732 ScUnoGuard aGuard; 1733 return mpRefMgr->getExternalFileCount(); 1734 } 1735 1736 Any SAL_CALL ScExternalDocLinksObj::getByIndex(sal_Int32 nIndex) 1737 { 1738 ScUnoGuard aGuard; 1739 if (nIndex > ::std::numeric_limits<sal_uInt16>::max() || nIndex < ::std::numeric_limits<sal_uInt16>::min()) 1740 throw lang::IndexOutOfBoundsException(); 1741 1742 sal_uInt16 nFileId = static_cast<sal_uInt16>(nIndex); 1743 1744 if (!mpRefMgr->hasExternalFile(nFileId)) 1745 throw lang::IndexOutOfBoundsException(); 1746 1747 Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpRefMgr, nFileId)); 1748 Any aAny; 1749 aAny <<= aDocLink; 1750 return aAny; 1751 } 1752 1753 Reference< container::XEnumeration > SAL_CALL ScExternalDocLinksObj::createEnumeration() 1754 { 1755 ScUnoGuard aGuard; 1756 Reference< container::XEnumeration > aRef( 1757 new ScIndexEnumeration(this, OUString::createFromAscii( 1758 "com.sun.star.sheet.ExternalDocLinks"))); 1759 return aRef; 1760 } 1761 1762 uno::Type SAL_CALL ScExternalDocLinksObj::getElementType() 1763 { 1764 ScUnoGuard aGuard; 1765 return getCppuType(static_cast<Reference<sheet::XExternalDocLinks>*>(0)); 1766 } 1767 1768 sal_Bool SAL_CALL ScExternalDocLinksObj::hasElements() 1769 { 1770 ScUnoGuard aGuard; 1771 return mpRefMgr->getExternalFileCount() > 0; 1772 } 1773