/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern bool bFrmDrag; extern bool bDDINetAttr; extern bool bExecuteDrag; #define OLESIZE 11905 - 2 * lMinBorder, 6 * MM50 #define SWTRANSFER_OBJECTTYPE_DRAWMODEL 0x00000001 #define SWTRANSFER_OBJECTTYPE_HTML 0x00000002 #define SWTRANSFER_OBJECTTYPE_RTF 0x00000004 #define SWTRANSFER_OBJECTTYPE_STRING 0x00000008 #define SWTRANSFER_OBJECTTYPE_SWOLE 0x00000010 #define SWTRANSFER_OBJECTTYPE_DDE 0x00000020 using namespace ::svx; using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::datatransfer; using namespace nsTransferBufferType; #define DDE_TXT_ENCODING osl_getThreadTextEncoding() class SwTrnsfrDdeLink : public ::sfx2::SvBaseLink { OUString sName; ::sfx2::SvLinkSourceRef refObj; SwTransferable& rTrnsfr; SwDocShell* pDocShell; sal_uLong nOldTimeOut; bool bDelBookmrk : 1; bool bInDisconnect : 1; bool FindDocShell(); using sfx2::SvBaseLink::Disconnect; protected: virtual ~SwTrnsfrDdeLink(); public: SwTrnsfrDdeLink( SwTransferable& rTrans, SwWrtShell& rSh ); virtual ::sfx2::SvBaseLink::UpdateResult DataChanged( const OUString& rMimeType, const ::com::sun::star::uno::Any & rValue ) SAL_OVERRIDE; virtual void Closed() SAL_OVERRIDE; bool WriteData( SvStream& rStrm ); void Disconnect( bool bRemoveDataAdvise ); }; // helper class for Action and Undo enclosing class SwTrnsfrActionAndUndo { SwWrtShell *pSh; SwUndoId eUndoId; public: SwTrnsfrActionAndUndo( SwWrtShell *pS, SwUndoId nId, const SwRewriter * pRewriter = 0, bool bDelSel = false) : pSh( pS ), eUndoId( nId ) { pSh->StartUndo( eUndoId, pRewriter ); if( bDelSel ) pSh->DelRight(); pSh->StartAllAction(); } ~SwTrnsfrActionAndUndo() { pSh->EndUndo(); pSh->EndAllAction(); } }; SwTransferable::SwTransferable( SwWrtShell& rSh ) : pWrtShell( &rSh ), pCreatorView( 0 ), pClpDocFac( 0 ), pClpGraphic( 0 ), pClpBitmap( 0 ), pOrigGrf( 0 ), pBkmk( 0 ), pImageMap( 0 ), pTargetURL( 0 ), eBufferType( TRNSFR_NONE ) { rSh.GetView().AddTransferable(*this); SwDocShell* pDShell = rSh.GetDoc()->GetDocShell(); if( pDShell ) { pDShell->FillTransferableObjectDescriptor( aObjDesc ); if( pDShell->GetMedium() ) { const INetURLObject& rURLObj = pDShell->GetMedium()->GetURLObject(); aObjDesc.maDisplayName = URIHelper::removePassword( rURLObj.GetMainURL( INetURLObject::NO_DECODE ), INetURLObject::WAS_ENCODED, INetURLObject::DECODE_UNAMBIGUOUS ); } PrepareOLE( aObjDesc ); } } SwTransferable::~SwTransferable() { Application::GetSolarMutex().acquire(); // the DDELink still needs the WrtShell! if( refDdeLink.Is() ) { ((SwTrnsfrDdeLink*)&refDdeLink)->Disconnect( true ); refDdeLink.Clear(); } pWrtShell = 0; // release reference to the document so that aDocShellRef will delete // it (if aDocShellRef is set). Otherwise, the OLE nodes keep references // to their sub-storage when the storage is already dead. delete pClpDocFac; // first close, then the Ref. can be cleared as well, so that // the DocShell really gets deleted! if( aDocShellRef.Is() ) { SfxObjectShell * pObj = aDocShellRef; SwDocShell* pDocSh = (SwDocShell*)pObj; pDocSh->DoClose(); } aDocShellRef.Clear(); SwModule* pMod = SW_MOD(); if(pMod) { if ( pMod->pDragDrop == this ) pMod->pDragDrop = 0; else if ( pMod->pXSelection == this ) pMod->pXSelection = 0; } delete pClpGraphic; delete pClpBitmap; delete pImageMap; delete pTargetURL; delete pBkmk; eBufferType = TRNSFR_NONE; Application::GetSolarMutex().release(); } static SwDoc * lcl_GetDoc(SwDocFac & rDocFac) { SwDoc *const pDoc = rDocFac.GetDoc(); OSL_ENSURE( pDoc, "Document not found" ); if (pDoc) { pDoc->SetClipBoard( true ); } return pDoc; } void SwTransferable::ObjectReleased() { SwModule *pMod = SW_MOD(); if( this == pMod->pDragDrop ) pMod->pDragDrop = 0; else if( this == pMod->pXSelection ) pMod->pXSelection = 0; } void SwTransferable::AddSupportedFormats() { // only need if we are the current XSelection Object SwModule *pMod = SW_MOD(); if( this == pMod->pXSelection ) { SetDataForDragAndDrop( Point( 0,0) ); } } void SwTransferable::InitOle( SfxObjectShell* pDoc, SwDoc& rDoc ) { //set OleVisArea. Upper left corner of the page and size of //RealSize in Twips. const Size aSz( OLESIZE ); SwRect aVis( Point( DOCUMENTBORDER, DOCUMENTBORDER ), aSz ); pDoc->SetVisArea( aVis.SVRect() ); rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::BROWSE_MODE, true ); } uno::Reference < embed::XEmbeddedObject > SwTransferable::FindOLEObj( sal_Int64& nAspect ) const { uno::Reference < embed::XEmbeddedObject > xObj; if( pClpDocFac ) { SwIterator aIter( *pClpDocFac->GetDoc()->GetDfltGrfFmtColl() ); for( SwCntntNode* pNd = aIter.First(); pNd; pNd = aIter.Next() ) if( ND_OLENODE == pNd->GetNodeType() ) { xObj = ((SwOLENode*)pNd)->GetOLEObj().GetOleRef(); nAspect = ((SwOLENode*)pNd)->GetAspect(); break; } } return xObj; } const Graphic* SwTransferable::FindOLEReplacementGraphic() const { if( pClpDocFac ) { SwIterator aIter( *pClpDocFac->GetDoc()->GetDfltGrfFmtColl() ); for( SwCntntNode* pNd = aIter.First(); pNd; pNd = aIter.Next() ) if( ND_OLENODE == pNd->GetNodeType() ) { return ((SwOLENode*)pNd)->GetGraphic(); } } return NULL; } void SwTransferable::RemoveDDELinkFormat( const Window& rWin ) { RemoveFormat( SOT_FORMATSTR_ID_LINK ); CopyToClipboard( (Window*)&rWin ); } namespace { //Resolves: fdo#40717 surely when we create a clipboard document we should //overwrite the clipboard documents styles and settings with that of the //source, so that we can WYSIWYG paste. If we want that the destinations //styles are used over the source styles, that's a matter of the //destination paste code to handle, not the source paste code. void lclOverWriteDoc(SwWrtShell &rSrcWrtShell, SwDoc &rDest) { const SwDoc &rSrc = *rSrcWrtShell.GetDoc(); rDest.ReplaceCompatabilityOptions(rSrc); rDest.ReplaceDefaults(rSrc); //It would probably make most sense here to only insert the styles used //by the selection, e.g. apply SwDoc::IsUsed on styles ? rDest.ReplaceStyles(rSrc, false); rSrcWrtShell.Copy(&rDest); } void lclCheckAndPerformRotation(Graphic& aGraphic) { GraphicNativeMetadata aMetadata; if ( aMetadata.read(aGraphic) ) { sal_uInt16 aRotation = aMetadata.getRotation(); if (aRotation != 0) { MessageDialog aQueryBox( 0,"QueryRotateIntoStandardOrientationDialog","modules/swriter/ui/queryrotateintostandarddialog.ui"); if (aQueryBox.Execute() == RET_YES) { GraphicNativeTransform aTransform( aGraphic ); aTransform.rotate( aRotation ); } } } } } bool SwTransferable::GetData( const DataFlavor& rFlavor ) { sal_uInt32 nFormat = SotExchange::GetFormat( rFlavor ); // we can only fullfil the request if // 1) we have data for this format // 2) we have either a clipboard document (pClpDocFac), or // we have a SwWrtShell (so we can generate a new clipboard document) if( !HasFormat( nFormat ) || ( pClpDocFac == NULL && pWrtShell == NULL ) ) return false; if( !pClpDocFac ) { SelectionType nSelectionType = pWrtShell->GetSelectionType(); // when pending we will not get the correct type, but nsSelectionType::SEL_TXT // as fallback. This *happens* durning D&D, so we need to check if we are in // the fallback and just try to get a graphic const bool bPending(pWrtShell->BasicActionPend()); // SEL_GRF is from ContentType of editsh if(bPending || ((nsSelectionType::SEL_GRF | nsSelectionType::SEL_DRW_FORM) & nSelectionType)) { pClpGraphic = new Graphic; if( !pWrtShell->GetDrawObjGraphic( FORMAT_GDIMETAFILE, *pClpGraphic )) pOrigGrf = pClpGraphic; pClpBitmap = new Graphic; if( !pWrtShell->GetDrawObjGraphic( FORMAT_BITMAP, *pClpBitmap )) pOrigGrf = pClpBitmap; // is it an URL-Button ? OUString sURL; OUString sDesc; if( pWrtShell->GetURLFromButton( sURL, sDesc ) ) { pBkmk = new INetBookmark( sURL, sDesc ); eBufferType = TRNSFR_INETFLD; } } pClpDocFac = new SwDocFac; SwDoc *const pTmpDoc = lcl_GetDoc(*pClpDocFac); pTmpDoc->LockExpFlds(); // never update fields - leave text as it is lclOverWriteDoc(*pWrtShell, *pTmpDoc); // in CORE a new one was created (OLE-Objekte copied!) aDocShellRef = pTmpDoc->GetTmpDocShell(); if( aDocShellRef.Is() ) SwTransferable::InitOle( aDocShellRef, *pTmpDoc ); pTmpDoc->SetTmpDocShell( (SfxObjectShell*)NULL ); if( nSelectionType & nsSelectionType::SEL_TXT && !pWrtShell->HasMark() ) { SwContentAtPos aCntntAtPos( SwContentAtPos::SW_INETATTR ); Point aPos( SwEditWin::GetDDStartPosX(), SwEditWin::GetDDStartPosY()); bool bSelect = bExecuteDrag && pWrtShell->GetView().GetDocShell() && !pWrtShell->GetView().GetDocShell()->IsReadOnly(); if( pWrtShell->GetContentAtPos( aPos, aCntntAtPos, bSelect ) ) { pBkmk = new INetBookmark( ((SwFmtINetFmt*)aCntntAtPos.aFnd.pAttr)->GetValue(), aCntntAtPos.sStr ); eBufferType = TRNSFR_INETFLD; if( bSelect ) pWrtShell->SelectTxtAttr( RES_TXTATR_INETFMT ); } } if( pWrtShell->IsFrmSelected() ) { SfxItemSet aSet( pWrtShell->GetAttrPool(), RES_URL, RES_URL ); pWrtShell->GetFlyFrmAttr( aSet ); const SwFmtURL& rURL = (SwFmtURL&)aSet.Get( RES_URL ); if( rURL.GetMap() ) pImageMap = new ImageMap( *rURL.GetMap() ); else if( !rURL.GetURL().isEmpty() ) pTargetURL = new INetImage( aEmptyOUStr, rURL.GetURL(), rURL.GetTargetFrameName(), aEmptyOUStr, Size() ); } } bool bOK = false; if( TRNSFR_OLE == eBufferType ) { //TODO/MBA: testing - is this the "single OLE object" case?! // get OLE-Object from ClipDoc and get the data from that. sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT; // will be set in the next statement uno::Reference < embed::XEmbeddedObject > xObj = FindOLEObj( nAspect ); const Graphic* pOLEGraph = FindOLEReplacementGraphic(); if( xObj.is() ) { TransferableDataHelper aD( new SvEmbedTransferHelper( xObj, pOLEGraph, nAspect ) ); uno::Any aAny( aD.GetAny( rFlavor )); if( aAny.hasValue() ) bOK = SetAny( aAny, rFlavor ); } // the following solution will be used in the case when the object can not generate the image // TODO/LATER: in future the transferhelper must probably be created based on object and the replacement stream if ( nFormat == SOT_FORMAT_GDIMETAFILE ) { pOLEGraph = FindOLEReplacementGraphic(); if ( pOLEGraph ) bOK = SetGDIMetaFile( pOLEGraph->GetGDIMetaFile(), rFlavor ); } } else { switch( nFormat ) { case SOT_FORMATSTR_ID_LINK: if( refDdeLink.Is() ) bOK = SetObject( &refDdeLink, SWTRANSFER_OBJECTTYPE_DDE, rFlavor ); break; case SOT_FORMATSTR_ID_OBJECTDESCRIPTOR: case SOT_FORMATSTR_ID_LINKSRCDESCRIPTOR: bOK = SetTransferableObjectDescriptor( aObjDesc, rFlavor ); break; case SOT_FORMATSTR_ID_DRAWING: { SwDoc *const pDoc = lcl_GetDoc(*pClpDocFac); bOK = SetObject( pDoc->getIDocumentDrawModelAccess().GetDrawModel(), SWTRANSFER_OBJECTTYPE_DRAWMODEL, rFlavor ); } break; case SOT_FORMAT_STRING: { SwDoc *const pDoc = lcl_GetDoc(*pClpDocFac); bOK = SetObject( pDoc, SWTRANSFER_OBJECTTYPE_STRING, rFlavor ); } break; case SOT_FORMAT_RTF: { SwDoc *const pDoc = lcl_GetDoc(*pClpDocFac); bOK = SetObject( pDoc, SWTRANSFER_OBJECTTYPE_RTF, rFlavor ); } break; case SOT_FORMATSTR_ID_HTML: { SwDoc *const pDoc = lcl_GetDoc(*pClpDocFac); bOK = SetObject( pDoc, SWTRANSFER_OBJECTTYPE_HTML, rFlavor ); } break; case SOT_FORMATSTR_ID_SVXB: if( eBufferType & TRNSFR_GRAPHIC && pOrigGrf ) bOK = SetGraphic( *pOrigGrf, rFlavor ); break; case SOT_FORMAT_GDIMETAFILE: if( eBufferType & TRNSFR_GRAPHIC ) bOK = SetGDIMetaFile( pClpGraphic->GetGDIMetaFile(), rFlavor ); break; case SOT_FORMAT_BITMAP: case SOT_FORMATSTR_ID_PNG: // Neither pClpBitmap nor pClpGraphic are necessarily set if( (eBufferType & TRNSFR_GRAPHIC) && (pClpBitmap != 0 || pClpGraphic != 0)) bOK = SetBitmapEx( (pClpBitmap ? pClpBitmap : pClpGraphic)->GetBitmapEx(), rFlavor ); break; case SOT_FORMATSTR_ID_SVIM: if( pImageMap ) bOK = SetImageMap( *pImageMap, rFlavor ); break; case SOT_FORMATSTR_ID_INET_IMAGE: if( pTargetURL ) bOK = SetINetImage( *pTargetURL, rFlavor ); break; case SOT_FORMATSTR_ID_SOLK: case SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK: case SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR: case SOT_FORMATSTR_ID_FILECONTENT: case SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR: case SOT_FORMAT_FILE: if( (TRNSFR_INETFLD & eBufferType) && pBkmk ) bOK = SetINetBookmark( *pBkmk, rFlavor ); break; case SOT_FORMATSTR_ID_EMBED_SOURCE: if( !aDocShellRef.Is() ) { SwDoc *const pDoc = lcl_GetDoc(*pClpDocFac); SwDocShell* pNewDocSh = new SwDocShell( pDoc, SFX_CREATE_MODE_EMBEDDED ); aDocShellRef = pNewDocSh; aDocShellRef->DoInitNew( NULL ); SwTransferable::InitOle( aDocShellRef, *pDoc ); } bOK = SetObject( &aDocShellRef, SWTRANSFER_OBJECTTYPE_SWOLE, rFlavor ); break; } } return bOK; } bool SwTransferable::WriteObject( SotStorageStreamRef& xStream, void* pObject, sal_uInt32 nObjectType, const DataFlavor& /*rFlavor*/ ) { bool bRet = false; WriterRef xWrt; switch( nObjectType ) { case SWTRANSFER_OBJECTTYPE_DRAWMODEL: { // don't change the sequence of commands SdrModel *pModel = (SdrModel*)pObject; xStream->SetBufferSize( 16348 ); // for the changed pool defaults from drawing layer pool set those // attributes as hard attributes to preserve them for saving const SfxItemPool& rItemPool = pModel->GetItemPool(); const SvxFontHeightItem& rDefaultFontHeight = (const SvxFontHeightItem&)rItemPool.GetDefaultItem(EE_CHAR_FONTHEIGHT); // SW should have no MasterPages OSL_ENSURE(0L == pModel->GetMasterPageCount(), "SW with MasterPages (!)"); for(sal_uInt16 a(0); a < pModel->GetPageCount(); a++) { const SdrPage* pPage = pModel->GetPage(a); SdrObjListIter aIter(*pPage, IM_DEEPNOGROUPS); while(aIter.IsMore()) { SdrObject* pObj = aIter.Next(); const SvxFontHeightItem& rItem = (const SvxFontHeightItem&)pObj->GetMergedItem(EE_CHAR_FONTHEIGHT); if(rItem.GetHeight() == rDefaultFontHeight.GetHeight()) { pObj->SetMergedItem(rDefaultFontHeight); } } } { uno::Reference xDocOut( new utl::OOutputStreamWrapper( *xStream ) ); if( SvxDrawingLayerExport( pModel, xDocOut ) ) xStream->Commit(); } bRet = ERRCODE_NONE == xStream->GetError(); } break; case SWTRANSFER_OBJECTTYPE_SWOLE: { SfxObjectShell* pEmbObj = (SfxObjectShell*) pObject; try { ::utl::TempFile aTempFile; aTempFile.EnableKillingFile(); uno::Reference< embed::XStorage > xWorkStore = ::comphelper::OStorageHelper::GetStorageFromURL( aTempFile.GetURL(), embed::ElementModes::READWRITE ); // write document storage pEmbObj->SetupStorage( xWorkStore, SOFFICE_FILEFORMAT_CURRENT, false ); // mba: no BaseURL for clipboard SfxMedium aMedium( xWorkStore, OUString() ); bRet = pEmbObj->DoSaveObjectAs( aMedium, false ); pEmbObj->DoSaveCompleted(); uno::Reference< embed::XTransactedObject > xTransact( xWorkStore, uno::UNO_QUERY ); if ( xTransact.is() ) xTransact->commit(); boost::scoped_ptr pSrcStm(::utl::UcbStreamHelper::CreateStream( aTempFile.GetURL(), STREAM_READ )); if( pSrcStm ) { xStream->SetBufferSize( 0xff00 ); xStream->WriteStream( *pSrcStm ); pSrcStm.reset(); } bRet = true; xWorkStore->dispose(); xWorkStore = uno::Reference < embed::XStorage >(); xStream->Commit(); } catch (const uno::Exception&) { } bRet = ( xStream->GetError() == ERRCODE_NONE ); } break; case SWTRANSFER_OBJECTTYPE_DDE: { xStream->SetBufferSize( 1024 ); SwTrnsfrDdeLink* pDdeLnk = (SwTrnsfrDdeLink*)pObject; if( pDdeLnk->WriteData( *xStream ) ) { xStream->Commit(); bRet = ERRCODE_NONE == xStream->GetError(); } } break; case SWTRANSFER_OBJECTTYPE_HTML: GetHTMLWriter( aEmptyOUStr, OUString(), xWrt ); break; case SWTRANSFER_OBJECTTYPE_RTF: GetRTFWriter( aEmptyOUStr, OUString(), xWrt ); break; case SWTRANSFER_OBJECTTYPE_STRING: GetASCWriter( aEmptyOUStr, OUString(), xWrt ); if( xWrt.Is() ) { SwAsciiOptions aAOpt; aAOpt.SetCharSet( RTL_TEXTENCODING_UTF8 ); xWrt->SetAsciiOptions( aAOpt ); // no start char for clipboard xWrt->bUCS2_WithStartChar = false; } break; } if( xWrt.Is() ) { SwDoc* pDoc = (SwDoc*)pObject; xWrt->bWriteClipboardDoc = true; xWrt->bWriteOnlyFirstTable = 0 != (TRNSFR_TABELLE & eBufferType); xWrt->SetShowProgress( false ); #if defined(DEBUGPASTE) SvFileStream aPasteDebug(OUString( "PASTEBUFFER.debug"), STREAM_WRITE|STREAM_TRUNC); SwWriter aDbgWrt( aPasteDebug, *pDoc ); aDbgWrt.Write( xWrt ); #endif SwWriter aWrt( *xStream, *pDoc ); if( !IsError( aWrt.Write( xWrt )) ) { xStream->WriteChar( '\0' ); // terminate with a zero xStream->Commit(); bRet = true; } } return bRet; } int SwTransferable::Cut() { int nRet = Copy( true ); if( nRet ) DeleteSelection(); return nRet; } void SwTransferable::DeleteSelection() { if(!pWrtShell) return; // ask for type of selection before action-bracketing const int nSelection = pWrtShell->GetSelectionType(); pWrtShell->StartUndo( UNDO_DELETE ); if( ( nsSelectionType::SEL_TXT | nsSelectionType::SEL_TBL ) & nSelection ) pWrtShell->IntelligentCut( nSelection ); pWrtShell->DelRight(); pWrtShell->EndUndo( UNDO_DELETE ); } int SwTransferable::PrepareForCopy( bool bIsCut ) { int nRet = 1; if(!pWrtShell) return 0; OUString sGrfNm; const int nSelection = pWrtShell->GetSelectionType(); if( nSelection == nsSelectionType::SEL_GRF ) { pClpGraphic = new Graphic; if( !pWrtShell->GetDrawObjGraphic( FORMAT_GDIMETAFILE, *pClpGraphic )) pOrigGrf = pClpGraphic; pClpBitmap = new Graphic; if( !pWrtShell->GetDrawObjGraphic( FORMAT_BITMAP, *pClpBitmap )) pOrigGrf = pClpBitmap; pClpDocFac = new SwDocFac; SwDoc *const pDoc = lcl_GetDoc(*pClpDocFac); pWrtShell->Copy( pDoc ); if (pOrigGrf && !pOrigGrf->GetBitmap().IsEmpty()) AddFormat( SOT_FORMATSTR_ID_SVXB ); PrepareOLE( aObjDesc ); AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR ); const Graphic* pGrf = pWrtShell->GetGraphic(); if( pGrf && pGrf->IsSupportedGraphic() ) { AddFormat( FORMAT_GDIMETAFILE ); AddFormat( SOT_FORMATSTR_ID_PNG ); AddFormat( FORMAT_BITMAP ); } eBufferType = TRNSFR_GRAPHIC; pWrtShell->GetGrfNms( &sGrfNm, 0 ); } else if ( nSelection == nsSelectionType::SEL_OLE ) { pClpDocFac = new SwDocFac; SwDoc *const pDoc = lcl_GetDoc(*pClpDocFac); aDocShellRef = new SwDocShell( pDoc, SFX_CREATE_MODE_EMBEDDED); aDocShellRef->DoInitNew( NULL ); pWrtShell->Copy( pDoc ); AddFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ); // --> OD #i98753# // set size of embedded object at the object description structure aObjDesc.maSize = OutputDevice::LogicToLogic( pWrtShell->GetObjSize(), MAP_TWIP, MAP_100TH_MM ); // <-- PrepareOLE( aObjDesc ); AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR ); AddFormat( FORMAT_GDIMETAFILE ); eBufferType = TRNSFR_OLE; } // Is there anything to provide anyway? else if ( pWrtShell->IsSelection() || pWrtShell->IsFrmSelected() || pWrtShell->IsObjSelected() ) { boost::scoped_ptr pWait; if( pWrtShell->ShouldWait() ) pWait.reset(new SwWait( *pWrtShell->GetView().GetDocShell(), true )); pClpDocFac = new SwDocFac; // create additional cursor so that equal treatment of keyboard // and mouse selection is possible. // In AddMode with keyboard selection, the new cursor is not created // before the cursor is moved after end of selection. if( pWrtShell->IsAddMode() && pWrtShell->SwCrsrShell::HasSelection() ) pWrtShell->CreateCrsr(); SwDoc *const pTmpDoc = lcl_GetDoc(*pClpDocFac); pTmpDoc->LockExpFlds(); // Never update fields - leave text as is lclOverWriteDoc(*pWrtShell, *pTmpDoc); { IDocumentMarkAccess* const pMarkAccess = pTmpDoc->getIDocumentMarkAccess(); ::std::vector< ::sw::mark::IMark* > vDdeMarks; // find all DDE-Bookmarks for(IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->getAllMarksBegin(); ppMark != pMarkAccess->getAllMarksEnd(); ++ppMark) { if(IDocumentMarkAccess::DDE_BOOKMARK == IDocumentMarkAccess::GetType(**ppMark)) vDdeMarks.push_back(ppMark->get()); } // remove all DDE-Bookmarks, they are invalid inside the clipdoc! for(::std::vector< ::sw::mark::IMark* >::iterator ppMark = vDdeMarks.begin(); ppMark != vDdeMarks.end(); ++ppMark) pMarkAccess->deleteMark(*ppMark); } // a new one was created in CORE (OLE objects copied!) aDocShellRef = pTmpDoc->GetTmpDocShell(); if( aDocShellRef.Is() ) SwTransferable::InitOle( aDocShellRef, *pTmpDoc ); pTmpDoc->SetTmpDocShell( (SfxObjectShell*)NULL ); if( pWrtShell->IsObjSelected() ) eBufferType = TRNSFR_DRAWING; else { eBufferType = TRNSFR_DOCUMENT; if (pWrtShell->IntelligentCut(nSelection, false) != SwWrtShell::NO_WORD) eBufferType = (TransferBufferType)(TRNSFR_DOCUMENT_WORD | eBufferType); } bool bDDELink = pWrtShell->IsSelection(); if( nSelection & nsSelectionType::SEL_TBL_CELLS ) { eBufferType = (TransferBufferType)(TRNSFR_TABELLE | eBufferType); bDDELink = pWrtShell->HasWholeTabSelection(); } //When someone needs it, we 'OLE' him something AddFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ); //put RTF ahead of the OLE's Metafile to have less loss if( !pWrtShell->IsObjSelected() ) { AddFormat( FORMAT_RTF ); AddFormat( SOT_FORMATSTR_ID_HTML ); } if( pWrtShell->IsSelection() ) AddFormat( FORMAT_STRING ); if( nSelection & ( nsSelectionType::SEL_DRW | nsSelectionType::SEL_DRW_FORM )) { AddFormat( SOT_FORMATSTR_ID_DRAWING ); if ( nSelection & nsSelectionType::SEL_DRW ) { AddFormat( FORMAT_GDIMETAFILE ); AddFormat( SOT_FORMATSTR_ID_PNG ); AddFormat( FORMAT_BITMAP ); } eBufferType = (TransferBufferType)( TRNSFR_GRAPHIC | eBufferType ); pClpGraphic = new Graphic; if( !pWrtShell->GetDrawObjGraphic( FORMAT_GDIMETAFILE, *pClpGraphic )) pOrigGrf = pClpGraphic; pClpBitmap = new Graphic; if( !pWrtShell->GetDrawObjGraphic( FORMAT_BITMAP, *pClpBitmap )) pOrigGrf = pClpBitmap; // is it an URL-Button ? OUString sURL; OUString sDesc; if( pWrtShell->GetURLFromButton( sURL, sDesc ) ) { AddFormat( FORMAT_STRING ); AddFormat( SOT_FORMATSTR_ID_SOLK ); AddFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ); AddFormat( SOT_FORMATSTR_ID_FILECONTENT ); AddFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ); AddFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ); eBufferType = (TransferBufferType)( TRNSFR_INETFLD | eBufferType ); nRet = sal_True; } } // at Cut, DDE-Link doesn't make sense!! SwDocShell* pDShell; if( !bIsCut && bDDELink && 0 != ( pDShell = pWrtShell->GetDoc()->GetDocShell()) && SFX_CREATE_MODE_STANDARD == pDShell->GetCreateMode() ) { AddFormat( SOT_FORMATSTR_ID_LINK ); refDdeLink = new SwTrnsfrDdeLink( *this, *pWrtShell ); } //ObjectDescriptor was already filly from the old DocShell. //Now adjust it. Thus in GetData the first query can still //be answered with delayed rendering. aObjDesc.mbCanLink = false; Size aSz( OLESIZE ); aObjDesc.maSize = OutputDevice::LogicToLogic( aSz, MAP_TWIP, MAP_100TH_MM ); PrepareOLE( aObjDesc ); AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR ); } else nRet = 0; if( pWrtShell->IsFrmSelected() ) { SfxItemSet aSet( pWrtShell->GetAttrPool(), RES_URL, RES_URL ); pWrtShell->GetFlyFrmAttr( aSet ); const SwFmtURL& rURL = (SwFmtURL&)aSet.Get( RES_URL ); if( rURL.GetMap() ) { pImageMap = new ImageMap( *rURL.GetMap() ); AddFormat( SOT_FORMATSTR_ID_SVIM ); } else if( !rURL.GetURL().isEmpty() ) { pTargetURL = new INetImage( sGrfNm, rURL.GetURL(), rURL.GetTargetFrameName(), aEmptyOUStr, Size() ); AddFormat( SOT_FORMATSTR_ID_INET_IMAGE ); } } return nRet; } int SwTransferable::Copy( bool bIsCut ) { int nRet = PrepareForCopy( bIsCut ); if ( nRet ) { CopyToClipboard( &pWrtShell->GetView().GetEditWin() ); } return nRet; } int SwTransferable::CalculateAndCopy() { if(!pWrtShell) return 0; SwWait aWait( *pWrtShell->GetView().GetDocShell(), true ); OUString aStr( pWrtShell->Calculate() ); pClpDocFac = new SwDocFac; SwDoc *const pDoc = lcl_GetDoc(*pClpDocFac); pWrtShell->Copy(pDoc, & aStr); eBufferType = TRNSFR_DOCUMENT; AddFormat( FORMAT_STRING ); CopyToClipboard( &pWrtShell->GetView().GetEditWin() ); return 1; } int SwTransferable::CopyGlossary( SwTextBlocks& rGlossary, const OUString& rStr ) { if(!pWrtShell) return 0; SwWait aWait( *pWrtShell->GetView().GetDocShell(), true ); pClpDocFac = new SwDocFac; SwDoc *const pCDoc = lcl_GetDoc(*pClpDocFac); SwNodes& rNds = pCDoc->GetNodes(); SwNodeIndex aNodeIdx( *rNds.GetEndOfContent().StartOfSectionNode() ); SwCntntNode* pCNd = rNds.GoNext( &aNodeIdx ); // go to 1st ContentNode SwPaM aPam( *pCNd ); pCDoc->LockExpFlds(); // never update fields - leave text as it is pCDoc->InsertGlossary( rGlossary, rStr, aPam, 0 ); // a new one was created in CORE (OLE-Objects copied!) aDocShellRef = pCDoc->GetTmpDocShell(); if( aDocShellRef.Is() ) SwTransferable::InitOle( aDocShellRef, *pCDoc ); pCDoc->SetTmpDocShell( (SfxObjectShell*)NULL ); eBufferType = TRNSFR_DOCUMENT; //When someone needs it, we 'OLE' her something. AddFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ); AddFormat( FORMAT_RTF ); AddFormat( SOT_FORMATSTR_ID_HTML ); AddFormat( FORMAT_STRING ); //ObjectDescriptor was already filled from the old DocShell. //Now adjust it. Thus in GetData the first query can still //be answered with delayed rendering. aObjDesc.mbCanLink = false; Size aSz( OLESIZE ); aObjDesc.maSize = OutputDevice::LogicToLogic( aSz, MAP_TWIP, MAP_100TH_MM ); PrepareOLE( aObjDesc ); AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR ); CopyToClipboard( &pWrtShell->GetView().GetEditWin() ); return 1; } static inline uno::Reference < XTransferable > * lcl_getTransferPointer ( uno::Reference < XTransferable > &xRef ) { return &xRef; } bool SwTransferable::IsPaste( const SwWrtShell& rSh, const TransferableDataHelper& rData ) { // Check the common case first: We can always paste our own data! // If _only_ the internal format can be pasted, this check will // yield 'true', while the one below would give a (wrong) result 'false'. bool bIsPaste = ( GetSwTransferable( rData ) != NULL ); // if it's not our own data, we need to have a closer look: if( ! bIsPaste ) { // determine the proper paste action, and return true if we find one uno::Reference xTransferable( rData.GetXTransferable() ); sal_uInt16 nDestination = SwTransferable::GetSotDestination( rSh ); sal_uInt16 nSourceOptions = (( EXCHG_DEST_DOC_TEXTFRAME == nDestination || EXCHG_DEST_SWDOC_FREE_AREA == nDestination || EXCHG_DEST_DOC_TEXTFRAME_WEB == nDestination || EXCHG_DEST_SWDOC_FREE_AREA_WEB == nDestination ) ? EXCHG_IN_ACTION_COPY : EXCHG_IN_ACTION_MOVE); sal_uLong nFormat; // output param for GetExchangeAction sal_uInt16 nEventAction; // output param for GetExchangeAction sal_uInt16 nAction = SotExchange::GetExchangeAction( rData.GetDataFlavorExVector(), nDestination, nSourceOptions, /* ?? */ EXCHG_IN_ACTION_DEFAULT, /* ?? */ nFormat, nEventAction, 0, lcl_getTransferPointer ( xTransferable ) ); // if we find a suitable action, we can paste! bIsPaste = (EXCHG_INOUT_ACTION_NONE != nAction); } return bIsPaste; } bool SwTransferable::Paste( SwWrtShell& rSh, TransferableDataHelper& rData ) { sal_uInt16 nEventAction, nAction=0, nDestination = SwTransferable::GetSotDestination( rSh ); sal_uLong nFormat = 0; if( GetSwTransferable( rData ) ) { nAction = EXCHG_OUT_ACTION_INSERT_PRIVATE; } else { sal_uInt16 nSourceOptions = (( EXCHG_DEST_DOC_TEXTFRAME == nDestination || EXCHG_DEST_SWDOC_FREE_AREA == nDestination || EXCHG_DEST_DOC_TEXTFRAME_WEB == nDestination || EXCHG_DEST_SWDOC_FREE_AREA_WEB == nDestination ) ? EXCHG_IN_ACTION_COPY : EXCHG_IN_ACTION_MOVE); uno::Reference xTransferable( rData.GetXTransferable() ); nAction = SotExchange::GetExchangeAction( rData.GetDataFlavorExVector(), nDestination, nSourceOptions, /* ?? */ EXCHG_IN_ACTION_DEFAULT, /* ?? */ nFormat, nEventAction, 0, lcl_getTransferPointer ( xTransferable ) ); } // special case for tables from draw application if( EXCHG_OUT_ACTION_INSERT_DRAWOBJ == (nAction & EXCHG_ACTION_MASK) ) { if( rData.HasFormat( SOT_FORMAT_RTF ) ) { nAction = EXCHG_OUT_ACTION_INSERT_STRING | (nAction & ~EXCHG_ACTION_MASK); nFormat = SOT_FORMAT_RTF; } } return EXCHG_INOUT_ACTION_NONE != nAction && SwTransferable::PasteData( rData, rSh, nAction, nFormat, nDestination, false, false ); } bool SwTransferable::PasteData( TransferableDataHelper& rData, SwWrtShell& rSh, sal_uInt16 nAction, sal_uLong nFormat, sal_uInt16 nDestination, bool bIsPasteFmt, bool bIsDefault, const Point* pPt, sal_Int8 nDropAction, bool bPasteSelection ) { SwWait aWait( *rSh.GetView().GetDocShell(), false ); boost::scoped_ptr pAction; SwModule* pMod = SW_MOD(); bool nRet = false; bool bCallAutoCaption = false; if( pPt ) { // external Drop if( bPasteSelection ? !pMod->pXSelection : !pMod->pDragDrop ) { switch( nDestination ) { case EXCHG_DEST_DOC_LNKD_GRAPH_W_IMAP: case EXCHG_DEST_DOC_LNKD_GRAPHOBJ: case EXCHG_DEST_DOC_GRAPH_W_IMAP: case EXCHG_DEST_DOC_GRAPHOBJ: case EXCHG_DEST_DOC_OLEOBJ: case EXCHG_DEST_DOC_DRAWOBJ: case EXCHG_DEST_DOC_URLBUTTON: case EXCHG_DEST_DOC_GROUPOBJ: // select frames/objects SwTransferable::SetSelInShell( rSh, true, pPt ); break; default: SwTransferable::SetSelInShell( rSh, false, pPt ); break; } } } else if( ( !GetSwTransferable( rData ) || bIsPasteFmt ) && !rSh.IsTableMode() && rSh.HasSelection() ) { // then delete the selections //don't delete selected content // - at table-selection // - at ReRead of a graphic/DDEData // - at D&D, for the right selection was taken care of // in Drop-Handler bool bDelSel = false; switch( nDestination ) { case EXCHG_DEST_DOC_TEXTFRAME: case EXCHG_DEST_SWDOC_FREE_AREA: case EXCHG_DEST_DOC_TEXTFRAME_WEB: case EXCHG_DEST_SWDOC_FREE_AREA_WEB: bDelSel = true; break; } if( bDelSel ) // #i34830# pAction.reset(new SwTrnsfrActionAndUndo( &rSh, UNDO_PASTE_CLIPBOARD, NULL, true )); } SwTransferable *pTrans=0, *pTunneledTrans=GetSwTransferable( rData ); // check for private drop bool bPrivateDrop(pPt && (bPasteSelection ? 0 != (pTrans = pMod->pXSelection) : 0 != (pTrans = pMod->pDragDrop))); bool bNeedToSelectBeforePaste(false); if(bPrivateDrop && DND_ACTION_LINK == nDropAction) { // internal drop on object, suppress bPrivateDrop to change internal fill bPrivateDrop = false; bNeedToSelectBeforePaste = true; } if(bPrivateDrop && pPt && DND_ACTION_MOVE == nDropAction) { // check if dragged over a useful target. If yes, use as content exchange // drop as if from external const SwFrmFmt* pSwFrmFmt = rSh.GetFmtFromObj(*pPt); if(pSwFrmFmt && 0 != dynamic_cast< const SwDrawFrmFmt* >(pSwFrmFmt)) { bPrivateDrop = false; bNeedToSelectBeforePaste = true; } } if(bPrivateDrop) { // then internal Drag & Drop or XSelection nRet = pTrans->PrivateDrop( rSh, *pPt, DND_ACTION_MOVE == nDropAction, bPasteSelection ); } else if( !pPt && pTunneledTrans && EXCHG_OUT_ACTION_INSERT_PRIVATE == nAction ) { // then internal paste nRet = pTunneledTrans->PrivatePaste( rSh ); } else if( EXCHG_INOUT_ACTION_NONE != nAction ) { if( !pAction ) { pAction.reset(new SwTrnsfrActionAndUndo( &rSh, UNDO_PASTE_CLIPBOARD)); } // in Drag&Drop MessageBoxes must not be showed bool bMsg = 0 == pPt; sal_uInt8 nActionFlags = static_cast< sal_uInt8 >(( nAction >> 8 ) & 0xFF); sal_uInt16 nClearedAction = ( nAction & EXCHG_ACTION_MASK ); // delete selections switch( nClearedAction ) { case EXCHG_OUT_ACTION_INSERT_PRIVATE: OSL_ENSURE( pPt, "EXCHG_OUT_ACTION_INSERT_PRIVATE: what should happen here?" ); break; case EXCHG_OUT_ACTION_MOVE_PRIVATE: OSL_ENSURE( pPt, "EXCHG_OUT_ACTION_MOVE_PRIVATE: what should happen here?" ); break; case EXCHG_IN_ACTION_MOVE: case EXCHG_IN_ACTION_COPY: case EXCHG_IN_ACTION_LINK: case EXCHG_OUT_ACTION_INSERT_HTML: case EXCHG_OUT_ACTION_INSERT_STRING: case EXCHG_OUT_ACTION_INSERT_IMAGEMAP: case EXCHG_OUT_ACTION_REPLACE_IMAGEMAP: // then we have to use the format switch( nFormat ) { case SOT_FORMATSTR_ID_DRAWING: nRet = SwTransferable::_PasteSdrFormat( rData, rSh, SW_PASTESDR_INSERT, pPt, nActionFlags, bNeedToSelectBeforePaste); break; case SOT_FORMATSTR_ID_HTML: case SOT_FORMATSTR_ID_HTML_SIMPLE: case SOT_FORMATSTR_ID_HTML_NO_COMMENT: case SOT_FORMAT_RTF: case SOT_FORMAT_STRING: nRet = SwTransferable::_PasteFileContent( rData, rSh, nFormat, bMsg ); break; case SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK: { INetBookmark aBkmk; if( rData.GetINetBookmark( nFormat, aBkmk ) ) { SwFmtINetFmt aFmt( aBkmk.GetURL(), OUString() ); rSh.InsertURL( aFmt, aBkmk.GetDescription() ); nRet = true; } } break; case SOT_FORMATSTR_ID_SD_OLE: nRet = SwTransferable::_PasteOLE( rData, rSh, nFormat, nActionFlags, bMsg ); break; case SOT_FORMATSTR_ID_SVIM: nRet = SwTransferable::_PasteImageMap( rData, rSh ); break; case SOT_FORMATSTR_ID_SVXB: case SOT_FORMAT_BITMAP: case SOT_FORMATSTR_ID_PNG: case SOT_FORMAT_GDIMETAFILE: nRet = SwTransferable::_PasteGrf( rData, rSh, nFormat, SW_PASTESDR_INSERT,pPt, nActionFlags, nDropAction, bNeedToSelectBeforePaste); break; case SOT_FORMATSTR_ID_XFORMS: case SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE: case SOT_FORMATSTR_ID_SBA_DATAEXCHANGE: case SOT_FORMATSTR_ID_SBA_CTRLDATAEXCHANGE: nRet = SwTransferable::_PasteDBData( rData, rSh, nFormat, EXCHG_IN_ACTION_LINK == nClearedAction, pPt, bMsg ); break; case SOT_FORMAT_FILE: nRet = SwTransferable::_PasteFileName( rData, rSh, nFormat, ( EXCHG_IN_ACTION_MOVE == nClearedAction ? SW_PASTESDR_REPLACE : EXCHG_IN_ACTION_LINK == nClearedAction ? SW_PASTESDR_SETATTR : SW_PASTESDR_INSERT), pPt, nActionFlags, bMsg, 0 ); break; case SOT_FORMAT_FILE_LIST: // then insert as graphics only nRet = SwTransferable::_PasteFileList( rData, rSh, EXCHG_IN_ACTION_LINK == nClearedAction, pPt, bMsg ); break; case SOT_FORMATSTR_ID_SONLK: if( pPt ) { NaviContentBookmark aBkmk; if( aBkmk.Paste( rData ) ) { if(bIsDefault) { switch(aBkmk.GetDefaultDragType()) { case REGION_MODE_NONE: nClearedAction = EXCHG_IN_ACTION_COPY; break; case REGION_MODE_EMBEDDED: nClearedAction = EXCHG_IN_ACTION_MOVE; break; case REGION_MODE_LINK: nClearedAction = EXCHG_IN_ACTION_LINK; break; } } rSh.NavigatorPaste( aBkmk, nClearedAction ); nRet = true; } } break; case SOT_FORMATSTR_ID_INET_IMAGE: case SOT_FORMATSTR_ID_NETSCAPE_IMAGE: nRet = SwTransferable::_PasteTargetURL( rData, rSh, SW_PASTESDR_INSERT, pPt, true ); break; default: OSL_ENSURE( pPt, "unknown format" ); } break; case EXCHG_OUT_ACTION_INSERT_FILE: { bool graphicInserted; nRet = SwTransferable::_PasteFileName( rData, rSh, nFormat, SW_PASTESDR_INSERT, pPt, nActionFlags, bMsg, &graphicInserted ); if( graphicInserted ) bCallAutoCaption = true; } break; case EXCHG_OUT_ACTION_INSERT_OLE: nRet = SwTransferable::_PasteOLE( rData, rSh, nFormat, nActionFlags,bMsg ); break; case EXCHG_OUT_ACTION_INSERT_DDE: { bool bReRead = 0 != CNT_HasGrf( rSh.GetCntType() ); nRet = SwTransferable::_PasteDDE( rData, rSh, bReRead, bMsg ); } break; case EXCHG_OUT_ACTION_INSERT_HYPERLINK: { OUString sURL, sDesc; if( SOT_FORMAT_FILE == nFormat ) { if( rData.GetString( nFormat, sURL ) && !sURL.isEmpty() ) { SwTransferable::_CheckForURLOrLNKFile( rData, sURL, &sDesc ); if( sDesc.isEmpty() ) sDesc = sURL; nRet = true; } } else { INetBookmark aBkmk; if( rData.GetINetBookmark( nFormat, aBkmk ) ) { sURL = aBkmk.GetURL(); sDesc = aBkmk.GetDescription(); nRet = true; } } if( nRet ) { SwFmtINetFmt aFmt( sURL, OUString() ); rSh.InsertURL( aFmt, sDesc ); } } break; case EXCHG_OUT_ACTION_GET_ATTRIBUTES: switch( nFormat ) { case SOT_FORMATSTR_ID_DRAWING: nRet = SwTransferable::_PasteSdrFormat( rData, rSh, SW_PASTESDR_SETATTR, pPt, nActionFlags, bNeedToSelectBeforePaste); break; case SOT_FORMATSTR_ID_SVXB: case SOT_FORMAT_GDIMETAFILE: case SOT_FORMAT_BITMAP: case SOT_FORMATSTR_ID_PNG: case SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK: case SOT_FORMAT_FILE: case SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR: case SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR: nRet = SwTransferable::_PasteGrf( rData, rSh, nFormat, SW_PASTESDR_SETATTR, pPt, nActionFlags, nDropAction, bNeedToSelectBeforePaste); break; default: OSL_FAIL( "unknown format" ); } break; case EXCHG_OUT_ACTION_INSERT_DRAWOBJ: nRet = SwTransferable::_PasteSdrFormat( rData, rSh, SW_PASTESDR_INSERT, pPt, nActionFlags, bNeedToSelectBeforePaste); break; case EXCHG_OUT_ACTION_INSERT_SVXB: case EXCHG_OUT_ACTION_INSERT_GDIMETAFILE: case EXCHG_OUT_ACTION_INSERT_BITMAP: case EXCHG_OUT_ACTION_INSERT_GRAPH: nRet = SwTransferable::_PasteGrf( rData, rSh, nFormat, SW_PASTESDR_INSERT, pPt, nActionFlags, nDropAction, bNeedToSelectBeforePaste); break; case EXCHG_OUT_ACTION_REPLACE_DRAWOBJ: nRet = SwTransferable::_PasteSdrFormat( rData, rSh, SW_PASTESDR_REPLACE, pPt, nActionFlags, bNeedToSelectBeforePaste); break; case EXCHG_OUT_ACTION_REPLACE_SVXB: case EXCHG_OUT_ACTION_REPLACE_GDIMETAFILE: case EXCHG_OUT_ACTION_REPLACE_BITMAP: case EXCHG_OUT_ACTION_REPLACE_GRAPH: nRet = SwTransferable::_PasteGrf( rData, rSh, nFormat, SW_PASTESDR_REPLACE,pPt, nActionFlags, nDropAction, bNeedToSelectBeforePaste); break; case EXCHG_OUT_ACTION_INSERT_INTERACTIVE: nRet = SwTransferable::_PasteAsHyperlink( rData, rSh, nFormat ); break; default: OSL_FAIL("unknown action" ); } } if( !bPasteSelection && rSh.IsFrmSelected() ) { rSh.EnterSelFrmMode(); //force ::SelectShell rSh.GetView().StopShellTimer(); } pAction.reset(); if( bCallAutoCaption ) rSh.GetView().AutoCaption( GRAPHIC_CAP ); return nRet; } sal_uInt16 SwTransferable::GetSotDestination( const SwWrtShell& rSh, const Point* pPt ) { sal_uInt16 nRet = EXCHG_INOUT_ACTION_NONE; ObjCntType eOType; if( pPt ) { SdrObject *pObj = 0; eOType = rSh.GetObjCntType( *pPt, pObj ); } else eOType = rSh.GetObjCntTypeOfSelection(); switch( eOType ) { case OBJCNT_GRF: { bool bIMap, bLink; if( pPt ) { bIMap = 0 != rSh.GetFmtFromObj( *pPt )->GetURL().GetMap(); OUString aDummy; rSh.GetGrfAtPos( *pPt, aDummy, bLink ); } else { bIMap = 0 != rSh.GetFlyFrmFmt()->GetURL().GetMap(); OUString aDummy; rSh.GetGrfNms( &aDummy, 0 ); bLink = !aDummy.isEmpty(); } if( bLink && bIMap ) nRet = EXCHG_DEST_DOC_LNKD_GRAPH_W_IMAP; else if( bLink ) nRet = EXCHG_DEST_DOC_LNKD_GRAPHOBJ; else if( bIMap ) nRet = EXCHG_DEST_DOC_GRAPH_W_IMAP; else nRet = EXCHG_DEST_DOC_GRAPHOBJ; } break; case OBJCNT_FLY: if( rSh.GetView().GetDocShell()->ISA(SwWebDocShell) ) nRet = EXCHG_DEST_DOC_TEXTFRAME_WEB; else nRet = EXCHG_DEST_DOC_TEXTFRAME; break; case OBJCNT_OLE: nRet = EXCHG_DEST_DOC_OLEOBJ; break; case OBJCNT_CONTROL: /* no Action avail */ case OBJCNT_SIMPLE: nRet = EXCHG_DEST_DOC_DRAWOBJ; break; case OBJCNT_URLBUTTON: nRet = EXCHG_DEST_DOC_URLBUTTON; break; case OBJCNT_GROUPOBJ: nRet = EXCHG_DEST_DOC_GROUPOBJ; break; // what do we do at multiple selections??? default: { if( rSh.GetView().GetDocShell()->ISA(SwWebDocShell) ) nRet = EXCHG_DEST_SWDOC_FREE_AREA_WEB; else nRet = EXCHG_DEST_SWDOC_FREE_AREA; } } return nRet; } bool SwTransferable::_PasteFileContent( TransferableDataHelper& rData, SwWrtShell& rSh, sal_uLong nFmt, bool bMsg ) { sal_uInt16 nResId = MSG_CLPBRD_FORMAT_ERROR; bool nRet = false; MSE40HTMLClipFormatObj aMSE40ClpObj; SotStorageStreamRef xStrm; SvStream* pStream = 0; SwRead pRead = 0; OUString sData; switch( nFmt ) { case SOT_FORMAT_STRING: { pRead = ReadAscii; if( rData.GetString( nFmt, sData ) ) { pStream = new SvMemoryStream( (void*)sData.getStr(), sData.getLength() * sizeof( sal_Unicode ), STREAM_READ ); #ifdef OSL_BIGENDIAN pStream->SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN ); #else pStream->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); #endif SwAsciiOptions aAOpt; aAOpt.SetCharSet( RTL_TEXTENCODING_UCS2 ); pRead->GetReaderOpt().SetASCIIOpts( aAOpt ); break; } } // no break - because then test if we get a stream default: if( rData.GetSotStorageStream( nFmt, xStrm ) ) { if( ( SOT_FORMATSTR_ID_HTML_SIMPLE == nFmt ) || ( SOT_FORMATSTR_ID_HTML_NO_COMMENT == nFmt ) ) { pStream = aMSE40ClpObj.IsValid( *xStrm ); pRead = ReadHTML; pRead->SetReadUTF8( true ); bool bNoComments = ( nFmt == SOT_FORMATSTR_ID_HTML_NO_COMMENT ); pRead->SetIgnoreHTMLComments( bNoComments ); } else { pStream = &xStrm; if( SOT_FORMAT_RTF == nFmt ) pRead = SwReaderWriter::GetReader( READER_WRITER_RTF ); else if( !pRead ) { pRead = ReadHTML; pRead->SetReadUTF8( true ); } } } break; } if( pStream && pRead ) { Link aOldLink( rSh.GetChgLnk() ); rSh.SetChgLnk( Link() ); const SwPosition& rInsPos = *rSh.GetCrsr()->Start(); SwReader aReader( *pStream, aEmptyOUStr, OUString(), *rSh.GetCrsr() ); rSh.SaveTblBoxCntnt( &rInsPos ); if( IsError( aReader.Read( *pRead )) ) nResId = ERR_CLPBRD_READ; else nResId = 0, nRet = true; rSh.SetChgLnk( aOldLink ); if( nRet ) rSh.CallChgLnk(); } else nResId = MSG_CLPBRD_FORMAT_ERROR; // Exist a SvMemoryStream? (data in the OUString and xStrm is empty) if( pStream && !xStrm.Is() ) delete pStream; if( bMsg && nResId ) { InfoBox( 0, SW_RES( nResId )).Execute(); } return nRet; } bool SwTransferable::_PasteOLE( TransferableDataHelper& rData, SwWrtShell& rSh, sal_uLong nFmt, sal_uInt8 nActionFlags, bool bMsg ) { bool nRet = false; TransferableObjectDescriptor aObjDesc; uno::Reference < io::XInputStream > xStrm; uno::Reference < embed::XStorage > xStore; Reader* pRead = 0; // Get the preferred format SotFormatStringId nId; if( rData.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ ) ) nId = SOT_FORMATSTR_ID_EMBEDDED_OBJ; else if( rData.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ) && rData.HasFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR )) nId = SOT_FORMATSTR_ID_EMBED_SOURCE; else nId = 0; if( nId && rData.GetInputStream( nId, xStrm ) && xStrm.is() ) { // if there is an embedded object, first try if it's a writer object // this will be inserted into the document by using a Reader try { xStore = comphelper::OStorageHelper::GetStorageFromInputStream( xStrm ); switch( SotStorage::GetFormatID( xStore ) ) { case SOT_FORMATSTR_ID_STARWRITER_60: case SOT_FORMATSTR_ID_STARWRITERWEB_60: case SOT_FORMATSTR_ID_STARWRITERGLOB_60: case SOT_FORMATSTR_ID_STARWRITER_8: case SOT_FORMATSTR_ID_STARWRITERWEB_8: case SOT_FORMATSTR_ID_STARWRITERGLOB_8: pRead = ReadXML; break; default: try { uno::Reference < lang::XComponent > xComp( xStore, uno::UNO_QUERY ); xComp->dispose(); xStore = 0; } catch (const uno::Exception&) { } break; } } catch (const uno::Exception&) { // it wasn't a storage, but maybe it's a useful stream } nFmt = nId; } if( pRead ) { SwPaM &rPAM = *rSh.GetCrsr(); SwReader aReader( xStore, aEmptyOUStr, rPAM ); if( !IsError( aReader.Read( *pRead )) ) nRet = true; else if( bMsg ) InfoBox( 0, SW_RES(ERR_CLPBRD_READ) ).Execute(); } else { // temporary storage until the object is inserted uno::Reference< embed::XStorage > xTmpStor; uno::Reference < embed::XEmbeddedObject > xObj; OUString aName; comphelper::EmbeddedObjectContainer aCnt; if ( xStrm.is() ) { if ( !rData.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) ) { OSL_ENSURE( !xStrm.is(), "An object without descriptor in clipboard!"); } } else { if( rData.HasFormat( nFmt = SOT_FORMATSTR_ID_OBJECTDESCRIPTOR_OLE ) && rData.GetTransferableObjectDescriptor( nFmt, aObjDesc ) ) { if ( !rData.GetInputStream( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE, xStrm ) ) rData.GetInputStream( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE, xStrm ); if ( !xStrm.is() ) { // This is MSOLE object that should be created by direct using of system clipboard try { xTmpStor = ::comphelper::OStorageHelper::GetTemporaryStorage(); uno::Reference < embed::XEmbedObjectClipboardCreator > xClipboardCreator = embed::MSOLEObjectSystemCreator::create( ::comphelper::getProcessComponentContext() ); embed::InsertedObjectInfo aInfo = xClipboardCreator->createInstanceInitFromClipboard( xTmpStor, OUString( "DummyName" ), uno::Sequence< beans::PropertyValue >() ); // TODO/LATER: in future InsertedObjectInfo will be used to get container related information // for example whether the object should be an iconified one xObj = aInfo.Object; } catch (const uno::Exception&) { } } } } if ( xStrm.is() && !xObj.is() ) xObj = aCnt.InsertEmbeddedObject( xStrm, aName ); if( xObj.is() ) { svt::EmbeddedObjectRef xObjRef( xObj, aObjDesc.mnViewAspect ); // try to get the replacement image from the clipboard Graphic aGraphic; sal_uLong nGrFormat = 0; // limit the size of the preview metafile to 100000 actions GDIMetaFile aMetafile; if (rData.GetGDIMetaFile(FORMAT_GDIMETAFILE, aMetafile, 100000)) { nGrFormat = SOT_FORMAT_GDIMETAFILE; aGraphic = aMetafile; } // insert replacement image ( if there is one ) into the object helper if ( nGrFormat ) { DataFlavor aDataFlavor; SotExchange::GetFormatDataFlavor( nGrFormat, aDataFlavor ); xObjRef.SetGraphic( aGraphic, aDataFlavor.MimeType ); } else if ( aObjDesc.mnViewAspect == embed::Aspects::MSOLE_ICON ) { // it is important to have an icon, let an empty graphic be used // if no other graphic is provided // TODO/LATER: in future a default bitmap could be used OUString aMimeType; MapMode aMapMode( MAP_100TH_MM ); aGraphic.SetPrefSize( Size( 2500, 2500 ) ); aGraphic.SetPrefMapMode( aMapMode ); xObjRef.SetGraphic( aGraphic, aMimeType ); } //set size. This is a hack because of handing over, size should be //passed to the InsertOle!!!!!!!!!! Size aSize; if ( aObjDesc.mnViewAspect == embed::Aspects::MSOLE_ICON ) { if( aObjDesc.maSize.Width() && aObjDesc.maSize.Height() ) aSize = aObjDesc.maSize; else { MapMode aMapMode( MAP_100TH_MM ); aSize = xObjRef.GetSize( &aMapMode ); } } else if( aObjDesc.maSize.Width() && aObjDesc.maSize.Height() ) { aSize = Size( aObjDesc.maSize ); //always 100TH_MM MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( aObjDesc.mnViewAspect ) ); aSize = OutputDevice::LogicToLogic( aSize, MAP_100TH_MM, aUnit ); awt::Size aSz; try { aSz = xObj->getVisualAreaSize( aObjDesc.mnViewAspect ); } catch (const embed::NoVisualAreaSizeException&) { // in this case the provided size is used } if ( aSz.Width != aSize.Width() || aSz.Height != aSize.Height() ) { aSz.Width = aSize.Width(); aSz.Height = aSize.Height(); xObj->setVisualAreaSize( aObjDesc.mnViewAspect, aSz ); } } else { // the descriptor contains the wrong object size // the following call will let the MSOLE objects cache the size if it is possible // it should be done while the object is running try { xObj->getVisualAreaSize( aObjDesc.mnViewAspect ); } catch (const uno::Exception&) { } } //End of Hack! rSh.InsertOleObject( xObjRef ); nRet = true; if( nRet && ( nActionFlags & ( EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL >> 8) )) SwTransferable::_PasteTargetURL( rData, rSh, 0, 0, false ); // let the object be unloaded if possible SwOLEObj::UnloadObject( xObj, rSh.GetDoc(), embed::Aspects::MSOLE_CONTENT ); } } return nRet; } bool SwTransferable::_PasteTargetURL( TransferableDataHelper& rData, SwWrtShell& rSh, sal_uInt16 nAction, const Point* pPt, bool bInsertGRF ) { bool nRet = false; INetImage aINetImg; if( ( rData.HasFormat( SOT_FORMATSTR_ID_INET_IMAGE ) && rData.GetINetImage( SOT_FORMATSTR_ID_INET_IMAGE, aINetImg )) || ( rData.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_IMAGE ) && rData.GetINetImage( SOT_FORMATSTR_ID_NETSCAPE_IMAGE, aINetImg )) ) { if( !aINetImg.GetImageURL().isEmpty() && bInsertGRF ) { OUString sURL( aINetImg.GetImageURL() ); SwTransferable::_CheckForURLOrLNKFile( rData, sURL ); //!!! check at FileSystem - only then it make sense to test graphics !!! Graphic aGraphic; GraphicFilter &rFlt = GraphicFilter::GetGraphicFilter(); nRet = GRFILTER_OK == GraphicFilter::LoadGraphic( sURL, aEmptyOUStr, aGraphic, &rFlt ); if( nRet ) { //Check and Perform rotation if needed lclCheckAndPerformRotation(aGraphic); switch( nAction ) { case SW_PASTESDR_INSERT: SwTransferable::SetSelInShell( rSh, false, pPt ); rSh.Insert( sURL, aEmptyOUStr, aGraphic ); break; case SW_PASTESDR_REPLACE: if( rSh.IsObjSelected() ) { rSh.ReplaceSdrObj( sURL, aEmptyOUStr, &aGraphic ); Point aPt( pPt ? *pPt : rSh.GetCrsrDocPos() ); SwTransferable::SetSelInShell( rSh, true, &aPt ); } else rSh.ReRead( sURL, aEmptyOUStr, &aGraphic ); break; case SW_PASTESDR_SETATTR: if( rSh.IsObjSelected() ) rSh.Paste( aGraphic, OUString() ); else if( OBJCNT_GRF == rSh.GetObjCntTypeOfSelection() ) rSh.ReRead( sURL, aEmptyOUStr, &aGraphic ); else { SwTransferable::SetSelInShell( rSh, false, pPt ); rSh.Insert( sURL, aEmptyOUStr, aGraphic ); } break; default: nRet = false; } } } else nRet = true; } if( nRet ) { SfxItemSet aSet( rSh.GetAttrPool(), RES_URL, RES_URL ); rSh.GetFlyFrmAttr( aSet ); SwFmtURL aURL( (SwFmtURL&)aSet.Get( RES_URL ) ); if( aURL.GetURL() != aINetImg.GetTargetURL() || aURL.GetTargetFrameName() != aINetImg.GetTargetFrame() ) { aURL.SetURL( aINetImg.GetTargetURL(), false ); aURL.SetTargetFrameName( aINetImg.GetTargetFrame() ); aSet.Put( aURL ); rSh.SetFlyFrmAttr( aSet ); } } return nRet; } void SwTransferable::SetSelInShell( SwWrtShell& rSh, bool bSelectFrm, const Point* pPt ) { if( bSelectFrm ) { // select frames/objects if( pPt && !rSh.GetView().GetViewFrame()->GetDispatcher()->IsLocked() ) { rSh.GetView().NoRotate(); if( rSh.SelectObj( *pPt )) { rSh.HideCrsr(); rSh.EnterSelFrmMode( pPt ); bFrmDrag = true; } } } else { if( rSh.IsFrmSelected() || rSh.IsObjSelected() ) { rSh.UnSelectFrm(); rSh.LeaveSelFrmMode(); rSh.GetView().GetEditWin().StopInsFrm(); bFrmDrag = false; } else if( rSh.GetView().GetDrawFuncPtr() ) rSh.GetView().GetEditWin().StopInsFrm(); rSh.EnterStdMode(); if( pPt ) rSh.SwCrsrShell::SetCrsr( *pPt, true ); } } bool SwTransferable::_PasteDDE( TransferableDataHelper& rData, SwWrtShell& rWrtShell, bool bReReadGrf, bool bMsg ) { // data from Clipboardformat OUString aApp, aTopic, aItem; { SotStorageStreamRef xStrm; if( !rData.GetSotStorageStream( SOT_FORMATSTR_ID_LINK, xStrm )) { OSL_ENSURE( !&rWrtShell, "DDE Data not found." ); return false; } // report useful error!! rtl_TextEncoding eEncoding = DDE_TXT_ENCODING; aApp = read_zeroTerminated_uInt8s_ToOUString(*xStrm, eEncoding); aTopic = read_zeroTerminated_uInt8s_ToOUString(*xStrm, eEncoding); aItem = read_zeroTerminated_uInt8s_ToOUString(*xStrm, eEncoding); } OUString aCmd; sfx2::MakeLnkName( aCmd, &aApp, aTopic, aItem ); // do we want to read in a graphic now? sal_uLong nFormat; if( !rData.HasFormat( FORMAT_RTF ) && !rData.HasFormat( SOT_FORMATSTR_ID_HTML ) && !rData.HasFormat( FORMAT_STRING ) && (rData.HasFormat( nFormat = FORMAT_GDIMETAFILE ) || rData.HasFormat( nFormat = FORMAT_BITMAP )) ) { Graphic aGrf; bool nRet = rData.GetGraphic( nFormat, aGrf ); if( nRet ) { OUString sLnkTyp("DDE"); if ( bReReadGrf ) rWrtShell.ReRead( aCmd, sLnkTyp, &aGrf ); else rWrtShell.Insert( aCmd, sLnkTyp, aGrf ); } return nRet; } SwFieldType* pTyp = 0; sal_uInt16 i = 1,j; OUString aName; bool bAlreadyThere = false, bDoublePaste = false; sal_uInt16 nSize = rWrtShell.GetFldTypeCount(); const ::utl::TransliterationWrapper& rColl = ::GetAppCmpStrIgnore(); do { aName = aApp; aName += OUString::number( i ); for( j = INIT_FLDTYPES; j < nSize; j++ ) { pTyp = rWrtShell.GetFldType( j ); if( RES_DDEFLD == pTyp->Which() ) { OUString sTmp( ((SwDDEFieldType*)pTyp)->GetCmd() ); if( rColl.isEqual( sTmp, aCmd ) && sfx2::LINKUPDATE_ALWAYS == ((SwDDEFieldType*)pTyp)->GetType() ) { aName = pTyp->GetName(); bDoublePaste = true; break; } else if( rColl.isEqual( aName, pTyp->GetName() ) ) break; } } if( j == nSize ) bAlreadyThere = false; else { bAlreadyThere = true; i++; } } while( bAlreadyThere && !bDoublePaste ); if( !bDoublePaste ) { SwDDEFieldType aType( aName, aCmd, sfx2::LINKUPDATE_ALWAYS ); pTyp = rWrtShell.InsertFldType( aType ); } SwDDEFieldType* pDDETyp = (SwDDEFieldType*)pTyp; OUString aExpand; if( rData.GetString( FORMAT_STRING, aExpand )) { do { // middle checked loop // When data comes from a spreadsheet, we add a DDE-table if( ( rData.HasFormat( SOT_FORMATSTR_ID_SYLK ) || rData.HasFormat( SOT_FORMATSTR_ID_SYLK_BIGCAPS ) ) && !aExpand.isEmpty() && ( 1 < comphelper::string::getTokenCount(aExpand, '\n') || comphelper::string::getTokenCount(aExpand, '\t') ) ) { OUString sTmp( aExpand ); sal_Int32 nRows = comphelper::string::getTokenCount(sTmp, '\n'); if( nRows ) --nRows; sTmp = sTmp.getToken( 0, '\n' ); sal_Int32 nCols = comphelper::string::getTokenCount(sTmp, '\t'); // at least one column & row must be there if( !nRows || !nCols ) { if( bMsg ) InfoBox(0, SW_RESSTR(STR_NO_TABLE)).Execute(); pDDETyp = 0; break; } rWrtShell.InsertDDETable( SwInsertTableOptions( tabopts::SPLIT_LAYOUT, 1 ), // TODO MULTIHEADER pDDETyp, nRows, nCols ); } else if( 1 < comphelper::string::getTokenCount(aExpand, '\n') ) { // multiple paragraphs -> insert a protected section if( rWrtShell.HasSelection() ) rWrtShell.DelRight(); SwSectionData aSect( DDE_LINK_SECTION, aName ); aSect.SetLinkFileName( aCmd ); aSect.SetProtectFlag(true); rWrtShell.InsertSection( aSect ); pDDETyp = 0; // remove FieldTypes again } else { // Einfuegen SwDDEField aSwDDEField( pDDETyp ); rWrtShell.Insert( aSwDDEField ); } } while( false ); } else pDDETyp = 0; // remove FieldTypes again if( !pDDETyp && !bDoublePaste ) { // remove FieldType again - error occurred! for( j = nSize; j >= INIT_FLDTYPES; --j ) if( pTyp == rWrtShell.GetFldType( j ) ) { rWrtShell.RemoveFldType( j ); break; } } return true; } bool SwTransferable::_PasteSdrFormat( TransferableDataHelper& rData, SwWrtShell& rSh, sal_uInt16 nAction, const Point* pPt, sal_uInt8 nActionFlags, bool bNeedToSelectBeforePaste) { bool nRet = false; SotStorageStreamRef xStrm; if( rData.GetSotStorageStream( SOT_FORMATSTR_ID_DRAWING, xStrm )) { xStrm->SetVersion( SOFFICE_FILEFORMAT_50 ); if(bNeedToSelectBeforePaste && pPt) { // if this is an internal drag, need to set the target right (select it), else // still the source will be selected SwTransferable::SetSelInShell( rSh, true, pPt ); } rSh.Paste( *xStrm, nAction, pPt ); nRet = true; if( nRet && ( nActionFlags & ( EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL >> 8) )) SwTransferable::_PasteTargetURL( rData, rSh, 0, 0, false ); } return nRet; } bool SwTransferable::_PasteGrf( TransferableDataHelper& rData, SwWrtShell& rSh, sal_uLong nFmt, sal_uInt16 nAction, const Point* pPt, sal_uInt8 nActionFlags, sal_Int8 nDropAction, bool bNeedToSelectBeforePaste) { bool nRet = false; Graphic aGraphic; INetBookmark aBkmk; bool bCheckForGrf = false, bCheckForImageMap = false; switch( nFmt ) { case SOT_FORMAT_BITMAP: case SOT_FORMATSTR_ID_PNG: case SOT_FORMAT_GDIMETAFILE: nRet = rData.GetGraphic( nFmt, aGraphic ); break; case SOT_FORMATSTR_ID_SVXB: { SotStorageStreamRef xStm; if(rData.GetSotStorageStream(SOT_FORMATSTR_ID_SVXB, xStm)) { ReadGraphic( *xStm, aGraphic ); nRet = (GRAPHIC_NONE != aGraphic.GetType() && GRAPHIC_DEFAULT != aGraphic.GetType()); } break; } case SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK: case SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR: case SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR: if( ( nRet = rData.GetINetBookmark( nFmt, aBkmk ) )) { if( SW_PASTESDR_SETATTR == nAction ) nFmt = SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK; else bCheckForGrf = true; } break; case SOT_FORMAT_FILE: { OUString sTxt; if( ( nRet = rData.GetString( nFmt, sTxt ) ) ) { OUString sDesc; SwTransferable::_CheckForURLOrLNKFile( rData, sTxt, &sDesc ); aBkmk = INetBookmark( URIHelper::SmartRel2Abs(INetURLObject(), sTxt, Link(), false ), sDesc ); bCheckForGrf = true; bCheckForImageMap = SW_PASTESDR_REPLACE == nAction; } } break; default: nRet = rData.GetGraphic( nFmt, aGraphic ); break; } if( bCheckForGrf ) { //!!! check at FileSystem - only then it makes sense to test the graphics !!! GraphicFilter &rFlt = GraphicFilter::GetGraphicFilter(); nRet = GRFILTER_OK == GraphicFilter::LoadGraphic( aBkmk.GetURL(), aEmptyOUStr, aGraphic, &rFlt ); if( !nRet && SW_PASTESDR_SETATTR == nAction && SOT_FORMAT_FILE == nFmt && // only at frame selection rSh.IsFrmSelected() ) { // then set as hyperlink after the graphic nFmt = SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK; nRet = true; } } if(pPt && bNeedToSelectBeforePaste) { // when using internal D&Ds, still the source object is selected and // this is necessary to get the correct source data which is also // dependent from selection. After receiving the drag data it is // now tiime to select the correct target object SwTransferable::SetSelInShell( rSh, true, pPt ); } if( nRet ) { //Check and Perform rotation if needed lclCheckAndPerformRotation(aGraphic); OUString sURL; if( rSh.GetView().GetDocShell()->ISA(SwWebDocShell) // #i123922# if link action is noted, also take URL || DND_ACTION_LINK == nDropAction) { sURL = aBkmk.GetURL(); } switch( nAction ) { case SW_PASTESDR_INSERT: { SwTransferable::SetSelInShell( rSh, false, pPt ); rSh.Insert( sURL, aEmptyOUStr, aGraphic ); break; } case SW_PASTESDR_REPLACE: { if( rSh.IsObjSelected() ) { // #i123922# for D&D on draw objects, do for now the same for // SW_PASTESDR_REPLACE (D&D) as for SW_PASTESDR_SETATTR (D&D and // CTRL+SHIFT). The code below replaces the draw object with // a writer graphic; maybe this is an option later again if wanted rSh.Paste( aGraphic, sURL ); // rSh.ReplaceSdrObj( sURL, aEmptyOUStr, &aGraphic ); // Point aPt( pPt ? *pPt : rSh.GetCrsrDocPos() ); // SwTransferable::SetSelInShell( rSh, sal_True, &aPt ); } else { // set graphic at writer graphic without link rSh.ReRead( sURL, aEmptyOUStr, &aGraphic ); } break; } case SW_PASTESDR_SETATTR: { if( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK == nFmt ) { if( rSh.IsFrmSelected() ) { SfxItemSet aSet( rSh.GetAttrPool(), RES_URL, RES_URL ); rSh.GetFlyFrmAttr( aSet ); SwFmtURL aURL( (SwFmtURL&)aSet.Get( RES_URL ) ); aURL.SetURL( aBkmk.GetURL(), false ); aSet.Put( aURL ); rSh.SetFlyFrmAttr( aSet ); } } else if( rSh.IsObjSelected() ) { // set as attribute at DrawObject rSh.Paste( aGraphic, sURL ); } else if( OBJCNT_GRF == rSh.GetObjCntTypeOfSelection() ) { // set as linked graphic at writer graphic frame rSh.ReRead( sURL, aEmptyOUStr, &aGraphic ); } else { SwTransferable::SetSelInShell( rSh, false, pPt ); rSh.Insert( aBkmk.GetURL(), aEmptyOUStr, aGraphic ); } break; } default: { nRet = false; break; } } } if( nRet ) { if( nActionFlags & (( EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_REPLACE_IMAGEMAP ) >> 8) ) SwTransferable::_PasteImageMap( rData, rSh ); if( nActionFlags & ( EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL >> 8) ) SwTransferable::_PasteTargetURL( rData, rSh, 0, 0, false ); } else if( bCheckForImageMap ) { // or should the file be an ImageMap-File? ImageMap aMap; SfxMedium aMed( INetURLObject(aBkmk.GetURL()).GetFull(), STREAM_STD_READ ); SvStream* pStream = aMed.GetInStream(); if( pStream != NULL && !pStream->GetError() && // mba: no BaseURL for clipboard functionality aMap.Read( *pStream, IMAP_FORMAT_DETECT, OUString() ) == IMAP_ERR_OK && aMap.GetIMapObjectCount() ) { SfxItemSet aSet( rSh.GetAttrPool(), RES_URL, RES_URL ); rSh.GetFlyFrmAttr( aSet ); SwFmtURL aURL( (SwFmtURL&)aSet.Get( RES_URL ) ); aURL.SetMap( &aMap ); aSet.Put( aURL ); rSh.SetFlyFrmAttr( aSet ); nRet = true; } } return nRet; } bool SwTransferable::_PasteImageMap( TransferableDataHelper& rData, SwWrtShell& rSh ) { bool nRet = false; if( rData.HasFormat( SOT_FORMATSTR_ID_SVIM )) { SfxItemSet aSet( rSh.GetAttrPool(), RES_URL, RES_URL ); rSh.GetFlyFrmAttr( aSet ); SwFmtURL aURL( (SwFmtURL&)aSet.Get( RES_URL ) ); const ImageMap* pOld = aURL.GetMap(); // set or replace, that is the question ImageMap aImageMap; if( rData.GetImageMap( SOT_FORMATSTR_ID_SVIM, aImageMap ) && ( !pOld || aImageMap != *pOld )) { aURL.SetMap( &aImageMap ); aSet.Put( aURL ); rSh.SetFlyFrmAttr( aSet ); } nRet = true; } return nRet; } bool SwTransferable::_PasteAsHyperlink( TransferableDataHelper& rData, SwWrtShell& rSh, sal_uLong nFmt ) { bool nRet = false; OUString sFile; if( rData.GetString( nFmt, sFile ) && !sFile.isEmpty() ) { OUString sDesc; SwTransferable::_CheckForURLOrLNKFile( rData, sFile, &sDesc ); // first, make the URL absolute INetURLObject aURL; aURL.SetSmartProtocol( INET_PROT_FILE ); aURL.SetSmartURL( sFile ); sFile = aURL.GetMainURL( INetURLObject::NO_DECODE ); switch( rSh.GetObjCntTypeOfSelection() ) { case OBJCNT_FLY: case OBJCNT_GRF: case OBJCNT_OLE: { SfxItemSet aSet( rSh.GetAttrPool(), RES_URL, RES_URL ); rSh.GetFlyFrmAttr( aSet ); SwFmtURL aURL2( (SwFmtURL&)aSet.Get( RES_URL ) ); aURL2.SetURL( sFile, false ); if( aURL2.GetName().isEmpty() ) aURL2.SetName( sFile ); aSet.Put( aURL2 ); rSh.SetFlyFrmAttr( aSet ); } break; default: { rSh.InsertURL( SwFmtINetFmt( sFile, OUString() ), sDesc.isEmpty() ? sFile : sDesc); } } nRet = true; } return nRet; } bool SwTransferable::_PasteFileName( TransferableDataHelper& rData, SwWrtShell& rSh, sal_uLong nFmt, sal_uInt16 nAction, const Point* pPt, sal_uInt8 nActionFlags, bool /* bMsg */, bool * graphicInserted) { bool nRet = SwTransferable::_PasteGrf( rData, rSh, nFmt, nAction, pPt, nActionFlags, 0, false); if (graphicInserted != 0) { *graphicInserted = nRet; } if( !nRet ) { OUString sFile, sDesc; if( rData.GetString( nFmt, sFile ) && !sFile.isEmpty() ) { #if HAVE_FEATURE_AVMEDIA INetURLObject aMediaURL; aMediaURL.SetSmartURL( sFile ); const OUString aMediaURLStr( aMediaURL.GetMainURL( INetURLObject::NO_DECODE ) ); if( ::avmedia::MediaWindow::isMediaURL( aMediaURLStr, ""/*TODO?*/ ) ) { const SfxStringItem aMediaURLItem( SID_INSERT_AVMEDIA, aMediaURLStr ); rSh.GetView().GetViewFrame()->GetDispatcher()->Execute( SID_INSERT_AVMEDIA, SFX_CALLMODE_SYNCHRON, &aMediaURLItem, 0L ); } #else if (false) { } #endif else { bool bIsURLFile = SwTransferable::_CheckForURLOrLNKFile( rData, sFile, &sDesc ); //Own FileFormat? --> insert, not for StarWriter/Web OUString sFileURL = URIHelper::SmartRel2Abs(INetURLObject(), sFile, Link(), false ); const SfxFilter* pFlt = SW_PASTESDR_SETATTR == nAction ? 0 : SwIoSystem::GetFileFilter( sFileURL, aEmptyOUStr ); if( pFlt && !rSh.GetView().GetDocShell()->ISA(SwWebDocShell) ) { // and then pull up the insert-region-dialog by PostUser event SwSectionData * pSect = new SwSectionData( FILE_LINK_SECTION, rSh.GetDoc()->GetUniqueSectionName() ); pSect->SetLinkFileName( sFileURL ); pSect->SetProtectFlag( true ); Application::PostUserEvent( STATIC_LINK( &rSh, SwWrtShell, InsertRegionDialog ), pSect ); nRet = true; } else if( SW_PASTESDR_SETATTR == nAction || ( bIsURLFile && SW_PASTESDR_INSERT == nAction )) { //we can insert foreign files as links after all // first, make the URL absolute INetURLObject aURL; aURL.SetSmartProtocol( INET_PROT_FILE ); aURL.SetSmartURL( sFile ); sFile = aURL.GetMainURL( INetURLObject::NO_DECODE ); switch( rSh.GetObjCntTypeOfSelection() ) { case OBJCNT_FLY: case OBJCNT_GRF: case OBJCNT_OLE: { SfxItemSet aSet( rSh.GetAttrPool(), RES_URL, RES_URL ); rSh.GetFlyFrmAttr( aSet ); SwFmtURL aURL2( (SwFmtURL&)aSet.Get( RES_URL ) ); aURL2.SetURL( sFile, false ); if( aURL2.GetName().isEmpty() ) aURL2.SetName( sFile ); aSet.Put( aURL2 ); rSh.SetFlyFrmAttr( aSet ); } break; default: { rSh.InsertURL( SwFmtINetFmt( sFile, OUString() ), sDesc.isEmpty() ? sFile : sDesc ); } } nRet = true; } } } } return nRet; } bool SwTransferable::_PasteDBData( TransferableDataHelper& rData, SwWrtShell& rSh, sal_uLong nFmt, bool bLink, const Point* pDragPt, bool bMsg ) { bool nRet = false; OUString sTxt; if( rData.GetString( nFmt, sTxt ) && !sTxt.isEmpty() ) { sal_uInt16 nWh = SOT_FORMATSTR_ID_SBA_CTRLDATAEXCHANGE == nFmt ? 0 : SOT_FORMATSTR_ID_SBA_DATAEXCHANGE == nFmt ? (bLink ? FN_QRY_MERGE_FIELD : FN_QRY_INSERT) : (bLink ? 0 : FN_QRY_INSERT_FIELD ); DataFlavorExVector& rVector = rData.GetDataFlavorExVector(); bool bHaveColumnDescriptor = OColumnTransferable::canExtractColumnDescriptor(rVector, CTF_COLUMN_DESCRIPTOR | CTF_CONTROL_EXCHANGE); if ( SOT_FORMATSTR_ID_XFORMS == nFmt ) { SdrObject* pObj; rSh.MakeDrawView(); FmFormView* pFmView = PTR_CAST( FmFormView, rSh.GetDrawView() ); if(pFmView) { const OXFormsDescriptor &rDesc = OXFormsTransferable::extractDescriptor(rData); if(0 != (pObj = pFmView->CreateXFormsControl(rDesc))) { rSh.SwFEShell::InsertDrawObj( *pObj, *pDragPt ); } } } else if( nWh ) { boost::scoped_ptr pConnectionItem; boost::scoped_ptr pCursorItem; boost::scoped_ptr pColumnItem; boost::scoped_ptr pSourceItem; boost::scoped_ptr pCommandItem; boost::scoped_ptr pCommandTypeItem; boost::scoped_ptr pColumnNameItem; boost::scoped_ptr pSelectionItem; bool bDataAvailable = true; ODataAccessDescriptor aDesc; if(bHaveColumnDescriptor) aDesc = OColumnTransferable::extractColumnDescriptor(rData); else if(ODataAccessObjectTransferable::canExtractObjectDescriptor(rVector) ) aDesc = ODataAccessObjectTransferable::extractObjectDescriptor(rData); else bDataAvailable = false; if ( bDataAvailable ) { pConnectionItem.reset(new SfxUsrAnyItem(FN_DB_CONNECTION_ANY, aDesc[daConnection])); pColumnItem.reset(new SfxUsrAnyItem(FN_DB_COLUMN_ANY, aDesc[daColumnObject])); pSourceItem.reset(new SfxUsrAnyItem(FN_DB_DATA_SOURCE_ANY, makeAny(aDesc.getDataSource()))); pCommandItem.reset(new SfxUsrAnyItem(FN_DB_DATA_COMMAND_ANY, aDesc[daCommand])); pCommandTypeItem.reset(new SfxUsrAnyItem(FN_DB_DATA_COMMAND_TYPE_ANY, aDesc[daCommandType])); pColumnNameItem.reset(new SfxUsrAnyItem(FN_DB_DATA_COLUMN_NAME_ANY, aDesc[daColumnName])); pSelectionItem.reset(new SfxUsrAnyItem(FN_DB_DATA_SELECTION_ANY, aDesc[daSelection])); pCursorItem.reset(new SfxUsrAnyItem(FN_DB_DATA_CURSOR_ANY, aDesc[daCursor])); } SwView& rView = rSh.GetView(); //force ::SelectShell rView.StopShellTimer(); SfxStringItem aDataDesc( nWh, sTxt ); rView.GetViewFrame()->GetDispatcher()->Execute( nWh, SFX_CALLMODE_ASYNCHRON, &aDataDesc, pConnectionItem.get(), pColumnItem.get(), pSourceItem.get(), pCommandItem.get(), pCommandTypeItem.get(), pColumnNameItem.get(), pSelectionItem.get(), pCursorItem.get(), 0L); } else { SdrObject* pObj; rSh.MakeDrawView(); FmFormView* pFmView = PTR_CAST( FmFormView, rSh.GetDrawView() ); if (pFmView && bHaveColumnDescriptor) { if ( 0 != (pObj = pFmView->CreateFieldControl( OColumnTransferable::extractColumnDescriptor(rData) ) ) ) rSh.SwFEShell::InsertDrawObj( *pObj, *pDragPt ); } } nRet = true; } else if( bMsg ) { InfoBox( 0, SW_RES(MSG_CLPBRD_FORMAT_ERROR)).Execute(); } return nRet; } bool SwTransferable::_PasteFileList( TransferableDataHelper& rData, SwWrtShell& rSh, bool bLink, const Point* pPt, bool bMsg ) { bool nRet = false; FileList aFileList; if( rData.GetFileList( SOT_FORMAT_FILE_LIST, aFileList ) && aFileList.Count() ) { sal_uInt16 nAct = bLink ? SW_PASTESDR_SETATTR : SW_PASTESDR_INSERT; OUString sFlyNm; // iterate over the filelist for( sal_uLong n = 0, nEnd = aFileList.Count(); n < nEnd; ++n ) { TransferDataContainer* pHlp = new TransferDataContainer; pHlp->CopyString( FORMAT_FILE, aFileList.GetFile( n )); TransferableDataHelper aData( pHlp ); if( SwTransferable::_PasteFileName( aData, rSh, SOT_FORMAT_FILE, nAct, pPt, sal_False, bMsg, 0 )) { if( bLink ) { sFlyNm = rSh.GetFlyName(); SwTransferable::SetSelInShell( rSh, false, pPt ); } nRet = true; } } if( !sFlyNm.isEmpty() ) rSh.GotoFly( sFlyNm ); } else if( bMsg ) { InfoBox( 0, SW_RES(MSG_CLPBRD_FORMAT_ERROR)).Execute(); } return nRet; } bool SwTransferable::_CheckForURLOrLNKFile( TransferableDataHelper& rData, OUString& rFileName, OUString* pTitle ) { bool bIsURLFile = false; INetBookmark aBkmk; if( rData.GetINetBookmark( SOT_FORMATSTR_ID_SOLK, aBkmk ) ) { rFileName = aBkmk.GetURL(); if( pTitle ) *pTitle = aBkmk.GetDescription(); bIsURLFile = true; } else { sal_Int32 nLen = rFileName.getLength(); if( 4 < nLen && '.' == rFileName[ nLen - 4 ]) { OUString sExt( rFileName.copy( nLen - 3 )); if( sExt.equalsIgnoreAsciiCase( "url" )) { OSL_ENSURE( !&rFileName, "how do we read today .URL - Files?" ); } } } return bIsURLFile; } bool SwTransferable::IsPasteSpecial( const SwWrtShell& rWrtShell, const TransferableDataHelper& rData ) { // we can paste-special if there's an entry in the paste-special-format list SvxClipboardFmtItem aClipboardFmtItem(0); FillClipFmtItem( rWrtShell, rData, aClipboardFmtItem); return aClipboardFmtItem.Count() > 0; } bool SwTransferable::PasteFormat( SwWrtShell& rSh, TransferableDataHelper& rData, sal_uLong nFormat ) { SwWait aWait( *rSh.GetView().GetDocShell(), false ); bool nRet = false; sal_uLong nPrivateFmt = FORMAT_PRIVATE; SwTransferable *pClipboard = GetSwTransferable( rData ); if( pClipboard && ((TRNSFR_DOCUMENT|TRNSFR_GRAPHIC|TRNSFR_OLE) & pClipboard->eBufferType )) nPrivateFmt = SOT_FORMATSTR_ID_EMBED_SOURCE; if( pClipboard && nPrivateFmt == nFormat ) nRet = pClipboard->PrivatePaste( rSh ); else if( rData.HasFormat( nFormat ) ) { uno::Reference xTransferable( rData.GetXTransferable() ); sal_uInt16 nEventAction, nDestination = SwTransferable::GetSotDestination( rSh ), nSourceOptions = (( EXCHG_DEST_DOC_TEXTFRAME == nDestination || EXCHG_DEST_SWDOC_FREE_AREA == nDestination || EXCHG_DEST_DOC_TEXTFRAME_WEB == nDestination || EXCHG_DEST_SWDOC_FREE_AREA_WEB == nDestination ) ? EXCHG_IN_ACTION_COPY : EXCHG_IN_ACTION_MOVE), nAction = SotExchange::GetExchangeAction( rData.GetDataFlavorExVector(), nDestination, nSourceOptions, /* ?? */ EXCHG_IN_ACTION_DEFAULT, /* ?? */ nFormat, nEventAction, nFormat, lcl_getTransferPointer ( xTransferable ) ); if( EXCHG_INOUT_ACTION_NONE != nAction ) nRet = SwTransferable::PasteData( rData, rSh, nAction, nFormat, nDestination, true, false ); } return nRet; } bool SwTransferable::_TestAllowedFormat( const TransferableDataHelper& rData, sal_uLong nFormat, sal_uInt16 nDestination ) { sal_uInt16 nAction = EXCHG_INOUT_ACTION_NONE, nEventAction; if( rData.HasFormat( nFormat )) { uno::Reference xTransferable( rData.GetXTransferable() ); nAction = SotExchange::GetExchangeAction( rData.GetDataFlavorExVector(), nDestination, EXCHG_IN_ACTION_COPY, EXCHG_IN_ACTION_COPY, nFormat, nEventAction, nFormat, lcl_getTransferPointer ( xTransferable ) ); } return EXCHG_INOUT_ACTION_NONE != nAction; } /** * the list of formats which will be offered to the user in the 'Paste * Special...' dialog and the paste button menu */ static sal_uInt16 aPasteSpecialIds[] = { SOT_FORMATSTR_ID_HTML, SOT_FORMATSTR_ID_HTML_SIMPLE, SOT_FORMATSTR_ID_HTML_NO_COMMENT, FORMAT_RTF, FORMAT_STRING, SOT_FORMATSTR_ID_SONLK, SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, SOT_FORMATSTR_ID_DRAWING, SOT_FORMATSTR_ID_SVXB, FORMAT_GDIMETAFILE, FORMAT_BITMAP, SOT_FORMATSTR_ID_SVIM, SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, 0 }; bool SwTransferable::PasteUnformatted( SwWrtShell& rSh, TransferableDataHelper& rData ) { // Plain text == unformatted return SwTransferable::PasteFormat( rSh, rData, SOT_FORMAT_STRING ); } bool SwTransferable::PasteSpecial( SwWrtShell& rSh, TransferableDataHelper& rData, sal_uLong& rFormatUsed ) { bool nRet = false; SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); boost::scoped_ptr pDlg(pFact->CreatePasteDialog( &rSh.GetView().GetEditWin() )); DataFlavorExVector aFormats( rData.GetDataFlavorExVector() ); TransferableObjectDescriptor aDesc; sal_uInt16 nDest = SwTransferable::GetSotDestination( rSh ); SwTransferable *pClipboard = GetSwTransferable( rData ); if( pClipboard ) { aDesc = pClipboard->aObjDesc; sal_uInt16 nResId; if( pClipboard->eBufferType & TRNSFR_DOCUMENT ) nResId = STR_PRIVATETEXT; else if( pClipboard->eBufferType & TRNSFR_GRAPHIC ) nResId = STR_PRIVATEGRAPHIC; else if( pClipboard->eBufferType == TRNSFR_OLE ) nResId = STR_PRIVATEOLE; else nResId = 0; if( nResId ) { if( STR_PRIVATEOLE == nResId || STR_PRIVATEGRAPHIC == nResId ) { // add SOT_FORMATSTR_ID_EMBED_SOURCE to the formats. This // format display then the private format name. DataFlavorEx aFlavorEx; aFlavorEx.mnSotId = SOT_FORMATSTR_ID_EMBED_SOURCE; aFormats.insert( aFormats.begin(), aFlavorEx ); } pDlg->SetObjName( pClipboard->aObjDesc.maClassName, SW_RES( nResId ) ); pDlg->Insert( SOT_FORMATSTR_ID_EMBED_SOURCE, aEmptyOUStr ); } } else { if( rData.HasFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR ) ) rData.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aDesc ); if( SwTransferable::_TestAllowedFormat( rData, SOT_FORMATSTR_ID_EMBED_SOURCE, nDest )) pDlg->Insert( SOT_FORMATSTR_ID_EMBED_SOURCE, aEmptyOUStr ); if( SwTransferable::_TestAllowedFormat( rData, SOT_FORMATSTR_ID_LINK_SOURCE, nDest )) pDlg->Insert( SOT_FORMATSTR_ID_LINK_SOURCE, aEmptyOUStr ); } if( SwTransferable::_TestAllowedFormat( rData, SOT_FORMATSTR_ID_LINK, nDest )) pDlg->Insert( SOT_FORMATSTR_ID_LINK, SW_RES(STR_DDEFORMAT) ); for( sal_uInt16* pIds = aPasteSpecialIds; *pIds; ++pIds ) if( SwTransferable::_TestAllowedFormat( rData, *pIds, nDest )) pDlg->Insert( *pIds, aEmptyOUStr ); sal_uLong nFormat = pDlg->GetFormat( rData.GetTransferable() ); if( nFormat ) nRet = SwTransferable::PasteFormat( rSh, rData, nFormat ); if ( nRet ) rFormatUsed = nFormat; return nRet; } void SwTransferable::FillClipFmtItem( const SwWrtShell& rSh, const TransferableDataHelper& rData, SvxClipboardFmtItem & rToFill ) { sal_uInt16 nDest = SwTransferable::GetSotDestination( rSh ); SwTransferable *pClipboard = GetSwTransferable( rData ); if( pClipboard ) { sal_uInt16 nResId; if( pClipboard->eBufferType & TRNSFR_DOCUMENT ) nResId = STR_PRIVATETEXT; else if( pClipboard->eBufferType & TRNSFR_GRAPHIC ) nResId = STR_PRIVATEGRAPHIC; else if( pClipboard->eBufferType == TRNSFR_OLE ) nResId = STR_PRIVATEOLE; else nResId = 0; if( nResId ) rToFill.AddClipbrdFormat( SOT_FORMATSTR_ID_EMBED_SOURCE, SW_RESSTR( nResId ) ); } else { TransferableObjectDescriptor aDesc; if( rData.HasFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR ) ) ((TransferableDataHelper&)rData).GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aDesc ); if( SwTransferable::_TestAllowedFormat( rData, SOT_FORMATSTR_ID_EMBED_SOURCE, nDest )) rToFill.AddClipbrdFormat( SOT_FORMATSTR_ID_EMBED_SOURCE, aDesc.maTypeName ); if( SwTransferable::_TestAllowedFormat( rData, SOT_FORMATSTR_ID_LINK_SOURCE, nDest )) rToFill.AddClipbrdFormat( SOT_FORMATSTR_ID_LINK_SOURCE ); SotFormatStringId nFormat; if ( rData.HasFormat(nFormat = SOT_FORMATSTR_ID_EMBED_SOURCE_OLE) || rData.HasFormat(nFormat = SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE) ) { OUString sName,sSource; if ( SvPasteObjectHelper::GetEmbeddedName(rData,sName,sSource,nFormat) ) rToFill.AddClipbrdFormat( nFormat, sName ); } } if( SwTransferable::_TestAllowedFormat( rData, SOT_FORMATSTR_ID_LINK, nDest )) rToFill.AddClipbrdFormat( SOT_FORMATSTR_ID_LINK, SW_RESSTR(STR_DDEFORMAT) ); for( sal_uInt16* pIds = aPasteSpecialIds; *pIds; ++pIds ) if( SwTransferable::_TestAllowedFormat( rData, *pIds, nDest )) rToFill.AddClipbrdFormat( *pIds, aEmptyOUStr ); } void SwTransferable::SetDataForDragAndDrop( const Point& rSttPos ) { if(!pWrtShell) return; OUString sGrfNm; const int nSelection = pWrtShell->GetSelectionType(); if( nsSelectionType::SEL_GRF == nSelection) { AddFormat( SOT_FORMATSTR_ID_SVXB ); const Graphic* pGrf = pWrtShell->GetGraphic(); if ( pGrf && pGrf->IsSupportedGraphic() ) { AddFormat( FORMAT_GDIMETAFILE ); AddFormat( SOT_FORMATSTR_ID_PNG ); AddFormat( FORMAT_BITMAP ); } eBufferType = TRNSFR_GRAPHIC; pWrtShell->GetGrfNms( &sGrfNm, 0 ); } else if( nsSelectionType::SEL_OLE == nSelection ) { AddFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ); PrepareOLE( aObjDesc ); AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR ); AddFormat( FORMAT_GDIMETAFILE ); eBufferType = TRNSFR_OLE; } //Is there anything to provide anyway? else if ( pWrtShell->IsSelection() || pWrtShell->IsFrmSelected() || pWrtShell->IsObjSelected() ) { if( pWrtShell->IsObjSelected() ) eBufferType = TRNSFR_DRAWING; else { eBufferType = TRNSFR_DOCUMENT; if( SwWrtShell::NO_WORD != pWrtShell->IntelligentCut( nSelection, false )) eBufferType = TransferBufferType( TRNSFR_DOCUMENT_WORD | eBufferType); } if( nSelection & nsSelectionType::SEL_TBL_CELLS ) eBufferType = (TransferBufferType)(TRNSFR_TABELLE | eBufferType); AddFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ); //put RTF ahead of the OLE's Metafile for less loss if( !pWrtShell->IsObjSelected() ) { AddFormat( FORMAT_RTF ); AddFormat( SOT_FORMATSTR_ID_HTML ); } if( pWrtShell->IsSelection() ) AddFormat( FORMAT_STRING ); if( nSelection & ( nsSelectionType::SEL_DRW | nsSelectionType::SEL_DRW_FORM )) { AddFormat( SOT_FORMATSTR_ID_DRAWING ); if ( nSelection & nsSelectionType::SEL_DRW ) { AddFormat( FORMAT_GDIMETAFILE ); AddFormat( SOT_FORMATSTR_ID_PNG ); AddFormat( FORMAT_BITMAP ); } eBufferType = (TransferBufferType)( TRNSFR_GRAPHIC | eBufferType ); pClpGraphic = new Graphic; if( !pWrtShell->GetDrawObjGraphic( FORMAT_GDIMETAFILE, *pClpGraphic )) pOrigGrf = pClpGraphic; pClpBitmap = new Graphic; if( !pWrtShell->GetDrawObjGraphic( FORMAT_BITMAP, *pClpBitmap )) pOrigGrf = pClpBitmap; // is it an URL-Button ? OUString sURL; OUString sDesc; if( pWrtShell->GetURLFromButton( sURL, sDesc ) ) { AddFormat( FORMAT_STRING ); AddFormat( SOT_FORMATSTR_ID_SOLK ); AddFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ); AddFormat( SOT_FORMATSTR_ID_FILECONTENT ); AddFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ); AddFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ); eBufferType = (TransferBufferType)( TRNSFR_INETFLD | eBufferType ); } } //ObjectDescriptor was already filled from the old DocShell. //Now adjust it. Thus in GetData the first query can still //be answered with delayed rendering. aObjDesc.mbCanLink = false; aObjDesc.maDragStartPos = rSttPos; aObjDesc.maSize = OutputDevice::LogicToLogic( Size( OLESIZE ), MAP_TWIP, MAP_100TH_MM ); PrepareOLE( aObjDesc ); AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR ); } else if( nSelection & nsSelectionType::SEL_TXT && !pWrtShell->HasMark() ) { // is only one field - selected? SwContentAtPos aCntntAtPos( SwContentAtPos::SW_INETATTR ); Point aPos( SwEditWin::GetDDStartPosX(), SwEditWin::GetDDStartPosY()); if( pWrtShell->GetContentAtPos( aPos, aCntntAtPos ) ) { AddFormat( FORMAT_STRING ); AddFormat( SOT_FORMATSTR_ID_SOLK ); AddFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ); AddFormat( SOT_FORMATSTR_ID_FILECONTENT ); AddFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ); AddFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ); eBufferType = TRNSFR_INETFLD; } } if( pWrtShell->IsFrmSelected() ) { SfxItemSet aSet( pWrtShell->GetAttrPool(), RES_URL, RES_URL ); pWrtShell->GetFlyFrmAttr( aSet ); const SwFmtURL& rURL = (SwFmtURL&)aSet.Get( RES_URL ); if( rURL.GetMap() ) { pImageMap = new ImageMap( *rURL.GetMap() ); AddFormat( SOT_FORMATSTR_ID_SVIM ); } else if( !rURL.GetURL().isEmpty() ) { pTargetURL = new INetImage( sGrfNm, rURL.GetURL(), rURL.GetTargetFrameName(), aEmptyOUStr, Size() ); AddFormat( SOT_FORMATSTR_ID_INET_IMAGE ); } } } void SwTransferable::StartDrag( Window* pWin, const Point& rPos ) { if(!pWrtShell) return; bOldIdle = pWrtShell->GetViewOptions()->IsIdle(); bCleanUp = true; ((SwViewOption *)pWrtShell->GetViewOptions())->SetIdle( false ); if( pWrtShell->IsSelFrmMode() ) pWrtShell->ShowCrsr(); SW_MOD()->pDragDrop = this; SetDataForDragAndDrop( rPos ); sal_Int8 nDragOptions = DND_ACTION_COPYMOVE | DND_ACTION_LINK; SwDocShell* pDShell = pWrtShell->GetView().GetDocShell(); if( ( pDShell && pDShell->IsReadOnly() ) || pWrtShell->HasReadonlySel() ) nDragOptions &= ~DND_ACTION_MOVE; TransferableHelper::StartDrag( pWin, nDragOptions ); } void SwTransferable::DragFinished( sal_Int8 nAction ) { //And the last finishing work so that all statuses are right if( DND_ACTION_MOVE == nAction ) { if( bCleanUp ) { //It was dropped outside of Writer. We still have to //delete. pWrtShell->StartAllAction(); pWrtShell->StartUndo( UNDO_UI_DRAG_AND_MOVE ); if ( pWrtShell->IsTableMode() ) pWrtShell->DeleteTblSel(); else { if ( !(pWrtShell->IsSelFrmMode() || pWrtShell->IsObjSelected()) ) //SmartCut, take one of the blanks along pWrtShell->IntelligentCut( pWrtShell->GetSelectionType(), true ); pWrtShell->DelRight(); } pWrtShell->EndUndo( UNDO_UI_DRAG_AND_MOVE ); pWrtShell->EndAllAction(); } else { const int nSelection = pWrtShell->GetSelectionType(); if( ( nsSelectionType::SEL_FRM | nsSelectionType::SEL_GRF | nsSelectionType::SEL_OLE | nsSelectionType::SEL_DRW ) & nSelection ) { pWrtShell->EnterSelFrmMode(); } } } pWrtShell->GetView().GetEditWin().DragFinished(); if( pWrtShell->IsSelFrmMode() ) pWrtShell->HideCrsr(); else pWrtShell->ShowCrsr(); ((SwViewOption *)pWrtShell->GetViewOptions())->SetIdle( bOldIdle ); } bool SwTransferable::PrivatePaste( SwWrtShell& rShell ) { // first, ask for the SelectionType, then action-bracketing !!!! // (otherwise it's not pasted into a TableSelection!!!) OSL_ENSURE( !rShell.ActionPend(), "Paste must never have an ActionPend" ); if ( !pClpDocFac ) return false; // the return value of the SwFEShell::Paste also is bool! const int nSelection = rShell.GetSelectionType(); SwRewriter aRewriter; SwTrnsfrActionAndUndo aAction( &rShell, UNDO_PASTE_CLIPBOARD); bool bKillPaMs = false; //Delete selected content, not at table-selection and table in Clipboard, and dont delete hovering graphics. if( rShell.HasSelection() && !( nSelection & nsSelectionType::SEL_TBL_CELLS) && !( nSelection & nsSelectionType::SEL_DRW)) { bKillPaMs = true; rShell.SetRetainSelection( true ); rShell.DelRight(); // when a Fly was selected, a valid cursor position has to be found now // (parked Cursor!) if( ( nsSelectionType::SEL_FRM | nsSelectionType::SEL_GRF | nsSelectionType::SEL_OLE | nsSelectionType::SEL_DRW | nsSelectionType::SEL_DRW_FORM ) & nSelection ) { // position the cursor again Point aPt( rShell.GetCharRect().Pos() ); rShell.SwCrsrShell::SetCrsr( aPt, true ); } rShell.SetRetainSelection( false ); } if ( nSelection & nsSelectionType::SEL_DRW) //unselect hovering graphics { rShell.ResetSelect(NULL,false); } bool bInWrd = false, bEndWrd = false, bSttWrd = false, bSmart = 0 != (TRNSFR_DOCUMENT_WORD & eBufferType); if( bSmart ) { // Why not for other Scripts? If TRNSFR_DOCUMENT_WORD is set, we have a word // in the buffer, word in this context means 'something with spaces at beginning // and end'. In this case we definitely want these spaces to be inserted here. bInWrd = rShell.IsInWrd(); bEndWrd = rShell.IsEndWrd(); bSmart = bInWrd || bEndWrd; if( bSmart ) { bSttWrd = rShell.IsSttWrd(); if( bSmart && !bSttWrd && (bInWrd || bEndWrd) ) rShell.SwEditShell::Insert(' '); } } bool nRet = rShell.Paste( pClpDocFac->GetDoc() ); if( bKillPaMs ) rShell.KillPams(); // If Smart Paste then insert blank if( nRet && bSmart && ((bInWrd && !bEndWrd )|| bSttWrd) ) rShell.SwEditShell::Insert(' '); return nRet; } bool SwTransferable::PrivateDrop( SwWrtShell& rSh, const Point& rDragPt, bool bMove, bool bIsXSelection ) { int cWord = 0; bool bInWrd = false; bool bEndWrd = false; bool bSttWrd = false; bool bSttPara = false; bool bTblSel = false; bool bFrmSel = false; SwWrtShell& rSrcSh = *GetShell(); rSh.UnSetVisCrsr(); if( TRNSFR_INETFLD == eBufferType ) { if( rSh.GetFmtFromObj( rDragPt ) ) { INetBookmark aTmp; if( (TRNSFR_INETFLD & eBufferType) && pBkmk ) aTmp = *pBkmk; // select target graphic if( rSh.SelectObj( rDragPt ) ) { rSh.HideCrsr(); rSh.EnterSelFrmMode( &rDragPt ); bFrmDrag = true; } const int nSelection = rSh.GetSelectionType(); // not yet consider Draw objects if( nsSelectionType::SEL_GRF & nSelection ) { SfxItemSet aSet( rSh.GetAttrPool(), RES_URL, RES_URL ); rSh.GetFlyFrmAttr( aSet ); SwFmtURL aURL( (SwFmtURL&)aSet.Get( RES_URL ) ); aURL.SetURL( aTmp.GetURL(), false ); aSet.Put( aURL ); rSh.SetFlyFrmAttr( aSet ); return true; } if( nsSelectionType::SEL_DRW & nSelection ) { rSh.LeaveSelFrmMode(); rSh.UnSelectFrm(); rSh.ShowCrsr(); bFrmDrag = false; } } } if( &rSh != &rSrcSh && (nsSelectionType::SEL_GRF & rSh.GetSelectionType()) && TRNSFR_GRAPHIC == eBufferType ) { // ReRead the graphic OUString sGrfNm; OUString sFltNm; rSrcSh.GetGrfNms( &sGrfNm, &sFltNm ); rSh.ReRead( sGrfNm, sFltNm, rSrcSh.GetGraphic() ); return true; } //not in selections or selected frames if( rSh.ChgCurrPam( rDragPt ) || ( rSh.IsSelFrmMode() && rSh.IsInsideSelectedObj( rDragPt )) ) return false; if( rSrcSh.IsTableMode() ) bTblSel = true; else if( rSrcSh.IsSelFrmMode() || rSrcSh.IsObjSelected() ) { // don't move position-protected objects! if( bMove && rSrcSh.IsSelObjProtected( FLYPROTECT_POS ) ) return false; bFrmSel = true; } const int nSel = rSrcSh.GetSelectionType(); SwUndoId eUndoId = bMove ? UNDO_UI_DRAG_AND_MOVE : UNDO_UI_DRAG_AND_COPY; SwRewriter aRewriter; aRewriter.AddRule(UndoArg1, rSrcSh.GetSelDescr()); if(rSrcSh.GetDoc() != rSh.GetDoc()) rSrcSh.StartUndo( eUndoId, &aRewriter ); rSh.StartUndo( eUndoId, &aRewriter ); rSh.StartAction(); rSrcSh.StartAction(); if( &rSrcSh != &rSh ) { rSh.EnterStdMode(); rSh.SwCrsrShell::SetCrsr( rDragPt, true ); cWord = rSrcSh.IntelligentCut( nSel, false ); } else if( !bTblSel && !bFrmSel ) { if( !rSh.IsAddMode() ) { // #i87233# if ( rSh.IsBlockMode() ) { // preserve order of cursors for block mode rSh.GoPrevCrsr(); } rSh.SwCrsrShell::CreateCrsr(); } rSh.SwCrsrShell::SetCrsr( rDragPt, true, false ); rSh.GoPrevCrsr(); cWord = rSh.IntelligentCut( rSh.GetSelectionType(), false ); rSh.GoNextCrsr(); } bInWrd = rSh.IsInWrd(); bEndWrd = rSh.IsEndWrd(); bSttWrd = !bEndWrd && rSh.IsSttWrd(); bSttPara= rSh.IsSttPara(); Point aSttPt( SwEditWin::GetDDStartPosX(), SwEditWin::GetDDStartPosY() ); // at first, select INetFelder! if( TRNSFR_INETFLD == eBufferType ) { if( &rSrcSh == &rSh ) { rSh.GoPrevCrsr(); rSh.SwCrsrShell::SetCrsr( aSttPt, true ); rSh.SelectTxtAttr( RES_TXTATR_INETFMT ); if( rSh.ChgCurrPam( rDragPt ) ) { // don't copy/move inside of yourself rSh.DestroyCrsr(); rSh.EndUndo(); rSh.EndAction(); rSh.EndAction(); return false; } rSh.GoNextCrsr(); } else { rSrcSh.SwCrsrShell::SetCrsr( aSttPt, true ); rSrcSh.SelectTxtAttr( RES_TXTATR_INETFMT ); } // is there an URL attribute at the insert point? Then replace that, // so simply put up a selection? rSh.DelINetAttrWithText(); bDDINetAttr = true; } if ( rSrcSh.IsSelFrmMode() ) { //Hack: fool the special treatment aSttPt -= aSttPt - rSrcSh.GetObjRect().Pos(); } bool bRet = rSrcSh.SwFEShell::Copy( &rSh, aSttPt, rDragPt, bMove, !bIsXSelection ); if( !bIsXSelection ) { rSrcSh.Push(); if ( bRet && bMove && !bFrmSel ) { if ( bTblSel ) { /* delete table contents not cells */ rSrcSh.Delete(); } else { //SmartCut, take one of the blanks along. rSh.SwCrsrShell::DestroyCrsr(); if ( cWord == SwWrtShell::WORD_SPACE_BEFORE ) rSh.ExtendSelection( false ); else if ( cWord == SwWrtShell::WORD_SPACE_AFTER ) rSh.ExtendSelection(); rSrcSh.DelRight(); } } rSrcSh.KillPams(); rSrcSh.Pop( false ); /* after dragging a table selection inside one shell set cursor to the drop position. */ if( &rSh == &rSrcSh && ( bTblSel || rSh.IsBlockMode() ) ) { rSrcSh.SwCrsrShell::SetCrsr(rDragPt); rSrcSh.GetSwCrsr()->SetMark(); } } if( bRet && !bTblSel && !bFrmSel ) { if( (bInWrd || bEndWrd) && (cWord == SwWrtShell::WORD_SPACE_AFTER || cWord == SwWrtShell::WORD_SPACE_BEFORE) ) { if ( bSttWrd || (bInWrd && !bEndWrd)) rSh.SwEditShell::Insert(' ', bIsXSelection); if ( !bSttWrd || (bInWrd && !bSttPara) ) { rSh.SwapPam(); if ( !bSttWrd ) rSh.SwEditShell::Insert(' ', bIsXSelection); rSh.SwapPam(); } } if( bIsXSelection ) { if( &rSrcSh == &rSh && !rSh.IsAddMode() ) { rSh.SwCrsrShell::DestroyCrsr(); rSh.GoPrevCrsr(); } else { rSh.SwapPam(); rSh.SwCrsrShell::ClearMark(); } } else { if( rSh.IsAddMode() ) rSh.SwCrsrShell::CreateCrsr(); else { // turn on selection mode rSh.SttSelect(); rSh.EndSelect(); } } } if( bRet && bMove && bFrmSel ) rSrcSh.LeaveSelFrmMode(); if( rSrcSh.GetDoc() != rSh.GetDoc() ) rSrcSh.EndUndo(); rSh.EndUndo(); // put the shell in the right state if( &rSrcSh != &rSh && ( rSh.IsFrmSelected() || rSh.IsObjSelected() )) rSh.EnterSelFrmMode(); rSrcSh.EndAction(); rSh.EndAction(); return true; } // Interfaces for Selection void SwTransferable::CreateSelection( SwWrtShell& rSh, const SwViewShell * _pCreatorView ) { SwModule *pMod = SW_MOD(); SwTransferable* pNew = new SwTransferable( rSh ); pNew->pCreatorView = _pCreatorView; uno::Reference< XTransferable > xRef( pNew ); pMod->pXSelection = pNew; pNew->CopyToSelection( rSh.GetWin() ); } void SwTransferable::ClearSelection( SwWrtShell& rSh, const SwViewShell * _pCreatorView) { SwModule *pMod = SW_MOD(); if( pMod->pXSelection && ((!pMod->pXSelection->pWrtShell) || (pMod->pXSelection->pWrtShell == &rSh)) && (!_pCreatorView || (pMod->pXSelection->pCreatorView == _pCreatorView)) ) { TransferableHelper::ClearSelection( rSh.GetWin() ); } } namespace { class theSwTransferableUnoTunnelId : public rtl::Static< UnoTunnelIdInit, SwTransferable > {}; } const Sequence< sal_Int8 >& SwTransferable::getUnoTunnelId() { return theSwTransferableUnoTunnelId::get().getSeq(); } sal_Int64 SwTransferable::getSomething( const Sequence< sal_Int8 >& rId ) throw( RuntimeException, std::exception ) { sal_Int64 nRet; if( ( rId.getLength() == 16 ) && ( 0 == memcmp( getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) ) { nRet = sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >( this ) ); } else nRet = TransferableHelper::getSomething(rId); return nRet; } SwTransferable* SwTransferable::GetSwTransferable( const TransferableDataHelper& rData ) { SwTransferable* pSwTransferable = NULL; uno::Reference xTunnel( rData.GetTransferable(), UNO_QUERY ); if ( xTunnel.is() ) { sal_Int64 nHandle = xTunnel->getSomething( getUnoTunnelId() ); if ( nHandle ) pSwTransferable = (SwTransferable*) (sal_IntPtr) nHandle; } return pSwTransferable; } SwTrnsfrDdeLink::SwTrnsfrDdeLink( SwTransferable& rTrans, SwWrtShell& rSh ) : rTrnsfr(rTrans) , pDocShell(0) , nOldTimeOut(0) , bDelBookmrk(false) , bInDisconnect(false) { // we only end up here with table- or text selection if( nsSelectionType::SEL_TBL_CELLS & rSh.GetSelectionType() ) { SwFrmFmt* pFmt = rSh.GetTableFmt(); if( pFmt ) sName = pFmt->GetName(); } else { // creating a temp. bookmark without undo bool bUndo = rSh.DoesUndo(); rSh.DoUndo( false ); bool bIsModified = rSh.IsModified(); ::sw::mark::IMark* pMark = rSh.SetBookmark( KeyCode(), OUString(), OUString(), IDocumentMarkAccess::DDE_BOOKMARK); if(pMark) { sName = pMark->GetName(); bDelBookmrk = true; if( !bIsModified ) rSh.ResetModified(); } else sName = ""; rSh.DoUndo( bUndo ); } if( !sName.isEmpty() && 0 != ( pDocShell = rSh.GetDoc()->GetDocShell() ) ) { // then we create our "server" and connect to it refObj = pDocShell->DdeCreateLinkSource( sName ); if( refObj.Is() ) { refObj->AddConnectAdvise( this ); refObj->AddDataAdvise( this, aEmptyOUStr, ADVISEMODE_NODATA | ADVISEMODE_ONLYONCE ); nOldTimeOut = refObj->GetUpdateTimeout(); refObj->SetUpdateTimeout( 0 ); } } } SwTrnsfrDdeLink::~SwTrnsfrDdeLink() { if( refObj.Is() ) Disconnect( true ); } ::sfx2::SvBaseLink::UpdateResult SwTrnsfrDdeLink::DataChanged( const OUString& , const uno::Any& ) { // well, that's it with the link if( !bInDisconnect ) { if( FindDocShell() && pDocShell->GetView() ) rTrnsfr.RemoveDDELinkFormat( pDocShell->GetView()->GetEditWin() ); Disconnect( false ); } return SUCCESS; } bool SwTrnsfrDdeLink::WriteData( SvStream& rStrm ) { if( !refObj.Is() || !FindDocShell() ) return false; rtl_TextEncoding eEncoding = DDE_TXT_ENCODING; const OString aAppNm(OUStringToOString( Application::GetAppName(), eEncoding)); const OString aTopic(OUStringToOString( pDocShell->GetTitle(SFX_TITLE_FULLNAME), eEncoding)); const OString aName(OUStringToOString(sName, eEncoding)); boost::scoped_array pMem(new sal_Char[ aAppNm.getLength() + aTopic.getLength() + aName.getLength() + 4 ]); sal_Int32 nLen = aAppNm.getLength(); memcpy( pMem.get(), aAppNm.getStr(), nLen ); pMem[ nLen++ ] = 0; memcpy( pMem.get() + nLen, aTopic.getStr(), aTopic.getLength() ); nLen = nLen + aTopic.getLength(); pMem[ nLen++ ] = 0; memcpy( pMem.get() + nLen, aName.getStr(), aName.getLength() ); nLen = nLen + aName.getLength(); pMem[ nLen++ ] = 0; pMem[ nLen++ ] = 0; rStrm.Write( pMem.get(), nLen ); pMem.reset(); IDocumentMarkAccess* const pMarkAccess = pDocShell->GetDoc()->getIDocumentMarkAccess(); IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->findMark(sName); if(ppMark != pMarkAccess->getAllMarksEnd() && IDocumentMarkAccess::GetType(**ppMark) != IDocumentMarkAccess::BOOKMARK) { // the mark is still a DdeBookmark // we replace it with a Bookmark, so it will get saved etc. ::sw::mark::IMark* const pMark = ppMark->get(); ::sfx2::SvLinkSource* p = &refObj; SwServerObject& rServerObject = dynamic_cast(*p); // collecting state of old mark SwPaM aPaM(pMark->GetMarkStart()); *aPaM.GetPoint() = pMark->GetMarkStart(); if(pMark->IsExpanded()) { aPaM.SetMark(); *aPaM.GetMark() = pMark->GetMarkEnd(); } OUString sMarkName = pMark->GetName(); // remove mark rServerObject.SetNoServer(); // this removes the connection between SwServerObject and mark // N.B. ppMark was not loaded from file and cannot have xml:id pMarkAccess->deleteMark(ppMark); // recreate as Bookmark ::sw::mark::IMark* const pNewMark = pMarkAccess->makeMark( aPaM, sMarkName, IDocumentMarkAccess::BOOKMARK); rServerObject.SetDdeBookmark(*pNewMark); } bDelBookmrk = false; return true; } void SwTrnsfrDdeLink::Disconnect( bool bRemoveDataAdvise ) { // don't accept DataChanged anymore, when already in Disconnect! // (DTOR from Bookmark sends a DataChanged!) bool bOldDisconnect = bInDisconnect; bInDisconnect = true; // destroy the unused bookmark again (without Undo!)? if( bDelBookmrk && refObj.Is() && FindDocShell() ) { SwDoc* pDoc = pDocShell->GetDoc(); ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo()); // #i58448# Link aSavedOle2Link( pDoc->GetOle2Link() ); pDoc->SetOle2Link( Link() ); bool bIsModified = pDoc->IsModified(); IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess(); pMarkAccess->deleteMark(pMarkAccess->findMark(sName)); if( !bIsModified ) pDoc->ResetModified(); // #i58448# pDoc->SetOle2Link( aSavedOle2Link ); bDelBookmrk = false; } if( refObj.Is() ) { refObj->SetUpdateTimeout( nOldTimeOut ); refObj->RemoveConnectAdvise( this ); if( bRemoveDataAdvise ) // in a DataChanged the SelectionObject must NEVER be deleted // is already handled by the base class // (ADVISEMODE_ONLYONCE!!!!) // but always in normal Disconnect! refObj->RemoveAllDataAdvise( this ); refObj.Clear(); } bInDisconnect = bOldDisconnect; } bool SwTrnsfrDdeLink::FindDocShell() { TypeId aType( TYPE( SwDocShell ) ); SfxObjectShell* pTmpSh = SfxObjectShell::GetFirst( &aType ); while( pTmpSh ) { if( pTmpSh == pDocShell ) // that's what we want to have { if( pDocShell->GetDoc() ) return true; break; // the Doc is not there anymore, so leave! } pTmpSh = SfxObjectShell::GetNext( *pTmpSh, &aType ); } pDocShell = 0; return false; } void SwTrnsfrDdeLink::Closed() { if( !bInDisconnect && refObj.Is() ) { refObj->RemoveAllDataAdvise( this ); refObj->RemoveConnectAdvise( this ); refObj.Clear(); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */