1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sc.hxx" 30 31 32 33 // INCLUDE --------------------------------------------------------------- 34 35 #include "scitems.hxx" 36 #include <editeng/eeitem.hxx> 37 38 #include <sfx2/app.hxx> 39 #include <editeng/editobj.hxx> 40 #include <sfx2/linkmgr.hxx> 41 #include <svx/svdundo.hxx> 42 #include <sfx2/bindings.hxx> 43 #include <sfx2/printer.hxx> 44 #include <vcl/msgbox.hxx> 45 #include <vcl/sound.hxx> 46 #include <vcl/virdev.hxx> 47 #include <vcl/waitobj.hxx> 48 #include <svl/zforlist.hxx> 49 #include <svl/PasswordHelper.hxx> 50 51 #include <basic/sbstar.hxx> 52 #include <com/sun/star/container/XNameContainer.hpp> 53 #include <com/sun/star/script/ModuleType.hpp> 54 #include <com/sun/star/script/XLibraryContainer.hpp> 55 #include <com/sun/star/script/vba/XVBAModuleInfo.hpp> 56 57 #include <list> 58 59 #include "docfunc.hxx" 60 61 #include "sc.hrc" 62 63 #include "arealink.hxx" 64 #include "attrib.hxx" 65 #include "dociter.hxx" 66 #include "autoform.hxx" 67 #include "cell.hxx" 68 #include "detdata.hxx" 69 #include "detfunc.hxx" 70 #include "docpool.hxx" 71 #include "docsh.hxx" 72 #include "drwlayer.hxx" 73 #include "editutil.hxx" 74 #include "globstr.hrc" 75 //CHINA001 #include "namecrea.hxx" // NAME_TOP etc. 76 #include "olinetab.hxx" 77 #include "patattr.hxx" 78 #include "rangenam.hxx" 79 #include "rangeutl.hxx" 80 #include "refundo.hxx" 81 #include "scresid.hxx" 82 #include "stlpool.hxx" 83 #include "stlsheet.hxx" 84 #include "tablink.hxx" 85 #include "tabvwsh.hxx" 86 #include "uiitems.hxx" 87 #include "undoblk.hxx" 88 #include "undocell.hxx" 89 #include "undodraw.hxx" 90 #include "undotab.hxx" 91 #include "waitoff.hxx" 92 #include "sizedev.hxx" 93 #include "scmod.hxx" 94 #include "inputhdl.hxx" 95 #include "inputwin.hxx" 96 #include "editable.hxx" 97 #include "compiler.hxx" 98 #include "scui_def.hxx" //CHINA001 99 #include "tabprotection.hxx" 100 #include "clipparam.hxx" 101 #include "externalrefmgr.hxx" 102 103 #include <memory> 104 #include <basic/basmgr.hxx> 105 #include <boost/scoped_ptr.hpp> 106 107 using namespace com::sun::star; 108 using ::com::sun::star::uno::Sequence; 109 110 // STATIC DATA ----------------------------------------------------------- 111 112 //======================================================================== 113 114 IMPL_LINK( ScDocFunc, NotifyDrawUndo, SdrUndoAction*, pUndoAction ) 115 { 116 // #i101118# if drawing layer collects the undo actions, add it there 117 ScDrawLayer* pDrawLayer = rDocShell.GetDocument()->GetDrawLayer(); 118 if( pDrawLayer && pDrawLayer->IsRecording() ) 119 pDrawLayer->AddCalcUndo( pUndoAction ); 120 else 121 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoDraw( pUndoAction, &rDocShell ) ); 122 rDocShell.SetDrawModified(); 123 124 // the affected sheet isn't known, so all stream positions are invalidated 125 ScDocument* pDoc = rDocShell.GetDocument(); 126 SCTAB nTabCount = pDoc->GetTableCount(); 127 for (SCTAB nTab=0; nTab<nTabCount; nTab++) 128 if (pDoc->IsStreamValid(nTab)) 129 pDoc->SetStreamValid(nTab, sal_False); 130 131 return 0; 132 } 133 134 //------------------------------------------------------------------------ 135 136 // Zeile ueber dem Range painten (fuer Linien nach AdjustRowHeight) 137 138 void lcl_PaintAbove( ScDocShell& rDocShell, const ScRange& rRange ) 139 { 140 SCROW nRow = rRange.aStart.Row(); 141 if ( nRow > 0 ) 142 { 143 SCTAB nTab = rRange.aStart.Tab(); //! alle? 144 --nRow; 145 rDocShell.PostPaint( ScRange(0,nRow,nTab, MAXCOL,nRow,nTab), PAINT_GRID ); 146 } 147 } 148 149 //------------------------------------------------------------------------ 150 151 sal_Bool ScDocFunc::AdjustRowHeight( const ScRange& rRange, sal_Bool bPaint ) 152 { 153 ScDocument* pDoc = rDocShell.GetDocument(); 154 if ( pDoc->IsImportingXML() ) 155 { 156 // for XML import, all row heights are updated together after importing 157 return sal_False; 158 } 159 if ( !pDoc->IsAdjustHeightEnabled() ) 160 { 161 return sal_False; 162 } 163 164 SCTAB nTab = rRange.aStart.Tab(); 165 SCROW nStartRow = rRange.aStart.Row(); 166 SCROW nEndRow = rRange.aEnd.Row(); 167 168 ScSizeDeviceProvider aProv( &rDocShell ); 169 Fraction aOne(1,1); 170 171 sal_Bool bChanged = pDoc->SetOptimalHeight( nStartRow, nEndRow, nTab, 0, aProv.GetDevice(), 172 aProv.GetPPTX(), aProv.GetPPTY(), aOne, aOne, sal_False ); 173 174 if ( bPaint && bChanged ) 175 rDocShell.PostPaint( 0, nStartRow, nTab, MAXCOL, MAXROW, nTab, 176 PAINT_GRID | PAINT_LEFT ); 177 178 return bChanged; 179 } 180 181 182 //------------------------------------------------------------------------ 183 184 sal_Bool ScDocFunc::DetectiveAddPred(const ScAddress& rPos) 185 { 186 ScDocShellModificator aModificator( rDocShell ); 187 188 rDocShell.MakeDrawLayer(); 189 ScDocument* pDoc = rDocShell.GetDocument(); 190 sal_Bool bUndo (pDoc->IsUndoEnabled()); 191 ScDrawLayer* pModel = pDoc->GetDrawLayer(); 192 SCCOL nCol = rPos.Col(); 193 SCROW nRow = rPos.Row(); 194 SCTAB nTab = rPos.Tab(); 195 196 if (bUndo) 197 pModel->BeginCalcUndo(); 198 sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).ShowPred( nCol, nRow ); 199 SdrUndoGroup* pUndo = NULL; 200 if (bUndo) 201 pUndo = pModel->GetCalcUndo(); 202 if (bDone) 203 { 204 ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDPRED ); 205 pDoc->AddDetectiveOperation( aOperation ); 206 if (bUndo) 207 { 208 rDocShell.GetUndoManager()->AddUndoAction( 209 new ScUndoDetective( &rDocShell, pUndo, &aOperation ) ); 210 } 211 aModificator.SetDocumentModified(); 212 SfxBindings* pBindings = rDocShell.GetViewBindings(); 213 if (pBindings) 214 pBindings->Invalidate( SID_DETECTIVE_REFRESH ); 215 } 216 else 217 delete pUndo; 218 219 return bDone; 220 } 221 222 sal_Bool ScDocFunc::DetectiveDelPred(const ScAddress& rPos) 223 { 224 ScDocument* pDoc = rDocShell.GetDocument(); 225 226 sal_Bool bUndo(pDoc->IsUndoEnabled()); 227 ScDrawLayer* pModel = pDoc->GetDrawLayer(); 228 if (!pModel) 229 return sal_False; 230 231 ScDocShellModificator aModificator( rDocShell ); 232 233 SCCOL nCol = rPos.Col(); 234 SCROW nRow = rPos.Row(); 235 SCTAB nTab = rPos.Tab(); 236 237 if (bUndo) 238 pModel->BeginCalcUndo(); 239 sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).DeletePred( nCol, nRow ); 240 SdrUndoGroup* pUndo = NULL; 241 if (bUndo) 242 pUndo = pModel->GetCalcUndo(); 243 if (bDone) 244 { 245 ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_DELPRED ); 246 pDoc->AddDetectiveOperation( aOperation ); 247 if (bUndo) 248 { 249 rDocShell.GetUndoManager()->AddUndoAction( 250 new ScUndoDetective( &rDocShell, pUndo, &aOperation ) ); 251 } 252 aModificator.SetDocumentModified(); 253 SfxBindings* pBindings = rDocShell.GetViewBindings(); 254 if (pBindings) 255 pBindings->Invalidate( SID_DETECTIVE_REFRESH ); 256 } 257 else 258 delete pUndo; 259 260 return bDone; 261 } 262 263 sal_Bool ScDocFunc::DetectiveAddSucc(const ScAddress& rPos) 264 { 265 ScDocShellModificator aModificator( rDocShell ); 266 267 rDocShell.MakeDrawLayer(); 268 ScDocument* pDoc = rDocShell.GetDocument(); 269 270 sal_Bool bUndo(pDoc->IsUndoEnabled()); 271 ScDrawLayer* pModel = pDoc->GetDrawLayer(); 272 SCCOL nCol = rPos.Col(); 273 SCROW nRow = rPos.Row(); 274 SCTAB nTab = rPos.Tab(); 275 276 if (bUndo) 277 pModel->BeginCalcUndo(); 278 sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).ShowSucc( nCol, nRow ); 279 SdrUndoGroup* pUndo = NULL; 280 if (bUndo) 281 pUndo = pModel->GetCalcUndo(); 282 if (bDone) 283 { 284 ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDSUCC ); 285 pDoc->AddDetectiveOperation( aOperation ); 286 if (bUndo) 287 { 288 rDocShell.GetUndoManager()->AddUndoAction( 289 new ScUndoDetective( &rDocShell, pUndo, &aOperation ) ); 290 } 291 aModificator.SetDocumentModified(); 292 SfxBindings* pBindings = rDocShell.GetViewBindings(); 293 if (pBindings) 294 pBindings->Invalidate( SID_DETECTIVE_REFRESH ); 295 } 296 else 297 delete pUndo; 298 299 return bDone; 300 } 301 302 sal_Bool ScDocFunc::DetectiveDelSucc(const ScAddress& rPos) 303 { 304 ScDocument* pDoc = rDocShell.GetDocument(); 305 306 sal_Bool bUndo (pDoc->IsUndoEnabled()); 307 ScDrawLayer* pModel = pDoc->GetDrawLayer(); 308 if (!pModel) 309 return sal_False; 310 311 ScDocShellModificator aModificator( rDocShell ); 312 313 SCCOL nCol = rPos.Col(); 314 SCROW nRow = rPos.Row(); 315 SCTAB nTab = rPos.Tab(); 316 317 if (bUndo) 318 pModel->BeginCalcUndo(); 319 sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).DeleteSucc( nCol, nRow ); 320 SdrUndoGroup* pUndo = NULL; 321 if (bUndo) 322 pUndo = pModel->GetCalcUndo(); 323 if (bDone) 324 { 325 ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_DELSUCC ); 326 pDoc->AddDetectiveOperation( aOperation ); 327 if (bUndo) 328 { 329 rDocShell.GetUndoManager()->AddUndoAction( 330 new ScUndoDetective( &rDocShell, pUndo, &aOperation ) ); 331 } 332 aModificator.SetDocumentModified(); 333 SfxBindings* pBindings = rDocShell.GetViewBindings(); 334 if (pBindings) 335 pBindings->Invalidate( SID_DETECTIVE_REFRESH ); 336 } 337 else 338 delete pUndo; 339 340 return bDone; 341 } 342 343 sal_Bool ScDocFunc::DetectiveAddError(const ScAddress& rPos) 344 { 345 ScDocShellModificator aModificator( rDocShell ); 346 347 rDocShell.MakeDrawLayer(); 348 ScDocument* pDoc = rDocShell.GetDocument(); 349 350 sal_Bool bUndo (pDoc->IsUndoEnabled()); 351 ScDrawLayer* pModel = pDoc->GetDrawLayer(); 352 SCCOL nCol = rPos.Col(); 353 SCROW nRow = rPos.Row(); 354 SCTAB nTab = rPos.Tab(); 355 356 if (bUndo) 357 pModel->BeginCalcUndo(); 358 sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).ShowError( nCol, nRow ); 359 SdrUndoGroup* pUndo = NULL; 360 if (bUndo) 361 pUndo = pModel->GetCalcUndo(); 362 if (bDone) 363 { 364 ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDERROR ); 365 pDoc->AddDetectiveOperation( aOperation ); 366 if (bUndo) 367 { 368 rDocShell.GetUndoManager()->AddUndoAction( 369 new ScUndoDetective( &rDocShell, pUndo, &aOperation ) ); 370 } 371 aModificator.SetDocumentModified(); 372 SfxBindings* pBindings = rDocShell.GetViewBindings(); 373 if (pBindings) 374 pBindings->Invalidate( SID_DETECTIVE_REFRESH ); 375 } 376 else 377 delete pUndo; 378 379 return bDone; 380 } 381 382 sal_Bool ScDocFunc::DetectiveMarkInvalid(SCTAB nTab) 383 { 384 ScDocShellModificator aModificator( rDocShell ); 385 386 rDocShell.MakeDrawLayer(); 387 ScDocument* pDoc = rDocShell.GetDocument(); 388 389 sal_Bool bUndo (pDoc->IsUndoEnabled()); 390 ScDrawLayer* pModel = pDoc->GetDrawLayer(); 391 392 Window* pWaitWin = rDocShell.GetActiveDialogParent(); 393 if (pWaitWin) 394 pWaitWin->EnterWait(); 395 if (bUndo) 396 pModel->BeginCalcUndo(); 397 sal_Bool bOverflow; 398 sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).MarkInvalid( bOverflow ); 399 SdrUndoGroup* pUndo = NULL; 400 if (bUndo) 401 pUndo = pModel->GetCalcUndo(); 402 if (pWaitWin) 403 pWaitWin->LeaveWait(); 404 if (bDone) 405 { 406 if (pUndo && bUndo) 407 { 408 pUndo->SetComment( ScGlobal::GetRscString( STR_UNDO_DETINVALID ) ); 409 rDocShell.GetUndoManager()->AddUndoAction( pUndo ); 410 } 411 aModificator.SetDocumentModified(); 412 if ( bOverflow ) 413 { 414 InfoBox( NULL, 415 ScGlobal::GetRscString( STR_DETINVALID_OVERFLOW ) ).Execute(); 416 } 417 } 418 else 419 delete pUndo; 420 421 return bDone; 422 } 423 424 sal_Bool ScDocFunc::DetectiveDelAll(SCTAB nTab) 425 { 426 ScDocument* pDoc = rDocShell.GetDocument(); 427 428 sal_Bool bUndo (pDoc->IsUndoEnabled()); 429 ScDrawLayer* pModel = pDoc->GetDrawLayer(); 430 if (!pModel) 431 return sal_False; 432 433 ScDocShellModificator aModificator( rDocShell ); 434 435 if (bUndo) 436 pModel->BeginCalcUndo(); 437 sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).DeleteAll( SC_DET_DETECTIVE ); 438 SdrUndoGroup* pUndo = NULL; 439 if (bUndo) 440 pUndo = pModel->GetCalcUndo(); 441 if (bDone) 442 { 443 ScDetOpList* pOldList = pDoc->GetDetOpList(); 444 ScDetOpList* pUndoList = NULL; 445 if (bUndo) 446 pUndoList = pOldList ? new ScDetOpList(*pOldList) : NULL; 447 448 pDoc->ClearDetectiveOperations(); 449 450 if (bUndo) 451 { 452 rDocShell.GetUndoManager()->AddUndoAction( 453 new ScUndoDetective( &rDocShell, pUndo, NULL, pUndoList ) ); 454 } 455 aModificator.SetDocumentModified(); 456 SfxBindings* pBindings = rDocShell.GetViewBindings(); 457 if (pBindings) 458 pBindings->Invalidate( SID_DETECTIVE_REFRESH ); 459 } 460 else 461 delete pUndo; 462 463 return bDone; 464 } 465 466 sal_Bool ScDocFunc::DetectiveRefresh( sal_Bool bAutomatic ) 467 { 468 sal_Bool bDone = sal_False; 469 ScDocument* pDoc = rDocShell.GetDocument(); 470 471 sal_Bool bUndo (pDoc->IsUndoEnabled()); 472 ScDetOpList* pList = pDoc->GetDetOpList(); 473 if ( pList && pList->Count() ) 474 { 475 rDocShell.MakeDrawLayer(); 476 ScDrawLayer* pModel = pDoc->GetDrawLayer(); 477 if (bUndo) 478 pModel->BeginCalcUndo(); 479 480 // Loeschen auf allen Tabellen 481 482 SCTAB nTabCount = pDoc->GetTableCount(); 483 for (SCTAB nTab=0; nTab<nTabCount; nTab++) 484 ScDetectiveFunc( pDoc,nTab ).DeleteAll( SC_DET_ARROWS ); // don't remove circles 485 486 // Wiederholen 487 488 sal_uInt16 nCount = pList->Count(); 489 for (sal_uInt16 i=0; i<nCount; i++) 490 { 491 ScDetOpData* pData = (*pList)[i]; 492 if (pData) 493 { 494 ScAddress aPos = pData->GetPos(); 495 ScDetectiveFunc aFunc( pDoc, aPos.Tab() ); 496 SCCOL nCol = aPos.Col(); 497 SCROW nRow = aPos.Row(); 498 switch (pData->GetOperation()) 499 { 500 case SCDETOP_ADDSUCC: 501 aFunc.ShowSucc( nCol, nRow ); 502 break; 503 case SCDETOP_DELSUCC: 504 aFunc.DeleteSucc( nCol, nRow ); 505 break; 506 case SCDETOP_ADDPRED: 507 aFunc.ShowPred( nCol, nRow ); 508 break; 509 case SCDETOP_DELPRED: 510 aFunc.DeletePred( nCol, nRow ); 511 break; 512 case SCDETOP_ADDERROR: 513 aFunc.ShowError( nCol, nRow ); 514 break; 515 default: 516 DBG_ERROR("falsche Op bei DetectiveRefresh"); 517 } 518 } 519 } 520 521 if (bUndo) 522 { 523 SdrUndoGroup* pUndo = pModel->GetCalcUndo(); 524 if (pUndo) 525 { 526 pUndo->SetComment( ScGlobal::GetRscString( STR_UNDO_DETREFRESH ) ); 527 // wenn automatisch, an letzte Aktion anhaengen 528 rDocShell.GetUndoManager()->AddUndoAction( 529 new ScUndoDraw( pUndo, &rDocShell ), 530 bAutomatic ); 531 } 532 } 533 rDocShell.SetDrawModified(); 534 bDone = sal_True; 535 } 536 return bDone; 537 } 538 539 //------------------------------------------------------------------------ 540 541 sal_Bool ScDocFunc::DeleteContents( const ScMarkData& rMark, sal_uInt16 nFlags, 542 sal_Bool bRecord, sal_Bool bApi ) 543 { 544 ScDocShellModificator aModificator( rDocShell ); 545 546 if ( !rMark.IsMarked() && !rMark.IsMultiMarked() ) 547 { 548 DBG_ERROR("ScDocFunc::DeleteContents ohne Markierung"); 549 return sal_False; 550 } 551 552 ScDocument* pDoc = rDocShell.GetDocument(); 553 554 if (bRecord && !pDoc->IsUndoEnabled()) 555 bRecord = sal_False; 556 557 ScEditableTester aTester( pDoc, rMark ); 558 if (!aTester.IsEditable()) 559 { 560 if (!bApi) 561 rDocShell.ErrorMessage(aTester.GetMessageId()); 562 return sal_False; 563 } 564 565 ScRange aMarkRange; 566 sal_Bool bSimple = sal_False; 567 568 ScMarkData aMultiMark = rMark; 569 aMultiMark.SetMarking(sal_False); // fuer MarkToMulti 570 571 ScDocument* pUndoDoc = NULL; 572 sal_Bool bMulti = !bSimple && aMultiMark.IsMultiMarked(); 573 if (!bSimple) 574 { 575 aMultiMark.MarkToMulti(); 576 aMultiMark.GetMultiMarkArea( aMarkRange ); 577 } 578 ScRange aExtendedRange(aMarkRange); 579 if (!bSimple) 580 { 581 if ( pDoc->ExtendMerge( aExtendedRange, sal_True ) ) 582 bMulti = sal_False; 583 } 584 585 // keine Objekte auf geschuetzten Tabellen 586 sal_Bool bObjects = sal_False; 587 if ( nFlags & IDF_OBJECTS ) 588 { 589 bObjects = sal_True; 590 SCTAB nTabCount = pDoc->GetTableCount(); 591 for (SCTAB nTab=0; nTab<nTabCount; nTab++) 592 if (aMultiMark.GetTableSelect(nTab) && pDoc->IsTabProtected(nTab)) 593 bObjects = sal_False; 594 } 595 596 sal_uInt16 nExtFlags = 0; // extra flags are needed only if attributes are deleted 597 if ( nFlags & IDF_ATTRIB ) 598 rDocShell.UpdatePaintExt( nExtFlags, aMarkRange ); 599 600 // Reihenfolge: 601 // 1) BeginDrawUndo 602 // 2) Objekte loeschen (DrawUndo wird gefuellt) 603 // 3) Inhalte fuer Undo kopieren und Undo-Aktion anlegen 604 // 4) Inhalte loeschen 605 606 bool bDrawUndo = bObjects || (nFlags & IDF_NOTE); 607 if (bRecord && bDrawUndo) 608 pDoc->BeginDrawUndo(); 609 610 if (bObjects) 611 { 612 if (bMulti) 613 pDoc->DeleteObjectsInSelection( aMultiMark ); 614 else 615 pDoc->DeleteObjectsInArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), 616 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), 617 aMultiMark ); 618 } 619 620 if ( bRecord ) 621 { 622 pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 623 pUndoDoc->InitUndo( pDoc, aMarkRange.aStart.Tab(), aMarkRange.aEnd.Tab() ); 624 625 // bei "Format/Standard" alle Attribute kopieren, weil CopyToDocument 626 // nur mit IDF_HARDATTR zu langsam ist: 627 sal_uInt16 nUndoDocFlags = nFlags; 628 if (nFlags & IDF_ATTRIB) 629 nUndoDocFlags |= IDF_ATTRIB; 630 if (nFlags & IDF_EDITATTR) // Edit-Engine-Attribute 631 nUndoDocFlags |= IDF_STRING; // -> Zellen werden geaendert 632 if (nFlags & IDF_NOTE) 633 nUndoDocFlags |= IDF_CONTENTS; // #68795# copy all cells with their notes 634 // note captions are handled in drawing undo 635 nUndoDocFlags |= IDF_NOCAPTIONS; 636 pDoc->CopyToDocument( aExtendedRange, nUndoDocFlags, bMulti, pUndoDoc, &aMultiMark ); 637 } 638 639 //! HideAllCursors(); // falls Zusammenfassung aufgehoben wird 640 if (bSimple) 641 pDoc->DeleteArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), 642 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), 643 aMultiMark, nFlags ); 644 else 645 { 646 pDoc->DeleteSelection( nFlags, aMultiMark ); 647 // aMultiMark.MarkToSimple(); 648 } 649 650 // add undo action after drawing undo is complete (objects and note captions) 651 if( bRecord ) 652 rDocShell.GetUndoManager()->AddUndoAction( 653 new ScUndoDeleteContents( &rDocShell, aMultiMark, aExtendedRange, 654 pUndoDoc, bMulti, nFlags, bDrawUndo ) ); 655 656 if (!AdjustRowHeight( aExtendedRange )) 657 rDocShell.PostPaint( aExtendedRange, PAINT_GRID, nExtFlags ); 658 else if (nExtFlags & SC_PF_LINES) 659 lcl_PaintAbove( rDocShell, aExtendedRange ); // fuer Linien ueber dem Bereich 660 661 // rDocShell.UpdateOle(GetViewData()); //! an der View? 662 aModificator.SetDocumentModified(); 663 //! CellContentChanged(); 664 //! ShowAllCursors(); 665 666 #if 0 667 //! muss an der View bleiben !!!! 668 if ( nFlags & IDF_ATTRIB ) 669 { 670 if ( nFlags & IDF_CONTENTS ) 671 ForgetFormatArea(); 672 else 673 StartFormatArea(); // Attribute loeschen ist auch Attributierung 674 } 675 #endif 676 677 return sal_True; 678 } 679 680 //------------------------------------------------------------------------ 681 682 sal_Bool ScDocFunc::TransliterateText( const ScMarkData& rMark, sal_Int32 nType, 683 sal_Bool bRecord, sal_Bool bApi ) 684 { 685 ScDocShellModificator aModificator( rDocShell ); 686 687 ScDocument* pDoc = rDocShell.GetDocument(); 688 if (bRecord && !pDoc->IsUndoEnabled()) 689 bRecord = sal_False; 690 691 ScEditableTester aTester( pDoc, rMark ); 692 if (!aTester.IsEditable()) 693 { 694 if (!bApi) 695 rDocShell.ErrorMessage(aTester.GetMessageId()); 696 return sal_False; 697 } 698 699 ScRange aMarkRange; 700 ScMarkData aMultiMark = rMark; 701 aMultiMark.SetMarking(sal_False); // for MarkToMulti 702 aMultiMark.MarkToMulti(); 703 aMultiMark.GetMultiMarkArea( aMarkRange ); 704 705 if (bRecord) 706 { 707 SCTAB nStartTab = aMarkRange.aStart.Tab(); 708 SCTAB nTabCount = pDoc->GetTableCount(); 709 710 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 711 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab ); 712 for (SCTAB i=0; i<nTabCount; i++) 713 if (i != nStartTab && rMark.GetTableSelect(i)) 714 pUndoDoc->AddUndoTab( i, i ); 715 716 ScRange aCopyRange = aMarkRange; 717 aCopyRange.aStart.SetTab(0); 718 aCopyRange.aEnd.SetTab(nTabCount-1); 719 pDoc->CopyToDocument( aCopyRange, IDF_CONTENTS, sal_True, pUndoDoc, &aMultiMark ); 720 721 rDocShell.GetUndoManager()->AddUndoAction( 722 new ScUndoTransliterate( &rDocShell, aMultiMark, pUndoDoc, nType ) ); 723 } 724 725 pDoc->TransliterateText( aMultiMark, nType ); 726 727 if (!AdjustRowHeight( aMarkRange )) 728 rDocShell.PostPaint( aMarkRange, PAINT_GRID ); 729 730 aModificator.SetDocumentModified(); 731 732 return sal_True; 733 } 734 735 //------------------------------------------------------------------------ 736 737 sal_Bool ScDocFunc::SetNormalString( const ScAddress& rPos, const String& rText, sal_Bool bApi ) 738 { 739 ScDocShellModificator aModificator( rDocShell ); 740 ScDocument* pDoc = rDocShell.GetDocument(); 741 742 sal_Bool bUndo(pDoc->IsUndoEnabled()); 743 ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() ); 744 if (!aTester.IsEditable()) 745 { 746 if (!bApi) 747 rDocShell.ErrorMessage(aTester.GetMessageId()); 748 return sal_False; 749 } 750 751 SCTAB* pTabs = NULL; 752 ScBaseCell** ppOldCells = NULL; 753 sal_Bool* pHasFormat = NULL; 754 sal_uLong* pOldFormats = NULL; 755 ScBaseCell* pDocCell = pDoc->GetCell( rPos ); 756 sal_Bool bEditDeleted = (pDocCell && pDocCell->GetCellType() == CELLTYPE_EDIT); 757 if (bUndo) 758 { 759 pTabs = new SCTAB[1]; 760 pTabs[0] = rPos.Tab(); 761 ppOldCells = new ScBaseCell*[1]; 762 ppOldCells[0] = pDocCell ? pDocCell->CloneWithoutNote( *pDoc ) : 0; 763 764 pHasFormat = new sal_Bool[1]; 765 pOldFormats = new sal_uLong[1]; 766 const SfxPoolItem* pItem; 767 const ScPatternAttr* pPattern = pDoc->GetPattern( rPos.Col(),rPos.Row(),rPos.Tab() ); 768 if ( SFX_ITEM_SET == pPattern->GetItemSet().GetItemState( 769 ATTR_VALUE_FORMAT,sal_False,&pItem) ) 770 { 771 pHasFormat[0] = sal_True; 772 pOldFormats[0] = ((const SfxUInt32Item*)pItem)->GetValue(); 773 } 774 else 775 pHasFormat[0] = sal_False; 776 } 777 778 pDoc->SetString( rPos.Col(), rPos.Row(), rPos.Tab(), rText ); 779 780 if (bUndo) 781 { 782 // wegen ChangeTracking darf UndoAction erst nach SetString angelegt werden 783 rDocShell.GetUndoManager()->AddUndoAction(new ScUndoEnterData( &rDocShell, rPos.Col(),rPos.Row(),rPos.Tab(), 1,pTabs, 784 ppOldCells, pHasFormat, pOldFormats, rText, NULL ) ); 785 } 786 787 if ( bEditDeleted || pDoc->HasAttrib( ScRange(rPos), HASATTR_NEEDHEIGHT ) ) 788 AdjustRowHeight( ScRange(rPos) ); 789 790 rDocShell.PostPaintCell( rPos ); 791 aModificator.SetDocumentModified(); 792 793 // #107160# notify input handler here the same way as in PutCell 794 if (bApi) 795 NotifyInputHandler( rPos ); 796 797 return sal_True; 798 } 799 800 sal_Bool ScDocFunc::PutCell( const ScAddress& rPos, ScBaseCell* pNewCell, sal_Bool bApi ) 801 { 802 ScDocShellModificator aModificator( rDocShell ); 803 ScDocument* pDoc = rDocShell.GetDocument(); 804 sal_Bool bUndo (pDoc->IsUndoEnabled()); 805 sal_Bool bXMLLoading(pDoc->IsImportingXML()); 806 807 // #i925#; it is not neccessary to test whether the cell is editable on loading a XML document 808 if (!bXMLLoading) 809 { 810 ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() ); 811 if (!aTester.IsEditable()) 812 { 813 if (!bApi) 814 rDocShell.ErrorMessage(aTester.GetMessageId()); 815 pNewCell->Delete(); 816 return sal_False; 817 } 818 } 819 820 sal_Bool bEditCell = ( pNewCell->GetCellType() == CELLTYPE_EDIT ); 821 ScBaseCell* pDocCell = pDoc->GetCell( rPos ); 822 sal_Bool bEditDeleted = (pDocCell && pDocCell->GetCellType() == CELLTYPE_EDIT); 823 sal_Bool bHeight = ( bEditDeleted || bEditCell || 824 pDoc->HasAttrib( ScRange(rPos), HASATTR_NEEDHEIGHT ) ); 825 826 ScBaseCell* pUndoCell = (bUndo && pDocCell) ? pDocCell->CloneWithoutNote( *pDoc, rPos ) : 0; 827 ScBaseCell* pRedoCell = (bUndo && pNewCell) ? pNewCell->CloneWithoutNote( *pDoc, rPos ) : 0; 828 829 pDoc->PutCell( rPos, pNewCell ); 830 831 // wegen ChangeTracking darf UndoAction erst nach PutCell angelegt werden 832 if (bUndo) 833 { 834 rDocShell.GetUndoManager()->AddUndoAction( 835 new ScUndoPutCell( &rDocShell, rPos, pUndoCell, pRedoCell, bHeight ) ); 836 } 837 838 if (bHeight) 839 AdjustRowHeight( ScRange(rPos) ); 840 841 if (!bXMLLoading) 842 rDocShell.PostPaintCell( rPos ); 843 844 aModificator.SetDocumentModified(); 845 846 // #i925#; it is not neccessary to notify on loading a XML document 847 // #103934#; notify editline and cell in edit mode 848 if (bApi && !bXMLLoading) 849 NotifyInputHandler( rPos ); 850 851 return sal_True; 852 } 853 854 void ScDocFunc::NotifyInputHandler( const ScAddress& rPos ) 855 { 856 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell(); 857 if ( pViewSh && pViewSh->GetViewData()->GetDocShell() == &rDocShell ) 858 { 859 ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl(); 860 if ( pInputHdl && pInputHdl->GetCursorPos() == rPos ) 861 { 862 sal_Bool bIsEditMode(pInputHdl->IsEditMode()); 863 864 // set modified if in editmode, because so the string is not set in the InputWindow like in the cell 865 // (the cell shows the same like the InputWindow) 866 if (bIsEditMode) 867 pInputHdl->SetModified(); 868 pViewSh->UpdateInputHandler(sal_False, !bIsEditMode); 869 } 870 } 871 } 872 873 struct ScMyRememberItem 874 { 875 sal_uInt16 nIndex; 876 SfxItemSet aItemSet; 877 878 ScMyRememberItem(const SfxItemSet& rItemSet, sal_uInt16 nTempIndex) : 879 nIndex(nTempIndex), aItemSet(rItemSet) {} 880 }; 881 882 typedef ::std::list<ScMyRememberItem*> ScMyRememberItemList; 883 884 sal_Bool ScDocFunc::PutData( const ScAddress& rPos, ScEditEngineDefaulter& rEngine, sal_Bool bInterpret, sal_Bool bApi ) 885 { 886 // PutData ruft PutCell oder SetNormalString 887 888 sal_Bool bRet = sal_False; 889 ScDocument* pDoc = rDocShell.GetDocument(); 890 ScEditAttrTester aTester( &rEngine ); 891 sal_Bool bEditCell = aTester.NeedsObject(); 892 if ( bEditCell ) 893 { 894 // #i61702# With bLoseContent set, the content of rEngine isn't restored 895 // (used in loading XML, where after the removeActionLock call the API obejct's 896 // EditEngine isn't accessed again. 897 sal_Bool bLoseContent = pDoc->IsImportingXML(); 898 899 sal_Bool bUpdateMode(rEngine.GetUpdateMode()); 900 if (bUpdateMode) 901 rEngine.SetUpdateMode(sal_False); 902 903 ScMyRememberItemList aRememberItems; 904 ScMyRememberItem* pRememberItem = NULL; 905 906 // All paragraph attributes must be removed before calling CreateTextObject, 907 // not only alignment, so the object doesn't contain the cell attributes as 908 // paragraph attributes. Before remove the attributes store they in a list to 909 // set they back to the EditEngine. 910 sal_uInt16 nCount = rEngine.GetParagraphCount(); 911 for (sal_uInt16 i=0; i<nCount; i++) 912 { 913 const SfxItemSet& rOld = rEngine.GetParaAttribs( i ); 914 if ( rOld.Count() ) 915 { 916 if ( !bLoseContent ) 917 { 918 pRememberItem = new ScMyRememberItem(rEngine.GetParaAttribs(i), i); 919 aRememberItems.push_back(pRememberItem); 920 } 921 rEngine.SetParaAttribs( i, SfxItemSet( *rOld.GetPool(), rOld.GetRanges() ) ); 922 } 923 } 924 925 EditTextObject* pNewData = rEngine.CreateTextObject(); 926 bRet = PutCell( rPos, 927 new ScEditCell( pNewData, pDoc, rEngine.GetEditTextObjectPool() ), 928 bApi ); 929 delete pNewData; 930 931 // Set the paragraph attributes back to the EditEngine. 932 if (!aRememberItems.empty()) 933 { 934 // ScMyRememberItem* pRememberItem = NULL; 935 ScMyRememberItemList::iterator aItr = aRememberItems.begin(); 936 while (aItr != aRememberItems.end()) 937 { 938 pRememberItem = *aItr; 939 rEngine.SetParaAttribs(pRememberItem->nIndex, pRememberItem->aItemSet); 940 delete pRememberItem; 941 aItr = aRememberItems.erase(aItr); 942 } 943 } 944 945 // #i61702# if the content isn't accessed, there's no need to set the UpdateMode again 946 if ( bUpdateMode && !bLoseContent ) 947 rEngine.SetUpdateMode(sal_True); 948 } 949 else 950 { 951 String aText = rEngine.GetText(); 952 if ( bInterpret || !aText.Len() ) 953 bRet = SetNormalString( rPos, aText, bApi ); 954 else 955 bRet = PutCell( rPos, new ScStringCell( aText ), bApi ); 956 } 957 958 if ( bRet && aTester.NeedsCellAttr() ) 959 { 960 const SfxItemSet& rEditAttr = aTester.GetAttribs(); 961 ScPatternAttr aPattern( pDoc->GetPool() ); 962 aPattern.GetFromEditItemSet( &rEditAttr ); 963 aPattern.DeleteUnchanged( pDoc->GetPattern( rPos.Col(), rPos.Row(), rPos.Tab() ) ); 964 aPattern.GetItemSet().ClearItem( ATTR_HOR_JUSTIFY ); // wasn't removed above if no edit object 965 if ( aPattern.GetItemSet().Count() > 0 ) 966 { 967 ScMarkData aMark; 968 aMark.SelectTable( rPos.Tab(), sal_True ); 969 aMark.SetMarkArea( ScRange( rPos ) ); 970 ApplyAttributes( aMark, aPattern, sal_True, bApi ); 971 } 972 } 973 974 return bRet; 975 } 976 977 978 ScTokenArray* lcl_ScDocFunc_CreateTokenArrayXML( const String& rText, const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar ) 979 { 980 ScTokenArray* pCode = new ScTokenArray; 981 pCode->AddString( rText ); 982 if( (eGrammar == formula::FormulaGrammar::GRAM_EXTERNAL) && (rFormulaNmsp.Len() > 0) ) 983 pCode->AddString( rFormulaNmsp ); 984 return pCode; 985 } 986 987 988 ScBaseCell* ScDocFunc::InterpretEnglishString( const ScAddress& rPos, 989 const String& rText, const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar, short* pRetFormatType ) 990 { 991 ScDocument* pDoc = rDocShell.GetDocument(); 992 ScBaseCell* pNewCell = NULL; 993 994 if ( rText.Len() > 1 && rText.GetChar(0) == '=' ) 995 { 996 ScTokenArray* pCode; 997 if ( pDoc->IsImportingXML() ) 998 { // temporary formula string as string tokens 999 pCode = lcl_ScDocFunc_CreateTokenArrayXML( rText, rFormulaNmsp, eGrammar ); 1000 pDoc->IncXMLImportedFormulaCount( rText.Len() ); 1001 } 1002 else 1003 { 1004 ScCompiler aComp( pDoc, rPos ); 1005 aComp.SetGrammar(eGrammar); 1006 pCode = aComp.CompileString( rText ); 1007 } 1008 pNewCell = new ScFormulaCell( pDoc, rPos, pCode, eGrammar, MM_NONE ); 1009 delete pCode; // Zell-ctor hat das TokenArray kopiert 1010 } 1011 else if ( rText.Len() > 1 && rText.GetChar(0) == '\'' ) 1012 { 1013 // for bEnglish, "'" at the beginning is always interpreted as text 1014 // marker and stripped 1015 pNewCell = ScBaseCell::CreateTextCell( rText.Copy( 1 ), pDoc ); 1016 } 1017 else // (nur) auf englisches Zahlformat testen 1018 { 1019 SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); 1020 sal_uInt32 nEnglish = pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US); 1021 double fVal; 1022 if ( pFormatter->IsNumberFormat( rText, nEnglish, fVal ) ) 1023 { 1024 pNewCell = new ScValueCell( fVal ); 1025 // return the format type from the English format, so a localized format can be created 1026 if ( pRetFormatType ) 1027 *pRetFormatType = pFormatter->GetType( nEnglish ); 1028 } 1029 else if ( rText.Len() ) 1030 pNewCell = ScBaseCell::CreateTextCell( rText, pDoc ); 1031 1032 // das (englische) Zahlformat wird nicht gesetzt 1033 //! passendes lokales Format suchen und setzen??? 1034 } 1035 1036 return pNewCell; 1037 } 1038 1039 1040 sal_Bool ScDocFunc::SetCellText( const ScAddress& rPos, const String& rText, 1041 sal_Bool bInterpret, sal_Bool bEnglish, sal_Bool bApi, 1042 const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar ) 1043 { 1044 // SetCellText ruft PutCell oder SetNormalString 1045 1046 ScDocument* pDoc = rDocShell.GetDocument(); 1047 ScBaseCell* pNewCell = NULL; 1048 if ( bInterpret ) 1049 { 1050 if ( bEnglish ) 1051 { 1052 ::boost::scoped_ptr<ScExternalRefManager::ApiGuard> pExtRefGuard; 1053 if (bApi) 1054 pExtRefGuard.reset(new ScExternalRefManager::ApiGuard(pDoc)); 1055 1056 // code moved to own method InterpretEnglishString because it is also used in 1057 // ScCellRangeObj::setFormulaArray 1058 1059 pNewCell = InterpretEnglishString( rPos, rText, rFormulaNmsp, eGrammar ); 1060 } 1061 // sonst Null behalten -> SetString mit lokalen Formeln/Zahlformat 1062 } 1063 else if ( rText.Len() ) 1064 { 1065 OSL_ENSURE( rFormulaNmsp.Len() == 0, "ScDocFunc::SetCellText - formula namespace, but do not interpret?" ); 1066 pNewCell = ScBaseCell::CreateTextCell( rText, pDoc ); // immer Text 1067 } 1068 1069 if (pNewCell) 1070 return PutCell( rPos, pNewCell, bApi ); 1071 else 1072 return SetNormalString( rPos, rText, bApi ); 1073 } 1074 1075 //------------------------------------------------------------------------ 1076 1077 bool ScDocFunc::ShowNote( const ScAddress& rPos, bool bShow ) 1078 { 1079 ScDocument& rDoc = *rDocShell.GetDocument(); 1080 ScPostIt* pNote = rDoc.GetNote( rPos ); 1081 if( !pNote || (bShow == pNote->IsCaptionShown()) ) return false; 1082 1083 // move the caption to internal or hidden layer and create undo action 1084 pNote->ShowCaption( rPos, bShow ); 1085 if( rDoc.IsUndoEnabled() ) 1086 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoShowHideNote( rDocShell, rPos, bShow ) ); 1087 1088 if (rDoc.IsStreamValid(rPos.Tab())) 1089 rDoc.SetStreamValid(rPos.Tab(), sal_False); 1090 1091 rDocShell.SetDocumentModified(); 1092 1093 return true; 1094 } 1095 1096 //------------------------------------------------------------------------ 1097 1098 bool ScDocFunc::SetNoteText( const ScAddress& rPos, const String& rText, sal_Bool bApi ) 1099 { 1100 ScDocShellModificator aModificator( rDocShell ); 1101 1102 ScDocument* pDoc = rDocShell.GetDocument(); 1103 ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() ); 1104 if (!aTester.IsEditable()) 1105 { 1106 if (!bApi) 1107 rDocShell.ErrorMessage(aTester.GetMessageId()); 1108 return false; 1109 } 1110 1111 String aNewText = rText; 1112 aNewText.ConvertLineEnd(); //! ist das noetig ??? 1113 1114 if( ScPostIt* pNote = (aNewText.Len() > 0) ? pDoc->GetOrCreateNote( rPos ) : pDoc->GetNote( rPos ) ) 1115 pNote->SetText( rPos, aNewText ); 1116 1117 //! Undo !!! 1118 1119 if (pDoc->IsStreamValid(rPos.Tab())) 1120 pDoc->SetStreamValid(rPos.Tab(), sal_False); 1121 1122 rDocShell.PostPaintCell( rPos ); 1123 aModificator.SetDocumentModified(); 1124 1125 return true; 1126 } 1127 1128 //------------------------------------------------------------------------ 1129 1130 bool ScDocFunc::ReplaceNote( const ScAddress& rPos, const String& rNoteText, const String* pAuthor, const String* pDate, sal_Bool bApi ) 1131 { 1132 bool bDone = false; 1133 1134 ScDocShellModificator aModificator( rDocShell ); 1135 ScDocument& rDoc = *rDocShell.GetDocument(); 1136 ScEditableTester aTester( &rDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() ); 1137 if (aTester.IsEditable()) 1138 { 1139 ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer(); 1140 ::svl::IUndoManager* pUndoMgr = (pDrawLayer && rDoc.IsUndoEnabled()) ? rDocShell.GetUndoManager() : 0; 1141 1142 ScNoteData aOldData; 1143 ScPostIt* pOldNote = rDoc.ReleaseNote( rPos ); 1144 if( pOldNote ) 1145 { 1146 // ensure existing caption object before draw undo tracking starts 1147 pOldNote->GetOrCreateCaption( rPos ); 1148 // rescue note data for undo 1149 aOldData = pOldNote->GetNoteData(); 1150 } 1151 1152 // collect drawing undo actions for deleting/inserting caption obejcts 1153 if( pUndoMgr ) 1154 pDrawLayer->BeginCalcUndo(); 1155 1156 // delete the note (creates drawing undo action for the caption object) 1157 delete pOldNote; 1158 1159 // create new note (creates drawing undo action for the new caption object) 1160 ScNoteData aNewData; 1161 if( ScPostIt* pNewNote = ScNoteUtil::CreateNoteFromString( rDoc, rPos, rNoteText, false, true ) ) 1162 { 1163 if( pAuthor ) pNewNote->SetAuthor( *pAuthor ); 1164 if( pDate ) pNewNote->SetDate( *pDate ); 1165 // rescue note data for undo 1166 aNewData = pNewNote->GetNoteData(); 1167 } 1168 1169 // create the undo action 1170 if( pUndoMgr && (aOldData.mpCaption || aNewData.mpCaption) ) 1171 pUndoMgr->AddUndoAction( new ScUndoReplaceNote( rDocShell, rPos, aOldData, aNewData, pDrawLayer->GetCalcUndo() ) ); 1172 1173 // repaint cell (to make note marker visible) 1174 rDocShell.PostPaintCell( rPos ); 1175 1176 if (rDoc.IsStreamValid(rPos.Tab())) 1177 rDoc.SetStreamValid(rPos.Tab(), sal_False); 1178 1179 aModificator.SetDocumentModified(); 1180 bDone = true; 1181 } 1182 else if (!bApi) 1183 { 1184 rDocShell.ErrorMessage(aTester.GetMessageId()); 1185 } 1186 1187 return bDone; 1188 } 1189 1190 //------------------------------------------------------------------------ 1191 1192 sal_Bool ScDocFunc::ApplyAttributes( const ScMarkData& rMark, const ScPatternAttr& rPattern, 1193 sal_Bool bRecord, sal_Bool bApi ) 1194 { 1195 ScDocument* pDoc = rDocShell.GetDocument(); 1196 if ( bRecord && !pDoc->IsUndoEnabled() ) 1197 bRecord = sal_False; 1198 1199 sal_Bool bImportingXML = pDoc->IsImportingXML(); 1200 // Cell formats can still be set if the range isn't editable only because of matrix formulas. 1201 // #i62483# When loading XML, the check can be skipped altogether. 1202 sal_Bool bOnlyNotBecauseOfMatrix; 1203 if ( !bImportingXML && !pDoc->IsSelectionEditable( rMark, &bOnlyNotBecauseOfMatrix ) 1204 && !bOnlyNotBecauseOfMatrix ) 1205 { 1206 if (!bApi) 1207 rDocShell.ErrorMessage(STR_PROTECTIONERR); 1208 return sal_False; 1209 } 1210 1211 ScDocShellModificator aModificator( rDocShell ); 1212 1213 //! Umrandung 1214 1215 ScRange aMultiRange; 1216 sal_Bool bMulti = rMark.IsMultiMarked(); 1217 if ( bMulti ) 1218 rMark.GetMultiMarkArea( aMultiRange ); 1219 else 1220 rMark.GetMarkArea( aMultiRange ); 1221 1222 if ( bRecord ) 1223 { 1224 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 1225 pUndoDoc->InitUndo( pDoc, aMultiRange.aStart.Tab(), aMultiRange.aEnd.Tab() ); 1226 pDoc->CopyToDocument( aMultiRange, IDF_ATTRIB, bMulti, pUndoDoc, &rMark ); 1227 1228 rDocShell.GetUndoManager()->AddUndoAction( 1229 new ScUndoSelectionAttr( 1230 &rDocShell, rMark, 1231 aMultiRange.aStart.Col(), aMultiRange.aStart.Row(), aMultiRange.aStart.Tab(), 1232 aMultiRange.aEnd.Col(), aMultiRange.aEnd.Row(), aMultiRange.aEnd.Tab(), 1233 pUndoDoc, bMulti, &rPattern ) ); 1234 } 1235 1236 // While loading XML it is not neccessary to ask HasAttrib. It needs too much time. 1237 sal_uInt16 nExtFlags = 0; 1238 if ( !bImportingXML ) 1239 rDocShell.UpdatePaintExt( nExtFlags, aMultiRange ); // content before the change 1240 pDoc->ApplySelectionPattern( rPattern, rMark ); 1241 if ( !bImportingXML ) 1242 rDocShell.UpdatePaintExt( nExtFlags, aMultiRange ); // content after the change 1243 1244 if (!AdjustRowHeight( aMultiRange )) 1245 rDocShell.PostPaint( aMultiRange, PAINT_GRID, nExtFlags ); 1246 else if (nExtFlags & SC_PF_LINES) 1247 lcl_PaintAbove( rDocShell, aMultiRange ); // fuer Linien ueber dem Bereich 1248 1249 aModificator.SetDocumentModified(); 1250 1251 return sal_True; 1252 } 1253 1254 1255 sal_Bool ScDocFunc::ApplyStyle( const ScMarkData& rMark, const String& rStyleName, 1256 sal_Bool bRecord, sal_Bool bApi ) 1257 { 1258 ScDocument* pDoc = rDocShell.GetDocument(); 1259 if ( bRecord && !pDoc->IsUndoEnabled() ) 1260 bRecord = sal_False; 1261 1262 sal_Bool bImportingXML = pDoc->IsImportingXML(); 1263 // Cell formats can still be set if the range isn't editable only because of matrix formulas. 1264 // #i62483# When loading XML, the check can be skipped altogether. 1265 sal_Bool bOnlyNotBecauseOfMatrix; 1266 if ( !bImportingXML && !pDoc->IsSelectionEditable( rMark, &bOnlyNotBecauseOfMatrix ) 1267 && !bOnlyNotBecauseOfMatrix ) 1268 { 1269 if (!bApi) 1270 rDocShell.ErrorMessage(STR_PROTECTIONERR); 1271 return sal_False; 1272 } 1273 1274 ScStyleSheet* pStyleSheet = (ScStyleSheet*) pDoc->GetStyleSheetPool()->Find( 1275 rStyleName, SFX_STYLE_FAMILY_PARA ); 1276 if (!pStyleSheet) 1277 return sal_False; 1278 1279 ScDocShellModificator aModificator( rDocShell ); 1280 1281 ScRange aMultiRange; 1282 sal_Bool bMulti = rMark.IsMultiMarked(); 1283 if ( bMulti ) 1284 rMark.GetMultiMarkArea( aMultiRange ); 1285 else 1286 rMark.GetMarkArea( aMultiRange ); 1287 1288 if ( bRecord ) 1289 { 1290 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 1291 SCTAB nStartTab = aMultiRange.aStart.Tab(); 1292 SCTAB nTabCount = pDoc->GetTableCount(); 1293 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab ); 1294 for (SCTAB i=0; i<nTabCount; i++) 1295 if (i != nStartTab && rMark.GetTableSelect(i)) 1296 pUndoDoc->AddUndoTab( i, i ); 1297 1298 ScRange aCopyRange = aMultiRange; 1299 aCopyRange.aStart.SetTab(0); 1300 aCopyRange.aEnd.SetTab(nTabCount-1); 1301 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pUndoDoc, &rMark ); 1302 1303 rDocShell.GetUndoManager()->AddUndoAction( 1304 new ScUndoSelectionStyle( 1305 &rDocShell, rMark, aMultiRange, rStyleName, pUndoDoc ) ); 1306 1307 } 1308 1309 // sal_Bool bPaintExt = pDoc->HasAttrib( aMultiRange, HASATTR_PAINTEXT ); 1310 // pDoc->ApplySelectionPattern( rPattern, rMark ); 1311 1312 pDoc->ApplySelectionStyle( (ScStyleSheet&)*pStyleSheet, rMark ); 1313 1314 // if (!bPaintExt) 1315 // bPaintExt = pDoc->HasAttrib( aMultiRange, HASATTR_PAINTEXT ); 1316 // sal_uInt16 nExtFlags = bPaintExt ? SC_PF_LINES : 0; 1317 sal_uInt16 nExtFlags = 0; 1318 if (!AdjustRowHeight( aMultiRange )) 1319 rDocShell.PostPaint( aMultiRange, PAINT_GRID, nExtFlags ); 1320 else if (nExtFlags & SC_PF_LINES) 1321 lcl_PaintAbove( rDocShell, aMultiRange ); // fuer Linien ueber dem Bereich 1322 1323 aModificator.SetDocumentModified(); 1324 1325 return sal_True; 1326 } 1327 1328 //------------------------------------------------------------------------ 1329 1330 sal_Bool ScDocFunc::InsertCells( const ScRange& rRange, const ScMarkData* pTabMark, InsCellCmd eCmd, 1331 sal_Bool bRecord, sal_Bool bApi, sal_Bool bPartOfPaste ) 1332 { 1333 ScDocShellModificator aModificator( rDocShell ); 1334 1335 SCCOL nStartCol = rRange.aStart.Col(); 1336 SCROW nStartRow = rRange.aStart.Row(); 1337 SCTAB nStartTab = rRange.aStart.Tab(); 1338 SCCOL nEndCol = rRange.aEnd.Col(); 1339 SCROW nEndRow = rRange.aEnd.Row(); 1340 SCTAB nEndTab = rRange.aEnd.Tab(); 1341 1342 if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) ) 1343 { 1344 DBG_ERROR("invalid row in InsertCells"); 1345 return sal_False; 1346 } 1347 1348 ScDocument* pDoc = rDocShell.GetDocument(); 1349 SCTAB nTabCount = pDoc->GetTableCount(); 1350 SCCOL nPaintStartX = nStartCol; 1351 SCROW nPaintStartY = nStartRow; 1352 SCCOL nPaintEndX = nEndCol; 1353 SCROW nPaintEndY = nEndRow; 1354 sal_uInt16 nPaintFlags = PAINT_GRID; 1355 sal_Bool bSuccess; 1356 SCTAB i; 1357 1358 ScTabViewShell* pViewSh = rDocShell.GetBestViewShell(); //preserve current cursor position 1359 SCCOL nCursorCol = 0; 1360 SCROW nCursorRow = 0; 1361 if( pViewSh ) 1362 { 1363 nCursorCol = pViewSh->GetViewData()->GetCurX(); 1364 nCursorRow = pViewSh->GetViewData()->GetCurY(); 1365 } 1366 1367 if (bRecord && !pDoc->IsUndoEnabled()) 1368 bRecord = sal_False; 1369 1370 ScMarkData aMark; 1371 if (pTabMark) 1372 aMark = *pTabMark; 1373 else 1374 { 1375 SCTAB nCount = 0; 1376 for( i=0; i<nTabCount; i++ ) 1377 { 1378 if( !pDoc->IsScenario(i) ) 1379 { 1380 nCount++; 1381 if( nCount == nEndTab+1 ) 1382 { 1383 aMark.SelectTable( i, sal_True ); 1384 break; 1385 } 1386 } 1387 } 1388 } 1389 1390 ScMarkData aFullMark( aMark ); // including scenario sheets 1391 for( i=0; i<nTabCount; i++ ) 1392 if( aMark.GetTableSelect( i ) ) 1393 { 1394 for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) 1395 aFullMark.SelectTable( j, sal_True ); 1396 } 1397 1398 SCTAB nSelCount = aMark.GetSelectCount(); 1399 1400 // zugehoerige Szenarien auch anpassen 1401 // Test zusammengefasste 1402 1403 SCCOL nMergeTestStartX = nStartCol; 1404 SCROW nMergeTestStartY = nStartRow; 1405 SCCOL nMergeTestEndX = nEndCol; 1406 SCROW nMergeTestEndY = nEndRow; 1407 1408 ScRange aExtendMergeRange( rRange ); 1409 1410 if( rRange.aStart == rRange.aEnd && pDoc->HasAttrib(rRange, HASATTR_MERGED) ) 1411 { 1412 pDoc->ExtendMerge( aExtendMergeRange ); 1413 pDoc->ExtendOverlapped( aExtendMergeRange ); 1414 nMergeTestEndX = aExtendMergeRange.aEnd.Col(); 1415 nMergeTestEndY = aExtendMergeRange.aEnd.Row(); 1416 nPaintEndX = nMergeTestEndX; 1417 nPaintEndY = nMergeTestEndY; 1418 } 1419 1420 if ( eCmd == INS_INSROWS ) 1421 { 1422 nMergeTestStartX = 0; 1423 nMergeTestEndX = MAXCOL; 1424 } 1425 if ( eCmd == INS_INSCOLS ) 1426 { 1427 nMergeTestStartY = 0; 1428 nMergeTestEndY = MAXROW; 1429 } 1430 if ( eCmd == INS_CELLSDOWN ) 1431 nMergeTestEndY = MAXROW; 1432 if ( eCmd == INS_CELLSRIGHT ) 1433 nMergeTestEndX = MAXCOL; 1434 1435 sal_Bool bNeedRefresh = sal_False; 1436 1437 SCCOL nEditTestEndX = (eCmd==INS_INSCOLS) ? MAXCOL : nMergeTestEndX; 1438 SCROW nEditTestEndY = (eCmd==INS_INSROWS) ? MAXROW : nMergeTestEndY; 1439 ScEditableTester aTester( pDoc, nMergeTestStartX, nMergeTestStartY, nEditTestEndX, nEditTestEndY, aMark ); 1440 if (!aTester.IsEditable()) 1441 { 1442 if (!bApi) 1443 rDocShell.ErrorMessage(aTester.GetMessageId()); 1444 return sal_False; 1445 } 1446 1447 WaitObject aWait( rDocShell.GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference 1448 1449 ScDocument* pRefUndoDoc = NULL; 1450 ScRefUndoData* pUndoData = NULL; 1451 if ( bRecord ) 1452 { 1453 pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 1454 pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, sal_False, sal_False ); 1455 1456 // pRefUndoDoc is filled in InsertCol / InsertRow 1457 1458 pUndoData = new ScRefUndoData( pDoc ); 1459 1460 pDoc->BeginDrawUndo(); 1461 } 1462 1463 // #i8302 : we unmerge overwhelming ranges, before insertion all the actions are put in the same ListAction 1464 // the patch comes from mloiseleur and maoyg 1465 sal_Bool bInsertMerge = sal_False; 1466 std::vector<ScRange> qIncreaseRange; 1467 String aUndo = ScGlobal::GetRscString( STR_UNDO_INSERTCELLS ); 1468 if (bRecord) 1469 rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo ); 1470 1471 for( i=0; i<nTabCount; i++ ) 1472 { 1473 if( aMark.GetTableSelect(i) ) 1474 { 1475 if( pDoc->HasAttrib( nMergeTestStartX, nMergeTestStartY, i, nMergeTestEndX, nMergeTestEndY, i, HASATTR_MERGED | HASATTR_OVERLAPPED ) ) 1476 { 1477 if (eCmd==INS_CELLSRIGHT) 1478 bNeedRefresh = sal_True; 1479 1480 SCCOL nMergeStartX = nMergeTestStartX; 1481 SCROW nMergeStartY = nMergeTestStartY; 1482 SCCOL nMergeEndX = nMergeTestEndX; 1483 SCROW nMergeEndY = nMergeTestEndY; 1484 1485 pDoc->ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i ); 1486 pDoc->ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i ); 1487 1488 if(( eCmd == INS_CELLSDOWN && ( nMergeStartX != nMergeTestStartX || nMergeEndX != nMergeTestEndX )) || 1489 (eCmd == INS_CELLSRIGHT && ( nMergeStartY != nMergeTestStartY || nMergeEndY != nMergeTestEndY )) ) 1490 { 1491 if (!bApi) 1492 rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0); 1493 rDocShell.GetUndoManager()->LeaveListAction(); 1494 return sal_False; 1495 } 1496 1497 SCCOL nTestCol = -1; 1498 SCROW nTestRow1 = -1; 1499 SCROW nTestRow2 = -1; 1500 1501 ScDocAttrIterator aTestIter( pDoc, i, nMergeTestStartX, nMergeTestStartY, nMergeTestEndX, nMergeTestEndY ); 1502 ScRange aExtendRange( nMergeTestStartX, nMergeTestStartY, i, nMergeTestEndX, nMergeTestEndY, i ); 1503 const ScPatternAttr* pPattern = NULL; 1504 const ScMergeAttr* pMergeFlag = NULL; 1505 const ScMergeFlagAttr* pMergeFlagAttr = NULL; 1506 while ( ( pPattern = aTestIter.GetNext( nTestCol, nTestRow1, nTestRow2 ) ) != NULL ) 1507 { 1508 pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem(ATTR_MERGE); 1509 pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG); 1510 sal_Int16 nNewFlags = pMergeFlagAttr->GetValue() & ( SC_MF_HOR | SC_MF_VER ); 1511 if( ( pMergeFlag && pMergeFlag->IsMerged() ) || nNewFlags == SC_MF_HOR || nNewFlags == SC_MF_VER ) 1512 { 1513 ScRange aRange( nTestCol, nTestRow1, i ); 1514 pDoc->ExtendOverlapped(aRange); 1515 pDoc->ExtendMerge(aRange, sal_True, sal_True); 1516 1517 if( nTestRow1 < nTestRow2 && nNewFlags == SC_MF_HOR ) 1518 { 1519 for( SCROW nTestRow = nTestRow1; nTestRow <= nTestRow2; nTestRow++ ) 1520 { 1521 ScRange aTestRange( nTestCol, nTestRow, i ); 1522 pDoc->ExtendOverlapped( aTestRange ); 1523 pDoc->ExtendMerge( aTestRange, sal_True, sal_True); 1524 ScRange aMergeRange( aTestRange.aStart.Col(),aTestRange.aStart.Row(), i ); 1525 if( !aExtendRange.In( aMergeRange ) ) 1526 { 1527 qIncreaseRange.push_back( aTestRange ); 1528 bInsertMerge = sal_True; 1529 } 1530 } 1531 } 1532 else 1533 { 1534 ScRange aMergeRange( aRange.aStart.Col(),aRange.aStart.Row(), i ); 1535 if( !aExtendRange.In( aMergeRange ) ) 1536 { 1537 qIncreaseRange.push_back( aRange ); 1538 } 1539 bInsertMerge = sal_True; 1540 } 1541 } 1542 } 1543 1544 if( bInsertMerge ) 1545 { 1546 if( eCmd == INS_INSROWS || eCmd == INS_CELLSDOWN ) 1547 { 1548 nStartRow = aExtendMergeRange.aStart.Row(); 1549 nEndRow = aExtendMergeRange.aEnd.Row(); 1550 1551 if( eCmd == INS_CELLSDOWN ) 1552 nEndCol = nMergeTestEndX; 1553 else 1554 { 1555 nStartCol = 0; 1556 nEndCol = MAXCOL; 1557 } 1558 } 1559 else if( eCmd == INS_CELLSRIGHT || eCmd == INS_INSCOLS ) 1560 { 1561 1562 nStartCol = aExtendMergeRange.aStart.Col(); 1563 nEndCol = aExtendMergeRange.aEnd.Col(); 1564 if( eCmd == INS_CELLSRIGHT ) 1565 { 1566 nEndRow = nMergeTestEndY; 1567 } 1568 else 1569 { 1570 nStartRow = 0; 1571 nEndRow = MAXROW; 1572 } 1573 } 1574 1575 if( !qIncreaseRange.empty() ) 1576 { 1577 for( ::std::vector<ScRange>::const_iterator iIter( qIncreaseRange.begin()); iIter != qIncreaseRange.end(); iIter++ ) 1578 { 1579 ScRange aRange( *iIter ); 1580 if( pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) ) 1581 { 1582 UnmergeCells( aRange, sal_True, sal_True ); 1583 } 1584 } 1585 } 1586 } 1587 else 1588 { 1589 if (!bApi) 1590 rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0); 1591 rDocShell.GetUndoManager()->LeaveListAction(); 1592 return sal_False; 1593 } 1594 } 1595 } 1596 } 1597 1598 switch (eCmd) 1599 { 1600 case INS_CELLSDOWN: 1601 bSuccess = pDoc->InsertRow( nStartCol, 0, nEndCol, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &aFullMark ); 1602 nPaintEndY = MAXROW; 1603 break; 1604 case INS_INSROWS: 1605 bSuccess = pDoc->InsertRow( 0, 0, MAXCOL, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &aFullMark ); 1606 nPaintStartX = 0; 1607 nPaintEndX = MAXCOL; 1608 nPaintEndY = MAXROW; 1609 nPaintFlags |= PAINT_LEFT; 1610 break; 1611 case INS_CELLSRIGHT: 1612 bSuccess = pDoc->InsertCol( nStartRow, 0, nEndRow, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &aFullMark ); 1613 nPaintEndX = MAXCOL; 1614 break; 1615 case INS_INSCOLS: 1616 bSuccess = pDoc->InsertCol( 0, 0, MAXROW, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &aFullMark ); 1617 nPaintStartY = 0; 1618 nPaintEndY = MAXROW; 1619 nPaintEndX = MAXCOL; 1620 nPaintFlags |= PAINT_TOP; 1621 break; 1622 default: 1623 DBG_ERROR("Falscher Code beim Einfuegen"); 1624 bSuccess = sal_False; 1625 break; 1626 } 1627 1628 if ( bSuccess ) 1629 { 1630 SCTAB* pTabs = NULL; 1631 SCTAB* pScenarios = NULL; 1632 SCTAB nUndoPos = 0; 1633 1634 if ( bRecord ) 1635 { 1636 pTabs = new SCTAB[nSelCount]; 1637 pScenarios = new SCTAB[nSelCount]; 1638 nUndoPos = 0; 1639 for( i=0; i<nTabCount; i++ ) 1640 { 1641 if( aMark.GetTableSelect( i ) ) 1642 { 1643 SCTAB nCount = 0; 1644 for( SCTAB j=i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) 1645 nCount ++; 1646 1647 pScenarios[nUndoPos] = nCount; 1648 pTabs[nUndoPos] = i; 1649 nUndoPos ++; 1650 } 1651 } 1652 1653 if( !bInsertMerge ) 1654 { 1655 rDocShell.GetUndoManager()->LeaveListAction(); 1656 } 1657 1658 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoInsertCells( 1659 &rDocShell, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ), 1660 nUndoPos, pTabs, pScenarios, eCmd, pRefUndoDoc, pUndoData, bPartOfPaste ) ); 1661 } 1662 1663 // #i8302 : we remerge growing ranges, with the new part inserted 1664 1665 while( !qIncreaseRange.empty() ) 1666 { 1667 ScRange aRange = qIncreaseRange.back(); 1668 if( !pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) ) 1669 { 1670 switch (eCmd) 1671 { 1672 case INS_CELLSDOWN: 1673 case INS_INSROWS: 1674 aRange.aEnd.IncRow(static_cast<SCsCOL>(nEndRow-nStartRow+1)); 1675 break; 1676 case INS_CELLSRIGHT: 1677 case INS_INSCOLS: 1678 aRange.aEnd.IncCol(static_cast<SCsCOL>(nEndCol-nStartCol+1)); 1679 break; 1680 default: 1681 break; 1682 } 1683 MergeCells(aRange, sal_False, sal_True, sal_True); 1684 } 1685 qIncreaseRange.pop_back(); 1686 } 1687 1688 if( bInsertMerge ) 1689 rDocShell.GetUndoManager()->LeaveListAction(); 1690 1691 for( i=0; i<nTabCount; i++ ) 1692 { 1693 if( aMark.GetTableSelect( i ) ) 1694 { 1695 if (bNeedRefresh) 1696 pDoc->ExtendMerge( nMergeTestStartX, nMergeTestStartY, nMergeTestEndX, nMergeTestEndY, i, sal_True ); 1697 else 1698 pDoc->RefreshAutoFilter( nMergeTestStartX, nMergeTestStartY, nMergeTestEndX, nMergeTestEndY, i ); 1699 1700 if ( eCmd == INS_INSROWS || eCmd == INS_INSCOLS ) 1701 pDoc->UpdatePageBreaks( i ); 1702 1703 sal_uInt16 nExtFlags = 0; 1704 rDocShell.UpdatePaintExt( nExtFlags, nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i ); 1705 1706 SCTAB nScenarioCount = 0; 1707 1708 for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) 1709 nScenarioCount ++; 1710 1711 sal_Bool bAdjusted = ( eCmd == INS_INSROWS ) ? AdjustRowHeight(ScRange(0, nStartRow, i, MAXCOL, nEndRow, i+nScenarioCount )) : 1712 AdjustRowHeight(ScRange(0, nPaintStartY, i, MAXCOL, nPaintEndY, i+nScenarioCount )); 1713 if (bAdjusted) 1714 { 1715 // paint only what is not done by AdjustRowHeight 1716 if (nPaintFlags & PAINT_TOP) 1717 rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, PAINT_TOP ); 1718 } 1719 else 1720 rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, nPaintFlags, nExtFlags ); 1721 } 1722 } 1723 //aModificator.SetDocumentModified(); 1724 } 1725 else 1726 { 1727 if( bInsertMerge ) 1728 { 1729 while( !qIncreaseRange.empty() ) 1730 { 1731 ScRange aRange = qIncreaseRange.back(); 1732 MergeCells(aRange, sal_False, sal_True, sal_True); 1733 qIncreaseRange.pop_back(); 1734 } 1735 1736 if( pViewSh ) 1737 { 1738 pViewSh->MarkRange( rRange, sal_False ); 1739 pViewSh->SetCursor( nCursorCol, nCursorRow ); 1740 } 1741 } 1742 1743 rDocShell.GetUndoManager()->LeaveListAction(); 1744 rDocShell.GetUndoManager()->RemoveLastUndoAction(); 1745 1746 delete pRefUndoDoc; 1747 delete pUndoData; 1748 if (!bApi) 1749 rDocShell.ErrorMessage(STR_INSERT_FULL); // Spalte/Zeile voll 1750 } 1751 1752 aModificator.SetDocumentModified(); 1753 1754 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); 1755 return bSuccess; 1756 } 1757 1758 sal_Bool ScDocFunc::DeleteCells( const ScRange& rRange, const ScMarkData* pTabMark, DelCellCmd eCmd, 1759 sal_Bool bRecord, sal_Bool bApi ) 1760 { 1761 ScDocShellModificator aModificator( rDocShell ); 1762 1763 SCCOL nStartCol = rRange.aStart.Col(); 1764 SCROW nStartRow = rRange.aStart.Row(); 1765 SCTAB nStartTab = rRange.aStart.Tab(); 1766 SCCOL nEndCol = rRange.aEnd.Col(); 1767 SCROW nEndRow = rRange.aEnd.Row(); 1768 SCTAB nEndTab = rRange.aEnd.Tab(); 1769 1770 if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) ) 1771 { 1772 DBG_ERROR("invalid row in DeleteCells"); 1773 return sal_False; 1774 } 1775 1776 ScDocument* pDoc = rDocShell.GetDocument(); 1777 SCTAB nTabCount = pDoc->GetTableCount(); 1778 SCCOL nPaintStartX = nStartCol; 1779 SCROW nPaintStartY = nStartRow; 1780 SCCOL nPaintEndX = nEndCol; 1781 SCROW nPaintEndY = nEndRow; 1782 sal_uInt16 nPaintFlags = PAINT_GRID; 1783 SCTAB i; 1784 1785 if (bRecord && !pDoc->IsUndoEnabled()) 1786 bRecord = sal_False; 1787 1788 ScMarkData aMark; 1789 if (pTabMark) 1790 aMark = *pTabMark; 1791 else 1792 { 1793 SCTAB nCount = 0; 1794 for( i=0; i<nTabCount; i++ ) 1795 { 1796 if( !pDoc->IsScenario(i) ) 1797 { 1798 nCount++; 1799 if( nCount == nEndTab+1 ) 1800 { 1801 aMark.SelectTable( i, sal_True ); 1802 break; 1803 } 1804 } 1805 } 1806 } 1807 1808 ScMarkData aFullMark( aMark ); // including scenario sheets 1809 for( i=0; i<nTabCount; i++ ) 1810 if( aMark.GetTableSelect( i ) ) 1811 { 1812 for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) 1813 aFullMark.SelectTable( j, sal_True ); 1814 } 1815 1816 SCTAB nSelCount = aMark.GetSelectCount(); 1817 1818 SCCOL nUndoStartX = nStartCol; 1819 SCROW nUndoStartY = nStartRow; 1820 SCCOL nUndoEndX = nEndCol; 1821 SCROW nUndoEndY = nEndRow; 1822 1823 ScRange aExtendMergeRange( rRange ); 1824 1825 if( rRange.aStart == rRange.aEnd && pDoc->HasAttrib(rRange, HASATTR_MERGED) ) 1826 { 1827 pDoc->ExtendMerge( aExtendMergeRange ); 1828 pDoc->ExtendOverlapped( aExtendMergeRange ); 1829 nUndoEndX = aExtendMergeRange.aEnd.Col(); 1830 nUndoEndY = aExtendMergeRange.aEnd.Row(); 1831 nPaintEndX = nUndoEndX; 1832 nPaintEndY = nUndoEndY; 1833 } 1834 1835 if (eCmd==DEL_DELROWS) 1836 { 1837 nUndoStartX = 0; 1838 nUndoEndX = MAXCOL; 1839 } 1840 if (eCmd==DEL_DELCOLS) 1841 { 1842 nUndoStartY = 0; 1843 nUndoEndY = MAXROW; 1844 } 1845 // Test Zellschutz 1846 1847 SCCOL nEditTestEndX = nUndoEndX; 1848 if ( eCmd==DEL_DELCOLS || eCmd==DEL_CELLSLEFT ) 1849 nEditTestEndX = MAXCOL; 1850 SCROW nEditTestEndY = nUndoEndY; 1851 if ( eCmd==DEL_DELROWS || eCmd==DEL_CELLSUP ) 1852 nEditTestEndY = MAXROW; 1853 ScEditableTester aTester( pDoc, nUndoStartX, nUndoStartY, nEditTestEndX, nEditTestEndY, aMark ); 1854 if (!aTester.IsEditable()) 1855 { 1856 if (!bApi) 1857 rDocShell.ErrorMessage(aTester.GetMessageId()); 1858 return sal_False; 1859 } 1860 1861 // Test zusammengefasste 1862 1863 SCCOL nMergeTestEndX = (eCmd==DEL_CELLSLEFT) ? MAXCOL : nUndoEndX; 1864 SCROW nMergeTestEndY = (eCmd==DEL_CELLSUP) ? MAXROW : nUndoEndY; 1865 SCCOL nExtendStartCol = nUndoStartX; 1866 SCROW nExtendStartRow = nUndoStartY; 1867 sal_Bool bNeedRefresh = sal_False; 1868 1869 //Issue 8302 want to be able to insert into the middle of merged cells 1870 //the patch comes from maoyg 1871 ::std::vector<ScRange> qDecreaseRange; 1872 sal_Bool bDeletingMerge = sal_False; 1873 String aUndo = ScGlobal::GetRscString( STR_UNDO_DELETECELLS ); 1874 if (bRecord) 1875 rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo ); 1876 1877 for( i=0; i<nTabCount; i++ ) 1878 { 1879 if( aMark.GetTableSelect(i) ) 1880 { 1881 if ( pDoc->HasAttrib( nUndoStartX, nUndoStartY, i, nMergeTestEndX, nMergeTestEndY, i, HASATTR_MERGED | HASATTR_OVERLAPPED )) 1882 { 1883 SCCOL nMergeStartX = nUndoStartX; 1884 SCROW nMergeStartY = nUndoStartY; 1885 SCCOL nMergeEndX = nMergeTestEndX; 1886 SCROW nMergeEndY = nMergeTestEndY; 1887 1888 pDoc->ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i ); 1889 pDoc->ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i ); 1890 if( ( eCmd == DEL_CELLSUP && ( nMergeStartX != nUndoStartX || nMergeEndX != nMergeTestEndX))|| 1891 ( eCmd == DEL_CELLSLEFT && ( nMergeStartY != nUndoStartY || nMergeEndY != nMergeTestEndY))) 1892 { 1893 if (!bApi) 1894 rDocShell.ErrorMessage(STR_MSSG_DELETECELLS_0); 1895 rDocShell.GetUndoManager()->LeaveListAction(); 1896 return sal_False; 1897 } 1898 1899 nExtendStartCol = nMergeStartX; 1900 nExtendStartRow = nMergeStartY; 1901 SCCOL nTestCol = -1; 1902 SCROW nTestRow1 = -1; 1903 SCROW nTestRow2 = -1; 1904 1905 ScDocAttrIterator aTestIter( pDoc, i, nUndoStartX, nUndoStartY, nMergeTestEndX, nMergeTestEndY ); 1906 ScRange aExtendRange( nUndoStartX, nUndoStartY, i, nMergeTestEndX, nMergeTestEndY, i ); 1907 const ScPatternAttr* pPattern = NULL; 1908 const ScMergeAttr* pMergeFlag = NULL; 1909 const ScMergeFlagAttr* pMergeFlagAttr = NULL; 1910 while ( ( pPattern = aTestIter.GetNext( nTestCol, nTestRow1, nTestRow2 ) ) != NULL ) 1911 { 1912 pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem( ATTR_MERGE ); 1913 pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem( ATTR_MERGE_FLAG ); 1914 sal_Int16 nNewFlags = pMergeFlagAttr->GetValue() & ( SC_MF_HOR | SC_MF_VER ); 1915 if( ( pMergeFlag && pMergeFlag->IsMerged() ) || nNewFlags == SC_MF_HOR || nNewFlags == SC_MF_VER ) 1916 { 1917 ScRange aRange( nTestCol, nTestRow1, i ); 1918 pDoc->ExtendOverlapped( aRange ); 1919 pDoc->ExtendMerge( aRange, sal_True, sal_True ); 1920 1921 if( nTestRow1 < nTestRow2 && nNewFlags == SC_MF_HOR ) 1922 { 1923 for( SCROW nTestRow = nTestRow1; nTestRow <= nTestRow2; nTestRow++ ) 1924 { 1925 ScRange aTestRange( nTestCol, nTestRow, i ); 1926 pDoc->ExtendOverlapped( aTestRange ); 1927 pDoc->ExtendMerge( aTestRange, sal_True, sal_True); 1928 ScRange aMergeRange( aTestRange.aStart.Col(),aTestRange.aStart.Row(), i ); 1929 if( !aExtendRange.In( aMergeRange ) ) 1930 { 1931 qDecreaseRange.push_back( aTestRange ); 1932 bDeletingMerge = sal_True; 1933 } 1934 } 1935 } 1936 else 1937 { 1938 ScRange aMergeRange( aRange.aStart.Col(),aRange.aStart.Row(), i ); 1939 if( !aExtendRange.In( aMergeRange ) ) 1940 { 1941 qDecreaseRange.push_back( aRange ); 1942 } 1943 bDeletingMerge = sal_True; 1944 } 1945 } 1946 } 1947 1948 if( bDeletingMerge ) 1949 { 1950 1951 if( eCmd == DEL_DELROWS || eCmd == DEL_CELLSUP ) 1952 { 1953 nStartRow = aExtendMergeRange.aStart.Row(); 1954 nEndRow = aExtendMergeRange.aEnd.Row(); 1955 bNeedRefresh = sal_True; 1956 1957 if( eCmd == DEL_CELLSUP ) 1958 { 1959 nEndCol = aExtendMergeRange.aEnd.Col(); 1960 } 1961 else 1962 { 1963 nStartCol = 0; 1964 nEndCol = MAXCOL; 1965 } 1966 } 1967 else if( eCmd == DEL_CELLSLEFT || eCmd == DEL_DELCOLS ) 1968 { 1969 1970 nStartCol = aExtendMergeRange.aStart.Col(); 1971 nEndCol = aExtendMergeRange.aEnd.Col(); 1972 if( eCmd == DEL_CELLSLEFT ) 1973 { 1974 nEndRow = aExtendMergeRange.aEnd.Row(); 1975 bNeedRefresh = sal_True; 1976 } 1977 else 1978 { 1979 nStartRow = 0; 1980 nEndRow = MAXROW; 1981 } 1982 } 1983 1984 if( !qDecreaseRange.empty() ) 1985 { 1986 for( ::std::vector<ScRange>::const_iterator iIter( qDecreaseRange.begin()); iIter != qDecreaseRange.end(); iIter++ ) 1987 { 1988 ScRange aRange( *iIter ); 1989 if( pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) ) 1990 { 1991 UnmergeCells( aRange, sal_True, sal_True ); 1992 } 1993 } 1994 } 1995 } 1996 else 1997 { 1998 if (!bApi) 1999 rDocShell.ErrorMessage(STR_MSSG_DELETECELLS_0); 2000 rDocShell.GetUndoManager()->LeaveListAction(); 2001 return sal_False; 2002 } 2003 } 2004 } 2005 } 2006 2007 // 2008 // ausfuehren 2009 // 2010 2011 WaitObject aWait( rDocShell.GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference 2012 2013 ScDocument* pUndoDoc = NULL; 2014 ScDocument* pRefUndoDoc = NULL; 2015 ScRefUndoData* pUndoData = NULL; 2016 if ( bRecord ) 2017 { 2018 // With the fix for #101329#, UpdateRef always puts cells into pRefUndoDoc at their old position, 2019 // so it's no longer necessary to copy more than the deleted range into pUndoDoc. 2020 2021 pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 2022 pUndoDoc->InitUndo( pDoc, 0, nTabCount-1, (eCmd==DEL_DELCOLS), (eCmd==DEL_DELROWS) ); 2023 for( i=0; i<nTabCount; i++ ) 2024 { 2025 if( aMark.GetTableSelect( i ) ) 2026 { 2027 SCTAB nScenarioCount = 0; 2028 2029 for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) 2030 nScenarioCount ++; 2031 2032 pDoc->CopyToDocument( nUndoStartX, nUndoStartY, i, nUndoEndX, nUndoEndY, i+nScenarioCount, 2033 IDF_ALL | IDF_NOCAPTIONS, sal_False, pUndoDoc ); 2034 } 2035 } 2036 2037 pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 2038 pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, sal_False, sal_False ); 2039 2040 pUndoData = new ScRefUndoData( pDoc ); 2041 2042 pDoc->BeginDrawUndo(); 2043 } 2044 2045 sal_uInt16 nExtFlags = 0; 2046 for( i=0; i<nTabCount; i++ ) 2047 { 2048 if( aMark.GetTableSelect( i ) ) 2049 rDocShell.UpdatePaintExt( nExtFlags, nStartCol, nStartRow, i, nEndCol, nEndRow, i ); 2050 } 2051 2052 sal_Bool bUndoOutline = sal_False; 2053 switch (eCmd) 2054 { 2055 case DEL_CELLSUP: 2056 pDoc->DeleteRow( nStartCol, 0, nEndCol, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, NULL, &aFullMark ); 2057 nPaintEndY = MAXROW; 2058 break; 2059 case DEL_DELROWS: 2060 pDoc->DeleteRow( 0, 0, MAXCOL, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &bUndoOutline, &aFullMark ); 2061 nPaintStartX = 0; 2062 nPaintEndX = MAXCOL; 2063 nPaintEndY = MAXROW; 2064 nPaintFlags |= PAINT_LEFT; 2065 break; 2066 case DEL_CELLSLEFT: 2067 pDoc->DeleteCol( nStartRow, 0, nEndRow, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, NULL, &aFullMark ); 2068 nPaintEndX = MAXCOL; 2069 break; 2070 case DEL_DELCOLS: 2071 pDoc->DeleteCol( 0, 0, MAXROW, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &bUndoOutline, &aFullMark ); 2072 nPaintStartY = 0; 2073 nPaintEndY = MAXROW; 2074 nPaintEndX = MAXCOL; 2075 nPaintFlags |= PAINT_TOP; 2076 break; 2077 default: 2078 DBG_ERROR("Falscher Code beim Loeschen"); 2079 break; 2080 } 2081 2082 //! Test, ob Outline in Groesse geaendert 2083 2084 if ( bRecord ) 2085 { 2086 for( i=0; i<nTabCount; i++ ) 2087 if( aFullMark.GetTableSelect( i ) ) 2088 pRefUndoDoc->DeleteAreaTab(nUndoStartX,nUndoStartY,nUndoEndX,nUndoEndY, i, IDF_ALL); 2089 2090 // alle Tabellen anlegen, damit Formeln kopiert werden koennen: 2091 pUndoDoc->AddUndoTab( 0, nTabCount-1, sal_False, sal_False ); 2092 2093 // kopieren mit bColRowFlags=sal_False (#54194#) 2094 pRefUndoDoc->CopyToDocument(0,0,0,MAXCOL,MAXROW,MAXTAB,IDF_FORMULA,sal_False,pUndoDoc,NULL,sal_False); 2095 delete pRefUndoDoc; 2096 2097 SCTAB* pTabs = new SCTAB[nSelCount]; 2098 SCTAB* pScenarios = new SCTAB[nSelCount]; 2099 SCTAB nUndoPos = 0; 2100 2101 for( i=0; i<nTabCount; i++ ) 2102 { 2103 if( aMark.GetTableSelect( i ) ) 2104 { 2105 SCTAB nCount = 0; 2106 for( SCTAB j=i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) 2107 nCount ++; 2108 2109 pScenarios[nUndoPos] = nCount; 2110 pTabs[nUndoPos] = i; 2111 nUndoPos ++; 2112 } 2113 } 2114 2115 if( !bDeletingMerge ) 2116 { 2117 rDocShell.GetUndoManager()->LeaveListAction(); 2118 } 2119 2120 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoDeleteCells( 2121 &rDocShell, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ),nUndoPos, pTabs, pScenarios, 2122 eCmd, pUndoDoc, pUndoData ) ); 2123 } 2124 2125 // #i8302 want to be able to insert into the middle of merged cells 2126 // the patch comes from maoyg 2127 2128 while( !qDecreaseRange.empty() ) 2129 { 2130 ScRange aRange = qDecreaseRange.back(); 2131 2132 long nDecreaseRowCount = 0; 2133 long nDecreaseColCount = 0; 2134 if( eCmd == DEL_CELLSUP || eCmd == DEL_DELROWS ) 2135 { 2136 if( nStartRow >= aRange.aStart.Row() && nStartRow <= aRange.aEnd.Row() && nEndRow>= aRange.aStart.Row() && nEndRow <= aRange.aEnd.Row() ) 2137 nDecreaseRowCount = nEndRow-nStartRow+1; 2138 else if( nStartRow >= aRange.aStart.Row() && nStartRow <= aRange.aEnd.Row() && nEndRow >= aRange.aStart.Row() && nEndRow >= aRange.aEnd.Row() ) 2139 nDecreaseRowCount = aRange.aEnd.Row()-nStartRow+1; 2140 else if( nStartRow >= aRange.aStart.Row() && nStartRow >= aRange.aEnd.Row() && nEndRow>= aRange.aStart.Row() && nEndRow <= aRange.aEnd.Row() ) 2141 nDecreaseRowCount = aRange.aEnd.Row()-nEndRow+1; 2142 } 2143 else if( eCmd == DEL_CELLSLEFT || eCmd == DEL_DELCOLS ) 2144 { 2145 if( nStartCol >= aRange.aStart.Col() && nStartCol <= aRange.aEnd.Col() && nEndCol>= aRange.aStart.Col() && nEndCol <= aRange.aEnd.Col() ) 2146 nDecreaseColCount = nEndCol-nStartCol+1; 2147 else if( nStartCol >= aRange.aStart.Col() && nStartCol <= aRange.aEnd.Col() && nEndCol >= aRange.aStart.Col() && nEndCol >= aRange.aEnd.Col() ) 2148 nDecreaseColCount = aRange.aEnd.Col()-nStartCol+1; 2149 else if( nStartCol >= aRange.aStart.Col() && nStartCol >= aRange.aEnd.Col() && nEndCol>= aRange.aStart.Col() && nEndCol <= aRange.aEnd.Col() ) 2150 nDecreaseColCount = aRange.aEnd.Col()-nEndCol+1; 2151 } 2152 2153 switch (eCmd) 2154 { 2155 case DEL_CELLSUP: 2156 case DEL_DELROWS: 2157 aRange.aEnd.SetRow(static_cast<SCsCOL>( aRange.aEnd.Row()-nDecreaseRowCount)); 2158 break; 2159 case DEL_CELLSLEFT: 2160 case DEL_DELCOLS: 2161 aRange.aEnd.SetCol(static_cast<SCsCOL>( aRange.aEnd.Col()-nDecreaseColCount)); 2162 break; 2163 default: 2164 break; 2165 } 2166 2167 if( !pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) ) 2168 { 2169 MergeCells( aRange, sal_False, sal_True, sal_True ); 2170 } 2171 qDecreaseRange.pop_back(); 2172 } 2173 2174 if( bDeletingMerge ) 2175 rDocShell.GetUndoManager()->LeaveListAction(); 2176 2177 if ( bNeedRefresh ) 2178 { 2179 // #i51445# old merge flag attributes must be deleted also for single cells, 2180 // not only for whole columns/rows 2181 2182 if ( eCmd==DEL_DELCOLS || eCmd==DEL_CELLSLEFT ) 2183 nMergeTestEndX = MAXCOL; 2184 if ( eCmd==DEL_DELROWS || eCmd==DEL_CELLSUP ) 2185 nMergeTestEndY = MAXROW; 2186 ScPatternAttr aPattern( pDoc->GetPool() ); 2187 aPattern.GetItemSet().Put( ScMergeFlagAttr() ); 2188 2189 pDoc->ApplyPatternArea( nExtendStartCol, nExtendStartRow, nMergeTestEndX, nMergeTestEndY, aMark, aPattern ); 2190 2191 for( i=0; i<nTabCount; i++ ) 2192 { 2193 if( aMark.GetTableSelect( i ) ) 2194 { 2195 SCTAB nScenarioCount = 0; 2196 2197 for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) 2198 nScenarioCount ++; 2199 2200 ScRange aMergedRange( nExtendStartCol, nExtendStartRow, i, nMergeTestEndX, nMergeTestEndY, i+nScenarioCount ); 2201 pDoc->ExtendMerge( aMergedRange, sal_True ); 2202 } 2203 } 2204 } 2205 2206 for( i=0; i<nTabCount; i++ ) 2207 { 2208 if( aMark.GetTableSelect( i ) ) 2209 { 2210 if ( eCmd == DEL_DELCOLS || eCmd == DEL_DELROWS ) 2211 pDoc->UpdatePageBreaks( i ); 2212 2213 rDocShell.UpdatePaintExt( nExtFlags, nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i ); 2214 2215 SCTAB nScenarioCount = 0; 2216 2217 for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) 2218 nScenarioCount ++; 2219 2220 // ganze Zeilen loeschen: nichts anpassen 2221 if ( eCmd == DEL_DELROWS || !AdjustRowHeight(ScRange( 0, nPaintStartY, i, MAXCOL, nPaintEndY, i+nScenarioCount )) ) 2222 rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, nPaintFlags, nExtFlags ); 2223 else 2224 { 2225 // paint only what is not done by AdjustRowHeight 2226 if (nExtFlags & SC_PF_LINES) 2227 lcl_PaintAbove( rDocShell, ScRange( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount) ); 2228 if (nPaintFlags & PAINT_TOP) 2229 rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, PAINT_TOP ); 2230 } 2231 } 2232 } 2233 aModificator.SetDocumentModified(); 2234 2235 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); 2236 2237 return sal_True; 2238 } 2239 2240 sal_Bool ScDocFunc::MoveBlock( const ScRange& rSource, const ScAddress& rDestPos, 2241 sal_Bool bCut, sal_Bool bRecord, sal_Bool bPaint, sal_Bool bApi ) 2242 { 2243 ScDocShellModificator aModificator( rDocShell ); 2244 2245 SCCOL nStartCol = rSource.aStart.Col(); 2246 SCROW nStartRow = rSource.aStart.Row(); 2247 SCTAB nStartTab = rSource.aStart.Tab(); 2248 SCCOL nEndCol = rSource.aEnd.Col(); 2249 SCROW nEndRow = rSource.aEnd.Row(); 2250 SCTAB nEndTab = rSource.aEnd.Tab(); 2251 SCCOL nDestCol = rDestPos.Col(); 2252 SCROW nDestRow = rDestPos.Row(); 2253 SCTAB nDestTab = rDestPos.Tab(); 2254 2255 if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) || !ValidRow(nDestRow) ) 2256 { 2257 DBG_ERROR("invalid row in MoveBlock"); 2258 return sal_False; 2259 } 2260 2261 // zugehoerige Szenarien auch anpassen - nur wenn innerhalb einer Tabelle verschoben wird! 2262 sal_Bool bScenariosAdded = sal_False; 2263 ScDocument* pDoc = rDocShell.GetDocument(); 2264 if (bRecord && !pDoc->IsUndoEnabled()) 2265 bRecord = sal_False; 2266 2267 SCTAB nTabCount = pDoc->GetTableCount(); 2268 if ( nDestTab == nStartTab && !pDoc->IsScenario(nEndTab) ) 2269 while ( nEndTab+1 < nTabCount && pDoc->IsScenario(nEndTab+1) ) 2270 { 2271 ++nEndTab; 2272 bScenariosAdded = sal_True; 2273 } 2274 2275 SCTAB nSrcTabCount = nEndTab-nStartTab+1; 2276 SCTAB nDestEndTab = nDestTab+nSrcTabCount-1; 2277 SCTAB nTab; 2278 2279 ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP ); 2280 2281 ScMarkData aSourceMark; 2282 for (nTab=nStartTab; nTab<=nEndTab; nTab++) 2283 aSourceMark.SelectTable( nTab, sal_True ); // Source selektieren 2284 aSourceMark.SetMarkArea( rSource ); 2285 2286 ScDocShellRef aDragShellRef; 2287 if ( pDoc->HasOLEObjectsInArea( rSource ) ) 2288 { 2289 aDragShellRef = new ScDocShell; // DocShell needs a Ref immediately 2290 aDragShellRef->DoInitNew(NULL); 2291 } 2292 ScDrawLayer::SetGlobalDrawPersist(aDragShellRef); 2293 2294 ScClipParam aClipParam(ScRange(nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nStartTab), bCut); 2295 pDoc->CopyToClip(aClipParam, pClipDoc, &aSourceMark, false, bScenariosAdded, true); 2296 2297 ScDrawLayer::SetGlobalDrawPersist(NULL); 2298 2299 SCCOL nOldEndCol = nEndCol; 2300 SCROW nOldEndRow = nEndRow; 2301 sal_Bool bClipOver = sal_False; 2302 for (nTab=nStartTab; nTab<=nEndTab; nTab++) 2303 { 2304 SCCOL nTmpEndCol = nOldEndCol; 2305 SCROW nTmpEndRow = nOldEndRow; 2306 if (pDoc->ExtendMerge( nStartCol, nStartRow, nTmpEndCol, nTmpEndRow, nTab )) 2307 bClipOver = sal_True; 2308 if ( nTmpEndCol > nEndCol ) nEndCol = nTmpEndCol; 2309 if ( nTmpEndRow > nEndRow ) nEndRow = nTmpEndRow; 2310 } 2311 2312 SCCOL nDestEndCol = nDestCol + ( nOldEndCol-nStartCol ); 2313 SCROW nDestEndRow = nDestRow + ( nOldEndRow-nStartRow ); 2314 2315 SCCOL nUndoEndCol = nDestCol + ( nEndCol-nStartCol ); // erweitert im Zielblock 2316 SCROW nUndoEndRow = nDestRow + ( nEndRow-nStartRow ); 2317 2318 sal_Bool bIncludeFiltered = bCut; 2319 if ( !bIncludeFiltered ) 2320 { 2321 // adjust sizes to include only non-filtered rows 2322 2323 SCCOL nClipX; 2324 SCROW nClipY; 2325 pClipDoc->GetClipArea( nClipX, nClipY, sal_False ); 2326 SCROW nUndoAdd = nUndoEndRow - nDestEndRow; 2327 nDestEndRow = nDestRow + nClipY; 2328 nUndoEndRow = nDestEndRow + nUndoAdd; 2329 } 2330 2331 if (!ValidCol(nUndoEndCol) || !ValidRow(nUndoEndRow)) 2332 { 2333 if (!bApi) 2334 rDocShell.ErrorMessage(STR_PASTE_FULL); 2335 delete pClipDoc; 2336 return sal_False; 2337 } 2338 2339 // Test auf Zellschutz 2340 2341 ScEditableTester aTester; 2342 for (nTab=nDestTab; nTab<=nDestEndTab; nTab++) 2343 aTester.TestBlock( pDoc, nTab, nDestCol,nDestRow, nUndoEndCol,nUndoEndRow ); 2344 if (bCut) 2345 for (nTab=nStartTab; nTab<=nEndTab; nTab++) 2346 aTester.TestBlock( pDoc, nTab, nStartCol,nStartRow, nEndCol,nEndRow ); 2347 2348 if (!aTester.IsEditable()) 2349 { 2350 if (!bApi) 2351 rDocShell.ErrorMessage(aTester.GetMessageId()); 2352 delete pClipDoc; 2353 return sal_False; 2354 } 2355 2356 // Test auf zusammengefasste - beim Verschieben erst nach dem Loeschen 2357 2358 if (bClipOver && !bCut) 2359 if (pDoc->HasAttrib( nDestCol,nDestRow,nDestTab, nUndoEndCol,nUndoEndRow,nDestEndTab, 2360 HASATTR_MERGED | HASATTR_OVERLAPPED )) 2361 { // "Zusammenfassen nicht verschachteln !" 2362 if (!bApi) 2363 rDocShell.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0); 2364 delete pClipDoc; 2365 return sal_False; 2366 } 2367 2368 // Are there borders in the cells? (for painting) 2369 2370 sal_uInt16 nSourceExt = 0; 2371 rDocShell.UpdatePaintExt( nSourceExt, nStartCol,nStartRow,nStartTab, nEndCol,nEndRow,nEndTab ); 2372 sal_uInt16 nDestExt = 0; 2373 rDocShell.UpdatePaintExt( nDestExt, nDestCol,nDestRow,nDestTab, nDestEndCol,nDestEndRow,nDestEndTab ); 2374 2375 // 2376 // ausfuehren 2377 // 2378 2379 ScDocument* pUndoDoc = NULL; 2380 ScDocument* pRefUndoDoc = NULL; 2381 ScRefUndoData* pUndoData = NULL; 2382 if (bRecord) 2383 { 2384 sal_Bool bWholeCols = ( nStartRow == 0 && nEndRow == MAXROW ); 2385 sal_Bool bWholeRows = ( nStartCol == 0 && nEndCol == MAXCOL ); 2386 sal_uInt16 nUndoFlags = (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS; 2387 2388 pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 2389 pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab, bWholeCols, bWholeRows ); 2390 2391 if (bCut) 2392 { 2393 pDoc->CopyToDocument( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab, 2394 nUndoFlags, sal_False, pUndoDoc ); 2395 pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 2396 pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, sal_False, sal_False ); 2397 } 2398 2399 if ( nDestTab != nStartTab ) 2400 pUndoDoc->AddUndoTab( nDestTab, nDestEndTab, bWholeCols, bWholeRows ); 2401 pDoc->CopyToDocument( nDestCol, nDestRow, nDestTab, 2402 nDestEndCol, nDestEndRow, nDestEndTab, 2403 nUndoFlags, sal_False, pUndoDoc ); 2404 2405 pUndoData = new ScRefUndoData( pDoc ); 2406 2407 pDoc->BeginDrawUndo(); 2408 } 2409 2410 sal_Bool bSourceHeight = sal_False; // Hoehen angepasst? 2411 if (bCut) 2412 { 2413 ScMarkData aDelMark; // only for tables 2414 for (nTab=nStartTab; nTab<=nEndTab; nTab++) 2415 { 2416 pDoc->DeleteAreaTab( nStartCol,nStartRow, nOldEndCol,nOldEndRow, nTab, IDF_ALL ); 2417 aDelMark.SelectTable( nTab, sal_True ); 2418 } 2419 pDoc->DeleteObjectsInArea( nStartCol,nStartRow, nOldEndCol,nOldEndRow, aDelMark ); 2420 2421 // Test auf zusammengefasste 2422 2423 if (bClipOver) 2424 if (pDoc->HasAttrib( nDestCol,nDestRow,nDestTab, 2425 nUndoEndCol,nUndoEndRow,nDestEndTab, 2426 HASATTR_MERGED | HASATTR_OVERLAPPED )) 2427 { 2428 pDoc->CopyFromClip( rSource, aSourceMark, IDF_ALL, pRefUndoDoc, pClipDoc ); 2429 for (nTab=nStartTab; nTab<=nEndTab; nTab++) 2430 { 2431 SCCOL nTmpEndCol = nEndCol; 2432 SCROW nTmpEndRow = nEndRow; 2433 pDoc->ExtendMerge( nStartCol, nStartRow, nTmpEndCol, nTmpEndRow, nTab, sal_True ); 2434 } 2435 2436 // Fehlermeldung erst nach dem Wiederherstellen des Inhalts 2437 if (!bApi) // "Zusammenfassen nicht verschachteln !" 2438 rDocShell.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0); 2439 2440 delete pUndoDoc; 2441 delete pRefUndoDoc; 2442 delete pUndoData; 2443 delete pClipDoc; 2444 return sal_False; 2445 } 2446 2447 bSourceHeight = AdjustRowHeight( rSource, sal_False ); 2448 } 2449 2450 ScRange aPasteDest( nDestCol, nDestRow, nDestTab, nDestEndCol, nDestEndRow, nDestEndTab ); 2451 2452 ScMarkData aDestMark; 2453 for (nTab=nDestTab; nTab<=nDestEndTab; nTab++) 2454 aDestMark.SelectTable( nTab, sal_True ); // Destination selektieren 2455 aDestMark.SetMarkArea( aPasteDest ); 2456 2457 /* Do not copy cell notes and drawing objects here. While pasting, the 2458 function ScDocument::UpdateReference() is called which calls 2459 ScDrawLayer::MoveCells() which may move away inserted objects to wrong 2460 positions (e.g. if source and destination range overlaps). Cell notes 2461 and drawing objects are pasted below after doing all adjusting. */ 2462 pDoc->CopyFromClip( aPasteDest, aDestMark, IDF_ALL & ~(IDF_NOTE | IDF_OBJECTS), 2463 pRefUndoDoc, pClipDoc, sal_True, sal_False, bIncludeFiltered ); 2464 2465 // skipped rows and merged cells don't mix 2466 if ( !bIncludeFiltered && pClipDoc->HasClipFilteredRows() ) 2467 UnmergeCells( aPasteDest, sal_False, sal_True ); 2468 2469 VirtualDevice aVirtDev; 2470 sal_Bool bDestHeight = AdjustRowHeight( 2471 ScRange( 0,nDestRow,nDestTab, MAXCOL,nDestEndRow,nDestEndTab ), 2472 sal_False ); 2473 2474 /* Paste cell notes and drawing objects after adjusting formula references 2475 and row heights. There are no cell notes or drawing objects, if the 2476 clipdoc does not contain a drawing layer. 2477 #i102056# Passing IDF_NOTE only would overwrite cell contents with 2478 empty note cells, therefore the special modifier IDF_ADDNOTES is passed 2479 here too which changes the behaviour of ScColumn::CopyFromClip() to not 2480 touch existing cells. */ 2481 if ( pClipDoc->GetDrawLayer() ) 2482 pDoc->CopyFromClip( aPasteDest, aDestMark, IDF_NOTE | IDF_ADDNOTES | IDF_OBJECTS, 2483 pRefUndoDoc, pClipDoc, sal_True, sal_False, bIncludeFiltered ); 2484 2485 if (bRecord) 2486 { 2487 if (pRefUndoDoc) 2488 { 2489 // alle Tabellen anlegen, damit Formeln kopiert werden koennen: 2490 pUndoDoc->AddUndoTab( 0, nTabCount-1, sal_False, sal_False ); 2491 2492 pRefUndoDoc->DeleteArea( nDestCol, nDestRow, nDestEndCol, nDestEndRow, aSourceMark, IDF_ALL ); 2493 // kopieren mit bColRowFlags=sal_False (#54194#) 2494 pRefUndoDoc->CopyToDocument( 0, 0, 0, MAXCOL, MAXROW, MAXTAB, 2495 IDF_FORMULA, sal_False, pUndoDoc, NULL, sal_False ); 2496 delete pRefUndoDoc; 2497 } 2498 2499 rDocShell.GetUndoManager()->AddUndoAction( 2500 new ScUndoDragDrop( &rDocShell, ScRange( 2501 nStartCol, nStartRow, nStartTab, 2502 nOldEndCol, nOldEndRow, nEndTab ), 2503 ScAddress( nDestCol, nDestRow, nDestTab ), 2504 bCut, pUndoDoc, pUndoData, bScenariosAdded ) ); 2505 } 2506 2507 SCCOL nDestPaintEndCol = nDestEndCol; 2508 SCROW nDestPaintEndRow = nDestEndRow; 2509 for (nTab=nDestTab; nTab<=nDestEndTab; nTab++) 2510 { 2511 SCCOL nTmpEndCol = nDestEndCol; 2512 SCROW nTmpEndRow = nDestEndRow; 2513 pDoc->ExtendMerge( nDestCol, nDestRow, nTmpEndCol, nTmpEndRow, nTab, sal_True ); 2514 if (nTmpEndCol > nDestPaintEndCol) nDestPaintEndCol = nTmpEndCol; 2515 if (nTmpEndRow > nDestPaintEndRow) nDestPaintEndRow = nTmpEndRow; 2516 } 2517 2518 if (bCut) 2519 for (nTab=nStartTab; nTab<=nEndTab; nTab++) 2520 pDoc->RefreshAutoFilter( nStartCol, nStartRow, nEndCol, nEndRow, nTab ); 2521 2522 if (bPaint) 2523 { 2524 // Zielbereich: 2525 2526 SCCOL nPaintStartX = nDestCol; 2527 SCROW nPaintStartY = nDestRow; 2528 SCCOL nPaintEndX = nDestPaintEndCol; 2529 SCROW nPaintEndY = nDestPaintEndRow; 2530 sal_uInt16 nFlags = PAINT_GRID; 2531 2532 if ( nStartRow==0 && nEndRow==MAXROW ) // Breiten mitkopiert? 2533 { 2534 nPaintEndX = MAXCOL; 2535 nPaintStartY = 0; 2536 nPaintEndY = MAXROW; 2537 nFlags |= PAINT_TOP; 2538 } 2539 if ( bDestHeight || ( nStartCol == 0 && nEndCol == MAXCOL ) ) 2540 { 2541 nPaintEndY = MAXROW; 2542 nPaintStartX = 0; 2543 nPaintEndX = MAXCOL; 2544 nFlags |= PAINT_LEFT; 2545 } 2546 if ( bScenariosAdded ) 2547 { 2548 nPaintStartX = 0; 2549 nPaintStartY = 0; 2550 nPaintEndX = MAXCOL; 2551 nPaintEndY = MAXROW; 2552 } 2553 2554 rDocShell.PostPaint( nPaintStartX,nPaintStartY,nDestTab, 2555 nPaintEndX,nPaintEndY,nDestEndTab, nFlags, nSourceExt | nDestExt ); 2556 2557 if ( bCut ) 2558 { 2559 // Quellbereich: 2560 2561 nPaintStartX = nStartCol; 2562 nPaintStartY = nStartRow; 2563 nPaintEndX = nEndCol; 2564 nPaintEndY = nEndRow; 2565 nFlags = PAINT_GRID; 2566 2567 if ( bSourceHeight ) 2568 { 2569 nPaintEndY = MAXROW; 2570 nPaintStartX = 0; 2571 nPaintEndX = MAXCOL; 2572 nFlags |= PAINT_LEFT; 2573 } 2574 if ( bScenariosAdded ) 2575 { 2576 nPaintStartX = 0; 2577 nPaintStartY = 0; 2578 nPaintEndX = MAXCOL; 2579 nPaintEndY = MAXROW; 2580 } 2581 2582 rDocShell.PostPaint( nPaintStartX,nPaintStartY,nStartTab, 2583 nPaintEndX,nPaintEndY,nEndTab, nFlags, nSourceExt ); 2584 } 2585 } 2586 2587 aModificator.SetDocumentModified(); 2588 2589 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); 2590 2591 delete pClipDoc; 2592 return sal_True; 2593 } 2594 2595 //------------------------------------------------------------------------ 2596 uno::Reference< uno::XInterface > GetDocModuleObject( SfxObjectShell& rDocSh, String& sCodeName ) 2597 { 2598 uno::Reference< lang::XMultiServiceFactory> xSF(rDocSh.GetModel(), uno::UNO_QUERY); 2599 uno::Reference< container::XNameAccess > xVBACodeNamedObjectAccess; 2600 uno::Reference< uno::XInterface > xDocModuleApiObject; 2601 if ( xSF.is() ) 2602 { 2603 xVBACodeNamedObjectAccess.set( xSF->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAObjectModuleObjectProvider"))), uno::UNO_QUERY ); 2604 xDocModuleApiObject.set( xVBACodeNamedObjectAccess->getByName( sCodeName ), uno::UNO_QUERY ); 2605 } 2606 return xDocModuleApiObject; 2607 2608 } 2609 2610 script::ModuleInfo lcl_InitModuleInfo( SfxObjectShell& rDocSh, String& sModule ) 2611 { 2612 script::ModuleInfo sModuleInfo; 2613 sModuleInfo.ModuleType = script::ModuleType::DOCUMENT; 2614 sModuleInfo.ModuleObject = GetDocModuleObject( rDocSh, sModule ); 2615 return sModuleInfo; 2616 } 2617 2618 void VBA_InsertModule( ScDocument& rDoc, SCTAB nTab, String& sModuleName, String& sSource ) 2619 { 2620 SfxObjectShell& rDocSh = *rDoc.GetDocumentShell(); 2621 uno::Reference< script::XLibraryContainer > xLibContainer = rDocSh.GetBasicContainer(); 2622 DBG_ASSERT( xLibContainer.is(), "No BasicContainer!" ); 2623 2624 uno::Reference< container::XNameContainer > xLib; 2625 if( xLibContainer.is() ) 2626 { 2627 String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) ); 2628 if ( rDocSh.GetBasicManager() && rDocSh.GetBasicManager()->GetName().Len() ) 2629 aLibName = rDocSh.GetBasicManager()->GetName(); 2630 uno::Any aLibAny = xLibContainer->getByName( aLibName ); 2631 aLibAny >>= xLib; 2632 } 2633 if( xLib.is() ) 2634 { 2635 // if the Module with codename exists then find a new name 2636 sal_Int32 nNum = 0; 2637 String genModuleName; 2638 if ( sModuleName.Len() ) 2639 sModuleName = sModuleName; 2640 else 2641 { 2642 genModuleName = String::CreateFromAscii( "Sheet1" ); 2643 nNum = 1; 2644 } 2645 while( xLib->hasByName( genModuleName ) ) 2646 genModuleName = rtl::OUString::createFromAscii( "Sheet" ) + rtl::OUString::valueOf( ++nNum ); 2647 2648 uno::Any aSourceAny; 2649 rtl::OUString sTmpSource = sSource; 2650 if ( sTmpSource.getLength() == 0 ) 2651 sTmpSource = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Rem Attribute VBA_ModuleType=VBADocumentModule\nOption VBASupport 1\n" )); 2652 aSourceAny <<= sTmpSource; 2653 uno::Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, uno::UNO_QUERY ); 2654 if ( xVBAModuleInfo.is() ) 2655 { 2656 rDoc.SetCodeName( nTab, genModuleName ); 2657 script::ModuleInfo sModuleInfo = lcl_InitModuleInfo( rDocSh, genModuleName ); 2658 xVBAModuleInfo->insertModuleInfo( genModuleName, sModuleInfo ); 2659 xLib->insertByName( genModuleName, aSourceAny ); 2660 } 2661 2662 } 2663 } 2664 2665 void VBA_DeleteModule( ScDocShell& rDocSh, String& sModuleName ) 2666 { 2667 uno::Reference< script::XLibraryContainer > xLibContainer = rDocSh.GetBasicContainer(); 2668 DBG_ASSERT( xLibContainer.is(), "No BasicContainer!" ); 2669 2670 uno::Reference< container::XNameContainer > xLib; 2671 if( xLibContainer.is() ) 2672 { 2673 String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) ); 2674 if ( rDocSh.GetBasicManager() && rDocSh.GetBasicManager()->GetName().Len() ) 2675 aLibName = rDocSh.GetBasicManager()->GetName(); 2676 uno::Any aLibAny = xLibContainer->getByName( aLibName ); 2677 aLibAny >>= xLib; 2678 } 2679 if( xLib.is() ) 2680 { 2681 uno::Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, uno::UNO_QUERY ); 2682 if( xLib->hasByName( sModuleName ) ) 2683 xLib->removeByName( sModuleName ); 2684 if ( xVBAModuleInfo.is() ) 2685 xVBAModuleInfo->removeModuleInfo( sModuleName ); 2686 2687 } 2688 } 2689 2690 2691 sal_Bool ScDocFunc::InsertTable( SCTAB nTab, const String& rName, sal_Bool bRecord, sal_Bool bApi ) 2692 { 2693 sal_Bool bSuccess = sal_False; 2694 WaitObject aWait( rDocShell.GetActiveDialogParent() ); 2695 2696 ScDocShellModificator aModificator( rDocShell ); 2697 2698 ScDocument* pDoc = rDocShell.GetDocument(); 2699 2700 2701 // Strange loop, also basic is loaded too early ( InsertTable ) 2702 // is called via the xml import for sheets in described in odf 2703 sal_Bool bInsertDocModule = false; 2704 2705 if( !rDocShell.GetDocument()->IsImportingXML() ) 2706 { 2707 bInsertDocModule = pDoc ? pDoc->IsInVBAMode() : false; 2708 } 2709 if ( bInsertDocModule || ( bRecord && !pDoc->IsUndoEnabled() ) ) 2710 bRecord = sal_False; 2711 2712 if (bRecord) 2713 pDoc->BeginDrawUndo(); // InsertTab erzeugt ein SdrUndoNewPage 2714 2715 SCTAB nTabCount = pDoc->GetTableCount(); 2716 sal_Bool bAppend = ( nTab >= nTabCount ); 2717 if ( bAppend ) 2718 nTab = nTabCount; // wichtig fuer Undo 2719 2720 if (pDoc->InsertTab( nTab, rName )) 2721 { 2722 String sCodeName; 2723 if (bRecord) 2724 rDocShell.GetUndoManager()->AddUndoAction( 2725 new ScUndoInsertTab( &rDocShell, nTab, bAppend, rName)); 2726 // Views updaten: 2727 // Only insert vba modules if vba mode ( and not currently importing XML ) 2728 if( bInsertDocModule ) 2729 { 2730 String sSource; 2731 VBA_InsertModule( *pDoc, nTab, sCodeName, sSource ); 2732 } 2733 rDocShell.Broadcast( ScTablesHint( SC_TAB_INSERTED, nTab ) ); 2734 2735 rDocShell.PostPaintExtras(); 2736 aModificator.SetDocumentModified(); 2737 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); 2738 bSuccess = sal_True; 2739 } 2740 else if (!bApi) 2741 rDocShell.ErrorMessage(STR_TABINSERT_ERROR); 2742 2743 return bSuccess; 2744 } 2745 2746 sal_Bool ScDocFunc::DeleteTable( SCTAB nTab, sal_Bool bRecord, sal_Bool /* bApi */ ) 2747 { 2748 WaitObject aWait( rDocShell.GetActiveDialogParent() ); 2749 2750 ScDocShellModificator aModificator( rDocShell ); 2751 2752 sal_Bool bSuccess = sal_False; 2753 ScDocument* pDoc = rDocShell.GetDocument(); 2754 sal_Bool bVbaEnabled = pDoc ? pDoc->IsInVBAMode() : false; 2755 if (bRecord && !pDoc->IsUndoEnabled()) 2756 bRecord = sal_False; 2757 if ( bVbaEnabled ) 2758 bRecord = sal_False; 2759 sal_Bool bWasLinked = pDoc->IsLinked(nTab); 2760 ScDocument* pUndoDoc = NULL; 2761 ScRefUndoData* pUndoData = NULL; 2762 if (bRecord) 2763 { 2764 pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 2765 SCTAB nCount = pDoc->GetTableCount(); 2766 2767 pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True ); // nur nTab mit Flags 2768 pUndoDoc->AddUndoTab( 0, nCount-1 ); // alle Tabs fuer Referenzen 2769 2770 pDoc->CopyToDocument(0,0,nTab, MAXCOL,MAXROW,nTab, IDF_ALL,sal_False, pUndoDoc ); 2771 String aOldName; 2772 pDoc->GetName( nTab, aOldName ); 2773 pUndoDoc->RenameTab( nTab, aOldName, sal_False ); 2774 if (bWasLinked) 2775 pUndoDoc->SetLink( nTab, pDoc->GetLinkMode(nTab), pDoc->GetLinkDoc(nTab), 2776 pDoc->GetLinkFlt(nTab), pDoc->GetLinkOpt(nTab), 2777 pDoc->GetLinkTab(nTab), 2778 pDoc->GetLinkRefreshDelay(nTab) ); 2779 2780 if ( pDoc->IsScenario(nTab) ) 2781 { 2782 pUndoDoc->SetScenario( nTab, sal_True ); 2783 String aComment; 2784 Color aColor; 2785 sal_uInt16 nScenFlags; 2786 pDoc->GetScenarioData( nTab, aComment, aColor, nScenFlags ); 2787 pUndoDoc->SetScenarioData( nTab, aComment, aColor, nScenFlags ); 2788 sal_Bool bActive = pDoc->IsActiveScenario( nTab ); 2789 pUndoDoc->SetActiveScenario( nTab, bActive ); 2790 } 2791 pUndoDoc->SetVisible( nTab, pDoc->IsVisible( nTab ) ); 2792 pUndoDoc->SetTabBgColor( nTab, pDoc->GetTabBgColor(nTab) ); 2793 pUndoDoc->SetSheetEvents( nTab, pDoc->GetSheetEvents( nTab ) ); 2794 2795 // Drawing-Layer muss sein Undo selbst in der Hand behalten !!! 2796 pDoc->BeginDrawUndo(); // DeleteTab erzeugt ein SdrUndoDelPage 2797 2798 pUndoData = new ScRefUndoData( pDoc ); 2799 } 2800 2801 String sCodeName; 2802 sal_Bool bHasCodeName = pDoc->GetCodeName( nTab, sCodeName ); 2803 if (pDoc->DeleteTab( nTab, pUndoDoc )) 2804 { 2805 if (bRecord) 2806 { 2807 SvShorts theTabs; 2808 theTabs.push_back(nTab); 2809 rDocShell.GetUndoManager()->AddUndoAction( 2810 new ScUndoDeleteTab( &rDocShell, theTabs, pUndoDoc, pUndoData )); 2811 } 2812 // Views updaten: 2813 if( bVbaEnabled ) 2814 { 2815 if( bHasCodeName ) 2816 { 2817 VBA_DeleteModule( rDocShell, sCodeName ); 2818 } 2819 } 2820 rDocShell.Broadcast( ScTablesHint( SC_TAB_DELETED, nTab ) ); 2821 2822 if (bWasLinked) 2823 { 2824 rDocShell.UpdateLinks(); // Link-Manager updaten 2825 SfxBindings* pBindings = rDocShell.GetViewBindings(); 2826 if (pBindings) 2827 pBindings->Invalidate(SID_LINKS); 2828 } 2829 2830 rDocShell.PostPaintExtras(); 2831 aModificator.SetDocumentModified(); 2832 2833 SfxApplication* pSfxApp = SFX_APP(); // Navigator 2834 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); 2835 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) ); 2836 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); 2837 2838 bSuccess = sal_True; 2839 } 2840 else 2841 { 2842 delete pUndoDoc; 2843 delete pUndoData; 2844 } 2845 return bSuccess; 2846 } 2847 2848 sal_Bool ScDocFunc::SetTableVisible( SCTAB nTab, sal_Bool bVisible, sal_Bool bApi ) 2849 { 2850 ScDocument* pDoc = rDocShell.GetDocument(); 2851 sal_Bool bUndo(pDoc->IsUndoEnabled()); 2852 if ( pDoc->IsVisible( nTab ) == bVisible ) 2853 return sal_True; // nichts zu tun - ok 2854 2855 if ( !pDoc->IsDocEditable() ) 2856 { 2857 if (!bApi) 2858 rDocShell.ErrorMessage(STR_PROTECTIONERR); 2859 return sal_False; 2860 } 2861 2862 ScDocShellModificator aModificator( rDocShell ); 2863 2864 if ( !bVisible && !pDoc->IsImportingXML() ) // #i57869# allow hiding in any order for loading 2865 { 2866 // nicht alle Tabellen ausblenden 2867 2868 sal_uInt16 nVisCount = 0; 2869 SCTAB nCount = pDoc->GetTableCount(); 2870 for (SCTAB i=0; i<nCount; i++) 2871 if (pDoc->IsVisible(i)) 2872 ++nVisCount; 2873 2874 if (nVisCount <= 1) 2875 { 2876 if (!bApi) 2877 rDocShell.ErrorMessage(STR_PROTECTIONERR); //! eigene Meldung? 2878 return sal_False; 2879 } 2880 } 2881 2882 pDoc->SetVisible( nTab, bVisible ); 2883 if (bUndo) 2884 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoShowHideTab( &rDocShell, nTab, bVisible ) ); 2885 2886 // Views updaten: 2887 if (!bVisible) 2888 rDocShell.Broadcast( ScTablesHint( SC_TAB_HIDDEN, nTab ) ); 2889 2890 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); 2891 rDocShell.PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS); 2892 aModificator.SetDocumentModified(); 2893 2894 return sal_True; 2895 } 2896 2897 sal_Bool ScDocFunc::SetLayoutRTL( SCTAB nTab, sal_Bool bRTL, sal_Bool /* bApi */ ) 2898 { 2899 ScDocument* pDoc = rDocShell.GetDocument(); 2900 sal_Bool bUndo(pDoc->IsUndoEnabled()); 2901 if ( pDoc->IsLayoutRTL( nTab ) == bRTL ) 2902 return sal_True; // nothing to do - ok 2903 2904 //! protection (sheet or document?) 2905 2906 ScDocShellModificator aModificator( rDocShell ); 2907 2908 pDoc->SetLayoutRTL( nTab, bRTL ); 2909 2910 if (bUndo) 2911 { 2912 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoLayoutRTL( &rDocShell, nTab, bRTL ) ); 2913 } 2914 2915 rDocShell.PostPaint( 0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_ALL ); 2916 aModificator.SetDocumentModified(); 2917 2918 SfxBindings* pBindings = rDocShell.GetViewBindings(); 2919 if (pBindings) 2920 { 2921 pBindings->Invalidate( FID_TAB_RTL ); 2922 pBindings->Invalidate( SID_ATTR_SIZE ); 2923 } 2924 2925 return sal_True; 2926 } 2927 2928 //UNUSED2009-05 sal_Bool ScDocFunc::SetGrammar( formula::FormulaGrammar::Grammar eGrammar ) 2929 //UNUSED2009-05 { 2930 //UNUSED2009-05 ScDocument* pDoc = rDocShell.GetDocument(); 2931 //UNUSED2009-05 2932 //UNUSED2009-05 if ( pDoc->GetGrammar() == eGrammar ) 2933 //UNUSED2009-05 return sal_True; 2934 //UNUSED2009-05 2935 //UNUSED2009-05 sal_Bool bUndo(pDoc->IsUndoEnabled()); 2936 //UNUSED2009-05 ScDocShellModificator aModificator( rDocShell ); 2937 //UNUSED2009-05 2938 //UNUSED2009-05 pDoc->SetGrammar( eGrammar ); 2939 //UNUSED2009-05 2940 //UNUSED2009-05 if (bUndo) 2941 //UNUSED2009-05 { 2942 //UNUSED2009-05 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoSetGrammar( &rDocShell, eGrammar ) ); 2943 //UNUSED2009-05 } 2944 //UNUSED2009-05 2945 //UNUSED2009-05 rDocShell.PostPaint( 0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_ALL ); 2946 //UNUSED2009-05 2947 //UNUSED2009-05 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell(); 2948 //UNUSED2009-05 if (NULL != pViewSh) 2949 //UNUSED2009-05 { 2950 //UNUSED2009-05 pViewSh->UpdateInputHandler( sal_False, sal_False ); 2951 //UNUSED2009-05 } 2952 //UNUSED2009-05 2953 //UNUSED2009-05 aModificator.SetDocumentModified(); 2954 //UNUSED2009-05 2955 //UNUSED2009-05 SfxBindings* pBindings = rDocShell.GetViewBindings(); 2956 //UNUSED2009-05 if (pBindings) 2957 //UNUSED2009-05 { 2958 //UNUSED2009-05 // erAck: 2006-09-07T22:19+0200 commented out in CWS scr1c1 2959 //UNUSED2009-05 //pBindings->Invalidate( FID_TAB_USE_R1C1 ); 2960 //UNUSED2009-05 } 2961 //UNUSED2009-05 2962 //UNUSED2009-05 return sal_True; 2963 //UNUSED2009-05 } 2964 2965 sal_Bool ScDocFunc::RenameTable( SCTAB nTab, const String& rName, sal_Bool bRecord, sal_Bool bApi ) 2966 { 2967 ScDocument* pDoc = rDocShell.GetDocument(); 2968 if (bRecord && !pDoc->IsUndoEnabled()) 2969 bRecord = sal_False; 2970 if ( !pDoc->IsDocEditable() ) 2971 { 2972 if (!bApi) 2973 rDocShell.ErrorMessage(STR_PROTECTIONERR); 2974 return sal_False; 2975 } 2976 2977 ScDocShellModificator aModificator( rDocShell ); 2978 2979 sal_Bool bSuccess = sal_False; 2980 String sOldName; 2981 pDoc->GetName(nTab, sOldName); 2982 if (pDoc->RenameTab( nTab, rName )) 2983 { 2984 if (bRecord) 2985 { 2986 rDocShell.GetUndoManager()->AddUndoAction( 2987 new ScUndoRenameTab( &rDocShell, nTab, sOldName, rName)); 2988 } 2989 rDocShell.PostPaintExtras(); 2990 aModificator.SetDocumentModified(); 2991 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); 2992 2993 bSuccess = sal_True; 2994 } 2995 return bSuccess; 2996 } 2997 2998 bool ScDocFunc::SetTabBgColor( SCTAB nTab, const Color& rColor, bool bRecord, bool bApi ) 2999 { 3000 3001 ScDocument* pDoc = rDocShell.GetDocument(); 3002 if (bRecord && !pDoc->IsUndoEnabled()) 3003 bRecord = false; 3004 if ( !pDoc->IsDocEditable() || pDoc->IsTabProtected(nTab) ) 3005 { 3006 if (!bApi) 3007 rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Check to see what this string is... 3008 return false; 3009 } 3010 3011 Color aOldTabBgColor; 3012 aOldTabBgColor = pDoc->GetTabBgColor(nTab); 3013 3014 bool bSuccess = false; 3015 pDoc->SetTabBgColor(nTab, rColor); 3016 if ( pDoc->GetTabBgColor(nTab) == rColor) 3017 bSuccess = true; 3018 if (bSuccess) 3019 { 3020 if (bRecord) 3021 { 3022 rDocShell.GetUndoManager()->AddUndoAction( 3023 new ScUndoTabColor( &rDocShell, nTab, aOldTabBgColor, rColor)); 3024 } 3025 rDocShell.PostPaintExtras(); 3026 ScDocShellModificator aModificator( rDocShell ); 3027 aModificator.SetDocumentModified(); 3028 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); 3029 3030 bSuccess = true; 3031 } 3032 return bSuccess; 3033 } 3034 3035 bool ScDocFunc::SetTabBgColor( 3036 ScUndoTabColorInfo::List& rUndoTabColorList, bool bRecord, bool bApi ) 3037 { 3038 ScDocument* pDoc = rDocShell.GetDocument(); 3039 if (bRecord && !pDoc->IsUndoEnabled()) 3040 bRecord = false; 3041 3042 if ( !pDoc->IsDocEditable() ) 3043 { 3044 if (!bApi) 3045 rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Get a better String Error... 3046 return false; 3047 } 3048 3049 sal_uInt16 nTab; 3050 Color aNewTabBgColor; 3051 bool bSuccess = true; 3052 size_t nTabProtectCount = 0; 3053 size_t nTabListCount = rUndoTabColorList.size(); 3054 for ( size_t i = 0; i < nTabListCount; ++i ) 3055 { 3056 ScUndoTabColorInfo& rInfo = rUndoTabColorList[i]; 3057 nTab = rInfo.mnTabId; 3058 if ( !pDoc->IsTabProtected(nTab) ) 3059 { 3060 aNewTabBgColor = rInfo.maNewTabBgColor; 3061 rInfo.maOldTabBgColor = pDoc->GetTabBgColor(nTab); 3062 pDoc->SetTabBgColor(nTab, aNewTabBgColor); 3063 if ( pDoc->GetTabBgColor(nTab) != aNewTabBgColor) 3064 { 3065 bSuccess = false; 3066 break; 3067 } 3068 } 3069 else 3070 { 3071 nTabProtectCount++; 3072 } 3073 } 3074 3075 if ( nTabProtectCount == nTabListCount ) 3076 { 3077 if (!bApi) 3078 rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Get a better String Error... 3079 return false; 3080 } 3081 3082 if (bSuccess) 3083 { 3084 if (bRecord) 3085 { 3086 rDocShell.GetUndoManager()->AddUndoAction( 3087 new ScUndoTabColor( &rDocShell, rUndoTabColorList)); 3088 } 3089 rDocShell.PostPaintExtras(); 3090 ScDocShellModificator aModificator( rDocShell ); 3091 aModificator.SetDocumentModified(); 3092 } 3093 return bSuccess; 3094 } 3095 3096 //------------------------------------------------------------------------ 3097 3098 //! SetWidthOrHeight - noch doppelt zu ViewFunc !!!!!! 3099 //! Probleme: 3100 //! - Optimale Hoehe fuer Edit-Zellen ist unterschiedlich zwischen Drucker und Bildschirm 3101 //! - Optimale Breite braucht Selektion, um evtl. nur selektierte Zellen zu beruecksichtigen 3102 3103 sal_uInt16 lcl_GetOptimalColWidth( ScDocShell& rDocShell, SCCOL nCol, SCTAB nTab, sal_Bool bFormula ) 3104 { 3105 sal_uInt16 nTwips = 0; 3106 3107 ScSizeDeviceProvider aProv(&rDocShell); 3108 OutputDevice* pDev = aProv.GetDevice(); // has pixel MapMode 3109 double nPPTX = aProv.GetPPTX(); 3110 double nPPTY = aProv.GetPPTY(); 3111 3112 ScDocument* pDoc = rDocShell.GetDocument(); 3113 Fraction aOne(1,1); 3114 nTwips = pDoc->GetOptimalColWidth( nCol, nTab, pDev, nPPTX, nPPTY, aOne, aOne, 3115 bFormula, NULL ); 3116 3117 return nTwips; 3118 } 3119 3120 sal_Bool ScDocFunc::SetWidthOrHeight( sal_Bool bWidth, SCCOLROW nRangeCnt, SCCOLROW* pRanges, SCTAB nTab, 3121 ScSizeMode eMode, sal_uInt16 nSizeTwips, 3122 sal_Bool bRecord, sal_Bool bApi ) 3123 { 3124 ScDocShellModificator aModificator( rDocShell ); 3125 3126 if (!nRangeCnt) 3127 return sal_True; 3128 3129 ScDocument* pDoc = rDocShell.GetDocument(); 3130 if ( bRecord && !pDoc->IsUndoEnabled() ) 3131 bRecord = sal_False; 3132 3133 // import into read-only document is possible 3134 if ( !pDoc->IsChangeReadOnlyEnabled() && !rDocShell.IsEditable() ) 3135 { 3136 if (!bApi) 3137 rDocShell.ErrorMessage(STR_PROTECTIONERR); //! eigene Meldung? 3138 return sal_False; 3139 } 3140 3141 sal_Bool bSuccess = sal_False; 3142 SCCOLROW nStart = pRanges[0]; 3143 SCCOLROW nEnd = pRanges[2*nRangeCnt-1]; 3144 3145 sal_Bool bFormula = sal_False; 3146 if ( eMode == SC_SIZE_OPTIMAL ) 3147 { 3148 //! Option "Formeln anzeigen" - woher nehmen? 3149 } 3150 3151 ScDocument* pUndoDoc = NULL; 3152 ScOutlineTable* pUndoTab = NULL; 3153 SCCOLROW* pUndoRanges = NULL; 3154 3155 if ( bRecord ) 3156 { 3157 pDoc->BeginDrawUndo(); // Drawing Updates 3158 3159 pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 3160 if (bWidth) 3161 { 3162 pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_False ); 3163 pDoc->CopyToDocument( static_cast<SCCOL>(nStart), 0, nTab, static_cast<SCCOL>(nEnd), MAXROW, nTab, IDF_NONE, sal_False, pUndoDoc ); 3164 } 3165 else 3166 { 3167 pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_False, sal_True ); 3168 pDoc->CopyToDocument( 0, static_cast<SCROW>(nStart), nTab, MAXCOL, static_cast<SCROW>(nEnd), nTab, IDF_NONE, sal_False, pUndoDoc ); 3169 } 3170 3171 pUndoRanges = new SCCOLROW[ 2*nRangeCnt ]; 3172 memmove( pUndoRanges, pRanges, 2*nRangeCnt*sizeof(SCCOLROW) ); 3173 3174 ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab ); 3175 if (pTable) 3176 pUndoTab = new ScOutlineTable( *pTable ); 3177 } 3178 3179 sal_Bool bShow = nSizeTwips > 0 || eMode != SC_SIZE_DIRECT; 3180 sal_Bool bOutline = sal_False; 3181 3182 pDoc->IncSizeRecalcLevel( nTab ); // nicht fuer jede Spalte einzeln 3183 for (SCCOLROW nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++) 3184 { 3185 SCCOLROW nStartNo = *(pRanges++); 3186 SCCOLROW nEndNo = *(pRanges++); 3187 3188 if ( !bWidth ) // Hoehen immer blockweise 3189 { 3190 if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT ) 3191 { 3192 sal_Bool bAll = ( eMode==SC_SIZE_OPTIMAL ); 3193 if (!bAll) 3194 { 3195 // fuer alle eingeblendeten CR_MANUALSIZE loeschen, 3196 // dann SetOptimalHeight mit bShrink = FALSE 3197 for (SCROW nRow=nStartNo; nRow<=nEndNo; nRow++) 3198 { 3199 sal_uInt8 nOld = pDoc->GetRowFlags(nRow,nTab); 3200 SCROW nLastRow = -1; 3201 bool bHidden = pDoc->RowHidden(nRow, nTab, nLastRow); 3202 if ( !bHidden && ( nOld & CR_MANUALSIZE ) ) 3203 pDoc->SetRowFlags( nRow, nTab, nOld & ~CR_MANUALSIZE ); 3204 } 3205 } 3206 3207 ScSizeDeviceProvider aProv( &rDocShell ); 3208 Fraction aOne(1,1); 3209 pDoc->SetOptimalHeight( nStartNo, nEndNo, nTab, 0, aProv.GetDevice(), 3210 aProv.GetPPTX(), aProv.GetPPTY(), aOne, aOne, bAll ); 3211 3212 if (bAll) 3213 pDoc->ShowRows( nStartNo, nEndNo, nTab, sal_True ); 3214 3215 // Manual-Flag wird bei bAll=sal_True schon in SetOptimalHeight gesetzt 3216 // (an bei Extra-Height, sonst aus). 3217 } 3218 else if ( eMode==SC_SIZE_DIRECT || eMode==SC_SIZE_ORIGINAL ) 3219 { 3220 if (nSizeTwips) 3221 { 3222 pDoc->SetRowHeightRange( nStartNo, nEndNo, nTab, nSizeTwips ); 3223 pDoc->SetManualHeight( nStartNo, nEndNo, nTab, sal_True ); // height was set manually 3224 } 3225 if ( eMode != SC_SIZE_ORIGINAL ) 3226 pDoc->ShowRows( nStartNo, nEndNo, nTab, nSizeTwips != 0 ); 3227 } 3228 else if ( eMode==SC_SIZE_SHOW ) 3229 { 3230 pDoc->ShowRows( nStartNo, nEndNo, nTab, sal_True ); 3231 } 3232 } 3233 else // Spaltenbreiten 3234 { 3235 for (SCCOL nCol=static_cast<SCCOL>(nStartNo); nCol<=static_cast<SCCOL>(nEndNo); nCol++) 3236 { 3237 SCCOL nLastCol = -1; 3238 if ( eMode != SC_SIZE_VISOPT || !pDoc->ColHidden(nCol, nTab, nLastCol) ) 3239 { 3240 sal_uInt16 nThisSize = nSizeTwips; 3241 3242 if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT ) 3243 nThisSize = nSizeTwips + 3244 lcl_GetOptimalColWidth( rDocShell, nCol, nTab, bFormula ); 3245 if ( nThisSize ) 3246 pDoc->SetColWidth( nCol, nTab, nThisSize ); 3247 3248 if ( eMode != SC_SIZE_ORIGINAL ) 3249 pDoc->ShowCol( nCol, nTab, bShow ); 3250 } 3251 } 3252 } 3253 3254 // adjust outlines 3255 3256 if ( eMode != SC_SIZE_ORIGINAL ) 3257 { 3258 if (bWidth) 3259 bOutline = bOutline || pDoc->UpdateOutlineCol( 3260 static_cast<SCCOL>(nStartNo), 3261 static_cast<SCCOL>(nEndNo), nTab, bShow ); 3262 else 3263 bOutline = bOutline || pDoc->UpdateOutlineRow( 3264 static_cast<SCROW>(nStartNo), 3265 static_cast<SCROW>(nEndNo), nTab, bShow ); 3266 } 3267 } 3268 pDoc->DecSizeRecalcLevel( nTab ); // nicht fuer jede Spalte einzeln 3269 3270 if (!bOutline) 3271 DELETEZ(pUndoTab); 3272 3273 if (bRecord) 3274 { 3275 ScMarkData aMark; 3276 aMark.SelectOneTable( nTab ); 3277 rDocShell.GetUndoManager()->AddUndoAction( 3278 new ScUndoWidthOrHeight( &rDocShell, aMark, 3279 nStart, nTab, nEnd, nTab, 3280 pUndoDoc, nRangeCnt, pUndoRanges, 3281 pUndoTab, eMode, nSizeTwips, bWidth ) ); 3282 } 3283 3284 pDoc->UpdatePageBreaks( nTab ); 3285 3286 rDocShell.PostPaint(0,0,nTab,MAXCOL,MAXROW,nTab,PAINT_ALL); 3287 aModificator.SetDocumentModified(); 3288 3289 return bSuccess; 3290 } 3291 3292 3293 sal_Bool ScDocFunc::InsertPageBreak( sal_Bool bColumn, const ScAddress& rPos, 3294 sal_Bool bRecord, sal_Bool bSetModified, sal_Bool /* bApi */ ) 3295 { 3296 ScDocShellModificator aModificator( rDocShell ); 3297 3298 ScDocument* pDoc = rDocShell.GetDocument(); 3299 if (bRecord && !pDoc->IsUndoEnabled()) 3300 bRecord = sal_False; 3301 SCTAB nTab = rPos.Tab(); 3302 SfxBindings* pBindings = rDocShell.GetViewBindings(); 3303 3304 SCCOLROW nPos = bColumn ? static_cast<SCCOLROW>(rPos.Col()) : 3305 static_cast<SCCOLROW>(rPos.Row()); 3306 if (nPos == 0) 3307 return sal_False; // erste Spalte / Zeile 3308 3309 ScBreakType nBreak = bColumn ? 3310 pDoc->HasColBreak(static_cast<SCCOL>(nPos), nTab) : 3311 pDoc->HasRowBreak(static_cast<SCROW>(nPos), nTab); 3312 if (nBreak & BREAK_MANUAL) 3313 return true; 3314 3315 if (bRecord) 3316 rDocShell.GetUndoManager()->AddUndoAction( 3317 new ScUndoPageBreak( &rDocShell, rPos.Col(), rPos.Row(), nTab, bColumn, sal_True ) ); 3318 3319 if (bColumn) 3320 pDoc->SetColBreak(static_cast<SCCOL>(nPos), nTab, false, true); 3321 else 3322 pDoc->SetRowBreak(static_cast<SCROW>(nPos), nTab, false, true); 3323 3324 pDoc->InvalidatePageBreaks(nTab); 3325 pDoc->UpdatePageBreaks( nTab ); 3326 3327 if (pDoc->IsStreamValid(nTab)) 3328 pDoc->SetStreamValid(nTab, sal_False); 3329 3330 if (bColumn) 3331 { 3332 rDocShell.PostPaint( static_cast<SCCOL>(nPos)-1, 0, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID ); 3333 if (pBindings) 3334 { 3335 pBindings->Invalidate( FID_INS_COLBRK ); 3336 pBindings->Invalidate( FID_DEL_COLBRK ); 3337 } 3338 } 3339 else 3340 { 3341 rDocShell.PostPaint( 0, static_cast<SCROW>(nPos)-1, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID ); 3342 if (pBindings) 3343 { 3344 pBindings->Invalidate( FID_INS_ROWBRK ); 3345 pBindings->Invalidate( FID_DEL_ROWBRK ); 3346 } 3347 } 3348 if (pBindings) 3349 pBindings->Invalidate( FID_DEL_MANUALBREAKS ); 3350 3351 if (bSetModified) 3352 aModificator.SetDocumentModified(); 3353 3354 return sal_True; 3355 } 3356 3357 sal_Bool ScDocFunc::RemovePageBreak( sal_Bool bColumn, const ScAddress& rPos, 3358 sal_Bool bRecord, sal_Bool bSetModified, sal_Bool /* bApi */ ) 3359 { 3360 ScDocShellModificator aModificator( rDocShell ); 3361 3362 ScDocument* pDoc = rDocShell.GetDocument(); 3363 if (bRecord && !pDoc->IsUndoEnabled()) 3364 bRecord = sal_False; 3365 SCTAB nTab = rPos.Tab(); 3366 SfxBindings* pBindings = rDocShell.GetViewBindings(); 3367 3368 SCCOLROW nPos = bColumn ? static_cast<SCCOLROW>(rPos.Col()) : 3369 static_cast<SCCOLROW>(rPos.Row()); 3370 3371 ScBreakType nBreak; 3372 if (bColumn) 3373 nBreak = pDoc->HasColBreak(static_cast<SCCOL>(nPos), nTab); 3374 else 3375 nBreak = pDoc->HasRowBreak(static_cast<SCROW>(nPos), nTab); 3376 if ((nBreak & BREAK_MANUAL) == 0) 3377 // There is no manual break. 3378 return false; 3379 3380 if (bRecord) 3381 rDocShell.GetUndoManager()->AddUndoAction( 3382 new ScUndoPageBreak( &rDocShell, rPos.Col(), rPos.Row(), nTab, bColumn, sal_False ) ); 3383 3384 if (bColumn) 3385 pDoc->RemoveColBreak(static_cast<SCCOL>(nPos), nTab, false, true); 3386 else 3387 pDoc->RemoveRowBreak(static_cast<SCROW>(nPos), nTab, false, true); 3388 3389 pDoc->UpdatePageBreaks( nTab ); 3390 3391 if (pDoc->IsStreamValid(nTab)) 3392 pDoc->SetStreamValid(nTab, sal_False); 3393 3394 if (bColumn) 3395 { 3396 rDocShell.PostPaint( static_cast<SCCOL>(nPos)-1, 0, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID ); 3397 if (pBindings) 3398 { 3399 pBindings->Invalidate( FID_INS_COLBRK ); 3400 pBindings->Invalidate( FID_DEL_COLBRK ); 3401 } 3402 } 3403 else 3404 { 3405 rDocShell.PostPaint( 0, nPos-1, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID ); 3406 if (pBindings) 3407 { 3408 pBindings->Invalidate( FID_INS_ROWBRK ); 3409 pBindings->Invalidate( FID_DEL_ROWBRK ); 3410 } 3411 } 3412 if (pBindings) 3413 pBindings->Invalidate( FID_DEL_MANUALBREAKS ); 3414 3415 if (bSetModified) 3416 aModificator.SetDocumentModified(); 3417 3418 return sal_True; 3419 } 3420 3421 //------------------------------------------------------------------------ 3422 3423 void ScDocFunc::ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect ) 3424 { 3425 ScDocument* pDoc = rDocShell.GetDocument(); 3426 3427 pDoc->SetTabProtection(nTab, &rProtect); 3428 if (pDoc->IsUndoEnabled()) 3429 { 3430 ScTableProtection* pProtect = pDoc->GetTabProtection(nTab); 3431 DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScTableProtection pointer is NULL!"); 3432 if (pProtect) 3433 { 3434 ::std::auto_ptr<ScTableProtection> p(new ScTableProtection(*pProtect)); 3435 p->setProtected(true); // just in case ... 3436 rDocShell.GetUndoManager()->AddUndoAction( 3437 new ScUndoTabProtect(&rDocShell, nTab, p) ); 3438 3439 // ownership of auto_ptr now transferred to ScUndoTabProtect. 3440 } 3441 } 3442 3443 rDocShell.PostPaintGridAll(); 3444 ScDocShellModificator aModificator(rDocShell); 3445 aModificator.SetDocumentModified(); 3446 } 3447 3448 sal_Bool ScDocFunc::Protect( SCTAB nTab, const String& rPassword, sal_Bool /*bApi*/ ) 3449 { 3450 ScDocument* pDoc = rDocShell.GetDocument(); 3451 if (nTab == TABLEID_DOC) 3452 { 3453 // document protection 3454 ScDocProtection aProtection; 3455 aProtection.setProtected(true); 3456 aProtection.setPassword(rPassword); 3457 pDoc->SetDocProtection(&aProtection); 3458 if (pDoc->IsUndoEnabled()) 3459 { 3460 ScDocProtection* pProtect = pDoc->GetDocProtection(); 3461 DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScDocProtection pointer is NULL!"); 3462 if (pProtect) 3463 { 3464 ::std::auto_ptr<ScDocProtection> p(new ScDocProtection(*pProtect)); 3465 p->setProtected(true); // just in case ... 3466 rDocShell.GetUndoManager()->AddUndoAction( 3467 new ScUndoDocProtect(&rDocShell, p) ); 3468 // ownership of auto_ptr is transferred to ScUndoDocProtect. 3469 } 3470 } 3471 } 3472 else 3473 { 3474 // sheet protection 3475 3476 ScTableProtection aProtection; 3477 aProtection.setProtected(true); 3478 aProtection.setPassword(rPassword); 3479 pDoc->SetTabProtection(nTab, &aProtection); 3480 if (pDoc->IsUndoEnabled()) 3481 { 3482 ScTableProtection* pProtect = pDoc->GetTabProtection(nTab); 3483 DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScTableProtection pointer is NULL!"); 3484 if (pProtect) 3485 { 3486 ::std::auto_ptr<ScTableProtection> p(new ScTableProtection(*pProtect)); 3487 p->setProtected(true); // just in case ... 3488 rDocShell.GetUndoManager()->AddUndoAction( 3489 new ScUndoTabProtect(&rDocShell, nTab, p) ); 3490 // ownership of auto_ptr now transferred to ScUndoTabProtect. 3491 } 3492 } 3493 } 3494 3495 rDocShell.PostPaintGridAll(); 3496 ScDocShellModificator aModificator( rDocShell ); 3497 aModificator.SetDocumentModified(); 3498 3499 return true; 3500 } 3501 3502 sal_Bool ScDocFunc::Unprotect( SCTAB nTab, const String& rPassword, sal_Bool bApi ) 3503 { 3504 ScDocument* pDoc = rDocShell.GetDocument(); 3505 3506 if (nTab == TABLEID_DOC) 3507 { 3508 // document protection 3509 3510 ScDocProtection* pDocProtect = pDoc->GetDocProtection(); 3511 if (!pDocProtect || !pDocProtect->isProtected()) 3512 // already unprotected (should not happen)! 3513 return true; 3514 3515 // save the protection state before unprotect (for undo). 3516 ::std::auto_ptr<ScDocProtection> pProtectCopy(new ScDocProtection(*pDocProtect)); 3517 3518 if (!pDocProtect->verifyPassword(rPassword)) 3519 { 3520 if (!bApi) 3521 { 3522 InfoBox aBox( rDocShell.GetActiveDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) ); 3523 aBox.Execute(); 3524 } 3525 return false; 3526 } 3527 3528 pDoc->SetDocProtection(NULL); 3529 if (pDoc->IsUndoEnabled()) 3530 { 3531 pProtectCopy->setProtected(false); 3532 rDocShell.GetUndoManager()->AddUndoAction( 3533 new ScUndoDocProtect(&rDocShell, pProtectCopy) ); 3534 // ownership of auto_ptr now transferred to ScUndoDocProtect. 3535 } 3536 } 3537 else 3538 { 3539 // sheet protection 3540 3541 ScTableProtection* pTabProtect = pDoc->GetTabProtection(nTab); 3542 if (!pTabProtect || !pTabProtect->isProtected()) 3543 // already unprotected (should not happen)! 3544 return true; 3545 3546 // save the protection state before unprotect (for undo). 3547 ::std::auto_ptr<ScTableProtection> pProtectCopy(new ScTableProtection(*pTabProtect)); 3548 if (!pTabProtect->verifyPassword(rPassword)) 3549 { 3550 if (!bApi) 3551 { 3552 InfoBox aBox( rDocShell.GetActiveDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) ); 3553 aBox.Execute(); 3554 } 3555 return false; 3556 } 3557 3558 pDoc->SetTabProtection(nTab, NULL); 3559 if (pDoc->IsUndoEnabled()) 3560 { 3561 pProtectCopy->setProtected(false); 3562 rDocShell.GetUndoManager()->AddUndoAction( 3563 new ScUndoTabProtect(&rDocShell, nTab, pProtectCopy) ); 3564 // ownership of auto_ptr now transferred to ScUndoTabProtect. 3565 } 3566 } 3567 3568 rDocShell.PostPaintGridAll(); 3569 ScDocShellModificator aModificator( rDocShell ); 3570 aModificator.SetDocumentModified(); 3571 3572 return true; 3573 } 3574 3575 //------------------------------------------------------------------------ 3576 3577 sal_Bool ScDocFunc::ClearItems( const ScMarkData& rMark, const sal_uInt16* pWhich, sal_Bool bApi ) 3578 { 3579 ScDocShellModificator aModificator( rDocShell ); 3580 3581 ScDocument* pDoc = rDocShell.GetDocument(); 3582 sal_Bool bUndo (pDoc->IsUndoEnabled()); 3583 ScEditableTester aTester( pDoc, rMark ); 3584 if (!aTester.IsEditable()) 3585 { 3586 if (!bApi) 3587 rDocShell.ErrorMessage(aTester.GetMessageId()); 3588 return sal_False; 3589 } 3590 3591 // #i12940# ClearItems is called (from setPropertyToDefault) directly with uno object's cached 3592 // MarkData (GetMarkData), so rMark must be changed to multi selection for ClearSelectionItems 3593 // here. 3594 3595 ScRange aMarkRange; 3596 ScMarkData aMultiMark = rMark; 3597 aMultiMark.SetMarking(sal_False); // for MarkToMulti 3598 aMultiMark.MarkToMulti(); 3599 aMultiMark.GetMultiMarkArea( aMarkRange ); 3600 3601 // if (bRecord) 3602 if (bUndo) 3603 { 3604 SCTAB nStartTab = aMarkRange.aStart.Tab(); 3605 SCTAB nEndTab = aMarkRange.aEnd.Tab(); 3606 3607 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 3608 pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab ); 3609 pDoc->CopyToDocument( aMarkRange, IDF_ATTRIB, sal_True, pUndoDoc, (ScMarkData*)&aMultiMark ); 3610 3611 rDocShell.GetUndoManager()->AddUndoAction( 3612 new ScUndoClearItems( &rDocShell, aMultiMark, pUndoDoc, pWhich ) ); 3613 } 3614 3615 pDoc->ClearSelectionItems( pWhich, aMultiMark ); 3616 3617 rDocShell.PostPaint( aMarkRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE ); 3618 aModificator.SetDocumentModified(); 3619 3620 //! Bindings-Invalidate etc.? 3621 3622 return sal_True; 3623 } 3624 3625 sal_Bool ScDocFunc::ChangeIndent( const ScMarkData& rMark, sal_Bool bIncrement, sal_Bool bApi ) 3626 { 3627 ScDocShellModificator aModificator( rDocShell ); 3628 3629 ScDocument* pDoc = rDocShell.GetDocument(); 3630 sal_Bool bUndo(pDoc->IsUndoEnabled()); 3631 ScEditableTester aTester( pDoc, rMark ); 3632 if (!aTester.IsEditable()) 3633 { 3634 if (!bApi) 3635 rDocShell.ErrorMessage(aTester.GetMessageId()); 3636 return sal_False; 3637 } 3638 3639 ScRange aMarkRange; 3640 rMark.GetMultiMarkArea( aMarkRange ); 3641 3642 // if (bRecord) 3643 if (bUndo) 3644 { 3645 SCTAB nStartTab = aMarkRange.aStart.Tab(); 3646 SCTAB nTabCount = pDoc->GetTableCount(); 3647 3648 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 3649 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab ); 3650 for (SCTAB i=0; i<nTabCount; i++) 3651 if (i != nStartTab && rMark.GetTableSelect(i)) 3652 pUndoDoc->AddUndoTab( i, i ); 3653 3654 ScRange aCopyRange = aMarkRange; 3655 aCopyRange.aStart.SetTab(0); 3656 aCopyRange.aEnd.SetTab(nTabCount-1); 3657 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, sal_True, pUndoDoc, (ScMarkData*)&rMark ); 3658 3659 rDocShell.GetUndoManager()->AddUndoAction( 3660 new ScUndoIndent( &rDocShell, rMark, pUndoDoc, bIncrement ) ); 3661 } 3662 3663 pDoc->ChangeSelectionIndent( bIncrement, rMark ); 3664 3665 rDocShell.PostPaint( aMarkRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE ); 3666 aModificator.SetDocumentModified(); 3667 3668 SfxBindings* pBindings = rDocShell.GetViewBindings(); 3669 if (pBindings) 3670 { 3671 pBindings->Invalidate( SID_ALIGNLEFT ); // ChangeIndent setzt auf links 3672 pBindings->Invalidate( SID_ALIGNRIGHT ); 3673 pBindings->Invalidate( SID_ALIGNBLOCK ); 3674 pBindings->Invalidate( SID_ALIGNCENTERHOR ); 3675 // pseudo slots for Format menu 3676 pBindings->Invalidate( SID_ALIGN_ANY_HDEFAULT ); 3677 pBindings->Invalidate( SID_ALIGN_ANY_LEFT ); 3678 pBindings->Invalidate( SID_ALIGN_ANY_HCENTER ); 3679 pBindings->Invalidate( SID_ALIGN_ANY_RIGHT ); 3680 pBindings->Invalidate( SID_ALIGN_ANY_JUSTIFIED ); 3681 } 3682 3683 return sal_True; 3684 } 3685 3686 sal_Bool ScDocFunc::AutoFormat( const ScRange& rRange, const ScMarkData* pTabMark, 3687 sal_uInt16 nFormatNo, sal_Bool bRecord, sal_Bool bApi ) 3688 { 3689 ScDocShellModificator aModificator( rDocShell ); 3690 3691 sal_Bool bSuccess = sal_False; 3692 ScDocument* pDoc = rDocShell.GetDocument(); 3693 SCCOL nStartCol = rRange.aStart.Col(); 3694 SCROW nStartRow = rRange.aStart.Row(); 3695 SCTAB nStartTab = rRange.aStart.Tab(); 3696 SCCOL nEndCol = rRange.aEnd.Col(); 3697 SCROW nEndRow = rRange.aEnd.Row(); 3698 SCTAB nEndTab = rRange.aEnd.Tab(); 3699 3700 if (bRecord && !pDoc->IsUndoEnabled()) 3701 bRecord = sal_False; 3702 ScMarkData aMark; 3703 if (pTabMark) 3704 aMark = *pTabMark; 3705 else 3706 { 3707 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) 3708 aMark.SelectTable( nTab, sal_True ); 3709 } 3710 3711 ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat(); 3712 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark ); 3713 if ( pAutoFormat && nFormatNo < pAutoFormat->GetCount() && aTester.IsEditable() ) 3714 { 3715 WaitObject aWait( rDocShell.GetActiveDialogParent() ); 3716 3717 sal_Bool bSize = (*pAutoFormat)[nFormatNo]->GetIncludeWidthHeight(); 3718 3719 SCTAB nTabCount = pDoc->GetTableCount(); 3720 ScDocument* pUndoDoc = NULL; 3721 if ( bRecord ) 3722 { 3723 pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 3724 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab, bSize, bSize ); 3725 for (SCTAB i=0; i<nTabCount; i++) 3726 if (i != nStartTab && aMark.GetTableSelect(i)) 3727 pUndoDoc->AddUndoTab( i, i, bSize, bSize ); 3728 3729 ScRange aCopyRange = rRange; 3730 aCopyRange.aStart.SetTab(0); 3731 aCopyRange.aStart.SetTab(nTabCount-1); 3732 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, sal_False, pUndoDoc, &aMark ); 3733 if (bSize) 3734 { 3735 pDoc->CopyToDocument( nStartCol,0,0, nEndCol,MAXROW,nTabCount-1, 3736 IDF_NONE, sal_False, pUndoDoc, &aMark ); 3737 pDoc->CopyToDocument( 0,nStartRow,0, MAXCOL,nEndRow,nTabCount-1, 3738 IDF_NONE, sal_False, pUndoDoc, &aMark ); 3739 } 3740 pDoc->BeginDrawUndo(); 3741 } 3742 3743 pDoc->AutoFormat( nStartCol, nStartRow, nEndCol, nEndRow, nFormatNo, aMark ); 3744 3745 if (bSize) 3746 { 3747 /* SCCOL nCols[2]; 3748 nCols[0] = nStartCol; 3749 nCols[1] = nEndCol; 3750 SCROW nRows[2]; 3751 nRows[0] = nStartRow; 3752 nRows[1] = nEndRow; 3753 */ 3754 SCCOLROW nCols[2] = { nStartCol, nEndCol }; 3755 SCCOLROW nRows[2] = { nStartRow, nEndRow }; 3756 3757 for (SCTAB nTab=0; nTab<nTabCount; nTab++) 3758 if (aMark.GetTableSelect(nTab)) 3759 { 3760 SetWidthOrHeight( sal_True, 1,nCols, nTab, SC_SIZE_VISOPT, STD_EXTRA_WIDTH, sal_False, sal_True); 3761 SetWidthOrHeight( sal_False,1,nRows, nTab, SC_SIZE_VISOPT, 0, sal_False, sal_False); 3762 rDocShell.PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, 3763 PAINT_GRID | PAINT_LEFT | PAINT_TOP ); 3764 } 3765 } 3766 else 3767 { 3768 for (SCTAB nTab=0; nTab<nTabCount; nTab++) 3769 if (aMark.GetTableSelect(nTab)) 3770 { 3771 sal_Bool bAdj = AdjustRowHeight( ScRange(nStartCol, nStartRow, nTab, 3772 nEndCol, nEndRow, nTab), sal_False ); 3773 if (bAdj) 3774 rDocShell.PostPaint( 0,nStartRow,nTab, MAXCOL,MAXROW,nTab, 3775 PAINT_GRID | PAINT_LEFT ); 3776 else 3777 rDocShell.PostPaint( nStartCol, nStartRow, nTab, 3778 nEndCol, nEndRow, nTab, PAINT_GRID ); 3779 } 3780 } 3781 3782 if ( bRecord ) // Draw-Undo erst jetzt verfuegbar 3783 { 3784 rDocShell.GetUndoManager()->AddUndoAction( 3785 new ScUndoAutoFormat( &rDocShell, rRange, pUndoDoc, aMark, bSize, nFormatNo ) ); 3786 } 3787 3788 aModificator.SetDocumentModified(); 3789 } 3790 else if (!bApi) 3791 rDocShell.ErrorMessage(aTester.GetMessageId()); 3792 3793 return bSuccess; 3794 } 3795 3796 //------------------------------------------------------------------------ 3797 3798 sal_Bool ScDocFunc::EnterMatrix( const ScRange& rRange, const ScMarkData* pTabMark, 3799 const ScTokenArray* pTokenArray, const String& rString, sal_Bool bApi, sal_Bool bEnglish, 3800 const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar ) 3801 { 3802 ScDocShellModificator aModificator( rDocShell ); 3803 3804 sal_Bool bSuccess = sal_False; 3805 ScDocument* pDoc = rDocShell.GetDocument(); 3806 SCCOL nStartCol = rRange.aStart.Col(); 3807 SCROW nStartRow = rRange.aStart.Row(); 3808 SCTAB nStartTab = rRange.aStart.Tab(); 3809 SCCOL nEndCol = rRange.aEnd.Col(); 3810 SCROW nEndRow = rRange.aEnd.Row(); 3811 SCTAB nEndTab = rRange.aEnd.Tab(); 3812 3813 sal_Bool bUndo(pDoc->IsUndoEnabled()); 3814 3815 ScMarkData aMark; 3816 if (pTabMark) 3817 aMark = *pTabMark; 3818 else 3819 { 3820 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) 3821 aMark.SelectTable( nTab, sal_True ); 3822 } 3823 3824 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark ); 3825 if ( aTester.IsEditable() ) 3826 { 3827 WaitObject aWait( rDocShell.GetActiveDialogParent() ); 3828 3829 ScDocument* pUndoDoc = NULL; 3830 // if (bRecord) // immer 3831 if (bUndo) 3832 { 3833 //! auch bei Undo selektierte Tabellen beruecksichtigen 3834 pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 3835 pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab ); 3836 pDoc->CopyToDocument( rRange, IDF_ALL & ~IDF_NOTE, sal_False, pUndoDoc ); 3837 } 3838 3839 // use TokenArray if given, string (and flags) otherwise 3840 if ( pTokenArray ) 3841 { 3842 pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow, 3843 aMark, EMPTY_STRING, pTokenArray, eGrammar); 3844 } 3845 else if ( pDoc->IsImportingXML() ) 3846 { 3847 ScTokenArray* pCode = lcl_ScDocFunc_CreateTokenArrayXML( rString, rFormulaNmsp, eGrammar ); 3848 pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow, 3849 aMark, EMPTY_STRING, pCode, eGrammar); 3850 delete pCode; 3851 pDoc->IncXMLImportedFormulaCount( rString.Len() ); 3852 } 3853 else if (bEnglish) 3854 { 3855 ScCompiler aComp( pDoc, rRange.aStart); 3856 aComp.SetGrammar(eGrammar); 3857 ScTokenArray* pCode = aComp.CompileString( rString ); 3858 pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow, 3859 aMark, EMPTY_STRING, pCode, eGrammar); 3860 delete pCode; 3861 } 3862 else 3863 pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow, 3864 aMark, rString, NULL, eGrammar); 3865 3866 // if (bRecord) // immer 3867 if (bUndo) 3868 { 3869 //! auch bei Undo selektierte Tabellen beruecksichtigen 3870 rDocShell.GetUndoManager()->AddUndoAction( 3871 new ScUndoEnterMatrix( &rDocShell, rRange, pUndoDoc, rString ) ); 3872 } 3873 3874 // Err522 beim Paint von DDE-Formeln werden jetzt beim Interpretieren abgefangen 3875 rDocShell.PostPaint( nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab, PAINT_GRID ); 3876 aModificator.SetDocumentModified(); 3877 3878 bSuccess = sal_True; 3879 } 3880 else if (!bApi) 3881 rDocShell.ErrorMessage(aTester.GetMessageId()); 3882 3883 return bSuccess; 3884 } 3885 3886 //------------------------------------------------------------------------ 3887 3888 sal_Bool ScDocFunc::TabOp( const ScRange& rRange, const ScMarkData* pTabMark, 3889 const ScTabOpParam& rParam, sal_Bool bRecord, sal_Bool bApi ) 3890 { 3891 ScDocShellModificator aModificator( rDocShell ); 3892 3893 sal_Bool bSuccess = sal_False; 3894 ScDocument* pDoc = rDocShell.GetDocument(); 3895 SCCOL nStartCol = rRange.aStart.Col(); 3896 SCROW nStartRow = rRange.aStart.Row(); 3897 SCTAB nStartTab = rRange.aStart.Tab(); 3898 SCCOL nEndCol = rRange.aEnd.Col(); 3899 SCROW nEndRow = rRange.aEnd.Row(); 3900 SCTAB nEndTab = rRange.aEnd.Tab(); 3901 3902 if (bRecord && !pDoc->IsUndoEnabled()) 3903 bRecord = sal_False; 3904 3905 ScMarkData aMark; 3906 if (pTabMark) 3907 aMark = *pTabMark; 3908 else 3909 { 3910 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) 3911 aMark.SelectTable( nTab, sal_True ); 3912 } 3913 3914 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark ); 3915 if ( aTester.IsEditable() ) 3916 { 3917 WaitObject aWait( rDocShell.GetActiveDialogParent() ); 3918 pDoc->SetDirty( rRange ); 3919 if ( bRecord ) 3920 { 3921 //! auch bei Undo selektierte Tabellen beruecksichtigen 3922 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 3923 pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab ); 3924 pDoc->CopyToDocument( rRange, IDF_ALL & ~IDF_NOTE, sal_False, pUndoDoc ); 3925 3926 rDocShell.GetUndoManager()->AddUndoAction( 3927 new ScUndoTabOp( &rDocShell, 3928 nStartCol, nStartRow, nStartTab, 3929 nEndCol, nEndRow, nEndTab, pUndoDoc, 3930 rParam.aRefFormulaCell, 3931 rParam.aRefFormulaEnd, 3932 rParam.aRefRowCell, 3933 rParam.aRefColCell, 3934 rParam.nMode) ); 3935 } 3936 pDoc->InsertTableOp(rParam, nStartCol, nStartRow, nEndCol, nEndRow, aMark); 3937 rDocShell.PostPaintGridAll(); 3938 aModificator.SetDocumentModified(); 3939 bSuccess = sal_True; 3940 } 3941 else if (!bApi) 3942 rDocShell.ErrorMessage(aTester.GetMessageId()); 3943 3944 return bSuccess; 3945 } 3946 3947 //------------------------------------------------------------------------ 3948 3949 inline ScDirection DirFromFillDir( FillDir eDir ) 3950 { 3951 if (eDir==FILL_TO_BOTTOM) 3952 return DIR_BOTTOM; 3953 else if (eDir==FILL_TO_RIGHT) 3954 return DIR_RIGHT; 3955 else if (eDir==FILL_TO_TOP) 3956 return DIR_TOP; 3957 else // if (eDir==FILL_TO_LEFT) 3958 return DIR_LEFT; 3959 } 3960 3961 sal_Bool ScDocFunc::FillSimple( const ScRange& rRange, const ScMarkData* pTabMark, 3962 FillDir eDir, sal_Bool bRecord, sal_Bool bApi ) 3963 { 3964 ScDocShellModificator aModificator( rDocShell ); 3965 3966 sal_Bool bSuccess = sal_False; 3967 ScDocument* pDoc = rDocShell.GetDocument(); 3968 SCCOL nStartCol = rRange.aStart.Col(); 3969 SCROW nStartRow = rRange.aStart.Row(); 3970 SCTAB nStartTab = rRange.aStart.Tab(); 3971 SCCOL nEndCol = rRange.aEnd.Col(); 3972 SCROW nEndRow = rRange.aEnd.Row(); 3973 SCTAB nEndTab = rRange.aEnd.Tab(); 3974 3975 if (bRecord && !pDoc->IsUndoEnabled()) 3976 bRecord = sal_False; 3977 3978 ScMarkData aMark; 3979 if (pTabMark) 3980 aMark = *pTabMark; 3981 else 3982 { 3983 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) 3984 aMark.SelectTable( nTab, sal_True ); 3985 } 3986 3987 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark ); 3988 if ( aTester.IsEditable() ) 3989 { 3990 WaitObject aWait( rDocShell.GetActiveDialogParent() ); 3991 3992 ScRange aSourceArea = rRange; 3993 ScRange aDestArea = rRange; 3994 3995 SCCOLROW nCount = 0; 3996 switch (eDir) 3997 { 3998 case FILL_TO_BOTTOM: 3999 nCount = aSourceArea.aEnd.Row()-aSourceArea.aStart.Row(); 4000 aSourceArea.aEnd.SetRow( aSourceArea.aStart.Row() ); 4001 break; 4002 case FILL_TO_RIGHT: 4003 nCount = aSourceArea.aEnd.Col()-aSourceArea.aStart.Col(); 4004 aSourceArea.aEnd.SetCol( aSourceArea.aStart.Col() ); 4005 break; 4006 case FILL_TO_TOP: 4007 nCount = aSourceArea.aEnd.Row()-aSourceArea.aStart.Row(); 4008 aSourceArea.aStart.SetRow( aSourceArea.aEnd.Row() ); 4009 break; 4010 case FILL_TO_LEFT: 4011 nCount = aSourceArea.aEnd.Col()-aSourceArea.aStart.Col(); 4012 aSourceArea.aStart.SetCol( aSourceArea.aEnd.Col() ); 4013 break; 4014 } 4015 4016 ScDocument* pUndoDoc = NULL; 4017 if ( bRecord ) 4018 { 4019 SCTAB nTabCount = pDoc->GetTableCount(); 4020 SCTAB nDestStartTab = aDestArea.aStart.Tab(); 4021 4022 pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 4023 pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab ); 4024 for (SCTAB i=0; i<nTabCount; i++) 4025 if (i != nDestStartTab && aMark.GetTableSelect(i)) 4026 pUndoDoc->AddUndoTab( i, i ); 4027 4028 ScRange aCopyRange = aDestArea; 4029 aCopyRange.aStart.SetTab(0); 4030 aCopyRange.aEnd.SetTab(nTabCount-1); 4031 pDoc->CopyToDocument( aCopyRange, IDF_AUTOFILL, sal_False, pUndoDoc, &aMark ); 4032 } 4033 4034 pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), 4035 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aMark, 4036 nCount, eDir, FILL_SIMPLE ); 4037 AdjustRowHeight(rRange); 4038 4039 if ( bRecord ) // Draw-Undo erst jetzt verfuegbar 4040 { 4041 rDocShell.GetUndoManager()->AddUndoAction( 4042 new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark, 4043 eDir, FILL_SIMPLE, FILL_DAY, MAXDOUBLE, 1.0, 1e307, 4044 pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) ); 4045 } 4046 4047 rDocShell.PostPaintGridAll(); 4048 // rDocShell.PostPaintDataChanged(); 4049 aModificator.SetDocumentModified(); 4050 4051 bSuccess = sal_True; 4052 } 4053 else if (!bApi) 4054 rDocShell.ErrorMessage(aTester.GetMessageId()); 4055 4056 return bSuccess; 4057 } 4058 4059 sal_Bool ScDocFunc::FillSeries( const ScRange& rRange, const ScMarkData* pTabMark, 4060 FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd, 4061 double fStart, double fStep, double fMax, 4062 sal_Bool bRecord, sal_Bool bApi ) 4063 { 4064 ScDocShellModificator aModificator( rDocShell ); 4065 4066 sal_Bool bSuccess = sal_False; 4067 ScDocument* pDoc = rDocShell.GetDocument(); 4068 SCCOL nStartCol = rRange.aStart.Col(); 4069 SCROW nStartRow = rRange.aStart.Row(); 4070 SCTAB nStartTab = rRange.aStart.Tab(); 4071 SCCOL nEndCol = rRange.aEnd.Col(); 4072 SCROW nEndRow = rRange.aEnd.Row(); 4073 SCTAB nEndTab = rRange.aEnd.Tab(); 4074 4075 if (bRecord && !pDoc->IsUndoEnabled()) 4076 bRecord = sal_False; 4077 4078 ScMarkData aMark; 4079 if (pTabMark) 4080 aMark = *pTabMark; 4081 else 4082 { 4083 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) 4084 aMark.SelectTable( nTab, sal_True ); 4085 } 4086 4087 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark ); 4088 if ( aTester.IsEditable() ) 4089 { 4090 WaitObject aWait( rDocShell.GetActiveDialogParent() ); 4091 4092 ScRange aSourceArea = rRange; 4093 ScRange aDestArea = rRange; 4094 4095 SCSIZE nCount = pDoc->GetEmptyLinesInBlock( 4096 aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), aSourceArea.aStart.Tab(), 4097 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aSourceArea.aEnd.Tab(), 4098 DirFromFillDir(eDir) ); 4099 4100 // #27665# mindestens eine Zeile/Spalte als Quellbereich behalten: 4101 SCSIZE nTotLines = ( eDir == FILL_TO_BOTTOM || eDir == FILL_TO_TOP ) ? 4102 static_cast<SCSIZE>( aSourceArea.aEnd.Row() - aSourceArea.aStart.Row() + 1 ) : 4103 static_cast<SCSIZE>( aSourceArea.aEnd.Col() - aSourceArea.aStart.Col() + 1 ); 4104 if ( nCount >= nTotLines ) 4105 nCount = nTotLines - 1; 4106 4107 switch (eDir) 4108 { 4109 case FILL_TO_BOTTOM: 4110 aSourceArea.aEnd.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aEnd.Row() - nCount ) ); 4111 break; 4112 case FILL_TO_RIGHT: 4113 aSourceArea.aEnd.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aEnd.Col() - nCount ) ); 4114 break; 4115 case FILL_TO_TOP: 4116 aSourceArea.aStart.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aStart.Row() + nCount ) ); 4117 break; 4118 case FILL_TO_LEFT: 4119 aSourceArea.aStart.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aStart.Col() + nCount ) ); 4120 break; 4121 } 4122 4123 ScDocument* pUndoDoc = NULL; 4124 if ( bRecord ) 4125 { 4126 SCTAB nTabCount = pDoc->GetTableCount(); 4127 SCTAB nDestStartTab = aDestArea.aStart.Tab(); 4128 4129 pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 4130 pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab ); 4131 for (SCTAB i=0; i<nTabCount; i++) 4132 if (i != nDestStartTab && aMark.GetTableSelect(i)) 4133 pUndoDoc->AddUndoTab( i, i ); 4134 4135 pDoc->CopyToDocument( 4136 aDestArea.aStart.Col(), aDestArea.aStart.Row(), 0, 4137 aDestArea.aEnd.Col(), aDestArea.aEnd.Row(), nTabCount-1, 4138 IDF_AUTOFILL, sal_False, pUndoDoc, &aMark ); 4139 } 4140 4141 if (aDestArea.aStart.Col() <= aDestArea.aEnd.Col() && 4142 aDestArea.aStart.Row() <= aDestArea.aEnd.Row()) 4143 { 4144 if ( fStart != MAXDOUBLE ) 4145 { 4146 SCCOL nValX = (eDir == FILL_TO_LEFT) ? aDestArea.aEnd.Col() : aDestArea.aStart.Col(); 4147 SCROW nValY = (eDir == FILL_TO_TOP ) ? aDestArea.aEnd.Row() : aDestArea.aStart.Row(); 4148 SCTAB nTab = aDestArea.aStart.Tab(); 4149 pDoc->SetValue( nValX, nValY, nTab, fStart ); 4150 } 4151 pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), 4152 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aMark, 4153 nCount, eDir, eCmd, eDateCmd, fStep, fMax ); 4154 AdjustRowHeight(rRange); 4155 4156 rDocShell.PostPaintGridAll(); 4157 // rDocShell.PostPaintDataChanged(); 4158 aModificator.SetDocumentModified(); 4159 } 4160 4161 if ( bRecord ) // Draw-Undo erst jetzt verfuegbar 4162 { 4163 rDocShell.GetUndoManager()->AddUndoAction( 4164 new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark, 4165 eDir, eCmd, eDateCmd, fStart, fStep, fMax, 4166 pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) ); 4167 } 4168 4169 bSuccess = sal_True; 4170 } 4171 else if (!bApi) 4172 rDocShell.ErrorMessage(aTester.GetMessageId()); 4173 4174 return bSuccess; 4175 } 4176 4177 sal_Bool ScDocFunc::FillAuto( ScRange& rRange, const ScMarkData* pTabMark, 4178 FillDir eDir, sal_uLong nCount, sal_Bool bRecord, sal_Bool bApi ) 4179 { 4180 ScDocShellModificator aModificator( rDocShell ); 4181 4182 ScDocument* pDoc = rDocShell.GetDocument(); 4183 SCCOL nStartCol = rRange.aStart.Col(); 4184 SCROW nStartRow = rRange.aStart.Row(); 4185 SCTAB nStartTab = rRange.aStart.Tab(); 4186 SCCOL nEndCol = rRange.aEnd.Col(); 4187 SCROW nEndRow = rRange.aEnd.Row(); 4188 SCTAB nEndTab = rRange.aEnd.Tab(); 4189 4190 if (bRecord && !pDoc->IsUndoEnabled()) 4191 bRecord = sal_False; 4192 4193 ScMarkData aMark; 4194 if (pTabMark) 4195 aMark = *pTabMark; 4196 else 4197 { 4198 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) 4199 aMark.SelectTable( nTab, sal_True ); 4200 } 4201 4202 ScRange aSourceArea = rRange; 4203 ScRange aDestArea = rRange; 4204 4205 FillCmd eCmd = FILL_AUTO; 4206 FillDateCmd eDateCmd = FILL_DAY; 4207 double fStep = 1.0; 4208 double fMax = MAXDOUBLE; 4209 4210 switch (eDir) 4211 { 4212 case FILL_TO_BOTTOM: 4213 aDestArea.aEnd.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aEnd.Row() + nCount ) ); 4214 break; 4215 case FILL_TO_TOP: 4216 if (nCount > sal::static_int_cast<sal_uLong>( aSourceArea.aStart.Row() )) 4217 { 4218 DBG_ERROR("FillAuto: Row < 0"); 4219 nCount = aSourceArea.aStart.Row(); 4220 } 4221 aDestArea.aStart.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aStart.Row() - nCount ) ); 4222 break; 4223 case FILL_TO_RIGHT: 4224 aDestArea.aEnd.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aEnd.Col() + nCount ) ); 4225 break; 4226 case FILL_TO_LEFT: 4227 if (nCount > sal::static_int_cast<sal_uLong>( aSourceArea.aStart.Col() )) 4228 { 4229 DBG_ERROR("FillAuto: Col < 0"); 4230 nCount = aSourceArea.aStart.Col(); 4231 } 4232 aDestArea.aStart.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aStart.Col() - nCount ) ); 4233 break; 4234 default: 4235 DBG_ERROR("Falsche Richtung bei FillAuto"); 4236 break; 4237 } 4238 4239 // Zellschutz testen 4240 //! Quellbereich darf geschuetzt sein !!! 4241 //! aber kein Matrixfragment enthalten !!! 4242 4243 ScEditableTester aTester( pDoc, aDestArea ); 4244 if ( !aTester.IsEditable() ) 4245 { 4246 if (!bApi) 4247 rDocShell.ErrorMessage(aTester.GetMessageId()); 4248 return sal_False; 4249 } 4250 4251 if ( pDoc->HasSelectedBlockMatrixFragment( nStartCol, nStartRow, 4252 nEndCol, nEndRow, aMark ) ) 4253 { 4254 if (!bApi) 4255 rDocShell.ErrorMessage(STR_MATRIXFRAGMENTERR); 4256 return sal_False; 4257 } 4258 4259 WaitObject aWait( rDocShell.GetActiveDialogParent() ); 4260 4261 ScDocument* pUndoDoc = NULL; 4262 if ( bRecord ) 4263 { 4264 SCTAB nTabCount = pDoc->GetTableCount(); 4265 SCTAB nDestStartTab = aDestArea.aStart.Tab(); 4266 4267 pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 4268 pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab ); 4269 for (SCTAB i=0; i<nTabCount; i++) 4270 if (i != nDestStartTab && aMark.GetTableSelect(i)) 4271 pUndoDoc->AddUndoTab( i, i ); 4272 4273 // do not clone note captions in undo document 4274 pDoc->CopyToDocument( 4275 aDestArea.aStart.Col(), aDestArea.aStart.Row(), 0, 4276 aDestArea.aEnd.Col(), aDestArea.aEnd.Row(), nTabCount-1, 4277 IDF_AUTOFILL, sal_False, pUndoDoc, &aMark ); 4278 } 4279 4280 pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), 4281 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aMark, 4282 nCount, eDir, eCmd, eDateCmd, fStep, fMax ); 4283 4284 AdjustRowHeight(aDestArea); 4285 4286 if ( bRecord ) // Draw-Undo erst jetzt verfuegbar 4287 { 4288 rDocShell.GetUndoManager()->AddUndoAction( 4289 new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark, 4290 eDir, eCmd, eDateCmd, MAXDOUBLE, fStep, fMax, 4291 pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) ); 4292 } 4293 4294 rDocShell.PostPaintGridAll(); 4295 // rDocShell.PostPaintDataChanged(); 4296 aModificator.SetDocumentModified(); 4297 4298 rRange = aDestArea; // Zielbereich zurueckgeben (zum Markieren) 4299 return sal_True; 4300 } 4301 4302 //------------------------------------------------------------------------ 4303 4304 sal_Bool ScDocFunc::MergeCells( const ScRange& rRange, sal_Bool bContents, sal_Bool bRecord, sal_Bool bApi ) 4305 { 4306 ScDocShellModificator aModificator( rDocShell ); 4307 4308 ScDocument* pDoc = rDocShell.GetDocument(); 4309 SCCOL nStartCol = rRange.aStart.Col(); 4310 SCROW nStartRow = rRange.aStart.Row(); 4311 SCCOL nEndCol = rRange.aEnd.Col(); 4312 SCROW nEndRow = rRange.aEnd.Row(); 4313 SCTAB nTab = rRange.aStart.Tab(); 4314 4315 if (bRecord && !pDoc->IsUndoEnabled()) 4316 bRecord = sal_False; 4317 4318 ScEditableTester aTester( pDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow ); 4319 if (!aTester.IsEditable()) 4320 { 4321 if (!bApi) 4322 rDocShell.ErrorMessage(aTester.GetMessageId()); 4323 return sal_False; 4324 } 4325 4326 if ( nStartCol == nEndCol && nStartRow == nEndRow ) 4327 { 4328 // nichts zu tun 4329 return sal_True; 4330 } 4331 4332 if ( pDoc->HasAttrib( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, 4333 HASATTR_MERGED | HASATTR_OVERLAPPED ) ) 4334 { 4335 // "Zusammenfassen nicht verschachteln !" 4336 if (!bApi) 4337 rDocShell.ErrorMessage(STR_MSSG_MERGECELLS_0); 4338 return sal_False; 4339 } 4340 4341 sal_Bool bNeedContents = bContents && 4342 ( !pDoc->IsBlockEmpty( nTab, nStartCol,nStartRow+1, nStartCol,nEndRow, true ) || 4343 !pDoc->IsBlockEmpty( nTab, nStartCol+1,nStartRow, nEndCol,nEndRow, true ) ); 4344 4345 ScDocument* pUndoDoc = 0; 4346 if (bRecord) 4347 { 4348 // test if the range contains other notes which also implies that we need an undo document 4349 bool bHasNotes = false; 4350 for( ScAddress aPos( nStartCol, nStartRow, nTab ); !bHasNotes && (aPos.Col() <= nEndCol); aPos.IncCol() ) 4351 for( aPos.SetRow( nStartRow ); !bHasNotes && (aPos.Row() <= nEndRow); aPos.IncRow() ) 4352 bHasNotes = ((aPos.Col() != nStartCol) || (aPos.Row() != nStartRow)) && (pDoc->GetNote( aPos ) != 0); 4353 4354 if (bNeedContents || bHasNotes) 4355 { 4356 pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 4357 pUndoDoc->InitUndo( pDoc, nTab, nTab ); 4358 // note captions are collected by drawing undo 4359 pDoc->CopyToDocument( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, 4360 IDF_ALL|IDF_NOCAPTIONS, sal_False, pUndoDoc ); 4361 } 4362 if( bHasNotes ) 4363 pDoc->BeginDrawUndo(); 4364 } 4365 4366 if (bNeedContents) 4367 pDoc->DoMergeContents( nTab, nStartCol,nStartRow, nEndCol,nEndRow ); 4368 pDoc->DoMerge( nTab, nStartCol,nStartRow, nEndCol,nEndRow ); 4369 4370 if( bRecord ) 4371 { 4372 SdrUndoGroup* pDrawUndo = pDoc->GetDrawLayer() ? pDoc->GetDrawLayer()->GetCalcUndo() : 0; 4373 rDocShell.GetUndoManager()->AddUndoAction( 4374 new ScUndoMerge( &rDocShell, 4375 nStartCol, nStartRow, nTab, 4376 nEndCol, nEndRow, nTab, bNeedContents, pUndoDoc, pDrawUndo ) ); 4377 } 4378 4379 if ( !AdjustRowHeight( ScRange( 0,nStartRow,nTab, MAXCOL,nEndRow,nTab ) ) ) 4380 rDocShell.PostPaint( nStartCol, nStartRow, nTab, 4381 nEndCol, nEndRow, nTab, PAINT_GRID ); 4382 if (bNeedContents) 4383 pDoc->SetDirty( rRange ); 4384 aModificator.SetDocumentModified(); 4385 4386 SfxBindings* pBindings = rDocShell.GetViewBindings(); 4387 if (pBindings) 4388 { 4389 pBindings->Invalidate( FID_MERGE_ON ); 4390 pBindings->Invalidate( FID_MERGE_OFF ); 4391 pBindings->Invalidate( FID_MERGE_TOGGLE ); 4392 } 4393 4394 return sal_True; 4395 } 4396 4397 sal_Bool ScDocFunc::UnmergeCells( const ScRange& rRange, sal_Bool bRecord, sal_Bool bApi ) 4398 { 4399 ScDocShellModificator aModificator( rDocShell ); 4400 4401 ScDocument* pDoc = rDocShell.GetDocument(); 4402 SCTAB nTab = rRange.aStart.Tab(); 4403 4404 if (bRecord && !pDoc->IsUndoEnabled()) 4405 bRecord = sal_False; 4406 4407 if ( pDoc->HasAttrib( rRange, HASATTR_MERGED ) ) 4408 { 4409 ScRange aExtended = rRange; 4410 pDoc->ExtendMerge( aExtended ); 4411 ScRange aRefresh = aExtended; 4412 pDoc->ExtendOverlapped( aRefresh ); 4413 4414 if (bRecord) 4415 { 4416 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 4417 pUndoDoc->InitUndo( pDoc, nTab, nTab ); 4418 pDoc->CopyToDocument( aExtended, IDF_ATTRIB, sal_False, pUndoDoc ); 4419 rDocShell.GetUndoManager()->AddUndoAction( 4420 new ScUndoRemoveMerge( &rDocShell, rRange, pUndoDoc ) ); 4421 } 4422 4423 const SfxPoolItem& rDefAttr = pDoc->GetPool()->GetDefaultItem( ATTR_MERGE ); 4424 ScPatternAttr aPattern( pDoc->GetPool() ); 4425 aPattern.GetItemSet().Put( rDefAttr ); 4426 pDoc->ApplyPatternAreaTab( rRange.aStart.Col(), rRange.aStart.Row(), 4427 rRange.aEnd.Col(), rRange.aEnd.Row(), nTab, 4428 aPattern ); 4429 4430 pDoc->RemoveFlagsTab( aExtended.aStart.Col(), aExtended.aStart.Row(), 4431 aExtended.aEnd.Col(), aExtended.aEnd.Row(), nTab, 4432 SC_MF_HOR | SC_MF_VER ); 4433 4434 pDoc->ExtendMerge( aRefresh, sal_True, sal_False ); 4435 4436 if ( !AdjustRowHeight( aExtended ) ) 4437 rDocShell.PostPaint( aExtended, PAINT_GRID ); 4438 aModificator.SetDocumentModified(); 4439 } 4440 else if (!bApi) 4441 Sound::Beep(); //! sal_False zurueck??? 4442 4443 return sal_True; 4444 } 4445 4446 //------------------------------------------------------------------------ 4447 4448 sal_Bool ScDocFunc::ModifyRangeNames( const ScRangeName& rNewRanges, sal_Bool bApi ) 4449 { 4450 return SetNewRangeNames( new ScRangeName( rNewRanges ), bApi ); 4451 } 4452 4453 sal_Bool ScDocFunc::SetNewRangeNames( ScRangeName* pNewRanges, sal_Bool /* bApi */ ) // takes ownership of pNewRanges 4454 { 4455 ScDocShellModificator aModificator( rDocShell ); 4456 4457 DBG_ASSERT( pNewRanges, "pNewRanges is 0" ); 4458 ScDocument* pDoc = rDocShell.GetDocument(); 4459 sal_Bool bUndo(pDoc->IsUndoEnabled()); 4460 4461 if (bUndo) 4462 { 4463 ScRangeName* pOld = pDoc->GetRangeName(); 4464 ScRangeName* pUndoRanges = new ScRangeName(*pOld); 4465 ScRangeName* pRedoRanges = new ScRangeName(*pNewRanges); 4466 rDocShell.GetUndoManager()->AddUndoAction( 4467 new ScUndoRangeNames( &rDocShell, pUndoRanges, pRedoRanges ) ); 4468 } 4469 4470 // #i55926# While loading XML, formula cells only have a single string token, 4471 // so CompileNameFormula would never find any name (index) tokens, and would 4472 // unnecessarily loop through all cells. 4473 sal_Bool bCompile = ( !pDoc->IsImportingXML() && pDoc->GetNamedRangesLockCount() == 0 ); 4474 4475 if ( bCompile ) 4476 pDoc->CompileNameFormula( sal_True ); // CreateFormulaString 4477 pDoc->SetRangeName( pNewRanges ); // takes ownership 4478 if ( bCompile ) 4479 pDoc->CompileNameFormula( sal_False ); // CompileFormulaString 4480 4481 aModificator.SetDocumentModified(); 4482 4483 // #i114072# don't broadcast while loading a file 4484 // (navigator and input line for other open documents would be notified) 4485 if ( bCompile ) 4486 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) ); 4487 4488 return sal_True; 4489 } 4490 4491 //------------------------------------------------------------------------ 4492 4493 void ScDocFunc::CreateOneName( ScRangeName& rList, 4494 SCCOL nPosX, SCROW nPosY, SCTAB nTab, 4495 SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, 4496 sal_Bool& rCancel, sal_Bool bApi ) 4497 { 4498 if (rCancel) 4499 return; 4500 4501 ScDocument* pDoc = rDocShell.GetDocument(); 4502 if (!pDoc->HasValueData( nPosX, nPosY, nTab )) 4503 { 4504 String aName; 4505 pDoc->GetString( nPosX, nPosY, nTab, aName ); 4506 ScRangeData::MakeValidName(aName); 4507 if (aName.Len()) 4508 { 4509 String aContent; 4510 ScRange( nX1, nY1, nTab, nX2, nY2, nTab ).Format( aContent, SCR_ABS_3D, pDoc ); 4511 4512 sal_Bool bInsert = sal_False; 4513 sal_uInt16 nOldPos; 4514 if (rList.SearchName( aName, nOldPos )) // vorhanden ? 4515 { 4516 ScRangeData* pOld = rList[nOldPos]; 4517 String aOldStr; 4518 pOld->GetSymbol( aOldStr ); 4519 if (aOldStr != aContent) 4520 { 4521 if (bApi) 4522 bInsert = sal_True; // per API nicht nachfragen 4523 else 4524 { 4525 String aTemplate = ScGlobal::GetRscString( STR_CREATENAME_REPLACE ); 4526 4527 String aMessage = aTemplate.GetToken( 0, '#' ); 4528 aMessage += aName; 4529 aMessage += aTemplate.GetToken( 1, '#' ); 4530 4531 short nResult = QueryBox( rDocShell.GetActiveDialogParent(), 4532 WinBits(WB_YES_NO_CANCEL | WB_DEF_YES), 4533 aMessage ).Execute(); 4534 if ( nResult == RET_YES ) 4535 { 4536 rList.AtFree(nOldPos); 4537 bInsert = sal_True; 4538 } 4539 else if ( nResult == RET_CANCEL ) 4540 rCancel = sal_True; 4541 } 4542 } 4543 } 4544 else 4545 bInsert = sal_True; 4546 4547 if (bInsert) 4548 { 4549 ScRangeData* pData = new ScRangeData( pDoc, aName, aContent, 4550 ScAddress( nPosX, nPosY, nTab)); 4551 if (!rList.Insert(pData)) 4552 { 4553 DBG_ERROR("nanu?"); 4554 delete pData; 4555 } 4556 } 4557 } 4558 } 4559 } 4560 4561 sal_Bool ScDocFunc::CreateNames( const ScRange& rRange, sal_uInt16 nFlags, sal_Bool bApi ) 4562 { 4563 if (!nFlags) 4564 return sal_False; // war nix 4565 4566 ScDocShellModificator aModificator( rDocShell ); 4567 4568 sal_Bool bDone = sal_False; 4569 SCCOL nStartCol = rRange.aStart.Col(); 4570 SCROW nStartRow = rRange.aStart.Row(); 4571 SCCOL nEndCol = rRange.aEnd.Col(); 4572 SCROW nEndRow = rRange.aEnd.Row(); 4573 SCTAB nTab = rRange.aStart.Tab(); 4574 DBG_ASSERT(rRange.aEnd.Tab() == nTab, "CreateNames: mehrere Tabellen geht nicht"); 4575 4576 sal_Bool bValid = sal_True; 4577 if ( nFlags & ( NAME_TOP | NAME_BOTTOM ) ) 4578 if ( nStartRow == nEndRow ) 4579 bValid = sal_False; 4580 if ( nFlags & ( NAME_LEFT | NAME_RIGHT ) ) 4581 if ( nStartCol == nEndCol ) 4582 bValid = sal_False; 4583 4584 if (bValid) 4585 { 4586 ScDocument* pDoc = rDocShell.GetDocument(); 4587 ScRangeName* pNames = pDoc->GetRangeName(); 4588 if (!pNames) 4589 return sal_False; // soll nicht sein 4590 ScRangeName aNewRanges( *pNames ); 4591 4592 sal_Bool bTop = ( ( nFlags & NAME_TOP ) != 0 ); 4593 sal_Bool bLeft = ( ( nFlags & NAME_LEFT ) != 0 ); 4594 sal_Bool bBottom = ( ( nFlags & NAME_BOTTOM ) != 0 ); 4595 sal_Bool bRight = ( ( nFlags & NAME_RIGHT ) != 0 ); 4596 4597 SCCOL nContX1 = nStartCol; 4598 SCROW nContY1 = nStartRow; 4599 SCCOL nContX2 = nEndCol; 4600 SCROW nContY2 = nEndRow; 4601 4602 if ( bTop ) 4603 ++nContY1; 4604 if ( bLeft ) 4605 ++nContX1; 4606 if ( bBottom ) 4607 --nContY2; 4608 if ( bRight ) 4609 --nContX2; 4610 4611 sal_Bool bCancel = sal_False; 4612 SCCOL i; 4613 SCROW j; 4614 4615 if ( bTop ) 4616 for (i=nContX1; i<=nContX2; i++) 4617 CreateOneName( aNewRanges, i,nStartRow,nTab, i,nContY1,i,nContY2, bCancel, bApi ); 4618 if ( bLeft ) 4619 for (j=nContY1; j<=nContY2; j++) 4620 CreateOneName( aNewRanges, nStartCol,j,nTab, nContX1,j,nContX2,j, bCancel, bApi ); 4621 if ( bBottom ) 4622 for (i=nContX1; i<=nContX2; i++) 4623 CreateOneName( aNewRanges, i,nEndRow,nTab, i,nContY1,i,nContY2, bCancel, bApi ); 4624 if ( bRight ) 4625 for (j=nContY1; j<=nContY2; j++) 4626 CreateOneName( aNewRanges, nEndCol,j,nTab, nContX1,j,nContX2,j, bCancel, bApi ); 4627 4628 if ( bTop && bLeft ) 4629 CreateOneName( aNewRanges, nStartCol,nStartRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi ); 4630 if ( bTop && bRight ) 4631 CreateOneName( aNewRanges, nEndCol,nStartRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi ); 4632 if ( bBottom && bLeft ) 4633 CreateOneName( aNewRanges, nStartCol,nEndRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi ); 4634 if ( bBottom && bRight ) 4635 CreateOneName( aNewRanges, nEndCol,nEndRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi ); 4636 4637 bDone = ModifyRangeNames( aNewRanges, bApi ); 4638 4639 aModificator.SetDocumentModified(); 4640 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) ); 4641 } 4642 4643 return bDone; 4644 } 4645 4646 //------------------------------------------------------------------------ 4647 4648 sal_Bool ScDocFunc::InsertNameList( const ScAddress& rStartPos, sal_Bool bApi ) 4649 { 4650 ScDocShellModificator aModificator( rDocShell ); 4651 4652 4653 sal_Bool bDone = sal_False; 4654 ScDocument* pDoc = rDocShell.GetDocument(); 4655 const sal_Bool bRecord = pDoc->IsUndoEnabled(); 4656 SCTAB nTab = rStartPos.Tab(); 4657 ScDocument* pUndoDoc = NULL; 4658 4659 ScRangeName* pList = pDoc->GetRangeName(); 4660 sal_uInt16 nCount = pList->GetCount(); 4661 sal_uInt16 nValidCount = 0; 4662 sal_uInt16 i; 4663 for (i=0; i<nCount; i++) 4664 { 4665 ScRangeData* pData = (*pList)[i]; 4666 if ( !pData->HasType( RT_DATABASE ) && !pData->HasType( RT_SHARED ) ) 4667 ++nValidCount; 4668 } 4669 4670 if (nValidCount) 4671 { 4672 SCCOL nStartCol = rStartPos.Col(); 4673 SCROW nStartRow = rStartPos.Row(); 4674 SCCOL nEndCol = nStartCol + 1; 4675 SCROW nEndRow = nStartRow + static_cast<SCROW>(nValidCount) - 1; 4676 4677 ScEditableTester aTester( pDoc, nTab, nStartCol,nStartRow, nEndCol,nEndRow ); 4678 if (aTester.IsEditable()) 4679 { 4680 if (bRecord) 4681 { 4682 pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 4683 pUndoDoc->InitUndo( pDoc, nTab, nTab ); 4684 pDoc->CopyToDocument( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab, 4685 IDF_ALL, sal_False, pUndoDoc ); 4686 4687 pDoc->BeginDrawUndo(); // wegen Hoehenanpassung 4688 } 4689 4690 ScRangeData** ppSortArray = new ScRangeData* [ nValidCount ]; 4691 sal_uInt16 j = 0; 4692 for (i=0; i<nCount; i++) 4693 { 4694 ScRangeData* pData = (*pList)[i]; 4695 if ( !pData->HasType( RT_DATABASE ) && !pData->HasType( RT_SHARED ) ) 4696 ppSortArray[j++] = pData; 4697 } 4698 #ifndef ICC 4699 qsort( (void*)ppSortArray, nValidCount, sizeof(ScRangeData*), 4700 &ScRangeData_QsortNameCompare ); 4701 #else 4702 qsort( (void*)ppSortArray, nValidCount, sizeof(ScRangeData*), 4703 ICCQsortNameCompare ); 4704 #endif 4705 String aName; 4706 rtl::OUStringBuffer aContent; 4707 String aFormula; 4708 SCROW nOutRow = nStartRow; 4709 for (j=0; j<nValidCount; j++) 4710 { 4711 ScRangeData* pData = ppSortArray[j]; 4712 pData->GetName(aName); 4713 // relative Referenzen Excel-konform auf die linke Spalte anpassen: 4714 pData->UpdateSymbol(aContent, ScAddress( nStartCol, nOutRow, nTab )); 4715 aFormula = '='; 4716 aFormula += aContent; 4717 pDoc->PutCell( nStartCol,nOutRow,nTab, new ScStringCell( aName ) ); 4718 pDoc->PutCell( nEndCol ,nOutRow,nTab, new ScStringCell( aFormula ) ); 4719 ++nOutRow; 4720 } 4721 4722 delete [] ppSortArray; 4723 4724 if (bRecord) 4725 { 4726 ScDocument* pRedoDoc = new ScDocument( SCDOCMODE_UNDO ); 4727 pRedoDoc->InitUndo( pDoc, nTab, nTab ); 4728 pDoc->CopyToDocument( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab, 4729 IDF_ALL, sal_False, pRedoDoc ); 4730 4731 rDocShell.GetUndoManager()->AddUndoAction( 4732 new ScUndoListNames( &rDocShell, 4733 ScRange( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab ), 4734 pUndoDoc, pRedoDoc ) ); 4735 } 4736 4737 if (!AdjustRowHeight(ScRange(0,nStartRow,nTab,MAXCOL,nEndRow,nTab))) 4738 rDocShell.PostPaint( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab, PAINT_GRID ); 4739 //! rDocShell.UpdateOle(GetViewData()); 4740 aModificator.SetDocumentModified(); 4741 bDone = sal_True; 4742 } 4743 else if (!bApi) 4744 rDocShell.ErrorMessage(aTester.GetMessageId()); 4745 } 4746 return bDone; 4747 } 4748 4749 //------------------------------------------------------------------------ 4750 4751 sal_Bool ScDocFunc::ResizeMatrix( const ScRange& rOldRange, const ScAddress& rNewEnd, sal_Bool bApi ) 4752 { 4753 ScDocument* pDoc = rDocShell.GetDocument(); 4754 SCCOL nStartCol = rOldRange.aStart.Col(); 4755 SCROW nStartRow = rOldRange.aStart.Row(); 4756 SCTAB nTab = rOldRange.aStart.Tab(); 4757 4758 sal_Bool bUndo(pDoc->IsUndoEnabled()); 4759 4760 sal_Bool bRet = sal_False; 4761 4762 String aFormula; 4763 pDoc->GetFormula( nStartCol, nStartRow, nTab, aFormula ); 4764 if ( aFormula.GetChar(0) == '{' && aFormula.GetChar(aFormula.Len()-1) == '}' ) 4765 { 4766 String aUndo = ScGlobal::GetRscString( STR_UNDO_RESIZEMATRIX ); 4767 if (bUndo) 4768 rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo ); 4769 4770 aFormula.Erase(0,1); 4771 aFormula.Erase(aFormula.Len()-1,1); 4772 4773 ScMarkData aMark; 4774 aMark.SetMarkArea( rOldRange ); 4775 aMark.SelectTable( nTab, sal_True ); 4776 ScRange aNewRange( rOldRange.aStart, rNewEnd ); 4777 4778 if ( DeleteContents( aMark, IDF_CONTENTS, sal_True, bApi ) ) 4779 { 4780 // GRAM_PODF_A1 for API compatibility. 4781 bRet = EnterMatrix( aNewRange, &aMark, NULL, aFormula, bApi, sal_False, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 ); 4782 if (!bRet) 4783 { 4784 // versuchen, alten Zustand wiederherzustellen 4785 EnterMatrix( rOldRange, &aMark, NULL, aFormula, bApi, sal_False, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 ); 4786 } 4787 } 4788 4789 if (bUndo) 4790 rDocShell.GetUndoManager()->LeaveListAction(); 4791 } 4792 4793 return bRet; 4794 } 4795 4796 //------------------------------------------------------------------------ 4797 4798 sal_Bool ScDocFunc::InsertAreaLink( const String& rFile, const String& rFilter, 4799 const String& rOptions, const String& rSource, 4800 const ScRange& rDestRange, sal_uLong nRefresh, 4801 sal_Bool bFitBlock, sal_Bool bApi ) 4802 { 4803 //! auch fuer ScViewFunc::InsertAreaLink benutzen! 4804 4805 ScDocument* pDoc = rDocShell.GetDocument(); 4806 sal_Bool bUndo (pDoc->IsUndoEnabled()); 4807 4808 sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager(); 4809 4810 // #i52120# if other area links exist at the same start position, 4811 // remove them first (file format specifies only one link definition 4812 // for a cell) 4813 4814 sal_uInt16 nLinkCount = pLinkManager->GetLinks().Count(); 4815 sal_uInt16 nRemoved = 0; 4816 sal_uInt16 nLinkPos = 0; 4817 while (nLinkPos<nLinkCount) 4818 { 4819 ::sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[nLinkPos]; 4820 if ( pBase->ISA(ScAreaLink) && 4821 static_cast<ScAreaLink*>(pBase)->GetDestArea().aStart == rDestRange.aStart ) 4822 { 4823 if ( bUndo ) 4824 { 4825 if ( !nRemoved ) 4826 { 4827 // group all remove and the insert action 4828 String aUndo = ScGlobal::GetRscString( STR_UNDO_INSERTAREALINK ); 4829 rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo ); 4830 } 4831 4832 ScAreaLink* pOldArea = static_cast<ScAreaLink*>(pBase); 4833 rDocShell.GetUndoManager()->AddUndoAction( 4834 new ScUndoRemoveAreaLink( &rDocShell, 4835 pOldArea->GetFile(), pOldArea->GetFilter(), pOldArea->GetOptions(), 4836 pOldArea->GetSource(), pOldArea->GetDestArea(), pOldArea->GetRefreshDelay() ) ); 4837 } 4838 pLinkManager->Remove( pBase ); 4839 nLinkCount = pLinkManager->GetLinks().Count(); 4840 ++nRemoved; 4841 } 4842 else 4843 ++nLinkPos; 4844 } 4845 4846 String aFilterName = rFilter; 4847 String aNewOptions = rOptions; 4848 if (!aFilterName.Len()) 4849 ScDocumentLoader::GetFilterName( rFile, aFilterName, aNewOptions, sal_True, !bApi ); 4850 4851 // remove application prefix from filter name here, so the filter options 4852 // aren't reset when the filter name is changed in ScAreaLink::DataChanged 4853 ScDocumentLoader::RemoveAppPrefix( aFilterName ); 4854 4855 ScAreaLink* pLink = new ScAreaLink( &rDocShell, rFile, aFilterName, 4856 aNewOptions, rSource, rDestRange, nRefresh ); 4857 pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, rFile, &aFilterName, &rSource ); 4858 4859 // Undo fuer den leeren Link 4860 4861 if (bUndo) 4862 { 4863 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoInsertAreaLink( &rDocShell, 4864 rFile, aFilterName, aNewOptions, 4865 rSource, rDestRange, nRefresh ) ); 4866 if ( nRemoved ) 4867 rDocShell.GetUndoManager()->LeaveListAction(); // undo for link update is still separate 4868 } 4869 4870 // Update hat sein eigenes Undo 4871 if (pDoc->IsExecuteLinkEnabled()) 4872 { 4873 pLink->SetDoInsert(bFitBlock); // beim ersten Update ggf. nichts einfuegen 4874 pLink->Update(); // kein SetInCreate -> Update ausfuehren 4875 } 4876 pLink->SetDoInsert(sal_True); // Default = sal_True 4877 4878 SfxBindings* pBindings = rDocShell.GetViewBindings(); 4879 if (pBindings) 4880 pBindings->Invalidate( SID_LINKS ); 4881 4882 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); // Navigator 4883 4884 return sal_True; 4885 } 4886 4887 4888 4889 4890