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