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 27 #include <hintids.hxx> 28 #include <vcl/svapp.hxx> 29 #include <vcl/outdev.hxx> 30 31 #include <osl/thread.hxx> 32 #include <salhelper/condition.hxx> 33 #include <comphelper/mediadescriptor.hxx> 34 #include <sfx2/docfile.hxx> 35 #include <sfx2/lnkbase.hxx> 36 #include <sfx2/linkmgr.hxx> 37 #include <sfx2/objsh.hxx> 38 #include <editeng/boxitem.hxx> 39 #ifndef _SVX_SVXIDS_HRC 40 #include <svx/svxids.hrc> // fuer die EventIds 41 #endif 42 #include <sfx2/linkmgr.hxx> 43 #include <svtools/soerr.hxx> 44 #include <fmtfsize.hxx> 45 #include <fmtanchr.hxx> 46 #include <frmatr.hxx> 47 #include <frmfmt.hxx> 48 #include <doc.hxx> 49 #include <pam.hxx> 50 #include <editsh.hxx> 51 #include <swtable.hxx> 52 #include <docary.hxx> 53 #include <swevent.hxx> 54 #include <swbaslnk.hxx> 55 #include <swserv.hxx> 56 #include <ndgrf.hxx> 57 #include <ndole.hxx> 58 #include <hints.hxx> 59 #include <tabfrm.hxx> 60 #include <cntfrm.hxx> 61 #include <htmltbl.hxx> 62 63 using namespace com::sun::star; 64 65 sal_Bool SetGrfFlySize( const Size& rGrfSz, const Size& rFrmSz, SwGrfNode* pGrfNd ); 66 67 TYPEINIT1( SwBaseLink, ::sfx2::SvBaseLink ); 68 69 SV_IMPL_REF( SwServerObject ) 70 71 void lcl_CallModify( SwGrfNode& rGrfNd, SfxPoolItem& rItem ) 72 { 73 //JP 4.7.2001: call fist all not SwNoTxtFrames, then the SwNoTxtFrames. 74 // The reason is, that in the SwNoTxtFrames the Graphic 75 // after a Paint will be swapped out! So all other "behind" 76 // them havent't a loaded Graphic. - #86501# 77 rGrfNd.LockModify(); 78 79 SwClientIter aIter( rGrfNd ); // TODO 80 for( int n = 0; n < 2; ++n ) 81 { 82 SwClient * pLast = aIter.GoStart(); 83 if( pLast ) // konnte zum Anfang gesprungen werden ?? 84 { 85 do { 86 if( (0 == n) ^ ( 0 != pLast->ISA( SwCntntFrm )) ) 87 pLast->ModifyNotification( &rItem, &rItem ); 88 } while( 0 != ( pLast = ++aIter )); 89 } 90 } 91 rGrfNd.UnlockModify(); 92 } 93 94 95 void SwBaseLink::DataChanged( const String& rMimeType, 96 const uno::Any & rValue ) 97 { 98 if( !pCntntNode ) 99 { 100 ASSERT(!this, "DataChanged ohne ContentNode" ); 101 return ; 102 } 103 104 SwDoc* pDoc = pCntntNode->GetDoc(); 105 if( pDoc->IsInDtor() || ChkNoDataFlag() || bIgnoreDataChanged ) 106 { 107 bIgnoreDataChanged = sal_False; 108 return ; 109 } 110 111 sal_uLong nFmt = SotExchange::GetFormatIdFromMimeType( rMimeType ); 112 113 if( pCntntNode->IsNoTxtNode() && 114 nFmt == sfx2::LinkManager::RegisterStatusInfoId() ) 115 { 116 // nur eine Statusaenderung - Events bedienen ? 117 ::rtl::OUString sState; 118 if( rValue.hasValue() && ( rValue >>= sState )) 119 { 120 sal_uInt16 nEvent = 0; 121 switch( sState.toInt32() ) 122 { 123 case sfx2::LinkManager::STATE_LOAD_OK: nEvent = SVX_EVENT_IMAGE_LOAD; break; 124 case sfx2::LinkManager::STATE_LOAD_ERROR: nEvent = SVX_EVENT_IMAGE_ERROR; break; 125 case sfx2::LinkManager::STATE_LOAD_ABORT: nEvent = SVX_EVENT_IMAGE_ABORT; break; 126 } 127 128 SwFrmFmt* pFmt; 129 if( nEvent && 0 != ( pFmt = pCntntNode->GetFlyFmt() )) 130 { 131 SwCallMouseEvent aCallEvent; 132 aCallEvent.Set( EVENT_OBJECT_IMAGE, pFmt ); 133 pDoc->CallEvent( nEvent, aCallEvent ); 134 } 135 } 136 return; // das wars! 137 } 138 139 sal_Bool bUpdate = sal_False; 140 sal_Bool bGraphicArrived = sal_False; 141 sal_Bool bGraphicPieceArrived = sal_False; 142 sal_Bool bDontNotify = sal_False; 143 Size aGrfSz, aFrmFmtSz; 144 145 if( pCntntNode->IsGrfNode() ) 146 { 147 SwGrfNode* pSwGrfNode = dynamic_cast< SwGrfNode* >(pCntntNode); 148 OSL_ENSURE(pSwGrfNode, "Error, pSwGrfNode expected when node answers IsGrfNode() with true (!)"); 149 const GraphicObject& rGrfObj = pSwGrfNode->GetGrfObj(); 150 151 bDontNotify = pSwGrfNode->IsFrameInPaint(); 152 153 bGraphicArrived = GetObj()->IsDataComplete(); 154 bGraphicPieceArrived = GetObj()->IsPending(); 155 pSwGrfNode->SetGrafikArrived( bGraphicArrived ); 156 157 Graphic aGrf; 158 if( sfx2::LinkManager::GetGraphicFromAny( rMimeType, rValue, aGrf ) && 159 ( GRAPHIC_DEFAULT != aGrf.GetType() || 160 GRAPHIC_DEFAULT != rGrfObj.GetType() ) ) 161 { 162 aGrfSz = ::GetGraphicSizeTwip( aGrf, 0 ); 163 if( pSwGrfNode->IsChgTwipSizeFromPixel() ) 164 { 165 const MapMode aMapTwip( MAP_TWIP ); 166 aFrmFmtSz = 167 Application::GetDefaultDevice()->PixelToLogic( 168 aGrf.GetSizePixel(), aMapTwip ); 169 170 } 171 else 172 { 173 aFrmFmtSz = aGrfSz; 174 } 175 Size aSz( pSwGrfNode->GetTwipSize() ); 176 177 if( bGraphicPieceArrived && GRAPHIC_DEFAULT != aGrf.GetType() && 178 ( !aSz.Width() || !aSz.Height() ) ) 179 { 180 // wenn nur ein Teil ankommt, aber die Groesse nicht 181 // gesetzt ist, dann muss "unten" der Teil von 182 // bGraphicArrived durchlaufen werden! 183 // (ansonten wird die Grafik in deft. Size gepaintet) 184 bGraphicArrived = sal_True; 185 bGraphicPieceArrived = sal_False; 186 } 187 188 pSwGrfNode->SetGraphic(aGrf, rGrfObj.GetLink()); 189 bUpdate = sal_True; 190 191 // Bug 33999: damit der Node den Transparent-Status 192 // richtig gesetzt hat, ohne auf die Grafik 193 // zugreifen zu muessen (sonst erfolgt ein SwapIn!). 194 if( bGraphicArrived ) 195 { 196 // Bug #34735#: immer mit der korrekten Grafik-Size 197 // arbeiten 198 if( aGrfSz.Height() && aGrfSz.Width() && 199 aSz.Height() && aSz.Width() && 200 aGrfSz != aSz ) 201 pSwGrfNode->SetTwipSize( aGrfSz ); 202 } 203 } 204 if ( bUpdate && !bGraphicArrived && !bGraphicPieceArrived ) 205 pSwGrfNode->SetTwipSize( Size(0,0) ); 206 } 207 else if( pCntntNode->IsOLENode() ) 208 bUpdate = sal_True; 209 210 ViewShell *pSh = 0; 211 SwEditShell* pESh = pDoc->GetEditShell( &pSh ); 212 213 if ( bUpdate && bGraphicPieceArrived && !(bSwapIn || bDontNotify) ) 214 { 215 //Hint ohne Actions verschicken, loest direktes Paint aus. 216 if ( (!pSh || !pSh->ActionPend()) && (!pESh || !pESh->ActionPend()) ) 217 { 218 SwMsgPoolItem aMsgHint( RES_GRAPHIC_PIECE_ARRIVED ); 219 pCntntNode->ModifyNotification( &aMsgHint, &aMsgHint ); 220 bUpdate = sal_False; 221 } 222 } 223 224 static sal_Bool bInNotifyLinks = sal_False; 225 if( bUpdate && !bDontNotify && (!bSwapIn || bGraphicArrived) && 226 !bInNotifyLinks) 227 { 228 sal_Bool bLockView = sal_False; 229 if( pSh ) 230 { 231 bLockView = pSh->IsViewLocked(); 232 pSh->LockView( sal_True ); 233 } 234 235 if( pESh ) 236 pESh->StartAllAction(); 237 else if( pSh ) 238 pSh->StartAction(); 239 240 SwMsgPoolItem aMsgHint( static_cast<sal_uInt16>( 241 bGraphicArrived ? RES_GRAPHIC_ARRIVED : RES_UPDATE_ATTR ) ); 242 243 if ( bGraphicArrived ) 244 { 245 //Alle benachrichtigen, die am gleichen Link horchen. 246 bInNotifyLinks = sal_True; 247 248 const ::sfx2::SvBaseLinks& rLnks = pDoc->GetLinkManager().GetLinks(); 249 for( sal_uInt16 n = rLnks.Count(); n; ) 250 { 251 ::sfx2::SvBaseLink* pLnk = &(*rLnks[ --n ]); 252 if( pLnk && OBJECT_CLIENT_GRF == pLnk->GetObjType() && 253 pLnk->ISA( SwBaseLink ) && pLnk->GetObj() == GetObj() ) 254 { 255 SwBaseLink* pBLink = (SwBaseLink*)pLnk; 256 SwGrfNode* pGrfNd = (SwGrfNode*)pBLink->pCntntNode; 257 258 if( pBLink != this && 259 ( !bSwapIn || 260 GRAPHIC_DEFAULT == pGrfNd->GetGrfObj().GetType())) 261 { 262 pBLink->bIgnoreDataChanged = sal_False; 263 pBLink->DataChanged( rMimeType, rValue ); 264 pBLink->bIgnoreDataChanged = sal_True; 265 266 pGrfNd->SetGrafikArrived( ((SwGrfNode*)pCntntNode)-> 267 IsGrafikArrived() ); 268 269 // Fly der Grafik anpassen ! 270 if( !::SetGrfFlySize( aGrfSz, aFrmFmtSz, pGrfNd ) ) 271 ::lcl_CallModify( *pGrfNd, aMsgHint ); 272 } 273 else if( pBLink == this && 274 !::SetGrfFlySize( aGrfSz, aFrmFmtSz, pGrfNd ) ) 275 // Fly der Grafik anpassen ! 276 ::lcl_CallModify( *pGrfNd, aMsgHint ); 277 } 278 } 279 280 bInNotifyLinks = sal_False; 281 } 282 else 283 { 284 pCntntNode->ModifyNotification( &aMsgHint, &aMsgHint ); 285 } 286 287 288 if( pESh ) 289 { 290 const sal_Bool bEndActionByVirDev = pESh->IsEndActionByVirDev(); 291 pESh->SetEndActionByVirDev( sal_True ); 292 pESh->EndAllAction(); 293 pESh->SetEndActionByVirDev( bEndActionByVirDev ); 294 } 295 else if( pSh ) 296 pSh->EndAction(); 297 298 if( pSh && !bLockView ) 299 pSh->LockView( sal_False ); 300 } 301 } 302 303 sal_Bool SetGrfFlySize( const Size& rGrfSz, const Size& rFrmSz, SwGrfNode* pGrfNd ) 304 { 305 sal_Bool bRet = sal_False; 306 ViewShell *pSh; 307 CurrShell *pCurr = 0; 308 if ( pGrfNd->GetDoc()->GetEditShell( &pSh ) ) 309 pCurr = new CurrShell( pSh ); 310 311 Size aSz = pGrfNd->GetTwipSize(); 312 if ( !(aSz.Width() && aSz.Height()) && 313 rGrfSz.Width() && rGrfSz.Height() ) 314 { 315 SwFrmFmt* pFmt; 316 if( pGrfNd->IsChgTwipSize() && 317 0 != (pFmt = pGrfNd->GetFlyFmt()) ) 318 { 319 Size aCalcSz( aSz ); 320 if ( !aSz.Height() && aSz.Width() ) 321 //passende Hoehe ausrechnen. 322 aCalcSz.Height() = rFrmSz.Height() * 323 aSz.Width() / rFrmSz.Width(); 324 else if ( !aSz.Width() && aSz.Height() ) 325 //passende Breite ausrechnen 326 aCalcSz.Width() = rFrmSz.Width() * 327 aSz.Height() / rFrmSz.Height(); 328 else 329 //Hoehe und Breite uebernehmen 330 aCalcSz = rFrmSz; 331 332 const SvxBoxItem &rBox = pFmt->GetBox(); 333 aCalcSz.Width() += rBox.CalcLineSpace(BOX_LINE_LEFT) + 334 rBox.CalcLineSpace(BOX_LINE_RIGHT); 335 aCalcSz.Height()+= rBox.CalcLineSpace(BOX_LINE_TOP) + 336 rBox.CalcLineSpace(BOX_LINE_BOTTOM); 337 const SwFmtFrmSize& rOldAttr = pFmt->GetFrmSize(); 338 if( rOldAttr.GetSize() != aCalcSz ) 339 { 340 SwFmtFrmSize aAttr( rOldAttr ); 341 aAttr.SetSize( aCalcSz ); 342 pFmt->SetFmtAttr( aAttr ); 343 bRet = sal_True; 344 } 345 346 if( !aSz.Width() ) 347 { 348 // Wenn die Grafik in einer Tabelle verankert ist, muess 349 // die Tabellen-Spalten neu berechnet werden 350 const SwDoc *pDoc = pGrfNd->GetDoc(); 351 const SwPosition* pAPos = pFmt->GetAnchor().GetCntntAnchor(); 352 SwNode *pANd; 353 SwTableNode *pTblNd; 354 if( pAPos && 355 0 != (pANd = & pAPos->nNode.GetNode()) && 356 0 != (pTblNd = pANd->FindTableNode()) ) 357 { 358 const sal_Bool bLastGrf = !pTblNd->GetTable().DecGrfsThatResize(); 359 SwHTMLTableLayout *pLayout = 360 pTblNd->GetTable().GetHTMLTableLayout(); 361 if( pLayout ) 362 { 363 const sal_uInt16 nBrowseWidth = 364 pLayout->GetBrowseWidthByTable( *pDoc ); 365 if ( nBrowseWidth ) 366 { 367 pLayout->Resize( nBrowseWidth, sal_True, sal_True, 368 bLastGrf ? HTMLTABLE_RESIZE_NOW 369 : 500 ); 370 } 371 } 372 } 373 } 374 } 375 376 // SetTwipSize skaliert ggf. eine ImageMap neu und 377 // braucht dazu das Frame-Format 378 pGrfNd->SetTwipSize( rGrfSz ); 379 } 380 381 delete pCurr; 382 383 return bRet; 384 } 385 386 387 sal_Bool SwBaseLink::SwapIn( sal_Bool bWaitForData, sal_Bool bNativFormat ) 388 { 389 bSwapIn = sal_True; 390 391 sal_Bool bRes; 392 393 if( !GetObj() && ( bNativFormat || ( !IsSynchron() && bWaitForData ) )) 394 { 395 AddNextRef(); 396 _GetRealObject(); 397 ReleaseRef(); 398 } 399 400 #if OSL_DEBUG_LEVEL > 1 401 { 402 String sGrfNm; 403 if(GetLinkManager()) 404 GetLinkManager()->GetDisplayNames( this, 0, &sGrfNm, 0, 0 ); 405 int x = 0; 406 ++x; 407 } 408 #endif 409 410 if( GetObj() ) 411 { 412 String aMimeType( SotExchange::GetFormatMimeType( GetContentType() )); 413 uno::Any aValue; 414 GetObj()->GetData( aValue, aMimeType, !IsSynchron() && bWaitForData ); 415 416 if( bWaitForData && !GetObj() ) 417 { 418 ASSERT( !this, "das SvxFileObject wurde in einem GetData geloescht!" ); 419 bRes = sal_False; 420 } 421 else if( 0 != ( bRes = aValue.hasValue() ) ) 422 { 423 //JP 14.04.99: Bug 64820 - das Flag muss beim SwapIn natuerlich 424 // zurueckgesetzt werden. Die Daten sollen ja neu 425 // uebernommen werden 426 bIgnoreDataChanged = sal_False; 427 DataChanged( aMimeType, aValue ); 428 } 429 } 430 else if( !IsSynchron() && bWaitForData ) 431 { 432 SetSynchron( sal_True ); 433 bRes = Update(); 434 SetSynchron( sal_False ); 435 } 436 else 437 bRes = Update(); 438 439 bSwapIn = sal_False; 440 return bRes; 441 } 442 443 void SwBaseLink::Closed() 444 { 445 if( pCntntNode && !pCntntNode->GetDoc()->IsInDtor() ) 446 { 447 // wir heben die Verbindung auf 448 if( pCntntNode->IsGrfNode() ) 449 ((SwGrfNode*)pCntntNode)->ReleaseLink(); 450 } 451 SvBaseLink::Closed(); 452 } 453 454 const SwNode* SwBaseLink::GetAnchor() const 455 { 456 if (pCntntNode) 457 { 458 SwFrmFmt *const pFmt = pCntntNode->GetFlyFmt(); 459 if (pFmt) 460 { 461 const SwFmtAnchor& rAnchor = pFmt->GetAnchor(); 462 SwPosition const*const pAPos = rAnchor.GetCntntAnchor(); 463 if (pAPos && 464 ((FLY_AS_CHAR == rAnchor.GetAnchorId()) || 465 (FLY_AT_CHAR == rAnchor.GetAnchorId()) || 466 (FLY_AT_FLY == rAnchor.GetAnchorId()) || 467 (FLY_AT_PARA == rAnchor.GetAnchorId()))) 468 { 469 return &pAPos->nNode.GetNode(); 470 } 471 return 0; 472 } 473 } 474 475 ASSERT( !this, "GetAnchor nicht ueberlagert" ); 476 return 0; 477 } 478 479 sal_Bool SwBaseLink::IsRecursion( const SwBaseLink* pChkLnk ) const 480 { 481 SwServerObjectRef aRef( (SwServerObject*)GetObj() ); 482 if( aRef.Is() ) 483 { 484 // es ist ein ServerObject, also frage nach allen darin 485 // befindlichen Links, ob wir darin enthalten sind. Ansonsten 486 // handelt es sich um eine Rekursion. 487 return aRef->IsLinkInServer( pChkLnk ); 488 } 489 return sal_False; 490 } 491 492 sal_Bool SwBaseLink::IsInRange( sal_uLong, sal_uLong, xub_StrLen, xub_StrLen ) const 493 { 494 // Grafik oder OLE-Links nicht, 495 // Felder oder Sections haben eigene Ableitung! 496 return sal_False; 497 } 498 499 SwBaseLink::~SwBaseLink() 500 { 501 } 502