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 32 33 //---------------------------------------------------------------------------- 34 35 #define _SV_NOXSOUND 36 37 #define _BASE_DLGS_HXX 38 #define _BIGINT_HXX 39 #define _CACHESTR_HXX 40 #define _CONFIG_HXX 41 #define _CURSOR_HXX 42 #define _CTRLTOOL_HXX 43 #define _DLGCFG_HXX 44 #define _DYNARR_HXX 45 #define _EXTATTR_HXX 46 #define _FILDLG_HXX 47 #define _FONTDLG_HXX 48 #define _FRM3D_HXX 49 #define _INTRO_HXX 50 #define _ISETBWR_HXX 51 #define _NO_SVRTF_PARSER_HXX 52 #define _MACRODLG_HXX 53 #define _MODALDLG_HXX 54 #define _MOREBUTTON_HXX 55 #define _OUTLINER_HXX 56 //#define _PRNDLG_HXX 57 //#define _POLY_HXX 58 #define _PVRWIN_HXX 59 //#define _QUEUE_HXX 60 #define _RULER_HXX 61 #define _SCRWIN_HXX 62 #define _SETBRW_HXX 63 //#define _STACK_HXX 64 //#define _STATUS_HXX *** 65 #define _STDCTRL_HXX 66 #define _STDMENU_HXX 67 //#define _TAB_HXX 68 #define _TABBAR_HXX 69 #define _TREELIST_HXX 70 #define _VALUESET_HXX 71 #define _VCATTR_HXX 72 #define _VCBRW_HXX 73 #define _VCTRLS_HXX 74 #define _VCSBX_HXX 75 #define _VCONT_HXX 76 #define _VDRWOBJ_HXX 77 78 //#define _SELENG_HXX 79 //#define _SOUND_HXX 80 //#define _SYSDLG_HXX 81 82 83 84 85 #define _PASSWD_HXX 86 87 #define _SFX_DOCFILE_HXX 88 //#define _SFX_DOCFILT_HXX 89 #define _SFX_DOCINF_HXX 90 #define _SFX_DOCSH_HXX 91 //#define _SFXDOCFILT_HXX 92 //#define _SFXDOCINF_HXX 93 //#define _SFXDOCSH_HXX 94 #define _SFX_PRNMON_HXX 95 #define _SFX_RESMGR_HXX 96 #define _SFX_TEMPLDLG_HXX 97 //#define _SFXAPPWIN_HXX 98 #define _SFXBASIC_HXX 99 #define _SFXCTRLITEM 100 #define _SFXDLGCFG_HXX 101 //#define _SFXDISPATCH_HXX 102 #define _SFXFILEDLG_HXX 103 //#define _SFXIMGMGR_HXX 104 #define _SFXIPFRM_HXX 105 #define _SFX_MACRO_HXX 106 #define _SFXMNUITEM_HXX 107 #define _SFXMNUMGR_HXX 108 #define _SFXMULTISEL_HXX 109 //#define _SFXMSG_HXX 110 #define _SFXMSGDESCR_HXX 111 #define _SFXMSGPOOL_HXX 112 #define _SFX_MINFITEM_HXX 113 #define _SFXOBJFACE_HXX 114 #define _SFXOBJFAC_HXX 115 #define _SFX_SAVEOPT_HXX 116 #define _SFXSTBITEM_HXX 117 #define _SFXSTBMGR_HXX 118 #define _SFXTBXCTRL_HXX 119 #define _SFXTBXMGR_HXX 120 121 #define _SI_HXX 122 //#define _SI_DLL_HXX 123 //#define _SIDLL_HXX 124 //#define _SI_NOITEMS 125 //#define _SI_NOOTHERFORMS 126 //#define _SI_NOSBXCONTROLS 127 //#define _SINOSBXCONTROLS 128 //#define _SI_NODRW 129 //#define _SI_NOCONTROL 130 131 #define _SVBOXITM_HXX 132 #define _SVCONTNR_HXX // 133 134 #define _SDR_NOTRANSFORM 135 136 #define _SVDRAG_HXX 137 #define _SVINCVW_HXX 138 //#define _SV_MULTISEL_HXX 139 #define _SVRTV_HXX 140 #define _SVTABBX_HXX 141 #define _SVTREEBOX_HXX 142 #define _SVTREELIST_HXX 143 144 #define _SVX_DAILDLL_HXX 145 #define _SVX_HYPHEN_HXX 146 #define _SVX_IMPGRF_HXX 147 #define _SVX_LAYCTRL_HXX 148 #define _SVX_OPTITEMS_HXX 149 #define _SVX_OPTGERL_HXX 150 #define _SVX_OPTSAVE_HXX 151 #define _SVX_OPTSPELL_HXX 152 #define _SVX_OPTPATH_HXX 153 #define _SVX_OPTLINGU_HXX 154 #define _SVX_RULER_HXX 155 #define _SVX_RULRITEM_HXX 156 #define _SVX_SELCTRL_HXX 157 #define _SVX_SPLWRAP_HXX 158 #define _SVX_SPLDLG_HXX 159 #define _SVX_STDDLG_HXX 160 #define _SVX_THESDLG_HXX 161 162 // INCLUDE ------------------------------------------------------------------- 163 164 #include "scitems.hxx" 165 #include <svx/dbexch.hrc> 166 #include <svx/svdetc.hxx> 167 #include <svx/svditer.hxx> 168 #include <svx/svdoole2.hxx> 169 #include <svx/svdpage.hxx> 170 #include <sfx2/dispatch.hxx> 171 #include <sfx2/docfile.hxx> 172 #include <svl/stritem.hxx> 173 #include <svl/ptitem.hxx> 174 #include <svl/urlbmk.hxx> 175 #include <sot/clsids.hxx> 176 #include <sot/formats.hxx> 177 #include <vcl/graph.hxx> 178 #include <vcl/virdev.hxx> 179 #include <vcl/msgbox.hxx> 180 #include <tools/urlobj.hxx> 181 #include <sot/exchange.hxx> 182 #include <memory> 183 184 #include "attrib.hxx" 185 #include "patattr.hxx" 186 #include "dociter.hxx" 187 #include "viewfunc.hxx" 188 #include "tabvwsh.hxx" 189 #include "docsh.hxx" 190 #include "docfunc.hxx" 191 #include "undoblk.hxx" 192 #include "refundo.hxx" 193 #include "globstr.hrc" 194 #include "global.hxx" 195 #include "transobj.hxx" 196 #include "drwtrans.hxx" 197 #include "rangenam.hxx" 198 #include "dbcolect.hxx" 199 #include "impex.hxx" // Sylk-ID fuer CB 200 #include "chgtrack.hxx" 201 #include "waitoff.hxx" 202 #include "scmod.hxx" 203 #include "sc.hrc" 204 #include "inputopt.hxx" 205 #include "warnbox.hxx" 206 #include "drwlayer.hxx" 207 #include "editable.hxx" 208 #include "transobj.hxx" 209 #include "drwtrans.hxx" 210 #include "docuno.hxx" 211 #include "clipparam.hxx" 212 #include "drawview.hxx" 213 #include "chartlis.hxx" 214 #include "charthelper.hxx" 215 216 217 using namespace com::sun::star; 218 219 // STATIC DATA --------------------------------------------------------------- 220 221 222 //============================================================================ 223 224 // GlobalName der Writer-DocShell kommt jetzt aus comphelper/classids.hxx 225 226 //---------------------------------------------------------------------------- 227 // C U T 228 229 void ScViewFunc::CutToClip( ScDocument* pClipDoc, sal_Bool bIncludeObjects ) 230 { 231 UpdateInputLine(); 232 233 ScEditableTester aTester( this ); 234 if (!aTester.IsEditable()) // selection editable? 235 { 236 ErrorMessage( aTester.GetMessageId() ); 237 return; 238 } 239 240 ScRange aRange; // zu loeschender Bereich 241 if ( GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE ) 242 { 243 ScDocument* pDoc = GetViewData()->GetDocument(); 244 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 245 ScMarkData& rMark = GetViewData()->GetMarkData(); 246 const sal_Bool bRecord(pDoc->IsUndoEnabled()); // Undo/Redo 247 248 ScDocShellModificator aModificator( *pDocSh ); 249 250 if ( !rMark.IsMarked() && !rMark.IsMultiMarked() ) // mark the range if not marked yet 251 { 252 DoneBlockMode(); 253 InitOwnBlockMode(); 254 rMark.SetMarkArea( aRange ); 255 MarkDataChanged(); 256 } 257 258 CopyToClip( pClipDoc, sal_True, sal_False, bIncludeObjects ); // Ab ins Clipboard 259 260 ScAddress aOldEnd( aRange.aEnd ); // Zusammengefasste Zellen im Bereich? 261 pDoc->ExtendMerge( aRange, sal_True ); 262 263 ScDocument* pUndoDoc = NULL; 264 if ( bRecord ) 265 { 266 pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 267 pUndoDoc->InitUndoSelected( pDoc, rMark ); 268 // all sheets - CopyToDocument skips those that don't exist in pUndoDoc 269 ScRange aCopyRange = aRange; 270 aCopyRange.aStart.SetTab(0); 271 aCopyRange.aEnd.SetTab(pDoc->GetTableCount()-1); 272 pDoc->CopyToDocument( aCopyRange, (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS, sal_False, pUndoDoc ); 273 pDoc->BeginDrawUndo(); 274 } 275 276 sal_uInt16 nExtFlags = 0; 277 pDocSh->UpdatePaintExt( nExtFlags, aRange ); 278 279 HideCursor(); // Cursor aendert sich ! 280 281 rMark.MarkToMulti(); 282 pDoc->DeleteSelection( IDF_ALL, rMark ); 283 if ( bIncludeObjects ) 284 pDoc->DeleteObjectsInSelection( rMark ); 285 rMark.MarkToSimple(); 286 287 if ( !AdjustRowHeight( aRange.aStart.Row(), aRange.aEnd.Row() ) ) 288 pDocSh->PostPaint( aRange, PAINT_GRID, nExtFlags ); 289 290 if ( bRecord ) // erst jetzt ist Draw-Undo verfuegbar 291 pDocSh->GetUndoManager()->AddUndoAction( 292 new ScUndoCut( pDocSh, aRange, aOldEnd, rMark, pUndoDoc ) ); 293 294 aModificator.SetDocumentModified(); 295 ShowCursor(); // Cursor aendert sich ! 296 pDocSh->UpdateOle(GetViewData()); 297 298 CellContentChanged(); 299 } 300 else 301 ErrorMessage( STR_NOMULTISELECT ); 302 } 303 304 305 //---------------------------------------------------------------------------- 306 // C O P Y 307 308 sal_Bool ScViewFunc::CopyToClip( ScDocument* pClipDoc, sal_Bool bCut, sal_Bool bApi, sal_Bool bIncludeObjects, sal_Bool bStopEdit ) 309 { 310 sal_Bool bDone = sal_False; 311 if ( bStopEdit ) 312 UpdateInputLine(); 313 314 ScRange aRange; 315 ScMarkType eMarkType = GetViewData()->GetSimpleArea( aRange ); 316 ScDocument* pDoc = GetViewData()->GetDocument(); 317 ScMarkData& rMark = GetViewData()->GetMarkData(); 318 if ( eMarkType == SC_MARK_SIMPLE || eMarkType == SC_MARK_SIMPLE_FILTERED ) 319 { 320 if ( !pDoc->HasSelectedBlockMatrixFragment( 321 aRange.aStart.Col(), aRange.aStart.Row(), 322 aRange.aEnd.Col(), aRange.aEnd.Row(), 323 rMark ) ) 324 { 325 sal_Bool bSysClip = sal_False; 326 if ( !pClipDoc ) // no clip doc specified 327 { 328 pClipDoc = new ScDocument( SCDOCMODE_CLIP ); // create one (deleted by ScTransferObj) 329 bSysClip = sal_True; // and copy into system 330 } 331 332 if ( !bCut ) 333 { 334 ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); 335 if ( pChangeTrack ) 336 pChangeTrack->ResetLastCut(); // kein CutMode mehr 337 } 338 339 if ( bSysClip && bIncludeObjects ) 340 { 341 sal_Bool bAnyOle = pDoc->HasOLEObjectsInArea( aRange, &rMark ); 342 // update ScGlobal::pDrawClipDocShellRef 343 ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) ); 344 } 345 346 ScClipParam aClipParam(aRange, bCut); 347 aClipParam.setSourceDocID( pDoc->GetDocumentID() ); 348 pDoc->CopyToClip(aClipParam, pClipDoc, &rMark, false, false, bIncludeObjects); 349 350 if ( pDoc && pClipDoc ) 351 { 352 ScDrawLayer* pDrawLayer = pClipDoc->GetDrawLayer(); 353 if ( pDrawLayer ) 354 { 355 ScClipParam& rClipParam = pClipDoc->GetClipParam(); 356 ScRangeListVector& rRangesVector = rClipParam.maProtectedChartRangesVector; 357 SCTAB nTabCount = pClipDoc->GetTableCount(); 358 for ( SCTAB nTab = 0; nTab < nTabCount; ++nTab ) 359 { 360 SdrPage* pPage = pDrawLayer->GetPage( static_cast< sal_uInt16 >( nTab ) ); 361 if ( pPage ) 362 { 363 ScChartHelper::FillProtectedChartRangesVector( rRangesVector, pDoc, pPage ); 364 } 365 } 366 } 367 } 368 369 if (bSysClip) 370 { 371 ScDrawLayer::SetGlobalDrawPersist(NULL); 372 373 ScGlobal::SetClipDocName( pDoc->GetDocumentShell()->GetTitle( SFX_TITLE_FULLNAME ) ); 374 } 375 pClipDoc->ExtendMerge( aRange, sal_True ); 376 377 if (bSysClip) 378 { 379 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 380 TransferableObjectDescriptor aObjDesc; 381 pDocSh->FillTransferableObjectDescriptor( aObjDesc ); 382 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass(); 383 // maSize is set in ScTransferObj ctor 384 385 ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc ); 386 uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj ); 387 388 if ( ScGlobal::pDrawClipDocShellRef ) 389 { 390 SfxObjectShellRef aPersistRef( &(*ScGlobal::pDrawClipDocShellRef) ); 391 pTransferObj->SetDrawPersist( aPersistRef ); // keep persist for ole objects alive 392 } 393 394 pTransferObj->CopyToClipboard( GetActiveWin() ); // system clipboard 395 SC_MOD()->SetClipObject( pTransferObj, NULL ); // internal clipboard 396 } 397 398 bDone = sal_True; 399 } 400 else 401 { 402 if (!bApi) 403 ErrorMessage(STR_MATRIXFRAGMENTERR); 404 } 405 } 406 else if (eMarkType == SC_MARK_MULTI) 407 { 408 bool bSuccess = false; 409 ScClipParam aClipParam; 410 aClipParam.mbCutMode = false; 411 rMark.MarkToSimple(); 412 rMark.FillRangeListWithMarks(&aClipParam.maRanges, false); 413 414 do 415 { 416 if (bCut) 417 // We con't support cutting of multi-selections. 418 break; 419 420 if (pClipDoc) 421 // TODO: What's this for? 422 break; 423 424 ::std::auto_ptr<ScDocument> pDocClip(new ScDocument(SCDOCMODE_CLIP)); 425 426 // Check for geometrical feasibility of the ranges. 427 bool bValidRanges = true; 428 ScRangePtr p = aClipParam.maRanges.First(); 429 SCCOL nPrevColDelta = 0; 430 SCROW nPrevRowDelta = 0; 431 SCCOL nPrevCol = p->aStart.Col(); 432 SCROW nPrevRow = p->aStart.Row(); 433 SCCOL nPrevColSize = p->aEnd.Col() - p->aStart.Col() + 1; 434 SCROW nPrevRowSize = p->aEnd.Row() - p->aStart.Row() + 1; 435 for (p = aClipParam.maRanges.Next(); p; p = aClipParam.maRanges.Next()) 436 { 437 if (pDoc->HasSelectedBlockMatrixFragment( 438 p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(), rMark)) 439 { 440 if (!bApi) 441 ErrorMessage(STR_MATRIXFRAGMENTERR); 442 return false; 443 } 444 445 SCCOL nColDelta = p->aStart.Col() - nPrevCol; 446 SCROW nRowDelta = p->aStart.Row() - nPrevRow; 447 448 if ((nColDelta && nRowDelta) || (nPrevColDelta && nRowDelta) || (nPrevRowDelta && nColDelta)) 449 { 450 bValidRanges = false; 451 break; 452 } 453 454 if (aClipParam.meDirection == ScClipParam::Unspecified) 455 { 456 if (nColDelta) 457 aClipParam.meDirection = ScClipParam::Column; 458 if (nRowDelta) 459 aClipParam.meDirection = ScClipParam::Row; 460 } 461 462 SCCOL nColSize = p->aEnd.Col() - p->aStart.Col() + 1; 463 SCROW nRowSize = p->aEnd.Row() - p->aStart.Row() + 1; 464 465 if (aClipParam.meDirection == ScClipParam::Column && nRowSize != nPrevRowSize) 466 { 467 // column-oriented ranges must have identical row size. 468 bValidRanges = false; 469 break; 470 } 471 if (aClipParam.meDirection == ScClipParam::Row && nColSize != nPrevColSize) 472 { 473 // likewise, row-oriented ranges must have identical 474 // column size. 475 bValidRanges = false; 476 break; 477 } 478 479 nPrevCol = p->aStart.Col(); 480 nPrevRow = p->aStart.Row(); 481 nPrevColDelta = nColDelta; 482 nPrevRowDelta = nRowDelta; 483 nPrevColSize = nColSize; 484 nPrevRowSize = nRowSize; 485 } 486 if (!bValidRanges) 487 break; 488 489 pDoc->CopyToClip(aClipParam, pDocClip.get(), &rMark, false, false, bIncludeObjects); 490 491 ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); 492 if ( pChangeTrack ) 493 pChangeTrack->ResetLastCut(); // kein CutMode mehr 494 495 { 496 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 497 TransferableObjectDescriptor aObjDesc; 498 pDocSh->FillTransferableObjectDescriptor( aObjDesc ); 499 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass(); 500 // maSize is set in ScTransferObj ctor 501 502 ScTransferObj* pTransferObj = new ScTransferObj( pDocClip.release(), aObjDesc ); 503 uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj ); 504 505 if ( ScGlobal::pDrawClipDocShellRef ) 506 { 507 SfxObjectShellRef aPersistRef( &(*ScGlobal::pDrawClipDocShellRef) ); 508 pTransferObj->SetDrawPersist( aPersistRef ); // keep persist for ole objects alive 509 } 510 511 pTransferObj->CopyToClipboard( GetActiveWin() ); // system clipboard 512 SC_MOD()->SetClipObject( pTransferObj, NULL ); // internal clipboard 513 } 514 515 bSuccess = true; 516 } 517 while (false); 518 519 if (!bSuccess && !bApi) 520 ErrorMessage(STR_NOMULTISELECT); 521 522 bDone = bSuccess; 523 } 524 else 525 { 526 if (!bApi) 527 ErrorMessage(STR_NOMULTISELECT); 528 } 529 530 return bDone; 531 } 532 533 ScTransferObj* ScViewFunc::CopyToTransferable() 534 { 535 ScRange aRange; 536 if ( GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE ) 537 { 538 ScDocument* pDoc = GetViewData()->GetDocument(); 539 ScMarkData& rMark = GetViewData()->GetMarkData(); 540 if ( !pDoc->HasSelectedBlockMatrixFragment( 541 aRange.aStart.Col(), aRange.aStart.Row(), 542 aRange.aEnd.Col(), aRange.aEnd.Row(), 543 rMark ) ) 544 { 545 ScDocument *pClipDoc = new ScDocument( SCDOCMODE_CLIP ); // create one (deleted by ScTransferObj) 546 547 sal_Bool bAnyOle = pDoc->HasOLEObjectsInArea( aRange, &rMark ); 548 ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) ); 549 550 ScClipParam aClipParam(aRange, false); 551 pDoc->CopyToClip(aClipParam, pClipDoc, &rMark, false, false, true); 552 553 ScDrawLayer::SetGlobalDrawPersist(NULL); 554 pClipDoc->ExtendMerge( aRange, sal_True ); 555 556 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 557 TransferableObjectDescriptor aObjDesc; 558 pDocSh->FillTransferableObjectDescriptor( aObjDesc ); 559 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass(); 560 ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc ); 561 return pTransferObj; 562 } 563 } 564 565 return NULL; 566 } 567 568 //---------------------------------------------------------------------------- 569 // P A S T E 570 571 void ScViewFunc::PasteDraw() 572 { 573 ScViewData* pViewData = GetViewData(); 574 SCCOL nPosX = pViewData->GetCurX(); 575 SCROW nPosY = pViewData->GetCurY(); 576 Window* pWin = GetActiveWin(); 577 Point aPos = pWin->PixelToLogic( pViewData->GetScrPos( nPosX, nPosY, 578 pViewData->GetActivePart() ) ); 579 ScDrawTransferObj* pDrawClip = ScDrawTransferObj::GetOwnClipboard( pWin ); 580 if (pDrawClip) 581 PasteDraw( aPos, pDrawClip->GetModel(), sal_False, 582 pDrawClip->GetSourceDocID() == pViewData->GetDocument()->GetDocumentID() ); 583 } 584 585 void ScViewFunc::PasteFromSystem() 586 { 587 UpdateInputLine(); 588 589 Window* pWin = GetActiveWin(); 590 ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin ); 591 ScDrawTransferObj* pDrawClip = ScDrawTransferObj::GetOwnClipboard( pWin ); 592 593 if (pOwnClip) 594 { 595 // #129384# keep a reference in case the clipboard is changed during PasteFromClip 596 uno::Reference<datatransfer::XTransferable> aOwnClipRef( pOwnClip ); 597 PasteFromClip( IDF_ALL, pOwnClip->GetDocument(), 598 PASTE_NOFUNC, sal_False, sal_False, sal_False, INS_NONE, IDF_NONE, 599 sal_True ); // allow warning dialog 600 } 601 else if (pDrawClip) 602 PasteDraw(); 603 else 604 { 605 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) ); 606 607 // if (pClipObj.Is()) 608 { 609 sal_uLong nBiff8 = SotExchange::RegisterFormatName( 610 String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Biff8"))); 611 sal_uLong nBiff5 = SotExchange::RegisterFormatName( 612 String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Biff5"))); 613 614 // als erstes SvDraw-Model, dann Grafik 615 // (Grafik darf nur bei einzelner Grafik drinstehen) 616 617 if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING )) 618 { 619 // special case for tables from drawing 620 if( aDataHelper.HasFormat( SOT_FORMAT_RTF ) ) 621 { 622 PasteFromSystem( FORMAT_RTF ); 623 } 624 else 625 { 626 PasteFromSystem( SOT_FORMATSTR_ID_DRAWING ); 627 } 628 } 629 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB )) 630 PasteFromSystem( SOT_FORMATSTR_ID_SVXB ); 631 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE )) 632 { 633 // If it's a Writer object, insert RTF instead of OLE 634 635 sal_Bool bDoRtf = sal_False; 636 TransferableObjectDescriptor aObjDesc; 637 if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) ) 638 { 639 bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) || 640 aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) ) 641 && aDataHelper.HasFormat( SOT_FORMAT_RTF ) ); 642 } 643 if ( bDoRtf ) 644 PasteFromSystem( FORMAT_RTF ); 645 else 646 PasteFromSystem( SOT_FORMATSTR_ID_EMBED_SOURCE ); 647 } 648 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE )) 649 PasteFromSystem( SOT_FORMATSTR_ID_LINK_SOURCE ); 650 // the following format can not affect scenario from #89579# 651 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE )) 652 PasteFromSystem( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ); 653 // FORMAT_PRIVATE no longer here (can't work if pOwnClip is NULL) 654 else if (aDataHelper.HasFormat(nBiff8)) // before xxx_OLE formats 655 PasteFromSystem(nBiff8); 656 else if (aDataHelper.HasFormat(nBiff5)) 657 PasteFromSystem(nBiff5); 658 else if (aDataHelper.HasFormat(FORMAT_RTF)) 659 PasteFromSystem(FORMAT_RTF); 660 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML)) 661 PasteFromSystem(SOT_FORMATSTR_ID_HTML); 662 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML_SIMPLE)) 663 PasteFromSystem(SOT_FORMATSTR_ID_HTML_SIMPLE); 664 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_SYLK)) 665 PasteFromSystem(SOT_FORMATSTR_ID_SYLK); 666 else if (aDataHelper.HasFormat(FORMAT_STRING)) 667 PasteFromSystem(FORMAT_STRING); 668 else if (aDataHelper.HasFormat(FORMAT_GDIMETAFILE)) 669 PasteFromSystem(FORMAT_GDIMETAFILE); 670 else if (aDataHelper.HasFormat(FORMAT_BITMAP)) 671 PasteFromSystem(FORMAT_BITMAP); 672 // #89579# xxx_OLE formats come last, like in SotExchange tables 673 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE )) 674 PasteFromSystem( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ); 675 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE )) 676 PasteFromSystem( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ); 677 // else 678 // ErrorMessage(STR_PASTE_ERROR); 679 } 680 // else 681 // ErrorMessage(STR_PASTE_ERROR); 682 } 683 684 // keine Fehlermeldung, weil SID_PASTE in der idl das FastCall-Flag hat, 685 // also auch gerufen wird, wenn nichts im Clipboard steht (#42531#) 686 } 687 688 void ScViewFunc::PasteFromTransferable( const uno::Reference<datatransfer::XTransferable>& rxTransferable ) 689 { 690 ScTransferObj *pOwnClip=0; 691 ScDrawTransferObj *pDrawClip=0; 692 uno::Reference<lang::XUnoTunnel> xTunnel( rxTransferable, uno::UNO_QUERY ); 693 if ( xTunnel.is() ) 694 { 695 sal_Int64 nHandle = xTunnel->getSomething( ScTransferObj::getUnoTunnelId() ); 696 if ( nHandle ) 697 pOwnClip = (ScTransferObj*) (sal_IntPtr) nHandle; 698 else 699 { 700 nHandle = xTunnel->getSomething( ScDrawTransferObj::getUnoTunnelId() ); 701 if ( nHandle ) 702 pDrawClip = (ScDrawTransferObj*) (sal_IntPtr) nHandle; 703 } 704 } 705 706 if (pOwnClip) 707 { 708 PasteFromClip( IDF_ALL, pOwnClip->GetDocument(), 709 PASTE_NOFUNC, sal_False, sal_False, sal_False, INS_NONE, IDF_NONE, 710 sal_True ); // allow warning dialog 711 } 712 else if (pDrawClip) 713 { 714 ScViewData* pViewData = GetViewData(); 715 SCCOL nPosX = pViewData->GetCurX(); 716 SCROW nPosY = pViewData->GetCurY(); 717 Window* pWin = GetActiveWin(); 718 Point aPos = pWin->PixelToLogic( pViewData->GetScrPos( nPosX, nPosY, pViewData->GetActivePart() ) ); 719 PasteDraw( aPos, pDrawClip->GetModel(), sal_False, pDrawClip->GetSourceDocID() == pViewData->GetDocument()->GetDocumentID() ); 720 } 721 else 722 { 723 TransferableDataHelper aDataHelper( rxTransferable ); 724 { 725 sal_uLong nBiff8 = SotExchange::RegisterFormatName( 726 String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Biff8"))); 727 sal_uLong nBiff5 = SotExchange::RegisterFormatName( 728 String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Biff5"))); 729 sal_uLong nFormatId = 0; 730 // als erstes SvDraw-Model, dann Grafik 731 // (Grafik darf nur bei einzelner Grafik drinstehen) 732 733 if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING )) 734 nFormatId = SOT_FORMATSTR_ID_DRAWING; 735 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB )) 736 nFormatId = SOT_FORMATSTR_ID_SVXB; 737 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE )) 738 { 739 // If it's a Writer object, insert RTF instead of OLE 740 sal_Bool bDoRtf = sal_False; 741 TransferableObjectDescriptor aObjDesc; 742 if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) ) 743 { 744 bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) || 745 aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) ) 746 && aDataHelper.HasFormat( SOT_FORMAT_RTF ) ); 747 } 748 if ( bDoRtf ) 749 nFormatId = FORMAT_RTF; 750 else 751 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE; 752 } 753 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE )) 754 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE; 755 // the following format can not affect scenario from #89579# 756 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE )) 757 nFormatId = SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE; 758 // FORMAT_PRIVATE no longer here (can't work if pOwnClip is NULL) 759 else if (aDataHelper.HasFormat(nBiff8)) // before xxx_OLE formats 760 nFormatId = nBiff8; 761 else if (aDataHelper.HasFormat(nBiff5)) 762 nFormatId = nBiff5; 763 else if (aDataHelper.HasFormat(FORMAT_RTF)) 764 nFormatId = FORMAT_RTF; 765 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML)) 766 nFormatId = SOT_FORMATSTR_ID_HTML; 767 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML_SIMPLE)) 768 nFormatId = SOT_FORMATSTR_ID_HTML_SIMPLE; 769 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_SYLK)) 770 nFormatId = SOT_FORMATSTR_ID_SYLK; 771 else if (aDataHelper.HasFormat(FORMAT_STRING)) 772 nFormatId = FORMAT_STRING; 773 else if (aDataHelper.HasFormat(FORMAT_GDIMETAFILE)) 774 nFormatId = FORMAT_GDIMETAFILE; 775 else if (aDataHelper.HasFormat(FORMAT_BITMAP)) 776 nFormatId = FORMAT_BITMAP; 777 // #89579# xxx_OLE formats come last, like in SotExchange tables 778 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE )) 779 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE_OLE; 780 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE )) 781 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE; 782 else 783 return; 784 785 PasteDataFormat( nFormatId, aDataHelper.GetTransferable(), 786 GetViewData()->GetCurX(), GetViewData()->GetCurY(), 787 NULL, sal_False, sal_False ); 788 } 789 } 790 } 791 792 sal_Bool ScViewFunc::PasteFromSystem( sal_uLong nFormatId, sal_Bool bApi ) 793 { 794 UpdateInputLine(); 795 796 sal_Bool bRet = sal_True; 797 Window* pWin = GetActiveWin(); 798 ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin ); 799 if ( nFormatId == 0 && pOwnClip ) 800 { 801 // #129384# keep a reference in case the clipboard is changed during PasteFromClip 802 uno::Reference<datatransfer::XTransferable> aOwnClipRef( pOwnClip ); 803 PasteFromClip( IDF_ALL, pOwnClip->GetDocument(), 804 PASTE_NOFUNC, sal_False, sal_False, sal_False, INS_NONE, IDF_NONE, 805 !bApi ); // allow warning dialog 806 } 807 else 808 { 809 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) ); 810 if ( !aDataHelper.GetTransferable().is() ) 811 return sal_False; 812 813 bRet = PasteDataFormat( nFormatId, aDataHelper.GetTransferable(), 814 GetViewData()->GetCurX(), GetViewData()->GetCurY(), 815 NULL, sal_False, !bApi ); // allow warning dialog 816 817 if ( !bRet && !bApi ) 818 ErrorMessage(STR_PASTE_ERROR); 819 } 820 return bRet; 821 } 822 823 824 //---------------------------------------------------------------------------- 825 // P A S T E 826 827 sal_Bool ScViewFunc::PasteOnDrawObject( const uno::Reference<datatransfer::XTransferable>& rxTransferable, 828 SdrObject* pHitObj, sal_Bool bLink ) 829 { 830 sal_Bool bRet = sal_False; 831 if ( bLink ) 832 { 833 TransferableDataHelper aDataHelper( rxTransferable ); 834 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) ) 835 { 836 SotStorageStreamRef xStm; 837 if( aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_SVXB, xStm ) ) 838 { 839 Graphic aGraphic; 840 *xStm >> aGraphic; 841 bRet = ApplyGraphicToObject( pHitObj, aGraphic ); 842 } 843 } 844 else if ( aDataHelper.HasFormat( SOT_FORMAT_GDIMETAFILE ) ) 845 { 846 GDIMetaFile aMtf; 847 if( aDataHelper.GetGDIMetaFile( FORMAT_GDIMETAFILE, aMtf ) ) 848 bRet = ApplyGraphicToObject( pHitObj, Graphic(aMtf) ); 849 } 850 else if ( aDataHelper.HasFormat( SOT_FORMAT_BITMAP ) ) 851 { 852 Bitmap aBmp; 853 if( aDataHelper.GetBitmap( FORMAT_BITMAP, aBmp ) ) 854 bRet = ApplyGraphicToObject( pHitObj, Graphic(aBmp) ); 855 } 856 } 857 else 858 { 859 // ham' wa noch nich 860 } 861 return bRet; 862 } 863 864 sal_Bool lcl_SelHasAttrib( ScDocument* pDoc, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, 865 const ScMarkData& rTabSelection, sal_uInt16 nMask ) 866 { 867 SCTAB nTabCount = pDoc->GetTableCount(); 868 for (SCTAB nTab=0; nTab<nTabCount; nTab++) 869 if ( rTabSelection.GetTableSelect(nTab) && pDoc->HasAttrib( nCol1, nRow1, nTab, nCol2, nRow2, nTab, nMask ) ) 870 return sal_True; 871 return sal_False; 872 } 873 874 // 875 // Einfuegen auf Tabelle: 876 // 877 878 // internes Paste 879 880 namespace { 881 882 class CursorSwitcher 883 { 884 public: 885 CursorSwitcher(ScViewFunc* pViewFunc) : 886 mpViewFunc(pViewFunc) 887 { 888 mpViewFunc->HideCursor(); 889 } 890 891 ~CursorSwitcher() 892 { 893 mpViewFunc->ShowCursor(); 894 } 895 private: 896 ScViewFunc* mpViewFunc; 897 }; 898 899 bool lcl_checkDestRangeForOverwrite(const ScRange& rDestRange, const ScDocument* pDoc, const ScMarkData& rMark, Window* pParentWnd) 900 { 901 bool bIsEmpty = true; 902 SCTAB nTabCount = pDoc->GetTableCount(); 903 for (SCTAB nTab=0; nTab < nTabCount && bIsEmpty; ++nTab) 904 { 905 if (!rMark.GetTableSelect(nTab)) 906 continue; 907 908 bIsEmpty = pDoc->IsBlockEmpty(nTab, rDestRange.aStart.Col(), rDestRange.aStart.Row(), 909 rDestRange.aEnd.Col(), rDestRange.aEnd.Row()); 910 } 911 912 if (!bIsEmpty) 913 { 914 ScReplaceWarnBox aBox(pParentWnd); 915 if (aBox.Execute() != RET_YES) 916 { 917 // changing the configuration is within the ScReplaceWarnBox 918 return false; 919 } 920 } 921 return true; 922 } 923 924 } 925 926 sal_Bool ScViewFunc::PasteFromClip( sal_uInt16 nFlags, ScDocument* pClipDoc, 927 sal_uInt16 nFunction, sal_Bool bSkipEmpty, 928 sal_Bool bTranspose, sal_Bool bAsLink, 929 InsCellCmd eMoveMode, sal_uInt16 nUndoExtraFlags, 930 sal_Bool bAllowDialogs ) 931 { 932 if (!pClipDoc) 933 { 934 DBG_ERROR("PasteFromClip: pClipDoc=0 not allowed"); 935 return sal_False; 936 } 937 938 // fuer Undo etc. immer alle oder keine Inhalte sichern 939 sal_uInt16 nContFlags = IDF_NONE; 940 if (nFlags & IDF_CONTENTS) 941 nContFlags |= IDF_CONTENTS; 942 if (nFlags & IDF_ATTRIB) 943 nContFlags |= IDF_ATTRIB; 944 // evtl. Attribute ins Undo ohne sie vom Clip ins Doc zu kopieren 945 sal_uInt16 nUndoFlags = nContFlags; 946 if (nUndoExtraFlags & IDF_ATTRIB) 947 nUndoFlags |= IDF_ATTRIB; 948 // do not copy note captions into undo document 949 nUndoFlags |= IDF_NOCAPTIONS; 950 951 ScClipParam& rClipParam = pClipDoc->GetClipParam(); 952 if (rClipParam.isMultiRange()) 953 return PasteMultiRangesFromClip( 954 nFlags, pClipDoc, nFunction, bSkipEmpty, bTranspose, bAsLink, bAllowDialogs, 955 eMoveMode, nContFlags, nUndoFlags); 956 957 sal_Bool bCutMode = pClipDoc->IsCutMode(); // if transposing, take from original clipdoc 958 sal_Bool bIncludeFiltered = bCutMode; 959 960 // paste drawing: also if IDF_NOTE is set (to create drawing layer for note captions) 961 sal_Bool bPasteDraw = ( pClipDoc->GetDrawLayer() && ( nFlags & (IDF_OBJECTS|IDF_NOTE) ) ); 962 963 ScDocShellRef aTransShellRef; // for objects in xTransClip - must remain valid as long as xTransClip 964 ScDocument* pOrigClipDoc = NULL; 965 ::std::auto_ptr< ScDocument > xTransClip; 966 if ( bTranspose ) 967 { 968 SCCOL nX; 969 SCROW nY; 970 // include filtered rows until TransposeClip can skip them 971 bIncludeFiltered = sal_True; 972 pClipDoc->GetClipArea( nX, nY, sal_True ); 973 if ( nY > static_cast<sal_Int32>(MAXCOL) ) // zuviele Zeilen zum Transponieren 974 { 975 ErrorMessage(STR_PASTE_FULL); 976 return sal_False; 977 } 978 pOrigClipDoc = pClipDoc; // fuer Referenzen 979 980 if ( bPasteDraw ) 981 { 982 aTransShellRef = new ScDocShell; // DocShell needs a Ref immediately 983 aTransShellRef->DoInitNew(NULL); 984 } 985 ScDrawLayer::SetGlobalDrawPersist(aTransShellRef); 986 987 xTransClip.reset( new ScDocument( SCDOCMODE_CLIP )); 988 pClipDoc->TransposeClip( xTransClip.get(), nFlags, bAsLink ); 989 pClipDoc = xTransClip.get(); 990 991 ScDrawLayer::SetGlobalDrawPersist(NULL); 992 } 993 994 SCCOL nStartCol; 995 SCROW nStartRow; 996 SCTAB nStartTab; 997 SCCOL nEndCol; 998 SCROW nEndRow; 999 SCTAB nEndTab; 1000 SCCOL nClipSizeX; 1001 SCROW nClipSizeY; 1002 pClipDoc->GetClipArea( nClipSizeX, nClipSizeY, sal_True ); // size in clipboard doc 1003 1004 // size in target doc: include filtered rows only if CutMode is set 1005 SCCOL nDestSizeX; 1006 SCROW nDestSizeY; 1007 pClipDoc->GetClipArea( nDestSizeX, nDestSizeY, bIncludeFiltered ); 1008 1009 ScDocument* pDoc = GetViewData()->GetDocument(); 1010 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 1011 ScMarkData& rMark = GetViewData()->GetMarkData(); 1012 ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager(); 1013 const sal_Bool bRecord(pDoc->IsUndoEnabled()); 1014 1015 ScDocShellModificator aModificator( *pDocSh ); 1016 1017 ScRange aMarkRange; 1018 ScMarkData aFilteredMark( rMark); // local copy for all modifications 1019 ScMarkType eMarkType = GetViewData()->GetSimpleArea( aMarkRange, aFilteredMark); 1020 bool bMarkIsFiltered = (eMarkType == SC_MARK_SIMPLE_FILTERED); 1021 bool bNoPaste = ((eMarkType != SC_MARK_SIMPLE && !bMarkIsFiltered) || 1022 (bMarkIsFiltered && (eMoveMode != INS_NONE || bAsLink))); 1023 if (!bNoPaste && !rMark.IsMarked()) 1024 { 1025 // Create a selection with clipboard row count and check that for 1026 // filtered. 1027 nStartCol = GetViewData()->GetCurX(); 1028 nStartRow = GetViewData()->GetCurY(); 1029 nStartTab = GetViewData()->GetTabNo(); 1030 nEndCol = nStartCol + nDestSizeX; 1031 nEndRow = nStartRow + nDestSizeY; 1032 nEndTab = nStartTab; 1033 aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab); 1034 if (ScViewUtil::HasFiltered( aMarkRange, pDoc)) 1035 { 1036 bMarkIsFiltered = true; 1037 // Fit to clipboard's row count unfiltered rows. If there is no 1038 // fit assume that pasting is not possible. Note that nDestSizeY is 1039 // size-1 (difference). 1040 if (!ScViewUtil::FitToUnfilteredRows( aMarkRange, pDoc, nDestSizeY+1)) 1041 bNoPaste = true; 1042 } 1043 aFilteredMark.SetMarkArea( aMarkRange); 1044 } 1045 if (bNoPaste) 1046 { 1047 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0); 1048 return sal_False; 1049 } 1050 1051 SCROW nUnfilteredRows = aMarkRange.aEnd.Row() - aMarkRange.aStart.Row() + 1; 1052 ScRangeList aRangeList; 1053 if (bMarkIsFiltered) 1054 { 1055 ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc); 1056 aFilteredMark.FillRangeListWithMarks( &aRangeList, sal_False); 1057 nUnfilteredRows = 0; 1058 for (ScRange* p = aRangeList.First(); p; p = aRangeList.Next()) 1059 { 1060 nUnfilteredRows += p->aEnd.Row() - p->aStart.Row() + 1; 1061 } 1062 #if 0 1063 /* This isn't needed but could be a desired restriction. */ 1064 // For filtered, destination rows have to be an exact multiple of 1065 // source rows. Note that nDestSizeY is size-1 (difference), so 1066 // nDestSizeY==0 fits always. 1067 if ((nUnfilteredRows % (nDestSizeY+1)) != 0) 1068 { 1069 /* FIXME: this should be a more descriptive error message then. */ 1070 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0); 1071 return sal_False; 1072 } 1073 #endif 1074 } 1075 1076 SCCOL nMarkAddX = 0; 1077 SCROW nMarkAddY = 0; 1078 1079 // Also for a filtered selection the area is used, for undo et al. 1080 if ( aFilteredMark.IsMarked() || bMarkIsFiltered ) 1081 { 1082 aMarkRange.GetVars( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab); 1083 SCCOL nBlockAddX = nEndCol-nStartCol; 1084 SCROW nBlockAddY = nEndRow-nStartRow; 1085 1086 // #58422# Nachfrage, wenn die Selektion groesser als 1 Zeile/Spalte, aber kleiner 1087 // als das Clipboard ist (dann wird ueber die Selektion hinaus eingefuegt) 1088 1089 // ClipSize is not size, but difference 1090 if ( ( nBlockAddX != 0 && nBlockAddX < nDestSizeX ) || 1091 ( nBlockAddY != 0 && nBlockAddY < nDestSizeY ) || 1092 ( bMarkIsFiltered && nUnfilteredRows < nDestSizeY+1 ) ) 1093 { 1094 ScWaitCursorOff aWaitOff( GetFrameWin() ); 1095 String aMessage = ScGlobal::GetRscString( STR_PASTE_BIGGER ); 1096 QueryBox aBox( GetViewData()->GetDialogParent(), 1097 WinBits(WB_YES_NO | WB_DEF_NO), aMessage ); 1098 if ( aBox.Execute() != RET_YES ) 1099 { 1100 return sal_False; 1101 } 1102 } 1103 1104 if (nBlockAddX > nDestSizeX) 1105 nMarkAddX = nBlockAddX - nDestSizeX; // fuer Merge-Test 1106 else 1107 { 1108 nEndCol = nStartCol + nDestSizeX; 1109 if (nEndCol > aMarkRange.aEnd.Col()) 1110 { 1111 // #i113553# larger range has to be included in aFilteredMark (for undo), but extending columns can't changed the filtered status 1112 aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ); 1113 aFilteredMark.SetMarkArea( aMarkRange ); 1114 if (bMarkIsFiltered) 1115 { 1116 ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc ); 1117 aFilteredMark.FillRangeListWithMarks( &aRangeList, sal_True ); 1118 } 1119 } 1120 } 1121 1122 if (nBlockAddY > nDestSizeY) 1123 nMarkAddY = nBlockAddY - nDestSizeY; // fuer Merge-Test 1124 else 1125 { 1126 nEndRow = nStartRow + nDestSizeY; 1127 if (bMarkIsFiltered || nEndRow > aMarkRange.aEnd.Row()) 1128 { 1129 // Same as above if nothing was marked: re-fit selection to 1130 // unfiltered rows. Extending the selection actually may 1131 // introduce filtered rows where there weren't any before, so 1132 // we also need to test for that. 1133 aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab); 1134 if (bMarkIsFiltered || ScViewUtil::HasFiltered( aMarkRange, pDoc)) 1135 { 1136 bMarkIsFiltered = true; 1137 // Worst case: all rows up to the end of the sheet are filtered. 1138 if (!ScViewUtil::FitToUnfilteredRows( aMarkRange, pDoc, nDestSizeY+1)) 1139 { 1140 ErrorMessage(STR_PASTE_FULL); 1141 return sal_False; 1142 } 1143 } 1144 aMarkRange.GetVars( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab); 1145 aFilteredMark.SetMarkArea( aMarkRange); 1146 if (bMarkIsFiltered) 1147 { 1148 ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc); 1149 aFilteredMark.FillRangeListWithMarks( &aRangeList, sal_True); 1150 } 1151 } 1152 } 1153 } 1154 else 1155 { 1156 nStartCol = GetViewData()->GetCurX(); 1157 nStartRow = GetViewData()->GetCurY(); 1158 nStartTab = GetViewData()->GetTabNo(); 1159 nEndCol = nStartCol + nDestSizeX; 1160 nEndRow = nStartRow + nDestSizeY; 1161 nEndTab = nStartTab; 1162 } 1163 1164 bool bOffLimits = !ValidCol(nEndCol) || !ValidRow(nEndRow); 1165 1166 // Zielbereich, wie er angezeigt wird: 1167 ScRange aUserRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ); 1168 1169 // Sollen Zellen eingefuegt werden? 1170 // (zu grosse nEndCol/nEndRow werden weiter unten erkannt) 1171 sal_Bool bInsertCells = ( eMoveMode != INS_NONE && !bOffLimits ); 1172 if ( bInsertCells ) 1173 { 1174 // #94115# Instead of EnterListAction, the paste undo action is merged into the 1175 // insert action, so Repeat can insert the right cells 1176 1177 MarkRange( aUserRange ); // wird vor CopyFromClip sowieso gesetzt 1178 1179 // #72930# CutMode is reset on insertion of cols/rows but needed again on cell move 1180 sal_Bool bCut = pClipDoc->IsCutMode(); 1181 if (!InsertCells( eMoveMode, bRecord, sal_True )) // is inserting possible? 1182 { 1183 return sal_False; 1184 // #i21036# EnterListAction isn't used, and InsertCells doesn't insert 1185 // its undo action on failure, so no undo handling is needed here 1186 } 1187 if ( bCut ) 1188 pClipDoc->SetCutMode( bCut ); 1189 } 1190 else if (!bOffLimits) 1191 { 1192 sal_Bool bAskIfNotEmpty = bAllowDialogs && 1193 ( nFlags & IDF_CONTENTS ) && 1194 nFunction == PASTE_NOFUNC && 1195 SC_MOD()->GetInputOptions().GetReplaceCellsWarn(); 1196 if ( bAskIfNotEmpty ) 1197 { 1198 if (!lcl_checkDestRangeForOverwrite(aUserRange, pDoc, aFilteredMark, GetViewData()->GetDialogParent())) 1199 return false; 1200 } 1201 } 1202 1203 SCCOL nClipStartX; // Clipboard-Bereich erweitern 1204 SCROW nClipStartY; 1205 pClipDoc->GetClipStart( nClipStartX, nClipStartY ); 1206 SCCOL nUndoEndCol = nClipStartX + nClipSizeX; 1207 SCROW nUndoEndRow = nClipStartY + nClipSizeY; // end of source area in clipboard document 1208 sal_Bool bClipOver = sal_False; 1209 // #i68690# ExtendMerge for the clip doc must be called with the clipboard's sheet numbers. 1210 // The same end column/row can be used for all calls because the clip doc doesn't contain 1211 // content outside the clip area. 1212 for (SCTAB nClipTab=0; nClipTab<=MAXTAB; nClipTab++) 1213 if ( pClipDoc->HasTable(nClipTab) ) 1214 if ( pClipDoc->ExtendMerge( nClipStartX,nClipStartY, nUndoEndCol,nUndoEndRow, nClipTab, sal_False ) ) 1215 bClipOver = sal_True; 1216 nUndoEndCol -= nClipStartX + nClipSizeX; 1217 nUndoEndRow -= nClipStartY + nClipSizeY; // now contains only the difference added by ExtendMerge 1218 nUndoEndCol = sal::static_int_cast<SCCOL>( nUndoEndCol + nEndCol ); 1219 nUndoEndRow = sal::static_int_cast<SCROW>( nUndoEndRow + nEndRow ); // destination area, expanded for merged cells 1220 1221 // if (nUndoEndCol < nEndCol) nUndoEndCol = nEndCol; 1222 // if (nUndoEndRow < nEndRow) nUndoEndRow = nEndRow; 1223 1224 // nUndoEndCol += nMarkAddX; 1225 // nUndoEndRow += nMarkAddY; 1226 1227 if (nUndoEndCol>MAXCOL || nUndoEndRow>MAXROW) 1228 { 1229 ErrorMessage(STR_PASTE_FULL); 1230 return sal_False; 1231 } 1232 1233 pDoc->ExtendMergeSel( nStartCol,nStartRow, nUndoEndCol,nUndoEndRow, aFilteredMark, sal_False ); 1234 1235 // Test auf Zellschutz 1236 1237 ScEditableTester aTester( pDoc, nStartTab, nStartCol,nStartRow, nUndoEndCol,nUndoEndRow ); 1238 if (!aTester.IsEditable()) 1239 { 1240 ErrorMessage(aTester.GetMessageId()); 1241 return sal_False; 1242 } 1243 1244 //! Test auf Ueberlappung 1245 //! nur wirkliche Schnittmenge testen !!!!!!! 1246 1247 // pDoc->HasCommonAttr( StartCol,nStartRow, nUndoEndCol,nUndoEndRow, nStartTab, 1248 // pClipDoc, nClipStartX, nClipStartY ); 1249 1250 ScDocFunc& rDocFunc = pDocSh->GetDocFunc(); 1251 if ( bRecord ) 1252 { 1253 String aUndo = ScGlobal::GetRscString( pClipDoc->IsCutMode() ? STR_UNDO_MOVE : STR_UNDO_COPY ); 1254 pUndoMgr->EnterListAction( aUndo, aUndo ); 1255 } 1256 1257 if (bClipOver) 1258 if (lcl_SelHasAttrib( pDoc, nStartCol,nStartRow, nUndoEndCol,nUndoEndRow, aFilteredMark, HASATTR_OVERLAPPED )) 1259 { // "Cell merge not possible if cells already merged" 1260 ScDocAttrIterator aIter( pDoc, nStartTab, nStartCol, nStartRow, nUndoEndCol, nUndoEndRow ); 1261 const ScPatternAttr* pPattern = NULL; 1262 const ScMergeAttr* pMergeFlag = NULL; 1263 const ScMergeFlagAttr* pMergeFlagAttr = NULL; 1264 SCCOL nCol = -1; 1265 SCROW nRow1 = -1; 1266 SCROW nRow2 = -1; 1267 while ( ( pPattern = aIter.GetNext( nCol, nRow1, nRow2 ) ) != NULL ) 1268 { 1269 pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem(ATTR_MERGE); 1270 pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG); 1271 if( ( pMergeFlag && pMergeFlag->IsMerged() ) || ( pMergeFlagAttr && pMergeFlagAttr->IsOverlapped() ) ) 1272 { 1273 ScRange aRange(nCol, nRow1, nStartTab); 1274 pDoc->ExtendOverlapped(aRange); 1275 pDoc->ExtendMerge(aRange, sal_True, sal_True); 1276 rDocFunc.UnmergeCells(aRange, bRecord, sal_True); 1277 } 1278 } 1279 } 1280 1281 if ( !bCutMode ) 1282 { 1283 ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); 1284 if ( pChangeTrack ) 1285 pChangeTrack->ResetLastCut(); // kein CutMode mehr 1286 } 1287 1288 sal_Bool bColInfo = ( nStartRow==0 && nEndRow==MAXROW ); 1289 sal_Bool bRowInfo = ( nStartCol==0 && nEndCol==MAXCOL ); 1290 1291 ScDocument* pUndoDoc = NULL; 1292 ScDocument* pRefUndoDoc = NULL; 1293 ScDocument* pRedoDoc = NULL; 1294 ScRefUndoData* pUndoData = NULL; 1295 1296 if ( bRecord ) 1297 { 1298 pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 1299 pUndoDoc->InitUndoSelected( pDoc, aFilteredMark, bColInfo, bRowInfo ); 1300 1301 // all sheets - CopyToDocument skips those that don't exist in pUndoDoc 1302 SCTAB nTabCount = pDoc->GetTableCount(); 1303 pDoc->CopyToDocument( nStartCol, nStartRow, 0, nUndoEndCol, nUndoEndRow, nTabCount-1, 1304 nUndoFlags, sal_False, pUndoDoc ); 1305 1306 if ( bCutMode ) 1307 { 1308 pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 1309 pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, sal_False, sal_False ); 1310 1311 pUndoData = new ScRefUndoData( pDoc ); 1312 } 1313 } 1314 1315 sal_uInt16 nExtFlags = 0; 1316 pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab, 1317 nEndCol, nEndRow, nEndTab ); // content before the change 1318 1319 if (GetViewData()->IsActive()) 1320 { 1321 DoneBlockMode(); 1322 InitOwnBlockMode(); 1323 } 1324 rMark.SetMarkArea( aUserRange ); 1325 MarkDataChanged(); 1326 1327 HideCursor(); // Cursor aendert sich ! 1328 1329 // 1330 // Aus Clipboard kopieren, 1331 // wenn gerechnet werden soll, Originaldaten merken 1332 // 1333 1334 ScDocument* pMixDoc = NULL; 1335 if ( bSkipEmpty || nFunction ) 1336 { 1337 if ( nFlags & IDF_CONTENTS ) 1338 { 1339 pMixDoc = new ScDocument( SCDOCMODE_UNDO ); 1340 pMixDoc->InitUndo( pDoc, nStartTab, nEndTab ); 1341 pDoc->CopyToDocument( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab, 1342 IDF_CONTENTS, sal_False, pMixDoc ); 1343 } 1344 } 1345 1346 /* Make draw layer and start drawing undo. 1347 - Needed before AdjustBlockHeight to track moved drawing objects. 1348 - Needed before pDoc->CopyFromClip to track inserted note caption objects. 1349 */ 1350 if ( bPasteDraw ) 1351 pDocSh->MakeDrawLayer(); 1352 if ( bRecord ) 1353 pDoc->BeginDrawUndo(); 1354 1355 sal_uInt16 nNoObjFlags = nFlags & ~IDF_OBJECTS; 1356 if (!bAsLink) 1357 { 1358 // copy normally (original range) 1359 pDoc->CopyFromClip( aUserRange, aFilteredMark, nNoObjFlags, 1360 pRefUndoDoc, pClipDoc, sal_True, sal_False, bIncludeFiltered, 1361 bSkipEmpty, (bMarkIsFiltered ? &aRangeList : NULL) ); 1362 1363 // bei Transpose Referenzen per Hand anpassen 1364 if ( bTranspose && bCutMode && (nFlags & IDF_CONTENTS) ) 1365 pDoc->UpdateTranspose( aUserRange.aStart, pOrigClipDoc, aFilteredMark, pRefUndoDoc ); 1366 } 1367 else if (!bTranspose) 1368 { 1369 // copy with bAsLink=TRUE 1370 pDoc->CopyFromClip( aUserRange, aFilteredMark, nNoObjFlags, pRefUndoDoc, pClipDoc, 1371 sal_True, sal_True, bIncludeFiltered, bSkipEmpty ); 1372 } 1373 else 1374 { 1375 // alle Inhalte kopieren (im TransClipDoc stehen nur Formeln) 1376 pDoc->CopyFromClip( aUserRange, aFilteredMark, nContFlags, pRefUndoDoc, pClipDoc ); 1377 } 1378 1379 // skipped rows and merged cells don't mix 1380 if ( !bIncludeFiltered && pClipDoc->HasClipFilteredRows() ) 1381 rDocFunc.UnmergeCells( aUserRange, sal_False, sal_True ); 1382 1383 pDoc->ExtendMergeSel( nStartCol, nStartRow, nEndCol, nEndRow, aFilteredMark, sal_True ); // Refresh 1384 // und Bereich neu 1385 1386 if ( pMixDoc ) // Rechenfunktionen mit Original-Daten auszufuehren ? 1387 { 1388 pDoc->MixDocument( aUserRange, nFunction, bSkipEmpty, pMixDoc ); 1389 } 1390 delete pMixDoc; 1391 1392 AdjustBlockHeight(); // update row heights before pasting objects 1393 1394 ::std::vector< ::rtl::OUString > aExcludedChartNames; 1395 SdrPage* pPage = NULL; 1396 1397 if ( nFlags & IDF_OBJECTS ) 1398 { 1399 ScDrawView* pScDrawView = GetScDrawView(); 1400 SdrModel* pModel = ( pScDrawView ? pScDrawView->GetModel() : NULL ); 1401 pPage = ( pModel ? pModel->GetPage( static_cast< sal_uInt16 >( nStartTab ) ) : NULL ); 1402 if ( pPage ) 1403 { 1404 ScChartHelper::GetChartNames( aExcludedChartNames, pPage ); 1405 } 1406 1407 // Paste the drawing objects after the row heights have been updated. 1408 1409 pDoc->CopyFromClip( aUserRange, aFilteredMark, IDF_OBJECTS, pRefUndoDoc, pClipDoc, 1410 sal_True, sal_False, bIncludeFiltered ); 1411 } 1412 1413 // 1414 // 1415 // 1416 1417 pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab, 1418 nEndCol, nEndRow, nEndTab ); // content after the change 1419 1420 1421 // ggf. Autofilter-Koepfe loeschen 1422 if (bCutMode) 1423 if (pDoc->RefreshAutoFilter( nClipStartX,nClipStartY, nClipStartX+nClipSizeX, 1424 nClipStartY+nClipSizeY, nStartTab )) 1425 pDocSh->PostPaint( nClipStartX,nClipStartY,nStartTab, 1426 nClipStartX+nClipSizeX,nClipStartY,nStartTab, 1427 PAINT_GRID ); 1428 1429 ShowCursor(); // Cursor aendert sich ! 1430 1431 //! Block-Bereich bei RefUndoDoc weglassen !!! 1432 1433 if ( bRecord ) 1434 { 1435 // Redo-Daten werden erst beim ersten Undo kopiert 1436 // ohne RefUndoDoc muss das Redo-Doc noch nicht angelegt werden 1437 1438 if (pRefUndoDoc) 1439 { 1440 pRedoDoc = new ScDocument( SCDOCMODE_UNDO ); 1441 pRedoDoc->InitUndo( pDoc, nStartTab, nEndTab, bColInfo, bRowInfo ); 1442 1443 // angepasste Referenzen ins Redo-Doc 1444 1445 SCTAB nTabCount = pDoc->GetTableCount(); 1446 pRedoDoc->AddUndoTab( 0, nTabCount-1 ); 1447 pDoc->CopyUpdated( pRefUndoDoc, pRedoDoc ); 1448 1449 // alte Referenzen ins Undo-Doc 1450 1451 //! Tabellen selektieren ? 1452 pUndoDoc->AddUndoTab( 0, nTabCount-1 ); 1453 pRefUndoDoc->DeleteArea( nStartCol, nStartRow, nEndCol, nEndRow, aFilteredMark, IDF_ALL ); 1454 pRefUndoDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1, 1455 IDF_FORMULA, sal_False, pUndoDoc ); 1456 delete pRefUndoDoc; 1457 } 1458 1459 // DeleteUnchanged for pUndoData is in ScUndoPaste ctor, 1460 // UndoData for redo is made during first undo 1461 1462 ScUndoPasteOptions aOptions; // store options for repeat 1463 aOptions.nFunction = nFunction; 1464 aOptions.bSkipEmpty = bSkipEmpty; 1465 aOptions.bTranspose = bTranspose; 1466 aOptions.bAsLink = bAsLink; 1467 aOptions.eMoveMode = eMoveMode; 1468 1469 SfxUndoAction* pUndo = new ScUndoPaste( pDocSh, 1470 nStartCol, nStartRow, nStartTab, 1471 nUndoEndCol, nUndoEndRow, nEndTab, aFilteredMark, 1472 pUndoDoc, pRedoDoc, nFlags | nUndoFlags, 1473 pUndoData, NULL, NULL, NULL, 1474 sal_False, &aOptions ); // sal_False = Redo data not yet copied 1475 1476 if ( bInsertCells ) 1477 { 1478 // Merge the paste undo action into the insert action. 1479 // Use ScUndoWrapper so the ScUndoPaste pointer can be stored in the insert action. 1480 1481 pUndoMgr->AddUndoAction( new ScUndoWrapper( pUndo ), sal_True ); 1482 } 1483 else 1484 pUndoMgr->AddUndoAction( pUndo ); 1485 pUndoMgr->LeaveListAction(); 1486 } 1487 1488 sal_uInt16 nPaint = PAINT_GRID; 1489 if (bColInfo) 1490 { 1491 nPaint |= PAINT_TOP; 1492 nUndoEndCol = MAXCOL; // nur zum Zeichnen ! 1493 } 1494 if (bRowInfo) 1495 { 1496 nPaint |= PAINT_LEFT; 1497 nUndoEndRow = MAXROW; // nur zum Zeichnen ! 1498 } 1499 pDocSh->PostPaint( nStartCol, nStartRow, nStartTab, 1500 nUndoEndCol, nUndoEndRow, nEndTab, nPaint, nExtFlags ); 1501 // AdjustBlockHeight has already been called above 1502 1503 aModificator.SetDocumentModified(); 1504 PostPasteFromClip(aUserRange, rMark); 1505 1506 if ( nFlags & IDF_OBJECTS ) 1507 { 1508 ScModelObj* pModelObj = ( pDocSh ? ScModelObj::getImplementation( pDocSh->GetModel() ) : NULL ); 1509 if ( pDoc && pPage && pModelObj ) 1510 { 1511 bool bSameDoc = ( rClipParam.getSourceDocID() == pDoc->GetDocumentID() ); 1512 const ScRangeListVector& rProtectedChartRangesVector( rClipParam.maProtectedChartRangesVector ); 1513 ScChartHelper::CreateProtectedChartListenersAndNotify( pDoc, pPage, pModelObj, nStartTab, 1514 rProtectedChartRangesVector, aExcludedChartNames, bSameDoc ); 1515 } 1516 } 1517 1518 return sal_True; 1519 } 1520 1521 bool ScViewFunc::PasteMultiRangesFromClip( 1522 sal_uInt16 nFlags, ScDocument* pClipDoc, sal_uInt16 nFunction, 1523 bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs, 1524 InsCellCmd eMoveMode, sal_uInt16 /*nContFlags*/, sal_uInt16 nUndoFlags) 1525 { 1526 ScViewData& rViewData = *GetViewData(); 1527 ScDocument* pDoc = rViewData.GetDocument(); 1528 ScDocShell* pDocSh = rViewData.GetDocShell(); 1529 ScMarkData aMark(rViewData.GetMarkData()); 1530 const ScAddress& rCurPos = rViewData.GetCurPos(); 1531 ScClipParam& rClipParam = pClipDoc->GetClipParam(); 1532 SCCOL nColSize = rClipParam.getPasteColSize(); 1533 SCROW nRowSize = rClipParam.getPasteRowSize(); 1534 1535 if (bTranspose) 1536 { 1537 if (static_cast<SCROW>(rCurPos.Col()) + nRowSize-1 > static_cast<SCROW>(MAXCOL)) 1538 { 1539 ErrorMessage(STR_PASTE_FULL); 1540 return false; 1541 } 1542 1543 ::std::auto_ptr<ScDocument> pTransClip(new ScDocument(SCDOCMODE_CLIP)); 1544 pClipDoc->TransposeClip(pTransClip.get(), nFlags, bAsLink); 1545 pClipDoc = pTransClip.release(); 1546 SCCOL nTempColSize = nColSize; 1547 nColSize = static_cast<SCCOL>(nRowSize); 1548 nRowSize = static_cast<SCROW>(nTempColSize); 1549 } 1550 1551 if (!ValidCol(rCurPos.Col()+nColSize-1) || !ValidRow(rCurPos.Row()+nRowSize-1)) 1552 { 1553 ErrorMessage(STR_PASTE_FULL); 1554 return false; 1555 } 1556 1557 // Determine the first and last selected sheet numbers. 1558 SCTAB nTab1 = aMark.GetFirstSelected(); 1559 SCTAB nTab2 = nTab1; 1560 for (SCTAB i = nTab1+1; i <= MAXTAB; ++i) 1561 if (aMark.GetTableSelect(i)) 1562 nTab2 = i; 1563 1564 ScDocShellModificator aModificator(*pDocSh); 1565 1566 // For multi-selection paste, we don't support cell duplication for larger 1567 // destination range. In case the destination is marked, we reset it to 1568 // the clip size. 1569 ScRange aMarkedRange(rCurPos.Col(), rCurPos.Row(), nTab1, 1570 rCurPos.Col()+nColSize-1, rCurPos.Row()+nRowSize-1, nTab2); 1571 1572 // Extend the marked range to account for filtered rows in the destination 1573 // area. 1574 if (ScViewUtil::HasFiltered(aMarkedRange, pDoc)) 1575 { 1576 if (!ScViewUtil::FitToUnfilteredRows(aMarkedRange, pDoc, nRowSize)) 1577 return false; 1578 } 1579 1580 bool bAskIfNotEmpty = 1581 bAllowDialogs && (nFlags & IDF_CONTENTS) && 1582 nFunction == PASTE_NOFUNC && SC_MOD()->GetInputOptions().GetReplaceCellsWarn(); 1583 1584 if (bAskIfNotEmpty) 1585 { 1586 if (!lcl_checkDestRangeForOverwrite(aMarkedRange, pDoc, aMark, rViewData.GetDialogParent())) 1587 return false; 1588 } 1589 1590 aMark.SetMarkArea(aMarkedRange); 1591 MarkRange(aMarkedRange); 1592 1593 bool bInsertCells = (eMoveMode != INS_NONE); 1594 if (bInsertCells) 1595 { 1596 if (!InsertCells(eMoveMode, pDoc->IsUndoEnabled(), true)) 1597 return false; 1598 } 1599 1600 ::std::auto_ptr<ScDocument> pUndoDoc; 1601 if (pDoc->IsUndoEnabled()) 1602 { 1603 pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO)); 1604 pUndoDoc->InitUndoSelected(pDoc, aMark, false, false); 1605 pDoc->CopyToDocument(aMarkedRange, nUndoFlags, false, pUndoDoc.get(), &aMark, true); 1606 } 1607 1608 ::std::auto_ptr<ScDocument> pMixDoc; 1609 if ( bSkipEmpty || nFunction ) 1610 { 1611 if ( nFlags & IDF_CONTENTS ) 1612 { 1613 pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO)); 1614 pMixDoc->InitUndoSelected(pDoc, aMark, false, false); 1615 pDoc->CopyToDocument(aMarkedRange, IDF_CONTENTS, false, pMixDoc.get(), &aMark, true); 1616 } 1617 } 1618 1619 /* Make draw layer and start drawing undo. 1620 - Needed before AdjustBlockHeight to track moved drawing objects. 1621 - Needed before pDoc->CopyFromClip to track inserted note caption objects. 1622 */ 1623 if (nFlags & IDF_OBJECTS) 1624 pDocSh->MakeDrawLayer(); 1625 if (pDoc->IsUndoEnabled()) 1626 pDoc->BeginDrawUndo(); 1627 1628 CursorSwitcher aCursorSwitch(this); 1629 sal_uInt16 nNoObjFlags = nFlags & ~IDF_OBJECTS; 1630 pDoc->CopyMultiRangeFromClip(rCurPos, aMark, nNoObjFlags, pClipDoc, 1631 true, bAsLink, false, bSkipEmpty); 1632 1633 if (pMixDoc.get()) 1634 pDoc->MixDocument(aMarkedRange, nFunction, bSkipEmpty, pMixDoc.get()); 1635 1636 AdjustBlockHeight(); // update row heights before pasting objects 1637 1638 if (nFlags & IDF_OBJECTS) 1639 { 1640 // Paste the drawing objects after the row heights have been updated. 1641 pDoc->CopyMultiRangeFromClip(rCurPos, aMark, IDF_OBJECTS, pClipDoc, 1642 true, false, false, true); 1643 } 1644 1645 pDocSh->PostPaint( 1646 aMarkedRange.aStart.Col(), aMarkedRange.aStart.Row(), nTab1, 1647 aMarkedRange.aEnd.Col(), aMarkedRange.aEnd.Row(), nTab1, PAINT_GRID); 1648 1649 if (pDoc->IsUndoEnabled()) 1650 { 1651 ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager(); 1652 String aUndo = ScGlobal::GetRscString( 1653 pClipDoc->IsCutMode() ? STR_UNDO_CUT : STR_UNDO_COPY); 1654 pUndoMgr->EnterListAction(aUndo, aUndo); 1655 1656 ScUndoPasteOptions aOptions; // store options for repeat 1657 aOptions.nFunction = nFunction; 1658 aOptions.bSkipEmpty = bSkipEmpty; 1659 aOptions.bTranspose = bTranspose; 1660 aOptions.bAsLink = bAsLink; 1661 aOptions.eMoveMode = eMoveMode; 1662 1663 ScUndoPaste* pUndo = new ScUndoPaste(pDocSh, 1664 aMarkedRange.aStart.Col(), 1665 aMarkedRange.aStart.Row(), 1666 aMarkedRange.aStart.Tab(), 1667 aMarkedRange.aEnd.Col(), 1668 aMarkedRange.aEnd.Row(), 1669 aMarkedRange.aEnd.Tab(), 1670 aMark, pUndoDoc.release(), NULL, nFlags|nUndoFlags, NULL, NULL, NULL, NULL, false, &aOptions); 1671 1672 if (bInsertCells) 1673 pUndoMgr->AddUndoAction(new ScUndoWrapper(pUndo), true); 1674 else 1675 pUndoMgr->AddUndoAction(pUndo, false); 1676 1677 pUndoMgr->LeaveListAction(); 1678 } 1679 aModificator.SetDocumentModified(); 1680 PostPasteFromClip(aMarkedRange, aMark); 1681 return true; 1682 } 1683 1684 void ScViewFunc::PostPasteFromClip(const ScRange& rPasteRange, const ScMarkData& rMark) 1685 { 1686 ScViewData* pViewData = GetViewData(); 1687 ScDocShell* pDocSh = pViewData->GetDocShell(); 1688 ScDocument* pDoc = pViewData->GetDocument(); 1689 pDocSh->UpdateOle(pViewData); 1690 1691 SelectionChanged(); 1692 1693 // #i97876# Spreadsheet data changes are not notified 1694 ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() ); 1695 if ( pModelObj && pModelObj->HasChangesListeners() ) 1696 { 1697 ScRangeList aChangeRanges; 1698 SCTAB nTabCount = pDoc->GetTableCount(); 1699 for ( SCTAB i = 0; i < nTabCount; ++i ) 1700 { 1701 if ( rMark.GetTableSelect( i ) ) 1702 { 1703 ScRange aChangeRange(rPasteRange); 1704 aChangeRange.aStart.SetTab( i ); 1705 aChangeRange.aEnd.SetTab( i ); 1706 aChangeRanges.Append( aChangeRange ); 1707 } 1708 } 1709 pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges ); 1710 } 1711 } 1712 1713 1714 //---------------------------------------------------------------------------- 1715 // D R A G A N D D R O P 1716 // 1717 // innerhalb des Dokuments 1718 1719 sal_Bool ScViewFunc::MoveBlockTo( const ScRange& rSource, const ScAddress& rDestPos, 1720 sal_Bool bCut, sal_Bool bRecord, sal_Bool bPaint, sal_Bool bApi ) 1721 { 1722 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 1723 HideAllCursors(); // wegen zusammengefassten 1724 1725 sal_Bool bSuccess = sal_True; 1726 SCTAB nDestTab = rDestPos.Tab(); 1727 const ScMarkData& rMark = GetViewData()->GetMarkData(); 1728 if ( rSource.aStart.Tab() == nDestTab && rSource.aEnd.Tab() == nDestTab && rMark.GetSelectCount() > 1 ) 1729 { 1730 // moving within one table and several tables selected -> apply to all selected tables 1731 1732 if ( bRecord ) 1733 { 1734 String aUndo = ScGlobal::GetRscString( bCut ? STR_UNDO_MOVE : STR_UNDO_COPY ); 1735 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo ); 1736 } 1737 1738 // collect ranges of consecutive selected tables 1739 1740 ScRange aLocalSource = rSource; 1741 ScAddress aLocalDest = rDestPos; 1742 SCTAB nTabCount = pDocSh->GetDocument()->GetTableCount(); 1743 SCTAB nStartTab = 0; 1744 while ( nStartTab < nTabCount && bSuccess ) 1745 { 1746 while ( nStartTab < nTabCount && !rMark.GetTableSelect(nStartTab) ) 1747 ++nStartTab; 1748 if ( nStartTab < nTabCount ) 1749 { 1750 SCTAB nEndTab = nStartTab; 1751 while ( nEndTab+1 < nTabCount && rMark.GetTableSelect(nEndTab+1) ) 1752 ++nEndTab; 1753 1754 aLocalSource.aStart.SetTab( nStartTab ); 1755 aLocalSource.aEnd.SetTab( nEndTab ); 1756 aLocalDest.SetTab( nStartTab ); 1757 1758 bSuccess = pDocSh->GetDocFunc().MoveBlock( 1759 aLocalSource, aLocalDest, bCut, bRecord, bPaint, bApi ); 1760 1761 nStartTab = nEndTab + 1; 1762 } 1763 } 1764 1765 if ( bRecord ) 1766 pDocSh->GetUndoManager()->LeaveListAction(); 1767 } 1768 else 1769 { 1770 // move the block as specified 1771 bSuccess = pDocSh->GetDocFunc().MoveBlock( 1772 rSource, rDestPos, bCut, bRecord, bPaint, bApi ); 1773 } 1774 1775 ShowAllCursors(); 1776 if (bSuccess) 1777 { 1778 // Zielbereich markieren 1779 ScAddress aDestEnd( 1780 rDestPos.Col() + rSource.aEnd.Col() - rSource.aStart.Col(), 1781 rDestPos.Row() + rSource.aEnd.Row() - rSource.aStart.Row(), 1782 nDestTab ); 1783 1784 sal_Bool bIncludeFiltered = bCut; 1785 if ( !bIncludeFiltered ) 1786 { 1787 // find number of non-filtered rows 1788 SCROW nPastedCount = pDocSh->GetDocument()->CountNonFilteredRows( 1789 rSource.aStart.Row(), rSource.aEnd.Row(), rSource.aStart.Tab()); 1790 1791 if ( nPastedCount == 0 ) 1792 nPastedCount = 1; 1793 aDestEnd.SetRow( rDestPos.Row() + nPastedCount - 1 ); 1794 } 1795 1796 MarkRange( ScRange( rDestPos, aDestEnd ), sal_False ); //! sal_False ??? 1797 1798 pDocSh->UpdateOle(GetViewData()); 1799 SelectionChanged(); 1800 } 1801 return bSuccess; 1802 } 1803 1804 // Link innerhalb des Dokuments 1805 1806 sal_Bool ScViewFunc::LinkBlock( const ScRange& rSource, const ScAddress& rDestPos, sal_Bool bApi ) 1807 { 1808 // Test auf Ueberlappung 1809 1810 if ( rSource.aStart.Tab() == rDestPos.Tab() ) 1811 { 1812 SCCOL nDestEndCol = rDestPos.Col() + ( rSource.aEnd.Col() - rSource.aStart.Col() ); 1813 SCROW nDestEndRow = rDestPos.Row() + ( rSource.aEnd.Row() - rSource.aStart.Row() ); 1814 1815 if ( rSource.aStart.Col() <= nDestEndCol && rDestPos.Col() <= rSource.aEnd.Col() && 1816 rSource.aStart.Row() <= nDestEndRow && rDestPos.Row() <= rSource.aEnd.Row() ) 1817 { 1818 if (!bApi) 1819 ErrorMessage( STR_ERR_LINKOVERLAP ); 1820 return sal_False; 1821 } 1822 } 1823 1824 // Ausfuehren per Paste 1825 1826 ScDocument* pDoc = GetViewData()->GetDocument(); 1827 ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP ); 1828 pDoc->CopyTabToClip( rSource.aStart.Col(), rSource.aStart.Row(), 1829 rSource.aEnd.Col(), rSource.aEnd.Row(), 1830 rSource.aStart.Tab(), pClipDoc ); 1831 1832 // Zielbereich markieren (Cursor setzen, keine Markierung) 1833 1834 if ( GetViewData()->GetTabNo() != rDestPos.Tab() ) 1835 SetTabNo( rDestPos.Tab() ); 1836 1837 MoveCursorAbs( rDestPos.Col(), rDestPos.Row(), SC_FOLLOW_NONE, sal_False, sal_False ); 1838 1839 // Paste 1840 1841 PasteFromClip( IDF_ALL, pClipDoc, PASTE_NOFUNC, sal_False, sal_False, sal_True ); // als Link 1842 1843 delete pClipDoc; 1844 1845 return sal_True; 1846 } 1847 1848 1849 1850 1851