xref: /trunk/main/sc/source/ui/unoobj/linkuno.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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()
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 )
152 {
153     ScUnoGuard aGuard;
154     setFileName(aName);     // Name ist der Dateiname (URL)
155 }
156 
157 // XRefreshable
158 
refresh()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 
addRefreshListener(const uno::Reference<util::XRefreshListener> & xListener)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 
removeRefreshListener(const uno::Reference<util::XRefreshListener> & xListener)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 
Refreshed_Impl()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 
ModifyRefreshDelay_Impl(sal_Int32 nRefresh)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 
getPropertySetInfo()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 
setPropertyValue(const rtl::OUString & aPropertyName,const uno::Any & aValue)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 
getPropertyValue(const rtl::OUString & aPropertyName)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 
SC_IMPL_DUMMY_PROPERTY_LISTENER(ScSheetLinkObj)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 
setFileName(const rtl::OUString & rNewName)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 
getFilter(void) const323 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 
setFilter(const rtl::OUString & Filter)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 
getFilterOptions(void) const344 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 
setFilterOptions(const rtl::OUString & FilterOptions)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 
getRefreshDelay(void) const365 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 
setRefreshDelay(sal_Int32 nRefreshDelay)375 void ScSheetLinkObj::setRefreshDelay(sal_Int32 nRefreshDelay)
376 {
377     ScUnoGuard aGuard;
378     ModifyRefreshDelay_Impl( nRefreshDelay );
379 }
380 
381 //------------------------------------------------------------------------
382 
ScSheetLinksObj(ScDocShell * pDocSh)383 ScSheetLinksObj::ScSheetLinksObj(ScDocShell* pDocSh) :
384     pDocShell( pDocSh )
385 {
386     pDocShell->GetDocument()->AddUnoObject(*this);
387 }
388 
~ScSheetLinksObj()389 ScSheetLinksObj::~ScSheetLinksObj()
390 {
391     if (pDocShell)
392         pDocShell->GetDocument()->RemoveUnoObject(*this);
393 }
394 
Notify(SfxBroadcaster &,const SfxHint & rHint)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 
GetObjectByIndex_Impl(sal_Int32 nIndex)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 
GetObjectByName_Impl(const rtl::OUString & aName)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 
createEnumeration()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 
getCount()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 
getByIndex(sal_Int32 nIndex)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 
getElementType()501 uno::Type SAL_CALL ScSheetLinksObj::getElementType()
502 {
503     ScUnoGuard aGuard;
504     return getCppuType((uno::Reference<beans::XPropertySet>*)0);
505 }
506 
hasElements()507 sal_Bool SAL_CALL ScSheetLinksObj::hasElements()
508 {
509     ScUnoGuard aGuard;
510     return ( getCount() != 0 );
511 }
512 
getByName(const rtl::OUString & aName)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 
hasByName(const rtl::OUString & aName)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 
getElementNames()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 
lcl_GetAreaLink(ScDocShell * pDocShell,sal_uInt16 nPos)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 
ScAreaLinkObj(ScDocShell * pDocSh,sal_uInt16 nP)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 
~ScAreaLinkObj()612 ScAreaLinkObj::~ScAreaLinkObj()
613 {
614     if (pDocShell)
615         pDocShell->GetDocument()->RemoveUnoObject(*this);
616 }
617 
Notify(SfxBroadcaster &,const SfxHint & rHint)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 
Modify_Impl(const rtl::OUString * pNewFile,const rtl::OUString * pNewFilter,const rtl::OUString * pNewOptions,const rtl::OUString * pNewSource,const table::CellRangeAddress * pNewDest)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 
ModifyRefreshDelay_Impl(sal_Int32 nRefresh)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 
refresh()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 
addRefreshListener(const uno::Reference<util::XRefreshListener> & xListener)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 
removeRefreshListener(const uno::Reference<util::XRefreshListener> & xListener)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 
Refreshed_Impl()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 
getPropertySetInfo()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 
setPropertyValue(const rtl::OUString & aPropertyName,const uno::Any & aValue)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 
getPropertyValue(const rtl::OUString & aPropertyName)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 
SC_IMPL_DUMMY_PROPERTY_LISTENER(ScAreaLinkObj)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 
setFileName(const rtl::OUString & rNewName)820 void ScAreaLinkObj::setFileName(const rtl::OUString& rNewName)
821 {
822     ScUnoGuard aGuard;
823     Modify_Impl( &rNewName, NULL, NULL, NULL, NULL );
824 }
825 
getFilter(void) const826 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 
setFilter(const rtl::OUString & Filter)836 void ScAreaLinkObj::setFilter(const rtl::OUString& Filter)
837 {
838     ScUnoGuard aGuard;
839     Modify_Impl( NULL, &Filter, NULL, NULL, NULL );
840 }
841 
getFilterOptions(void) const842 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 
setFilterOptions(const rtl::OUString & FilterOptions)852 void ScAreaLinkObj::setFilterOptions(const rtl::OUString& FilterOptions)
853 {
854     ScUnoGuard aGuard;
855     Modify_Impl( NULL, NULL, &FilterOptions, NULL, NULL );
856 }
857 
getRefreshDelay(void) const858 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 
setRefreshDelay(sal_Int32 nRefreshDelay)868 void ScAreaLinkObj::setRefreshDelay(sal_Int32 nRefreshDelay)
869 {
870     ScUnoGuard aGuard;
871     ModifyRefreshDelay_Impl( nRefreshDelay );
872 }
873 
874 // XAreaLink
875 
getSourceArea()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 
setSourceArea(const rtl::OUString & aSourceArea)886 void SAL_CALL ScAreaLinkObj::setSourceArea( const rtl::OUString& aSourceArea )
887 {
888     ScUnoGuard aGuard;
889     Modify_Impl( NULL, NULL, NULL, &aSourceArea, NULL );
890 }
891 
getDestArea()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 
setDestArea(const table::CellRangeAddress & aDestArea)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 
ScAreaLinksObj(ScDocShell * pDocSh)910 ScAreaLinksObj::ScAreaLinksObj(ScDocShell* pDocSh) :
911     pDocShell( pDocSh )
912 {
913     pDocShell->GetDocument()->AddUnoObject(*this);
914 }
915 
~ScAreaLinksObj()916 ScAreaLinksObj::~ScAreaLinksObj()
917 {
918     if (pDocShell)
919         pDocShell->GetDocument()->RemoveUnoObject(*this);
920 }
921 
Notify(SfxBroadcaster &,const SfxHint & rHint)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 
GetObjectByIndex_Impl(sal_Int32 nIndex)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 
insertAtPosition(const table::CellAddress & aDestPos,const rtl::OUString & aFileName,const rtl::OUString & aSourceArea,const rtl::OUString & aFilter,const rtl::OUString & aFilterOptions)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 
removeByIndex(sal_Int32 nIndex)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 
createEnumeration()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 
getCount()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 
getByIndex(sal_Int32 nIndex)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 
getElementType()1019 uno::Type SAL_CALL ScAreaLinksObj::getElementType()
1020 {
1021     ScUnoGuard aGuard;
1022     return getCppuType((uno::Reference<sheet::XAreaLink>*)0);
1023 }
1024 
hasElements()1025 sal_Bool SAL_CALL ScAreaLinksObj::hasElements()
1026 {
1027     ScUnoGuard aGuard;
1028     return ( getCount() != 0 );
1029 }
1030 
1031 //------------------------------------------------------------------------
1032 
ScDDELinkObj(ScDocShell * pDocSh,const String & rA,const String & rT,const String & rI)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 
~ScDDELinkObj()1043 ScDDELinkObj::~ScDDELinkObj()
1044 {
1045     if (pDocShell)
1046         pDocShell->GetDocument()->RemoveUnoObject(*this);
1047 }
1048 
Notify(SfxBroadcaster &,const SfxHint & rHint)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 
lcl_BuildDDEName(const String & rAppl,const String & rTopic,const String & rItem)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 
getName()1083 rtl::OUString SAL_CALL ScDDELinkObj::getName()
1084 {
1085     ScUnoGuard aGuard;
1086     return lcl_BuildDDEName( aAppl, aTopic, aItem );
1087 }
1088 
setName(const rtl::OUString &)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 
getApplication()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 
getTopic()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 
getItem()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 
refresh()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 
addRefreshListener(const uno::Reference<util::XRefreshListener> & xListener)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 
removeRefreshListener(const uno::Reference<util::XRefreshListener> & xListener)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 
getResults()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 
setResults(const uno::Sequence<uno::Sequence<uno::Any>> & aResults)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 
Refreshed_Impl()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 
ScDDELinksObj(ScDocShell * pDocSh)1244 ScDDELinksObj::ScDDELinksObj(ScDocShell* pDocSh) :
1245     pDocShell( pDocSh )
1246 {
1247     pDocShell->GetDocument()->AddUnoObject(*this);
1248 }
1249 
~ScDDELinksObj()1250 ScDDELinksObj::~ScDDELinksObj()
1251 {
1252     if (pDocShell)
1253         pDocShell->GetDocument()->RemoveUnoObject(*this);
1254 }
1255 
Notify(SfxBroadcaster &,const SfxHint & rHint)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 
GetObjectByIndex_Impl(sal_Int32 nIndex)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 
GetObjectByName_Impl(const rtl::OUString & aName)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 
createEnumeration()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 
getCount()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 
getByIndex(sal_Int32 nIndex)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 
getElementType()1330 uno::Type SAL_CALL ScDDELinksObj::getElementType()
1331 {
1332     ScUnoGuard aGuard;
1333     return getCppuType((uno::Reference<sheet::XDDELink>*)0);
1334 }
1335 
hasElements()1336 sal_Bool SAL_CALL ScDDELinksObj::hasElements()
1337 {
1338     ScUnoGuard aGuard;
1339     return ( getCount() != 0 );
1340 }
1341 
getByName(const rtl::OUString & aName)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 
getElementNames()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 
hasByName(const rtl::OUString & aName)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 
addDDELink(const::rtl::OUString & aApplication,const::rtl::OUString & aTopic,const::rtl::OUString & aItem,::com::sun::star::sheet::DDELinkMode nMode)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 
ScExternalSheetCacheObj(ScExternalRefCache::TableTypeRef pTable,size_t nIndex)1453 ScExternalSheetCacheObj::ScExternalSheetCacheObj(ScExternalRefCache::TableTypeRef pTable, size_t nIndex) :
1454     mpTable(pTable),
1455     mnIndex(nIndex)
1456 {
1457 }
1458 
~ScExternalSheetCacheObj()1459 ScExternalSheetCacheObj::~ScExternalSheetCacheObj()
1460 {
1461 }
1462 
setCellValue(sal_Int32 nCol,sal_Int32 nRow,const Any & rValue)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 
getCellValue(sal_Int32 nCol,sal_Int32 nRow)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 
getAllRows()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 
getAllColumns(sal_Int32 nRow)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 
getTokenIndex()1543 sal_Int32 SAL_CALL ScExternalSheetCacheObj::getTokenIndex()
1544 {
1545     return static_cast< sal_Int32 >( mnIndex );
1546 }
1547 
1548 // ============================================================================
1549 
ScExternalDocLinkObj(ScExternalRefManager * pRefMgr,sal_uInt16 nFileId)1550 ScExternalDocLinkObj::ScExternalDocLinkObj(ScExternalRefManager* pRefMgr, sal_uInt16 nFileId) :
1551     mpRefMgr(pRefMgr), mnFileId(nFileId)
1552 {
1553 }
1554 
~ScExternalDocLinkObj()1555 ScExternalDocLinkObj::~ScExternalDocLinkObj()
1556 {
1557 }
1558 
addSheetCache(const OUString & aSheetName,sal_Bool bDynamicCache)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 
getByName(const::rtl::OUString & aName)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 
getElementNames()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 
hasByName(const OUString & aName)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 
getCount()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 
getByIndex(sal_Int32 nApiIndex)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 
createEnumeration()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 
getElementType()1656 uno::Type SAL_CALL ScExternalDocLinkObj::getElementType()
1657 {
1658     ScUnoGuard aGuard;
1659     return getCppuType(static_cast<Reference<sheet::XExternalDocLink>*>(0));
1660 }
1661 
hasElements()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 
getTokenIndex()1670 sal_Int32 SAL_CALL ScExternalDocLinkObj::getTokenIndex()
1671 {
1672     return static_cast<sal_Int32>(mnFileId);
1673 }
1674 
1675 // ============================================================================
1676 
ScExternalDocLinksObj(ScDocShell * pDocShell)1677 ScExternalDocLinksObj::ScExternalDocLinksObj(ScDocShell* pDocShell) :
1678     mpDocShell(pDocShell),
1679     mpRefMgr(pDocShell->GetDocument()->GetExternalRefManager())
1680 {
1681 }
1682 
~ScExternalDocLinksObj()1683 ScExternalDocLinksObj::~ScExternalDocLinksObj()
1684 {
1685 }
1686 
addDocLink(const OUString & aDocName)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 
getByName(const::rtl::OUString & aName)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 
getElementNames()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 
hasByName(const OUString & aName)1724 sal_Bool SAL_CALL ScExternalDocLinksObj::hasByName(const OUString &aName)
1725 {
1726     ScUnoGuard aGuard;
1727     return mpRefMgr->hasExternalFile(aName);
1728 }
1729 
getCount()1730 sal_Int32 SAL_CALL ScExternalDocLinksObj::getCount()
1731 {
1732     ScUnoGuard aGuard;
1733     return mpRefMgr->getExternalFileCount();
1734 }
1735 
getByIndex(sal_Int32 nIndex)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 
createEnumeration()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 
getElementType()1762 uno::Type SAL_CALL ScExternalDocLinksObj::getElementType()
1763 {
1764     ScUnoGuard aGuard;
1765     return getCppuType(static_cast<Reference<sheet::XExternalDocLinks>*>(0));
1766 }
1767 
hasElements()1768 sal_Bool SAL_CALL ScExternalDocLinksObj::hasElements()
1769 {
1770     ScUnoGuard aGuard;
1771     return mpRefMgr->getExternalFileCount() > 0;
1772 }
1773