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