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