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 pBindings->Invalidate( SID_ATTR_LRSPACE );//xuxu 3672 pBindings->Invalidate( SID_ATTR_PARA_ADJUST_LEFT ); 3673 pBindings->Invalidate( SID_ATTR_PARA_ADJUST_RIGHT ); 3674 pBindings->Invalidate( SID_ATTR_PARA_ADJUST_BLOCK ); 3675 pBindings->Invalidate( SID_ATTR_PARA_ADJUST_CENTER); 3676 // pseudo slots for Format menu 3677 pBindings->Invalidate( SID_ALIGN_ANY_HDEFAULT ); 3678 pBindings->Invalidate( SID_ALIGN_ANY_LEFT ); 3679 pBindings->Invalidate( SID_ALIGN_ANY_HCENTER ); 3680 pBindings->Invalidate( SID_ALIGN_ANY_RIGHT ); 3681 pBindings->Invalidate( SID_ALIGN_ANY_JUSTIFIED ); 3682 } 3683 3684 return sal_True; 3685 } 3686 3687 sal_Bool ScDocFunc::AutoFormat( const ScRange& rRange, const ScMarkData* pTabMark, 3688 sal_uInt16 nFormatNo, sal_Bool bRecord, sal_Bool bApi ) 3689 { 3690 ScDocShellModificator aModificator( rDocShell ); 3691 3692 sal_Bool bSuccess = sal_False; 3693 ScDocument* pDoc = rDocShell.GetDocument(); 3694 SCCOL nStartCol = rRange.aStart.Col(); 3695 SCROW nStartRow = rRange.aStart.Row(); 3696 SCTAB nStartTab = rRange.aStart.Tab(); 3697 SCCOL nEndCol = rRange.aEnd.Col(); 3698 SCROW nEndRow = rRange.aEnd.Row(); 3699 SCTAB nEndTab = rRange.aEnd.Tab(); 3700 3701 if (bRecord && !pDoc->IsUndoEnabled()) 3702 bRecord = sal_False; 3703 ScMarkData aMark; 3704 if (pTabMark) 3705 aMark = *pTabMark; 3706 else 3707 { 3708 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) 3709 aMark.SelectTable( nTab, sal_True ); 3710 } 3711 3712 ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat(); 3713 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark ); 3714 if ( pAutoFormat && nFormatNo < pAutoFormat->GetCount() && aTester.IsEditable() ) 3715 { 3716 WaitObject aWait( rDocShell.GetActiveDialogParent() ); 3717 3718 sal_Bool bSize = (*pAutoFormat)[nFormatNo]->GetIncludeWidthHeight(); 3719 3720 SCTAB nTabCount = pDoc->GetTableCount(); 3721 ScDocument* pUndoDoc = NULL; 3722 if ( bRecord ) 3723 { 3724 pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 3725 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab, bSize, bSize ); 3726 for (SCTAB i=0; i<nTabCount; i++) 3727 if (i != nStartTab && aMark.GetTableSelect(i)) 3728 pUndoDoc->AddUndoTab( i, i, bSize, bSize ); 3729 3730 ScRange aCopyRange = rRange; 3731 aCopyRange.aStart.SetTab(0); 3732 aCopyRange.aStart.SetTab(nTabCount-1); 3733 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, sal_False, pUndoDoc, &aMark ); 3734 if (bSize) 3735 { 3736 pDoc->CopyToDocument( nStartCol,0,0, nEndCol,MAXROW,nTabCount-1, 3737 IDF_NONE, sal_False, pUndoDoc, &aMark ); 3738 pDoc->CopyToDocument( 0,nStartRow,0, MAXCOL,nEndRow,nTabCount-1, 3739 IDF_NONE, sal_False, pUndoDoc, &aMark ); 3740 } 3741 pDoc->BeginDrawUndo(); 3742 } 3743 3744 pDoc->AutoFormat( nStartCol, nStartRow, nEndCol, nEndRow, nFormatNo, aMark ); 3745 3746 if (bSize) 3747 { 3748 /* SCCOL nCols[2]; 3749 nCols[0] = nStartCol; 3750 nCols[1] = nEndCol; 3751 SCROW nRows[2]; 3752 nRows[0] = nStartRow; 3753 nRows[1] = nEndRow; 3754 */ 3755 SCCOLROW nCols[2] = { nStartCol, nEndCol }; 3756 SCCOLROW nRows[2] = { nStartRow, nEndRow }; 3757 3758 for (SCTAB nTab=0; nTab<nTabCount; nTab++) 3759 if (aMark.GetTableSelect(nTab)) 3760 { 3761 SetWidthOrHeight( sal_True, 1,nCols, nTab, SC_SIZE_VISOPT, STD_EXTRA_WIDTH, sal_False, sal_True); 3762 SetWidthOrHeight( sal_False,1,nRows, nTab, SC_SIZE_VISOPT, 0, sal_False, sal_False); 3763 rDocShell.PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, 3764 PAINT_GRID | PAINT_LEFT | PAINT_TOP ); 3765 } 3766 } 3767 else 3768 { 3769 for (SCTAB nTab=0; nTab<nTabCount; nTab++) 3770 if (aMark.GetTableSelect(nTab)) 3771 { 3772 sal_Bool bAdj = AdjustRowHeight( ScRange(nStartCol, nStartRow, nTab, 3773 nEndCol, nEndRow, nTab), sal_False ); 3774 if (bAdj) 3775 rDocShell.PostPaint( 0,nStartRow,nTab, MAXCOL,MAXROW,nTab, 3776 PAINT_GRID | PAINT_LEFT ); 3777 else 3778 rDocShell.PostPaint( nStartCol, nStartRow, nTab, 3779 nEndCol, nEndRow, nTab, PAINT_GRID ); 3780 } 3781 } 3782 3783 if ( bRecord ) // Draw-Undo erst jetzt verfuegbar 3784 { 3785 rDocShell.GetUndoManager()->AddUndoAction( 3786 new ScUndoAutoFormat( &rDocShell, rRange, pUndoDoc, aMark, bSize, nFormatNo ) ); 3787 } 3788 3789 aModificator.SetDocumentModified(); 3790 } 3791 else if (!bApi) 3792 rDocShell.ErrorMessage(aTester.GetMessageId()); 3793 3794 return bSuccess; 3795 } 3796 3797 //------------------------------------------------------------------------ 3798 3799 sal_Bool ScDocFunc::EnterMatrix( const ScRange& rRange, const ScMarkData* pTabMark, 3800 const ScTokenArray* pTokenArray, const String& rString, sal_Bool bApi, sal_Bool bEnglish, 3801 const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar ) 3802 { 3803 ScDocShellModificator aModificator( rDocShell ); 3804 3805 sal_Bool bSuccess = sal_False; 3806 ScDocument* pDoc = rDocShell.GetDocument(); 3807 SCCOL nStartCol = rRange.aStart.Col(); 3808 SCROW nStartRow = rRange.aStart.Row(); 3809 SCTAB nStartTab = rRange.aStart.Tab(); 3810 SCCOL nEndCol = rRange.aEnd.Col(); 3811 SCROW nEndRow = rRange.aEnd.Row(); 3812 SCTAB nEndTab = rRange.aEnd.Tab(); 3813 3814 sal_Bool bUndo(pDoc->IsUndoEnabled()); 3815 3816 ScMarkData aMark; 3817 if (pTabMark) 3818 aMark = *pTabMark; 3819 else 3820 { 3821 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) 3822 aMark.SelectTable( nTab, sal_True ); 3823 } 3824 3825 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark ); 3826 if ( aTester.IsEditable() ) 3827 { 3828 WaitObject aWait( rDocShell.GetActiveDialogParent() ); 3829 3830 ScDocument* pUndoDoc = NULL; 3831 // if (bRecord) // immer 3832 if (bUndo) 3833 { 3834 //! auch bei Undo selektierte Tabellen beruecksichtigen 3835 pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 3836 pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab ); 3837 pDoc->CopyToDocument( rRange, IDF_ALL & ~IDF_NOTE, sal_False, pUndoDoc ); 3838 } 3839 3840 // use TokenArray if given, string (and flags) otherwise 3841 if ( pTokenArray ) 3842 { 3843 pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow, 3844 aMark, EMPTY_STRING, pTokenArray, eGrammar); 3845 } 3846 else if ( pDoc->IsImportingXML() ) 3847 { 3848 ScTokenArray* pCode = lcl_ScDocFunc_CreateTokenArrayXML( rString, rFormulaNmsp, eGrammar ); 3849 pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow, 3850 aMark, EMPTY_STRING, pCode, eGrammar); 3851 delete pCode; 3852 pDoc->IncXMLImportedFormulaCount( rString.Len() ); 3853 } 3854 else if (bEnglish) 3855 { 3856 ScCompiler aComp( pDoc, rRange.aStart); 3857 aComp.SetGrammar(eGrammar); 3858 ScTokenArray* pCode = aComp.CompileString( rString ); 3859 pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow, 3860 aMark, EMPTY_STRING, pCode, eGrammar); 3861 delete pCode; 3862 } 3863 else 3864 pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow, 3865 aMark, rString, NULL, eGrammar); 3866 3867 // if (bRecord) // immer 3868 if (bUndo) 3869 { 3870 //! auch bei Undo selektierte Tabellen beruecksichtigen 3871 rDocShell.GetUndoManager()->AddUndoAction( 3872 new ScUndoEnterMatrix( &rDocShell, rRange, pUndoDoc, rString ) ); 3873 } 3874 3875 // Err522 beim Paint von DDE-Formeln werden jetzt beim Interpretieren abgefangen 3876 rDocShell.PostPaint( nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab, PAINT_GRID ); 3877 aModificator.SetDocumentModified(); 3878 3879 bSuccess = sal_True; 3880 } 3881 else if (!bApi) 3882 rDocShell.ErrorMessage(aTester.GetMessageId()); 3883 3884 return bSuccess; 3885 } 3886 3887 //------------------------------------------------------------------------ 3888 3889 sal_Bool ScDocFunc::TabOp( const ScRange& rRange, const ScMarkData* pTabMark, 3890 const ScTabOpParam& rParam, sal_Bool bRecord, sal_Bool bApi ) 3891 { 3892 ScDocShellModificator aModificator( rDocShell ); 3893 3894 sal_Bool bSuccess = sal_False; 3895 ScDocument* pDoc = rDocShell.GetDocument(); 3896 SCCOL nStartCol = rRange.aStart.Col(); 3897 SCROW nStartRow = rRange.aStart.Row(); 3898 SCTAB nStartTab = rRange.aStart.Tab(); 3899 SCCOL nEndCol = rRange.aEnd.Col(); 3900 SCROW nEndRow = rRange.aEnd.Row(); 3901 SCTAB nEndTab = rRange.aEnd.Tab(); 3902 3903 if (bRecord && !pDoc->IsUndoEnabled()) 3904 bRecord = sal_False; 3905 3906 ScMarkData aMark; 3907 if (pTabMark) 3908 aMark = *pTabMark; 3909 else 3910 { 3911 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) 3912 aMark.SelectTable( nTab, sal_True ); 3913 } 3914 3915 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark ); 3916 if ( aTester.IsEditable() ) 3917 { 3918 WaitObject aWait( rDocShell.GetActiveDialogParent() ); 3919 pDoc->SetDirty( rRange ); 3920 if ( bRecord ) 3921 { 3922 //! auch bei Undo selektierte Tabellen beruecksichtigen 3923 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 3924 pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab ); 3925 pDoc->CopyToDocument( rRange, IDF_ALL & ~IDF_NOTE, sal_False, pUndoDoc ); 3926 3927 rDocShell.GetUndoManager()->AddUndoAction( 3928 new ScUndoTabOp( &rDocShell, 3929 nStartCol, nStartRow, nStartTab, 3930 nEndCol, nEndRow, nEndTab, pUndoDoc, 3931 rParam.aRefFormulaCell, 3932 rParam.aRefFormulaEnd, 3933 rParam.aRefRowCell, 3934 rParam.aRefColCell, 3935 rParam.nMode) ); 3936 } 3937 pDoc->InsertTableOp(rParam, nStartCol, nStartRow, nEndCol, nEndRow, aMark); 3938 rDocShell.PostPaintGridAll(); 3939 aModificator.SetDocumentModified(); 3940 bSuccess = sal_True; 3941 } 3942 else if (!bApi) 3943 rDocShell.ErrorMessage(aTester.GetMessageId()); 3944 3945 return bSuccess; 3946 } 3947 3948 //------------------------------------------------------------------------ 3949 3950 inline ScDirection DirFromFillDir( FillDir eDir ) 3951 { 3952 if (eDir==FILL_TO_BOTTOM) 3953 return DIR_BOTTOM; 3954 else if (eDir==FILL_TO_RIGHT) 3955 return DIR_RIGHT; 3956 else if (eDir==FILL_TO_TOP) 3957 return DIR_TOP; 3958 else // if (eDir==FILL_TO_LEFT) 3959 return DIR_LEFT; 3960 } 3961 3962 sal_Bool ScDocFunc::FillSimple( const ScRange& rRange, const ScMarkData* pTabMark, 3963 FillDir eDir, sal_Bool bRecord, sal_Bool bApi ) 3964 { 3965 ScDocShellModificator aModificator( rDocShell ); 3966 3967 sal_Bool bSuccess = sal_False; 3968 ScDocument* pDoc = rDocShell.GetDocument(); 3969 SCCOL nStartCol = rRange.aStart.Col(); 3970 SCROW nStartRow = rRange.aStart.Row(); 3971 SCTAB nStartTab = rRange.aStart.Tab(); 3972 SCCOL nEndCol = rRange.aEnd.Col(); 3973 SCROW nEndRow = rRange.aEnd.Row(); 3974 SCTAB nEndTab = rRange.aEnd.Tab(); 3975 3976 if (bRecord && !pDoc->IsUndoEnabled()) 3977 bRecord = sal_False; 3978 3979 ScMarkData aMark; 3980 if (pTabMark) 3981 aMark = *pTabMark; 3982 else 3983 { 3984 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) 3985 aMark.SelectTable( nTab, sal_True ); 3986 } 3987 3988 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark ); 3989 if ( aTester.IsEditable() ) 3990 { 3991 WaitObject aWait( rDocShell.GetActiveDialogParent() ); 3992 3993 ScRange aSourceArea = rRange; 3994 ScRange aDestArea = rRange; 3995 3996 SCCOLROW nCount = 0; 3997 switch (eDir) 3998 { 3999 case FILL_TO_BOTTOM: 4000 nCount = aSourceArea.aEnd.Row()-aSourceArea.aStart.Row(); 4001 aSourceArea.aEnd.SetRow( aSourceArea.aStart.Row() ); 4002 break; 4003 case FILL_TO_RIGHT: 4004 nCount = aSourceArea.aEnd.Col()-aSourceArea.aStart.Col(); 4005 aSourceArea.aEnd.SetCol( aSourceArea.aStart.Col() ); 4006 break; 4007 case FILL_TO_TOP: 4008 nCount = aSourceArea.aEnd.Row()-aSourceArea.aStart.Row(); 4009 aSourceArea.aStart.SetRow( aSourceArea.aEnd.Row() ); 4010 break; 4011 case FILL_TO_LEFT: 4012 nCount = aSourceArea.aEnd.Col()-aSourceArea.aStart.Col(); 4013 aSourceArea.aStart.SetCol( aSourceArea.aEnd.Col() ); 4014 break; 4015 } 4016 4017 ScDocument* pUndoDoc = NULL; 4018 if ( bRecord ) 4019 { 4020 SCTAB nTabCount = pDoc->GetTableCount(); 4021 SCTAB nDestStartTab = aDestArea.aStart.Tab(); 4022 4023 pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 4024 pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab ); 4025 for (SCTAB i=0; i<nTabCount; i++) 4026 if (i != nDestStartTab && aMark.GetTableSelect(i)) 4027 pUndoDoc->AddUndoTab( i, i ); 4028 4029 ScRange aCopyRange = aDestArea; 4030 aCopyRange.aStart.SetTab(0); 4031 aCopyRange.aEnd.SetTab(nTabCount-1); 4032 pDoc->CopyToDocument( aCopyRange, IDF_AUTOFILL, sal_False, pUndoDoc, &aMark ); 4033 } 4034 4035 pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), 4036 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aMark, 4037 nCount, eDir, FILL_SIMPLE ); 4038 AdjustRowHeight(rRange); 4039 4040 if ( bRecord ) // Draw-Undo erst jetzt verfuegbar 4041 { 4042 rDocShell.GetUndoManager()->AddUndoAction( 4043 new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark, 4044 eDir, FILL_SIMPLE, FILL_DAY, MAXDOUBLE, 1.0, 1e307, 4045 pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) ); 4046 } 4047 4048 rDocShell.PostPaintGridAll(); 4049 // rDocShell.PostPaintDataChanged(); 4050 aModificator.SetDocumentModified(); 4051 4052 bSuccess = sal_True; 4053 } 4054 else if (!bApi) 4055 rDocShell.ErrorMessage(aTester.GetMessageId()); 4056 4057 return bSuccess; 4058 } 4059 4060 sal_Bool ScDocFunc::FillSeries( const ScRange& rRange, const ScMarkData* pTabMark, 4061 FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd, 4062 double fStart, double fStep, double fMax, 4063 sal_Bool bRecord, sal_Bool bApi ) 4064 { 4065 ScDocShellModificator aModificator( rDocShell ); 4066 4067 sal_Bool bSuccess = sal_False; 4068 ScDocument* pDoc = rDocShell.GetDocument(); 4069 SCCOL nStartCol = rRange.aStart.Col(); 4070 SCROW nStartRow = rRange.aStart.Row(); 4071 SCTAB nStartTab = rRange.aStart.Tab(); 4072 SCCOL nEndCol = rRange.aEnd.Col(); 4073 SCROW nEndRow = rRange.aEnd.Row(); 4074 SCTAB nEndTab = rRange.aEnd.Tab(); 4075 4076 if (bRecord && !pDoc->IsUndoEnabled()) 4077 bRecord = sal_False; 4078 4079 ScMarkData aMark; 4080 if (pTabMark) 4081 aMark = *pTabMark; 4082 else 4083 { 4084 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) 4085 aMark.SelectTable( nTab, sal_True ); 4086 } 4087 4088 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark ); 4089 if ( aTester.IsEditable() ) 4090 { 4091 WaitObject aWait( rDocShell.GetActiveDialogParent() ); 4092 4093 ScRange aSourceArea = rRange; 4094 ScRange aDestArea = rRange; 4095 4096 SCSIZE nCount = pDoc->GetEmptyLinesInBlock( 4097 aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), aSourceArea.aStart.Tab(), 4098 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aSourceArea.aEnd.Tab(), 4099 DirFromFillDir(eDir) ); 4100 4101 // #27665# mindestens eine Zeile/Spalte als Quellbereich behalten: 4102 SCSIZE nTotLines = ( eDir == FILL_TO_BOTTOM || eDir == FILL_TO_TOP ) ? 4103 static_cast<SCSIZE>( aSourceArea.aEnd.Row() - aSourceArea.aStart.Row() + 1 ) : 4104 static_cast<SCSIZE>( aSourceArea.aEnd.Col() - aSourceArea.aStart.Col() + 1 ); 4105 if ( nCount >= nTotLines ) 4106 nCount = nTotLines - 1; 4107 4108 switch (eDir) 4109 { 4110 case FILL_TO_BOTTOM: 4111 aSourceArea.aEnd.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aEnd.Row() - nCount ) ); 4112 break; 4113 case FILL_TO_RIGHT: 4114 aSourceArea.aEnd.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aEnd.Col() - nCount ) ); 4115 break; 4116 case FILL_TO_TOP: 4117 aSourceArea.aStart.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aStart.Row() + nCount ) ); 4118 break; 4119 case FILL_TO_LEFT: 4120 aSourceArea.aStart.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aStart.Col() + nCount ) ); 4121 break; 4122 } 4123 4124 ScDocument* pUndoDoc = NULL; 4125 if ( bRecord ) 4126 { 4127 SCTAB nTabCount = pDoc->GetTableCount(); 4128 SCTAB nDestStartTab = aDestArea.aStart.Tab(); 4129 4130 pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 4131 pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab ); 4132 for (SCTAB i=0; i<nTabCount; i++) 4133 if (i != nDestStartTab && aMark.GetTableSelect(i)) 4134 pUndoDoc->AddUndoTab( i, i ); 4135 4136 pDoc->CopyToDocument( 4137 aDestArea.aStart.Col(), aDestArea.aStart.Row(), 0, 4138 aDestArea.aEnd.Col(), aDestArea.aEnd.Row(), nTabCount-1, 4139 IDF_AUTOFILL, sal_False, pUndoDoc, &aMark ); 4140 } 4141 4142 if (aDestArea.aStart.Col() <= aDestArea.aEnd.Col() && 4143 aDestArea.aStart.Row() <= aDestArea.aEnd.Row()) 4144 { 4145 if ( fStart != MAXDOUBLE ) 4146 { 4147 SCCOL nValX = (eDir == FILL_TO_LEFT) ? aDestArea.aEnd.Col() : aDestArea.aStart.Col(); 4148 SCROW nValY = (eDir == FILL_TO_TOP ) ? aDestArea.aEnd.Row() : aDestArea.aStart.Row(); 4149 SCTAB nTab = aDestArea.aStart.Tab(); 4150 pDoc->SetValue( nValX, nValY, nTab, fStart ); 4151 } 4152 pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), 4153 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aMark, 4154 nCount, eDir, eCmd, eDateCmd, fStep, fMax ); 4155 AdjustRowHeight(rRange); 4156 4157 rDocShell.PostPaintGridAll(); 4158 // rDocShell.PostPaintDataChanged(); 4159 aModificator.SetDocumentModified(); 4160 } 4161 4162 if ( bRecord ) // Draw-Undo erst jetzt verfuegbar 4163 { 4164 rDocShell.GetUndoManager()->AddUndoAction( 4165 new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark, 4166 eDir, eCmd, eDateCmd, fStart, fStep, fMax, 4167 pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) ); 4168 } 4169 4170 bSuccess = sal_True; 4171 } 4172 else if (!bApi) 4173 rDocShell.ErrorMessage(aTester.GetMessageId()); 4174 4175 return bSuccess; 4176 } 4177 4178 sal_Bool ScDocFunc::FillAuto( ScRange& rRange, const ScMarkData* pTabMark, 4179 FillDir eDir, sal_uLong nCount, sal_Bool bRecord, sal_Bool bApi ) 4180 { 4181 ScDocShellModificator aModificator( rDocShell ); 4182 4183 ScDocument* pDoc = rDocShell.GetDocument(); 4184 SCCOL nStartCol = rRange.aStart.Col(); 4185 SCROW nStartRow = rRange.aStart.Row(); 4186 SCTAB nStartTab = rRange.aStart.Tab(); 4187 SCCOL nEndCol = rRange.aEnd.Col(); 4188 SCROW nEndRow = rRange.aEnd.Row(); 4189 SCTAB nEndTab = rRange.aEnd.Tab(); 4190 4191 if (bRecord && !pDoc->IsUndoEnabled()) 4192 bRecord = sal_False; 4193 4194 ScMarkData aMark; 4195 if (pTabMark) 4196 aMark = *pTabMark; 4197 else 4198 { 4199 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) 4200 aMark.SelectTable( nTab, sal_True ); 4201 } 4202 4203 ScRange aSourceArea = rRange; 4204 ScRange aDestArea = rRange; 4205 4206 FillCmd eCmd = FILL_AUTO; 4207 FillDateCmd eDateCmd = FILL_DAY; 4208 double fStep = 1.0; 4209 double fMax = MAXDOUBLE; 4210 4211 switch (eDir) 4212 { 4213 case FILL_TO_BOTTOM: 4214 aDestArea.aEnd.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aEnd.Row() + nCount ) ); 4215 break; 4216 case FILL_TO_TOP: 4217 if (nCount > sal::static_int_cast<sal_uLong>( aSourceArea.aStart.Row() )) 4218 { 4219 DBG_ERROR("FillAuto: Row < 0"); 4220 nCount = aSourceArea.aStart.Row(); 4221 } 4222 aDestArea.aStart.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aStart.Row() - nCount ) ); 4223 break; 4224 case FILL_TO_RIGHT: 4225 aDestArea.aEnd.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aEnd.Col() + nCount ) ); 4226 break; 4227 case FILL_TO_LEFT: 4228 if (nCount > sal::static_int_cast<sal_uLong>( aSourceArea.aStart.Col() )) 4229 { 4230 DBG_ERROR("FillAuto: Col < 0"); 4231 nCount = aSourceArea.aStart.Col(); 4232 } 4233 aDestArea.aStart.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aStart.Col() - nCount ) ); 4234 break; 4235 default: 4236 DBG_ERROR("Falsche Richtung bei FillAuto"); 4237 break; 4238 } 4239 4240 // Zellschutz testen 4241 //! Quellbereich darf geschuetzt sein !!! 4242 //! aber kein Matrixfragment enthalten !!! 4243 4244 ScEditableTester aTester( pDoc, aDestArea ); 4245 if ( !aTester.IsEditable() ) 4246 { 4247 if (!bApi) 4248 rDocShell.ErrorMessage(aTester.GetMessageId()); 4249 return sal_False; 4250 } 4251 4252 if ( pDoc->HasSelectedBlockMatrixFragment( nStartCol, nStartRow, 4253 nEndCol, nEndRow, aMark ) ) 4254 { 4255 if (!bApi) 4256 rDocShell.ErrorMessage(STR_MATRIXFRAGMENTERR); 4257 return sal_False; 4258 } 4259 4260 WaitObject aWait( rDocShell.GetActiveDialogParent() ); 4261 4262 ScDocument* pUndoDoc = NULL; 4263 if ( bRecord ) 4264 { 4265 SCTAB nTabCount = pDoc->GetTableCount(); 4266 SCTAB nDestStartTab = aDestArea.aStart.Tab(); 4267 4268 pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 4269 pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab ); 4270 for (SCTAB i=0; i<nTabCount; i++) 4271 if (i != nDestStartTab && aMark.GetTableSelect(i)) 4272 pUndoDoc->AddUndoTab( i, i ); 4273 4274 // do not clone note captions in undo document 4275 pDoc->CopyToDocument( 4276 aDestArea.aStart.Col(), aDestArea.aStart.Row(), 0, 4277 aDestArea.aEnd.Col(), aDestArea.aEnd.Row(), nTabCount-1, 4278 IDF_AUTOFILL, sal_False, pUndoDoc, &aMark ); 4279 } 4280 4281 pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), 4282 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aMark, 4283 nCount, eDir, eCmd, eDateCmd, fStep, fMax ); 4284 4285 AdjustRowHeight(aDestArea); 4286 4287 if ( bRecord ) // Draw-Undo erst jetzt verfuegbar 4288 { 4289 rDocShell.GetUndoManager()->AddUndoAction( 4290 new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark, 4291 eDir, eCmd, eDateCmd, MAXDOUBLE, fStep, fMax, 4292 pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) ); 4293 } 4294 4295 rDocShell.PostPaintGridAll(); 4296 // rDocShell.PostPaintDataChanged(); 4297 aModificator.SetDocumentModified(); 4298 4299 rRange = aDestArea; // Zielbereich zurueckgeben (zum Markieren) 4300 return sal_True; 4301 } 4302 4303 //------------------------------------------------------------------------ 4304 4305 sal_Bool ScDocFunc::MergeCells( const ScRange& rRange, sal_Bool bContents, sal_Bool bRecord, sal_Bool bApi ) 4306 { 4307 ScDocShellModificator aModificator( rDocShell ); 4308 4309 ScDocument* pDoc = rDocShell.GetDocument(); 4310 SCCOL nStartCol = rRange.aStart.Col(); 4311 SCROW nStartRow = rRange.aStart.Row(); 4312 SCCOL nEndCol = rRange.aEnd.Col(); 4313 SCROW nEndRow = rRange.aEnd.Row(); 4314 SCTAB nTab = rRange.aStart.Tab(); 4315 4316 if (bRecord && !pDoc->IsUndoEnabled()) 4317 bRecord = sal_False; 4318 4319 ScEditableTester aTester( pDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow ); 4320 if (!aTester.IsEditable()) 4321 { 4322 if (!bApi) 4323 rDocShell.ErrorMessage(aTester.GetMessageId()); 4324 return sal_False; 4325 } 4326 4327 if ( nStartCol == nEndCol && nStartRow == nEndRow ) 4328 { 4329 // nichts zu tun 4330 return sal_True; 4331 } 4332 4333 if ( pDoc->HasAttrib( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, 4334 HASATTR_MERGED | HASATTR_OVERLAPPED ) ) 4335 { 4336 // "Zusammenfassen nicht verschachteln !" 4337 if (!bApi) 4338 rDocShell.ErrorMessage(STR_MSSG_MERGECELLS_0); 4339 return sal_False; 4340 } 4341 4342 sal_Bool bNeedContents = bContents && 4343 ( !pDoc->IsBlockEmpty( nTab, nStartCol,nStartRow+1, nStartCol,nEndRow, true ) || 4344 !pDoc->IsBlockEmpty( nTab, nStartCol+1,nStartRow, nEndCol,nEndRow, true ) ); 4345 4346 ScDocument* pUndoDoc = 0; 4347 if (bRecord) 4348 { 4349 // test if the range contains other notes which also implies that we need an undo document 4350 bool bHasNotes = false; 4351 for( ScAddress aPos( nStartCol, nStartRow, nTab ); !bHasNotes && (aPos.Col() <= nEndCol); aPos.IncCol() ) 4352 for( aPos.SetRow( nStartRow ); !bHasNotes && (aPos.Row() <= nEndRow); aPos.IncRow() ) 4353 bHasNotes = ((aPos.Col() != nStartCol) || (aPos.Row() != nStartRow)) && (pDoc->GetNote( aPos ) != 0); 4354 4355 if (bNeedContents || bHasNotes) 4356 { 4357 pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 4358 pUndoDoc->InitUndo( pDoc, nTab, nTab ); 4359 // note captions are collected by drawing undo 4360 pDoc->CopyToDocument( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, 4361 IDF_ALL|IDF_NOCAPTIONS, sal_False, pUndoDoc ); 4362 } 4363 if( bHasNotes ) 4364 pDoc->BeginDrawUndo(); 4365 } 4366 4367 if (bNeedContents) 4368 pDoc->DoMergeContents( nTab, nStartCol,nStartRow, nEndCol,nEndRow ); 4369 pDoc->DoMerge( nTab, nStartCol,nStartRow, nEndCol,nEndRow ); 4370 4371 if( bRecord ) 4372 { 4373 SdrUndoGroup* pDrawUndo = pDoc->GetDrawLayer() ? pDoc->GetDrawLayer()->GetCalcUndo() : 0; 4374 rDocShell.GetUndoManager()->AddUndoAction( 4375 new ScUndoMerge( &rDocShell, 4376 nStartCol, nStartRow, nTab, 4377 nEndCol, nEndRow, nTab, bNeedContents, pUndoDoc, pDrawUndo ) ); 4378 } 4379 4380 if ( !AdjustRowHeight( ScRange( 0,nStartRow,nTab, MAXCOL,nEndRow,nTab ) ) ) 4381 rDocShell.PostPaint( nStartCol, nStartRow, nTab, 4382 nEndCol, nEndRow, nTab, PAINT_GRID ); 4383 if (bNeedContents) 4384 pDoc->SetDirty( rRange ); 4385 aModificator.SetDocumentModified(); 4386 4387 SfxBindings* pBindings = rDocShell.GetViewBindings(); 4388 if (pBindings) 4389 { 4390 pBindings->Invalidate( FID_MERGE_ON ); 4391 pBindings->Invalidate( FID_MERGE_OFF ); 4392 pBindings->Invalidate( FID_MERGE_TOGGLE ); 4393 } 4394 4395 return sal_True; 4396 } 4397 4398 sal_Bool ScDocFunc::UnmergeCells( const ScRange& rRange, sal_Bool bRecord, sal_Bool bApi ) 4399 { 4400 ScDocShellModificator aModificator( rDocShell ); 4401 4402 ScDocument* pDoc = rDocShell.GetDocument(); 4403 SCTAB nTab = rRange.aStart.Tab(); 4404 4405 if (bRecord && !pDoc->IsUndoEnabled()) 4406 bRecord = sal_False; 4407 4408 if ( pDoc->HasAttrib( rRange, HASATTR_MERGED ) ) 4409 { 4410 ScRange aExtended = rRange; 4411 pDoc->ExtendMerge( aExtended ); 4412 ScRange aRefresh = aExtended; 4413 pDoc->ExtendOverlapped( aRefresh ); 4414 4415 if (bRecord) 4416 { 4417 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 4418 pUndoDoc->InitUndo( pDoc, nTab, nTab ); 4419 pDoc->CopyToDocument( aExtended, IDF_ATTRIB, sal_False, pUndoDoc ); 4420 rDocShell.GetUndoManager()->AddUndoAction( 4421 new ScUndoRemoveMerge( &rDocShell, rRange, pUndoDoc ) ); 4422 } 4423 4424 const SfxPoolItem& rDefAttr = pDoc->GetPool()->GetDefaultItem( ATTR_MERGE ); 4425 ScPatternAttr aPattern( pDoc->GetPool() ); 4426 aPattern.GetItemSet().Put( rDefAttr ); 4427 pDoc->ApplyPatternAreaTab( rRange.aStart.Col(), rRange.aStart.Row(), 4428 rRange.aEnd.Col(), rRange.aEnd.Row(), nTab, 4429 aPattern ); 4430 4431 pDoc->RemoveFlagsTab( aExtended.aStart.Col(), aExtended.aStart.Row(), 4432 aExtended.aEnd.Col(), aExtended.aEnd.Row(), nTab, 4433 SC_MF_HOR | SC_MF_VER ); 4434 4435 pDoc->ExtendMerge( aRefresh, sal_True, sal_False ); 4436 4437 if ( !AdjustRowHeight( aExtended ) ) 4438 rDocShell.PostPaint( aExtended, PAINT_GRID ); 4439 aModificator.SetDocumentModified(); 4440 } 4441 else if (!bApi) 4442 Sound::Beep(); //! sal_False zurueck??? 4443 4444 return sal_True; 4445 } 4446 4447 //------------------------------------------------------------------------ 4448 4449 sal_Bool ScDocFunc::ModifyRangeNames( const ScRangeName& rNewRanges, sal_Bool bApi ) 4450 { 4451 return SetNewRangeNames( new ScRangeName( rNewRanges ), bApi ); 4452 } 4453 4454 sal_Bool ScDocFunc::SetNewRangeNames( ScRangeName* pNewRanges, sal_Bool /* bApi */ ) // takes ownership of pNewRanges 4455 { 4456 ScDocShellModificator aModificator( rDocShell ); 4457 4458 DBG_ASSERT( pNewRanges, "pNewRanges is 0" ); 4459 ScDocument* pDoc = rDocShell.GetDocument(); 4460 sal_Bool bUndo(pDoc->IsUndoEnabled()); 4461 4462 if (bUndo) 4463 { 4464 ScRangeName* pOld = pDoc->GetRangeName(); 4465 ScRangeName* pUndoRanges = new ScRangeName(*pOld); 4466 ScRangeName* pRedoRanges = new ScRangeName(*pNewRanges); 4467 rDocShell.GetUndoManager()->AddUndoAction( 4468 new ScUndoRangeNames( &rDocShell, pUndoRanges, pRedoRanges ) ); 4469 } 4470 4471 // #i55926# While loading XML, formula cells only have a single string token, 4472 // so CompileNameFormula would never find any name (index) tokens, and would 4473 // unnecessarily loop through all cells. 4474 sal_Bool bCompile = ( !pDoc->IsImportingXML() && pDoc->GetNamedRangesLockCount() == 0 ); 4475 4476 if ( bCompile ) 4477 pDoc->CompileNameFormula( sal_True ); // CreateFormulaString 4478 pDoc->SetRangeName( pNewRanges ); // takes ownership 4479 if ( bCompile ) 4480 pDoc->CompileNameFormula( sal_False ); // CompileFormulaString 4481 4482 aModificator.SetDocumentModified(); 4483 4484 // #i114072# don't broadcast while loading a file 4485 // (navigator and input line for other open documents would be notified) 4486 if ( bCompile ) 4487 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) ); 4488 4489 return sal_True; 4490 } 4491 4492 //------------------------------------------------------------------------ 4493 4494 void ScDocFunc::CreateOneName( ScRangeName& rList, 4495 SCCOL nPosX, SCROW nPosY, SCTAB nTab, 4496 SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, 4497 sal_Bool& rCancel, sal_Bool bApi ) 4498 { 4499 if (rCancel) 4500 return; 4501 4502 ScDocument* pDoc = rDocShell.GetDocument(); 4503 if (!pDoc->HasValueData( nPosX, nPosY, nTab )) 4504 { 4505 String aName; 4506 pDoc->GetString( nPosX, nPosY, nTab, aName ); 4507 ScRangeData::MakeValidName(aName); 4508 if (aName.Len()) 4509 { 4510 String aContent; 4511 ScRange( nX1, nY1, nTab, nX2, nY2, nTab ).Format( aContent, SCR_ABS_3D, pDoc ); 4512 4513 sal_Bool bInsert = sal_False; 4514 sal_uInt16 nOldPos; 4515 if (rList.SearchName( aName, nOldPos )) // vorhanden ? 4516 { 4517 ScRangeData* pOld = rList[nOldPos]; 4518 String aOldStr; 4519 pOld->GetSymbol( aOldStr ); 4520 if (aOldStr != aContent) 4521 { 4522 if (bApi) 4523 bInsert = sal_True; // per API nicht nachfragen 4524 else 4525 { 4526 String aTemplate = ScGlobal::GetRscString( STR_CREATENAME_REPLACE ); 4527 4528 String aMessage = aTemplate.GetToken( 0, '#' ); 4529 aMessage += aName; 4530 aMessage += aTemplate.GetToken( 1, '#' ); 4531 4532 short nResult = QueryBox( rDocShell.GetActiveDialogParent(), 4533 WinBits(WB_YES_NO_CANCEL | WB_DEF_YES), 4534 aMessage ).Execute(); 4535 if ( nResult == RET_YES ) 4536 { 4537 rList.AtFree(nOldPos); 4538 bInsert = sal_True; 4539 } 4540 else if ( nResult == RET_CANCEL ) 4541 rCancel = sal_True; 4542 } 4543 } 4544 } 4545 else 4546 bInsert = sal_True; 4547 4548 if (bInsert) 4549 { 4550 ScRangeData* pData = new ScRangeData( pDoc, aName, aContent, 4551 ScAddress( nPosX, nPosY, nTab)); 4552 if (!rList.Insert(pData)) 4553 { 4554 DBG_ERROR("nanu?"); 4555 delete pData; 4556 } 4557 } 4558 } 4559 } 4560 } 4561 4562 sal_Bool ScDocFunc::CreateNames( const ScRange& rRange, sal_uInt16 nFlags, sal_Bool bApi ) 4563 { 4564 if (!nFlags) 4565 return sal_False; // war nix 4566 4567 ScDocShellModificator aModificator( rDocShell ); 4568 4569 sal_Bool bDone = sal_False; 4570 SCCOL nStartCol = rRange.aStart.Col(); 4571 SCROW nStartRow = rRange.aStart.Row(); 4572 SCCOL nEndCol = rRange.aEnd.Col(); 4573 SCROW nEndRow = rRange.aEnd.Row(); 4574 SCTAB nTab = rRange.aStart.Tab(); 4575 DBG_ASSERT(rRange.aEnd.Tab() == nTab, "CreateNames: mehrere Tabellen geht nicht"); 4576 4577 sal_Bool bValid = sal_True; 4578 if ( nFlags & ( NAME_TOP | NAME_BOTTOM ) ) 4579 if ( nStartRow == nEndRow ) 4580 bValid = sal_False; 4581 if ( nFlags & ( NAME_LEFT | NAME_RIGHT ) ) 4582 if ( nStartCol == nEndCol ) 4583 bValid = sal_False; 4584 4585 if (bValid) 4586 { 4587 ScDocument* pDoc = rDocShell.GetDocument(); 4588 ScRangeName* pNames = pDoc->GetRangeName(); 4589 if (!pNames) 4590 return sal_False; // soll nicht sein 4591 ScRangeName aNewRanges( *pNames ); 4592 4593 sal_Bool bTop = ( ( nFlags & NAME_TOP ) != 0 ); 4594 sal_Bool bLeft = ( ( nFlags & NAME_LEFT ) != 0 ); 4595 sal_Bool bBottom = ( ( nFlags & NAME_BOTTOM ) != 0 ); 4596 sal_Bool bRight = ( ( nFlags & NAME_RIGHT ) != 0 ); 4597 4598 SCCOL nContX1 = nStartCol; 4599 SCROW nContY1 = nStartRow; 4600 SCCOL nContX2 = nEndCol; 4601 SCROW nContY2 = nEndRow; 4602 4603 if ( bTop ) 4604 ++nContY1; 4605 if ( bLeft ) 4606 ++nContX1; 4607 if ( bBottom ) 4608 --nContY2; 4609 if ( bRight ) 4610 --nContX2; 4611 4612 sal_Bool bCancel = sal_False; 4613 SCCOL i; 4614 SCROW j; 4615 4616 if ( bTop ) 4617 for (i=nContX1; i<=nContX2; i++) 4618 CreateOneName( aNewRanges, i,nStartRow,nTab, i,nContY1,i,nContY2, bCancel, bApi ); 4619 if ( bLeft ) 4620 for (j=nContY1; j<=nContY2; j++) 4621 CreateOneName( aNewRanges, nStartCol,j,nTab, nContX1,j,nContX2,j, bCancel, bApi ); 4622 if ( bBottom ) 4623 for (i=nContX1; i<=nContX2; i++) 4624 CreateOneName( aNewRanges, i,nEndRow,nTab, i,nContY1,i,nContY2, bCancel, bApi ); 4625 if ( bRight ) 4626 for (j=nContY1; j<=nContY2; j++) 4627 CreateOneName( aNewRanges, nEndCol,j,nTab, nContX1,j,nContX2,j, bCancel, bApi ); 4628 4629 if ( bTop && bLeft ) 4630 CreateOneName( aNewRanges, nStartCol,nStartRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi ); 4631 if ( bTop && bRight ) 4632 CreateOneName( aNewRanges, nEndCol,nStartRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi ); 4633 if ( bBottom && bLeft ) 4634 CreateOneName( aNewRanges, nStartCol,nEndRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi ); 4635 if ( bBottom && bRight ) 4636 CreateOneName( aNewRanges, nEndCol,nEndRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi ); 4637 4638 bDone = ModifyRangeNames( aNewRanges, bApi ); 4639 4640 aModificator.SetDocumentModified(); 4641 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) ); 4642 } 4643 4644 return bDone; 4645 } 4646 4647 //------------------------------------------------------------------------ 4648 4649 sal_Bool ScDocFunc::InsertNameList( const ScAddress& rStartPos, sal_Bool bApi ) 4650 { 4651 ScDocShellModificator aModificator( rDocShell ); 4652 4653 4654 sal_Bool bDone = sal_False; 4655 ScDocument* pDoc = rDocShell.GetDocument(); 4656 const sal_Bool bRecord = pDoc->IsUndoEnabled(); 4657 SCTAB nTab = rStartPos.Tab(); 4658 ScDocument* pUndoDoc = NULL; 4659 4660 ScRangeName* pList = pDoc->GetRangeName(); 4661 sal_uInt16 nCount = pList->GetCount(); 4662 sal_uInt16 nValidCount = 0; 4663 sal_uInt16 i; 4664 for (i=0; i<nCount; i++) 4665 { 4666 ScRangeData* pData = (*pList)[i]; 4667 if ( !pData->HasType( RT_DATABASE ) && !pData->HasType( RT_SHARED ) ) 4668 ++nValidCount; 4669 } 4670 4671 if (nValidCount) 4672 { 4673 SCCOL nStartCol = rStartPos.Col(); 4674 SCROW nStartRow = rStartPos.Row(); 4675 SCCOL nEndCol = nStartCol + 1; 4676 SCROW nEndRow = nStartRow + static_cast<SCROW>(nValidCount) - 1; 4677 4678 ScEditableTester aTester( pDoc, nTab, nStartCol,nStartRow, nEndCol,nEndRow ); 4679 if (aTester.IsEditable()) 4680 { 4681 if (bRecord) 4682 { 4683 pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 4684 pUndoDoc->InitUndo( pDoc, nTab, nTab ); 4685 pDoc->CopyToDocument( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab, 4686 IDF_ALL, sal_False, pUndoDoc ); 4687 4688 pDoc->BeginDrawUndo(); // wegen Hoehenanpassung 4689 } 4690 4691 ScRangeData** ppSortArray = new ScRangeData* [ nValidCount ]; 4692 sal_uInt16 j = 0; 4693 for (i=0; i<nCount; i++) 4694 { 4695 ScRangeData* pData = (*pList)[i]; 4696 if ( !pData->HasType( RT_DATABASE ) && !pData->HasType( RT_SHARED ) ) 4697 ppSortArray[j++] = pData; 4698 } 4699 #ifndef ICC 4700 qsort( (void*)ppSortArray, nValidCount, sizeof(ScRangeData*), 4701 &ScRangeData_QsortNameCompare ); 4702 #else 4703 qsort( (void*)ppSortArray, nValidCount, sizeof(ScRangeData*), 4704 ICCQsortNameCompare ); 4705 #endif 4706 String aName; 4707 rtl::OUStringBuffer aContent; 4708 String aFormula; 4709 SCROW nOutRow = nStartRow; 4710 for (j=0; j<nValidCount; j++) 4711 { 4712 ScRangeData* pData = ppSortArray[j]; 4713 pData->GetName(aName); 4714 // relative Referenzen Excel-konform auf die linke Spalte anpassen: 4715 pData->UpdateSymbol(aContent, ScAddress( nStartCol, nOutRow, nTab )); 4716 aFormula = '='; 4717 aFormula += aContent; 4718 pDoc->PutCell( nStartCol,nOutRow,nTab, new ScStringCell( aName ) ); 4719 pDoc->PutCell( nEndCol ,nOutRow,nTab, new ScStringCell( aFormula ) ); 4720 ++nOutRow; 4721 } 4722 4723 delete [] ppSortArray; 4724 4725 if (bRecord) 4726 { 4727 ScDocument* pRedoDoc = new ScDocument( SCDOCMODE_UNDO ); 4728 pRedoDoc->InitUndo( pDoc, nTab, nTab ); 4729 pDoc->CopyToDocument( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab, 4730 IDF_ALL, sal_False, pRedoDoc ); 4731 4732 rDocShell.GetUndoManager()->AddUndoAction( 4733 new ScUndoListNames( &rDocShell, 4734 ScRange( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab ), 4735 pUndoDoc, pRedoDoc ) ); 4736 } 4737 4738 if (!AdjustRowHeight(ScRange(0,nStartRow,nTab,MAXCOL,nEndRow,nTab))) 4739 rDocShell.PostPaint( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab, PAINT_GRID ); 4740 //! rDocShell.UpdateOle(GetViewData()); 4741 aModificator.SetDocumentModified(); 4742 bDone = sal_True; 4743 } 4744 else if (!bApi) 4745 rDocShell.ErrorMessage(aTester.GetMessageId()); 4746 } 4747 return bDone; 4748 } 4749 4750 //------------------------------------------------------------------------ 4751 4752 sal_Bool ScDocFunc::ResizeMatrix( const ScRange& rOldRange, const ScAddress& rNewEnd, sal_Bool bApi ) 4753 { 4754 ScDocument* pDoc = rDocShell.GetDocument(); 4755 SCCOL nStartCol = rOldRange.aStart.Col(); 4756 SCROW nStartRow = rOldRange.aStart.Row(); 4757 SCTAB nTab = rOldRange.aStart.Tab(); 4758 4759 sal_Bool bUndo(pDoc->IsUndoEnabled()); 4760 4761 sal_Bool bRet = sal_False; 4762 4763 String aFormula; 4764 pDoc->GetFormula( nStartCol, nStartRow, nTab, aFormula ); 4765 if ( aFormula.GetChar(0) == '{' && aFormula.GetChar(aFormula.Len()-1) == '}' ) 4766 { 4767 String aUndo = ScGlobal::GetRscString( STR_UNDO_RESIZEMATRIX ); 4768 if (bUndo) 4769 rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo ); 4770 4771 aFormula.Erase(0,1); 4772 aFormula.Erase(aFormula.Len()-1,1); 4773 4774 ScMarkData aMark; 4775 aMark.SetMarkArea( rOldRange ); 4776 aMark.SelectTable( nTab, sal_True ); 4777 ScRange aNewRange( rOldRange.aStart, rNewEnd ); 4778 4779 if ( DeleteContents( aMark, IDF_CONTENTS, sal_True, bApi ) ) 4780 { 4781 // GRAM_PODF_A1 for API compatibility. 4782 bRet = EnterMatrix( aNewRange, &aMark, NULL, aFormula, bApi, sal_False, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 ); 4783 if (!bRet) 4784 { 4785 // versuchen, alten Zustand wiederherzustellen 4786 EnterMatrix( rOldRange, &aMark, NULL, aFormula, bApi, sal_False, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 ); 4787 } 4788 } 4789 4790 if (bUndo) 4791 rDocShell.GetUndoManager()->LeaveListAction(); 4792 } 4793 4794 return bRet; 4795 } 4796 4797 //------------------------------------------------------------------------ 4798 4799 sal_Bool ScDocFunc::InsertAreaLink( const String& rFile, const String& rFilter, 4800 const String& rOptions, const String& rSource, 4801 const ScRange& rDestRange, sal_uLong nRefresh, 4802 sal_Bool bFitBlock, sal_Bool bApi ) 4803 { 4804 //! auch fuer ScViewFunc::InsertAreaLink benutzen! 4805 4806 ScDocument* pDoc = rDocShell.GetDocument(); 4807 sal_Bool bUndo (pDoc->IsUndoEnabled()); 4808 4809 sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager(); 4810 4811 // #i52120# if other area links exist at the same start position, 4812 // remove them first (file format specifies only one link definition 4813 // for a cell) 4814 4815 sal_uInt16 nLinkCount = pLinkManager->GetLinks().Count(); 4816 sal_uInt16 nRemoved = 0; 4817 sal_uInt16 nLinkPos = 0; 4818 while (nLinkPos<nLinkCount) 4819 { 4820 ::sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[nLinkPos]; 4821 if ( pBase->ISA(ScAreaLink) && 4822 static_cast<ScAreaLink*>(pBase)->GetDestArea().aStart == rDestRange.aStart ) 4823 { 4824 if ( bUndo ) 4825 { 4826 if ( !nRemoved ) 4827 { 4828 // group all remove and the insert action 4829 String aUndo = ScGlobal::GetRscString( STR_UNDO_INSERTAREALINK ); 4830 rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo ); 4831 } 4832 4833 ScAreaLink* pOldArea = static_cast<ScAreaLink*>(pBase); 4834 rDocShell.GetUndoManager()->AddUndoAction( 4835 new ScUndoRemoveAreaLink( &rDocShell, 4836 pOldArea->GetFile(), pOldArea->GetFilter(), pOldArea->GetOptions(), 4837 pOldArea->GetSource(), pOldArea->GetDestArea(), pOldArea->GetRefreshDelay() ) ); 4838 } 4839 pLinkManager->Remove( pBase ); 4840 nLinkCount = pLinkManager->GetLinks().Count(); 4841 ++nRemoved; 4842 } 4843 else 4844 ++nLinkPos; 4845 } 4846 4847 String aFilterName = rFilter; 4848 String aNewOptions = rOptions; 4849 if (!aFilterName.Len()) 4850 ScDocumentLoader::GetFilterName( rFile, aFilterName, aNewOptions, sal_True, !bApi ); 4851 4852 // remove application prefix from filter name here, so the filter options 4853 // aren't reset when the filter name is changed in ScAreaLink::DataChanged 4854 ScDocumentLoader::RemoveAppPrefix( aFilterName ); 4855 4856 ScAreaLink* pLink = new ScAreaLink( &rDocShell, rFile, aFilterName, 4857 aNewOptions, rSource, rDestRange, nRefresh ); 4858 pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, rFile, &aFilterName, &rSource ); 4859 4860 // Undo fuer den leeren Link 4861 4862 if (bUndo) 4863 { 4864 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoInsertAreaLink( &rDocShell, 4865 rFile, aFilterName, aNewOptions, 4866 rSource, rDestRange, nRefresh ) ); 4867 if ( nRemoved ) 4868 rDocShell.GetUndoManager()->LeaveListAction(); // undo for link update is still separate 4869 } 4870 4871 // Update hat sein eigenes Undo 4872 if (pDoc->IsExecuteLinkEnabled()) 4873 { 4874 pLink->SetDoInsert(bFitBlock); // beim ersten Update ggf. nichts einfuegen 4875 pLink->Update(); // kein SetInCreate -> Update ausfuehren 4876 } 4877 pLink->SetDoInsert(sal_True); // Default = sal_True 4878 4879 SfxBindings* pBindings = rDocShell.GetViewBindings(); 4880 if (pBindings) 4881 pBindings->Invalidate( SID_LINKS ); 4882 4883 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); // Navigator 4884 4885 return sal_True; 4886 } 4887 4888 4889 4890 4891