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