diff options
Diffstat (limited to 'sw/source/core/docnode/swbaslnk.cxx')
-rw-r--r-- | sw/source/core/docnode/swbaslnk.cxx | 537 |
1 files changed, 537 insertions, 0 deletions
diff --git a/sw/source/core/docnode/swbaslnk.cxx b/sw/source/core/docnode/swbaslnk.cxx new file mode 100644 index 000000000000..6aaef5e5e962 --- /dev/null +++ b/sw/source/core/docnode/swbaslnk.cxx @@ -0,0 +1,537 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + +#include <hintids.hxx> +#include <vcl/svapp.hxx> +#include <vcl/outdev.hxx> + +#include <osl/thread.hxx> +#include <salhelper/condition.hxx> +#include <comphelper/mediadescriptor.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/lnkbase.hxx> +#include <sfx2/linkmgr.hxx> +#include <sfx2/objsh.hxx> +#include <editeng/boxitem.hxx> +#include <svx/svxids.hrc> // fuer die EventIds +#include <sfx2/linkmgr.hxx> +#include <svtools/soerr.hxx> +#include <fmtfsize.hxx> +#include <fmtanchr.hxx> +#include <frmatr.hxx> +#include <frmfmt.hxx> +#include <doc.hxx> +#include <pam.hxx> +#include <editsh.hxx> +#include <swtable.hxx> +#include <docary.hxx> +#include <swevent.hxx> +#include <swbaslnk.hxx> +#include <swserv.hxx> +#include <ndgrf.hxx> +#include <ndole.hxx> +#include <hints.hxx> +#include <tabfrm.hxx> +#include <cntfrm.hxx> +#include <htmltbl.hxx> + +using namespace com::sun::star; + +BOOL SetGrfFlySize( const Size& rGrfSz, const Size& rFrmSz, SwGrfNode* pGrfNd ); + +TYPEINIT1( SwBaseLink, ::sfx2::SvBaseLink ); + +SV_IMPL_REF( SwServerObject ) + +void lcl_CallModify( SwGrfNode& rGrfNd, SfxPoolItem& rItem ) +{ + //JP 4.7.2001: call fist all not SwNoTxtFrames, then the SwNoTxtFrames. + // The reason is, that in the SwNoTxtFrames the Graphic + // after a Paint will be swapped out! So all other "behind" + // them havent't a loaded Graphic. - #86501# + rGrfNd.LockModify(); + + SwClientIter aIter( rGrfNd ); + for( int n = 0; n < 2; ++n ) + { + SwClient * pLast = aIter.GoStart(); + if( pLast ) // konnte zum Anfang gesprungen werden ?? + { + do { + if( (0 == n) ^ ( 0 != pLast->ISA( SwCntntFrm )) ) + pLast->Modify( &rItem, &rItem ); + } while( 0 != ( pLast = aIter++ )); + } + } + rGrfNd.UnlockModify(); +} + + +void SwBaseLink::DataChanged( const String& rMimeType, + const uno::Any & rValue ) +{ + if( !pCntntNode ) + { + OSL_ENSURE(!this, "DataChanged ohne ContentNode" ); + return ; + } + + SwDoc* pDoc = pCntntNode->GetDoc(); + if( pDoc->IsInDtor() || ChkNoDataFlag() || bIgnoreDataChanged ) + { + bIgnoreDataChanged = FALSE; + return ; + } + + ULONG nFmt = SotExchange::GetFormatIdFromMimeType( rMimeType ); + + if( pCntntNode->IsNoTxtNode() && + nFmt == sfx2::LinkManager::RegisterStatusInfoId() ) + { + // nur eine Statusaenderung - Events bedienen ? + ::rtl::OUString sState; + if( rValue.hasValue() && ( rValue >>= sState )) + { + USHORT nEvent = 0; + switch( sState.toInt32() ) + { + case sfx2::LinkManager::STATE_LOAD_OK: nEvent = SVX_EVENT_IMAGE_LOAD; break; + case sfx2::LinkManager::STATE_LOAD_ERROR: nEvent = SVX_EVENT_IMAGE_ERROR; break; + case sfx2::LinkManager::STATE_LOAD_ABORT: nEvent = SVX_EVENT_IMAGE_ABORT; break; + } + + SwFrmFmt* pFmt; + if( nEvent && 0 != ( pFmt = pCntntNode->GetFlyFmt() )) + { + SwCallMouseEvent aCallEvent; + aCallEvent.Set( EVENT_OBJECT_IMAGE, pFmt ); + pDoc->CallEvent( nEvent, aCallEvent ); + } + } + return; // das wars! + } + + BOOL bUpdate = FALSE; + BOOL bGraphicArrived = FALSE; + BOOL bGraphicPieceArrived = FALSE; + BOOL bDontNotify = FALSE; + Size aGrfSz, aFrmFmtSz; + + if( pCntntNode->IsGrfNode() ) + { + GraphicObject& rGrfObj = ((SwGrfNode*)pCntntNode)->GetGrfObj(); + + bDontNotify = ((SwGrfNode*)pCntntNode)->IsFrameInPaint(); + + bGraphicArrived = GetObj()->IsDataComplete(); + bGraphicPieceArrived = GetObj()->IsPending(); + ((SwGrfNode*)pCntntNode)->SetGrafikArrived( bGraphicArrived ); + + Graphic aGrf; + if( sfx2::LinkManager::GetGraphicFromAny( rMimeType, rValue, aGrf ) && + ( GRAPHIC_DEFAULT != aGrf.GetType() || + GRAPHIC_DEFAULT != rGrfObj.GetType() ) ) + { + aGrfSz = ::GetGraphicSizeTwip( aGrf, 0 ); + if( static_cast< const SwGrfNode * >( pCntntNode )->IsChgTwipSizeFromPixel() ) + { + const MapMode aMapTwip( MAP_TWIP ); + aFrmFmtSz = + Application::GetDefaultDevice()->PixelToLogic( + aGrf.GetSizePixel(), aMapTwip ); + + } + else + { + aFrmFmtSz = aGrfSz; + } + Size aSz( ((SwGrfNode*)pCntntNode)->GetTwipSize() ); + + if( bGraphicPieceArrived && GRAPHIC_DEFAULT != aGrf.GetType() && + ( !aSz.Width() || !aSz.Height() ) ) + { + // wenn nur ein Teil ankommt, aber die Groesse nicht + // gesetzt ist, dann muss "unten" der Teil von + // bGraphicArrived durchlaufen werden! + // (ansonten wird die Grafik in deft. Size gepaintet) + bGraphicArrived = TRUE; + bGraphicPieceArrived = FALSE; + } + + rGrfObj.SetGraphic( aGrf, rGrfObj.GetLink() ); + bUpdate = TRUE; + + // Bug 33999: damit der Node den Transparent-Status + // richtig gesetzt hat, ohne auf die Grafik + // zugreifen zu muessen (sonst erfolgt ein SwapIn!). + if( bGraphicArrived ) + { + // Bug #34735#: immer mit der korrekten Grafik-Size + // arbeiten + if( aGrfSz.Height() && aGrfSz.Width() && + aSz.Height() && aSz.Width() && + aGrfSz != aSz ) + ((SwGrfNode*)pCntntNode)->SetTwipSize( aGrfSz ); + } + } + if ( bUpdate && !bGraphicArrived && !bGraphicPieceArrived ) + ((SwGrfNode*)pCntntNode)->SetTwipSize( Size(0,0) ); + } + else if( pCntntNode->IsOLENode() ) + bUpdate = TRUE; + + ViewShell *pSh = 0; + SwEditShell* pESh = pDoc->GetEditShell( &pSh ); + + if ( bUpdate && bGraphicPieceArrived && !(bSwapIn || bDontNotify) ) + { + //Hint ohne Actions verschicken, loest direktes Paint aus. + if ( (!pSh || !pSh->ActionPend()) && (!pESh || !pESh->ActionPend()) ) + { + SwMsgPoolItem aMsgHint( RES_GRAPHIC_PIECE_ARRIVED ); + pCntntNode->Modify( &aMsgHint, &aMsgHint ); + bUpdate = FALSE; + } + } + + static BOOL bInNotifyLinks = FALSE; + if( bUpdate && !bDontNotify && (!bSwapIn || bGraphicArrived) && + !bInNotifyLinks) + { + BOOL bLockView = FALSE; + if( pSh ) + { + bLockView = pSh->IsViewLocked(); + pSh->LockView( TRUE ); + } + + if( pESh ) + pESh->StartAllAction(); + else if( pSh ) + pSh->StartAction(); + + SwMsgPoolItem aMsgHint( static_cast<USHORT>( + bGraphicArrived ? RES_GRAPHIC_ARRIVED : RES_UPDATE_ATTR ) ); + + if ( bGraphicArrived ) + { + //Alle benachrichtigen, die am gleichen Link horchen. + bInNotifyLinks = TRUE; + + const ::sfx2::SvBaseLinks& rLnks = pDoc->GetLinkManager().GetLinks(); + for( USHORT n = rLnks.Count(); n; ) + { + ::sfx2::SvBaseLink* pLnk = &(*rLnks[ --n ]); + if( pLnk && OBJECT_CLIENT_GRF == pLnk->GetObjType() && + pLnk->ISA( SwBaseLink ) && pLnk->GetObj() == GetObj() ) + { + SwBaseLink* pBLink = (SwBaseLink*)pLnk; + SwGrfNode* pGrfNd = (SwGrfNode*)pBLink->pCntntNode; + + if( pBLink != this && + ( !bSwapIn || + GRAPHIC_DEFAULT == pGrfNd->GetGrfObj().GetType())) + { + pBLink->bIgnoreDataChanged = FALSE; + pBLink->DataChanged( rMimeType, rValue ); + pBLink->bIgnoreDataChanged = TRUE; + + pGrfNd->SetGrafikArrived( ((SwGrfNode*)pCntntNode)-> + IsGrafikArrived() ); + + // Fly der Grafik anpassen ! + if( !::SetGrfFlySize( aGrfSz, aFrmFmtSz, pGrfNd ) ) + ::lcl_CallModify( *pGrfNd, aMsgHint ); + } + else if( pBLink == this && + !::SetGrfFlySize( aGrfSz, aFrmFmtSz, pGrfNd ) ) + // Fly der Grafik anpassen ! + ::lcl_CallModify( *pGrfNd, aMsgHint ); + } + } + + bInNotifyLinks = FALSE; + } + else + { + pCntntNode->Modify( &aMsgHint, &aMsgHint ); + } + + + if( pESh ) + { + const BOOL bEndActionByVirDev = pESh->IsEndActionByVirDev(); + pESh->SetEndActionByVirDev( TRUE ); + pESh->EndAllAction(); + pESh->SetEndActionByVirDev( bEndActionByVirDev ); + } + else if( pSh ) + pSh->EndAction(); + + if( pSh && !bLockView ) + pSh->LockView( FALSE ); + } +} + +BOOL SetGrfFlySize( const Size& rGrfSz, const Size& rFrmSz, SwGrfNode* pGrfNd ) +{ + BOOL bRet = FALSE; + ViewShell *pSh; + CurrShell *pCurr = 0; + if ( pGrfNd->GetDoc()->GetEditShell( &pSh ) ) + pCurr = new CurrShell( pSh ); + + Size aSz = pGrfNd->GetTwipSize(); + if ( !(aSz.Width() && aSz.Height()) && + rGrfSz.Width() && rGrfSz.Height() ) + { + SwFrmFmt* pFmt; + if( pGrfNd->IsChgTwipSize() && + 0 != (pFmt = pGrfNd->GetFlyFmt()) ) + { + Size aCalcSz( aSz ); + if ( !aSz.Height() && aSz.Width() ) + //passende Hoehe ausrechnen. + aCalcSz.Height() = rFrmSz.Height() * + aSz.Width() / rFrmSz.Width(); + else if ( !aSz.Width() && aSz.Height() ) + //passende Breite ausrechnen + aCalcSz.Width() = rFrmSz.Width() * + aSz.Height() / rFrmSz.Height(); + else + //Hoehe und Breite uebernehmen + aCalcSz = rFrmSz; + + const SvxBoxItem &rBox = pFmt->GetBox(); + aCalcSz.Width() += rBox.CalcLineSpace(BOX_LINE_LEFT) + + rBox.CalcLineSpace(BOX_LINE_RIGHT); + aCalcSz.Height()+= rBox.CalcLineSpace(BOX_LINE_TOP) + + rBox.CalcLineSpace(BOX_LINE_BOTTOM); + const SwFmtFrmSize& rOldAttr = pFmt->GetFrmSize(); + if( rOldAttr.GetSize() != aCalcSz ) + { + SwFmtFrmSize aAttr( rOldAttr ); + aAttr.SetSize( aCalcSz ); + pFmt->SetFmtAttr( aAttr ); + bRet = TRUE; + } + + if( !aSz.Width() ) + { + // Wenn die Grafik in einer Tabelle verankert ist, muess + // die Tabellen-Spalten neu berechnet werden + const SwDoc *pDoc = pGrfNd->GetDoc(); + const SwPosition* pAPos = pFmt->GetAnchor().GetCntntAnchor(); + SwNode *pANd; + SwTableNode *pTblNd; + if( pAPos && + 0 != (pANd = pDoc->GetNodes()[pAPos->nNode]) && + 0 != (pTblNd = pANd->FindTableNode()) ) + { + const BOOL bLastGrf = !pTblNd->GetTable().DecGrfsThatResize(); + SwHTMLTableLayout *pLayout = + pTblNd->GetTable().GetHTMLTableLayout(); + if( pLayout ) + { + const USHORT nBrowseWidth = + pLayout->GetBrowseWidthByTable( *pDoc ); + if ( nBrowseWidth ) + { + pLayout->Resize( nBrowseWidth, TRUE, TRUE, + bLastGrf ? HTMLTABLE_RESIZE_NOW + : 500 ); + } + } + } + } + } + + // SetTwipSize skaliert ggf. eine ImageMap neu und + // braucht dazu das Frame-Format + pGrfNd->SetTwipSize( rGrfSz ); + } + + delete pCurr; + + return bRet; +} + + +BOOL SwBaseLink::SwapIn( BOOL bWaitForData, BOOL bNativFormat ) +{ + bSwapIn = TRUE; + + BOOL bRes; + + if( !GetObj() && ( bNativFormat || ( !IsSynchron() && bWaitForData ) )) + { + AddNextRef(); + _GetRealObject(); + ReleaseRef(); + } + +#if OSL_DEBUG_LEVEL > 1 + { + String sGrfNm; + if(GetLinkManager()) + GetLinkManager()->GetDisplayNames( this, 0, &sGrfNm, 0, 0 ); + int x = 0; + ++x; + } +#endif + + // --> OD 2005-04-11 #i46300# - deactivate fix for issues i9861 and i33293 +// TestBalloonInputStream* pTBIS = 0; +// if(!m_xInputStreamToLoadFrom.is()) { +// if ( !pCntntNode->IsGrfNode() || +// static_cast<SwGrfNode*>(pCntntNode)->GetGrfObj().GetType() +// != GRAPHIC_DEFAULT ) +// { +// pTBIS = new TestBalloonInputStream(); +// m_xInputStreamToLoadFrom = pTBIS; +// } +// } + // <-- + + if( GetObj() ) + { + // --> OD 2005-04-11 #i46300# - deactivate fix for issues i9861 and i33293 +// GetObj()->setStreamToLoadFrom(m_xInputStreamToLoadFrom,m_bIsReadOnly); + // <-- + String aMimeType( SotExchange::GetFormatMimeType( GetContentType() )); + +//!! ??? what have we here to do ???? +//!! if( bNativFormat ) +//!! aData.SetAspect( aData.GetAspect() | ASPECT_ICON ); + + uno::Any aValue; + GetObj()->GetData( aValue, aMimeType, !IsSynchron() && bWaitForData ); + + if( bWaitForData && !GetObj() ) + { + OSL_ENSURE( !this, "das SvxFileObject wurde in einem GetData geloescht!" ); + bRes = FALSE; + } + else if( 0 != ( bRes = aValue.hasValue() ) ) + { + //JP 14.04.99: Bug 64820 - das Flag muss beim SwapIn natuerlich + // zurueckgesetzt werden. Die Daten sollen ja neu + // uebernommen werden + bIgnoreDataChanged = FALSE; + DataChanged( aMimeType, aValue ); + } + } + else if( !IsSynchron() && bWaitForData ) + { + SetSynchron( TRUE ); + bRes = Update(); + SetSynchron( FALSE ); + } + else + bRes = Update(); + + bSwapIn = FALSE; + + // --> OD 2005-04-11 #i46300# - deactivate fix for issues i9861 and i33293 +// if ( pTBIS && pTBIS->isTouched() ) +// { +// // --> OD 2005-04-11 #i46300# - determine correct URL for the graphic +// String sGrfNm; +// GetLinkManager()->GetDisplayNames( this, 0, &sGrfNm, 0, 0 ); +// (m_pReReadThread = new ReReadThread( +// this, sGrfNm, bWaitForData, bNativFormat))->create(); +// // <-- +// } + // <-- + return bRes; +} + +void SwBaseLink::Closed() +{ + if( pCntntNode && !pCntntNode->GetDoc()->IsInDtor() ) + { + // wir heben die Verbindung auf + if( pCntntNode->IsGrfNode() ) + ((SwGrfNode*)pCntntNode)->ReleaseLink(); + } + SvBaseLink::Closed(); +} + +const SwNode* SwBaseLink::GetAnchor() const +{ + if (pCntntNode) + { + SwFrmFmt *const pFmt = pCntntNode->GetFlyFmt(); + if (pFmt) + { + const SwFmtAnchor& rAnchor = pFmt->GetAnchor(); + SwPosition const*const pAPos = rAnchor.GetCntntAnchor(); + if (pAPos && + ((FLY_AS_CHAR == rAnchor.GetAnchorId()) || + (FLY_AT_CHAR == rAnchor.GetAnchorId()) || + (FLY_AT_FLY == rAnchor.GetAnchorId()) || + (FLY_AT_PARA == rAnchor.GetAnchorId()))) + { + return &pAPos->nNode.GetNode(); + } + return 0; + } + } + + OSL_ENSURE( !this, "GetAnchor nicht ueberlagert" ); + return 0; +} + +BOOL SwBaseLink::IsRecursion( const SwBaseLink* pChkLnk ) const +{ + SwServerObjectRef aRef( (SwServerObject*)GetObj() ); + if( aRef.Is() ) + { + // es ist ein ServerObject, also frage nach allen darin + // befindlichen Links, ob wir darin enthalten sind. Ansonsten + // handelt es sich um eine Rekursion. + return aRef->IsLinkInServer( pChkLnk ); + } + return FALSE; +} + +BOOL SwBaseLink::IsInRange( ULONG, ULONG, xub_StrLen, xub_StrLen ) const +{ + // Grafik oder OLE-Links nicht, + // Felder oder Sections haben eigene Ableitung! + return FALSE; +} + +SwBaseLink::~SwBaseLink() +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |