xref: /aoo4110/main/sc/source/ui/unoobj/linkuno.cxx (revision b1cdbd2c)
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