xref: /aoo41x/main/sw/source/core/graphic/ndgrf.cxx (revision 8a2cae91)
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 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_sw.hxx"
24 #include <hintids.hxx>
25 #include <vcl/salbtype.hxx>             // FRound
26 #include <tools/urlobj.hxx>
27 #include <svl/undo.hxx>
28 #ifndef SVTOOLS_FSTATHELPER_HXX
29 #include <svl/fstathelper.hxx>
30 #endif
31 #include <svtools/imap.hxx>
32 #include <svtools/filter.hxx>
33 #include <sot/storage.hxx>
34 #include <sfx2/linkmgr.hxx>
35 #include <editeng/boxitem.hxx>
36 #include <sot/formats.hxx>
37 #include <fmtfsize.hxx>
38 #include <fmturl.hxx>
39 #include <frmfmt.hxx>
40 #include <doc.hxx>
41 #include <frmatr.hxx>
42 #include <grfatr.hxx>
43 #include <swtypes.hxx>
44 #include <ndgrf.hxx>
45 #include <fmtcol.hxx>
46 #include <hints.hxx>
47 #include <swbaslnk.hxx>
48 #include <pagefrm.hxx>
49 #include <editsh.hxx>
50 #include <pam.hxx>
51 
52 #include <unotools/ucbstreamhelper.hxx>
53 #include <com/sun/star/embed/ElementModes.hpp>
54 #include <com/sun/star/embed/XTransactedObject.hpp>
55 #include <tools/link.hxx>
56 #include <vcl/svapp.hxx>
57 #include <com/sun/star/io/XSeekable.hpp>
58 #include <retrieveinputstreamconsumer.hxx>
59 #include <drawinglayer/processor2d/objectinfoextractor2d.hxx>
60 #include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx>
61 
62 using namespace com::sun::star;
63 
64 
65 // --------------------
66 // SwGrfNode
67 // --------------------
68 SwGrfNode::SwGrfNode(
69     const SwNodeIndex & rWhere,
70     const String& rGrfName,
71     const String& rFltName,
72     const Graphic* pGraphic,
73     SwGrfFmtColl *pGrfColl,
74     SwAttrSet* pAutoAttr )
75         : SwNoTxtNode( rWhere, ND_GRFNODE, pGrfColl, pAutoAttr ),
76           maGrfObj(),
77           mpReplacementGraphic( 0 ),
78           mbLinkedInputStreamReady( false ),
79           mbIsStreamReadOnly( sal_False )
80 {
81     maGrfObj.SetSwapStreamHdl( LINK( this, SwGrfNode, SwapGraphic ) );
82     bInSwapIn = bChgTwipSize = bChgTwipSizeFromPixel = bLoadLowResGrf = bFrameInPaint = bScaleImageMap = sal_False;
83 
84     bGrafikArrived = sal_True;
85     ReRead( rGrfName, rFltName, pGraphic, 0, sal_False );
86 }
87 
88 SwGrfNode::SwGrfNode(
89     const SwNodeIndex & rWhere,
90     const GraphicObject& rGrfObj,
91     SwGrfFmtColl *pGrfColl,
92     SwAttrSet* pAutoAttr )
93         : SwNoTxtNode( rWhere, ND_GRFNODE, pGrfColl, pAutoAttr ),
94           maGrfObj( rGrfObj ),
95           mpReplacementGraphic( 0 ),
96           mbLinkedInputStreamReady( false ),
97           mbIsStreamReadOnly( sal_False )
98 {
99     maGrfObj = rGrfObj;
100     maGrfObj.SetSwapStreamHdl( LINK( this, SwGrfNode, SwapGraphic ) );
101     if ( rGrfObj.HasUserData() && rGrfObj.IsSwappedOut() )
102         maGrfObj.SetSwapState();
103     bInSwapIn = bChgTwipSize = bChgTwipSizeFromPixel = bLoadLowResGrf = bFrameInPaint = bScaleImageMap = sal_False;
104     bGrafikArrived = sal_True;
105 }
106 
107 // Konstruktor fuer den SW/G-Reader. Dieser ctor wird verwendet,
108 // wenn eine gelinkte Grafik gelesen wird. Sie liest diese NICHT ein.
109 
110 SwGrfNode::SwGrfNode(
111     const SwNodeIndex & rWhere,
112     const String& rGrfName,
113     const String& rFltName,
114     SwGrfFmtColl *pGrfColl,
115     SwAttrSet* pAutoAttr )
116         :
117           SwNoTxtNode( rWhere, ND_GRFNODE, pGrfColl, pAutoAttr ),
118           maGrfObj(),
119           mpReplacementGraphic( 0 ),
120           mbLinkedInputStreamReady( false ),
121           mbIsStreamReadOnly( sal_False )
122 {
123     maGrfObj.SetSwapStreamHdl( LINK( this, SwGrfNode, SwapGraphic ) );
124 
125     Graphic aGrf;
126     aGrf.SetDefaultType();
127     maGrfObj.SetGraphic( aGrf, rGrfName );
128 
129     bInSwapIn = bChgTwipSize = bChgTwipSizeFromPixel = bLoadLowResGrf =
130             bFrameInPaint = bScaleImageMap = sal_False;
131     bGrafikArrived = sal_True;
132 
133     InsertLink( rGrfName, rFltName );
134     if ( IsLinkedFile() )
135     {
136         INetURLObject aUrl( rGrfName );
137         if ( INET_PROT_FILE == aUrl.GetProtocol() &&
138              FStatHelper::IsDocument( aUrl.GetMainURL( INetURLObject::NO_DECODE ) ) )
139         {
140             // File vorhanden, Verbindung herstellen ohne ein Update
141             ( (SwBaseLink*) &refLink )->Connect();
142         }
143     }
144 }
145 
146 sal_Bool SwGrfNode::ReRead(
147     const String& rGrfName,
148     const String& rFltName,
149     const Graphic* pGraphic,
150     const GraphicObject* pGrfObj,
151     sal_Bool bNewGrf )
152 {
153     sal_Bool bReadGrf = sal_False, bSetTwipSize = sal_True;
154     delete mpReplacementGraphic;
155     mpReplacementGraphic = 0;
156 
157     ASSERT( pGraphic || pGrfObj || rGrfName.Len(),
158         "GraphicNode without a name, Graphic or GraphicObject" );
159 
160     // ReadRead mit Namen
161     if ( refLink.Is() )
162     {
163         ASSERT( !bInSwapIn, "ReRead: stehe noch im SwapIn" );
164 
165         if ( rGrfName.Len() )
166         {
167             // Besonderheit: steht im FltNamen DDE, handelt es sich um eine
168             //					DDE-gelinkte Grafik
169             String sCmd( rGrfName );
170             if ( rFltName.Len() )
171             {
172                 sal_uInt16 nNewType;
173                 if ( rFltName.EqualsAscii( "DDE" ) )
174                     nNewType = OBJECT_CLIENT_DDE;
175                 else
176                 {
177                     sfx2::MakeLnkName( sCmd, 0, rGrfName, aEmptyStr, &rFltName );
178                     nNewType = OBJECT_CLIENT_GRF;
179                 }
180 
181                 if ( nNewType != refLink->GetObjType() )
182                 {
183                     refLink->Disconnect();
184                     ( (SwBaseLink*) &refLink )->SetObjType( nNewType );
185                 }
186             }
187 
188             refLink->SetLinkSourceName( sCmd );
189         }
190         else		// kein Name mehr, Link aufheben
191         {
192             GetDoc()->GetLinkManager().Remove( refLink );
193             refLink.Clear();
194         }
195 
196         if ( pGraphic )
197         {
198             maGrfObj.SetGraphic( *pGraphic, rGrfName );
199             onGraphicChanged();
200             bReadGrf = sal_True;
201         }
202         else if ( pGrfObj )
203         {
204             maGrfObj = *pGrfObj;
205             if ( pGrfObj->HasUserData() && pGrfObj->IsSwappedOut() )
206                 maGrfObj.SetSwapState();
207             maGrfObj.SetLink( rGrfName );
208             onGraphicChanged();
209             bReadGrf = sal_True;
210         }
211         else
212         {
213             // MIB 25.02.97: Daten der alten Grafik zuruecksetzen, damit
214             // die korrekte Ersatz-Darstellung erscheint, wenn die
215             // der neue Link nicht geladen werden konnte.
216             Graphic aGrf;
217             aGrf.SetDefaultType();
218             maGrfObj.SetGraphic( aGrf, rGrfName );
219 
220             if ( refLink.Is() )
221             {
222                 if ( getLayoutFrm( GetDoc()->GetCurrentLayout() ) )
223                 {
224                     SwMsgPoolItem aMsgHint( RES_GRF_REREAD_AND_INCACHE );
225                     ModifyNotification( &aMsgHint, &aMsgHint );
226                 }
227                 else if ( bNewGrf )
228                 {
229                     //TODO refLink->setInputStream(getInputStream());
230                     ( (SwBaseLink*) &refLink )->SwapIn();
231                 }
232             }
233             onGraphicChanged();
234             bSetTwipSize = sal_False;
235         }
236     }
237     else if ( pGraphic && !rGrfName.Len() )
238     {
239         // MIB 27.02.2001: Old stream must be deleted before the new one is set.
240         if ( HasEmbeddedStreamName() )
241             DelStreamName();
242 
243         maGrfObj.SetGraphic( *pGraphic );
244         onGraphicChanged();
245         bReadGrf = sal_True;
246     }
247     else if ( pGrfObj && !rGrfName.Len() )
248     {
249         // MIB 27.02.2001: Old stream must be deleted before the new one is set.
250         if ( HasEmbeddedStreamName() )
251             DelStreamName();
252 
253         maGrfObj = *pGrfObj;
254         onGraphicChanged();
255         if ( pGrfObj->HasUserData() && pGrfObj->IsSwappedOut() )
256             maGrfObj.SetSwapState();
257         bReadGrf = sal_True;
258     }
259     else if ( !bNewGrf && GRAPHIC_NONE != maGrfObj.GetType() )
260         return sal_True;
261 
262     else
263     {
264         if ( HasEmbeddedStreamName() )
265             DelStreamName();
266 
267         // einen neuen Grafik-Link anlegen
268         InsertLink( rGrfName, rFltName );
269 
270         if ( GetNodes().IsDocNodes() )
271         {
272             if ( pGraphic )
273             {
274                 maGrfObj.SetGraphic( *pGraphic, rGrfName );
275                 onGraphicChanged();
276                 bReadGrf = sal_True;
277                 // Verbindung herstellen ohne ein Update; Grafik haben wir!
278                 ( (SwBaseLink*) &refLink )->Connect();
279             }
280             else if ( pGrfObj )
281             {
282                 maGrfObj = *pGrfObj;
283                 maGrfObj.SetLink( rGrfName );
284                 onGraphicChanged();
285                 bReadGrf = sal_True;
286                 // Verbindung herstellen ohne ein Update; Grafik haben wir!
287                 ( (SwBaseLink*) &refLink )->Connect();
288             }
289             else
290             {
291                 Graphic aGrf;
292                 aGrf.SetDefaultType();
293                 maGrfObj.SetGraphic( aGrf, rGrfName );
294                 onGraphicChanged();
295                 if ( bNewGrf )
296                 {
297                     ( (SwBaseLink*) &refLink )->SwapIn();
298                 }
299             }
300         }
301     }
302 
303     // Bug 39281: Size nicht sofort loeschen - Events auf ImageMaps
304     //			  sollten nicht beim Austauschen nicht ins "leere greifen"
305     if ( bSetTwipSize )
306         SetTwipSize( ::GetGraphicSizeTwip( maGrfObj.GetGraphic(), 0 ) );
307 
308     // erzeuge noch einen Update auf die Frames
309     if ( bReadGrf && bNewGrf )
310     {
311         SwMsgPoolItem aMsgHint( RES_UPDATE_ATTR );
312         ModifyNotification( &aMsgHint, &aMsgHint );
313     }
314 
315     return bReadGrf;
316 }
317 
318 SwGrfNode::~SwGrfNode()
319 {
320     delete mpReplacementGraphic;
321     mpReplacementGraphic = 0;
322 
323     mpThreadConsumer.reset();
324 
325     SwDoc* pDoc = GetDoc();
326     if ( refLink.Is() )
327     {
328         ASSERT( !bInSwapIn, "DTOR: stehe noch im SwapIn" );
329         pDoc->GetLinkManager().Remove( refLink );
330         refLink->Disconnect();
331     }
332     else
333     {
334         // #i40014# - A graphic node, which are in linked
335         // section, whose link is another section is the document, doesn't
336         // have to remove the stream from the storage.
337         // Because it's hard to detect this case here and it would only fix
338         // one problem with shared graphic files - there are also problems,
339         // a certain graphic file is referenced by two independent graphic nodes,
340         // brush item or drawing objects, the stream isn't no longer removed here.
341         // To do this stuff correct, a reference counting on shared streams
342         // inside one document have to be implemented.
343 //        if( !pDoc->IsInDtor() && HasStreamName() )
344 //          DelStreamName();
345     }
346     //#39289# Die Frames muessen hier bereits geloescht weil der DTor der
347     //Frms die Grafik noch fuer StopAnimation braucht.
348     if ( GetDepends() )
349         DelFrms();
350 }
351 
352 /// allow reaction on change of content of GraphicObject
353 void SwGrfNode::onGraphicChanged()
354 {
355     // try to access SwFlyFrmFmt; since title/desc/name are set there, there is no
356     // use to continue if it is not yet set. If not yet set, call onGraphicChanged()
357     // when it is set.
358     SwFlyFrmFmt* pFlyFmt = dynamic_cast< SwFlyFrmFmt* >( GetFlyFmt() );
359 
360     if ( pFlyFmt != NULL )
361     {
362         const bool bWasSwappedOut = ( GetGrfObj().IsSwappedOut() == sal_True );
363 
364         String aName;
365         String aTitle;
366         String aDesc;
367         const SvgDataPtr& rSvgDataPtr = GetGrf().getSvgData();
368 
369         if ( rSvgDataPtr.get() )
370         {
371             const drawinglayer::primitive2d::Primitive2DSequence aSequence( rSvgDataPtr->getPrimitive2DSequence() );
372 
373             if ( aSequence.hasElements() )
374             {
375                 drawinglayer::geometry::ViewInformation2D aViewInformation2D;
376                 drawinglayer::processor2d::ObjectInfoPrimitiveExtractor2D aProcessor( aViewInformation2D );
377 
378                 aProcessor.process( aSequence );
379 
380                 const drawinglayer::primitive2d::ObjectInfoPrimitive2D* pResult = aProcessor.getResult();
381 
382                 if ( pResult )
383                 {
384                     aName = pResult->getName();
385                     aTitle = pResult->getTitle();
386                     aDesc = pResult->getDesc();
387                 }
388             }
389         }
390 
391         if ( aTitle.Len() > 0 )
392         {
393             SetTitle( aTitle );
394         }
395         else if ( aName.Len() > 0 )
396         {
397             SetTitle( aName );
398         }
399 
400         if ( aDesc.Len() > 0 )
401         {
402             SetDescription( aDesc );
403         }
404 
405         if ( bWasSwappedOut )
406         {
407             SwapOut();
408         }
409     }
410 }
411 
412 void SwGrfNode::SetGraphic(
413     const Graphic& rGraphic,
414     const String& rLink )
415 {
416     maGrfObj.SetGraphic( rGraphic, rLink );
417     onGraphicChanged();
418 }
419 
420 const GraphicObject* SwGrfNode::GetReplacementGrfObj() const
421 {
422     if ( !mpReplacementGraphic )
423     {
424         const SvgDataPtr& rSvgDataPtr = GetGrfObj().GetGraphic().getSvgData();
425 
426         if ( rSvgDataPtr.get() )
427         {
428             const_cast< SwGrfNode* >( this )->mpReplacementGraphic = new GraphicObject( rSvgDataPtr->getReplacement() );
429         }
430     }
431 
432     return mpReplacementGraphic;
433 }
434 
435 SwCntntNode *SwGrfNode::SplitCntntNode(
436     const SwPosition & )
437 {
438     return this;
439 }
440 
441 SwGrfNode * SwNodes::MakeGrfNode(
442     const SwNodeIndex & rWhere,
443     const String& rGrfName,
444     const String& rFltName,
445     const Graphic* pGraphic,
446     SwGrfFmtColl* pGrfColl,
447     SwAttrSet* pAutoAttr,
448     sal_Bool bDelayed )
449 {
450     ASSERT( pGrfColl, "MakeGrfNode: Formatpointer ist 0." );
451     SwGrfNode *pNode;
452     // Delayed erzeugen nur aus dem SW/G-Reader
453     if ( bDelayed )
454         pNode = new SwGrfNode( rWhere, rGrfName,
455             rFltName, pGrfColl, pAutoAttr );
456     else
457         pNode = new SwGrfNode( rWhere, rGrfName,
458             rFltName, pGraphic, pGrfColl, pAutoAttr );
459     return pNode;
460 }
461 
462 SwGrfNode * SwNodes::MakeGrfNode(
463     const SwNodeIndex & rWhere,
464     const GraphicObject& rGrfObj,
465     SwGrfFmtColl* pGrfColl,
466     SwAttrSet* pAutoAttr )
467 {
468     ASSERT( pGrfColl, "MakeGrfNode: Formatpointer ist 0." );
469     return new SwGrfNode( rWhere, rGrfObj, pGrfColl, pAutoAttr );
470 }
471 
472 Size SwGrfNode::GetTwipSize() const
473 {
474     return nGrfSize;
475 }
476 
477 sal_Bool SwGrfNode::ImportGraphic(
478     SvStream& rStrm )
479 {
480     Graphic aGraphic;
481     const String aURL( maGrfObj.GetUserData() );
482 
483     if ( !GraphicFilter::GetGraphicFilter()->ImportGraphic( aGraphic, aURL, rStrm ) )
484     {
485         delete mpReplacementGraphic;
486         mpReplacementGraphic = 0;
487 
488         maGrfObj.SetGraphic( aGraphic );
489         maGrfObj.SetUserData( aURL );
490         onGraphicChanged();
491         return sal_True;
492     }
493 
494     return sal_False;
495 }
496 
497 // Returnwert:
498 // -1 : ReRead erfolgreich
499 //  0 : nicht geladen
500 //  1 : Einlesen erfolgreich
501 
502 short SwGrfNode::SwapIn(
503     sal_Bool bWaitForData )
504 {
505     if ( bInSwapIn )					// nicht rekuriv!!
506         return !maGrfObj.IsSwappedOut();
507 
508     short nRet = 0;
509     bInSwapIn = sal_True;
510     SwBaseLink* pLink = (SwBaseLink*) (::sfx2::SvBaseLink*) refLink;
511 
512     if ( pLink )
513     {
514         if ( GRAPHIC_NONE == maGrfObj.GetType() ||
515              GRAPHIC_DEFAULT == maGrfObj.GetType() )
516         {
517             // noch nicht geladener Link
518             //TODO pLink->setInputStream(getInputStream());
519             if ( pLink->SwapIn( bWaitForData ) )
520                 nRet = -1;
521             else if ( GRAPHIC_DEFAULT == maGrfObj.GetType() )
522             {
523                 // keine default Bitmap mehr, also neu Painten!
524                 delete mpReplacementGraphic;
525                 mpReplacementGraphic = 0;
526 
527                 maGrfObj.SetGraphic( Graphic() );
528                 onGraphicChanged();
529                 SwMsgPoolItem aMsgHint( RES_GRAPHIC_PIECE_ARRIVED );
530                 ModifyNotification( &aMsgHint, &aMsgHint );
531             }
532         }
533         else if ( maGrfObj.IsSwappedOut() )
534         {
535             // nachzuladender Link
536             //TODO pLink->setInputStream(getInputStream());
537             nRet = pLink->SwapIn( bWaitForData ) ? 1 : 0;
538         }
539         else
540             nRet = 1;
541     }
542     else if ( maGrfObj.IsSwappedOut() )
543     {
544         // Die Grafik ist im Storage oder im TempFile drin
545         if ( !HasEmbeddedStreamName() )
546             nRet = (short) maGrfObj.SwapIn();
547         else
548         {
549 
550             try
551             {
552                 String aStrmName, aPicStgName;
553                 _GetStreamStorageNames( aStrmName, aPicStgName );
554                 uno::Reference< embed::XStorage > refPics = _GetDocSubstorageOrRoot( aPicStgName );
555                 SvStream* pStrm = _GetStreamForEmbedGrf( refPics, aStrmName );
556                 if ( pStrm )
557                 {
558                     if ( ImportGraphic( *pStrm ) )
559                         nRet = 1;
560                     delete pStrm;
561                 }
562             }
563             catch ( uno::Exception& )
564             {
565                 ASSERT( false, "<SwGrfNode::SwapIn(..)> - unhandled exception!" );
566             }
567         }
568 
569         if ( 1 == nRet )
570         {
571             SwMsgPoolItem aMsg( RES_GRAPHIC_SWAPIN );
572             ModifyNotification( &aMsg, &aMsg );
573         }
574     }
575     else
576         nRet = 1;
577     DBG_ASSERTWARNING( nRet, "Grafik kann nicht eingeswapt werden" );
578 
579     if ( nRet )
580     {
581         if ( !nGrfSize.Width() && !nGrfSize.Height() )
582             SetTwipSize( ::GetGraphicSizeTwip( maGrfObj.GetGraphic(), 0 ) );
583     }
584     bInSwapIn = sal_False;
585     return nRet;
586 }
587 
588 short SwGrfNode::SwapOut()
589 {
590     if ( maGrfObj.GetType() != GRAPHIC_DEFAULT
591          && maGrfObj.GetType() != GRAPHIC_NONE
592          && !maGrfObj.IsSwappedOut()
593          && !bInSwapIn )
594     {
595         if ( !refLink.Is() )
596         {
597             // Das Swapping brauchen wir nur fuer Embedded Pictures
598             // Die Grafik wird in eine TempFile geschrieben, wenn
599             // sie frisch eingefuegt war, d.h. wenn es noch keinen
600             // Streamnamen im Storage gibt.
601             if ( !HasEmbeddedStreamName() )
602                 if ( !maGrfObj.SwapOut() )
603                     return 0;
604         }
605         // Geschriebene Grafiken oder Links werden jetzt weggeschmissen
606         return (short) maGrfObj.SwapOut( NULL );
607     }
608     return 1;
609 }
610 
611 sal_Bool SwGrfNode::GetFileFilterNms(
612     String* pFileNm,
613     String* pFilterNm ) const
614     {
615     sal_Bool bRet = sal_False;
616     if ( refLink.Is() && refLink->GetLinkManager() )
617     {
618         sal_uInt16 nType = refLink->GetObjType();
619         if ( OBJECT_CLIENT_GRF == nType )
620             bRet = refLink->GetLinkManager()->GetDisplayNames(
621                 refLink, 0, pFileNm, 0, pFilterNm );
622         else if ( OBJECT_CLIENT_DDE == nType && pFileNm && pFilterNm )
623         {
624             String sApp, sTopic, sItem;
625             if ( refLink->GetLinkManager()->GetDisplayNames(
626                 refLink, &sApp, &sTopic, &sItem ) )
627             {
628                 ( *pFileNm = sApp ) += sfx2::cTokenSeperator;
629                 ( *pFileNm += sTopic ) += sfx2::cTokenSeperator;
630                 *pFileNm += sItem;
631                 pFilterNm->AssignAscii( RTL_CONSTASCII_STRINGPARAM( "DDE" ) );
632                 bRet = sal_True;
633             }
634         }
635     }
636     return bRet;
637 }
638 
639 // Eine Grafik Undo-faehig machen. Falls sie sich bereits in
640 // einem Storage befindet, muss sie geladen werden.
641 
642 sal_Bool SwGrfNode::SavePersistentData()
643 {
644     if ( refLink.Is() )
645     {
646         ASSERT( !bInSwapIn, "SavePersistentData: stehe noch im SwapIn" );
647         GetDoc()->GetLinkManager().Remove( refLink );
648         return sal_True;
649     }
650 
651     // Erst mal reinswappen, falls sie im Storage ist
652     if ( HasEmbeddedStreamName() && !SwapIn() )
653         return sal_False;
654 
655     // #i44367#
656     // Do not delete graphic file in storage, because the graphic file could
657     // be referenced by other graphic nodes.
658     // Because it's hard to detect this case here and it would only fix
659     // one problem with shared graphic files - there are also problems,
660     // a certain graphic file is referenced by two independent graphic nodes,
661     // brush item or drawing objects, the stream isn't no longer removed here.
662     // To do this stuff correct, a reference counting on shared streams
663     // inside one document have to be implemented.
664     // Important note: see also fix for #i40014#
665 //    if( HasStreamName() )
666 //        DelStreamName();
667 
668     // Und in TempFile rausswappen
669     return (sal_Bool) SwapOut();
670 }
671 
672 sal_Bool SwGrfNode::RestorePersistentData()
673 {
674     if ( refLink.Is() )
675     {
676         IDocumentLinksAdministration* pIDLA = getIDocumentLinksAdministration();
677         refLink->SetVisible( pIDLA->IsVisibleLinks() );
678         pIDLA->GetLinkManager().InsertDDELink( refLink );
679         if ( getIDocumentLayoutAccess()->GetCurrentLayout() )
680             refLink->Update();
681     }
682     return sal_True;
683 }
684 
685 void SwGrfNode::InsertLink(
686     const String& rGrfName,
687     const String& rFltName )
688 {
689     refLink = new SwBaseLink( sfx2::LINKUPDATE_ONCALL, FORMAT_GDIMETAFILE, this );
690 
691     IDocumentLinksAdministration* pIDLA = getIDocumentLinksAdministration();
692     if ( GetNodes().IsDocNodes() )
693     {
694         refLink->SetVisible( pIDLA->IsVisibleLinks() );
695         if ( rFltName.EqualsAscii( "DDE" ) )
696         {
697             sal_uInt16 nTmp = 0;
698             String sApp, sTopic, sItem;
699             sApp = rGrfName.GetToken( 0, sfx2::cTokenSeperator, nTmp );
700             sTopic = rGrfName.GetToken( 0, sfx2::cTokenSeperator, nTmp );
701             sItem = rGrfName.Copy( nTmp );
702             pIDLA->GetLinkManager().InsertDDELink( refLink,
703                 sApp, sTopic, sItem );
704         }
705         else
706         {
707             sal_Bool bSync = rFltName.EqualsAscii( "SYNCHRON" );
708             refLink->SetSynchron( bSync );
709             refLink->SetContentType( SOT_FORMATSTR_ID_SVXB );
710 
711             pIDLA->GetLinkManager().InsertFileLink( *refLink,
712             OBJECT_CLIENT_GRF, rGrfName,
713                 ( !bSync && rFltName.Len() ? &rFltName : 0 ) );
714         }
715     }
716     maGrfObj.SetLink( rGrfName );
717 }
718 
719 void SwGrfNode::ReleaseLink()
720 {
721     if ( refLink.Is() )
722     {
723         const String aFileName( maGrfObj.GetLink() );
724         const Graphic aLocalGraphic( maGrfObj.GetGraphic() );
725         const bool bHasOriginalData( aLocalGraphic.IsLink() );
726 
727         {
728             bInSwapIn = sal_True;
729             SwBaseLink* pLink = (SwBaseLink*) (::sfx2::SvBaseLink*) refLink;
730             //TODO pLink->setInputStream(getInputStream());
731             pLink->SwapIn( sal_True, sal_True );
732             bInSwapIn = sal_False;
733         }
734 
735         getIDocumentLinksAdministration()->GetLinkManager().Remove( refLink );
736         refLink.Clear();
737         maGrfObj.SetLink();
738 
739         // #15508# added extra processing after getting rid of the link. Use whatever is
740         // known from the formally linked graphic to get to a state as close to a directly
741         // unlinked insterted graphic as possible. Goal is to have a valid GfxLink at the
742         // ImplGraphic (see there) that holds temporary data to the original data and type
743         // information about the original data. Only when this is given will
744         // SvXMLGraphicHelper::ImplInsertGraphicURL which is used at export use that type
745         // and use the original graphic at export for the ODF, without evtl. recoding
746         // of trhe bitmap graphic data to something without loss (e.g. PNG) but bigger
747         if ( bHasOriginalData )
748         {
749             // #15508# if we have the original data at the Graphic, let it survive
750             // by using that Graphic again, this time at a GraphicObject without link.
751             // This happens e.g. when inserting a linked graphic and breaking the link
752             maGrfObj.SetGraphic( aLocalGraphic );
753         }
754         else if ( aFileName.Len() )
755         {
756             // #15508# we have no original data, but a file name. This happens e.g.
757             // when inserting a linked graphic and save, reload document. Try to access
758             // that data from the original file; if this works, use it. Else use the
759             // data we have (but without knowing the original format)
760             int nRes = GRFILTER_OK;
761             GraphicFilter* pFlt = GraphicFilter::GetGraphicFilter();
762             Graphic aNew;
763             nRes = GraphicFilter::LoadGraphic( aFileName, String(), aNew, pFlt );
764 
765             if ( GRFILTER_OK == nRes )
766             {
767                 maGrfObj.SetGraphic( aNew );
768             }
769         }
770     }
771 }
772 
773 void SwGrfNode::SetTwipSize(
774     const Size& rSz )
775 {
776     nGrfSize = rSz;
777     if ( IsScaleImageMap() && nGrfSize.Width() && nGrfSize.Height() )
778     {
779         // Image-Map an Grafik-Groesse anpassen
780         ScaleImageMap();
781 
782         // Image-Map nicht noch einmal skalieren
783         SetScaleImageMap( sal_False );
784     }
785 }
786 
787 void SwGrfNode::ScaleImageMap()
788 {
789     if ( !nGrfSize.Width() || !nGrfSize.Height() )
790         return;
791 
792     // dann die Image-Map skalieren
793     SwFrmFmt* pFmt = GetFlyFmt();
794 
795     if ( !pFmt )
796         return;
797 
798     SwFmtURL aURL( pFmt->GetURL() );
799     if ( !aURL.GetMap() )
800         return;
801 
802     sal_Bool bScale = sal_False;
803     Fraction aScaleX( 1, 1 );
804     Fraction aScaleY( 1, 1 );
805 
806     const SwFmtFrmSize& rFrmSize = pFmt->GetFrmSize();
807     const SvxBoxItem& rBox = pFmt->GetBox();
808 
809     if ( !rFrmSize.GetWidthPercent() )
810     {
811         SwTwips nWidth = rFrmSize.GetWidth();
812 
813         nWidth -= rBox.CalcLineSpace( BOX_LINE_LEFT ) +
814                   rBox.CalcLineSpace( BOX_LINE_RIGHT );
815 
816         ASSERT( nWidth>0, "Gibt es 0 twip breite Grafiken!?" );
817 
818         if ( nGrfSize.Width() != nWidth )
819         {
820             aScaleX = Fraction( nGrfSize.Width(), nWidth );
821             bScale = sal_True;
822         }
823     }
824     if ( !rFrmSize.GetHeightPercent() )
825     {
826         SwTwips nHeight = rFrmSize.GetHeight();
827 
828         nHeight -= rBox.CalcLineSpace( BOX_LINE_TOP ) +
829                    rBox.CalcLineSpace( BOX_LINE_BOTTOM );
830 
831         ASSERT( nHeight>0, "Gibt es 0 twip hohe Grafiken!?" );
832 
833         if ( nGrfSize.Height() != nHeight )
834         {
835             aScaleY = Fraction( nGrfSize.Height(), nHeight );
836             bScale = sal_True;
837         }
838     }
839 
840     if ( bScale )
841     {
842         aURL.GetMap()->Scale( aScaleX, aScaleY );
843         pFmt->SetFmtAttr( aURL );
844     }
845 }
846 
847 void SwGrfNode::DelStreamName()
848 {
849     if ( HasEmbeddedStreamName() )
850     {
851         // Dann die Grafik im Storage loeschen
852         uno::Reference< embed::XStorage > xDocStg = GetDoc()->GetDocStorage();
853         if ( xDocStg.is() )
854         {
855             try
856             {
857                 String aPicStgName, aStrmName;
858                 _GetStreamStorageNames( aStrmName, aPicStgName );
859                 uno::Reference< embed::XStorage > refPics = xDocStg;
860                 if ( aPicStgName.Len() )
861                     refPics = xDocStg->openStorageElement( aPicStgName, embed::ElementModes::READWRITE );
862                 refPics->removeElement( aStrmName );
863                 uno::Reference< embed::XTransactedObject > xTrans( refPics, uno::UNO_QUERY );
864                 if ( xTrans.is() )
865                     xTrans->commit();
866             }
867             catch ( uno::Exception& )
868             {
869                 // --> OD 2005-04-25 #i48434#
870                 ASSERT( false, "<SwGrfNode::DelStreamName()> - unhandled exception!" );
871                 // <--
872             }
873         }
874 
875         maGrfObj.SetUserData();
876     }
877 }
878 
879 /** helper method to get a substorage of the document storage for readonly access.
880 
881  #i53025#
882  A substorage with the specified name will be opened readonly. If the provided
883  name is empty the root storage will be returned.
884  */
885 uno::Reference< embed::XStorage > SwGrfNode::_GetDocSubstorageOrRoot(
886     const String& aStgName ) const
887     {
888     uno::Reference< embed::XStorage > refStor =
889             const_cast< SwGrfNode* >( this )->GetDoc()->GetDocStorage();
890     ASSERT( refStor.is(), "Kein Storage am Doc" );
891 
892     if ( aStgName.Len() )
893     {
894         if ( refStor.is() )
895             return refStor->openStorageElement( aStgName, embed::ElementModes::READ );
896     }
897 
898     return refStor;
899 }
900 
901 /** helper method to determine stream for the embedded graphic.
902 
903  #i48434#
904  Important note: caller of this method has to handle the thrown exceptions
905  #i53025#
906  Storage, which should contain the stream of the embedded graphic, is
907  provided via parameter. Otherwise the returned stream will be closed
908  after the the method returns, because its parent stream is closed and deleted.
909  Proposed name of embedded graphic stream is also provided by parameter.
910 
911  @author OD
912  */
913 SvStream* SwGrfNode::_GetStreamForEmbedGrf(
914     const uno::Reference< embed::XStorage >& _refPics,
915     String& _aStrmName ) const
916     {
917     SvStream* pStrm( 0L );
918 
919     if ( _refPics.is() && _aStrmName.Len() )
920     {
921         // If stream doesn't exist in the storage, try access the graphic file by
922         // re-generating its name.
923         // A save action can have changed the filename of the embedded graphic,
924         // because a changed unique ID of the graphic is calculated.
925         // #b6364738#
926         // recursive calls of <GetUniqueID()> have to be avoided.
927         // Thus, use local static boolean to assure this.
928         static bool bInRegenerateStrmName( false );
929         if ( !bInRegenerateStrmName &&
930              ( !_refPics->hasByName( _aStrmName ) ||
931                !_refPics->isStreamElement( _aStrmName ) ) )
932         {
933             bInRegenerateStrmName = true;
934             xub_StrLen nExtPos = _aStrmName.Search( '.' );
935             String aExtStr = _aStrmName.Copy( nExtPos );
936             Graphic aGraphic( GetGrfObj().GetGraphic() );
937             if ( aGraphic.GetType() != GRAPHIC_NONE )
938             {
939                 _aStrmName = String( GetGrfObj().GetUniqueID(), RTL_TEXTENCODING_ASCII_US );
940                 _aStrmName += aExtStr;
941             }
942             bInRegenerateStrmName = false;
943         }
944 
945         // assure that graphic file exist in the storage.
946         if ( _refPics->hasByName( _aStrmName ) &&
947              _refPics->isStreamElement( _aStrmName ) )
948         {
949             uno::Reference< io::XStream > refStrm = _refPics->openStreamElement( _aStrmName, embed::ElementModes::READ );
950             pStrm = utl::UcbStreamHelper::CreateStream( refStrm );
951         }
952         else
953         {
954             ASSERT( false, "<SwGrfNode::_GetStreamForEmbedGrf(..)> - embedded graphic file not found!" );
955         }
956     }
957 
958     return pStrm;
959 }
960 
961 
962 void SwGrfNode::_GetStreamStorageNames(
963     String& rStrmName,
964     String& rStorName ) const
965     {
966     rStorName.Erase();
967     rStrmName.Erase();
968 
969     String aUserData( maGrfObj.GetUserData() );
970     if ( !aUserData.Len() )
971         return;
972 
973     String aProt( RTL_CONSTASCII_STRINGPARAM( "vnd.sun.star.Package:" ) );
974     if ( 0 == aUserData.CompareTo( aProt, aProt.Len() ) )
975     {
976         // 6.0 (XML) Package
977         xub_StrLen nPos = aUserData.Search( '/' );
978         if ( STRING_NOTFOUND == nPos )
979         {
980             rStrmName = aUserData.Copy( aProt.Len() );
981         }
982         else
983         {
984             xub_StrLen nPathStart = aProt.Len();
985             if ( 0 == aUserData.CompareToAscii( "./", 2 ) )
986                 nPathStart += 2;
987             rStorName = aUserData.Copy( nPathStart, nPos - nPathStart );
988             rStrmName = aUserData.Copy( nPos + 1 );
989         }
990     }
991     else
992     {
993         ASSERT( false,
994             "<SwGrfNode::_GetStreamStorageNames(..)> - unknown graphic URL type. Code for handling 3.1 - 5.2 storages has been deleted by issue i53025." );
995     }
996     ASSERT( STRING_NOTFOUND == rStrmName.Search( '/' ),
997         "invalid graphic stream name" );
998 }
999 
1000 
1001 SwCntntNode* SwGrfNode::MakeCopy(
1002     SwDoc* pDoc,
1003     const SwNodeIndex& rIdx ) const
1004     {
1005     // kopiere die Formate in das andere Dokument:
1006     SwGrfFmtColl* pColl = pDoc->CopyGrfColl( *GetGrfColl() );
1007 
1008     Graphic aTmpGrf;
1009     SwBaseLink* pLink = (SwBaseLink*) (::sfx2::SvBaseLink*) refLink;
1010     if ( !pLink && HasEmbeddedStreamName() )
1011     {
1012         try
1013         {
1014             String aStrmName, aPicStgName;
1015             _GetStreamStorageNames( aStrmName, aPicStgName );
1016             uno::Reference< embed::XStorage > refPics = _GetDocSubstorageOrRoot( aPicStgName );
1017             SvStream* pStrm = _GetStreamForEmbedGrf( refPics, aStrmName );
1018             if ( pStrm )
1019             {
1020                 const String aURL( maGrfObj.GetUserData() );
1021                 GraphicFilter::GetGraphicFilter()->ImportGraphic( aTmpGrf, aURL, *pStrm );
1022                 delete pStrm;
1023             }
1024         }
1025         catch ( uno::Exception& )
1026         {
1027             ASSERT( false, "<SwGrfNode::MakeCopy(..)> - unhandled exception!" );
1028         }
1029     }
1030     else
1031     {
1032         if ( maGrfObj.IsSwappedOut() )
1033             const_cast< SwGrfNode* >( this )->SwapIn();
1034         aTmpGrf = maGrfObj.GetGraphic();
1035     }
1036 
1037     const sfx2::LinkManager& rMgr = getIDocumentLinksAdministration()->GetLinkManager();
1038     String sFile, sFilter;
1039     if ( IsLinkedFile() )
1040         rMgr.GetDisplayNames( refLink, 0, &sFile, 0, &sFilter );
1041     else if ( IsLinkedDDE() )
1042     {
1043         String sTmp1, sTmp2;
1044         rMgr.GetDisplayNames( refLink, &sTmp1, &sTmp2, &sFilter );
1045         sfx2::MakeLnkName( sFile, &sTmp1, sTmp2, sFilter );
1046         sFilter.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "DDE" ) );
1047     }
1048 
1049     SwGrfNode* pGrfNd = pDoc->GetNodes().MakeGrfNode( rIdx, sFile, sFilter,
1050         &aTmpGrf, pColl,
1051         (SwAttrSet*) GetpSwAttrSet() );
1052     pGrfNd->SetTitle( GetTitle() );
1053     pGrfNd->SetDescription( GetDescription() );
1054     pGrfNd->SetContour( HasContour(), HasAutomaticContour() );
1055     return pGrfNd;
1056 }
1057 
1058 IMPL_LINK( SwGrfNode, SwapGraphic, GraphicObject*, pGrfObj )
1059 {
1060     SvStream* pRet;
1061 
1062     // #101174#: Keep graphic while in swap in. That's at least important
1063     // when breaking links, because in this situation a reschedule call and
1064     // a DataChanged call lead to a paint of the graphic.
1065     if ( pGrfObj->IsInSwapOut() && ( IsSelected() || bInSwapIn ) )
1066         pRet = GRFMGR_AUTOSWAPSTREAM_NONE;
1067     else if ( refLink.Is() )
1068     {
1069         if ( pGrfObj->IsInSwapIn() )
1070         {
1071             // then make it by your self
1072             if ( !bInSwapIn )
1073             {
1074                 sal_Bool bIsModifyLocked = IsModifyLocked();
1075                 LockModify();
1076                 SwapIn( sal_False );
1077                 if ( !bIsModifyLocked )
1078                     UnlockModify();
1079             }
1080             pRet = GRFMGR_AUTOSWAPSTREAM_NONE;
1081         }
1082         else
1083             pRet = GRFMGR_AUTOSWAPSTREAM_LINK;
1084     }
1085     else
1086     {
1087         pRet = GRFMGR_AUTOSWAPSTREAM_TEMP;
1088 
1089         if ( HasEmbeddedStreamName() )
1090         {
1091             try
1092             {
1093                 String aStrmName, aPicStgName;
1094                 _GetStreamStorageNames( aStrmName, aPicStgName );
1095                 uno::Reference< embed::XStorage > refPics = _GetDocSubstorageOrRoot( aPicStgName );
1096                 SvStream* pStrm = _GetStreamForEmbedGrf( refPics, aStrmName );
1097                 if ( pStrm )
1098                 {
1099                     if ( pGrfObj->IsInSwapOut() )
1100                     {
1101                         pRet = GRFMGR_AUTOSWAPSTREAM_LINK;
1102                     }
1103                     else
1104                     {
1105                         ImportGraphic( *pStrm );
1106                         pRet = GRFMGR_AUTOSWAPSTREAM_LOADED;
1107                     }
1108                     delete pStrm;
1109                 }
1110             }
1111             catch ( uno::Exception& )
1112             {
1113                 ASSERT( false, "<SwapGraphic> - unhandled exception!" );
1114             }
1115         }
1116     }
1117 
1118     return (long) pRet;
1119 }
1120 
1121 // alle QuickDraw-Bitmaps eines speziellen Docs loeschen
1122 void DelAllGrfCacheEntries(
1123     SwDoc* pDoc )
1124 {
1125     if ( pDoc )
1126     {
1127         // alle Graphic-Links mit dem Namen aus dem Cache loeschen
1128         const sfx2::LinkManager& rLnkMgr = pDoc->GetLinkManager();
1129         const ::sfx2::SvBaseLinks& rLnks = rLnkMgr.GetLinks();
1130         SwGrfNode* pGrfNd;
1131         String sFileNm;
1132         for ( sal_uInt16 n = rLnks.Count(); n; )
1133         {
1134             ::sfx2::SvBaseLink* pLnk = &( *rLnks[--n] );
1135             if ( pLnk && OBJECT_CLIENT_GRF == pLnk->GetObjType()
1136                  && rLnkMgr.GetDisplayNames( pLnk, 0, &sFileNm )
1137                  && pLnk->ISA( SwBaseLink )
1138                  && 0 != ( pGrfNd = ( (SwBaseLink*) pLnk )->GetCntntNode()->GetGrfNode() ) )
1139             {
1140                 pGrfNd->ReleaseGraphicFromCache();
1141             }
1142         }
1143     }
1144 }
1145 
1146 // returns the with our graphic attributes filled Graphic-Attr-Structure
1147 GraphicAttr& SwGrfNode::GetGraphicAttr(
1148     GraphicAttr& rGA,
1149     const SwFrm* pFrm ) const
1150     {
1151     const SwAttrSet& rSet = GetSwAttrSet();
1152 
1153     rGA.SetDrawMode( (GraphicDrawMode) rSet.GetDrawModeGrf().GetValue() );
1154 
1155     const SwMirrorGrf & rMirror = rSet.GetMirrorGrf();
1156     sal_uLong nMirror = BMP_MIRROR_NONE;
1157     if ( rMirror.IsGrfToggle() && pFrm && !pFrm->FindPageFrm()->OnRightPage() )
1158     {
1159         switch (rMirror.GetValue())
1160         {
1161         case RES_MIRROR_GRAPH_DONT:
1162             nMirror = BMP_MIRROR_HORZ;
1163             break;
1164         case RES_MIRROR_GRAPH_VERT:
1165             nMirror = BMP_MIRROR_NONE;
1166             break;
1167         case RES_MIRROR_GRAPH_HOR:
1168             nMirror = BMP_MIRROR_HORZ | BMP_MIRROR_VERT;
1169             break;
1170         default:
1171             nMirror = BMP_MIRROR_VERT;
1172             break;
1173         }
1174     }
1175     else
1176         switch (rMirror.GetValue())
1177         {
1178         case RES_MIRROR_GRAPH_BOTH:
1179             nMirror = BMP_MIRROR_HORZ | BMP_MIRROR_VERT;
1180             break;
1181         case RES_MIRROR_GRAPH_VERT:
1182             nMirror = BMP_MIRROR_HORZ;
1183             break;
1184         case RES_MIRROR_GRAPH_HOR:
1185             nMirror = BMP_MIRROR_VERT;
1186             break;
1187         }
1188 
1189     rGA.SetMirrorFlags( nMirror );
1190 
1191     const SwCropGrf& rCrop = rSet.GetCropGrf();
1192     rGA.SetCrop( TWIP_TO_MM100( rCrop.GetLeft() ),
1193         TWIP_TO_MM100( rCrop.GetTop() ),
1194         TWIP_TO_MM100( rCrop.GetRight() ),
1195         TWIP_TO_MM100( rCrop.GetBottom() ) );
1196 
1197     const SwRotationGrf& rRotation = rSet.GetRotationGrf();
1198     rGA.SetRotation( rRotation.GetValue() );
1199 
1200     rGA.SetLuminance( rSet.GetLuminanceGrf().GetValue() );
1201     rGA.SetContrast( rSet.GetContrastGrf().GetValue() );
1202     rGA.SetChannelR( rSet.GetChannelRGrf().GetValue() );
1203     rGA.SetChannelG( rSet.GetChannelGGrf().GetValue() );
1204     rGA.SetChannelB( rSet.GetChannelBGrf().GetValue() );
1205     rGA.SetGamma( rSet.GetGammaGrf().GetValue() );
1206     rGA.SetInvert( rSet.GetInvertGrf().GetValue() );
1207 
1208     const sal_uInt16 nTrans = rSet.GetTransparencyGrf().GetValue();
1209     rGA.SetTransparency( (sal_uInt8) FRound(
1210         Min( nTrans, (sal_uInt16) 100 ) * 2.55 ) );
1211 
1212     return rGA;
1213 }
1214 
1215 sal_Bool SwGrfNode::IsTransparent() const
1216 {
1217     sal_Bool bRet = maGrfObj.IsTransparent();
1218     if ( !bRet )	// ask the attribut
1219         bRet = 0 != GetSwAttrSet().GetTransparencyGrf().GetValue();
1220 
1221     return bRet;
1222 }
1223 
1224 sal_Bool SwGrfNode::IsSelected() const
1225 {
1226     sal_Bool bRet = sal_False;
1227     const SwEditShell* pESh = GetDoc()->GetEditShell();
1228     if ( pESh )
1229     {
1230         const SwNode* pN = this;
1231         const ViewShell* pV = pESh;
1232         do
1233         {
1234             if ( pV->ISA( SwEditShell ) && pN == &( (SwCrsrShell*) pV )
1235                                                    ->GetCrsr()->GetPoint()->nNode.GetNode() )
1236             {
1237                 bRet = sal_True;
1238                 break;
1239             }
1240         }
1241         while (pESh != ( pV = (ViewShell*) pV->GetNext() ));
1242     }
1243     return bRet;
1244 }
1245 
1246 boost::weak_ptr< SwAsyncRetrieveInputStreamThreadConsumer > SwGrfNode::GetThreadConsumer()
1247 {
1248     return mpThreadConsumer;
1249 }
1250 
1251 void SwGrfNode::TriggerAsyncRetrieveInputStream()
1252 {
1253     if ( !IsLinkedFile() )
1254     {
1255         ASSERT( false,
1256             "<SwGrfNode::TriggerAsyncLoad()> - Method is misused. Method call is only valid for graphic nodes, which refer a linked graphic file" );
1257         return;
1258     }
1259 
1260     if ( mpThreadConsumer.get() == 0 )
1261     {
1262         mpThreadConsumer.reset( new SwAsyncRetrieveInputStreamThreadConsumer( *this ) );
1263 
1264         String sGrfNm;
1265         refLink->GetLinkManager()->GetDisplayNames( refLink, 0, &sGrfNm, 0, 0 );
1266 
1267         mpThreadConsumer->CreateThread( sGrfNm );
1268     }
1269 }
1270 
1271 bool SwGrfNode::IsLinkedInputStreamReady() const
1272 {
1273     return mbLinkedInputStreamReady;
1274 }
1275 
1276 void SwGrfNode::ApplyInputStream(
1277     com::sun::star::uno::Reference< com::sun::star::io::XInputStream > xInputStream,
1278     const sal_Bool bIsStreamReadOnly )
1279 {
1280     if ( IsLinkedFile() )
1281     {
1282         if ( xInputStream.is() )
1283         {
1284             mxInputStream = xInputStream;
1285             mbIsStreamReadOnly = bIsStreamReadOnly;
1286             mbLinkedInputStreamReady = true;
1287             SwMsgPoolItem aMsgHint( RES_LINKED_GRAPHIC_STREAM_ARRIVED );
1288             ModifyNotification( &aMsgHint, &aMsgHint );
1289         }
1290     }
1291 }
1292 
1293 void SwGrfNode::UpdateLinkWithInputStream()
1294 {
1295     // do not work on link, if a <SwapIn> has been triggered.
1296     if ( !bInSwapIn && IsLinkedFile() )
1297     {
1298         GetLink()->setStreamToLoadFrom( mxInputStream, mbIsStreamReadOnly );
1299         GetLink()->Update();
1300         SwMsgPoolItem aMsgHint( RES_GRAPHIC_ARRIVED );
1301         ModifyNotification( &aMsgHint, &aMsgHint );
1302 
1303         mxInputStream.clear();
1304         GetLink()->clearStreamToLoadFrom();
1305         mbLinkedInputStreamReady = false;
1306         mpThreadConsumer.reset();
1307     }
1308 }
1309 
1310 
1311 bool SwGrfNode::IsAsyncRetrieveInputStreamPossible() const
1312 {
1313     bool bRet = false;
1314 
1315     if ( IsLinkedFile() )
1316     {
1317         String sGrfNm;
1318         refLink->GetLinkManager()->GetDisplayNames( refLink, 0, &sGrfNm, 0, 0 );
1319         String sProtocol( RTL_CONSTASCII_STRINGPARAM( "vnd.sun.star.pkg:" ) );
1320         if ( sGrfNm.CompareTo( sProtocol, sProtocol.Len() ) != 0 )
1321         {
1322             bRet = true;
1323         }
1324     }
1325 
1326     return bRet;
1327 }
1328