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::PasteOnDrawObject( const uno::Reference<datatransfer::XTransferable>& rxTransferable, 824 SdrObject* pHitObj, sal_Bool bLink ) 825 { 826 sal_Bool bRet = sal_False; 827 if ( bLink ) 828 { 829 TransferableDataHelper aDataHelper( rxTransferable ); 830 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) ) 831 { 832 SotStorageStreamRef xStm; 833 if( aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_SVXB, xStm ) ) 834 { 835 Graphic aGraphic; 836 *xStm >> aGraphic; 837 bRet = ApplyGraphicToObject( pHitObj, aGraphic ); 838 } 839 } 840 else if ( aDataHelper.HasFormat( SOT_FORMAT_GDIMETAFILE ) ) 841 { 842 GDIMetaFile aMtf; 843 if( aDataHelper.GetGDIMetaFile( FORMAT_GDIMETAFILE, aMtf ) ) 844 bRet = ApplyGraphicToObject( pHitObj, Graphic(aMtf) ); 845 } 846 else if ( aDataHelper.HasFormat( SOT_FORMAT_BITMAP ) ) 847 { 848 BitmapEx aBmpEx; 849 if( aDataHelper.GetBitmapEx( FORMAT_BITMAP, aBmpEx ) ) 850 bRet = ApplyGraphicToObject( pHitObj, Graphic(aBmpEx) ); 851 } 852 } 853 else 854 { 855 // ham' wa noch nich 856 } 857 return bRet; 858 } 859 860 sal_Bool lcl_SelHasAttrib( ScDocument* pDoc, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, 861 const ScMarkData& rTabSelection, sal_uInt16 nMask ) 862 { 863 SCTAB nTabCount = pDoc->GetTableCount(); 864 for (SCTAB nTab=0; nTab<nTabCount; nTab++) 865 if ( rTabSelection.GetTableSelect(nTab) && pDoc->HasAttrib( nCol1, nRow1, nTab, nCol2, nRow2, nTab, nMask ) ) 866 return sal_True; 867 return sal_False; 868 } 869 870 // 871 // Einfuegen auf Tabelle: 872 // 873 874 // internes Paste 875 876 namespace { 877 878 class CursorSwitcher 879 { 880 public: 881 CursorSwitcher(ScViewFunc* pViewFunc) : 882 mpViewFunc(pViewFunc) 883 { 884 mpViewFunc->HideCursor(); 885 } 886 887 ~CursorSwitcher() 888 { 889 mpViewFunc->ShowCursor(); 890 } 891 private: 892 ScViewFunc* mpViewFunc; 893 }; 894 895 bool lcl_checkDestRangeForOverwrite(const ScRange& rDestRange, const ScDocument* pDoc, const ScMarkData& rMark, Window* pParentWnd) 896 { 897 bool bIsEmpty = true; 898 SCTAB nTabCount = pDoc->GetTableCount(); 899 for (SCTAB nTab=0; nTab < nTabCount && bIsEmpty; ++nTab) 900 { 901 if (!rMark.GetTableSelect(nTab)) 902 continue; 903 904 bIsEmpty = pDoc->IsBlockEmpty(nTab, rDestRange.aStart.Col(), rDestRange.aStart.Row(), 905 rDestRange.aEnd.Col(), rDestRange.aEnd.Row()); 906 } 907 908 if (!bIsEmpty) 909 { 910 ScReplaceWarnBox aBox(pParentWnd); 911 if (aBox.Execute() != RET_YES) 912 { 913 // changing the configuration is within the ScReplaceWarnBox 914 return false; 915 } 916 } 917 return true; 918 } 919 920 } 921 922 sal_Bool ScViewFunc::PasteFromClip( sal_uInt16 nFlags, ScDocument* pClipDoc, 923 sal_uInt16 nFunction, sal_Bool bSkipEmpty, 924 sal_Bool bTranspose, sal_Bool bAsLink, 925 InsCellCmd eMoveMode, sal_uInt16 nUndoExtraFlags, 926 sal_Bool bAllowDialogs ) 927 { 928 if (!pClipDoc) 929 { 930 DBG_ERROR("PasteFromClip: pClipDoc=0 not allowed"); 931 return sal_False; 932 } 933 934 // fuer Undo etc. immer alle oder keine Inhalte sichern 935 sal_uInt16 nContFlags = IDF_NONE; 936 if (nFlags & IDF_CONTENTS) 937 nContFlags |= IDF_CONTENTS; 938 if (nFlags & IDF_ATTRIB) 939 nContFlags |= IDF_ATTRIB; 940 // evtl. Attribute ins Undo ohne sie vom Clip ins Doc zu kopieren 941 sal_uInt16 nUndoFlags = nContFlags; 942 if (nUndoExtraFlags & IDF_ATTRIB) 943 nUndoFlags |= IDF_ATTRIB; 944 // do not copy note captions into undo document 945 nUndoFlags |= IDF_NOCAPTIONS; 946 947 ScClipParam& rClipParam = pClipDoc->GetClipParam(); 948 if (rClipParam.isMultiRange()) 949 return PasteMultiRangesFromClip( 950 nFlags, pClipDoc, nFunction, bSkipEmpty, bTranspose, bAsLink, bAllowDialogs, 951 eMoveMode, nContFlags, nUndoFlags); 952 953 sal_Bool bCutMode = pClipDoc->IsCutMode(); // if transposing, take from original clipdoc 954 sal_Bool bIncludeFiltered = bCutMode; 955 956 // paste drawing: also if IDF_NOTE is set (to create drawing layer for note captions) 957 sal_Bool bPasteDraw = ( pClipDoc->GetDrawLayer() && ( nFlags & (IDF_OBJECTS|IDF_NOTE) ) ); 958 959 ScDocShellRef aTransShellRef; // for objects in xTransClip - must remain valid as long as xTransClip 960 ScDocument* pOrigClipDoc = NULL; 961 ::std::auto_ptr< ScDocument > xTransClip; 962 if ( bTranspose ) 963 { 964 SCCOL nX; 965 SCROW nY; 966 // include filtered rows until TransposeClip can skip them 967 bIncludeFiltered = sal_True; 968 pClipDoc->GetClipArea( nX, nY, sal_True ); 969 if ( nY > static_cast<sal_Int32>(MAXCOL) ) // zuviele Zeilen zum Transponieren 970 { 971 ErrorMessage(STR_PASTE_FULL); 972 return sal_False; 973 } 974 pOrigClipDoc = pClipDoc; // fuer Referenzen 975 976 if ( bPasteDraw ) 977 { 978 aTransShellRef = new ScDocShell; // DocShell needs a Ref immediately 979 aTransShellRef->DoInitNew(NULL); 980 } 981 ScDrawLayer::SetGlobalDrawPersist(aTransShellRef); 982 983 xTransClip.reset( new ScDocument( SCDOCMODE_CLIP )); 984 pClipDoc->TransposeClip( xTransClip.get(), nFlags, bAsLink ); 985 pClipDoc = xTransClip.get(); 986 987 ScDrawLayer::SetGlobalDrawPersist(NULL); 988 } 989 990 SCCOL nStartCol; 991 SCROW nStartRow; 992 SCTAB nStartTab; 993 SCCOL nEndCol; 994 SCROW nEndRow; 995 SCTAB nEndTab; 996 SCCOL nClipSizeX; 997 SCROW nClipSizeY; 998 pClipDoc->GetClipArea( nClipSizeX, nClipSizeY, sal_True ); // size in clipboard doc 999 1000 // size in target doc: include filtered rows only if CutMode is set 1001 SCCOL nDestSizeX; 1002 SCROW nDestSizeY; 1003 pClipDoc->GetClipArea( nDestSizeX, nDestSizeY, bIncludeFiltered ); 1004 1005 ScDocument* pDoc = GetViewData()->GetDocument(); 1006 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 1007 ScMarkData& rMark = GetViewData()->GetMarkData(); 1008 ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager(); 1009 const sal_Bool bRecord(pDoc->IsUndoEnabled()); 1010 1011 ScDocShellModificator aModificator( *pDocSh ); 1012 1013 ScRange aMarkRange; 1014 ScMarkData aFilteredMark( rMark); // local copy for all modifications 1015 ScMarkType eMarkType = GetViewData()->GetSimpleArea( aMarkRange, aFilteredMark); 1016 bool bMarkIsFiltered = (eMarkType == SC_MARK_SIMPLE_FILTERED); 1017 bool bNoPaste = ((eMarkType != SC_MARK_SIMPLE && !bMarkIsFiltered) || 1018 (bMarkIsFiltered && (eMoveMode != INS_NONE || bAsLink))); 1019 if (!bNoPaste && !rMark.IsMarked()) 1020 { 1021 // Create a selection with clipboard row count and check that for 1022 // filtered. 1023 nStartCol = GetViewData()->GetCurX(); 1024 nStartRow = GetViewData()->GetCurY(); 1025 nStartTab = GetViewData()->GetTabNo(); 1026 nEndCol = nStartCol + nDestSizeX; 1027 nEndRow = nStartRow + nDestSizeY; 1028 nEndTab = nStartTab; 1029 aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab); 1030 if (ScViewUtil::HasFiltered( aMarkRange, pDoc)) 1031 { 1032 bMarkIsFiltered = true; 1033 // Fit to clipboard's row count unfiltered rows. If there is no 1034 // fit assume that pasting is not possible. Note that nDestSizeY is 1035 // size-1 (difference). 1036 if (!ScViewUtil::FitToUnfilteredRows( aMarkRange, pDoc, nDestSizeY+1)) 1037 bNoPaste = true; 1038 } 1039 aFilteredMark.SetMarkArea( aMarkRange); 1040 } 1041 if (bNoPaste) 1042 { 1043 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0); 1044 return sal_False; 1045 } 1046 1047 SCROW nUnfilteredRows = aMarkRange.aEnd.Row() - aMarkRange.aStart.Row() + 1; 1048 ScRangeList aRangeList; 1049 if (bMarkIsFiltered) 1050 { 1051 ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc); 1052 aFilteredMark.FillRangeListWithMarks( &aRangeList, sal_False); 1053 nUnfilteredRows = 0; 1054 for (ScRange* p = aRangeList.First(); p; p = aRangeList.Next()) 1055 { 1056 nUnfilteredRows += p->aEnd.Row() - p->aStart.Row() + 1; 1057 } 1058 #if 0 1059 /* This isn't needed but could be a desired restriction. */ 1060 // For filtered, destination rows have to be an exact multiple of 1061 // source rows. Note that nDestSizeY is size-1 (difference), so 1062 // nDestSizeY==0 fits always. 1063 if ((nUnfilteredRows % (nDestSizeY+1)) != 0) 1064 { 1065 /* FIXME: this should be a more descriptive error message then. */ 1066 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0); 1067 return sal_False; 1068 } 1069 #endif 1070 } 1071 1072 SCCOL nMarkAddX = 0; 1073 SCROW nMarkAddY = 0; 1074 1075 // Also for a filtered selection the area is used, for undo et al. 1076 if ( aFilteredMark.IsMarked() || bMarkIsFiltered ) 1077 { 1078 aMarkRange.GetVars( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab); 1079 SCCOL nBlockAddX = nEndCol-nStartCol; 1080 SCROW nBlockAddY = nEndRow-nStartRow; 1081 1082 // #58422# Nachfrage, wenn die Selektion groesser als 1 Zeile/Spalte, aber kleiner 1083 // als das Clipboard ist (dann wird ueber die Selektion hinaus eingefuegt) 1084 1085 // ClipSize is not size, but difference 1086 if ( ( nBlockAddX != 0 && nBlockAddX < nDestSizeX ) || 1087 ( nBlockAddY != 0 && nBlockAddY < nDestSizeY ) || 1088 ( bMarkIsFiltered && nUnfilteredRows < nDestSizeY+1 ) ) 1089 { 1090 ScWaitCursorOff aWaitOff( GetFrameWin() ); 1091 String aMessage = ScGlobal::GetRscString( STR_PASTE_BIGGER ); 1092 QueryBox aBox( GetViewData()->GetDialogParent(), 1093 WinBits(WB_YES_NO | WB_DEF_NO), aMessage ); 1094 if ( aBox.Execute() != RET_YES ) 1095 { 1096 return sal_False; 1097 } 1098 } 1099 1100 if (nBlockAddX > nDestSizeX) 1101 nMarkAddX = nBlockAddX - nDestSizeX; // fuer Merge-Test 1102 else 1103 { 1104 nEndCol = nStartCol + nDestSizeX; 1105 if (nEndCol > aMarkRange.aEnd.Col()) 1106 { 1107 // #i113553# larger range has to be included in aFilteredMark (for undo), but extending columns can't changed the filtered status 1108 aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ); 1109 aFilteredMark.SetMarkArea( aMarkRange ); 1110 if (bMarkIsFiltered) 1111 { 1112 ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc ); 1113 aFilteredMark.FillRangeListWithMarks( &aRangeList, sal_True ); 1114 } 1115 } 1116 } 1117 1118 if (nBlockAddY > nDestSizeY) 1119 nMarkAddY = nBlockAddY - nDestSizeY; // fuer Merge-Test 1120 else 1121 { 1122 nEndRow = nStartRow + nDestSizeY; 1123 if (bMarkIsFiltered || nEndRow > aMarkRange.aEnd.Row()) 1124 { 1125 // Same as above if nothing was marked: re-fit selection to 1126 // unfiltered rows. Extending the selection actually may 1127 // introduce filtered rows where there weren't any before, so 1128 // we also need to test for that. 1129 aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab); 1130 if (bMarkIsFiltered || ScViewUtil::HasFiltered( aMarkRange, pDoc)) 1131 { 1132 bMarkIsFiltered = true; 1133 // Worst case: all rows up to the end of the sheet are filtered. 1134 if (!ScViewUtil::FitToUnfilteredRows( aMarkRange, pDoc, nDestSizeY+1)) 1135 { 1136 ErrorMessage(STR_PASTE_FULL); 1137 return sal_False; 1138 } 1139 } 1140 aMarkRange.GetVars( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab); 1141 aFilteredMark.SetMarkArea( aMarkRange); 1142 if (bMarkIsFiltered) 1143 { 1144 ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc); 1145 aFilteredMark.FillRangeListWithMarks( &aRangeList, sal_True); 1146 } 1147 } 1148 } 1149 } 1150 else 1151 { 1152 nStartCol = GetViewData()->GetCurX(); 1153 nStartRow = GetViewData()->GetCurY(); 1154 nStartTab = GetViewData()->GetTabNo(); 1155 nEndCol = nStartCol + nDestSizeX; 1156 nEndRow = nStartRow + nDestSizeY; 1157 nEndTab = nStartTab; 1158 } 1159 1160 bool bOffLimits = !ValidCol(nEndCol) || !ValidRow(nEndRow); 1161 1162 // Zielbereich, wie er angezeigt wird: 1163 ScRange aUserRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ); 1164 1165 // Sollen Zellen eingefuegt werden? 1166 // (zu grosse nEndCol/nEndRow werden weiter unten erkannt) 1167 sal_Bool bInsertCells = ( eMoveMode != INS_NONE && !bOffLimits ); 1168 if ( bInsertCells ) 1169 { 1170 // #94115# Instead of EnterListAction, the paste undo action is merged into the 1171 // insert action, so Repeat can insert the right cells 1172 1173 MarkRange( aUserRange ); // wird vor CopyFromClip sowieso gesetzt 1174 1175 // #72930# CutMode is reset on insertion of cols/rows but needed again on cell move 1176 sal_Bool bCut = pClipDoc->IsCutMode(); 1177 if (!InsertCells( eMoveMode, bRecord, sal_True )) // is inserting possible? 1178 { 1179 return sal_False; 1180 // #i21036# EnterListAction isn't used, and InsertCells doesn't insert 1181 // its undo action on failure, so no undo handling is needed here 1182 } 1183 if ( bCut ) 1184 pClipDoc->SetCutMode( bCut ); 1185 } 1186 else if (!bOffLimits) 1187 { 1188 sal_Bool bAskIfNotEmpty = bAllowDialogs && 1189 ( nFlags & IDF_CONTENTS ) && 1190 nFunction == PASTE_NOFUNC && 1191 SC_MOD()->GetInputOptions().GetReplaceCellsWarn(); 1192 if ( bAskIfNotEmpty ) 1193 { 1194 if (!lcl_checkDestRangeForOverwrite(aUserRange, pDoc, aFilteredMark, GetViewData()->GetDialogParent())) 1195 return false; 1196 } 1197 } 1198 1199 SCCOL nClipStartX; // Clipboard-Bereich erweitern 1200 SCROW nClipStartY; 1201 pClipDoc->GetClipStart( nClipStartX, nClipStartY ); 1202 SCCOL nUndoEndCol = nClipStartX + nClipSizeX; 1203 SCROW nUndoEndRow = nClipStartY + nClipSizeY; // end of source area in clipboard document 1204 sal_Bool bClipOver = sal_False; 1205 // #i68690# ExtendMerge for the clip doc must be called with the clipboard's sheet numbers. 1206 // The same end column/row can be used for all calls because the clip doc doesn't contain 1207 // content outside the clip area. 1208 for (SCTAB nClipTab=0; nClipTab<=MAXTAB; nClipTab++) 1209 if ( pClipDoc->HasTable(nClipTab) ) 1210 if ( pClipDoc->ExtendMerge( nClipStartX,nClipStartY, nUndoEndCol,nUndoEndRow, nClipTab, sal_False ) ) 1211 bClipOver = sal_True; 1212 nUndoEndCol -= nClipStartX + nClipSizeX; 1213 nUndoEndRow -= nClipStartY + nClipSizeY; // now contains only the difference added by ExtendMerge 1214 nUndoEndCol = sal::static_int_cast<SCCOL>( nUndoEndCol + nEndCol ); 1215 nUndoEndRow = sal::static_int_cast<SCROW>( nUndoEndRow + nEndRow ); // destination area, expanded for merged cells 1216 1217 // if (nUndoEndCol < nEndCol) nUndoEndCol = nEndCol; 1218 // if (nUndoEndRow < nEndRow) nUndoEndRow = nEndRow; 1219 1220 // nUndoEndCol += nMarkAddX; 1221 // nUndoEndRow += nMarkAddY; 1222 1223 if (nUndoEndCol>MAXCOL || nUndoEndRow>MAXROW) 1224 { 1225 ErrorMessage(STR_PASTE_FULL); 1226 return sal_False; 1227 } 1228 1229 pDoc->ExtendMergeSel( nStartCol,nStartRow, nUndoEndCol,nUndoEndRow, aFilteredMark, sal_False ); 1230 1231 // Test auf Zellschutz 1232 1233 ScEditableTester aTester( pDoc, nStartTab, nStartCol,nStartRow, nUndoEndCol,nUndoEndRow ); 1234 if (!aTester.IsEditable()) 1235 { 1236 ErrorMessage(aTester.GetMessageId()); 1237 return sal_False; 1238 } 1239 1240 //! Test auf Ueberlappung 1241 //! nur wirkliche Schnittmenge testen !!!!!!! 1242 1243 // pDoc->HasCommonAttr( StartCol,nStartRow, nUndoEndCol,nUndoEndRow, nStartTab, 1244 // pClipDoc, nClipStartX, nClipStartY ); 1245 1246 ScDocFunc& rDocFunc = pDocSh->GetDocFunc(); 1247 if ( bRecord ) 1248 { 1249 String aUndo = ScGlobal::GetRscString( pClipDoc->IsCutMode() ? STR_UNDO_MOVE : STR_UNDO_COPY ); 1250 pUndoMgr->EnterListAction( aUndo, aUndo ); 1251 } 1252 1253 if (bClipOver) 1254 if (lcl_SelHasAttrib( pDoc, nStartCol,nStartRow, nUndoEndCol,nUndoEndRow, aFilteredMark, HASATTR_OVERLAPPED )) 1255 { // "Cell merge not possible if cells already merged" 1256 ScDocAttrIterator aIter( pDoc, nStartTab, nStartCol, nStartRow, nUndoEndCol, nUndoEndRow ); 1257 const ScPatternAttr* pPattern = NULL; 1258 const ScMergeAttr* pMergeFlag = NULL; 1259 const ScMergeFlagAttr* pMergeFlagAttr = NULL; 1260 SCCOL nCol = -1; 1261 SCROW nRow1 = -1; 1262 SCROW nRow2 = -1; 1263 while ( ( pPattern = aIter.GetNext( nCol, nRow1, nRow2 ) ) != NULL ) 1264 { 1265 pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem(ATTR_MERGE); 1266 pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG); 1267 if( ( pMergeFlag && pMergeFlag->IsMerged() ) || ( pMergeFlagAttr && pMergeFlagAttr->IsOverlapped() ) ) 1268 { 1269 ScRange aRange(nCol, nRow1, nStartTab); 1270 pDoc->ExtendOverlapped(aRange); 1271 pDoc->ExtendMerge(aRange, sal_True, sal_True); 1272 rDocFunc.UnmergeCells(aRange, bRecord, sal_True); 1273 } 1274 } 1275 } 1276 1277 if ( !bCutMode ) 1278 { 1279 ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); 1280 if ( pChangeTrack ) 1281 pChangeTrack->ResetLastCut(); // kein CutMode mehr 1282 } 1283 1284 sal_Bool bColInfo = ( nStartRow==0 && nEndRow==MAXROW ); 1285 sal_Bool bRowInfo = ( nStartCol==0 && nEndCol==MAXCOL ); 1286 1287 ScDocument* pUndoDoc = NULL; 1288 ScDocument* pRefUndoDoc = NULL; 1289 ScDocument* pRedoDoc = NULL; 1290 ScRefUndoData* pUndoData = NULL; 1291 1292 if ( bRecord ) 1293 { 1294 pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 1295 pUndoDoc->InitUndoSelected( pDoc, aFilteredMark, bColInfo, bRowInfo ); 1296 1297 // all sheets - CopyToDocument skips those that don't exist in pUndoDoc 1298 SCTAB nTabCount = pDoc->GetTableCount(); 1299 pDoc->CopyToDocument( nStartCol, nStartRow, 0, nUndoEndCol, nUndoEndRow, nTabCount-1, 1300 nUndoFlags, sal_False, pUndoDoc ); 1301 1302 if ( bCutMode ) 1303 { 1304 pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 1305 pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, sal_False, sal_False ); 1306 1307 pUndoData = new ScRefUndoData( pDoc ); 1308 } 1309 } 1310 1311 sal_uInt16 nExtFlags = 0; 1312 pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab, 1313 nEndCol, nEndRow, nEndTab ); // content before the change 1314 1315 if (GetViewData()->IsActive()) 1316 { 1317 DoneBlockMode(); 1318 InitOwnBlockMode(); 1319 } 1320 rMark.SetMarkArea( aUserRange ); 1321 MarkDataChanged(); 1322 1323 HideCursor(); // Cursor aendert sich ! 1324 1325 // 1326 // Aus Clipboard kopieren, 1327 // wenn gerechnet werden soll, Originaldaten merken 1328 // 1329 1330 ScDocument* pMixDoc = NULL; 1331 if ( bSkipEmpty || nFunction ) 1332 { 1333 if ( nFlags & IDF_CONTENTS ) 1334 { 1335 pMixDoc = new ScDocument( SCDOCMODE_UNDO ); 1336 pMixDoc->InitUndo( pDoc, nStartTab, nEndTab ); 1337 pDoc->CopyToDocument( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab, 1338 IDF_CONTENTS, sal_False, pMixDoc ); 1339 } 1340 } 1341 1342 /* Make draw layer and start drawing undo. 1343 - Needed before AdjustBlockHeight to track moved drawing objects. 1344 - Needed before pDoc->CopyFromClip to track inserted note caption objects. 1345 */ 1346 if ( bPasteDraw ) 1347 pDocSh->MakeDrawLayer(); 1348 if ( bRecord ) 1349 pDoc->BeginDrawUndo(); 1350 1351 sal_uInt16 nNoObjFlags = nFlags & ~IDF_OBJECTS; 1352 if (!bAsLink) 1353 { 1354 // copy normally (original range) 1355 pDoc->CopyFromClip( aUserRange, aFilteredMark, nNoObjFlags, 1356 pRefUndoDoc, pClipDoc, sal_True, sal_False, bIncludeFiltered, 1357 bSkipEmpty, (bMarkIsFiltered ? &aRangeList : NULL) ); 1358 1359 // bei Transpose Referenzen per Hand anpassen 1360 if ( bTranspose && bCutMode && (nFlags & IDF_CONTENTS) ) 1361 pDoc->UpdateTranspose( aUserRange.aStart, pOrigClipDoc, aFilteredMark, pRefUndoDoc ); 1362 } 1363 else if (!bTranspose) 1364 { 1365 // copy with bAsLink=TRUE 1366 pDoc->CopyFromClip( aUserRange, aFilteredMark, nNoObjFlags, pRefUndoDoc, pClipDoc, 1367 sal_True, sal_True, bIncludeFiltered, bSkipEmpty ); 1368 } 1369 else 1370 { 1371 // alle Inhalte kopieren (im TransClipDoc stehen nur Formeln) 1372 pDoc->CopyFromClip( aUserRange, aFilteredMark, nContFlags, pRefUndoDoc, pClipDoc ); 1373 } 1374 1375 // skipped rows and merged cells don't mix 1376 if ( !bIncludeFiltered && pClipDoc->HasClipFilteredRows() ) 1377 rDocFunc.UnmergeCells( aUserRange, sal_False, sal_True ); 1378 1379 pDoc->ExtendMergeSel( nStartCol, nStartRow, nEndCol, nEndRow, aFilteredMark, sal_True ); // Refresh 1380 // und Bereich neu 1381 1382 if ( pMixDoc ) // Rechenfunktionen mit Original-Daten auszufuehren ? 1383 { 1384 pDoc->MixDocument( aUserRange, nFunction, bSkipEmpty, pMixDoc ); 1385 } 1386 delete pMixDoc; 1387 1388 AdjustBlockHeight(); // update row heights before pasting objects 1389 1390 ::std::vector< ::rtl::OUString > aExcludedChartNames; 1391 SdrPage* pPage = NULL; 1392 1393 if ( nFlags & IDF_OBJECTS ) 1394 { 1395 ScDrawView* pScDrawView = GetScDrawView(); 1396 SdrModel* pModel = ( pScDrawView ? pScDrawView->GetModel() : NULL ); 1397 pPage = ( pModel ? pModel->GetPage( static_cast< sal_uInt16 >( nStartTab ) ) : NULL ); 1398 if ( pPage ) 1399 { 1400 ScChartHelper::GetChartNames( aExcludedChartNames, pPage ); 1401 } 1402 1403 // Paste the drawing objects after the row heights have been updated. 1404 1405 pDoc->CopyFromClip( aUserRange, aFilteredMark, IDF_OBJECTS, pRefUndoDoc, pClipDoc, 1406 sal_True, sal_False, bIncludeFiltered ); 1407 } 1408 1409 // 1410 // 1411 // 1412 1413 pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab, 1414 nEndCol, nEndRow, nEndTab ); // content after the change 1415 1416 1417 // ggf. Autofilter-Koepfe loeschen 1418 if (bCutMode) 1419 if (pDoc->RefreshAutoFilter( nClipStartX,nClipStartY, nClipStartX+nClipSizeX, 1420 nClipStartY+nClipSizeY, nStartTab )) 1421 pDocSh->PostPaint( nClipStartX,nClipStartY,nStartTab, 1422 nClipStartX+nClipSizeX,nClipStartY,nStartTab, 1423 PAINT_GRID ); 1424 1425 ShowCursor(); // Cursor aendert sich ! 1426 1427 //! Block-Bereich bei RefUndoDoc weglassen !!! 1428 1429 if ( bRecord ) 1430 { 1431 // Redo-Daten werden erst beim ersten Undo kopiert 1432 // ohne RefUndoDoc muss das Redo-Doc noch nicht angelegt werden 1433 1434 if (pRefUndoDoc) 1435 { 1436 pRedoDoc = new ScDocument( SCDOCMODE_UNDO ); 1437 pRedoDoc->InitUndo( pDoc, nStartTab, nEndTab, bColInfo, bRowInfo ); 1438 1439 // angepasste Referenzen ins Redo-Doc 1440 1441 SCTAB nTabCount = pDoc->GetTableCount(); 1442 pRedoDoc->AddUndoTab( 0, nTabCount-1 ); 1443 pDoc->CopyUpdated( pRefUndoDoc, pRedoDoc ); 1444 1445 // alte Referenzen ins Undo-Doc 1446 1447 //! Tabellen selektieren ? 1448 pUndoDoc->AddUndoTab( 0, nTabCount-1 ); 1449 pRefUndoDoc->DeleteArea( nStartCol, nStartRow, nEndCol, nEndRow, aFilteredMark, IDF_ALL ); 1450 pRefUndoDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1, 1451 IDF_FORMULA, sal_False, pUndoDoc ); 1452 delete pRefUndoDoc; 1453 } 1454 1455 // DeleteUnchanged for pUndoData is in ScUndoPaste ctor, 1456 // UndoData for redo is made during first undo 1457 1458 ScUndoPasteOptions aOptions; // store options for repeat 1459 aOptions.nFunction = nFunction; 1460 aOptions.bSkipEmpty = bSkipEmpty; 1461 aOptions.bTranspose = bTranspose; 1462 aOptions.bAsLink = bAsLink; 1463 aOptions.eMoveMode = eMoveMode; 1464 1465 SfxUndoAction* pUndo = new ScUndoPaste( pDocSh, 1466 nStartCol, nStartRow, nStartTab, 1467 nUndoEndCol, nUndoEndRow, nEndTab, aFilteredMark, 1468 pUndoDoc, pRedoDoc, nFlags | nUndoFlags, 1469 pUndoData, NULL, NULL, NULL, 1470 sal_False, &aOptions ); // sal_False = Redo data not yet copied 1471 1472 if ( bInsertCells ) 1473 { 1474 // Merge the paste undo action into the insert action. 1475 // Use ScUndoWrapper so the ScUndoPaste pointer can be stored in the insert action. 1476 1477 pUndoMgr->AddUndoAction( new ScUndoWrapper( pUndo ), sal_True ); 1478 } 1479 else 1480 pUndoMgr->AddUndoAction( pUndo ); 1481 pUndoMgr->LeaveListAction(); 1482 } 1483 1484 sal_uInt16 nPaint = PAINT_GRID; 1485 if (bColInfo) 1486 { 1487 nPaint |= PAINT_TOP; 1488 nUndoEndCol = MAXCOL; // nur zum Zeichnen ! 1489 } 1490 if (bRowInfo) 1491 { 1492 nPaint |= PAINT_LEFT; 1493 nUndoEndRow = MAXROW; // nur zum Zeichnen ! 1494 } 1495 pDocSh->PostPaint( nStartCol, nStartRow, nStartTab, 1496 nUndoEndCol, nUndoEndRow, nEndTab, nPaint, nExtFlags ); 1497 // AdjustBlockHeight has already been called above 1498 1499 aModificator.SetDocumentModified(); 1500 PostPasteFromClip(aUserRange, rMark); 1501 1502 if ( nFlags & IDF_OBJECTS ) 1503 { 1504 ScModelObj* pModelObj = ( pDocSh ? ScModelObj::getImplementation( pDocSh->GetModel() ) : NULL ); 1505 if ( pDoc && pPage && pModelObj ) 1506 { 1507 bool bSameDoc = ( rClipParam.getSourceDocID() == pDoc->GetDocumentID() ); 1508 const ScRangeListVector& rProtectedChartRangesVector( rClipParam.maProtectedChartRangesVector ); 1509 ScChartHelper::CreateProtectedChartListenersAndNotify( pDoc, pPage, pModelObj, nStartTab, 1510 rProtectedChartRangesVector, aExcludedChartNames, bSameDoc ); 1511 } 1512 } 1513 1514 return sal_True; 1515 } 1516 1517 bool ScViewFunc::PasteMultiRangesFromClip( 1518 sal_uInt16 nFlags, ScDocument* pClipDoc, sal_uInt16 nFunction, 1519 bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs, 1520 InsCellCmd eMoveMode, sal_uInt16 /*nContFlags*/, sal_uInt16 nUndoFlags) 1521 { 1522 ScViewData& rViewData = *GetViewData(); 1523 ScDocument* pDoc = rViewData.GetDocument(); 1524 ScDocShell* pDocSh = rViewData.GetDocShell(); 1525 ScMarkData aMark(rViewData.GetMarkData()); 1526 const ScAddress& rCurPos = rViewData.GetCurPos(); 1527 ScClipParam& rClipParam = pClipDoc->GetClipParam(); 1528 SCCOL nColSize = rClipParam.getPasteColSize(); 1529 SCROW nRowSize = rClipParam.getPasteRowSize(); 1530 1531 if (bTranspose) 1532 { 1533 if (static_cast<SCROW>(rCurPos.Col()) + nRowSize-1 > static_cast<SCROW>(MAXCOL)) 1534 { 1535 ErrorMessage(STR_PASTE_FULL); 1536 return false; 1537 } 1538 1539 ::std::auto_ptr<ScDocument> pTransClip(new ScDocument(SCDOCMODE_CLIP)); 1540 pClipDoc->TransposeClip(pTransClip.get(), nFlags, bAsLink); 1541 pClipDoc = pTransClip.release(); 1542 SCCOL nTempColSize = nColSize; 1543 nColSize = static_cast<SCCOL>(nRowSize); 1544 nRowSize = static_cast<SCROW>(nTempColSize); 1545 } 1546 1547 if (!ValidCol(rCurPos.Col()+nColSize-1) || !ValidRow(rCurPos.Row()+nRowSize-1)) 1548 { 1549 ErrorMessage(STR_PASTE_FULL); 1550 return false; 1551 } 1552 1553 // Determine the first and last selected sheet numbers. 1554 SCTAB nTab1 = aMark.GetFirstSelected(); 1555 SCTAB nTab2 = nTab1; 1556 for (SCTAB i = nTab1+1; i <= MAXTAB; ++i) 1557 if (aMark.GetTableSelect(i)) 1558 nTab2 = i; 1559 1560 ScDocShellModificator aModificator(*pDocSh); 1561 1562 // For multi-selection paste, we don't support cell duplication for larger 1563 // destination range. In case the destination is marked, we reset it to 1564 // the clip size. 1565 ScRange aMarkedRange(rCurPos.Col(), rCurPos.Row(), nTab1, 1566 rCurPos.Col()+nColSize-1, rCurPos.Row()+nRowSize-1, nTab2); 1567 1568 // Extend the marked range to account for filtered rows in the destination 1569 // area. 1570 if (ScViewUtil::HasFiltered(aMarkedRange, pDoc)) 1571 { 1572 if (!ScViewUtil::FitToUnfilteredRows(aMarkedRange, pDoc, nRowSize)) 1573 return false; 1574 } 1575 1576 bool bAskIfNotEmpty = 1577 bAllowDialogs && (nFlags & IDF_CONTENTS) && 1578 nFunction == PASTE_NOFUNC && SC_MOD()->GetInputOptions().GetReplaceCellsWarn(); 1579 1580 if (bAskIfNotEmpty) 1581 { 1582 if (!lcl_checkDestRangeForOverwrite(aMarkedRange, pDoc, aMark, rViewData.GetDialogParent())) 1583 return false; 1584 } 1585 1586 aMark.SetMarkArea(aMarkedRange); 1587 MarkRange(aMarkedRange); 1588 1589 bool bInsertCells = (eMoveMode != INS_NONE); 1590 if (bInsertCells) 1591 { 1592 if (!InsertCells(eMoveMode, pDoc->IsUndoEnabled(), true)) 1593 return false; 1594 } 1595 1596 ::std::auto_ptr<ScDocument> pUndoDoc; 1597 if (pDoc->IsUndoEnabled()) 1598 { 1599 pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO)); 1600 pUndoDoc->InitUndoSelected(pDoc, aMark, false, false); 1601 pDoc->CopyToDocument(aMarkedRange, nUndoFlags, false, pUndoDoc.get(), &aMark, true); 1602 } 1603 1604 ::std::auto_ptr<ScDocument> pMixDoc; 1605 if ( bSkipEmpty || nFunction ) 1606 { 1607 if ( nFlags & IDF_CONTENTS ) 1608 { 1609 pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO)); 1610 pMixDoc->InitUndoSelected(pDoc, aMark, false, false); 1611 pDoc->CopyToDocument(aMarkedRange, IDF_CONTENTS, false, pMixDoc.get(), &aMark, true); 1612 } 1613 } 1614 1615 /* Make draw layer and start drawing undo. 1616 - Needed before AdjustBlockHeight to track moved drawing objects. 1617 - Needed before pDoc->CopyFromClip to track inserted note caption objects. 1618 */ 1619 if (nFlags & IDF_OBJECTS) 1620 pDocSh->MakeDrawLayer(); 1621 if (pDoc->IsUndoEnabled()) 1622 pDoc->BeginDrawUndo(); 1623 1624 CursorSwitcher aCursorSwitch(this); 1625 sal_uInt16 nNoObjFlags = nFlags & ~IDF_OBJECTS; 1626 pDoc->CopyMultiRangeFromClip(rCurPos, aMark, nNoObjFlags, pClipDoc, 1627 true, bAsLink, false, bSkipEmpty); 1628 1629 if (pMixDoc.get()) 1630 pDoc->MixDocument(aMarkedRange, nFunction, bSkipEmpty, pMixDoc.get()); 1631 1632 AdjustBlockHeight(); // update row heights before pasting objects 1633 1634 if (nFlags & IDF_OBJECTS) 1635 { 1636 // Paste the drawing objects after the row heights have been updated. 1637 pDoc->CopyMultiRangeFromClip(rCurPos, aMark, IDF_OBJECTS, pClipDoc, 1638 true, false, false, true); 1639 } 1640 1641 pDocSh->PostPaint( 1642 aMarkedRange.aStart.Col(), aMarkedRange.aStart.Row(), nTab1, 1643 aMarkedRange.aEnd.Col(), aMarkedRange.aEnd.Row(), nTab1, PAINT_GRID); 1644 1645 if (pDoc->IsUndoEnabled()) 1646 { 1647 ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager(); 1648 String aUndo = ScGlobal::GetRscString( 1649 pClipDoc->IsCutMode() ? STR_UNDO_CUT : STR_UNDO_COPY); 1650 pUndoMgr->EnterListAction(aUndo, aUndo); 1651 1652 ScUndoPasteOptions aOptions; // store options for repeat 1653 aOptions.nFunction = nFunction; 1654 aOptions.bSkipEmpty = bSkipEmpty; 1655 aOptions.bTranspose = bTranspose; 1656 aOptions.bAsLink = bAsLink; 1657 aOptions.eMoveMode = eMoveMode; 1658 1659 ScUndoPaste* pUndo = new ScUndoPaste(pDocSh, 1660 aMarkedRange.aStart.Col(), 1661 aMarkedRange.aStart.Row(), 1662 aMarkedRange.aStart.Tab(), 1663 aMarkedRange.aEnd.Col(), 1664 aMarkedRange.aEnd.Row(), 1665 aMarkedRange.aEnd.Tab(), 1666 aMark, pUndoDoc.release(), NULL, nFlags|nUndoFlags, NULL, NULL, NULL, NULL, false, &aOptions); 1667 1668 if (bInsertCells) 1669 pUndoMgr->AddUndoAction(new ScUndoWrapper(pUndo), true); 1670 else 1671 pUndoMgr->AddUndoAction(pUndo, false); 1672 1673 pUndoMgr->LeaveListAction(); 1674 } 1675 aModificator.SetDocumentModified(); 1676 PostPasteFromClip(aMarkedRange, aMark); 1677 return true; 1678 } 1679 1680 void ScViewFunc::PostPasteFromClip(const ScRange& rPasteRange, const ScMarkData& rMark) 1681 { 1682 ScViewData* pViewData = GetViewData(); 1683 ScDocShell* pDocSh = pViewData->GetDocShell(); 1684 ScDocument* pDoc = pViewData->GetDocument(); 1685 pDocSh->UpdateOle(pViewData); 1686 1687 SelectionChanged(); 1688 1689 // #i97876# Spreadsheet data changes are not notified 1690 ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() ); 1691 if ( pModelObj && pModelObj->HasChangesListeners() ) 1692 { 1693 ScRangeList aChangeRanges; 1694 SCTAB nTabCount = pDoc->GetTableCount(); 1695 for ( SCTAB i = 0; i < nTabCount; ++i ) 1696 { 1697 if ( rMark.GetTableSelect( i ) ) 1698 { 1699 ScRange aChangeRange(rPasteRange); 1700 aChangeRange.aStart.SetTab( i ); 1701 aChangeRange.aEnd.SetTab( i ); 1702 aChangeRanges.Append( aChangeRange ); 1703 } 1704 } 1705 pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges ); 1706 } 1707 } 1708 1709 1710 //---------------------------------------------------------------------------- 1711 // D R A G A N D D R O P 1712 // 1713 // innerhalb des Dokuments 1714 1715 sal_Bool ScViewFunc::MoveBlockTo( const ScRange& rSource, const ScAddress& rDestPos, 1716 sal_Bool bCut, sal_Bool bRecord, sal_Bool bPaint, sal_Bool bApi ) 1717 { 1718 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 1719 HideAllCursors(); // wegen zusammengefassten 1720 1721 sal_Bool bSuccess = sal_True; 1722 SCTAB nDestTab = rDestPos.Tab(); 1723 const ScMarkData& rMark = GetViewData()->GetMarkData(); 1724 if ( rSource.aStart.Tab() == nDestTab && rSource.aEnd.Tab() == nDestTab && rMark.GetSelectCount() > 1 ) 1725 { 1726 // moving within one table and several tables selected -> apply to all selected tables 1727 1728 if ( bRecord ) 1729 { 1730 String aUndo = ScGlobal::GetRscString( bCut ? STR_UNDO_MOVE : STR_UNDO_COPY ); 1731 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo ); 1732 } 1733 1734 // collect ranges of consecutive selected tables 1735 1736 ScRange aLocalSource = rSource; 1737 ScAddress aLocalDest = rDestPos; 1738 SCTAB nTabCount = pDocSh->GetDocument()->GetTableCount(); 1739 SCTAB nStartTab = 0; 1740 while ( nStartTab < nTabCount && bSuccess ) 1741 { 1742 while ( nStartTab < nTabCount && !rMark.GetTableSelect(nStartTab) ) 1743 ++nStartTab; 1744 if ( nStartTab < nTabCount ) 1745 { 1746 SCTAB nEndTab = nStartTab; 1747 while ( nEndTab+1 < nTabCount && rMark.GetTableSelect(nEndTab+1) ) 1748 ++nEndTab; 1749 1750 aLocalSource.aStart.SetTab( nStartTab ); 1751 aLocalSource.aEnd.SetTab( nEndTab ); 1752 aLocalDest.SetTab( nStartTab ); 1753 1754 bSuccess = pDocSh->GetDocFunc().MoveBlock( 1755 aLocalSource, aLocalDest, bCut, bRecord, bPaint, bApi ); 1756 1757 nStartTab = nEndTab + 1; 1758 } 1759 } 1760 1761 if ( bRecord ) 1762 pDocSh->GetUndoManager()->LeaveListAction(); 1763 } 1764 else 1765 { 1766 // move the block as specified 1767 bSuccess = pDocSh->GetDocFunc().MoveBlock( 1768 rSource, rDestPos, bCut, bRecord, bPaint, bApi ); 1769 } 1770 1771 ShowAllCursors(); 1772 if (bSuccess) 1773 { 1774 // Zielbereich markieren 1775 ScAddress aDestEnd( 1776 rDestPos.Col() + rSource.aEnd.Col() - rSource.aStart.Col(), 1777 rDestPos.Row() + rSource.aEnd.Row() - rSource.aStart.Row(), 1778 nDestTab ); 1779 1780 sal_Bool bIncludeFiltered = bCut; 1781 if ( !bIncludeFiltered ) 1782 { 1783 // find number of non-filtered rows 1784 SCROW nPastedCount = pDocSh->GetDocument()->CountNonFilteredRows( 1785 rSource.aStart.Row(), rSource.aEnd.Row(), rSource.aStart.Tab()); 1786 1787 if ( nPastedCount == 0 ) 1788 nPastedCount = 1; 1789 aDestEnd.SetRow( rDestPos.Row() + nPastedCount - 1 ); 1790 } 1791 1792 MarkRange( ScRange( rDestPos, aDestEnd ), sal_False ); //! sal_False ??? 1793 1794 pDocSh->UpdateOle(GetViewData()); 1795 SelectionChanged(); 1796 } 1797 return bSuccess; 1798 } 1799 1800 // Link innerhalb des Dokuments 1801 1802 sal_Bool ScViewFunc::LinkBlock( const ScRange& rSource, const ScAddress& rDestPos, sal_Bool bApi ) 1803 { 1804 // Test auf Ueberlappung 1805 1806 if ( rSource.aStart.Tab() == rDestPos.Tab() ) 1807 { 1808 SCCOL nDestEndCol = rDestPos.Col() + ( rSource.aEnd.Col() - rSource.aStart.Col() ); 1809 SCROW nDestEndRow = rDestPos.Row() + ( rSource.aEnd.Row() - rSource.aStart.Row() ); 1810 1811 if ( rSource.aStart.Col() <= nDestEndCol && rDestPos.Col() <= rSource.aEnd.Col() && 1812 rSource.aStart.Row() <= nDestEndRow && rDestPos.Row() <= rSource.aEnd.Row() ) 1813 { 1814 if (!bApi) 1815 ErrorMessage( STR_ERR_LINKOVERLAP ); 1816 return sal_False; 1817 } 1818 } 1819 1820 // Ausfuehren per Paste 1821 1822 ScDocument* pDoc = GetViewData()->GetDocument(); 1823 ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP ); 1824 pDoc->CopyTabToClip( rSource.aStart.Col(), rSource.aStart.Row(), 1825 rSource.aEnd.Col(), rSource.aEnd.Row(), 1826 rSource.aStart.Tab(), pClipDoc ); 1827 1828 // Zielbereich markieren (Cursor setzen, keine Markierung) 1829 1830 if ( GetViewData()->GetTabNo() != rDestPos.Tab() ) 1831 SetTabNo( rDestPos.Tab() ); 1832 1833 MoveCursorAbs( rDestPos.Col(), rDestPos.Row(), SC_FOLLOW_NONE, sal_False, sal_False ); 1834 1835 // Paste 1836 1837 PasteFromClip( IDF_ALL, pClipDoc, PASTE_NOFUNC, sal_False, sal_False, sal_True ); // als Link 1838 1839 delete pClipDoc; 1840 1841 return sal_True; 1842 } 1843 1844 1845 1846 1847