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