1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sc.hxx" 30 31 32 33 //------------------------------------------------------------------ 34 35 // INCLUDE --------------------------------------------------------------- 36 37 #include "scitems.hxx" 38 #include <editeng/eeitem.hxx> 39 40 #include <sfx2/app.hxx> 41 #include <svx/algitem.hxx> 42 #include <editeng/boxitem.hxx> 43 #include <editeng/editobj.hxx> 44 #include <editeng/editview.hxx> 45 #include <editeng/langitem.hxx> 46 #include <editeng/scripttypeitem.hxx> 47 #include <sfx2/bindings.hxx> 48 #include <svl/zforlist.hxx> 49 #include <svl/zformat.hxx> 50 #include <vcl/msgbox.hxx> 51 #include <vcl/sound.hxx> 52 #include <vcl/virdev.hxx> 53 #include <vcl/waitobj.hxx> 54 #include <vcl/wrkwin.hxx> 55 #include <stdlib.h> // qsort 56 57 #include "viewfunc.hxx" 58 #include "tabvwsh.hxx" 59 #include "docsh.hxx" 60 #include "attrib.hxx" 61 #include "patattr.hxx" 62 #include "docpool.hxx" 63 #include "uiitems.hxx" 64 #include "sc.hrc" 65 #include "undocell.hxx" 66 #include "undoblk.hxx" 67 #include "undotab.hxx" 68 #include "refundo.hxx" 69 #include "dbcolect.hxx" 70 #include "olinetab.hxx" 71 #include "rangeutl.hxx" 72 #include "rangenam.hxx" 73 #include "globstr.hrc" 74 #include "global.hxx" 75 #include "stlsheet.hxx" 76 #include "editutil.hxx" 77 //CHINA001 #include "namecrea.hxx" // wegen Flags 78 #include "cell.hxx" 79 #include "scresid.hxx" 80 #include "inputhdl.hxx" 81 #include "scmod.hxx" 82 #include "inputopt.hxx" 83 #include "compiler.hxx" 84 #include "docfunc.hxx" 85 #include "appoptio.hxx" 86 #include "dociter.hxx" 87 #include "sizedev.hxx" 88 #include "editable.hxx" 89 #include "scui_def.hxx" //CHINA001 90 #include "funcdesc.hxx" 91 #include "docuno.hxx" 92 #include "cellsuno.hxx" 93 //================================================================== 94 95 ScViewFunc::ScViewFunc( Window* pParent, ScDocShell& rDocSh, ScTabViewShell* pViewShell ) : 96 ScTabView( pParent, rDocSh, pViewShell ), 97 bFormatValid( sal_False ) 98 { 99 } 100 101 //UNUSED2008-05 ScViewFunc::ScViewFunc( Window* pParent, const ScViewFunc& rViewFunc, ScTabViewShell* pViewShell ) : 102 //UNUSED2008-05 ScTabView( pParent, rViewFunc, pViewShell ), 103 //UNUSED2008-05 bFormatValid( sal_False ) 104 //UNUSED2008-05 { 105 //UNUSED2008-05 } 106 107 ScViewFunc::~ScViewFunc() 108 { 109 } 110 111 //------------------------------------------------------------------------------------ 112 113 void ScViewFunc::StartFormatArea() 114 { 115 // ueberhaupt aktiviert? 116 if ( !SC_MOD()->GetInputOptions().GetExtendFormat() ) 117 return; 118 119 // start only with single cell (marked or cursor position) 120 ScRange aMarkRange; 121 sal_Bool bOk = (GetViewData()->GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE); 122 if ( bOk && aMarkRange.aStart != aMarkRange.aEnd ) 123 bOk = sal_False; 124 125 if (bOk) 126 { 127 bFormatValid = sal_True; 128 aFormatSource = aMarkRange.aStart; 129 aFormatArea = ScRange( aFormatSource ); 130 } 131 else 132 bFormatValid = sal_False; // keinen alten Bereich behalten 133 } 134 135 sal_Bool ScViewFunc::TestFormatArea( SCCOL nCol, SCROW nRow, SCTAB nTab, sal_Bool bAttrChanged ) 136 { 137 // ueberhaupt aktiviert? 138 if ( !SC_MOD()->GetInputOptions().GetExtendFormat() ) 139 return sal_False; 140 141 // Test: Eingabe mit Zahlformat (bAttrChanged) immer als neue Attributierung behandeln 142 // (alte Area verwerfen). Wenn das nicht gewollt ist, den if-Teil weglassen: 143 if ( bAttrChanged ) 144 { 145 StartFormatArea(); 146 return sal_False; 147 } 148 149 //! Abfrage, ob Zelle leer war ??? 150 151 sal_Bool bFound = sal_False; 152 ScRange aNewRange = aFormatArea; 153 if ( bFormatValid && nTab == aFormatSource.Tab() ) 154 { 155 if ( nRow >= aFormatArea.aStart.Row() && nRow <= aFormatArea.aEnd.Row() ) 156 { 157 // innerhalb ? 158 if ( nCol >= aFormatArea.aStart.Col() && nCol <= aFormatArea.aEnd.Col() ) 159 { 160 bFound = sal_True; // Bereich nicht aendern 161 } 162 // links ? 163 if ( nCol+1 == aFormatArea.aStart.Col() ) 164 { 165 bFound = sal_True; 166 aNewRange.aStart.SetCol( nCol ); 167 } 168 // rechts ? 169 if ( nCol == aFormatArea.aEnd.Col()+1 ) 170 { 171 bFound = sal_True; 172 aNewRange.aEnd.SetCol( nCol ); 173 } 174 } 175 if ( nCol >= aFormatArea.aStart.Col() && nCol <= aFormatArea.aEnd.Col() ) 176 { 177 // oben ? 178 if ( nRow+1 == aFormatArea.aStart.Row() ) 179 { 180 bFound = sal_True; 181 aNewRange.aStart.SetRow( nRow ); 182 } 183 // unten ? 184 if ( nRow == aFormatArea.aEnd.Row()+1 ) 185 { 186 bFound = sal_True; 187 aNewRange.aEnd.SetRow( nRow ); 188 } 189 } 190 } 191 192 if (bFound) 193 aFormatArea = aNewRange; // erweitern 194 else 195 { 196 bFormatValid = sal_False; // ausserhalb -> abbrechen 197 if ( bAttrChanged ) // Wert mit Zahlformat eingegeben? 198 StartFormatArea(); // dann ggf. neu starten 199 } 200 201 return bFound; 202 } 203 204 void ScViewFunc::DoAutoAttributes( SCCOL nCol, SCROW nRow, SCTAB nTab, 205 sal_Bool bAttrChanged, sal_Bool bAddUndo ) 206 { 207 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 208 ScDocument* pDoc = pDocSh->GetDocument(); 209 if (bAddUndo && !pDoc->IsUndoEnabled()) 210 bAddUndo = sal_False; 211 212 const ScPatternAttr* pSource = pDoc->GetPattern( 213 aFormatSource.Col(), aFormatSource.Row(), nTab ); 214 if ( !((const ScMergeAttr&)pSource->GetItem(ATTR_MERGE)).IsMerged() ) 215 { 216 const ScPatternAttr* pDocOld = pDoc->GetPattern( nCol, nRow, nTab ); 217 // pDocOld ist nur bis zum Apply... gueltig! 218 219 ScPatternAttr* pOldPattern = NULL; 220 if ( bAddUndo ) 221 pOldPattern = new ScPatternAttr( *pDocOld ); 222 223 const ScStyleSheet* pSrcStyle = pSource->GetStyleSheet(); 224 if ( pSrcStyle && pSrcStyle != pDocOld->GetStyleSheet() ) 225 pDoc->ApplyStyle( nCol, nRow, nTab, *pSrcStyle ); 226 pDoc->ApplyPattern( nCol, nRow, nTab, *pSource ); 227 AdjustRowHeight( nRow, nRow, sal_True ); //! nicht doppelt ? 228 229 if ( bAddUndo ) 230 { 231 const ScPatternAttr* pNewPattern = pDoc->GetPattern( nCol, nRow, nTab ); 232 233 pDocSh->GetUndoManager()->AddUndoAction( 234 new ScUndoCursorAttr( pDocSh, nCol, nRow, nTab, 235 pOldPattern, pNewPattern, pSource, 236 sal_True ) ); 237 238 delete pOldPattern; // wird im Undo kopiert (Pool) 239 } 240 } 241 242 if ( bAttrChanged ) // Wert mit Zahlformat eingegeben? 243 aFormatSource.Set( nCol, nRow, nTab ); // dann als neue Quelle 244 } 245 246 //------------------------------------------------------------------------------------ 247 248 // Hilfsroutinen 249 250 sal_uInt16 ScViewFunc::GetOptimalColWidth( SCCOL nCol, SCTAB nTab, sal_Bool bFormula ) 251 { 252 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 253 ScDocument* pDoc = pDocSh->GetDocument(); 254 ScMarkData& rMark = GetViewData()->GetMarkData(); 255 256 double nPPTX = GetViewData()->GetPPTX(); 257 double nPPTY = GetViewData()->GetPPTY(); 258 Fraction aZoomX = GetViewData()->GetZoomX(); 259 Fraction aZoomY = GetViewData()->GetZoomY(); 260 261 ScSizeDeviceProvider aProv(pDocSh); 262 if (aProv.IsPrinter()) 263 { 264 nPPTX = aProv.GetPPTX(); 265 nPPTY = aProv.GetPPTY(); 266 aZoomX = aZoomY = Fraction( 1, 1 ); 267 } 268 269 sal_uInt16 nTwips = pDoc->GetOptimalColWidth( nCol, nTab, aProv.GetDevice(), 270 nPPTX, nPPTY, aZoomX, aZoomY, bFormula, &rMark ); 271 return nTwips; 272 } 273 274 sal_Bool ScViewFunc::SelectionEditable( sal_Bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) 275 { 276 sal_Bool bRet; 277 ScDocument* pDoc = GetViewData()->GetDocument(); 278 ScMarkData& rMark = GetViewData()->GetMarkData(); 279 if (rMark.IsMarked() || rMark.IsMultiMarked()) 280 bRet = pDoc->IsSelectionEditable( rMark, pOnlyNotBecauseOfMatrix ); 281 else 282 { 283 SCCOL nCol = GetViewData()->GetCurX(); 284 SCROW nRow = GetViewData()->GetCurY(); 285 SCTAB nTab = GetViewData()->GetTabNo(); 286 bRet = pDoc->IsBlockEditable( nTab, nCol, nRow, nCol, nRow, 287 pOnlyNotBecauseOfMatrix ); 288 } 289 return bRet; 290 } 291 292 #ifndef LRU_MAX 293 #define LRU_MAX 10 294 #endif 295 296 sal_Bool lcl_FunctionKnown( sal_uInt16 nOpCode ) 297 { 298 const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList(); 299 if ( pFuncList ) 300 { 301 sal_uLong nCount = pFuncList->GetCount(); 302 for (sal_uLong i=0; i<nCount; i++) 303 if ( pFuncList->GetFunction(i)->nFIndex == nOpCode ) 304 return sal_True; 305 } 306 return sal_False; 307 } 308 309 sal_Bool lcl_AddFunction( ScAppOptions& rAppOpt, sal_uInt16 nOpCode ) 310 { 311 sal_uInt16 nOldCount = rAppOpt.GetLRUFuncListCount(); 312 sal_uInt16* pOldList = rAppOpt.GetLRUFuncList(); 313 sal_uInt16 nPos; 314 for (nPos=0; nPos<nOldCount; nPos++) 315 if (pOldList[nPos] == nOpCode) // is the function already in the list? 316 { 317 if ( nPos == 0 ) 318 return sal_False; // already at the top -> no change 319 320 // count doesn't change, so the original array is modified 321 322 for (sal_uInt16 nCopy=nPos; nCopy>0; nCopy--) 323 pOldList[nCopy] = pOldList[nCopy-1]; 324 pOldList[0] = nOpCode; 325 326 return sal_True; // list has changed 327 } 328 329 if ( !lcl_FunctionKnown( nOpCode ) ) 330 return sal_False; // not in function list -> no change 331 332 sal_uInt16 nNewCount = Min( (sal_uInt16)(nOldCount + 1), (sal_uInt16)LRU_MAX ); 333 sal_uInt16 nNewList[LRU_MAX]; 334 nNewList[0] = nOpCode; 335 for (nPos=1; nPos<nNewCount; nPos++) 336 nNewList[nPos] = pOldList[nPos-1]; 337 rAppOpt.SetLRUFuncList( nNewList, nNewCount ); 338 339 return sal_True; // list has changed 340 } 341 342 // eigentliche Funktionen 343 344 // Eingabe - Undo OK 345 346 void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rString, 347 sal_Bool bRecord, const EditTextObject* pData ) 348 { 349 ScDocument* pDoc = GetViewData()->GetDocument(); 350 ScMarkData& rMark = GetViewData()->GetMarkData(); 351 SCTAB nTabCount = pDoc->GetTableCount(); 352 SCTAB nSelCount = rMark.GetSelectCount(); 353 SCTAB i; 354 if (bRecord && !pDoc->IsUndoEnabled()) 355 bRecord = sal_False; 356 357 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 358 ScDocShellModificator aModificator( *pDocSh ); 359 360 ScEditableTester aTester( pDoc, nCol,nRow, nCol,nRow, rMark ); 361 if (aTester.IsEditable()) 362 { 363 sal_Bool bEditDeleted = sal_False; 364 sal_uInt8 nOldScript = 0; 365 366 ScBaseCell** ppOldCells = NULL; 367 sal_Bool* pHasFormat = NULL; 368 sal_uLong* pOldFormats = NULL; 369 SCTAB* pTabs = NULL; 370 SCTAB nUndoPos = 0; 371 EditTextObject* pUndoData = NULL; 372 if ( bRecord ) 373 { 374 ppOldCells = new ScBaseCell*[nSelCount]; 375 pHasFormat = new sal_Bool[nSelCount]; 376 pOldFormats = new sal_uLong[nSelCount]; 377 pTabs = new SCTAB[nSelCount]; 378 nUndoPos = 0; 379 380 for (i=0; i<nTabCount; i++) 381 if (rMark.GetTableSelect(i)) 382 { 383 pTabs[nUndoPos] = i; 384 ScBaseCell* pDocCell; 385 pDoc->GetCell( nCol, nRow, i, pDocCell ); 386 if ( pDocCell ) 387 { 388 ppOldCells[nUndoPos] = pDocCell->CloneWithoutNote( *pDoc ); 389 if ( pDocCell->GetCellType() == CELLTYPE_EDIT ) 390 bEditDeleted = sal_True; 391 392 sal_uInt8 nDocScript = pDoc->GetScriptType( nCol, nRow, i, pDocCell ); 393 if ( nOldScript == 0 ) 394 nOldScript = nDocScript; 395 else if ( nDocScript != nOldScript ) 396 bEditDeleted = sal_True; 397 } 398 else 399 { 400 ppOldCells[nUndoPos] = NULL; 401 } 402 403 const SfxPoolItem* pItem; 404 const ScPatternAttr* pPattern = pDoc->GetPattern(nCol, nRow, i); 405 if ( SFX_ITEM_SET == pPattern->GetItemSet().GetItemState( 406 ATTR_VALUE_FORMAT,sal_False,&pItem) ) 407 { 408 pHasFormat[nUndoPos] = sal_True; 409 pOldFormats[nUndoPos] = ((const SfxUInt32Item*)pItem)->GetValue(); 410 } 411 else 412 pHasFormat[nUndoPos] = sal_False; 413 414 ++nUndoPos; 415 } 416 417 DBG_ASSERT( nUndoPos==nSelCount, "nUndoPos!=nSelCount" ); 418 419 pUndoData = ( pData ? pData->Clone() : NULL ); 420 } 421 422 bool bFormula = false; 423 424 // a single '=' character is handled as string (needed for special filters) 425 if ( rString.Len() > 1 ) 426 { 427 if ( rString.GetChar(0) == '=' ) 428 { 429 // handle as formula 430 bFormula = true; 431 } 432 else if ( rString.GetChar(0) == '+' || rString.GetChar(0) == '-' ) 433 { 434 // if there is more than one leading '+' or '-' character, remove the additional ones 435 String aString( rString ); 436 xub_StrLen nIndex = 1; 437 xub_StrLen nLen = aString.Len(); 438 while ( nIndex < nLen && ( aString.GetChar( nIndex ) == '+' || aString.GetChar( nIndex ) == '-' ) ) 439 { 440 ++nIndex; 441 } 442 aString.Erase( 1, nIndex - 1 ); 443 444 // if the remaining part without the leading '+' or '-' character 445 // is non-empty and not a number, handle as formula 446 if ( aString.Len() > 1 ) 447 { 448 sal_uInt32 nFormat = 0; 449 pDoc->GetNumberFormat( nCol, nRow, nTab, nFormat ); 450 SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); 451 double fNumber = 0; 452 if ( !pFormatter->IsNumberFormat( aString, nFormat, fNumber ) ) 453 { 454 bFormula = true; 455 } 456 } 457 } 458 } 459 460 sal_Bool bNumFmtChanged = sal_False; 461 if ( bFormula ) 462 { // Formel, compile mit AutoCorrection 463 for (i=0; i<nTabCount; i++) 464 if (rMark.GetTableSelect(i)) 465 break; 466 ScAddress aPos( nCol, nRow, i ); 467 ScCompiler aComp( pDoc, aPos); 468 aComp.SetGrammar(pDoc->GetGrammar()); 469 //2do: AutoCorrection via CalcOptions abschaltbar machen 470 aComp.SetAutoCorrection( sal_True ); 471 if ( rString.GetChar(0) == '+' || rString.GetChar(0) == '-' ) 472 { 473 aComp.SetExtendedErrorDetection( true ); 474 } 475 String aFormula( rString ); 476 ScTokenArray* pArr; 477 sal_Bool bAgain; 478 do 479 { 480 bAgain = sal_False; 481 sal_Bool bAddEqual = sal_False; 482 ScTokenArray* pArrFirst = pArr = aComp.CompileString( aFormula ); 483 sal_Bool bCorrected = aComp.IsCorrected(); 484 if ( bCorrected ) 485 { // probieren, mit erster Parser-Korrektur neu zu parsen 486 pArr = aComp.CompileString( aComp.GetCorrectedFormula() ); 487 } 488 if ( !pArr->GetCodeError() ) 489 { 490 bAddEqual = sal_True; 491 aComp.CompileTokenArray(); 492 bCorrected |= aComp.IsCorrected(); 493 } 494 if ( bCorrected ) 495 { 496 String aCorrectedFormula; 497 if ( bAddEqual ) 498 { 499 aCorrectedFormula = '='; 500 aCorrectedFormula += aComp.GetCorrectedFormula(); 501 } 502 else 503 aCorrectedFormula = aComp.GetCorrectedFormula(); 504 short nResult; 505 if ( aCorrectedFormula.Len() == 1 ) 506 nResult = RET_NO; // leere Formel, nur '=' 507 else 508 { 509 String aMessage( ScResId( SCSTR_FORMULA_AUTOCORRECTION ) ); 510 aMessage += aCorrectedFormula; 511 nResult = QueryBox( GetViewData()->GetDialogParent(), 512 WinBits(WB_YES_NO | WB_DEF_YES), 513 aMessage ).Execute(); 514 } 515 if ( nResult == RET_YES ) 516 { 517 aFormula = aCorrectedFormula; 518 if ( pArr != pArrFirst ) 519 delete pArrFirst; 520 bAgain = sal_True; 521 } 522 else 523 { 524 if ( pArr != pArrFirst ) 525 { 526 delete pArr; 527 pArr = pArrFirst; 528 } 529 } 530 } 531 } while ( bAgain ); 532 // um in mehreren Tabellen eingesetzt zu werden, muss die Formel 533 // via ScFormulaCell copy-ctor evtl. wegen RangeNames neu kompiliert 534 // werden, gleiches Code-Array fuer alle Zellen geht nicht. 535 // Wenn das Array einen Fehler enthaelt, muss in den neu erzeugten 536 // Zellen RPN geloescht und der Fehler explizit gesetzt werden, da 537 // via FormulaCell copy-ctor und Interpreter das, wenn moeglich, 538 // wieder glattgebuegelt wird, zu intelligent.. z.B.: =1)) 539 sal_uInt16 nError = pArr->GetCodeError(); 540 if ( !nError ) 541 { 542 // #68693# update list of recent functions with all functions that 543 // are not within parentheses 544 545 ScModule* pScMod = SC_MOD(); 546 ScAppOptions aAppOpt = pScMod->GetAppOptions(); 547 sal_Bool bOptChanged = sal_False; 548 549 formula::FormulaToken** ppToken = pArr->GetArray(); 550 sal_uInt16 nTokens = pArr->GetLen(); 551 sal_uInt16 nLevel = 0; 552 for (sal_uInt16 nTP=0; nTP<nTokens; nTP++) 553 { 554 formula::FormulaToken* pTok = ppToken[nTP]; 555 OpCode eOp = pTok->GetOpCode(); 556 if ( eOp == ocOpen ) 557 ++nLevel; 558 else if ( eOp == ocClose && nLevel ) 559 --nLevel; 560 if ( nLevel == 0 && pTok->IsFunction() && 561 lcl_AddFunction( aAppOpt, sal::static_int_cast<sal_uInt16>( eOp ) ) ) 562 bOptChanged = sal_True; 563 } 564 565 if ( bOptChanged ) 566 { 567 pScMod->SetAppOptions(aAppOpt); 568 pScMod->RecentFunctionsChanged(); 569 } 570 } 571 572 ScFormulaCell aCell( pDoc, aPos, pArr,formula::FormulaGrammar::GRAM_DEFAULT, MM_NONE ); 573 delete pArr; 574 sal_Bool bAutoCalc = pDoc->GetAutoCalc(); 575 SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); 576 for ( ; i<nTabCount; i++) 577 { 578 if (rMark.GetTableSelect(i)) 579 { 580 aPos.SetTab( i ); 581 sal_uLong nIndex = (sal_uLong) ((SfxUInt32Item*) pDoc->GetAttr( 582 nCol, nRow, i, ATTR_VALUE_FORMAT ))->GetValue(); 583 if ( pFormatter->GetType( nIndex ) == NUMBERFORMAT_TEXT || 584 ( ( rString.GetChar(0) == '+' || rString.GetChar(0) == '-' ) && nError && rString.Equals( aFormula ) ) ) 585 { 586 if ( pData ) 587 { 588 ScEditCell* pCell = new ScEditCell( pData, pDoc, NULL ); 589 pDoc->PutCell( aPos, pCell ); 590 } 591 else 592 { 593 ScStringCell* pCell = new ScStringCell( aFormula ); 594 pDoc->PutCell( aPos, pCell ); 595 } 596 } 597 else 598 { 599 DELETEZ(pUndoData); 600 ScFormulaCell* pCell = new ScFormulaCell( aCell, *pDoc, aPos ); 601 if ( nError ) 602 { 603 pCell->GetCode()->DelRPN(); 604 pCell->SetErrCode( nError ); 605 if(pCell->GetCode()->IsHyperLink()) 606 pCell->GetCode()->SetHyperLink(sal_False); 607 } 608 pDoc->PutCell( aPos, pCell ); 609 if ( !bAutoCalc ) 610 { // einmal nur die Zelle berechnen und wieder dirty setzen 611 pCell->Interpret(); 612 pCell->SetDirtyVar(); 613 pDoc->PutInFormulaTree( pCell ); 614 } 615 } 616 617 } 618 } 619 } 620 else 621 { 622 for (i=0; i<nTabCount; i++) 623 if (rMark.GetTableSelect(i)) 624 if (pDoc->SetString( nCol, nRow, i, rString )) 625 bNumFmtChanged = sal_True; 626 } 627 628 // row height must be changed if new text has a different script type 629 for (i=0; i<nTabCount && !bEditDeleted; i++) 630 if (rMark.GetTableSelect(i)) 631 if ( pDoc->GetScriptType( nCol, nRow, i ) != nOldScript ) 632 bEditDeleted = sal_True; 633 634 HideAllCursors(); 635 636 if (bEditDeleted || pDoc->HasAttrib( nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_NEEDHEIGHT )) 637 AdjustRowHeight(nRow,nRow); 638 639 sal_Bool bAutoFormat = TestFormatArea(nCol, nRow, nTab, bNumFmtChanged); 640 if (bAutoFormat) 641 DoAutoAttributes(nCol, nRow, nTab, bNumFmtChanged, bRecord); 642 643 if ( bRecord ) 644 { // wg. ChangeTrack erst jetzt 645 pDocSh->GetUndoManager()->AddUndoAction( 646 new ScUndoEnterData( pDocSh, nCol, nRow, nTab, nUndoPos, pTabs, 647 ppOldCells, pHasFormat, pOldFormats, 648 rString, pUndoData ) ); 649 } 650 651 for (i=0; i<nTabCount; i++) 652 if (rMark.GetTableSelect(i)) 653 pDocSh->PostPaintCell( nCol, nRow, i ); 654 655 ShowAllCursors(); 656 657 pDocSh->UpdateOle(GetViewData()); 658 659 // #i97876# Spreadsheet data changes are not notified 660 ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() ); 661 if ( pModelObj && pModelObj->HasChangesListeners() ) 662 { 663 ScRangeList aChangeRanges; 664 for ( i = 0; i < nTabCount; ++i ) 665 { 666 if ( rMark.GetTableSelect( i ) ) 667 { 668 aChangeRanges.Append( ScRange( nCol, nRow, i ) ); 669 } 670 } 671 pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges ); 672 } 673 674 aModificator.SetDocumentModified(); 675 } 676 else 677 { 678 ErrorMessage(aTester.GetMessageId()); 679 PaintArea( nCol, nRow, nCol, nRow ); // da steht evtl. noch die Edit-Engine 680 } 681 } 682 683 // Wert in einzele Zelle eintragen (nur auf nTab) 684 685 void ScViewFunc::EnterValue( SCCOL nCol, SCROW nRow, SCTAB nTab, const double& rValue ) 686 { 687 ScDocument* pDoc = GetViewData()->GetDocument(); 688 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 689 sal_Bool bUndo (pDoc->IsUndoEnabled()); 690 691 if ( pDoc && pDocSh ) 692 { 693 ScDocShellModificator aModificator( *pDocSh ); 694 695 ScEditableTester aTester( pDoc, nTab, nCol,nRow, nCol,nRow ); 696 if (aTester.IsEditable()) 697 { 698 ScAddress aPos( nCol, nRow, nTab ); 699 ScBaseCell* pOldCell = pDoc->GetCell( aPos ); 700 sal_Bool bNeedHeight = ( pOldCell && pOldCell->GetCellType() == CELLTYPE_EDIT ) 701 || pDoc->HasAttrib( 702 nCol,nRow,nTab, nCol,nRow,nTab, HASATTR_NEEDHEIGHT ); 703 704 // Undo 705 ScBaseCell* pUndoCell = (bUndo && pOldCell) ? pOldCell->CloneWithoutNote( *pDoc ) : 0; 706 707 pDoc->SetValue( nCol, nRow, nTab, rValue ); 708 709 // wg. ChangeTrack nach Aenderung im Dokument 710 if (bUndo) 711 { 712 pDocSh->GetUndoManager()->AddUndoAction( 713 new ScUndoEnterValue( pDocSh, aPos, pUndoCell, rValue, bNeedHeight ) ); 714 } 715 716 /*! Zeilenhoehe anpassen? Dann auch bei Undo... 717 if (bNeedHeight) 718 AdjustRowHeight(nRow,nRow); 719 */ 720 721 pDocSh->PostPaintCell( aPos ); 722 pDocSh->UpdateOle(GetViewData()); 723 aModificator.SetDocumentModified(); 724 } 725 else 726 ErrorMessage(aTester.GetMessageId()); 727 } 728 } 729 730 void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const EditTextObject* pData, 731 sal_Bool bRecord, sal_Bool bTestSimple ) 732 { 733 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 734 ScMarkData& rMark = GetViewData()->GetMarkData(); 735 ScDocument* pDoc = pDocSh->GetDocument(); 736 if (bRecord && !pDoc->IsUndoEnabled()) 737 bRecord = sal_False; 738 739 ScDocShellModificator aModificator( *pDocSh ); 740 741 ScEditableTester aTester( pDoc, nTab, nCol,nRow, nCol,nRow ); 742 if (aTester.IsEditable()) 743 { 744 // 745 // Test auf Attribute 746 // 747 sal_Bool bSimple = sal_False; 748 sal_Bool bCommon = sal_False; 749 ScPatternAttr* pCellAttrs = NULL; 750 EditTextObject* pNewData = NULL; 751 String aString; 752 753 const ScPatternAttr* pOldPattern = pDoc->GetPattern( nCol, nRow, nTab ); 754 ScTabEditEngine aEngine( *pOldPattern, pDoc->GetEnginePool() ); 755 aEngine.SetText(*pData); 756 757 if (bTestSimple) // Testen, ob einfacher String ohne Attribute 758 { 759 ScEditAttrTester aAttrTester( &aEngine ); 760 bSimple = !aAttrTester.NeedsObject(); 761 bCommon = aAttrTester.NeedsCellAttr(); 762 763 // formulas have to be recognized even if they're formatted 764 // (but commmon attributes are still collected) 765 766 if ( !bSimple && aEngine.GetParagraphCount() == 1 ) 767 { 768 String aParStr = aEngine.GetText( (sal_uInt16) 0 ); 769 if ( aParStr.GetChar(0) == '=' ) 770 bSimple = sal_True; 771 } 772 773 if (bCommon) // Attribute fuer Tabelle 774 { 775 pCellAttrs = new ScPatternAttr( *pOldPattern ); 776 pCellAttrs->GetFromEditItemSet( &aAttrTester.GetAttribs() ); 777 //! remove common attributes from EditEngine? 778 } 779 } 780 781 // #i97726# always get text for "repeat" of undo action 782 aString = ScEditUtil::GetSpaceDelimitedString(aEngine); 783 784 // 785 // Undo 786 // 787 788 SCTAB nTabCount = pDoc->GetTableCount(); 789 SCTAB nSelCount = rMark.GetSelectCount(); 790 SCTAB i; 791 ScBaseCell** ppOldCells = NULL; 792 SCTAB* pTabs = NULL; 793 SCTAB nPos = 0; 794 EditTextObject* pUndoData = NULL; 795 if (bRecord && !bSimple) 796 { 797 ppOldCells = new ScBaseCell*[nSelCount]; 798 pTabs = new SCTAB[nSelCount]; 799 nPos = 0; 800 801 for (i=0; i<nTabCount; i++) 802 if (rMark.GetTableSelect(i)) 803 { 804 pTabs[nPos] = i; 805 ScBaseCell* pDocCell; 806 pDoc->GetCell( nCol, nRow, i, pDocCell ); 807 ppOldCells[nPos] = pDocCell ? pDocCell->CloneWithoutNote( *pDoc ) : 0; 808 ++nPos; 809 } 810 811 DBG_ASSERT( nPos==nSelCount, "nPos!=nSelCount" ); 812 813 pUndoData = pData->Clone(); 814 } 815 816 // 817 // Daten eintragen 818 // 819 820 if (bCommon) 821 pDoc->ApplyPattern(nCol,nRow,nTab,*pCellAttrs); //! Undo 822 823 if (bSimple) 824 { 825 if (bCommon) 826 AdjustRowHeight(nRow,nRow); 827 828 EnterData(nCol,nRow,nTab,aString,bRecord); 829 } 830 else 831 { 832 for (i=0; i<nTabCount; i++) 833 if (rMark.GetTableSelect(i)) 834 pDoc->PutCell( nCol, nRow, i, new ScEditCell( pData, pDoc, NULL ) ); 835 836 if ( bRecord ) 837 { // wg. ChangeTrack erst jetzt 838 pDocSh->GetUndoManager()->AddUndoAction( 839 new ScUndoEnterData( pDocSh, nCol, nRow, nTab, nPos, pTabs, 840 ppOldCells, NULL, NULL, aString, 841 pUndoData ) ); 842 } 843 844 HideAllCursors(); 845 846 AdjustRowHeight(nRow,nRow); 847 848 for (i=0; i<nTabCount; i++) 849 if (rMark.GetTableSelect(i)) 850 pDocSh->PostPaintCell( nCol, nRow, i ); 851 852 ShowAllCursors(); 853 854 pDocSh->UpdateOle(GetViewData()); 855 856 // #i97876# Spreadsheet data changes are not notified 857 ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() ); 858 if ( pModelObj && pModelObj->HasChangesListeners() ) 859 { 860 ScRangeList aChangeRanges; 861 for ( i = 0; i < nTabCount; ++i ) 862 { 863 if ( rMark.GetTableSelect( i ) ) 864 { 865 aChangeRanges.Append( ScRange( nCol, nRow, i ) ); 866 } 867 } 868 pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges ); 869 } 870 871 aModificator.SetDocumentModified(); 872 } 873 874 delete pCellAttrs; 875 delete pNewData; 876 } 877 else 878 { 879 ErrorMessage(aTester.GetMessageId()); 880 PaintArea( nCol, nRow, nCol, nRow ); // da steht evtl. noch die Edit-Engine 881 } 882 } 883 884 void ScViewFunc::EnterDataAtCursor( const String& rString ) 885 { 886 SCCOL nPosX = GetViewData()->GetCurX(); 887 SCROW nPosY = GetViewData()->GetCurY(); 888 SCTAB nTab = GetViewData()->GetTabNo(); 889 890 EnterData( nPosX, nPosY, nTab, rString ); 891 } 892 893 void ScViewFunc::EnterMatrix( const String& rString ) 894 { 895 ScViewData* pData = GetViewData(); 896 const ScMarkData& rMark = pData->GetMarkData(); 897 if ( !rMark.IsMarked() && !rMark.IsMultiMarked() ) 898 { 899 // nichts markiert -> automatisch Block mit Groesse des Ergebnisses 900 // Formel temporaer berechnen, um an die Groesse heranzukommen 901 902 ScDocument* pDoc = pData->GetDocument(); 903 SCCOL nCol = pData->GetCurX(); 904 SCROW nRow = pData->GetCurY(); 905 SCTAB nTab = pData->GetTabNo(); 906 ScFormulaCell aFormCell( pDoc, ScAddress(nCol,nRow,nTab), rString,formula::FormulaGrammar::GRAM_DEFAULT, MM_FORMULA ); 907 908 SCSIZE nSizeX; 909 SCSIZE nSizeY; 910 aFormCell.GetResultDimensions( nSizeX, nSizeY ); 911 if ( nSizeX != 0 && nSizeY != 0 && 912 nCol+nSizeX-1 <= sal::static_int_cast<SCSIZE>(MAXCOL) && 913 nRow+nSizeY-1 <= sal::static_int_cast<SCSIZE>(MAXROW) ) 914 { 915 ScRange aResult( nCol, nRow, nTab, 916 sal::static_int_cast<SCCOL>(nCol+nSizeX-1), 917 sal::static_int_cast<SCROW>(nRow+nSizeY-1), nTab ); 918 MarkRange( aResult, sal_False ); 919 } 920 } 921 922 ScRange aRange; 923 if (pData->GetSimpleArea(aRange) == SC_MARK_SIMPLE) 924 { 925 ScDocShell* pDocSh = pData->GetDocShell(); 926 sal_Bool bSuccess = pDocSh->GetDocFunc().EnterMatrix( aRange, &rMark, NULL, rString, sal_False, sal_False, EMPTY_STRING, formula::FormulaGrammar::GRAM_DEFAULT ); 927 if (bSuccess) 928 pDocSh->UpdateOle(GetViewData()); 929 } 930 else 931 ErrorMessage(STR_NOMULTISELECT); 932 } 933 934 sal_uInt8 ScViewFunc::GetSelectionScriptType() 935 { 936 sal_uInt8 nScript = 0; 937 938 ScDocument* pDoc = GetViewData()->GetDocument(); 939 const ScMarkData& rMark = GetViewData()->GetMarkData(); 940 if ( !rMark.IsMarked() && !rMark.IsMultiMarked() ) 941 { 942 // no selection -> cursor 943 944 nScript = pDoc->GetScriptType( GetViewData()->GetCurX(), 945 GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); 946 } 947 else 948 { 949 ScRangeList aRanges; 950 rMark.FillRangeListWithMarks( &aRanges, sal_False ); 951 sal_uLong nCount = aRanges.Count(); 952 for (sal_uLong i=0; i<nCount; i++) 953 { 954 ScRange aRange = *aRanges.GetObject(i); 955 ScCellIterator aIter( pDoc, aRange ); 956 ScBaseCell* pCell = aIter.GetFirst(); 957 while ( pCell ) 958 { 959 nScript |= pDoc->GetScriptType( aIter.GetCol(), aIter.GetRow(), aIter.GetTab(), pCell ); 960 pCell = aIter.GetNext(); 961 } 962 } 963 } 964 965 if (nScript == 0) 966 nScript = ScGlobal::GetDefaultScriptType(); 967 968 return nScript; 969 } 970 971 const ScPatternAttr* ScViewFunc::GetSelectionPattern() 972 { 973 // Don't use UnmarkFiltered in slot state functions, for performance reasons. 974 // The displayed state is always that of the whole selection including filtered rows. 975 976 const ScMarkData& rMark = GetViewData()->GetMarkData(); 977 ScDocument* pDoc = GetViewData()->GetDocument(); 978 if ( rMark.IsMarked() || rMark.IsMultiMarked() ) 979 { 980 // MarkToMulti is no longer necessary for pDoc->GetSelectionPattern 981 const ScPatternAttr* pAttr = pDoc->GetSelectionPattern( rMark ); 982 return pAttr; 983 } 984 else 985 { 986 SCCOL nCol = GetViewData()->GetCurX(); 987 SCROW nRow = GetViewData()->GetCurY(); 988 SCTAB nTab = GetViewData()->GetTabNo(); 989 990 ScMarkData aTempMark( rMark ); // copy sheet selection 991 aTempMark.SetMarkArea( ScRange( nCol, nRow, nTab ) ); 992 const ScPatternAttr* pAttr = pDoc->GetSelectionPattern( aTempMark ); 993 return pAttr; 994 } 995 } 996 997 void ScViewFunc::GetSelectionFrame( SvxBoxItem& rLineOuter, 998 SvxBoxInfoItem& rLineInner ) 999 { 1000 ScDocument* pDoc = GetViewData()->GetDocument(); 1001 const ScMarkData& rMark = GetViewData()->GetMarkData(); 1002 1003 if ( rMark.IsMarked() || rMark.IsMultiMarked() ) 1004 { 1005 if ( rMark.IsMultiMarked() ) 1006 { 1007 ScMarkData aNewMark( rMark ); // use local copy for MarkToSimple 1008 aNewMark.MarkToSimple(); // simple block is needed for GetSelectionFrame 1009 pDoc->GetSelectionFrame( aNewMark, rLineOuter, rLineInner ); 1010 } 1011 else 1012 pDoc->GetSelectionFrame( rMark, rLineOuter, rLineInner ); 1013 } 1014 else 1015 { 1016 const ScPatternAttr* pAttrs = 1017 pDoc->GetPattern( GetViewData()->GetCurX(), 1018 GetViewData()->GetCurY(), 1019 GetViewData()->GetTabNo() ); 1020 1021 rLineOuter = (const SvxBoxItem&) (pAttrs->GetItem( ATTR_BORDER )); 1022 rLineInner = (const SvxBoxInfoItem&)(pAttrs->GetItem( ATTR_BORDER_INNER )); 1023 rLineInner.SetTable(sal_False); 1024 rLineInner.SetDist(sal_True); 1025 rLineInner.SetMinDist(sal_False); 1026 } 1027 } 1028 1029 // 1030 // Attribute anwenden - Undo OK 1031 // 1032 // kompletter Set ( ATTR_STARTINDEX, ATTR_ENDINDEX ) 1033 // 1034 1035 void ScViewFunc::ApplyAttributes( const SfxItemSet* pDialogSet, 1036 const SfxItemSet* pOldSet, 1037 sal_Bool bRecord ) 1038 { 1039 // nur wegen Matrix nicht editierbar? Attribute trotzdem ok 1040 sal_Bool bOnlyNotBecauseOfMatrix; 1041 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix ) 1042 { 1043 ErrorMessage(STR_PROTECTIONERR); 1044 return; 1045 } 1046 1047 ScPatternAttr aOldAttrs( new SfxItemSet(*pOldSet) ); 1048 ScPatternAttr aNewAttrs( new SfxItemSet(*pDialogSet) ); 1049 aNewAttrs.DeleteUnchanged( &aOldAttrs ); 1050 1051 if ( pDialogSet->GetItemState( ATTR_VALUE_FORMAT ) == SFX_ITEM_SET ) 1052 { // #82521# don't reset to default SYSTEM GENERAL if not intended 1053 sal_uInt32 nOldFormat = 1054 ((const SfxUInt32Item&)pOldSet->Get( ATTR_VALUE_FORMAT )).GetValue(); 1055 sal_uInt32 nNewFormat = 1056 ((const SfxUInt32Item&)pDialogSet->Get( ATTR_VALUE_FORMAT )).GetValue(); 1057 if ( nNewFormat != nOldFormat ) 1058 { 1059 SvNumberFormatter* pFormatter = 1060 GetViewData()->GetDocument()->GetFormatTable(); 1061 const SvNumberformat* pOldEntry = pFormatter->GetEntry( nOldFormat ); 1062 LanguageType eOldLang = 1063 pOldEntry ? pOldEntry->GetLanguage() : LANGUAGE_DONTKNOW; 1064 const SvNumberformat* pNewEntry = pFormatter->GetEntry( nNewFormat ); 1065 LanguageType eNewLang = 1066 pNewEntry ? pNewEntry->GetLanguage() : LANGUAGE_DONTKNOW; 1067 if ( eNewLang != eOldLang ) 1068 { 1069 aNewAttrs.GetItemSet().Put( 1070 SvxLanguageItem( eNewLang, ATTR_LANGUAGE_FORMAT ) ); 1071 1072 // #40606# nur die Sprache geaendert -> Zahlformat-Attribut nicht anfassen 1073 sal_uInt32 nNewMod = nNewFormat % SV_COUNTRY_LANGUAGE_OFFSET; 1074 if ( nNewMod == ( nOldFormat % SV_COUNTRY_LANGUAGE_OFFSET ) && 1075 nNewMod <= SV_MAX_ANZ_STANDARD_FORMATE ) 1076 aNewAttrs.GetItemSet().ClearItem( ATTR_VALUE_FORMAT ); 1077 } 1078 } 1079 } 1080 1081 const SvxBoxItem* pOldOuter = (const SvxBoxItem*) &pOldSet->Get( ATTR_BORDER ); 1082 const SvxBoxItem* pNewOuter = (const SvxBoxItem*) &pDialogSet->Get( ATTR_BORDER ); 1083 const SvxBoxInfoItem* pOldInner = (const SvxBoxInfoItem*) &pOldSet->Get( ATTR_BORDER_INNER ); 1084 const SvxBoxInfoItem* pNewInner = (const SvxBoxInfoItem*) &pDialogSet->Get( ATTR_BORDER_INNER ); 1085 SfxItemSet& rNewSet = aNewAttrs.GetItemSet(); 1086 SfxItemPool* pNewPool = rNewSet.GetPool(); 1087 1088 pNewPool->Put( *pNewOuter ); // noch nicht loeschen 1089 pNewPool->Put( *pNewInner ); 1090 rNewSet.ClearItem( ATTR_BORDER ); 1091 rNewSet.ClearItem( ATTR_BORDER_INNER ); 1092 1093 /* 1094 * Feststellen, ob Rahmenattribute zu setzen sind: 1095 * 1. Neu != Alt 1096 * 2. Ist eine der Linien nicht-DontCare (seit 238.f: IsxxValid()) 1097 * 1098 */ 1099 1100 sal_Bool bFrame = (pDialogSet->GetItemState( ATTR_BORDER ) != SFX_ITEM_DEFAULT) 1101 || (pDialogSet->GetItemState( ATTR_BORDER_INNER ) != SFX_ITEM_DEFAULT); 1102 1103 if ( pNewOuter==pOldOuter && pNewInner==pOldInner ) 1104 bFrame = sal_False; 1105 1106 // das sollte doch der Pool abfangen: ?!??!?? 1107 1108 if ( bFrame && pNewOuter && pNewInner ) 1109 if ( *pNewOuter == *pOldOuter && *pNewInner == *pOldInner ) 1110 bFrame = sal_False; 1111 1112 if ( pNewInner ) 1113 { 1114 bFrame = bFrame 1115 && ( pNewInner->IsValid(VALID_LEFT) 1116 || pNewInner->IsValid(VALID_RIGHT) 1117 || pNewInner->IsValid(VALID_TOP) 1118 || pNewInner->IsValid(VALID_BOTTOM) 1119 || pNewInner->IsValid(VALID_HORI) 1120 || pNewInner->IsValid(VALID_VERT) ); 1121 } 1122 else 1123 bFrame = sal_False; 1124 1125 if (!bFrame) 1126 ApplySelectionPattern( aNewAttrs, bRecord ); // nur normale 1127 else 1128 { 1129 // wenn neue Items Default-Items sind, so muessen die 1130 // alten Items geputtet werden: 1131 1132 sal_Bool bDefNewOuter = ( SFX_ITEMS_STATICDEFAULT == pNewOuter->GetKind() ); 1133 sal_Bool bDefNewInner = ( SFX_ITEMS_STATICDEFAULT == pNewInner->GetKind() ); 1134 1135 ApplyPatternLines( aNewAttrs, 1136 bDefNewOuter ? pOldOuter : pNewOuter, 1137 bDefNewInner ? pOldInner : pNewInner, 1138 bRecord ); 1139 } 1140 1141 pNewPool->Remove( *pNewOuter ); // freigeben 1142 pNewPool->Remove( *pNewInner ); 1143 1144 // Hoehen anpassen 1145 AdjustBlockHeight(); 1146 1147 // CellContentChanged wird von ApplySelectionPattern / ApplyPatternLines gerufen 1148 } 1149 1150 void ScViewFunc::ApplyAttr( const SfxPoolItem& rAttrItem ) 1151 { 1152 // nur wegen Matrix nicht editierbar? Attribute trotzdem ok 1153 sal_Bool bOnlyNotBecauseOfMatrix; 1154 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix ) 1155 { 1156 ErrorMessage(STR_PROTECTIONERR); 1157 return; 1158 } 1159 1160 ScPatternAttr aNewAttrs( new SfxItemSet( *GetViewData()->GetDocument()->GetPool(), 1161 ATTR_PATTERN_START, ATTR_PATTERN_END ) ); 1162 1163 aNewAttrs.GetItemSet().Put( rAttrItem ); 1164 // Wenn Ausrichtung eingestellt wird (ueber Buttons), immer Einzug 0 1165 if ( rAttrItem.Which() == ATTR_HOR_JUSTIFY ) 1166 aNewAttrs.GetItemSet().Put( SfxUInt16Item( ATTR_INDENT, 0 ) ); 1167 ApplySelectionPattern( aNewAttrs ); 1168 1169 AdjustBlockHeight(); 1170 1171 // CellContentChanged wird von ApplySelectionPattern gerufen 1172 } 1173 1174 1175 // Pattern und Rahmen 1176 1177 void ScViewFunc::ApplyPatternLines( const ScPatternAttr& rAttr, const SvxBoxItem* pNewOuter, 1178 const SvxBoxInfoItem* pNewInner, sal_Bool bRecord ) 1179 { 1180 ScDocument* pDoc = GetViewData()->GetDocument(); 1181 ScMarkData aFuncMark( GetViewData()->GetMarkData() ); // local copy for UnmarkFiltered 1182 ScViewUtil::UnmarkFiltered( aFuncMark, pDoc ); 1183 if (bRecord && !pDoc->IsUndoEnabled()) 1184 bRecord = sal_False; 1185 1186 ScRange aMarkRange; 1187 aFuncMark.MarkToSimple(); 1188 sal_Bool bMulti = aFuncMark.IsMultiMarked(); 1189 if (bMulti) 1190 aFuncMark.GetMultiMarkArea( aMarkRange ); 1191 else if (aFuncMark.IsMarked()) 1192 aFuncMark.GetMarkArea( aMarkRange ); 1193 else 1194 { 1195 aMarkRange = ScRange( GetViewData()->GetCurX(), 1196 GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); 1197 DoneBlockMode(); 1198 InitOwnBlockMode(); 1199 aFuncMark.SetMarkArea(aMarkRange); 1200 MarkDataChanged(); 1201 } 1202 1203 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 1204 1205 ScDocShellModificator aModificator( *pDocSh ); 1206 1207 if (bRecord) 1208 { 1209 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 1210 SCTAB nStartTab = aMarkRange.aStart.Tab(); 1211 SCTAB nTabCount = pDoc->GetTableCount(); 1212 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab ); 1213 for (SCTAB i=0; i<nTabCount; i++) 1214 if (i != nStartTab && aFuncMark.GetTableSelect(i)) 1215 pUndoDoc->AddUndoTab( i, i ); 1216 1217 ScRange aCopyRange = aMarkRange; 1218 aCopyRange.aStart.SetTab(0); 1219 aCopyRange.aEnd.SetTab(nTabCount-1); 1220 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pUndoDoc, &aFuncMark ); 1221 1222 pDocSh->GetUndoManager()->AddUndoAction( 1223 new ScUndoSelectionAttr( 1224 pDocSh, aFuncMark, 1225 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), aMarkRange.aStart.Tab(), 1226 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), aMarkRange.aEnd.Tab(), 1227 pUndoDoc, bMulti, &rAttr, pNewOuter, pNewInner ) ); 1228 } 1229 1230 sal_uInt16 nExt = SC_PF_TESTMERGE; 1231 pDocSh->UpdatePaintExt( nExt, aMarkRange ); // content before the change 1232 1233 pDoc->ApplySelectionFrame( aFuncMark, pNewOuter, pNewInner ); 1234 1235 pDocSh->UpdatePaintExt( nExt, aMarkRange ); // content after the change 1236 1237 aFuncMark.MarkToMulti(); 1238 pDoc->ApplySelectionPattern( rAttr, aFuncMark ); 1239 1240 pDocSh->PostPaint( aMarkRange, PAINT_GRID, nExt ); 1241 pDocSh->UpdateOle(GetViewData()); 1242 aModificator.SetDocumentModified(); 1243 CellContentChanged(); 1244 1245 StartFormatArea(); 1246 } 1247 1248 // nur Pattern 1249 1250 void ScViewFunc::ApplySelectionPattern( const ScPatternAttr& rAttr, 1251 sal_Bool bRecord, sal_Bool bCursorOnly ) 1252 { 1253 ScViewData* pViewData = GetViewData(); 1254 ScDocShell* pDocSh = pViewData->GetDocShell(); 1255 ScDocument* pDoc = pDocSh->GetDocument(); 1256 ScMarkData aFuncMark( pViewData->GetMarkData() ); // local copy for UnmarkFiltered 1257 ScViewUtil::UnmarkFiltered( aFuncMark, pDoc ); 1258 1259 if (bRecord && !pDoc->IsUndoEnabled()) 1260 bRecord = sal_False; 1261 1262 // State from old ItemSet doesn't matter for paint flags, as any change will be 1263 // from SFX_ITEM_SET in the new ItemSet (default is ignored in ApplyPattern). 1264 // New alignment is checked (check in PostPaint isn't enough) in case a right 1265 // alignment is changed to left. 1266 const SfxItemSet& rNewSet = rAttr.GetItemSet(); 1267 sal_Bool bSetLines = rNewSet.GetItemState( ATTR_BORDER, sal_True ) == SFX_ITEM_SET || 1268 rNewSet.GetItemState( ATTR_SHADOW, sal_True ) == SFX_ITEM_SET; 1269 sal_Bool bSetAlign = rNewSet.GetItemState( ATTR_HOR_JUSTIFY, sal_True ) == SFX_ITEM_SET; 1270 1271 sal_uInt16 nExtFlags = 0; 1272 if ( bSetLines ) 1273 nExtFlags |= SC_PF_LINES; 1274 if ( bSetAlign ) 1275 nExtFlags |= SC_PF_WHOLEROWS; 1276 1277 ScDocShellModificator aModificator( *pDocSh ); 1278 1279 sal_Bool bMulti = aFuncMark.IsMultiMarked(); 1280 aFuncMark.MarkToMulti(); 1281 sal_Bool bOnlyTab = (!aFuncMark.IsMultiMarked() && !bCursorOnly && aFuncMark.GetSelectCount() > 1); 1282 if (bOnlyTab) 1283 { 1284 SCCOL nCol = pViewData->GetCurX(); 1285 SCROW nRow = pViewData->GetCurY(); 1286 SCTAB nTab = pViewData->GetTabNo(); 1287 aFuncMark.SetMarkArea(ScRange(nCol,nRow,nTab)); 1288 aFuncMark.MarkToMulti(); 1289 } 1290 1291 ScRangeList aChangeRanges; 1292 1293 if (aFuncMark.IsMultiMarked() && !bCursorOnly) 1294 { 1295 ScRange aMarkRange; 1296 aFuncMark.GetMultiMarkArea( aMarkRange ); 1297 SCTAB nTabCount = pDoc->GetTableCount(); 1298 for ( SCTAB i = 0; i < nTabCount; ++i ) 1299 { 1300 if ( aFuncMark.GetTableSelect( i ) ) 1301 { 1302 ScRange aChangeRange( aMarkRange ); 1303 aChangeRange.aStart.SetTab( i ); 1304 aChangeRange.aEnd.SetTab( i ); 1305 aChangeRanges.Append( aChangeRange ); 1306 } 1307 } 1308 1309 SCCOL nStartCol = aMarkRange.aStart.Col(); 1310 SCROW nStartRow = aMarkRange.aStart.Row(); 1311 SCTAB nStartTab = aMarkRange.aStart.Tab(); 1312 SCCOL nEndCol = aMarkRange.aEnd.Col(); 1313 SCROW nEndRow = aMarkRange.aEnd.Row(); 1314 SCTAB nEndTab = aMarkRange.aEnd.Tab(); 1315 1316 if (bRecord) 1317 { 1318 ScRange aCopyRange = aMarkRange; 1319 aCopyRange.aStart.SetTab(0); 1320 aCopyRange.aEnd.SetTab(nTabCount-1); 1321 1322 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 1323 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab ); 1324 for (SCTAB i=0; i<nTabCount; i++) 1325 if (i != nStartTab && aFuncMark.GetTableSelect(i)) 1326 pUndoDoc->AddUndoTab( i, i ); 1327 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pUndoDoc, &aFuncMark ); 1328 1329 aFuncMark.MarkToMulti(); 1330 1331 pDocSh->GetUndoManager()->AddUndoAction( 1332 new ScUndoSelectionAttr( 1333 pDocSh, aFuncMark, 1334 nStartCol, nStartRow, nStartTab, 1335 nEndCol, nEndRow, nEndTab, 1336 pUndoDoc, bMulti, &rAttr ) ); 1337 } 1338 1339 pDoc->ApplySelectionPattern( rAttr, aFuncMark ); 1340 1341 pDocSh->PostPaint( nStartCol, nStartRow, nStartTab, 1342 nEndCol, nEndRow, nEndTab, 1343 PAINT_GRID, nExtFlags | SC_PF_TESTMERGE ); 1344 pDocSh->UpdateOle(GetViewData()); 1345 aModificator.SetDocumentModified(); 1346 CellContentChanged(); 1347 } 1348 else // einzelne Zelle - Undo einfacher 1349 { 1350 SCCOL nCol = pViewData->GetCurX(); 1351 SCROW nRow = pViewData->GetCurY(); 1352 SCTAB nTab = pViewData->GetTabNo(); 1353 aChangeRanges.Append( ScRange( nCol, nRow, nTab ) ); 1354 ScPatternAttr* pOldPat = new ScPatternAttr(*pDoc->GetPattern( nCol, nRow, nTab )); 1355 1356 pDoc->ApplyPattern( nCol, nRow, nTab, rAttr ); 1357 1358 const ScPatternAttr* pNewPat = pDoc->GetPattern( nCol, nRow, nTab ); 1359 1360 if (bRecord) 1361 { 1362 pDocSh->GetUndoManager()->AddUndoAction( 1363 new ScUndoCursorAttr( pDocSh, 1364 nCol, nRow, nTab, 1365 pOldPat, pNewPat, &rAttr, 1366 sal_False ) ); // sal_False = nicht automatisch 1367 } 1368 delete pOldPat; // wird im Undo kopiert (Pool) 1369 1370 pDocSh->PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PAINT_GRID, nExtFlags | SC_PF_TESTMERGE ); 1371 pDocSh->UpdateOle(GetViewData()); 1372 aModificator.SetDocumentModified(); 1373 CellContentChanged(); 1374 } 1375 1376 // #i97876# Spreadsheet data changes are not notified 1377 ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() ); 1378 if ( pModelObj && pModelObj->HasChangesListeners() ) 1379 { 1380 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aProperties; 1381 sal_Int32 nCount = 0; 1382 const SfxItemPropertyMap* pMap = ScCellObj::GetCellPropertyMap(); 1383 PropertyEntryVector_t aPropVector = pMap->getPropertyEntries(); 1384 for ( sal_uInt16 nWhich = ATTR_PATTERN_START; nWhich <= ATTR_PATTERN_END; ++nWhich ) 1385 { 1386 const SfxPoolItem* pItem = 0; 1387 if ( rNewSet.GetItemState( nWhich, sal_True, &pItem ) == SFX_ITEM_SET && pItem ) 1388 { 1389 PropertyEntryVector_t::const_iterator aIt = aPropVector.begin(); 1390 while ( aIt != aPropVector.end()) 1391 { 1392 if ( aIt->nWID == nWhich ) 1393 { 1394 ::com::sun::star::uno::Any aVal; 1395 pItem->QueryValue( aVal, aIt->nMemberId ); 1396 aProperties.realloc( nCount + 1 ); 1397 aProperties[ nCount ].Name = aIt->sName; 1398 aProperties[ nCount ].Value <<= aVal; 1399 ++nCount; 1400 } 1401 ++aIt; 1402 } 1403 } 1404 } 1405 pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "attribute" ) ), aChangeRanges, aProperties ); 1406 } 1407 1408 StartFormatArea(); 1409 } 1410 1411 void ScViewFunc::ApplyUserItemSet( const SfxItemSet& rItemSet ) 1412 { 1413 // ItemSet from UI, may have different pool 1414 1415 sal_Bool bOnlyNotBecauseOfMatrix; 1416 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix ) 1417 { 1418 ErrorMessage(STR_PROTECTIONERR); 1419 return; 1420 } 1421 1422 ScPatternAttr aNewAttrs( GetViewData()->GetDocument()->GetPool() ); 1423 SfxItemSet& rNewSet = aNewAttrs.GetItemSet(); 1424 rNewSet.Put( rItemSet, sal_False ); 1425 ApplySelectionPattern( aNewAttrs ); 1426 1427 AdjustBlockHeight(); 1428 } 1429 1430 const SfxStyleSheet* ScViewFunc::GetStyleSheetFromMarked() 1431 { 1432 // Don't use UnmarkFiltered in slot state functions, for performance reasons. 1433 // The displayed state is always that of the whole selection including filtered rows. 1434 1435 const ScStyleSheet* pSheet = NULL; 1436 ScViewData* pViewData = GetViewData(); 1437 ScDocument* pDoc = pViewData->GetDocument(); 1438 ScMarkData& rMark = pViewData->GetMarkData(); 1439 1440 if ( rMark.IsMarked() || rMark.IsMultiMarked() ) 1441 pSheet = pDoc->GetSelectionStyle( rMark ); // MarkToMulti isn't necessary 1442 else 1443 pSheet = pDoc->GetStyle( pViewData->GetCurX(), 1444 pViewData->GetCurY(), 1445 pViewData->GetTabNo() ); 1446 1447 return pSheet; 1448 } 1449 1450 void ScViewFunc::SetStyleSheetToMarked( SfxStyleSheet* pStyleSheet, sal_Bool bRecord ) 1451 { 1452 // nur wegen Matrix nicht editierbar? Attribute trotzdem ok 1453 sal_Bool bOnlyNotBecauseOfMatrix; 1454 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix ) 1455 { 1456 ErrorMessage(STR_PROTECTIONERR); 1457 return; 1458 } 1459 1460 if ( !pStyleSheet) return; 1461 // ------------------------------------------------------------------- 1462 1463 ScViewData* pViewData = GetViewData(); 1464 ScDocShell* pDocSh = pViewData->GetDocShell(); 1465 ScDocument* pDoc = pDocSh->GetDocument(); 1466 ScMarkData aFuncMark( pViewData->GetMarkData() ); // local copy for UnmarkFiltered 1467 ScViewUtil::UnmarkFiltered( aFuncMark, pDoc ); 1468 SCTAB nTabCount = pDoc->GetTableCount(); 1469 if (bRecord && !pDoc->IsUndoEnabled()) 1470 bRecord = sal_False; 1471 1472 ScDocShellModificator aModificator( *pDocSh ); 1473 1474 if ( aFuncMark.IsMarked() || aFuncMark.IsMultiMarked() ) 1475 { 1476 ScRange aMarkRange; 1477 aFuncMark.MarkToMulti(); 1478 aFuncMark.GetMultiMarkArea( aMarkRange ); 1479 1480 if ( bRecord ) 1481 { 1482 SCTAB nTab = pViewData->GetTabNo(); 1483 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 1484 pUndoDoc->InitUndo( pDoc, nTab, nTab ); 1485 for (SCTAB i=0; i<nTabCount; i++) 1486 if (i != nTab && aFuncMark.GetTableSelect(i)) 1487 pUndoDoc->AddUndoTab( i, i ); 1488 1489 ScRange aCopyRange = aMarkRange; 1490 aCopyRange.aStart.SetTab(0); 1491 aCopyRange.aEnd.SetTab(nTabCount-1); 1492 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, sal_True, pUndoDoc, &aFuncMark ); 1493 aFuncMark.MarkToMulti(); 1494 1495 String aName = pStyleSheet->GetName(); 1496 pDocSh->GetUndoManager()->AddUndoAction( 1497 new ScUndoSelectionStyle( pDocSh, aFuncMark, aMarkRange, aName, pUndoDoc ) ); 1498 } 1499 1500 pDoc->ApplySelectionStyle( (ScStyleSheet&)*pStyleSheet, aFuncMark ); 1501 1502 if (!AdjustBlockHeight()) 1503 pViewData->GetDocShell()->PostPaint( aMarkRange, PAINT_GRID ); 1504 1505 aFuncMark.MarkToSimple(); 1506 } 1507 else 1508 { 1509 SCCOL nCol = pViewData->GetCurX(); 1510 SCROW nRow = pViewData->GetCurY(); 1511 SCTAB nTab = pViewData->GetTabNo(); 1512 1513 if ( bRecord ) 1514 { 1515 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 1516 pUndoDoc->InitUndo( pDoc, nTab, nTab ); 1517 for (SCTAB i=0; i<nTabCount; i++) 1518 if (i != nTab && aFuncMark.GetTableSelect(i)) 1519 pUndoDoc->AddUndoTab( i, i ); 1520 1521 ScRange aCopyRange( nCol, nRow, 0, nCol, nRow, nTabCount-1 ); 1522 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, sal_False, pUndoDoc ); 1523 1524 ScRange aMarkRange ( nCol, nRow, nTab ); 1525 ScMarkData aUndoMark = aFuncMark; 1526 aUndoMark.SetMultiMarkArea( aMarkRange ); 1527 1528 String aName = pStyleSheet->GetName(); 1529 pDocSh->GetUndoManager()->AddUndoAction( 1530 new ScUndoSelectionStyle( pDocSh, aUndoMark, aMarkRange, aName, pUndoDoc ) ); 1531 } 1532 1533 for (SCTAB i=0; i<nTabCount; i++) 1534 if (aFuncMark.GetTableSelect(i)) 1535 pDoc->ApplyStyle( nCol, nRow, i, (ScStyleSheet&)*pStyleSheet ); 1536 1537 if (!AdjustBlockHeight()) 1538 pViewData->GetDocShell()->PostPaintCell( nCol, nRow, nTab ); 1539 1540 } 1541 1542 aModificator.SetDocumentModified(); 1543 1544 StartFormatArea(); 1545 } 1546 1547 1548 void ScViewFunc::RemoveStyleSheetInUse( const SfxStyleSheetBase* pStyleSheet ) 1549 { 1550 if ( !pStyleSheet) return; 1551 // ------------------------------------------------------------------- 1552 1553 ScViewData* pViewData = GetViewData(); 1554 ScDocument* pDoc = pViewData->GetDocument(); 1555 ScDocShell* pDocSh = pViewData->GetDocShell(); 1556 1557 ScDocShellModificator aModificator( *pDocSh ); 1558 1559 VirtualDevice aVirtDev; 1560 aVirtDev.SetMapMode(MAP_PIXEL); 1561 pDoc->StyleSheetChanged( pStyleSheet, sal_True, &aVirtDev, 1562 pViewData->GetPPTX(), 1563 pViewData->GetPPTY(), 1564 pViewData->GetZoomX(), 1565 pViewData->GetZoomY() ); 1566 1567 pDocSh->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID|PAINT_LEFT ); 1568 aModificator.SetDocumentModified(); 1569 1570 ScInputHandler* pHdl = SC_MOD()->GetInputHdl(); 1571 if (pHdl) 1572 pHdl->ForgetLastPattern(); 1573 } 1574 1575 void ScViewFunc::UpdateStyleSheetInUse( const SfxStyleSheetBase* pStyleSheet ) 1576 { 1577 if ( !pStyleSheet) return; 1578 // ------------------------------------------------------------------- 1579 1580 ScViewData* pViewData = GetViewData(); 1581 ScDocument* pDoc = pViewData->GetDocument(); 1582 ScDocShell* pDocSh = pViewData->GetDocShell(); 1583 1584 ScDocShellModificator aModificator( *pDocSh ); 1585 1586 VirtualDevice aVirtDev; 1587 aVirtDev.SetMapMode(MAP_PIXEL); 1588 pDoc->StyleSheetChanged( pStyleSheet, sal_False, &aVirtDev, 1589 pViewData->GetPPTX(), 1590 pViewData->GetPPTY(), 1591 pViewData->GetZoomX(), 1592 pViewData->GetZoomY() ); 1593 1594 pDocSh->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID|PAINT_LEFT ); 1595 aModificator.SetDocumentModified(); 1596 1597 ScInputHandler* pHdl = SC_MOD()->GetInputHdl(); 1598 if (pHdl) 1599 pHdl->ForgetLastPattern(); 1600 } 1601 1602 // Zellen einfuegen - Undo OK 1603 1604 sal_Bool ScViewFunc::InsertCells( InsCellCmd eCmd, sal_Bool bRecord, sal_Bool bPartOfPaste ) 1605 { 1606 ScRange aRange; 1607 if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE) 1608 { 1609 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 1610 const ScMarkData& rMark = GetViewData()->GetMarkData(); 1611 sal_Bool bSuccess = pDocSh->GetDocFunc().InsertCells( aRange, &rMark, eCmd, bRecord, sal_False, bPartOfPaste ); 1612 if (bSuccess) 1613 { 1614 pDocSh->UpdateOle(GetViewData()); 1615 CellContentChanged(); 1616 1617 // #i97876# Spreadsheet data changes are not notified 1618 ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() ); 1619 if ( pModelObj && pModelObj->HasChangesListeners() ) 1620 { 1621 if ( eCmd == INS_INSROWS || eCmd == INS_INSCOLS ) 1622 { 1623 ScRangeList aChangeRanges; 1624 aChangeRanges.Append( aRange ); 1625 ::rtl::OUString aOperation = ( eCmd == INS_INSROWS ? 1626 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert-rows" ) ) : 1627 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert-columns" ) ) ); 1628 pModelObj->NotifyChanges( aOperation, aChangeRanges ); 1629 } 1630 } 1631 } 1632 return bSuccess; 1633 } 1634 else 1635 { 1636 ErrorMessage(STR_NOMULTISELECT); 1637 return sal_False; 1638 } 1639 } 1640 1641 // Zellen loeschen - Undo OK 1642 1643 void ScViewFunc::DeleteCells( DelCellCmd eCmd, sal_Bool bRecord ) 1644 { 1645 ScRange aRange; 1646 if ( GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE ) 1647 { 1648 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 1649 const ScMarkData& rMark = GetViewData()->GetMarkData(); 1650 1651 // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong 1652 if ( pDocSh->IsDocShared() && ( eCmd == DEL_DELROWS || eCmd == DEL_DELCOLS ) ) 1653 { 1654 ScRange aDelRange( aRange.aStart ); 1655 SCCOLROW nCount = 0; 1656 if ( eCmd == DEL_DELROWS ) 1657 { 1658 nCount = sal::static_int_cast< SCCOLROW >( aRange.aEnd.Row() - aRange.aStart.Row() + 1 ); 1659 } 1660 else 1661 { 1662 nCount = sal::static_int_cast< SCCOLROW >( aRange.aEnd.Col() - aRange.aStart.Col() + 1 ); 1663 } 1664 while ( nCount > 0 ) 1665 { 1666 pDocSh->GetDocFunc().DeleteCells( aDelRange, &rMark, eCmd, bRecord, sal_False ); 1667 --nCount; 1668 } 1669 } 1670 else 1671 { 1672 pDocSh->GetDocFunc().DeleteCells( aRange, &rMark, eCmd, bRecord, sal_False ); 1673 } 1674 1675 pDocSh->UpdateOle(GetViewData()); 1676 CellContentChanged(); 1677 1678 // #i97876# Spreadsheet data changes are not notified 1679 ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() ); 1680 if ( pModelObj && pModelObj->HasChangesListeners() ) 1681 { 1682 if ( eCmd == DEL_DELROWS || eCmd == DEL_DELCOLS ) 1683 { 1684 ScRangeList aChangeRanges; 1685 aChangeRanges.Append( aRange ); 1686 ::rtl::OUString aOperation = ( eCmd == DEL_DELROWS ? 1687 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete-rows" ) ) : 1688 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete-columns" ) ) ); 1689 pModelObj->NotifyChanges( aOperation, aChangeRanges ); 1690 } 1691 } 1692 1693 // #58106# Cursor direkt hinter den geloeschten Bereich setzen 1694 SCCOL nCurX = GetViewData()->GetCurX(); 1695 SCROW nCurY = GetViewData()->GetCurY(); 1696 if ( eCmd==DEL_CELLSLEFT || eCmd==DEL_DELCOLS ) 1697 nCurX = aRange.aStart.Col(); 1698 else 1699 nCurY = aRange.aStart.Row(); 1700 SetCursor( nCurX, nCurY ); 1701 } 1702 else 1703 { 1704 if (eCmd == DEL_DELCOLS) 1705 DeleteMulti( sal_False, bRecord ); 1706 else if (eCmd == DEL_DELROWS) 1707 DeleteMulti( sal_True, bRecord ); 1708 else 1709 ErrorMessage(STR_NOMULTISELECT); 1710 } 1711 1712 Unmark(); 1713 } 1714 1715 void ScViewFunc::DeleteMulti( sal_Bool bRows, sal_Bool bRecord ) 1716 { 1717 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 1718 ScDocShellModificator aModificator( *pDocSh ); 1719 SCTAB nTab = GetViewData()->GetTabNo(); 1720 ScDocument* pDoc = pDocSh->GetDocument(); 1721 ScMarkData aFuncMark( GetViewData()->GetMarkData() ); // local copy for UnmarkFiltered 1722 ScViewUtil::UnmarkFiltered( aFuncMark, pDoc ); 1723 1724 if (bRecord && !pDoc->IsUndoEnabled()) 1725 bRecord = sal_False; 1726 SCCOLROW* pRanges = new SCCOLROW[MAXCOLROWCOUNT]; 1727 SCCOLROW nRangeCnt = bRows ? aFuncMark.GetMarkRowRanges( pRanges ) : 1728 aFuncMark.GetMarkColumnRanges( pRanges ); 1729 if (nRangeCnt == 0) 1730 { 1731 pRanges[0] = pRanges[1] = bRows ? static_cast<SCCOLROW>(GetViewData()->GetCurY()) : static_cast<SCCOLROW>(GetViewData()->GetCurX()); 1732 nRangeCnt = 1; 1733 } 1734 1735 // Test ob erlaubt 1736 1737 SCCOLROW* pOneRange = pRanges; 1738 sal_uInt16 nErrorId = 0; 1739 sal_Bool bNeedRefresh = sal_False; 1740 SCCOLROW nRangeNo; 1741 for (nRangeNo=0; nRangeNo<nRangeCnt && !nErrorId; nRangeNo++) 1742 { 1743 SCCOLROW nStart = *(pOneRange++); 1744 SCCOLROW nEnd = *(pOneRange++); 1745 1746 SCCOL nStartCol, nEndCol; 1747 SCROW nStartRow, nEndRow; 1748 if ( bRows ) 1749 { 1750 nStartCol = 0; 1751 nEndCol = MAXCOL; 1752 nStartRow = static_cast<SCROW>(nStart); 1753 nEndRow = static_cast<SCROW>(nEnd); 1754 } 1755 else 1756 { 1757 nStartCol = static_cast<SCCOL>(nStart); 1758 nEndCol = static_cast<SCCOL>(nEnd); 1759 nStartRow = 0; 1760 nEndRow = MAXROW; 1761 } 1762 1763 // cell protection (only needed for first range, as all following cells are moved) 1764 if ( nRangeNo == 0 ) 1765 { 1766 // test to the end of the sheet 1767 ScEditableTester aTester( pDoc, nTab, nStartCol, nStartRow, MAXCOL, MAXROW ); 1768 if (!aTester.IsEditable()) 1769 nErrorId = aTester.GetMessageId(); 1770 } 1771 1772 // merged cells 1773 SCCOL nMergeStartX = nStartCol; 1774 SCROW nMergeStartY = nStartRow; 1775 SCCOL nMergeEndX = nEndCol; 1776 SCROW nMergeEndY = nEndRow; 1777 pDoc->ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, nTab ); 1778 pDoc->ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, nTab ); 1779 1780 if ( nMergeStartX != nStartCol || nMergeStartY != nStartRow ) 1781 { 1782 // Disallow deleting parts of a merged cell. 1783 // Deleting the start is allowed (merge is removed), so the end doesn't have to be checked. 1784 1785 nErrorId = STR_MSSG_DELETECELLS_0; 1786 } 1787 if ( nMergeEndX != nEndCol || nMergeEndY != nEndRow ) 1788 { 1789 // detect if the start of a merged cell is deleted, so the merge flags can be refreshed 1790 1791 bNeedRefresh = sal_True; 1792 } 1793 } 1794 1795 if ( nErrorId ) 1796 { 1797 ErrorMessage( nErrorId ); 1798 delete[] pRanges; 1799 return; 1800 } 1801 1802 // ausfuehren 1803 1804 WaitObject aWait( GetFrameWin() ); // wichtig wegen TrackFormulas bei UpdateReference 1805 1806 ScDocument* pUndoDoc = NULL; 1807 ScRefUndoData* pUndoData = NULL; 1808 if (bRecord) 1809 { 1810 pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 1811 pUndoDoc->InitUndo( pDoc, nTab, nTab, !bRows, bRows ); // Zeilenhoehen 1812 1813 pOneRange = pRanges; 1814 for (nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++) 1815 { 1816 SCCOLROW nStart = *(pOneRange++); 1817 SCCOLROW nEnd = *(pOneRange++); 1818 if (bRows) 1819 pDoc->CopyToDocument( 0,nStart,nTab, MAXCOL,nEnd,nTab, IDF_ALL,sal_False,pUndoDoc ); 1820 else 1821 pDoc->CopyToDocument( static_cast<SCCOL>(nStart),0,nTab, 1822 static_cast<SCCOL>(nEnd),MAXROW,nTab, 1823 IDF_ALL,sal_False,pUndoDoc ); 1824 } 1825 1826 // alle Formeln wegen Referenzen 1827 SCTAB nTabCount = pDoc->GetTableCount(); 1828 pUndoDoc->AddUndoTab( 0, nTabCount-1, sal_False, sal_False ); 1829 pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,MAXTAB, IDF_FORMULA,sal_False,pUndoDoc ); 1830 1831 pUndoData = new ScRefUndoData( pDoc ); 1832 1833 pDoc->BeginDrawUndo(); 1834 } 1835 1836 pOneRange = &pRanges[2*nRangeCnt]; // rueckwaerts 1837 for (nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++) 1838 { 1839 SCCOLROW nEnd = *(--pOneRange); 1840 SCCOLROW nStart = *(--pOneRange); 1841 1842 if (bRows) 1843 pDoc->DeleteRow( 0,nTab, MAXCOL,nTab, nStart, static_cast<SCSIZE>(nEnd-nStart+1) ); 1844 else 1845 pDoc->DeleteCol( 0,nTab, MAXROW,nTab, static_cast<SCCOL>(nStart), static_cast<SCSIZE>(nEnd-nStart+1) ); 1846 } 1847 1848 if (bNeedRefresh) 1849 { 1850 SCCOLROW nFirstStart = pRanges[0]; 1851 SCCOL nStartCol = bRows ? 0 : static_cast<SCCOL>(nFirstStart); 1852 SCROW nStartRow = bRows ? static_cast<SCROW>(nFirstStart) : 0; 1853 SCCOL nEndCol = MAXCOL; 1854 SCROW nEndRow = MAXROW; 1855 1856 pDoc->RemoveFlagsTab( nStartCol, nStartRow, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER ); 1857 pDoc->ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow, nTab, sal_True ); 1858 } 1859 1860 if (bRecord) 1861 { 1862 pDocSh->GetUndoManager()->AddUndoAction( 1863 new ScUndoDeleteMulti( pDocSh, bRows, bNeedRefresh, nTab, pRanges, nRangeCnt, 1864 pUndoDoc, pUndoData ) ); 1865 } 1866 1867 if (!AdjustRowHeight(0, MAXROW)) 1868 { 1869 if (bRows) 1870 pDocSh->PostPaint( 0,pRanges[0],nTab, MAXCOL,MAXROW,nTab, PAINT_GRID | PAINT_LEFT ); 1871 else 1872 pDocSh->PostPaint( static_cast<SCCOL>(pRanges[0]),0,nTab, 1873 MAXCOL,MAXROW,nTab, PAINT_GRID | PAINT_TOP ); 1874 } 1875 aModificator.SetDocumentModified(); 1876 1877 CellContentChanged(); 1878 1879 // #58106# Cursor direkt hinter den ersten geloeschten Bereich setzen 1880 SCCOL nCurX = GetViewData()->GetCurX(); 1881 SCROW nCurY = GetViewData()->GetCurY(); 1882 if ( bRows ) 1883 nCurY = pRanges[0]; 1884 else 1885 nCurX = static_cast<SCCOL>(pRanges[0]); 1886 SetCursor( nCurX, nCurY ); 1887 1888 delete[] pRanges; 1889 1890 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); 1891 } 1892 1893 // Inhalte loeschen 1894 1895 void ScViewFunc::DeleteContents( sal_uInt16 nFlags, sal_Bool bRecord ) 1896 { 1897 // nur wegen Matrix nicht editierbar? Attribute trotzdem ok 1898 sal_Bool bOnlyNotBecauseOfMatrix; 1899 sal_Bool bEditable = SelectionEditable( &bOnlyNotBecauseOfMatrix ); 1900 if ( !bEditable ) 1901 { 1902 if ( !(bOnlyNotBecauseOfMatrix && 1903 ((nFlags & (IDF_ATTRIB | IDF_EDITATTR)) == nFlags)) ) 1904 { 1905 ErrorMessage(bOnlyNotBecauseOfMatrix ? STR_MATRIXFRAGMENTERR : STR_PROTECTIONERR); 1906 return; 1907 } 1908 } 1909 1910 ScRange aMarkRange; 1911 sal_Bool bSimple = sal_False; 1912 1913 ScDocument* pDoc = GetViewData()->GetDocument(); 1914 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 1915 ScMarkData aFuncMark( GetViewData()->GetMarkData() ); // local copy for UnmarkFiltered 1916 ScViewUtil::UnmarkFiltered( aFuncMark, pDoc ); 1917 1918 if (bRecord && !pDoc->IsUndoEnabled()) 1919 bRecord = sal_False; 1920 1921 ScDocShellModificator aModificator( *pDocSh ); 1922 1923 if ( !aFuncMark.IsMarked() && !aFuncMark.IsMultiMarked() ) 1924 { 1925 aMarkRange.aStart.SetCol(GetViewData()->GetCurX()); 1926 aMarkRange.aStart.SetRow(GetViewData()->GetCurY()); 1927 aMarkRange.aStart.SetTab(GetViewData()->GetTabNo()); 1928 aMarkRange.aEnd = aMarkRange.aStart; 1929 if ( pDoc->HasAttrib( aMarkRange, HASATTR_MERGED ) ) 1930 { 1931 // InitOwnBlockMode(); 1932 aFuncMark.SetMarkArea( aMarkRange ); 1933 } 1934 else 1935 bSimple = sal_True; 1936 } 1937 1938 aFuncMark.SetMarking(sal_False); // for MarkToMulti 1939 aFuncMark.MarkToSimple(); // before bMulti test below 1940 1941 DBG_ASSERT( aFuncMark.IsMarked() || aFuncMark.IsMultiMarked() || bSimple, "delete what?" ); 1942 1943 ScDocument* pUndoDoc = NULL; 1944 sal_Bool bMulti = !bSimple && aFuncMark.IsMultiMarked(); 1945 if (!bSimple) 1946 { 1947 aFuncMark.MarkToMulti(); 1948 aFuncMark.GetMultiMarkArea( aMarkRange ); 1949 } 1950 ScRange aExtendedRange(aMarkRange); 1951 if (!bSimple) 1952 { 1953 if ( pDoc->ExtendMerge( aExtendedRange, sal_True ) ) 1954 bMulti = sal_False; 1955 } 1956 1957 // keine Objekte auf geschuetzten Tabellen 1958 sal_Bool bObjects = sal_False; 1959 if ( nFlags & IDF_OBJECTS ) 1960 { 1961 bObjects = sal_True; 1962 SCTAB nTabCount = pDoc->GetTableCount(); 1963 for (SCTAB nTab=0; nTab<nTabCount; nTab++) 1964 if (aFuncMark.GetTableSelect(nTab) && pDoc->IsTabProtected(nTab)) 1965 bObjects = sal_False; 1966 } 1967 1968 sal_uInt16 nExtFlags = 0; // extra flags are needed only if attributes are deleted 1969 if ( nFlags & IDF_ATTRIB ) 1970 pDocSh->UpdatePaintExt( nExtFlags, aMarkRange ); 1971 1972 // Reihenfolge: 1973 // 1) BeginDrawUndo 1974 // 2) Objekte loeschen (DrawUndo wird gefuellt) 1975 // 3) Inhalte fuer Undo kopieren 1976 // 4) Inhalte loeschen 1977 // 5) Undo-Aktion anlegen 1978 1979 sal_Bool bDrawUndo = bObjects || ( nFlags & IDF_NOTE ); // needed for shown notes 1980 if ( bDrawUndo && bRecord ) 1981 pDoc->BeginDrawUndo(); 1982 1983 if (bObjects) 1984 { 1985 if (bMulti) 1986 pDoc->DeleteObjectsInSelection( aFuncMark ); 1987 else 1988 pDoc->DeleteObjectsInArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), 1989 /*!*/ aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), 1990 aFuncMark ); 1991 } 1992 1993 if ( bRecord ) 1994 { 1995 pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 1996 SCTAB nTab = aMarkRange.aStart.Tab(); 1997 pUndoDoc->InitUndo( pDoc, nTab, nTab ); 1998 SCTAB nTabCount = pDoc->GetTableCount(); 1999 for (SCTAB i=0; i<nTabCount; i++) 2000 if (i != nTab && aFuncMark.GetTableSelect(i)) 2001 pUndoDoc->AddUndoTab( i, i ); 2002 ScRange aCopyRange = aExtendedRange; 2003 aCopyRange.aStart.SetTab(0); 2004 aCopyRange.aEnd.SetTab(nTabCount-1); 2005 2006 // bei "Format/Standard" alle Attribute kopieren, weil CopyToDocument 2007 // nur mit IDF_HARDATTR zu langsam ist: 2008 sal_uInt16 nUndoDocFlags = nFlags; 2009 if (nFlags & IDF_ATTRIB) 2010 nUndoDocFlags |= IDF_ATTRIB; 2011 if (nFlags & IDF_EDITATTR) // Edit-Engine-Attribute 2012 nUndoDocFlags |= IDF_STRING; // -> Zellen werden geaendert 2013 if (nFlags & IDF_NOTE) 2014 nUndoDocFlags |= IDF_CONTENTS; // #68795# copy all cells with their notes 2015 // do not copy note captions to undo document 2016 nUndoDocFlags |= IDF_NOCAPTIONS; 2017 pDoc->CopyToDocument( aCopyRange, nUndoDocFlags, bMulti, pUndoDoc, &aFuncMark ); 2018 } 2019 2020 HideAllCursors(); // falls Zusammenfassung aufgehoben wird 2021 if (bSimple) 2022 pDoc->DeleteArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), 2023 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), 2024 aFuncMark, nFlags ); 2025 else 2026 { 2027 pDoc->DeleteSelection( nFlags, aFuncMark ); 2028 // aFuncMark.MarkToSimple(); 2029 } 2030 2031 if ( bRecord ) 2032 { 2033 pDocSh->GetUndoManager()->AddUndoAction( 2034 new ScUndoDeleteContents( pDocSh, aFuncMark, aExtendedRange, 2035 pUndoDoc, bMulti, nFlags, bDrawUndo ) ); 2036 } 2037 2038 if (!AdjustRowHeight( aExtendedRange.aStart.Row(), aExtendedRange.aEnd.Row() )) 2039 pDocSh->PostPaint( aExtendedRange, PAINT_GRID, nExtFlags ); 2040 2041 pDocSh->UpdateOle(GetViewData()); 2042 2043 // #i97876# Spreadsheet data changes are not notified 2044 ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() ); 2045 if ( pModelObj && pModelObj->HasChangesListeners() ) 2046 { 2047 ScRangeList aChangeRanges; 2048 if ( bSimple ) 2049 { 2050 aChangeRanges.Append( aMarkRange ); 2051 } 2052 else 2053 { 2054 aFuncMark.FillRangeListWithMarks( &aChangeRanges, sal_False ); 2055 } 2056 pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges ); 2057 } 2058 2059 aModificator.SetDocumentModified(); 2060 CellContentChanged(); 2061 ShowAllCursors(); 2062 2063 if ( nFlags & IDF_ATTRIB ) 2064 { 2065 if ( nFlags & IDF_CONTENTS ) 2066 ForgetFormatArea(); 2067 else 2068 StartFormatArea(); // Attribute loeschen ist auch Attributierung 2069 } 2070 } 2071 2072 // Spaltenbreiten/Zeilenhoehen (ueber Header) - Undo OK 2073 2074 void ScViewFunc::SetWidthOrHeight( sal_Bool bWidth, SCCOLROW nRangeCnt, SCCOLROW* pRanges, 2075 ScSizeMode eMode, sal_uInt16 nSizeTwips, 2076 sal_Bool bRecord, sal_Bool bPaint, ScMarkData* pMarkData ) 2077 { 2078 if (nRangeCnt == 0) 2079 return; 2080 2081 // use view's mark if none specified 2082 if ( !pMarkData ) 2083 pMarkData = &GetViewData()->GetMarkData(); 2084 2085 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 2086 ScDocument* pDoc = pDocSh->GetDocument(); 2087 SCTAB nTabCount = pDoc->GetTableCount(); 2088 SCTAB nFirstTab = pMarkData->GetFirstSelected(); 2089 SCTAB nCurTab = GetViewData()->GetTabNo(); 2090 SCTAB nTab; 2091 if (bRecord && !pDoc->IsUndoEnabled()) 2092 bRecord = sal_False; 2093 2094 ScDocShellModificator aModificator( *pDocSh ); 2095 2096 sal_Bool bAllowed = sal_True; 2097 for (nTab=0; nTab<nTabCount && bAllowed; nTab++) 2098 if (pMarkData->GetTableSelect(nTab)) 2099 { 2100 for ( SCCOLROW i=0; i<nRangeCnt && bAllowed; i++ ) 2101 { 2102 sal_Bool bOnlyMatrix; 2103 if (bWidth) 2104 bAllowed = pDoc->IsBlockEditable( nTab, 2105 static_cast<SCCOL>(pRanges[2*i]),0, 2106 static_cast<SCCOL>(pRanges[2*i+1]),MAXROW, 2107 &bOnlyMatrix ) || bOnlyMatrix; 2108 else 2109 bAllowed = pDoc->IsBlockEditable( nTab, 0,pRanges[2*i], 2110 MAXCOL,pRanges[2*i+1], &bOnlyMatrix ) || 2111 bOnlyMatrix; 2112 } 2113 } 2114 if ( !bAllowed ) 2115 { 2116 ErrorMessage(STR_PROTECTIONERR); 2117 return; 2118 } 2119 2120 SCCOLROW nStart = pRanges[0]; 2121 SCCOLROW nEnd = pRanges[2*nRangeCnt-1]; 2122 2123 sal_Bool bFormula = sal_False; 2124 if ( eMode == SC_SIZE_OPTIMAL ) 2125 { 2126 const ScViewOptions& rOpts = GetViewData()->GetOptions(); 2127 bFormula = rOpts.GetOption( VOPT_FORMULAS ); 2128 } 2129 2130 ScDocument* pUndoDoc = NULL; 2131 ScOutlineTable* pUndoTab = NULL; 2132 SCCOLROW* pUndoRanges = NULL; 2133 2134 if ( bRecord ) 2135 { 2136 pDoc->BeginDrawUndo(); // Drawing Updates 2137 2138 pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 2139 for (nTab=0; nTab<nTabCount; nTab++) 2140 if (pMarkData->GetTableSelect(nTab)) 2141 { 2142 if (bWidth) 2143 { 2144 if ( nTab == nFirstTab ) 2145 pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_False ); 2146 else 2147 pUndoDoc->AddUndoTab( nTab, nTab, sal_True, sal_False ); 2148 pDoc->CopyToDocument( static_cast<SCCOL>(nStart), 0, nTab, 2149 static_cast<SCCOL>(nEnd), MAXROW, nTab, IDF_NONE, 2150 sal_False, pUndoDoc ); 2151 } 2152 else 2153 { 2154 if ( nTab == nFirstTab ) 2155 pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_False, sal_True ); 2156 else 2157 pUndoDoc->AddUndoTab( nTab, nTab, sal_False, sal_True ); 2158 pDoc->CopyToDocument( 0, nStart, nTab, MAXCOL, nEnd, nTab, IDF_NONE, sal_False, pUndoDoc ); 2159 } 2160 } 2161 2162 pUndoRanges = new SCCOLROW[ 2*nRangeCnt ]; 2163 memmove( pUndoRanges, pRanges, 2*nRangeCnt*sizeof(SCCOLROW) ); 2164 2165 //! outlines from all tables? 2166 ScOutlineTable* pTable = pDoc->GetOutlineTable( nCurTab ); 2167 if (pTable) 2168 pUndoTab = new ScOutlineTable( *pTable ); 2169 } 2170 2171 if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT ) 2172 pMarkData->MarkToMulti(); 2173 2174 sal_Bool bShow = nSizeTwips > 0 || eMode != SC_SIZE_DIRECT; 2175 sal_Bool bOutline = sal_False; 2176 2177 for (nTab=0; nTab<nTabCount; nTab++) 2178 if (pMarkData->GetTableSelect(nTab)) 2179 { 2180 const SCCOLROW* pTabRanges = pRanges; 2181 2182 pDoc->IncSizeRecalcLevel( nTab ); // nicht fuer jede Spalte einzeln 2183 pDoc->InitializeNoteCaptions( nTab ); 2184 for (SCCOLROW nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++) 2185 { 2186 SCCOLROW nStartNo = *(pTabRanges++); 2187 SCCOLROW nEndNo = *(pTabRanges++); 2188 2189 if ( !bWidth ) // Hoehen immer blockweise 2190 { 2191 if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT ) 2192 { 2193 sal_Bool bAll = ( eMode==SC_SIZE_OPTIMAL ); 2194 if (!bAll) 2195 { 2196 // fuer alle eingeblendeten CR_MANUALSIZE loeschen, 2197 // dann SetOptimalHeight mit bShrink = FALSE 2198 for (SCROW nRow = nStartNo; nRow <= nEndNo; ++nRow) 2199 { 2200 SCROW nLastRow = nRow; 2201 if (pDoc->RowHidden(nRow, nTab, NULL, &nLastRow)) 2202 { 2203 nRow = nLastRow; 2204 continue; 2205 } 2206 2207 sal_uInt8 nOld = pDoc->GetRowFlags(nRow, nTab); 2208 if (nOld & CR_MANUALSIZE) 2209 pDoc->SetRowFlags(nRow, nTab, nOld & ~CR_MANUALSIZE); 2210 } 2211 } 2212 2213 double nPPTX = GetViewData()->GetPPTX(); 2214 double nPPTY = GetViewData()->GetPPTY(); 2215 Fraction aZoomX = GetViewData()->GetZoomX(); 2216 Fraction aZoomY = GetViewData()->GetZoomY(); 2217 2218 ScSizeDeviceProvider aProv(pDocSh); 2219 if (aProv.IsPrinter()) 2220 { 2221 nPPTX = aProv.GetPPTX(); 2222 nPPTY = aProv.GetPPTY(); 2223 aZoomX = aZoomY = Fraction( 1, 1 ); 2224 } 2225 2226 pDoc->SetOptimalHeight( nStartNo, nEndNo, nTab, nSizeTwips, aProv.GetDevice(), 2227 nPPTX, nPPTY, aZoomX, aZoomY, bAll ); 2228 if (bAll) 2229 pDoc->ShowRows( nStartNo, nEndNo, nTab, sal_True ); 2230 2231 // Manual-Flag wird bei bAll=sal_True schon in SetOptimalHeight gesetzt 2232 // (an bei Extra-Height, sonst aus). 2233 } 2234 else if ( eMode==SC_SIZE_DIRECT ) 2235 { 2236 if (nSizeTwips) 2237 { 2238 pDoc->SetRowHeightRange( nStartNo, nEndNo, nTab, nSizeTwips ); 2239 pDoc->SetManualHeight( nStartNo, nEndNo, nTab, sal_True ); // height was set manually 2240 } 2241 pDoc->ShowRows( nStartNo, nEndNo, nTab, nSizeTwips != 0 ); 2242 } 2243 else if ( eMode==SC_SIZE_SHOW ) 2244 { 2245 pDoc->ShowRows( nStartNo, nEndNo, nTab, sal_True ); 2246 } 2247 } 2248 else // Spaltenbreiten 2249 { 2250 for (SCCOL nCol=static_cast<SCCOL>(nStartNo); nCol<=static_cast<SCCOL>(nEndNo); nCol++) 2251 { 2252 if ( eMode != SC_SIZE_VISOPT || !pDoc->ColHidden(nCol, nTab) ) 2253 { 2254 sal_uInt16 nThisSize = nSizeTwips; 2255 2256 if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT ) 2257 nThisSize = nSizeTwips + GetOptimalColWidth( nCol, nTab, bFormula ); 2258 if ( nThisSize ) 2259 pDoc->SetColWidth( nCol, nTab, nThisSize ); 2260 2261 pDoc->ShowCol( nCol, nTab, bShow ); 2262 } 2263 } 2264 } 2265 2266 // Outline anpassen 2267 2268 if (bWidth) 2269 { 2270 if ( pDoc->UpdateOutlineCol( static_cast<SCCOL>(nStartNo), 2271 static_cast<SCCOL>(nEndNo), nTab, bShow ) ) 2272 bOutline = sal_True; 2273 } 2274 else 2275 { 2276 if ( pDoc->UpdateOutlineRow( nStartNo, nEndNo, nTab, bShow ) ) 2277 bOutline = sal_True; 2278 } 2279 } 2280 pDoc->DecSizeRecalcLevel( nTab ); // nicht fuer jede Spalte einzeln 2281 } 2282 2283 2284 if (!bOutline) 2285 DELETEZ(pUndoTab); 2286 2287 if (bRecord) 2288 { 2289 pDocSh->GetUndoManager()->AddUndoAction( 2290 new ScUndoWidthOrHeight( pDocSh, *pMarkData, 2291 nStart, nCurTab, nEnd, nCurTab, 2292 pUndoDoc, nRangeCnt, pUndoRanges, 2293 pUndoTab, eMode, nSizeTwips, bWidth ) ); 2294 } 2295 2296 for (nTab=0; nTab<nTabCount; nTab++) 2297 if (pMarkData->GetTableSelect(nTab)) 2298 pDoc->UpdatePageBreaks( nTab ); 2299 2300 GetViewData()->GetView()->UpdateScrollBars(); 2301 2302 if (bPaint) 2303 { 2304 HideCursor(); 2305 2306 for (nTab=0; nTab<nTabCount; nTab++) 2307 if (pMarkData->GetTableSelect(nTab)) 2308 { 2309 if (bWidth) 2310 { 2311 if (pDoc->HasAttrib( static_cast<SCCOL>(nStart),0,nTab, 2312 static_cast<SCCOL>(nEnd),MAXROW,nTab, 2313 HASATTR_MERGED | HASATTR_OVERLAPPED )) 2314 nStart = 0; 2315 if (nStart > 0) // weiter oben anfangen wegen Linien und Cursor 2316 --nStart; 2317 pDocSh->PostPaint( static_cast<SCCOL>(nStart), 0, nTab, 2318 MAXCOL, MAXROW, nTab, PAINT_GRID | PAINT_TOP ); 2319 } 2320 else 2321 { 2322 if (pDoc->HasAttrib( 0,nStart,nTab, MAXCOL,nEnd,nTab, HASATTR_MERGED | HASATTR_OVERLAPPED )) 2323 nStart = 0; 2324 if (nStart != 0) 2325 --nStart; 2326 pDocSh->PostPaint( 0, nStart, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID | PAINT_LEFT ); 2327 } 2328 } 2329 2330 pDocSh->UpdateOle(GetViewData()); 2331 aModificator.SetDocumentModified(); 2332 2333 ShowCursor(); 2334 } 2335 2336 // #i97876# Spreadsheet data changes are not notified 2337 if ( bWidth ) 2338 { 2339 ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() ); 2340 if ( pModelObj && pModelObj->HasChangesListeners() ) 2341 { 2342 ScRangeList aChangeRanges; 2343 for ( nTab = 0; nTab < nTabCount; ++nTab ) 2344 { 2345 if ( pMarkData->GetTableSelect( nTab ) ) 2346 { 2347 const SCCOLROW* pTabRanges = pRanges; 2348 for ( SCCOLROW nRange = 0; nRange < nRangeCnt; ++nRange ) 2349 { 2350 SCCOL nStartCol = static_cast< SCCOL >( *(pTabRanges++) ); 2351 SCCOL nEndCol = static_cast< SCCOL >( *(pTabRanges++) ); 2352 for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol ) 2353 { 2354 aChangeRanges.Append( ScRange( nCol, 0, nTab ) ); 2355 } 2356 } 2357 } 2358 } 2359 pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "column-resize" ) ), aChangeRanges ); 2360 } 2361 } 2362 } 2363 2364 // Spaltenbreiten/Zeilenhoehen (ueber Blockmarken) 2365 2366 void ScViewFunc::SetMarkedWidthOrHeight( sal_Bool bWidth, ScSizeMode eMode, sal_uInt16 nSizeTwips, 2367 sal_Bool bRecord, sal_Bool bPaint ) 2368 { 2369 ScMarkData& rMark = GetViewData()->GetMarkData(); 2370 2371 rMark.MarkToMulti(); 2372 if (!rMark.IsMultiMarked()) 2373 { 2374 SCCOL nCol = GetViewData()->GetCurX(); 2375 SCROW nRow = GetViewData()->GetCurY(); 2376 SCTAB nTab = GetViewData()->GetTabNo(); 2377 DoneBlockMode(); 2378 InitOwnBlockMode(); 2379 rMark.SetMultiMarkArea( ScRange( nCol,nRow,nTab ), sal_True ); 2380 MarkDataChanged(); 2381 } 2382 2383 SCCOLROW* pRanges = new SCCOLROW[MAXCOLROWCOUNT]; 2384 SCCOLROW nRangeCnt = 0; 2385 2386 if ( bWidth ) 2387 nRangeCnt = rMark.GetMarkColumnRanges( pRanges ); 2388 else 2389 nRangeCnt = rMark.GetMarkRowRanges( pRanges ); 2390 2391 SetWidthOrHeight( bWidth, nRangeCnt, pRanges, eMode, nSizeTwips, bRecord, bPaint ); 2392 2393 delete[] pRanges; 2394 rMark.MarkToSimple(); 2395 } 2396 2397 void ScViewFunc::ModifyCellSize( ScDirection eDir, sal_Bool bOptimal ) 2398 { 2399 //! Schrittweiten einstellbar 2400 // Schrittweite ist auch Minimum 2401 sal_uInt16 nStepX = STD_COL_WIDTH / 5; 2402 sal_uInt16 nStepY = ScGlobal::nStdRowHeight; 2403 2404 ScModule* pScMod = SC_MOD(); 2405 sal_Bool bAnyEdit = pScMod->IsInputMode(); 2406 SCCOL nCol = GetViewData()->GetCurX(); 2407 SCROW nRow = GetViewData()->GetCurY(); 2408 SCTAB nTab = GetViewData()->GetTabNo(); 2409 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 2410 ScDocument* pDoc = pDocSh->GetDocument(); 2411 2412 sal_Bool bAllowed, bOnlyMatrix; 2413 if ( eDir == DIR_LEFT || eDir == DIR_RIGHT ) 2414 bAllowed = pDoc->IsBlockEditable( nTab, nCol,0, nCol,MAXROW, &bOnlyMatrix ); 2415 else 2416 bAllowed = pDoc->IsBlockEditable( nTab, 0,nRow, MAXCOL,nRow, &bOnlyMatrix ); 2417 if ( !bAllowed && !bOnlyMatrix ) 2418 { 2419 ErrorMessage(STR_PROTECTIONERR); 2420 return; 2421 } 2422 2423 HideAllCursors(); 2424 2425 sal_uInt16 nWidth = pDoc->GetColWidth( nCol, nTab ); 2426 sal_uInt16 nHeight = pDoc->GetRowHeight( nRow, nTab ); 2427 SCCOLROW nRange[2]; 2428 if ( eDir == DIR_LEFT || eDir == DIR_RIGHT ) 2429 { 2430 if (bOptimal) // Breite dieser einen Zelle 2431 { 2432 if ( bAnyEdit ) 2433 { 2434 // beim Editieren die aktuelle Breite der Eingabe 2435 ScInputHandler* pHdl = pScMod->GetInputHdl( GetViewData()->GetViewShell() ); 2436 if (pHdl) 2437 { 2438 long nEdit = pHdl->GetTextSize().Width(); // in 1/100mm 2439 2440 const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab ); 2441 const SvxMarginItem& rMItem = 2442 (const SvxMarginItem&)pPattern->GetItem(ATTR_MARGIN); 2443 sal_uInt16 nMargin = rMItem.GetLeftMargin() + rMItem.GetRightMargin(); 2444 if ( ((const SvxHorJustifyItem&) pPattern-> 2445 GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_LEFT ) 2446 nMargin = sal::static_int_cast<sal_uInt16>( 2447 nMargin + ((const SfxUInt16Item&)pPattern->GetItem(ATTR_INDENT)).GetValue() ); 2448 2449 nWidth = (sal_uInt16)(nEdit * pDocSh->GetOutputFactor() / HMM_PER_TWIPS) 2450 + nMargin + STD_EXTRA_WIDTH; 2451 } 2452 } 2453 else 2454 { 2455 double nPPTX = GetViewData()->GetPPTX(); 2456 double nPPTY = GetViewData()->GetPPTY(); 2457 Fraction aZoomX = GetViewData()->GetZoomX(); 2458 Fraction aZoomY = GetViewData()->GetZoomY(); 2459 2460 ScSizeDeviceProvider aProv(pDocSh); 2461 if (aProv.IsPrinter()) 2462 { 2463 nPPTX = aProv.GetPPTX(); 2464 nPPTY = aProv.GetPPTY(); 2465 aZoomX = aZoomY = Fraction( 1, 1 ); 2466 } 2467 2468 long nPixel = pDoc->GetNeededSize( nCol, nRow, nTab, aProv.GetDevice(), 2469 nPPTX, nPPTY, aZoomX, aZoomY, sal_True ); 2470 sal_uInt16 nTwips = (sal_uInt16)( nPixel / nPPTX ); 2471 if (nTwips != 0) 2472 nWidth = nTwips + STD_EXTRA_WIDTH; 2473 else 2474 nWidth = STD_COL_WIDTH; 2475 } 2476 } 2477 else // vergroessern / verkleinern 2478 { 2479 if ( eDir == DIR_RIGHT ) 2480 nWidth = sal::static_int_cast<sal_uInt16>( nWidth + nStepX ); 2481 else if ( nWidth > nStepX ) 2482 nWidth = sal::static_int_cast<sal_uInt16>( nWidth - nStepX ); 2483 if ( nWidth < nStepX ) nWidth = nStepX; 2484 if ( nWidth > MAX_COL_WIDTH ) nWidth = MAX_COL_WIDTH; 2485 } 2486 nRange[0] = nRange[1] = nCol; 2487 SetWidthOrHeight( sal_True, 1, nRange, SC_SIZE_DIRECT, nWidth ); 2488 2489 // hier bei Breite auch Hoehe anpassen (nur die eine Zeile) 2490 2491 if (!bAnyEdit) 2492 { 2493 const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab ); 2494 sal_Bool bNeedHeight = 2495 ((const SfxBoolItem&)pPattern->GetItem( ATTR_LINEBREAK )).GetValue() || 2496 ((const SvxHorJustifyItem&)pPattern-> 2497 GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_BLOCK; 2498 if (bNeedHeight) 2499 AdjustRowHeight( nRow, nRow ); 2500 } 2501 } 2502 else 2503 { 2504 ScSizeMode eMode; 2505 if (bOptimal) 2506 { 2507 eMode = SC_SIZE_OPTIMAL; 2508 nHeight = 0; 2509 } 2510 else 2511 { 2512 eMode = SC_SIZE_DIRECT; 2513 if ( eDir == DIR_BOTTOM ) 2514 nHeight = sal::static_int_cast<sal_uInt16>( nHeight + nStepY ); 2515 else if ( nHeight > nStepY ) 2516 nHeight = sal::static_int_cast<sal_uInt16>( nHeight - nStepY ); 2517 if ( nHeight < nStepY ) nHeight = nStepY; 2518 if ( nHeight > MAX_COL_HEIGHT ) nHeight = MAX_COL_HEIGHT; 2519 //! MAX_COL_HEIGHT umbenennen in MAX_ROW_HEIGHT in global.hxx !!!!!! 2520 } 2521 nRange[0] = nRange[1] = nRow; 2522 SetWidthOrHeight( sal_False, 1, nRange, eMode, nHeight ); 2523 } 2524 2525 if ( bAnyEdit ) 2526 { 2527 UpdateEditView(); 2528 if ( pDoc->HasAttrib( nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_NEEDHEIGHT ) ) 2529 { 2530 ScInputHandler* pHdl = pScMod->GetInputHdl( GetViewData()->GetViewShell() ); 2531 if (pHdl) 2532 pHdl->SetModified(); // damit bei Enter die Hoehe angepasst wird 2533 } 2534 } 2535 2536 ShowAllCursors(); 2537 } 2538 2539 void ScViewFunc::ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect ) 2540 { 2541 if (nTab == TABLEID_DOC) 2542 return; 2543 2544 ScMarkData& rMark = GetViewData()->GetMarkData(); 2545 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 2546 ScDocument* pDoc = pDocSh->GetDocument(); 2547 ScDocFunc aFunc(*pDocSh); 2548 bool bUndo(pDoc->IsUndoEnabled()); 2549 2550 // modifying several tables is handled here 2551 2552 if (bUndo) 2553 { 2554 String aUndo = ScGlobal::GetRscString( STR_UNDO_PROTECT_TAB ); 2555 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo ); 2556 } 2557 2558 SCTAB nCount = pDocSh->GetDocument()->GetTableCount(); 2559 for ( SCTAB i=0; i<nCount; i++ ) 2560 if ( rMark.GetTableSelect(i) ) 2561 aFunc.ProtectSheet(i, rProtect); 2562 2563 if (bUndo) 2564 pDocSh->GetUndoManager()->LeaveListAction(); 2565 2566 UpdateLayerLocks(); //! broadcast to all views 2567 } 2568 2569 void ScViewFunc::Protect( SCTAB nTab, const String& rPassword ) 2570 { 2571 ScMarkData& rMark = GetViewData()->GetMarkData(); 2572 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 2573 ScDocument* pDoc = pDocSh->GetDocument(); 2574 ScDocFunc aFunc(*pDocSh); 2575 sal_Bool bUndo(pDoc->IsUndoEnabled()); 2576 2577 if ( nTab == TABLEID_DOC || rMark.GetSelectCount() <= 1 ) 2578 aFunc.Protect( nTab, rPassword, sal_False ); 2579 else 2580 { 2581 // modifying several tables is handled here 2582 2583 if (bUndo) 2584 { 2585 String aUndo = ScGlobal::GetRscString( STR_UNDO_PROTECT_TAB ); 2586 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo ); 2587 } 2588 2589 SCTAB nCount = pDocSh->GetDocument()->GetTableCount(); 2590 for ( SCTAB i=0; i<nCount; i++ ) 2591 if ( rMark.GetTableSelect(i) ) 2592 aFunc.Protect( i, rPassword, sal_False ); 2593 2594 if (bUndo) 2595 pDocSh->GetUndoManager()->LeaveListAction(); 2596 } 2597 2598 UpdateLayerLocks(); //! broadcast to all views 2599 } 2600 2601 sal_Bool ScViewFunc::Unprotect( SCTAB nTab, const String& rPassword ) 2602 { 2603 ScMarkData& rMark = GetViewData()->GetMarkData(); 2604 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 2605 ScDocument* pDoc = pDocSh->GetDocument(); 2606 ScDocFunc aFunc(*pDocSh); 2607 sal_Bool bChanged = sal_False; 2608 sal_Bool bUndo (pDoc->IsUndoEnabled()); 2609 2610 if ( nTab == TABLEID_DOC || rMark.GetSelectCount() <= 1 ) 2611 bChanged = aFunc.Unprotect( nTab, rPassword, sal_False ); 2612 else 2613 { 2614 // modifying several tables is handled here 2615 2616 if (bUndo) 2617 { 2618 String aUndo = ScGlobal::GetRscString( STR_UNDO_UNPROTECT_TAB ); 2619 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo ); 2620 } 2621 2622 SCTAB nCount = pDocSh->GetDocument()->GetTableCount(); 2623 for ( SCTAB i=0; i<nCount; i++ ) 2624 if ( rMark.GetTableSelect(i) ) 2625 if ( aFunc.Unprotect( i, rPassword, sal_False ) ) 2626 bChanged = sal_True; 2627 2628 if (bUndo) 2629 pDocSh->GetUndoManager()->LeaveListAction(); 2630 } 2631 2632 if (bChanged) 2633 UpdateLayerLocks(); //! broadcast to all views 2634 2635 return bChanged; 2636 } 2637 2638 void ScViewFunc::SetNoteText( const ScAddress& rPos, const String& rNoteText ) 2639 { 2640 GetViewData()->GetDocShell()->GetDocFunc().SetNoteText( rPos, rNoteText, sal_False ); 2641 } 2642 2643 void ScViewFunc::ReplaceNote( const ScAddress& rPos, const String& rNoteText, const String* pAuthor, const String* pDate ) 2644 { 2645 GetViewData()->GetDocShell()->GetDocFunc().ReplaceNote( rPos, rNoteText, pAuthor, pDate, sal_False ); 2646 } 2647 2648 void ScViewFunc::SetNumberFormat( short nFormatType, sal_uLong nAdd ) 2649 { 2650 // nur wegen Matrix nicht editierbar? Attribute trotzdem ok 2651 sal_Bool bOnlyNotBecauseOfMatrix; 2652 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix ) 2653 { 2654 ErrorMessage(STR_PROTECTIONERR); 2655 return; 2656 } 2657 2658 sal_uInt32 nNumberFormat = 0; 2659 ScViewData* pViewData = GetViewData(); 2660 ScDocument* pDoc = pViewData->GetDocument(); 2661 SvNumberFormatter* pNumberFormatter = pDoc->GetFormatTable(); 2662 LanguageType eLanguage = ScGlobal::eLnge; 2663 ScPatternAttr aNewAttrs( pDoc->GetPool() ); 2664 2665 // #67936# always take language from cursor position, even if there is a selection 2666 2667 sal_uInt32 nCurrentNumberFormat; 2668 pDoc->GetNumberFormat( pViewData->GetCurX(), 2669 pViewData->GetCurY(), 2670 pViewData->GetTabNo(), 2671 nCurrentNumberFormat ); 2672 const SvNumberformat* pEntry = pNumberFormatter->GetEntry( nCurrentNumberFormat ); 2673 if (pEntry) 2674 eLanguage = pEntry->GetLanguage(); // sonst ScGlobal::eLnge behalten 2675 2676 nNumberFormat = pNumberFormatter->GetStandardFormat( nFormatType, eLanguage ) + nAdd; 2677 2678 SfxItemSet& rSet = aNewAttrs.GetItemSet(); 2679 rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNumberFormat ) ); 2680 // ATTR_LANGUAGE_FORMAT nicht 2681 ApplySelectionPattern( aNewAttrs, sal_True ); 2682 } 2683 2684 void ScViewFunc::SetNumFmtByStr( const String& rCode ) 2685 { 2686 // nur wegen Matrix nicht editierbar? Attribute trotzdem ok 2687 sal_Bool bOnlyNotBecauseOfMatrix; 2688 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix ) 2689 { 2690 ErrorMessage(STR_PROTECTIONERR); 2691 return; 2692 } 2693 2694 ScViewData* pViewData = GetViewData(); 2695 ScDocument* pDoc = pViewData->GetDocument(); 2696 SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); 2697 2698 // Sprache immer von Cursorposition 2699 2700 sal_uInt32 nCurrentNumberFormat; 2701 pDoc->GetNumberFormat( pViewData->GetCurX(), pViewData->GetCurY(), 2702 pViewData->GetTabNo(), nCurrentNumberFormat ); 2703 const SvNumberformat* pEntry = pFormatter->GetEntry( nCurrentNumberFormat ); 2704 LanguageType eLanguage = pEntry ? pEntry->GetLanguage() : ScGlobal::eLnge; 2705 2706 // Index fuer String bestimmen 2707 2708 sal_Bool bOk = sal_True; 2709 sal_uInt32 nNumberFormat = pFormatter->GetEntryKey( rCode, eLanguage ); 2710 if ( nNumberFormat == NUMBERFORMAT_ENTRY_NOT_FOUND ) 2711 { 2712 // neu eintragen 2713 2714 String aFormat = rCode; // wird veraendert 2715 xub_StrLen nErrPos = 0; 2716 short nType = 0; //! ??? 2717 bOk = pFormatter->PutEntry( aFormat, nErrPos, nType, nNumberFormat, eLanguage ); 2718 } 2719 2720 if ( bOk ) // gueltiges Format? 2721 { 2722 ScPatternAttr aNewAttrs( pDoc->GetPool() ); 2723 SfxItemSet& rSet = aNewAttrs.GetItemSet(); 2724 rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNumberFormat ) ); 2725 rSet.Put( SvxLanguageItem( eLanguage, ATTR_LANGUAGE_FORMAT ) ); 2726 ApplySelectionPattern( aNewAttrs, sal_True ); 2727 } 2728 2729 //! sonst Fehler zuerueckgeben / Meldung ausgeben ??? 2730 } 2731 2732 void ScViewFunc::ChangeNumFmtDecimals( sal_Bool bIncrement ) 2733 { 2734 // nur wegen Matrix nicht editierbar? Attribute trotzdem ok 2735 sal_Bool bOnlyNotBecauseOfMatrix; 2736 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix ) 2737 { 2738 ErrorMessage(STR_PROTECTIONERR); 2739 return; 2740 } 2741 2742 ScDocument* pDoc = GetViewData()->GetDocument(); 2743 SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); 2744 2745 SCCOL nCol = GetViewData()->GetCurX(); 2746 SCROW nRow = GetViewData()->GetCurY(); 2747 SCTAB nTab = GetViewData()->GetTabNo(); 2748 2749 sal_uInt32 nOldFormat; 2750 pDoc->GetNumberFormat( nCol, nRow, nTab, nOldFormat ); 2751 const SvNumberformat* pOldEntry = pFormatter->GetEntry( nOldFormat ); 2752 if (!pOldEntry) 2753 { 2754 DBG_ERROR("Zahlformat nicht gefunden !!!"); 2755 return; 2756 } 2757 2758 // was haben wir denn da? 2759 2760 sal_uInt32 nNewFormat = nOldFormat; 2761 sal_Bool bError = sal_False; 2762 2763 LanguageType eLanguage = pOldEntry->GetLanguage(); 2764 sal_Bool bThousand, bNegRed; 2765 sal_uInt16 nPrecision, nLeading; 2766 pOldEntry->GetFormatSpecialInfo( bThousand, bNegRed, nPrecision, nLeading ); 2767 2768 short nOldType = pOldEntry->GetType(); 2769 if ( 0 == ( nOldType & ( 2770 NUMBERFORMAT_NUMBER | NUMBERFORMAT_CURRENCY | NUMBERFORMAT_PERCENT ) ) ) 2771 { 2772 // Datum, Zeit, Bruch, logisch, Text kann nicht angepasst werden 2773 //! bei Wisssenschaftlich kann es der Numberformatter auch nicht 2774 bError = sal_True; 2775 } 2776 2777 //! Das SvNumberformat hat einen Member bStandard, verraet ihn aber nicht 2778 sal_Bool bWasStandard = ( nOldFormat == pFormatter->GetStandardIndex( eLanguage ) ); 2779 if (bWasStandard) 2780 { 2781 // bei "Standard" die Nachkommastellen abhaengig vom Zellinhalt 2782 // 0 bei leer oder Text -> keine Nachkommastellen 2783 double nVal = pDoc->GetValue( ScAddress( nCol, nRow, nTab ) ); 2784 2785 // Die Wege des Numberformatters sind unergruendlich, darum ausprobieren: 2786 String aOut; 2787 Color* pCol; 2788 ((SvNumberformat*)pOldEntry)->GetOutputString( nVal, aOut, &pCol ); 2789 2790 nPrecision = 0; 2791 // 'E' fuer Exponential ist fest im Numberformatter 2792 if ( aOut.Search('E') != STRING_NOTFOUND ) 2793 bError = sal_True; // Exponential nicht veraendern 2794 else 2795 { 2796 String aDecSep( pFormatter->GetFormatDecimalSep( nOldFormat ) ); 2797 xub_StrLen nPos = aOut.Search( aDecSep ); 2798 if ( nPos != STRING_NOTFOUND ) 2799 nPrecision = aOut.Len() - nPos - aDecSep.Len(); 2800 // sonst 0 behalten 2801 } 2802 } 2803 2804 if (!bError) 2805 { 2806 if (bIncrement) 2807 { 2808 if (nPrecision<20) 2809 ++nPrecision; // erhoehen 2810 else 2811 bError = sal_True; // 20 ist Maximum 2812 } 2813 else 2814 { 2815 if (nPrecision) 2816 --nPrecision; // vermindern 2817 else 2818 bError = sal_True; // weniger als 0 geht nicht 2819 } 2820 } 2821 2822 if (!bError) 2823 { 2824 String aNewPicture; 2825 pFormatter->GenerateFormat( aNewPicture, nOldFormat, eLanguage, 2826 bThousand, bNegRed, nPrecision, nLeading ); 2827 2828 nNewFormat = pFormatter->GetEntryKey( aNewPicture, eLanguage ); 2829 if ( nNewFormat == NUMBERFORMAT_ENTRY_NOT_FOUND ) 2830 { 2831 xub_StrLen nErrPos = 0; 2832 short nNewType = 0; 2833 sal_Bool bOk = pFormatter->PutEntry( aNewPicture, nErrPos, 2834 nNewType, nNewFormat, eLanguage ); 2835 DBG_ASSERT( bOk, "falsches Zahlformat generiert" ); 2836 if (!bOk) 2837 bError = sal_True; 2838 } 2839 } 2840 2841 if (!bError) 2842 { 2843 ScPatternAttr aNewAttrs( pDoc->GetPool() ); 2844 SfxItemSet& rSet = aNewAttrs.GetItemSet(); 2845 rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat ) ); 2846 // ATTR_LANGUAGE_FORMAT nicht 2847 ApplySelectionPattern( aNewAttrs, sal_True ); 2848 } 2849 else 2850 Sound::Beep(); // war nix 2851 } 2852 2853 void ScViewFunc::ChangeIndent( sal_Bool bIncrement ) 2854 { 2855 ScViewData* pViewData = GetViewData(); 2856 ScDocShell* pDocSh = pViewData->GetDocShell(); 2857 ScMarkData& rMark = pViewData->GetMarkData(); 2858 2859 ScMarkData aWorkMark = rMark; 2860 ScViewUtil::UnmarkFiltered( aWorkMark, pDocSh->GetDocument() ); 2861 aWorkMark.MarkToMulti(); 2862 if (!aWorkMark.IsMultiMarked()) 2863 { 2864 SCCOL nCol = pViewData->GetCurX(); 2865 SCROW nRow = pViewData->GetCurY(); 2866 SCTAB nTab = pViewData->GetTabNo(); 2867 aWorkMark.SetMultiMarkArea( ScRange(nCol,nRow,nTab) ); 2868 } 2869 2870 sal_Bool bSuccess = pDocSh->GetDocFunc().ChangeIndent( aWorkMark, bIncrement, sal_False ); 2871 if (bSuccess) 2872 { 2873 pDocSh->UpdateOle(pViewData); 2874 StartFormatArea(); 2875 } 2876 } 2877 2878 sal_Bool ScViewFunc::InsertName( const String& rName, const String& rSymbol, 2879 const String& rType ) 2880 { 2881 // Type = P,R,C,F (und Kombinationen) 2882 //! Undo... 2883 2884 sal_Bool bOk = sal_False; 2885 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 2886 ScDocument* pDoc = pDocSh->GetDocument(); 2887 SCTAB nTab = GetViewData()->GetTabNo(); 2888 ScRangeName* pList = pDoc->GetRangeName(); 2889 2890 RangeType nType = RT_NAME; 2891 ScRangeData* pNewEntry = new ScRangeData( pDoc, rName, rSymbol, 2892 ScAddress( GetViewData()->GetCurX(), GetViewData()->GetCurY(), 2893 nTab), nType ); 2894 String aUpType = rType; 2895 aUpType.ToUpperAscii(); 2896 if ( aUpType.Search( 'P' ) != STRING_NOTFOUND ) 2897 nType |= RT_PRINTAREA; 2898 if ( aUpType.Search( 'R' ) != STRING_NOTFOUND ) 2899 nType |= RT_ROWHEADER; 2900 if ( aUpType.Search( 'C' ) != STRING_NOTFOUND ) 2901 nType |= RT_COLHEADER; 2902 if ( aUpType.Search( 'F' ) != STRING_NOTFOUND ) 2903 nType |= RT_CRITERIA; 2904 pNewEntry->AddType(nType); 2905 2906 if ( !pNewEntry->GetErrCode() ) // Text gueltig? 2907 { 2908 ScDocShellModificator aModificator( *pDocSh ); 2909 2910 pDoc->CompileNameFormula( sal_True ); // CreateFormulaString 2911 2912 // Eintrag bereits vorhanden? Dann vorher entfernen (=Aendern) 2913 sal_uInt16 nFoundAt; 2914 if ( pList->SearchName( rName, nFoundAt ) ) 2915 { // alten Index uebernehmen 2916 pNewEntry->SetIndex( ((ScRangeData*)pList->At(nFoundAt))->GetIndex() ); 2917 pList->AtFree( nFoundAt ); 2918 } 2919 2920 if ( pList->Insert( pNewEntry ) ) 2921 { 2922 pNewEntry = NULL; // nicht loeschen 2923 bOk = sal_True; 2924 } 2925 2926 pDoc->CompileNameFormula( sal_False ); // CompileFormulaString 2927 aModificator.SetDocumentModified(); 2928 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) ); 2929 } 2930 2931 delete pNewEntry; // wenn er nicht eingefuegt wurde 2932 return bOk; 2933 } 2934 2935 void ScViewFunc::CreateNames( sal_uInt16 nFlags ) 2936 { 2937 sal_Bool bDone = sal_False; 2938 ScRange aRange; 2939 if ( GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE ) 2940 bDone = GetViewData()->GetDocShell()->GetDocFunc().CreateNames( aRange, nFlags, sal_False ); 2941 2942 if (!bDone) 2943 ErrorMessage(STR_CREATENAME_MARKERR); 2944 } 2945 2946 sal_uInt16 ScViewFunc::GetCreateNameFlags() 2947 { 2948 sal_uInt16 nFlags = 0; 2949 2950 SCCOL nStartCol, nEndCol; 2951 SCROW nStartRow, nEndRow; 2952 SCTAB nDummy; 2953 if (GetViewData()->GetSimpleArea(nStartCol,nStartRow,nDummy,nEndCol,nEndRow,nDummy) == SC_MARK_SIMPLE) 2954 { 2955 ScDocument* pDoc = GetViewData()->GetDocument(); 2956 SCTAB nTab = GetViewData()->GetTabNo(); 2957 sal_Bool bOk; 2958 SCCOL i; 2959 SCROW j; 2960 2961 bOk = sal_True; 2962 SCCOL nFirstCol = nStartCol; 2963 SCCOL nLastCol = nEndCol; 2964 if (nStartCol+1 < nEndCol) { ++nFirstCol; --nLastCol; } 2965 for (i=nFirstCol; i<=nLastCol && bOk; i++) 2966 if (!pDoc->HasStringData( i,nStartRow,nTab )) 2967 bOk = sal_False; 2968 if (bOk) 2969 nFlags |= NAME_TOP; 2970 else // Bottom nur wenn nicht Top 2971 { 2972 bOk = sal_True; 2973 for (i=nFirstCol; i<=nLastCol && bOk; i++) 2974 if (!pDoc->HasStringData( i,nEndRow,nTab )) 2975 bOk = sal_False; 2976 if (bOk) 2977 nFlags |= NAME_BOTTOM; 2978 } 2979 2980 bOk = sal_True; 2981 SCROW nFirstRow = nStartRow; 2982 SCROW nLastRow = nEndRow; 2983 if (nStartRow+1 < nEndRow) { ++nFirstRow; --nLastRow; } 2984 for (j=nFirstRow; j<=nLastRow && bOk; j++) 2985 if (!pDoc->HasStringData( nStartCol,j,nTab )) 2986 bOk = sal_False; 2987 if (bOk) 2988 nFlags |= NAME_LEFT; 2989 else // Right nur wenn nicht Left 2990 { 2991 bOk = sal_True; 2992 for (j=nFirstRow; j<=nLastRow && bOk; j++) 2993 if (!pDoc->HasStringData( nEndCol,j,nTab )) 2994 bOk = sal_False; 2995 if (bOk) 2996 nFlags |= NAME_RIGHT; 2997 } 2998 } 2999 3000 if (nStartCol == nEndCol) 3001 nFlags &= ~( NAME_LEFT | NAME_RIGHT ); 3002 if (nStartRow == nEndRow) 3003 nFlags &= ~( NAME_TOP | NAME_BOTTOM ); 3004 3005 return nFlags; 3006 } 3007 3008 void ScViewFunc::InsertNameList() 3009 { 3010 ScAddress aPos( GetViewData()->GetCurX(), GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); 3011 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 3012 if ( pDocSh->GetDocFunc().InsertNameList( aPos, sal_False ) ) 3013 pDocSh->UpdateOle(GetViewData()); 3014 } 3015 3016 3017 3018 3019