1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sc.hxx" 30 31 // INCLUDE --------------------------------------------------------------- 32 33 34 35 #include "scitems.hxx" 36 #include <editeng/eeitem.hxx> 37 38 39 #include <com/sun/star/uno/Sequence.hxx> 40 #include <com/sun/star/embed/XTransactedObject.hpp> 41 42 #include <unotools/tempfile.hxx> 43 #include <unotools/ucbstreamhelper.hxx> 44 #include <comphelper/storagehelper.hxx> 45 #include <sot/storage.hxx> 46 #include <vcl/svapp.hxx> 47 #include <vcl/virdev.hxx> 48 #include <vos/mutex.hxx> 49 #include <sfx2/app.hxx> 50 #include <sfx2/docfile.hxx> 51 52 #include "transobj.hxx" 53 #include "document.hxx" 54 #include "viewopti.hxx" 55 #include "editutil.hxx" 56 #include "impex.hxx" 57 #include "cell.hxx" 58 #include "printfun.hxx" 59 #include "docfunc.hxx" 60 #include "scmod.hxx" 61 62 // for InitDocShell 63 #include <editeng/paperinf.hxx> 64 #include <editeng/sizeitem.hxx> 65 #include <svx/algitem.hxx> 66 #include <svl/intitem.hxx> 67 #include <svl/zforlist.hxx> 68 #include "docsh.hxx" 69 #include "markdata.hxx" 70 #include "stlpool.hxx" 71 #include "viewdata.hxx" 72 #include "dociter.hxx" 73 #include "cellsuno.hxx" 74 75 using namespace com::sun::star; 76 77 // ----------------------------------------------------------------------- 78 79 #define SCTRANS_TYPE_IMPEX 1 80 #define SCTRANS_TYPE_EDIT_RTF 2 81 #define SCTRANS_TYPE_EDIT_BIN 3 82 #define SCTRANS_TYPE_EMBOBJ 4 83 84 // ----------------------------------------------------------------------- 85 86 // static 87 void ScTransferObj::GetAreaSize( ScDocument* pDoc, SCTAB nTab1, SCTAB nTab2, SCROW& nRow, SCCOL& nCol ) 88 { 89 SCCOL nMaxCol = 0; 90 SCROW nMaxRow = 0; 91 for( SCTAB nTab = nTab1; nTab <= nTab2; nTab++ ) 92 { 93 SCCOL nLastCol = 0; 94 SCROW nLastRow = 0; 95 // GetPrintArea instead of GetCellArea - include drawing objects 96 if( pDoc->GetPrintArea( nTab, nLastCol, nLastRow ) ) 97 { 98 if( nLastCol > nMaxCol ) 99 nMaxCol = nLastCol; 100 if( nLastRow > nMaxRow ) 101 nMaxRow = nLastRow; 102 } 103 } 104 nRow = nMaxRow; 105 nCol = nMaxCol; 106 } 107 108 // static 109 void ScTransferObj::PaintToDev( OutputDevice* pDev, ScDocument* pDoc, double nPrintFactor, 110 const ScRange& rBlock, sal_Bool bMetaFile ) 111 { 112 if (!pDoc) 113 return; 114 115 Point aPoint; 116 Rectangle aBound( aPoint, pDev->GetOutputSize() ); //! use size from clip area? 117 118 ScViewData aViewData(NULL,NULL); 119 aViewData.InitData( pDoc ); 120 121 aViewData.SetTabNo( rBlock.aEnd.Tab() ); 122 aViewData.SetScreen( rBlock.aStart.Col(), rBlock.aStart.Row(), 123 rBlock.aEnd.Col(), rBlock.aEnd.Row() ); 124 125 ScPrintFunc::DrawToDev( pDoc, pDev, nPrintFactor, aBound, &aViewData, bMetaFile ); 126 } 127 128 // ----------------------------------------------------------------------- 129 130 ScTransferObj::ScTransferObj( ScDocument* pClipDoc, const TransferableObjectDescriptor& rDesc ) : 131 pDoc( pClipDoc ), 132 aObjDesc( rDesc ), 133 nDragHandleX( 0 ), 134 nDragHandleY( 0 ), 135 nDragSourceFlags( 0 ), 136 bDragWasInternal( sal_False ), 137 bUsedForLink( sal_False ), 138 bUseInApi( false ) 139 { 140 DBG_ASSERT(pDoc->IsClipboard(), "wrong document"); 141 142 // 143 // get aBlock from clipboard doc 144 // 145 146 SCCOL nCol1; 147 SCROW nRow1; 148 SCCOL nCol2; 149 SCROW nRow2; 150 pDoc->GetClipStart( nCol1, nRow1 ); 151 pDoc->GetClipArea( nCol2, nRow2, sal_True ); // real source area - include filtered rows 152 nCol2 = sal::static_int_cast<SCCOL>( nCol2 + nCol1 ); 153 nRow2 = sal::static_int_cast<SCROW>( nRow2 + nRow1 ); 154 155 SCCOL nDummy; 156 pDoc->GetClipArea( nDummy, nNonFiltered, sal_False ); 157 bHasFiltered = (nNonFiltered < (nRow2 - nRow1)); 158 ++nNonFiltered; // to get count instead of diff 159 160 SCTAB nTab1=0; 161 SCTAB nTab2=0; 162 sal_Bool bFirst = sal_True; 163 for (SCTAB i=0; i<=MAXTAB; i++) 164 if (pDoc->HasTable(i)) 165 { 166 if (bFirst) 167 nTab1 = i; 168 nTab2 = i; 169 bFirst = sal_False; 170 } 171 DBG_ASSERT(!bFirst, "no sheet selected"); 172 173 // only limit to used cells if whole sheet was marked 174 // (so empty cell areas can be copied) 175 if ( nCol2>=MAXCOL && nRow2>=MAXROW ) 176 { 177 SCROW nMaxRow; 178 SCCOL nMaxCol; 179 GetAreaSize( pDoc, nTab1, nTab2, nMaxRow, nMaxCol ); 180 if( nMaxRow < nRow2 ) 181 nRow2 = nMaxRow; 182 if( nMaxCol < nCol2 ) 183 nCol2 = nMaxCol; 184 } 185 186 aBlock = ScRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); 187 nVisibleTab = nTab1; // valid table as default 188 189 Rectangle aMMRect = pDoc->GetMMRect( nCol1,nRow1, nCol2,nRow2, nTab1 ); 190 aObjDesc.maSize = aMMRect.GetSize(); 191 PrepareOLE( aObjDesc ); 192 } 193 194 ScTransferObj::~ScTransferObj() 195 { 196 Application::GetSolarMutex().acquire(); 197 198 ScModule* pScMod = SC_MOD(); 199 if ( pScMod->GetClipData().pCellClipboard == this ) 200 { 201 DBG_ERROR("ScTransferObj wasn't released"); 202 pScMod->SetClipObject( NULL, NULL ); 203 } 204 if ( pScMod->GetDragData().pCellTransfer == this ) 205 { 206 DBG_ERROR("ScTransferObj wasn't released"); 207 pScMod->ResetDragObject(); 208 } 209 210 delete pDoc; // ScTransferObj is owner of clipboard document 211 212 aDocShellRef.Clear(); // before releasing the mutex 213 214 aDrawPersistRef.Clear(); // after the model 215 216 Application::GetSolarMutex().release(); 217 } 218 219 // static 220 ScTransferObj* ScTransferObj::GetOwnClipboard( Window* pUIWin ) 221 { 222 ScTransferObj* pObj = SC_MOD()->GetClipData().pCellClipboard; 223 if ( pObj && pUIWin ) 224 { 225 // check formats to see if pObj is really in the system clipboard 226 227 // pUIWin is NULL when called from core (IsClipboardSource), 228 // in that case don't access the system clipboard, because the call 229 // may be from other clipboard operations (like flushing, #86059#) 230 231 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pUIWin ) ); 232 if ( !aDataHelper.HasFormat( SOT_FORMATSTR_ID_DIF ) ) 233 { 234 // DBG_ERROR("ScTransferObj wasn't released"); 235 pObj = NULL; 236 } 237 } 238 return pObj; 239 } 240 241 void ScTransferObj::AddSupportedFormats() 242 { 243 AddFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ); 244 AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR ); 245 AddFormat( SOT_FORMAT_GDIMETAFILE ); 246 AddFormat( SOT_FORMAT_BITMAP ); 247 248 // ScImportExport formats 249 AddFormat( SOT_FORMATSTR_ID_HTML ); 250 AddFormat( SOT_FORMATSTR_ID_SYLK ); 251 AddFormat( SOT_FORMATSTR_ID_LINK ); 252 AddFormat( SOT_FORMATSTR_ID_DIF ); 253 AddFormat( SOT_FORMAT_STRING ); 254 255 AddFormat( SOT_FORMAT_RTF ); 256 if ( aBlock.aStart == aBlock.aEnd ) 257 AddFormat( SOT_FORMATSTR_ID_EDITENGINE ); 258 } 259 260 sal_Bool ScTransferObj::GetData( const datatransfer::DataFlavor& rFlavor ) 261 { 262 sal_uInt32 nFormat = SotExchange::GetFormat( rFlavor ); 263 sal_Bool bOK = sal_False; 264 265 if( HasFormat( nFormat ) ) 266 { 267 if ( nFormat == SOT_FORMATSTR_ID_LINKSRCDESCRIPTOR || nFormat == SOT_FORMATSTR_ID_OBJECTDESCRIPTOR ) 268 { 269 bOK = SetTransferableObjectDescriptor( aObjDesc, rFlavor ); 270 } 271 else if ( ( nFormat == SOT_FORMAT_RTF || nFormat == SOT_FORMATSTR_ID_EDITENGINE ) && 272 aBlock.aStart == aBlock.aEnd ) 273 { 274 // RTF from a single cell is handled by EditEngine 275 276 SCCOL nCol = aBlock.aStart.Col(); 277 SCROW nRow = aBlock.aStart.Row(); 278 SCTAB nTab = aBlock.aStart.Tab(); 279 280 const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab ); 281 ScTabEditEngine aEngine( *pPattern, pDoc->GetEditPool() ); 282 ScBaseCell* pCell = NULL; 283 pDoc->GetCell( nCol, nRow, nTab, pCell ); 284 if (pCell) 285 { 286 if (pCell->GetCellType() == CELLTYPE_EDIT) 287 { 288 const EditTextObject* pObj; 289 ((ScEditCell*)pCell)->GetData(pObj); 290 aEngine.SetText( *pObj ); 291 } 292 else 293 { 294 String aText; 295 pDoc->GetString( nCol, nRow, nTab, aText ); 296 aEngine.SetText(aText); 297 } 298 } 299 300 bOK = SetObject( &aEngine, 301 (nFormat == FORMAT_RTF) ? SCTRANS_TYPE_EDIT_RTF : SCTRANS_TYPE_EDIT_BIN, 302 rFlavor ); 303 } 304 else if ( ScImportExport::IsFormatSupported( nFormat ) || nFormat == SOT_FORMAT_RTF ) 305 { 306 // if this transfer object was used to create a DDE link, filtered rows 307 // have to be included for subsequent calls (to be consistent with link data) 308 if ( nFormat == SOT_FORMATSTR_ID_LINK ) 309 bUsedForLink = sal_True; 310 311 sal_Bool bIncludeFiltered = pDoc->IsCutMode() || bUsedForLink; 312 313 ScImportExport aObj( pDoc, aBlock ); 314 if ( bUsedForLink ) 315 aObj.SetExportTextOptions( ScExportTextOptions( ScExportTextOptions::ToSpace, ' ', false ) ); 316 aObj.SetFormulas( pDoc->GetViewOptions().GetOption( VOPT_FORMULAS ) ); 317 aObj.SetIncludeFiltered( bIncludeFiltered ); 318 319 // DataType depends on format type: 320 321 if ( rFlavor.DataType.equals( ::getCppuType( (const ::rtl::OUString*) 0 ) ) ) 322 { 323 rtl::OUString aString; 324 if ( aObj.ExportString( aString, nFormat ) ) 325 bOK = SetString( aString, rFlavor ); 326 } 327 else if ( rFlavor.DataType.equals( ::getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) ) ) 328 { 329 // SetObject converts a stream into a Int8-Sequence 330 bOK = SetObject( &aObj, SCTRANS_TYPE_IMPEX, rFlavor ); 331 } 332 else 333 { 334 DBG_ERROR("unknown DataType"); 335 } 336 } 337 else if ( nFormat == SOT_FORMAT_BITMAP ) 338 { 339 Rectangle aMMRect = pDoc->GetMMRect( aBlock.aStart.Col(), aBlock.aStart.Row(), 340 aBlock.aEnd.Col(), aBlock.aEnd.Row(), 341 aBlock.aStart.Tab() ); 342 VirtualDevice aVirtDev; 343 aVirtDev.SetOutputSizePixel( aVirtDev.LogicToPixel( aMMRect.GetSize(), MAP_100TH_MM ) ); 344 345 PaintToDev( &aVirtDev, pDoc, 1.0, aBlock, sal_False ); 346 347 aVirtDev.SetMapMode( MapMode( MAP_PIXEL ) ); 348 Bitmap aBmp = aVirtDev.GetBitmap( Point(), aVirtDev.GetOutputSize() ); 349 bOK = SetBitmap( aBmp, rFlavor ); 350 } 351 else if ( nFormat == SOT_FORMAT_GDIMETAFILE ) 352 { 353 InitDocShell(); 354 SfxObjectShell* pEmbObj = aDocShellRef; 355 356 // like SvEmbeddedTransfer::GetData: 357 358 GDIMetaFile aMtf; 359 VirtualDevice aVDev; 360 MapMode aMapMode( pEmbObj->GetMapUnit() ); 361 Rectangle aVisArea( pEmbObj->GetVisArea( ASPECT_CONTENT ) ); 362 363 aVDev.EnableOutput( sal_False ); 364 aVDev.SetMapMode( aMapMode ); 365 aMtf.SetPrefSize( aVisArea.GetSize() ); 366 aMtf.SetPrefMapMode( aMapMode ); 367 aMtf.Record( &aVDev ); 368 369 pEmbObj->DoDraw( &aVDev, Point(), aVisArea.GetSize(), JobSetup(), ASPECT_CONTENT ); 370 371 aMtf.Stop(); 372 aMtf.WindStart(); 373 374 bOK = SetGDIMetaFile( aMtf, rFlavor ); 375 } 376 else if ( nFormat == SOT_FORMATSTR_ID_EMBED_SOURCE ) 377 { 378 //TODO/LATER: differentiate between formats?! 379 InitDocShell(); // set aDocShellRef 380 381 SfxObjectShell* pEmbObj = aDocShellRef; 382 bOK = SetObject( pEmbObj, SCTRANS_TYPE_EMBOBJ, rFlavor ); 383 } 384 } 385 return bOK; 386 } 387 388 sal_Bool ScTransferObj::WriteObject( SotStorageStreamRef& rxOStm, void* pUserObject, sal_uInt32 nUserObjectId, 389 const datatransfer::DataFlavor& rFlavor ) 390 { 391 // called from SetObject, put data into stream 392 393 sal_Bool bRet = sal_False; 394 switch (nUserObjectId) 395 { 396 case SCTRANS_TYPE_IMPEX: 397 { 398 ScImportExport* pImpEx = (ScImportExport*)pUserObject; 399 400 sal_uInt32 nFormat = SotExchange::GetFormat( rFlavor ); 401 // mba: no BaseURL for data exchange 402 if ( pImpEx->ExportStream( *rxOStm, String(), nFormat ) ) 403 bRet = ( rxOStm->GetError() == ERRCODE_NONE ); 404 } 405 break; 406 407 case SCTRANS_TYPE_EDIT_RTF: 408 case SCTRANS_TYPE_EDIT_BIN: 409 { 410 ScTabEditEngine* pEngine = (ScTabEditEngine*)pUserObject; 411 if ( nUserObjectId == SCTRANS_TYPE_EDIT_RTF ) 412 { 413 pEngine->Write( *rxOStm, EE_FORMAT_RTF ); 414 bRet = ( rxOStm->GetError() == ERRCODE_NONE ); 415 } 416 else 417 { 418 // #107722# can't use Write for EditEngine format because that would 419 // write old format without support for unicode characters. 420 // Get the data from the EditEngine's transferable instead. 421 422 sal_uInt16 nParCnt = pEngine->GetParagraphCount(); 423 if ( nParCnt == 0 ) 424 nParCnt = 1; 425 ESelection aSel( 0, 0, nParCnt-1, pEngine->GetTextLen(nParCnt-1) ); 426 427 uno::Reference<datatransfer::XTransferable> xEditTrans = pEngine->CreateTransferable( aSel ); 428 TransferableDataHelper aEditHelper( xEditTrans ); 429 430 bRet = aEditHelper.GetSotStorageStream( rFlavor, rxOStm ); 431 } 432 } 433 break; 434 435 case SCTRANS_TYPE_EMBOBJ: 436 { 437 // TODO/MBA: testing 438 SfxObjectShell* pEmbObj = (SfxObjectShell*) pUserObject; 439 ::utl::TempFile aTempFile; 440 aTempFile.EnableKillingFile(); 441 uno::Reference< embed::XStorage > xWorkStore = 442 ::comphelper::OStorageHelper::GetStorageFromURL( aTempFile.GetURL(), embed::ElementModes::READWRITE ); 443 444 // write document storage 445 pEmbObj->SetupStorage( xWorkStore, SOFFICE_FILEFORMAT_CURRENT, sal_False ); 446 447 // mba: no relative ULRs for clipboard! 448 SfxMedium aMedium( xWorkStore, String() ); 449 bRet = pEmbObj->DoSaveObjectAs( aMedium, sal_False ); 450 pEmbObj->DoSaveCompleted(); 451 452 uno::Reference< embed::XTransactedObject > xTransact( xWorkStore, uno::UNO_QUERY ); 453 if ( xTransact.is() ) 454 xTransact->commit(); 455 456 SvStream* pSrcStm = ::utl::UcbStreamHelper::CreateStream( aTempFile.GetURL(), STREAM_READ ); 457 if( pSrcStm ) 458 { 459 rxOStm->SetBufferSize( 0xff00 ); 460 *rxOStm << *pSrcStm; 461 delete pSrcStm; 462 } 463 464 bRet = sal_True; 465 466 xWorkStore->dispose(); 467 xWorkStore = uno::Reference < embed::XStorage >(); 468 rxOStm->Commit(); 469 } 470 break; 471 472 default: 473 DBG_ERROR("unknown object id"); 474 } 475 return bRet; 476 } 477 478 void ScTransferObj::ObjectReleased() 479 { 480 ScModule* pScMod = SC_MOD(); 481 if ( pScMod->GetClipData().pCellClipboard == this ) 482 pScMod->SetClipObject( NULL, NULL ); 483 484 TransferableHelper::ObjectReleased(); 485 } 486 487 void ScTransferObj::DragFinished( sal_Int8 nDropAction ) 488 { 489 if ( nDropAction == DND_ACTION_MOVE && !bDragWasInternal && !(nDragSourceFlags & SC_DROP_NAVIGATOR) ) 490 { 491 // move: delete source data 492 ScDocShell* pSourceSh = GetSourceDocShell(); 493 if (pSourceSh) 494 { 495 ScMarkData aMarkData = GetSourceMarkData(); 496 // external drag&drop doesn't copy objects, so they also aren't deleted: 497 // #105703# bApi=sal_True, don't show error messages from drag&drop 498 pSourceSh->GetDocFunc().DeleteContents( aMarkData, IDF_ALL & ~IDF_OBJECTS, sal_True, sal_True ); 499 } 500 } 501 502 ScModule* pScMod = SC_MOD(); 503 if ( pScMod->GetDragData().pCellTransfer == this ) 504 pScMod->ResetDragObject(); 505 506 xDragSourceRanges = NULL; // don't keep source after dropping 507 508 TransferableHelper::DragFinished( nDropAction ); 509 } 510 511 void ScTransferObj::SetDragHandlePos( SCCOL nX, SCROW nY ) 512 { 513 nDragHandleX = nX; 514 nDragHandleY = nY; 515 } 516 517 void ScTransferObj::SetVisibleTab( SCTAB nNew ) 518 { 519 nVisibleTab = nNew; 520 } 521 522 void ScTransferObj::SetDrawPersist( const SfxObjectShellRef& rRef ) 523 { 524 aDrawPersistRef = rRef; 525 } 526 527 void ScTransferObj::SetDragSource( ScDocShell* pSourceShell, const ScMarkData& rMark ) 528 { 529 ScRangeList aRanges; 530 rMark.FillRangeListWithMarks( &aRanges, sal_False ); 531 xDragSourceRanges = new ScCellRangesObj( pSourceShell, aRanges ); 532 } 533 534 void ScTransferObj::SetDragSourceFlags( sal_uInt16 nFlags ) 535 { 536 nDragSourceFlags = nFlags; 537 } 538 539 void ScTransferObj::SetDragWasInternal() 540 { 541 bDragWasInternal = sal_True; 542 } 543 544 void ScTransferObj::SetUseInApi( bool bSet ) 545 { 546 bUseInApi = bSet; 547 } 548 549 ScDocument* ScTransferObj::GetSourceDocument() 550 { 551 ScDocShell* pSourceDocSh = GetSourceDocShell(); 552 if (pSourceDocSh) 553 return pSourceDocSh->GetDocument(); 554 return NULL; 555 } 556 557 ScDocShell* ScTransferObj::GetSourceDocShell() 558 { 559 ScCellRangesBase* pRangesObj = ScCellRangesBase::getImplementation( xDragSourceRanges ); 560 if (pRangesObj) 561 return pRangesObj->GetDocShell(); 562 563 return NULL; // none set 564 } 565 566 ScMarkData ScTransferObj::GetSourceMarkData() 567 { 568 ScMarkData aMarkData; 569 ScCellRangesBase* pRangesObj = ScCellRangesBase::getImplementation( xDragSourceRanges ); 570 if (pRangesObj) 571 { 572 const ScRangeList& rRanges = pRangesObj->GetRangeList(); 573 aMarkData.MarkFromRangeList( rRanges, sal_False ); 574 } 575 return aMarkData; 576 } 577 578 // 579 // initialize aDocShellRef with a live document from the ClipDoc 580 // 581 582 void ScTransferObj::InitDocShell() 583 { 584 if ( !aDocShellRef.Is() ) 585 { 586 ScDocShell* pDocSh = new ScDocShell; 587 aDocShellRef = pDocSh; // ref must be there before InitNew 588 589 pDocSh->DoInitNew(NULL); 590 591 ScDocument* pDestDoc = pDocSh->GetDocument(); 592 ScMarkData aDestMark; 593 aDestMark.SelectTable( 0, sal_True ); 594 595 pDestDoc->SetDocOptions( pDoc->GetDocOptions() ); // #i42666# 596 597 String aTabName; 598 pDoc->GetName( aBlock.aStart.Tab(), aTabName ); 599 pDestDoc->RenameTab( 0, aTabName, sal_False ); // no UpdateRef (empty) 600 601 pDestDoc->CopyStdStylesFrom( pDoc ); 602 603 SCCOL nStartX = aBlock.aStart.Col(); 604 SCROW nStartY = aBlock.aStart.Row(); 605 SCCOL nEndX = aBlock.aEnd.Col(); 606 SCROW nEndY = aBlock.aEnd.Row(); 607 608 // widths / heights 609 // (must be copied before CopyFromClip, for drawing objects) 610 611 SCCOL nCol, nLastCol; 612 SCTAB nSrcTab = aBlock.aStart.Tab(); 613 pDestDoc->SetLayoutRTL(0, pDoc->IsLayoutRTL(nSrcTab)); 614 for (nCol=nStartX; nCol<=nEndX; nCol++) 615 if ( pDoc->ColHidden(nCol, nSrcTab, nLastCol) ) 616 pDestDoc->ShowCol( nCol, 0, sal_False ); 617 else 618 pDestDoc->SetColWidth( nCol, 0, pDoc->GetColWidth( nCol, nSrcTab ) ); 619 620 ScBitMaskCompressedArray< SCROW, sal_uInt8> & rDestRowFlags = 621 pDestDoc->GetRowFlagsArrayModifiable(0); 622 623 for (SCROW nRow = nStartY; nRow <= nEndY; ++nRow) 624 { 625 sal_uInt8 nSourceFlags = pDoc->GetRowFlags(nRow, nSrcTab); 626 SCROW nLastRow = -1; 627 if ( pDoc->RowHidden(nRow, nSrcTab, nLastRow) ) 628 pDestDoc->ShowRow( nRow, 0, sal_False ); 629 else 630 { 631 pDestDoc->SetRowHeight( nRow, 0, pDoc->GetOriginalHeight( nRow, nSrcTab ) ); 632 633 // if height was set manually, that flag has to be copied, too 634 if ( nSourceFlags & CR_MANUALSIZE ) 635 rDestRowFlags.OrValue( nRow, CR_MANUALSIZE); 636 } 637 } 638 639 if ( pDoc->GetDrawLayer() ) 640 pDocSh->MakeDrawLayer(); 641 642 // cell range is copied to the original position, but on the first sheet 643 // -> bCutMode must be set 644 // pDoc is always a Clipboard-document 645 646 ScRange aDestRange( nStartX,nStartY,0, nEndX,nEndY,0 ); 647 sal_Bool bWasCut = pDoc->IsCutMode(); 648 if (!bWasCut) 649 pDoc->SetClipArea( aDestRange, sal_True ); // Cut 650 pDestDoc->CopyFromClip( aDestRange, aDestMark, IDF_ALL, NULL, pDoc, sal_False ); 651 pDoc->SetClipArea( aDestRange, bWasCut ); 652 653 StripRefs( pDoc, nStartX,nStartY, nEndX,nEndY, pDestDoc, 0,0 ); 654 655 ScRange aMergeRange = aDestRange; 656 pDestDoc->ExtendMerge( aMergeRange, sal_True ); 657 658 pDoc->CopyDdeLinks( pDestDoc ); // copy values of DDE Links 659 660 // page format (grid etc) and page size (maximum size for ole object) 661 662 Size aPaperSize = SvxPaperInfo::GetPaperSize( PAPER_A4 ); // Twips 663 ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool(); 664 String aStyleName = pDoc->GetPageStyle( aBlock.aStart.Tab() ); 665 SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, SFX_STYLE_FAMILY_PAGE ); 666 if (pStyleSheet) 667 { 668 const SfxItemSet& rSourceSet = pStyleSheet->GetItemSet(); 669 aPaperSize = ((const SvxSizeItem&) rSourceSet.Get(ATTR_PAGE_SIZE)).GetSize(); 670 671 // CopyStyleFrom kopiert SetItems mit richtigem Pool 672 ScStyleSheetPool* pDestPool = pDestDoc->GetStyleSheetPool(); 673 pDestPool->CopyStyleFrom( pStylePool, aStyleName, SFX_STYLE_FAMILY_PAGE ); 674 } 675 676 ScViewData aViewData( pDocSh, NULL ); 677 aViewData.SetScreen( nStartX,nStartY, nEndX,nEndY ); 678 aViewData.SetCurX( nStartX ); 679 aViewData.SetCurY( nStartY ); 680 681 pDestDoc->SetViewOptions( pDoc->GetViewOptions() ); 682 683 // Size 684 //! get while copying sizes 685 686 long nPosX = 0; 687 long nPosY = 0; 688 689 for (nCol=0; nCol<nStartX; nCol++) 690 nPosX += pDestDoc->GetColWidth( nCol, 0 ); 691 nPosY += pDestDoc->GetRowHeight( 0, nStartY-1, 0 ); 692 nPosX = (long) ( nPosX * HMM_PER_TWIPS ); 693 nPosY = (long) ( nPosY * HMM_PER_TWIPS ); 694 695 696 aPaperSize.Width() *= 2; // limit OLE object to double of page size 697 aPaperSize.Height() *= 2; 698 699 long nSizeX = 0; 700 long nSizeY = 0; 701 for (nCol=nStartX; nCol<=nEndX; nCol++) 702 { 703 long nAdd = pDestDoc->GetColWidth( nCol, 0 ); 704 if ( nSizeX+nAdd > aPaperSize.Width() && nSizeX ) // above limit? 705 break; 706 nSizeX += nAdd; 707 } 708 for (SCROW nRow=nStartY; nRow<=nEndY; nRow++) 709 { 710 long nAdd = pDestDoc->GetRowHeight( nRow, 0 ); 711 if ( nSizeY+nAdd > aPaperSize.Height() && nSizeY ) // above limit? 712 break; 713 nSizeY += nAdd; 714 } 715 nSizeX = (long) ( nSizeX * HMM_PER_TWIPS ); 716 nSizeY = (long) ( nSizeY * HMM_PER_TWIPS ); 717 718 // pDocSh->SetVisAreaSize( Size(nSizeX,nSizeY) ); 719 720 Rectangle aNewArea( Point(nPosX,nPosY), Size(nSizeX,nSizeY) ); 721 //TODO/LATER: why twice?! 722 //pDocSh->SvInPlaceObject::SetVisArea( aNewArea ); 723 pDocSh->SetVisArea( aNewArea ); 724 725 pDocSh->UpdateOle(&aViewData, sal_True); 726 727 //! SetDocumentModified? 728 if ( pDestDoc->IsChartListenerCollectionNeedsUpdate() ) 729 pDestDoc->UpdateChartListenerCollection(); 730 } 731 } 732 733 // static 734 SfxObjectShell* ScTransferObj::SetDrawClipDoc( sal_Bool bAnyOle ) 735 { 736 // update ScGlobal::pDrawClipDocShellRef 737 738 delete ScGlobal::pDrawClipDocShellRef; 739 if (bAnyOle) 740 { 741 ScGlobal::pDrawClipDocShellRef = 742 new ScDocShellRef(new ScDocShell(SFX_CREATE_MODE_INTERNAL)); // there must be a ref 743 (*ScGlobal::pDrawClipDocShellRef)->DoInitNew(NULL); 744 return *ScGlobal::pDrawClipDocShellRef; 745 } 746 else 747 { 748 ScGlobal::pDrawClipDocShellRef = NULL; 749 return NULL; 750 } 751 } 752 753 // static 754 void ScTransferObj::StripRefs( ScDocument* pDoc, 755 SCCOL nStartX, SCROW nStartY, SCCOL nEndX, SCROW nEndY, 756 ScDocument* pDestDoc, SCCOL nSubX, SCROW nSubY ) 757 { 758 if (!pDestDoc) 759 { 760 pDestDoc = pDoc; 761 DBG_ASSERT(nSubX==0&&nSubY==0, "can't move within the document"); 762 } 763 764 // In a clipboard doc the data don't have to be on the first sheet 765 766 SCTAB nSrcTab = 0; 767 while (nSrcTab<MAXTAB && !pDoc->HasTable(nSrcTab)) 768 ++nSrcTab; 769 SCTAB nDestTab = 0; 770 while (nDestTab<MAXTAB && !pDestDoc->HasTable(nDestTab)) 771 ++nDestTab; 772 773 if (!pDoc->HasTable(nSrcTab) || !pDestDoc->HasTable(nDestTab)) 774 { 775 DBG_ERROR("Sheet not found in ScTransferObj::StripRefs"); 776 return; 777 } 778 779 SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); 780 ScRange aRef; 781 782 ScCellIterator aIter( pDoc, nStartX, nStartY, nSrcTab, nEndX, nEndY, nSrcTab ); 783 ScBaseCell* pCell = aIter.GetFirst(); 784 while (pCell) 785 { 786 if (pCell->GetCellType() == CELLTYPE_FORMULA) 787 { 788 ScFormulaCell* pFCell = (ScFormulaCell*) pCell; 789 sal_Bool bOut = sal_False; 790 ScDetectiveRefIter aRefIter( pFCell ); 791 while ( !bOut && aRefIter.GetNextRef( aRef ) ) 792 { 793 if ( aRef.aStart.Tab() != nSrcTab || aRef.aEnd.Tab() != nSrcTab || 794 aRef.aStart.Col() < nStartX || aRef.aEnd.Col() > nEndX || 795 aRef.aStart.Row() < nStartY || aRef.aEnd.Row() > nEndY ) 796 bOut = sal_True; 797 } 798 if (bOut) 799 { 800 SCCOL nCol = aIter.GetCol() - nSubX; 801 SCROW nRow = aIter.GetRow() - nSubY; 802 803 ScBaseCell* pNew = 0; 804 sal_uInt16 nErrCode = pFCell->GetErrCode(); 805 if (nErrCode) 806 { 807 pNew = new ScStringCell( ScGlobal::GetErrorString(nErrCode) ); 808 if ( ((const SvxHorJustifyItem*) pDestDoc->GetAttr( 809 nCol,nRow,nDestTab, ATTR_HOR_JUSTIFY))->GetValue() == 810 SVX_HOR_JUSTIFY_STANDARD ) 811 pDestDoc->ApplyAttr( nCol,nRow,nDestTab, 812 SvxHorJustifyItem(SVX_HOR_JUSTIFY_RIGHT, ATTR_HOR_JUSTIFY) ); 813 } 814 else if (pFCell->IsValue()) 815 { 816 double fVal = pFCell->GetValue(); 817 pNew = new ScValueCell( fVal ); 818 } 819 else 820 { 821 String aStr; 822 pFCell->GetString(aStr); 823 if ( pFCell->IsMultilineResult() ) 824 pNew = new ScEditCell( aStr, pDestDoc ); 825 else 826 pNew = new ScStringCell( aStr ); 827 } 828 pDestDoc->PutCell( nCol,nRow,nDestTab, pNew ); 829 830 // number formats 831 832 sal_uLong nOldFormat = ((const SfxUInt32Item*) 833 pDestDoc->GetAttr(nCol,nRow,nDestTab, ATTR_VALUE_FORMAT))->GetValue(); 834 if ( (nOldFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 ) 835 { 836 sal_uLong nNewFormat = pFCell->GetStandardFormat( *pFormatter, 837 nOldFormat ); 838 pDestDoc->ApplyAttr( nCol,nRow,nDestTab, 839 SfxUInt32Item(ATTR_VALUE_FORMAT, nNewFormat) ); 840 } 841 } 842 } 843 pCell = aIter.GetNext(); 844 } 845 } 846 847 const com::sun::star::uno::Sequence< sal_Int8 >& ScTransferObj::getUnoTunnelId() 848 { 849 static com::sun::star::uno::Sequence< sal_Int8 > aSeq; 850 if( !aSeq.getLength() ) 851 { 852 static osl::Mutex aCreateMutex; 853 osl::Guard< osl::Mutex > aGuard( aCreateMutex ); 854 aSeq.realloc( 16 ); 855 rtl_createUuid( reinterpret_cast< sal_uInt8* >( aSeq.getArray() ), 0, sal_True ); 856 } 857 return aSeq; 858 } 859 860 sal_Int64 SAL_CALL ScTransferObj::getSomething( const com::sun::star::uno::Sequence< sal_Int8 >& rId ) throw( com::sun::star::uno::RuntimeException ) 861 { 862 sal_Int64 nRet; 863 if( ( rId.getLength() == 16 ) && 864 ( 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) ) 865 { 866 nRet = reinterpret_cast< sal_Int64 >( this ); 867 } 868 else 869 nRet = TransferableHelper::getSomething(rId); 870 return nRet; 871 } 872 873 874