xref: /aoo41x/main/sfx2/source/appl/fileobj.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sfx2.hxx"
30 
31 #include <vcl/wrkwin.hxx>
32 #include <vcl/msgbox.hxx>
33 #include <tools/urlobj.hxx>
34 #include <tools/stream.hxx>
35 #include <sot/formats.hxx>
36 #include <svtools/filter.hxx>
37 #include <sfx2/lnkbase.hxx>
38 #include <sfx2/app.hxx>
39 #include <sfx2/progress.hxx>
40 #include <sfx2/docfilt.hxx>
41 #include <sfx2/filedlghelper.hxx>
42 #include <sot/exchange.hxx>
43 #include <com/sun/star/uno/Any.hxx>
44 #include <com/sun/star/uno/Sequence.hxx>
45 #include <sfx2/docfac.hxx>
46 #include <com/sun/star/document/XTypeDetection.hpp>
47 #include <comphelper/mediadescriptor.hxx>
48 #include <comphelper/processfactory.hxx>
49 #include <sfx2/linkmgr.hxx>
50 #include <sfx2/opengrf.hxx>
51 #include "sfx2/sfxresid.hxx"
52 #include "fileobj.hxx"
53 #include "app.hrc"
54 
55 namespace css = ::com::sun::star;
56 
57 #define FILETYPE_TEXT		1
58 #define FILETYPE_GRF		2
59 #define FILETYPE_OBJECT		3
60 
61 struct Impl_DownLoadData
62 {
63 	Graphic aGrf;
64 	Timer aTimer;
65 
66 	Impl_DownLoadData( const Link& rLink )
67 	{
68 		aTimer.SetTimeout( 100 );
69 		aTimer.SetTimeoutHdl( rLink  );
70 		aGrf.SetDefaultType();
71 	}
72 	~Impl_DownLoadData()
73 	{
74 		aTimer.Stop();
75 	}
76 };
77 
78 // --------------------------------------------------------------------------
79 
80 
81 SvFileObject::SvFileObject() :
82 	pDownLoadData( NULL ), pOldParent( NULL ), nType( FILETYPE_TEXT )
83 {
84 	bLoadAgain = sal_True;
85 	bSynchron = bLoadError = bWaitForData = bDataReady = bNativFormat =
86 	bClearMedium = bStateChangeCalled = bInCallDownLoad = sal_False;
87 }
88 
89 
90 SvFileObject::~SvFileObject()
91 {
92 	if ( xMed.Is() )
93 	{
94 		xMed->SetDataAvailableLink( Link() );
95 		xMed->SetDoneLink( Link() );
96 		xMed.Clear();
97 	}
98 	delete pDownLoadData;
99 }
100 
101 
102 sal_Bool SvFileObject::GetData( ::com::sun::star::uno::Any & rData,
103 								const String & rMimeType,
104 								sal_Bool bGetSynchron )
105 {
106 	sal_uIntPtr nFmt = SotExchange::GetFormatStringId( rMimeType );
107 	switch( nType )
108 	{
109 	case FILETYPE_TEXT:
110 		if( FORMAT_FILE == nFmt )
111 		{
112 			// das Medium muss in der Applikation geoffnet werden, um die
113 			// relativen Datei Links aufzuloesen!!!! Wird ueber den
114 			// LinkManager und damit von dessen Storage erledigt.
115 			rData <<= rtl::OUString( sFileNm );
116 		}
117 		break;
118 
119 	case FILETYPE_GRF:
120 		if( !bLoadError )
121 		{
122 			SfxMediumRef xTmpMed;
123 
124 			if( FORMAT_GDIMETAFILE == nFmt || FORMAT_BITMAP == nFmt ||
125 				SOT_FORMATSTR_ID_SVXB == nFmt )
126 			{
127 				Graphic aGrf;
128 
129 				//JP 15.07.98: Bug 52959
130 				//		falls das Nativformat doch erwuenscht ist, muss am
131 				//		Ende das Flag zurueckgesetzt werden.
132 // wird einzig und allein im sw/ndgrf.cxx benutzt, wenn der Link vom
133 // GraphicNode entfernt wird.
134 				sal_Bool bOldNativFormat = bNativFormat;
135 //!!??				bNativFormat = 0 != (ASPECT_ICON & pSvData->GetAspect());
136 
137 				// falls gedruckt werden soll, warten wir bis die
138 				// Daten vorhanden sind
139 				if( bGetSynchron )
140 				{
141 					// testhalber mal ein LoadFile rufen um das nach-
142 					// laden ueberahaupt anzustossen
143 					if( !xMed.Is() )
144 						LoadFile_Impl();
145 
146 					if( !bInCallDownLoad )
147 					{
148 						xTmpMed = xMed;
149 						while( bWaitForData )
150 							Application::Reschedule();
151 
152 						xMed = xTmpMed;
153 						bClearMedium = sal_True;
154 					}
155 				}
156 
157 				if( pDownLoadData ||
158 					( !bWaitForData && ( xMed.Is() || 		// wurde als URL geladen
159 						( bSynchron && LoadFile_Impl() && xMed.Is() ) )) )
160 				{
161 					// falls
162 
163 					// falls es uebers Internet gesogen wurde, nicht
164 					// wieder versuchen
165 					if( !bGetSynchron )
166 						bLoadAgain = !xMed->IsRemote();
167 					bLoadError = !GetGraphic_Impl( aGrf, xMed->GetInStream() );
168 				}
169 				else if( !LoadFile_Impl() ||
170 						!GetGraphic_Impl( aGrf, xMed.Is() ? xMed->GetInStream() : 0 ))
171 				{
172 					if( !xMed.Is() )
173 						break;
174 					aGrf.SetDefaultType();
175 				}
176 
177 				if( SOT_FORMATSTR_ID_SVXB != nFmt )
178 					nFmt = (bLoadError || GRAPHIC_BITMAP == aGrf.GetType())
179 								? FORMAT_BITMAP
180 								: FORMAT_GDIMETAFILE;
181 
182 				SvMemoryStream aMemStm( 0, 65535 );
183 				switch ( nFmt )
184 				{
185 				case SOT_FORMATSTR_ID_SVXB:
186 					if( GRAPHIC_NONE != aGrf.GetType() )
187 					{
188 						aMemStm.SetVersion( SOFFICE_FILEFORMAT_50 );
189 						aMemStm << aGrf;
190 					}
191 					break;
192 
193 				case  FORMAT_BITMAP:
194 					if( !aGrf.GetBitmap().IsEmpty())
195 						aMemStm << aGrf.GetBitmap();
196 					break;
197 
198 				default:
199 					if( aGrf.GetGDIMetaFile().GetActionCount() )
200 					{
201 						GDIMetaFile aMeta( aGrf.GetGDIMetaFile() );
202 						aMeta.Write( aMemStm );
203 					}
204 				}
205                 rData <<= css::uno::Sequence< sal_Int8 >( (sal_Int8*) aMemStm.GetData(),
206 										aMemStm.Seek( STREAM_SEEK_TO_END ) );
207 
208 				bNativFormat = bOldNativFormat;
209 
210 				// alles fertig?
211 				if( xMed.Is() && !bSynchron && bClearMedium )
212 				{
213 					xMed.Clear();
214 					bClearMedium = sal_False;
215 				}
216 			}
217 		}
218 		break;
219 	case FILETYPE_OBJECT:
220 		// TODO/LATER: possibility to insert a new object
221 		rData <<= rtl::OUString( sFileNm );
222 		break;
223 	}
224 	return sal_True/*0 != aTypeList.Count()*/;
225 }
226 
227 
228 
229 
230 sal_Bool SvFileObject::Connect( sfx2::SvBaseLink* pLink )
231 {
232 	if( !pLink || !pLink->GetLinkManager() )
233 		return sal_False;
234 
235 	// teste doch mal, ob nicht ein anderer Link mit der gleichen
236 	// Verbindung schon existiert
237 	pLink->GetLinkManager()->GetDisplayNames( pLink, 0, &sFileNm, 0, &sFilter );
238 
239 	if( OBJECT_CLIENT_GRF == pLink->GetObjType() )
240 	{
241         SfxObjectShellRef pShell = pLink->GetLinkManager()->GetPersist();
242         if( pShell.Is() )
243 		{
244 			if( pShell->IsAbortingImport() )
245 				return sal_False;
246 
247 			if( pShell->GetMedium() )
248 				sReferer = pShell->GetMedium()->GetName();
249         }
250 	}
251 
252 	switch( pLink->GetObjType() )
253 	{
254 	case OBJECT_CLIENT_GRF:
255 		nType = FILETYPE_GRF;
256 		bSynchron = pLink->IsSynchron();
257 		break;
258 
259 	case OBJECT_CLIENT_FILE:
260 		nType = FILETYPE_TEXT;
261 		break;
262 
263 	case OBJECT_CLIENT_OLE:
264 		nType = FILETYPE_OBJECT;
265 		// TODO/LATER: introduce own type to be used for exchanging
266 		break;
267 
268 	default:
269 		return sal_False;
270 	}
271 
272 	SetUpdateTimeout( 0 );
273 
274 	// und jetzt bei diesem oder gefundenem Pseudo-Object anmelden
275 	AddDataAdvise( pLink, SotExchange::GetFormatMimeType( pLink->GetContentType()), 0 );
276 	return sal_True;
277 }
278 
279 
280 sal_Bool SvFileObject::LoadFile_Impl()
281 {
282 	// wir sind noch im Laden!!
283 	if( bWaitForData || !bLoadAgain || xMed.Is() || pDownLoadData )
284 		return sal_False;
285 
286 	// z.Z. nur auf die aktuelle DocShell
287 	xMed = new SfxMedium( sFileNm, STREAM_STD_READ, sal_True );
288     SvLinkSource::StreamToLoadFrom aStreamToLoadFrom =
289         getStreamToLoadFrom();
290     xMed->setStreamToLoadFrom(
291         aStreamToLoadFrom.m_xInputStreamToLoadFrom,
292         aStreamToLoadFrom.m_bIsReadOnly);
293 	// setStreamToLoadFrom(0,0);
294 	if( sReferer.Len() )
295 		xMed->SetReferer( sReferer );
296 
297 	if( !bSynchron )
298 	{
299 		bLoadAgain = bDataReady = bInNewData = sal_False;
300 		bWaitForData = sal_True;
301 
302 		SfxMediumRef xTmpMed = xMed;
303 		xMed->SetDataAvailableLink( STATIC_LINK( this, SvFileObject, LoadGrfNewData_Impl ) );
304 		bInCallDownLoad = sal_True;
305 		xMed->DownLoad( STATIC_LINK( this, SvFileObject, LoadGrfReady_Impl ) );
306 		bInCallDownLoad = sal_False;
307 
308 		bClearMedium = !xMed.Is();
309 		if( bClearMedium )
310 			xMed = xTmpMed;		// falls gleich im DownLoad schon schluss ist
311 		return bDataReady;
312 	}
313 
314 	bWaitForData = sal_True;
315 	bDataReady = bInNewData = sal_False;
316 	xMed->DownLoad();
317 	bLoadAgain = !xMed->IsRemote();
318 	bWaitForData = sal_False;
319 
320 	// Grafik ist fertig, also DataChanged von der Statusaederung schicken:
321 	SendStateChg_Impl( xMed->GetInStream() && xMed->GetInStream()->GetError()
322 						? sfx2::LinkManager::STATE_LOAD_ERROR : sfx2::LinkManager::STATE_LOAD_OK );
323 	return sal_True;
324 }
325 
326 
327 sal_Bool SvFileObject::GetGraphic_Impl( Graphic& rGrf, SvStream* pStream )
328 {
329 	GraphicFilter* pGF = GraphicFilter::GetGraphicFilter();
330 
331 	const sal_uInt16 nFilter = sFilter.Len() && pGF->GetImportFormatCount()
332 							? pGF->GetImportFormatNumber( sFilter )
333 							: GRFILTER_FORMAT_DONTKNOW;
334 
335 	String aEmptyStr;
336 	int nRes;
337 
338 	// vermeiden, dass ein native Link angelegt wird
339 	if( ( !pStream || !pDownLoadData ) && !rGrf.IsLink() &&
340 		!rGrf.GetContext() && !bNativFormat )
341 		rGrf.SetLink( GfxLink() );
342 
343 	if( !pStream )
344 		nRes = xMed.Is() ? GRFILTER_OPENERROR
345 						 : pGF->ImportGraphic( rGrf, INetURLObject(sFileNm),
346 							nFilter );
347 	else if( !pDownLoadData )
348 	{
349 		pStream->Seek( STREAM_SEEK_TO_BEGIN );
350 		nRes = pGF->ImportGraphic( rGrf, aEmptyStr, *pStream, nFilter );
351 	}
352 	else
353 	{
354 		nRes = pGF->ImportGraphic( pDownLoadData->aGrf, aEmptyStr,
355 									*pStream, nFilter );
356 
357 		if( pDownLoadData )
358 		{
359 			rGrf = pDownLoadData->aGrf;
360 			if( GRAPHIC_NONE == rGrf.GetType() )
361 				rGrf.SetDefaultType();
362 
363 
364 			if( !pDownLoadData->aGrf.GetContext() )
365 			{
366 				xMed->SetDataAvailableLink( Link() );
367 //				xMed->SetDoneLink( Link() );
368 				delete pDownLoadData, pDownLoadData = 0;
369 				bDataReady = sal_True;
370 				bWaitForData = sal_False;
371 			}
372 			else if( sal_False )
373 			{
374 				// Timer aufsetzen, um zurueck zukehren
375 				pDownLoadData->aTimer.Start();
376 			}
377 		}
378 	}
379 
380 	if( pStream && ERRCODE_IO_PENDING == pStream->GetError() )
381 		pStream->ResetError();
382 
383 #ifdef DBG_UTIL
384 	if( nRes )
385 	{
386 		if( xMed.Is() && !pStream )
387 		{
388 			DBG_WARNING3( "GrafikFehler [%d] - [%s] URL[%s]",
389 							nRes,
390 							xMed->GetPhysicalName().GetBuffer(),
391 							sFileNm.GetBuffer() );
392 		}
393 		else
394 		{
395 			DBG_WARNING2( "GrafikFehler [%d] - [%s]",
396 							nRes, sFileNm.GetBuffer() );
397 		}
398 	}
399 #endif
400 
401 	return GRFILTER_OK == nRes;
402 }
403 
404 /** detect the filter of the given file
405 
406     @param _rURL
407         specifies the URL of the file which filter is to detected.<br/>
408         If the URL doesn't denote a valid (existent and accessible) file, the
409         request is silently dropped.
410 */
411 String impl_getFilter( const String& _rURL )
412 {
413     String sFilter;
414     if ( _rURL.Len() == 0 )
415         return sFilter;
416 
417     try
418     {
419         css::uno::Reference< ::com::sun::star::document::XTypeDetection > xTypeDetection(
420             ::comphelper::getProcessServiceFactory()->createInstance(
421                 ::rtl::OUString::createFromAscii("com.sun.star.document.TypeDetection") ),
422                 css::uno::UNO_QUERY );
423         if ( xTypeDetection.is() )
424         {
425             ::comphelper::MediaDescriptor aDescr;
426             aDescr[ ::comphelper::MediaDescriptor::PROP_URL() ] <<= ::rtl::OUString( _rURL );
427             css::uno::Sequence< css::beans::PropertyValue > aDescrList =
428                 aDescr.getAsConstPropertyValueList();
429             ::rtl::OUString sType = xTypeDetection->queryTypeByDescriptor( aDescrList, sal_True );
430             if ( sType.getLength() )
431             {
432                 css::uno::Reference< css::container::XNameAccess > xTypeCont( xTypeDetection,
433                                                                               css::uno::UNO_QUERY );
434                 if ( xTypeCont.is() )
435                 {
436                     ::comphelper::SequenceAsHashMap lTypeProps( xTypeCont->getByName( sType ) );
437                     sFilter = lTypeProps.getUnpackedValueOrDefault(
438                         ::rtl::OUString::createFromAscii("PreferredFilter"), ::rtl::OUString() );
439                 }
440             }
441         }
442     }
443     catch( const css::uno::Exception& )
444     {
445     }
446 
447     return sFilter;
448 }
449 
450 void SvFileObject::Edit( Window* pParent, sfx2::SvBaseLink* pLink, const Link& rEndEditHdl )
451 {
452     aEndEditLink = rEndEditHdl;
453     String sFile, sRange, sTmpFilter;
454     if( pLink && pLink->GetLinkManager() )
455     {
456         pLink->GetLinkManager()->GetDisplayNames( pLink, 0, &sFile, &sRange, &sTmpFilter );
457 
458         switch( pLink->GetObjType() )
459         {
460             case OBJECT_CLIENT_GRF:
461             {
462                 nType = FILETYPE_GRF;       // falls noch nicht gesetzt
463 
464                 SvxOpenGraphicDialog aDlg(SfxResId(RID_SVXSTR_EDITGRFLINK));
465                 aDlg.EnableLink(sal_False);
466                 aDlg.SetPath( sFile, sal_True );
467                 aDlg.SetCurrentFilter( sTmpFilter );
468 
469                 if( !aDlg.Execute() )
470                 {
471                     sFile = aDlg.GetPath();
472                     sFile += ::sfx2::cTokenSeperator;
473                     sFile += ::sfx2::cTokenSeperator;
474                     sFile += aDlg.GetCurrentFilter();
475 
476                     if ( aEndEditLink.IsSet() )
477                         aEndEditLink.Call( &sFile );
478                 }
479                 else
480                     sFile.Erase();
481             }
482             break;
483 
484             case OBJECT_CLIENT_OLE:
485             {
486                 nType = FILETYPE_OBJECT; // if not set already
487                 pOldParent = Application::GetDefDialogParent();
488                 Application::SetDefDialogParent( pParent );
489 
490                 ::sfx2::FileDialogHelper* pFileDlg =
491                     pLink->GetFileDialog( (SFXWB_INSERT | WB_3DLOOK), String() );
492                 pFileDlg->StartExecuteModal( LINK( this, SvFileObject, DialogClosedHdl ) );
493             }
494             break;
495 
496             case OBJECT_CLIENT_FILE:
497             {
498                 nType = FILETYPE_TEXT; // if not set already
499                 pOldParent = Application::GetDefDialogParent();
500                 Application::SetDefDialogParent( pParent );
501 
502                 String sFactory;
503                 SfxObjectShell* pShell = pLink->GetLinkManager()->GetPersist();
504                 if ( pShell )
505                     sFactory = pShell->GetFactory().GetFactoryName();
506 
507                 ::sfx2::FileDialogHelper* pFileDlg =
508                     pLink->GetFileDialog( (SFXWB_INSERT | WB_3DLOOK), sFactory );
509                 pFileDlg->StartExecuteModal( LINK( this, SvFileObject, DialogClosedHdl ) );
510             }
511             break;
512 
513             default:
514                 sFile.Erase();
515         }
516 	}
517 }
518 
519 IMPL_STATIC_LINK( SvFileObject, LoadGrfReady_Impl, void*, EMPTYARG )
520 {
521 	// wenn wir von hier kommen, kann es kein Fehler mehr sein
522 	pThis->bLoadError = sal_False;
523 	pThis->bWaitForData = sal_False;
524 	pThis->bInCallDownLoad = sal_False;
525 
526 	if( !pThis->bInNewData && !pThis->bDataReady )
527 	{
528 			// Grafik ist fertig, also DataChanged von der Status-
529 			// aederung schicken:
530 		pThis->bDataReady = sal_True;
531 		pThis->SendStateChg_Impl( sfx2::LinkManager::STATE_LOAD_OK );
532 
533 			// und dann nochmal die Daten senden
534 		pThis->NotifyDataChanged();
535 	}
536 
537 	if( pThis->bDataReady )
538 	{
539 		pThis->bLoadAgain = sal_True;
540 		if( pThis->xMed.Is() )
541 		{
542 			pThis->xMed->SetDataAvailableLink( Link() );
543 			pThis->xMed->SetDoneLink( Link() );
544 
545 			Application::PostUserEvent(
546 						STATIC_LINK( pThis, SvFileObject, DelMedium_Impl ),
547 						new SfxMediumRef( pThis->xMed ));
548 			pThis->xMed.Clear();
549 		}
550 		if( pThis->pDownLoadData )
551 			delete pThis->pDownLoadData, pThis->pDownLoadData = 0;
552 	}
553 
554 	return 0;
555 }
556 
557 IMPL_STATIC_LINK( SvFileObject, DelMedium_Impl, SfxMediumRef*, pDelMed )
558 {
559 	(void)pThis;
560 	delete pDelMed;
561 	return 0;
562 }
563 
564 IMPL_STATIC_LINK( SvFileObject, LoadGrfNewData_Impl, void*, EMPTYARG )
565 {
566 	// wenn wir von hier kommen, kann es kein Fehler mehr sein
567 	if( pThis->bInNewData )
568 		return 0;
569 
570 	pThis->bInNewData = sal_True;
571 	pThis->bLoadError = sal_False;
572 
573 	if( !pThis->pDownLoadData )
574 	{
575 		pThis->pDownLoadData = new Impl_DownLoadData(
576 						STATIC_LINK( pThis, SvFileObject, LoadGrfNewData_Impl ) );
577 
578 		// Null-Link setzen, damit keine temporaeren Grafiken
579 		// rausgeswapt werden; der Filter prueft, ob schon
580 		// ein Link gesetzt ist => falls dies zutrifft, wird
581 		// _kein_ neuer Link gesetzt; der Link muss hier gesetzt werden,
582 		// (bevor das erste Mal gefiltert wird), um zu verhindern,
583 		// dass der Kontext zurueckgesetzt wird (aynchrones Laden)
584 		if( !pThis->bNativFormat )
585 		{
586 			static GfxLink aDummyLink;
587 			pThis->pDownLoadData->aGrf.SetLink( aDummyLink );
588 		}
589 	}
590 
591 	pThis->NotifyDataChanged();
592 
593 	SvStream* pStrm = pThis->xMed.Is() ? pThis->xMed->GetInStream() : 0;
594 	if( pStrm && pStrm->GetError() )
595 	{
596 		if( ERRCODE_IO_PENDING == pStrm->GetError() )
597 			pStrm->ResetError();
598 
599 		// im DataChanged ein DataReady?
600 		else if( pThis->bWaitForData && pThis->pDownLoadData )
601 		{
602 			pThis->bLoadError = sal_True;
603 		}
604 	}
605 
606 	if( pThis->bDataReady )
607 	{
608 		// Grafik ist fertig, also DataChanged von der Status-
609 		// aederung schicken:
610 		pThis->SendStateChg_Impl( pStrm->GetError() ? sfx2::LinkManager::STATE_LOAD_ERROR : sfx2::LinkManager::STATE_LOAD_OK );
611 	}
612 
613 	pThis->bInNewData = sal_False;
614 	return 0;
615 }
616 
617 IMPL_LINK( SvFileObject, DialogClosedHdl, sfx2::FileDialogHelper*, _pFileDlg )
618 {
619     String sFile;
620     Application::SetDefDialogParent( pOldParent );
621 
622     if ( FILETYPE_TEXT == nType || FILETYPE_OBJECT == nType )
623     {
624         if ( _pFileDlg && _pFileDlg->GetError() == ERRCODE_NONE )
625         {
626             String sURL( _pFileDlg->GetPath() );
627             sFile = sURL;
628             sFile += ::sfx2::cTokenSeperator;
629             sFile += ::sfx2::cTokenSeperator;
630             sFile += impl_getFilter( sURL );
631         }
632     }
633     else
634     {
635         DBG_ERRORFILE( "SvFileObject::DialogClosedHdl(): wrong file type" );
636     }
637 
638     if ( aEndEditLink.IsSet() )
639         aEndEditLink.Call( &sFile );
640     return 0;
641 }
642 
643 /*	[Beschreibung]
644 
645 	Die Methode stellt fest, ob aus einem DDE-Object die Daten gelesen
646 	werden kann.
647 	Zurueckgegeben wird:
648 		ERRCODE_NONE 			wenn sie komplett gelesen wurde
649 		ERRCODE_SO_PENDING		wenn sie noch nicht komplett gelesen wurde
650 		ERRCODE_SO_FALSE		sonst
651 */
652 sal_Bool SvFileObject::IsPending() const
653 {
654 	return FILETYPE_GRF == nType && !bLoadError &&
655 			( pDownLoadData || bWaitForData );
656 }
657 sal_Bool SvFileObject::IsDataComplete() const
658 {
659 	sal_Bool bRet = sal_False;
660 	if( FILETYPE_GRF != nType )
661 		bRet = sal_True;
662 	else if( !bLoadError && ( !bWaitForData && !pDownLoadData ))
663 	{
664 		SvFileObject* pThis = (SvFileObject*)this;
665 		if( bDataReady ||
666 			( bSynchron && pThis->LoadFile_Impl() && xMed.Is() ) )
667 			bRet = sal_True;
668 		else
669 		{
670 			INetURLObject aUrl( sFileNm );
671 			if( aUrl.HasError() ||
672 				INET_PROT_NOT_VALID == aUrl.GetProtocol() )
673 				bRet = sal_True;
674 		}
675 	}
676 	return bRet;
677 }
678 
679 
680 
681 void SvFileObject::CancelTransfers()
682 {
683 	// und aus dem Cache austragen, wenn man mitten im Laden ist
684 	if( !bDataReady )
685 	{
686 		// nicht noch mal aufsetzen
687 		bLoadAgain = sal_False;
688 		bDataReady = bLoadError = bWaitForData = sal_True;
689 		SendStateChg_Impl( sfx2::LinkManager::STATE_LOAD_ABORT );
690 	}
691 }
692 
693 
694 void SvFileObject::SendStateChg_Impl( sfx2::LinkManager::LinkState nState )
695 {
696 	if( !bStateChangeCalled && HasDataLinks() )
697 	{
698         css::uno::Any aAny;
699 		aAny <<= rtl::OUString::valueOf( (sal_Int32)nState );
700 		DataChanged( SotExchange::GetFormatName(
701 						sfx2::LinkManager::RegisterStatusInfoId()), aAny );
702 		bStateChangeCalled = sal_True;
703 	}
704 }
705 
706 
707