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