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