GPU-Calc: remove Alloc_Host_Ptr for clmem of NAN vector
[LibreOffice.git] / sc / source / ui / view / viewfunc.cxx
blob089024a8d50ddca7b229f498a50afca46d0eba29
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
22 #include "scitems.hxx"
23 #include <editeng/eeitem.hxx>
25 #include <sfx2/app.hxx>
26 #include <svx/algitem.hxx>
27 #include <editeng/boxitem.hxx>
28 #include <editeng/editobj.hxx>
29 #include <editeng/editview.hxx>
30 #include <editeng/langitem.hxx>
31 #include <editeng/scripttypeitem.hxx>
32 #include <editeng/justifyitem.hxx>
33 #include <sfx2/bindings.hxx>
34 #include <svl/zforlist.hxx>
35 #include <svl/zformat.hxx>
36 #include <vcl/msgbox.hxx>
37 #include <vcl/virdev.hxx>
38 #include <vcl/waitobj.hxx>
39 #include <vcl/wrkwin.hxx>
40 #include <stdlib.h>
42 #include "viewfunc.hxx"
43 #include "tabvwsh.hxx"
44 #include "docsh.hxx"
45 #include "attrib.hxx"
46 #include "patattr.hxx"
47 #include "docpool.hxx"
48 #include "uiitems.hxx"
49 #include "sc.hrc"
50 #include "undocell.hxx"
51 #include "undoblk.hxx"
52 #include "undotab.hxx"
53 #include "refundo.hxx"
54 #include "dbdata.hxx"
55 #include "olinetab.hxx"
56 #include "rangeutl.hxx"
57 #include "rangenam.hxx"
58 #include "globstr.hrc"
59 #include "global.hxx"
60 #include "stlsheet.hxx"
61 #include "editutil.hxx"
62 #include "formulacell.hxx"
63 #include "scresid.hxx"
64 #include "inputhdl.hxx"
65 #include "scmod.hxx"
66 #include "inputopt.hxx"
67 #include "compiler.hxx"
68 #include "docfunc.hxx"
69 #include "appoptio.hxx"
70 #include "dociter.hxx"
71 #include "sizedev.hxx"
72 #include "editable.hxx"
73 #include "scui_def.hxx"
74 #include "funcdesc.hxx"
75 #include "docuno.hxx"
76 #include "cellsuno.hxx"
77 #include "tokenarray.hxx"
80 //==================================================================
82 static void lcl_PostRepaintCondFormat( const ScConditionalFormat *pCondFmt, ScDocShell *pDocSh )
84 if( pCondFmt )
86 const ScRangeList& rRanges = pCondFmt->GetRange();
88 pDocSh->PostPaint( rRanges, PAINT_ALL );
93 //==================================================================
95 ScViewFunc::ScViewFunc( Window* pParent, ScDocShell& rDocSh, ScTabViewShell* pViewShell ) :
96 ScTabView( pParent, rDocSh, pViewShell ),
97 bFormatValid( false )
101 ScViewFunc::~ScViewFunc()
105 //------------------------------------------------------------------------------------
107 void ScViewFunc::StartFormatArea()
109 // anything to do?
110 if ( !SC_MOD()->GetInputOptions().GetExtendFormat() )
111 return;
113 // start only with single cell (marked or cursor position)
114 ScRange aMarkRange;
115 bool bOk = (GetViewData()->GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE);
116 if ( bOk && aMarkRange.aStart != aMarkRange.aEnd )
117 bOk = false;
119 if (bOk)
121 bFormatValid = true;
122 aFormatSource = aMarkRange.aStart;
123 aFormatArea = ScRange( aFormatSource );
125 else
126 bFormatValid = false; // discard old range
129 bool ScViewFunc::TestFormatArea( SCCOL nCol, SCROW nRow, SCTAB nTab, bool bAttrChanged )
131 // anything to do?
132 if ( !SC_MOD()->GetInputOptions().GetExtendFormat() )
133 return false;
135 // Test: treat input with numberformat (bAttrChanged) always as new Attribute
136 // (discard old Area ). If not not wanted, discard if-statement
137 if ( bAttrChanged )
139 StartFormatArea();
140 return false;
143 //! Test if cell empty ???
145 bool bFound = false;
146 ScRange aNewRange = aFormatArea;
147 if ( bFormatValid && nTab == aFormatSource.Tab() )
149 if ( nRow >= aFormatArea.aStart.Row() && nRow <= aFormatArea.aEnd.Row() )
151 // within range?
152 if ( nCol >= aFormatArea.aStart.Col() && nCol <= aFormatArea.aEnd.Col() )
154 bFound = true; // do not change range
156 // left ?
157 if ( nCol+1 == aFormatArea.aStart.Col() )
159 bFound = true;
160 aNewRange.aStart.SetCol( nCol );
162 // right ?
163 if ( nCol == aFormatArea.aEnd.Col()+1 )
165 bFound = true;
166 aNewRange.aEnd.SetCol( nCol );
169 if ( nCol >= aFormatArea.aStart.Col() && nCol <= aFormatArea.aEnd.Col() )
171 // top ?
172 if ( nRow+1 == aFormatArea.aStart.Row() )
174 bFound = true;
175 aNewRange.aStart.SetRow( nRow );
177 // bottom ?
178 if ( nRow == aFormatArea.aEnd.Row()+1 )
180 bFound = true;
181 aNewRange.aEnd.SetRow( nRow );
186 if (bFound)
187 aFormatArea = aNewRange; // extend
188 else
190 bFormatValid = false; // outdside of range -> break
191 if ( bAttrChanged ) // if value entered with numberformat?
192 StartFormatArea(); // then start again
195 return bFound;
198 void ScViewFunc::DoAutoAttributes( SCCOL nCol, SCROW nRow, SCTAB nTab,
199 bool bAttrChanged, bool bAddUndo )
201 ScDocShell* pDocSh = GetViewData()->GetDocShell();
202 ScDocument* pDoc = pDocSh->GetDocument();
203 if (bAddUndo && !pDoc->IsUndoEnabled())
204 bAddUndo = false;
206 const ScPatternAttr* pSource = pDoc->GetPattern(
207 aFormatSource.Col(), aFormatSource.Row(), nTab );
208 if ( !((const ScMergeAttr&)pSource->GetItem(ATTR_MERGE)).IsMerged() )
210 ScRange aRange( nCol, nRow, nTab, nCol, nRow, nTab );
211 ScMarkData aMark;
212 aMark.SetMarkArea( aRange );
214 ScDocFunc &rFunc = GetViewData()->GetDocFunc();
216 // pOldPattern is only valid until call to ApplyAttributes!
217 const ScPatternAttr* pOldPattern = pDoc->GetPattern( nCol, nRow, nTab );
218 const ScStyleSheet* pSrcStyle = pSource->GetStyleSheet();
219 if ( pSrcStyle && pSrcStyle != pOldPattern->GetStyleSheet() )
220 rFunc.ApplyStyle( aMark, pSrcStyle->GetName(), true, false );
222 rFunc.ApplyAttributes( aMark, *pSource, true, false );
225 if ( bAttrChanged ) // value entered with number format?
226 aFormatSource.Set( nCol, nRow, nTab ); // then set a new source
229 //------------------------------------------------------------------------------------
231 // additional routines
233 sal_uInt16 ScViewFunc::GetOptimalColWidth( SCCOL nCol, SCTAB nTab, bool bFormula )
235 ScDocShell* pDocSh = GetViewData()->GetDocShell();
236 ScDocument* pDoc = pDocSh->GetDocument();
237 ScMarkData& rMark = GetViewData()->GetMarkData();
239 double nPPTX = GetViewData()->GetPPTX();
240 double nPPTY = GetViewData()->GetPPTY();
241 Fraction aZoomX = GetViewData()->GetZoomX();
242 Fraction aZoomY = GetViewData()->GetZoomY();
244 ScSizeDeviceProvider aProv(pDocSh);
245 if (aProv.IsPrinter())
247 nPPTX = aProv.GetPPTX();
248 nPPTY = aProv.GetPPTY();
249 aZoomX = aZoomY = Fraction( 1, 1 );
252 sal_uInt16 nTwips = pDoc->GetOptimalColWidth( nCol, nTab, aProv.GetDevice(),
253 nPPTX, nPPTY, aZoomX, aZoomY, bFormula, &rMark );
254 return nTwips;
257 bool ScViewFunc::SelectionEditable( bool* pOnlyNotBecauseOfMatrix /* = NULL */ )
259 bool bRet;
260 ScDocument* pDoc = GetViewData()->GetDocument();
261 ScMarkData& rMark = GetViewData()->GetMarkData();
262 if (rMark.IsMarked() || rMark.IsMultiMarked())
263 bRet = pDoc->IsSelectionEditable( rMark, pOnlyNotBecauseOfMatrix );
264 else
266 SCCOL nCol = GetViewData()->GetCurX();
267 SCROW nRow = GetViewData()->GetCurY();
268 SCTAB nTab = GetViewData()->GetTabNo();
269 bRet = pDoc->IsBlockEditable( nTab, nCol, nRow, nCol, nRow,
270 pOnlyNotBecauseOfMatrix );
272 return bRet;
275 #ifndef LRU_MAX
276 #define LRU_MAX 10
277 #endif
279 static sal_Bool lcl_FunctionKnown( sal_uInt16 nOpCode )
281 const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList();
282 if ( pFuncList )
284 sal_uLong nCount = pFuncList->GetCount();
285 for (sal_uLong i=0; i<nCount; i++)
286 if ( pFuncList->GetFunction(i)->nFIndex == nOpCode )
287 return sal_True;
289 return false;
292 static sal_Bool lcl_AddFunction( ScAppOptions& rAppOpt, sal_uInt16 nOpCode )
294 sal_uInt16 nOldCount = rAppOpt.GetLRUFuncListCount();
295 sal_uInt16* pOldList = rAppOpt.GetLRUFuncList();
296 sal_uInt16 nPos;
297 for (nPos=0; nPos<nOldCount; nPos++)
298 if (pOldList[nPos] == nOpCode) // is the function already in the list?
300 if ( nPos == 0 )
301 return false; // already at the top -> no change
303 // count doesn't change, so the original array is modified
305 for (sal_uInt16 nCopy=nPos; nCopy>0; nCopy--)
306 pOldList[nCopy] = pOldList[nCopy-1];
307 pOldList[0] = nOpCode;
309 return sal_True; // list has changed
312 if ( !lcl_FunctionKnown( nOpCode ) )
313 return false; // not in function list -> no change
315 sal_uInt16 nNewCount = std::min( (sal_uInt16)(nOldCount + 1), (sal_uInt16)LRU_MAX );
316 sal_uInt16 nNewList[LRU_MAX];
317 nNewList[0] = nOpCode;
318 for (nPos=1; nPos<nNewCount; nPos++)
319 nNewList[nPos] = pOldList[nPos-1];
320 rAppOpt.SetLRUFuncList( nNewList, nNewCount );
322 return sal_True; // list has changed
325 namespace HelperNotifyChanges
327 void NotifyIfChangesListeners(ScDocShell &rDocShell, ScMarkData& rMark, SCCOL nCol, SCROW nRow,
328 const OUString &rType = OUString("cell-change"))
330 if (ScModelObj *pModelObj = getMustPropagateChangesModel(rDocShell))
332 ScRangeList aChangeRanges;
333 ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
334 for (; itr != itrEnd; ++itr)
335 aChangeRanges.Append( ScRange( nCol, nRow, *itr ) );
337 HelperNotifyChanges::Notify(*pModelObj, aChangeRanges, rType);
342 // actual functions
344 // input - undo OK
346 void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab,
347 const OUString& rString,
348 const EditTextObject* pData )
350 ScDocument* pDoc = GetViewData()->GetDocument();
351 ScMarkData& rMark = GetViewData()->GetMarkData();
352 bool bRecord = pDoc->IsUndoEnabled();
353 SCTAB i;
355 ScDocShell* pDocSh = GetViewData()->GetDocShell();
356 ScDocFunc &rFunc = GetViewData()->GetDocFunc();
357 ScDocShellModificator aModificator( *pDocSh );
359 ScEditableTester aTester( pDoc, nCol,nRow, nCol,nRow, rMark );
360 if (aTester.IsEditable())
362 if ( bRecord )
363 rFunc.EnterListAction( STR_UNDO_ENTERDATA );
365 bool bFormula = false;
367 // a single '=' character is handled as string (needed for special filters)
368 if ( rString.getLength() > 1 )
370 if ( rString[0] == '=' )
372 // handle as formula
373 bFormula = true;
375 else if ( rString[0] == '+' || rString[0] == '-' )
377 // if there is more than one leading '+' or '-' character, remove the additional ones
378 sal_Int32 nIndex = 1;
379 sal_Int32 nLen = rString.getLength();
380 while ( nIndex < nLen && ( rString[ nIndex ] == '+' || rString[ nIndex ] == '-' ) )
382 ++nIndex;
384 OUString aString = rString.replaceAt( 1, nIndex - 1, "" );
386 // if the remaining part without the leading '+' or '-' character
387 // is non-empty and not a number, handle as formula
388 if ( aString.getLength() > 1 )
390 sal_uInt32 nFormat = 0;
391 pDoc->GetNumberFormat( nCol, nRow, nTab, nFormat );
392 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
393 double fNumber = 0;
394 if ( !pFormatter->IsNumberFormat( aString, nFormat, fNumber ) )
396 bFormula = true;
402 bool bNumFmtChanged = false;
403 if ( bFormula )
404 { // formula, compile with autoCorrection
405 i = rMark.GetFirstSelected();
406 ScAddress aPos( nCol, nRow, i );
407 ScCompiler aComp( pDoc, aPos);
408 aComp.SetGrammar(pDoc->GetGrammar());
409 //2do: enable/disable autoCorrection via calcoptions
410 aComp.SetAutoCorrection( true );
411 if ( rString[0] == '+' || rString[0] == '-' )
413 aComp.SetExtendedErrorDetection( ScCompiler::EXTENDED_ERROR_DETECTION_NAME_BREAK );
415 OUString aFormula( rString );
416 ScTokenArray* pArr;
417 bool bAgain;
420 bAgain = false;
421 bool bAddEqual = false;
422 ScTokenArray* pArrFirst = pArr = aComp.CompileString( aFormula );
423 bool bCorrected = aComp.IsCorrected();
424 if ( bCorrected )
425 { // try to parse with first parser-correction
426 pArr = aComp.CompileString( aComp.GetCorrectedFormula() );
428 if ( !pArr->GetCodeError() )
430 bAddEqual = true;
431 aComp.CompileTokenArray();
432 bCorrected |= aComp.IsCorrected();
434 if ( bCorrected )
436 OUString aCorrectedFormula;
437 if ( bAddEqual )
439 aCorrectedFormula = "=" + aComp.GetCorrectedFormula();
441 else
442 aCorrectedFormula = aComp.GetCorrectedFormula();
443 short nResult;
444 if ( aCorrectedFormula.getLength() == 1 )
445 nResult = RET_NO; // empty formula, just '='
446 else
448 OUString aMessage( ScResId( SCSTR_FORMULA_AUTOCORRECTION ) );
449 aMessage += aCorrectedFormula;
450 nResult = QueryBox( GetViewData()->GetDialogParent(),
451 WinBits(WB_YES_NO | WB_DEF_YES),
452 aMessage ).Execute();
454 if ( nResult == RET_YES )
456 aFormula = aCorrectedFormula;
457 if ( pArr != pArrFirst )
458 delete pArrFirst;
459 bAgain = true;
461 else
463 if ( pArr != pArrFirst )
465 delete pArr;
466 pArr = pArrFirst;
470 } while ( bAgain );
471 // to be used in multiple tabs, the formula must be compiled anew
472 // via ScFormulaCell copy-ctor because of RangeNames,
473 // the same code-array for all cells is not possible.
474 // If the array has an error, (it) must be RPN-erased in the newly generated
475 // cellst and the error be set explicitly, so that
476 // via FormulaCell copy-ctor and Interpreter it will be, when possible,
477 // ironed out again, too intelligent.. e.g.: =1))
478 sal_uInt16 nError = pArr->GetCodeError();
479 if ( !nError )
481 // update list of recent functions with all functions that
482 // are not within parentheses
484 ScModule* pScMod = SC_MOD();
485 ScAppOptions aAppOpt = pScMod->GetAppOptions();
486 bool bOptChanged = false;
488 formula::FormulaToken** ppToken = pArr->GetArray();
489 sal_uInt16 nTokens = pArr->GetLen();
490 sal_uInt16 nLevel = 0;
491 for (sal_uInt16 nTP=0; nTP<nTokens; nTP++)
493 formula::FormulaToken* pTok = ppToken[nTP];
494 OpCode eOp = pTok->GetOpCode();
495 if ( eOp == ocOpen )
496 ++nLevel;
497 else if ( eOp == ocClose && nLevel )
498 --nLevel;
499 if ( nLevel == 0 && pTok->IsFunction() &&
500 lcl_AddFunction( aAppOpt, sal::static_int_cast<sal_uInt16>( eOp ) ) )
501 bOptChanged = true;
504 if ( bOptChanged )
506 pScMod->SetAppOptions(aAppOpt);
507 pScMod->RecentFunctionsChanged();
511 ScFormulaCell aCell(pDoc, aPos, *pArr, formula::FormulaGrammar::GRAM_DEFAULT, MM_NONE);
512 delete pArr;
514 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
515 ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
516 for (; itr != itrEnd; ++itr)
518 i = *itr;
519 aPos.SetTab( i );
520 sal_uLong nIndex = (sal_uLong) ((SfxUInt32Item*) pDoc->GetAttr(
521 nCol, nRow, i, ATTR_VALUE_FORMAT ))->GetValue();
522 if ( pFormatter->GetType( nIndex ) == NUMBERFORMAT_TEXT ||
523 ( ( rString[0] == '+' || rString[0] == '-' ) && nError && rString == aFormula ) )
525 if ( pData )
527 // A clone of pData will be stored in the cell.
528 rFunc.SetEditCell(aPos, *pData, true);
530 else
531 rFunc.SetStringCell(aPos, aFormula, true);
533 else
535 ScFormulaCell* pCell = new ScFormulaCell( aCell, *pDoc, aPos );
536 if ( nError )
538 pCell->GetCode()->DelRPN();
539 pCell->SetErrCode( nError );
540 if(pCell->GetCode()->IsHyperLink())
541 pCell->GetCode()->SetHyperLink(false);
543 rFunc.SetFormulaCell(aPos, pCell, true);
547 else
549 ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
550 for ( ; itr != itrEnd; ++itr )
552 bool bNumFmtSet = false;
553 rFunc.SetNormalString( bNumFmtSet, ScAddress( nCol, nRow, *itr ), rString, false );
554 if (bNumFmtSet)
556 /* FIXME: if set on any sheet results in changed only on
557 * sheet nTab for TestFormatArea() and DoAutoAttributes() */
558 bNumFmtChanged = true;
563 bool bAutoFormat = TestFormatArea(nCol, nRow, nTab, bNumFmtChanged);
565 if (bAutoFormat)
566 DoAutoAttributes(nCol, nRow, nTab, bNumFmtChanged, bRecord);
568 pDocSh->UpdateOle(GetViewData());
570 HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh, rMark, nCol, nRow);
572 if ( bRecord )
573 rFunc.EndListAction();
575 aModificator.SetDocumentModified();
576 lcl_PostRepaintCondFormat( pDoc->GetCondFormat( nCol, nRow, nTab ), pDocSh );
578 else
580 ErrorMessage(aTester.GetMessageId());
581 PaintArea( nCol, nRow, nCol, nRow ); // possibly the edit-engine is still painted there
585 // enter value in single cell (on nTab only)
587 void ScViewFunc::EnterValue( SCCOL nCol, SCROW nRow, SCTAB nTab, const double& rValue )
589 ScDocument* pDoc = GetViewData()->GetDocument();
590 ScDocShell* pDocSh = GetViewData()->GetDocShell();
592 if ( pDoc && pDocSh )
594 bool bUndo(pDoc->IsUndoEnabled());
595 ScDocShellModificator aModificator( *pDocSh );
597 ScEditableTester aTester( pDoc, nTab, nCol,nRow, nCol,nRow );
598 if (aTester.IsEditable())
600 ScAddress aPos( nCol, nRow, nTab );
601 ScCellValue aUndoCell;
602 if (bUndo)
603 aUndoCell.assign(*pDoc, aPos);
605 pDoc->SetValue( nCol, nRow, nTab, rValue );
607 // because of ChangeTrack after change in document
608 if (bUndo)
610 pDocSh->GetUndoManager()->AddUndoAction(
611 new ScUndoEnterValue(pDocSh, aPos, aUndoCell, rValue));
614 pDocSh->PostPaintCell( aPos );
615 pDocSh->UpdateOle(GetViewData());
616 aModificator.SetDocumentModified();
618 else
619 ErrorMessage(aTester.GetMessageId());
623 void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab,
624 const EditTextObject& rData, bool bTestSimple )
626 ScDocShell* pDocSh = GetViewData()->GetDocShell();
627 ScMarkData& rMark = GetViewData()->GetMarkData();
628 ScDocument* pDoc = pDocSh->GetDocument();
629 bool bRecord = pDoc->IsUndoEnabled();
631 ScDocShellModificator aModificator( *pDocSh );
633 ScEditableTester aTester( pDoc, nTab, nCol,nRow, nCol,nRow );
634 if (aTester.IsEditable())
637 // test for attribute
639 bool bSimple = false;
640 bool bCommon = false;
641 ScPatternAttr* pCellAttrs = NULL;
642 OUString aString;
644 const ScPatternAttr* pOldPattern = pDoc->GetPattern( nCol, nRow, nTab );
645 ScTabEditEngine aEngine( *pOldPattern, pDoc->GetEnginePool() );
646 aEngine.SetText(rData);
648 if (bTestSimple) // test, if simple string without attribute
650 ScEditAttrTester aAttrTester( &aEngine );
651 bSimple = !aAttrTester.NeedsObject();
652 bCommon = aAttrTester.NeedsCellAttr();
654 // formulas have to be recognized even if they're formatted
655 // (but commmon attributes are still collected)
657 if ( !bSimple && aEngine.GetParagraphCount() == 1 )
659 OUString aParStr(aEngine.GetText( 0 ));
660 if ( aParStr[0] == '=' )
661 bSimple = true;
664 if (bCommon) // attribute for tab
666 pCellAttrs = new ScPatternAttr( *pOldPattern );
667 pCellAttrs->GetFromEditItemSet( &aAttrTester.GetAttribs() );
668 //! remove common attributes from EditEngine?
672 // #i97726# always get text for "repeat" of undo action
673 aString = ScEditUtil::GetSpaceDelimitedString(aEngine);
676 // undo
679 EditTextObject* pUndoData = NULL;
680 ScUndoEnterData::ValuesType aOldValues;
682 if (bRecord && !bSimple)
684 ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
685 for (; itr != itrEnd; ++itr)
687 ScUndoEnterData::Value aOldValue;
688 aOldValue.mnTab = *itr;
689 aOldValue.maCell.assign(*pDoc, ScAddress(nCol, nRow, *itr));
690 aOldValues.push_back(aOldValue);
693 pUndoData = rData.Clone();
697 // enter data
700 if (bCommon)
701 pDoc->ApplyPattern(nCol,nRow,nTab,*pCellAttrs); //! undo
703 if (bSimple)
705 if (bCommon)
706 AdjustRowHeight(nRow,nRow);
708 EnterData(nCol,nRow,nTab,aString);
710 else
712 ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
713 for (; itr != itrEnd; ++itr)
715 ScAddress aPos(nCol, nRow, *itr);
716 pDoc->SetEditText(aPos, rData, pDoc->GetEditPool());
719 if ( bRecord )
720 { // because of ChangeTrack current first
721 pDocSh->GetUndoManager()->AddUndoAction(
722 new ScUndoEnterData(pDocSh, ScAddress(nCol,nRow,nTab), aOldValues, aString, pUndoData));
725 HideAllCursors();
727 AdjustRowHeight(nRow,nRow);
729 itr = rMark.begin();
730 for (; itr != itrEnd; ++itr)
731 pDocSh->PostPaintCell( nCol, nRow, *itr );
733 ShowAllCursors();
735 pDocSh->UpdateOle(GetViewData());
737 HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh, rMark, nCol, nRow);
739 aModificator.SetDocumentModified();
741 lcl_PostRepaintCondFormat( pDoc->GetCondFormat( nCol, nRow, nTab ), pDocSh );
743 delete pCellAttrs;
745 else
747 ErrorMessage(aTester.GetMessageId());
748 PaintArea( nCol, nRow, nCol, nRow ); // possibly the edit-engine is still painted there
752 void ScViewFunc::EnterDataAtCursor( const OUString& rString )
754 SCCOL nPosX = GetViewData()->GetCurX();
755 SCROW nPosY = GetViewData()->GetCurY();
756 SCTAB nTab = GetViewData()->GetTabNo();
758 EnterData( nPosX, nPosY, nTab, rString );
761 void ScViewFunc::EnterMatrix( const OUString& rString, ::formula::FormulaGrammar::Grammar eGram )
763 ScViewData* pData = GetViewData();
764 const ScMarkData& rMark = pData->GetMarkData();
765 if ( !rMark.IsMarked() && !rMark.IsMultiMarked() )
767 // nothing marked -> temporarily calculate block
768 // with size of result formula to get the size
770 ScDocument* pDoc = pData->GetDocument();
771 SCCOL nCol = pData->GetCurX();
772 SCROW nRow = pData->GetCurY();
773 SCTAB nTab = pData->GetTabNo();
774 ScFormulaCell aFormCell( pDoc, ScAddress(nCol,nRow,nTab), rString, eGram, MM_FORMULA );
776 SCSIZE nSizeX;
777 SCSIZE nSizeY;
778 aFormCell.GetResultDimensions( nSizeX, nSizeY );
779 if ( nSizeX != 0 && nSizeY != 0 &&
780 nCol+nSizeX-1 <= sal::static_int_cast<SCSIZE>(MAXCOL) &&
781 nRow+nSizeY-1 <= sal::static_int_cast<SCSIZE>(MAXROW) )
783 ScRange aResult( nCol, nRow, nTab,
784 sal::static_int_cast<SCCOL>(nCol+nSizeX-1),
785 sal::static_int_cast<SCROW>(nRow+nSizeY-1), nTab );
786 MarkRange( aResult, false );
790 ScRange aRange;
791 if (pData->GetSimpleArea(aRange) == SC_MARK_SIMPLE)
793 ScDocShell* pDocSh = pData->GetDocShell();
794 bool bSuccess = pDocSh->GetDocFunc().EnterMatrix(
795 aRange, &rMark, NULL, rString, false, false, EMPTY_OUSTRING, eGram );
796 if (bSuccess)
797 pDocSh->UpdateOle(GetViewData());
799 else
800 ErrorMessage(STR_NOMULTISELECT);
803 sal_uInt8 ScViewFunc::GetSelectionScriptType()
805 sal_uInt8 nScript = 0;
807 ScDocument* pDoc = GetViewData()->GetDocument();
808 const ScMarkData& rMark = GetViewData()->GetMarkData();
809 if ( !rMark.IsMarked() && !rMark.IsMultiMarked() )
811 // no selection -> cursor
813 nScript = pDoc->GetScriptType( GetViewData()->GetCurX(),
814 GetViewData()->GetCurY(), GetViewData()->GetTabNo());
816 else
818 ScRangeList aRanges;
819 rMark.FillRangeListWithMarks( &aRanges, false );
820 nScript = pDoc->GetRangeScriptType(aRanges);
823 if (nScript == 0)
824 nScript = ScGlobal::GetDefaultScriptType();
826 return nScript;
829 const ScPatternAttr* ScViewFunc::GetSelectionPattern()
831 // Don't use UnmarkFiltered in slot state functions, for performance reasons.
832 // The displayed state is always that of the whole selection including filtered rows.
834 const ScMarkData& rMark = GetViewData()->GetMarkData();
835 ScDocument* pDoc = GetViewData()->GetDocument();
836 if ( rMark.IsMarked() || rMark.IsMultiMarked() )
838 // MarkToMulti is no longer necessary for pDoc->GetSelectionPattern
839 const ScPatternAttr* pAttr = pDoc->GetSelectionPattern( rMark );
840 return pAttr;
842 else
844 SCCOL nCol = GetViewData()->GetCurX();
845 SCROW nRow = GetViewData()->GetCurY();
846 SCTAB nTab = GetViewData()->GetTabNo();
848 ScMarkData aTempMark( rMark ); // copy sheet selection
849 aTempMark.SetMarkArea( ScRange( nCol, nRow, nTab ) );
850 const ScPatternAttr* pAttr = pDoc->GetSelectionPattern( aTempMark );
851 return pAttr;
855 void ScViewFunc::GetSelectionFrame( SvxBoxItem& rLineOuter,
856 SvxBoxInfoItem& rLineInner )
858 ScDocument* pDoc = GetViewData()->GetDocument();
859 const ScMarkData& rMark = GetViewData()->GetMarkData();
861 if ( rMark.IsMarked() || rMark.IsMultiMarked() )
863 if ( rMark.IsMultiMarked() )
865 ScMarkData aNewMark( rMark ); // use local copy for MarkToSimple
866 aNewMark.MarkToSimple(); // simple block is needed for GetSelectionFrame
867 pDoc->GetSelectionFrame( aNewMark, rLineOuter, rLineInner );
869 else
870 pDoc->GetSelectionFrame( rMark, rLineOuter, rLineInner );
872 else
874 const ScPatternAttr* pAttrs =
875 pDoc->GetPattern( GetViewData()->GetCurX(),
876 GetViewData()->GetCurY(),
877 GetViewData()->GetTabNo() );
879 rLineOuter = (const SvxBoxItem&) (pAttrs->GetItem( ATTR_BORDER ));
880 rLineInner = (const SvxBoxInfoItem&)(pAttrs->GetItem( ATTR_BORDER_INNER ));
881 rLineInner.SetTable(false);
882 rLineInner.SetDist(true);
883 rLineInner.SetMinDist(false);
888 // apply attribute - undo OK
890 // complete set ( ATTR_STARTINDEX, ATTR_ENDINDEX )
893 void ScViewFunc::ApplyAttributes( const SfxItemSet* pDialogSet,
894 const SfxItemSet* pOldSet,
895 bool bRecord )
897 // not editable because of matrix only? attribute OK nonetheless
898 bool bOnlyNotBecauseOfMatrix;
899 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
901 ErrorMessage(STR_PROTECTIONERR);
902 return;
905 ScPatternAttr aOldAttrs( new SfxItemSet(*pOldSet) );
906 ScPatternAttr aNewAttrs( new SfxItemSet(*pDialogSet) );
907 aNewAttrs.DeleteUnchanged( &aOldAttrs );
909 if ( pDialogSet->GetItemState( ATTR_VALUE_FORMAT ) == SFX_ITEM_SET )
910 { // don't reset to default SYSTEM GENERAL if not intended
911 sal_uInt32 nOldFormat =
912 ((const SfxUInt32Item&)pOldSet->Get( ATTR_VALUE_FORMAT )).GetValue();
913 sal_uInt32 nNewFormat =
914 ((const SfxUInt32Item&)pDialogSet->Get( ATTR_VALUE_FORMAT )).GetValue();
915 if ( nNewFormat != nOldFormat )
917 SvNumberFormatter* pFormatter =
918 GetViewData()->GetDocument()->GetFormatTable();
919 const SvNumberformat* pOldEntry = pFormatter->GetEntry( nOldFormat );
920 LanguageType eOldLang =
921 pOldEntry ? pOldEntry->GetLanguage() : LANGUAGE_DONTKNOW;
922 const SvNumberformat* pNewEntry = pFormatter->GetEntry( nNewFormat );
923 LanguageType eNewLang =
924 pNewEntry ? pNewEntry->GetLanguage() : LANGUAGE_DONTKNOW;
925 if ( eNewLang != eOldLang )
927 aNewAttrs.GetItemSet().Put(
928 SvxLanguageItem( eNewLang, ATTR_LANGUAGE_FORMAT ) );
930 // only the language has changed -> do not touch numberformat-attribute
931 sal_uInt32 nNewMod = nNewFormat % SV_COUNTRY_LANGUAGE_OFFSET;
932 if ( nNewMod == ( nOldFormat % SV_COUNTRY_LANGUAGE_OFFSET ) &&
933 nNewMod <= SV_MAX_ANZ_STANDARD_FORMATE )
934 aNewAttrs.GetItemSet().ClearItem( ATTR_VALUE_FORMAT );
939 const SvxBoxItem* pOldOuter = (const SvxBoxItem*) &pOldSet->Get( ATTR_BORDER );
940 const SvxBoxItem* pNewOuter = (const SvxBoxItem*) &pDialogSet->Get( ATTR_BORDER );
941 const SvxBoxInfoItem* pOldInner = (const SvxBoxInfoItem*) &pOldSet->Get( ATTR_BORDER_INNER );
942 const SvxBoxInfoItem* pNewInner = (const SvxBoxInfoItem*) &pDialogSet->Get( ATTR_BORDER_INNER );
943 SfxItemSet& rNewSet = aNewAttrs.GetItemSet();
944 SfxItemPool* pNewPool = rNewSet.GetPool();
946 pNewPool->Put( *pNewOuter ); // don't delete yet
947 pNewPool->Put( *pNewInner );
948 rNewSet.ClearItem( ATTR_BORDER );
949 rNewSet.ClearItem( ATTR_BORDER_INNER );
952 * establish whether border attribute is to be set:
953 * 1. new != old
954 * 2. is one of the borders not-DontCare (since 238.f: IsxxValid())
958 bool bFrame = (pDialogSet->GetItemState( ATTR_BORDER ) != SFX_ITEM_DEFAULT)
959 || (pDialogSet->GetItemState( ATTR_BORDER_INNER ) != SFX_ITEM_DEFAULT);
961 if ( pNewOuter==pOldOuter && pNewInner==pOldInner )
962 bFrame = false;
964 // this should be intercepted by the pool: ?!??!??
966 if ( bFrame && pNewOuter && pNewInner )
967 if ( *pNewOuter == *pOldOuter && *pNewInner == *pOldInner )
968 bFrame = false;
970 if ( pNewInner )
972 bFrame = bFrame
973 && ( pNewInner->IsValid(VALID_LEFT)
974 || pNewInner->IsValid(VALID_RIGHT)
975 || pNewInner->IsValid(VALID_TOP)
976 || pNewInner->IsValid(VALID_BOTTOM)
977 || pNewInner->IsValid(VALID_HORI)
978 || pNewInner->IsValid(VALID_VERT) );
980 else
981 bFrame = false;
983 if (!bFrame)
984 ApplySelectionPattern( aNewAttrs, bRecord ); // standard only
985 else
987 // if new items are default-items, overwrite the old items:
989 bool bDefNewOuter = ( SFX_ITEMS_STATICDEFAULT == pNewOuter->GetKind() );
990 bool bDefNewInner = ( SFX_ITEMS_STATICDEFAULT == pNewInner->GetKind() );
992 ApplyPatternLines( aNewAttrs,
993 bDefNewOuter ? pOldOuter : pNewOuter,
994 bDefNewInner ? pOldInner : pNewInner,
995 bRecord );
998 pNewPool->Remove( *pNewOuter ); // release
999 pNewPool->Remove( *pNewInner );
1001 // adjust height
1002 AdjustBlockHeight();
1004 // CellContentChanged is called in ApplySelectionPattern / ApplyPatternLines
1007 void ScViewFunc::ApplyAttr( const SfxPoolItem& rAttrItem )
1009 // not editable because of matrix only? attribute OK nonetheless
1010 bool bOnlyNotBecauseOfMatrix;
1011 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
1013 ErrorMessage(STR_PROTECTIONERR);
1014 return;
1017 ScPatternAttr aNewAttrs( new SfxItemSet( *GetViewData()->GetDocument()->GetPool(),
1018 ATTR_PATTERN_START, ATTR_PATTERN_END ) );
1020 aNewAttrs.GetItemSet().Put( rAttrItem );
1021 // if justify is set (with Buttons), always indentation 0
1022 if ( rAttrItem.Which() == ATTR_HOR_JUSTIFY )
1023 aNewAttrs.GetItemSet().Put( SfxUInt16Item( ATTR_INDENT, 0 ) );
1024 ApplySelectionPattern( aNewAttrs );
1026 AdjustBlockHeight();
1028 // CellContentChanged is called in ApplySelectionPattern
1032 // patterns and borders
1034 void ScViewFunc::ApplyPatternLines( const ScPatternAttr& rAttr, const SvxBoxItem* pNewOuter,
1035 const SvxBoxInfoItem* pNewInner, bool bRecord )
1037 ScDocument* pDoc = GetViewData()->GetDocument();
1038 ScMarkData aFuncMark( GetViewData()->GetMarkData() ); // local copy for UnmarkFiltered
1039 ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
1040 if (bRecord && !pDoc->IsUndoEnabled())
1041 bRecord = false;
1043 ScRange aMarkRange;
1044 aFuncMark.MarkToSimple();
1045 bool bMulti = aFuncMark.IsMultiMarked();
1046 if (bMulti)
1047 aFuncMark.GetMultiMarkArea( aMarkRange );
1048 else if (aFuncMark.IsMarked())
1049 aFuncMark.GetMarkArea( aMarkRange );
1050 else
1052 aMarkRange = ScRange( GetViewData()->GetCurX(),
1053 GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
1054 DoneBlockMode();
1055 InitOwnBlockMode();
1056 aFuncMark.SetMarkArea(aMarkRange);
1057 MarkDataChanged();
1060 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1062 ScDocShellModificator aModificator( *pDocSh );
1064 if (bRecord)
1066 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1067 SCTAB nStartTab = aMarkRange.aStart.Tab();
1068 SCTAB nTabCount = pDoc->GetTableCount();
1069 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
1070 ScMarkData::iterator itr = aFuncMark.begin(), itrEnd = aFuncMark.end();
1071 for (; itr != itrEnd; ++itr)
1072 if (*itr != nStartTab)
1073 pUndoDoc->AddUndoTab( *itr, *itr );
1075 ScRange aCopyRange = aMarkRange;
1076 aCopyRange.aStart.SetTab(0);
1077 aCopyRange.aEnd.SetTab(nTabCount-1);
1078 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pUndoDoc, &aFuncMark );
1080 pDocSh->GetUndoManager()->AddUndoAction(
1081 new ScUndoSelectionAttr(
1082 pDocSh, aFuncMark,
1083 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), aMarkRange.aStart.Tab(),
1084 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), aMarkRange.aEnd.Tab(),
1085 pUndoDoc, bMulti, &rAttr, pNewOuter, pNewInner ) );
1088 sal_uInt16 nExt = SC_PF_TESTMERGE;
1089 pDocSh->UpdatePaintExt( nExt, aMarkRange ); // content before the change
1091 pDoc->ApplySelectionFrame( aFuncMark, pNewOuter, pNewInner );
1093 pDocSh->UpdatePaintExt( nExt, aMarkRange ); // content after the change
1095 aFuncMark.MarkToMulti();
1096 pDoc->ApplySelectionPattern( rAttr, aFuncMark );
1098 pDocSh->PostPaint( aMarkRange, PAINT_GRID, nExt );
1099 pDocSh->UpdateOle(GetViewData());
1100 aModificator.SetDocumentModified();
1101 CellContentChanged();
1103 StartFormatArea();
1106 // pattern only
1108 void ScViewFunc::ApplySelectionPattern( const ScPatternAttr& rAttr,
1109 bool bRecord, bool bCursorOnly )
1111 ScViewData* pViewData = GetViewData();
1112 ScDocShell* pDocSh = pViewData->GetDocShell();
1113 ScDocument* pDoc = pDocSh->GetDocument();
1114 ScMarkData aFuncMark( pViewData->GetMarkData() ); // local copy for UnmarkFiltered
1115 ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
1117 if (bRecord && !pDoc->IsUndoEnabled())
1118 bRecord = false;
1120 // State from old ItemSet doesn't matter for paint flags, as any change will be
1121 // from SFX_ITEM_SET in the new ItemSet (default is ignored in ApplyPattern).
1122 // New alignment is checked (check in PostPaint isn't enough) in case a right
1123 // alignment is changed to left.
1124 const SfxItemSet& rNewSet = rAttr.GetItemSet();
1125 bool bSetLines = rNewSet.GetItemState( ATTR_BORDER, true ) == SFX_ITEM_SET ||
1126 rNewSet.GetItemState( ATTR_SHADOW, true ) == SFX_ITEM_SET;
1127 bool bSetAlign = rNewSet.GetItemState( ATTR_HOR_JUSTIFY, true ) == SFX_ITEM_SET;
1129 sal_uInt16 nExtFlags = 0;
1130 if ( bSetLines )
1131 nExtFlags |= SC_PF_LINES;
1132 if ( bSetAlign )
1133 nExtFlags |= SC_PF_WHOLEROWS;
1135 ScDocShellModificator aModificator( *pDocSh );
1137 bool bMulti = aFuncMark.IsMultiMarked();
1138 aFuncMark.MarkToMulti();
1139 bool bOnlyTab = (!aFuncMark.IsMultiMarked() && !bCursorOnly && aFuncMark.GetSelectCount() > 1);
1140 if (bOnlyTab)
1142 SCCOL nCol = pViewData->GetCurX();
1143 SCROW nRow = pViewData->GetCurY();
1144 SCTAB nTab = pViewData->GetTabNo();
1145 aFuncMark.SetMarkArea(ScRange(nCol,nRow,nTab));
1146 aFuncMark.MarkToMulti();
1149 ScRangeList aChangeRanges;
1151 if (aFuncMark.IsMultiMarked() && !bCursorOnly)
1153 ScRange aMarkRange;
1154 aFuncMark.GetMultiMarkArea( aMarkRange );
1155 SCTAB nTabCount = pDoc->GetTableCount();
1156 ScMarkData::iterator itr = aFuncMark.begin(), itrEnd = aFuncMark.end();
1157 for (; itr != itrEnd; ++itr)
1159 ScRange aChangeRange( aMarkRange );
1160 aChangeRange.aStart.SetTab( *itr );
1161 aChangeRange.aEnd.SetTab( *itr );
1162 aChangeRanges.Append( aChangeRange );
1165 SCCOL nStartCol = aMarkRange.aStart.Col();
1166 SCROW nStartRow = aMarkRange.aStart.Row();
1167 SCTAB nStartTab = aMarkRange.aStart.Tab();
1168 SCCOL nEndCol = aMarkRange.aEnd.Col();
1169 SCROW nEndRow = aMarkRange.aEnd.Row();
1170 SCTAB nEndTab = aMarkRange.aEnd.Tab();
1172 ScUndoSelectionAttr* pUndoAttr = NULL;
1173 ScEditDataArray* pEditDataArray = NULL;
1174 if (bRecord)
1176 ScRange aCopyRange = aMarkRange;
1177 aCopyRange.aStart.SetTab(0);
1178 aCopyRange.aEnd.SetTab(nTabCount-1);
1180 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1181 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
1182 itr = aFuncMark.begin();
1183 for (; itr != itrEnd; ++itr)
1184 if (*itr != nStartTab)
1185 pUndoDoc->AddUndoTab( *itr, *itr );
1186 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pUndoDoc, &aFuncMark );
1188 aFuncMark.MarkToMulti();
1190 pUndoAttr = new ScUndoSelectionAttr(
1191 pDocSh, aFuncMark, nStartCol, nStartRow, nStartTab,
1192 nEndCol, nEndRow, nEndTab, pUndoDoc, bMulti, &rAttr );
1193 pDocSh->GetUndoManager()->AddUndoAction(pUndoAttr);
1194 pEditDataArray = pUndoAttr->GetDataArray();
1197 pDoc->ApplySelectionPattern( rAttr, aFuncMark, pEditDataArray );
1199 pDocSh->PostPaint( nStartCol, nStartRow, nStartTab,
1200 nEndCol, nEndRow, nEndTab,
1201 PAINT_GRID, nExtFlags | SC_PF_TESTMERGE );
1202 pDocSh->UpdateOle(GetViewData());
1203 aModificator.SetDocumentModified();
1204 CellContentChanged();
1206 else // single cell - simpler undo
1208 SCCOL nCol = pViewData->GetCurX();
1209 SCROW nRow = pViewData->GetCurY();
1210 SCTAB nTab = pViewData->GetTabNo();
1212 EditTextObject* pOldEditData = NULL;
1213 EditTextObject* pNewEditData = NULL;
1214 ScAddress aPos(nCol, nRow, nTab);
1215 if (pDoc->GetCellType(aPos) == CELLTYPE_EDIT)
1217 pOldEditData = pDoc->GetEditText(aPos)->Clone();
1218 pDoc->RemoveEditTextCharAttribs(aPos, rAttr);
1219 pNewEditData = pDoc->GetEditText(aPos)->Clone();
1222 aChangeRanges.Append(aPos);
1223 ScPatternAttr* pOldPat = new ScPatternAttr(*pDoc->GetPattern( nCol, nRow, nTab ));
1225 pDoc->ApplyPattern( nCol, nRow, nTab, rAttr );
1227 const ScPatternAttr* pNewPat = pDoc->GetPattern( nCol, nRow, nTab );
1229 if (bRecord)
1231 ScUndoCursorAttr* pUndo = new ScUndoCursorAttr(
1232 pDocSh, nCol, nRow, nTab, pOldPat, pNewPat, &rAttr, false );
1233 pUndo->SetEditData(pOldEditData, pNewEditData);
1234 pDocSh->GetUndoManager()->AddUndoAction(pUndo);
1236 delete pOldPat; // is copied in undo (Pool)
1238 pDocSh->PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PAINT_GRID, nExtFlags | SC_PF_TESTMERGE );
1239 pDocSh->UpdateOle(GetViewData());
1240 aModificator.SetDocumentModified();
1241 CellContentChanged();
1244 ScModelObj* pModelObj = HelperNotifyChanges::getMustPropagateChangesModel(*pDocSh);
1245 if (pModelObj)
1247 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aProperties;
1248 sal_Int32 nCount = 0;
1249 const SfxItemPropertyMap& rMap = ScCellObj::GetCellPropertyMap();
1250 PropertyEntryVector_t aPropVector = rMap.getPropertyEntries();
1251 for ( sal_uInt16 nWhich = ATTR_PATTERN_START; nWhich <= ATTR_PATTERN_END; ++nWhich )
1253 const SfxPoolItem* pItem = 0;
1254 if ( rNewSet.GetItemState( nWhich, true, &pItem ) == SFX_ITEM_SET && pItem )
1256 PropertyEntryVector_t::const_iterator aIt = aPropVector.begin();
1257 while ( aIt != aPropVector.end())
1259 if ( aIt->nWID == nWhich )
1261 ::com::sun::star::uno::Any aVal;
1262 pItem->QueryValue( aVal, aIt->nMemberId );
1263 aProperties.realloc( nCount + 1 );
1264 aProperties[ nCount ].Name = aIt->sName;
1265 aProperties[ nCount ].Value <<= aVal;
1266 ++nCount;
1268 ++aIt;
1272 HelperNotifyChanges::Notify(*pModelObj, aChangeRanges, "attribute", aProperties);
1275 StartFormatArea();
1278 void ScViewFunc::ApplyUserItemSet( const SfxItemSet& rItemSet )
1280 // ItemSet from UI, may have different pool
1282 bool bOnlyNotBecauseOfMatrix;
1283 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
1285 ErrorMessage(STR_PROTECTIONERR);
1286 return;
1289 ScPatternAttr aNewAttrs( GetViewData()->GetDocument()->GetPool() );
1290 SfxItemSet& rNewSet = aNewAttrs.GetItemSet();
1291 rNewSet.Put( rItemSet, false );
1292 ApplySelectionPattern( aNewAttrs );
1294 AdjustBlockHeight();
1297 const SfxStyleSheet* ScViewFunc::GetStyleSheetFromMarked()
1299 // Don't use UnmarkFiltered in slot state functions, for performance reasons.
1300 // The displayed state is always that of the whole selection including filtered rows.
1302 const ScStyleSheet* pSheet = NULL;
1303 ScViewData* pViewData = GetViewData();
1304 ScDocument* pDoc = pViewData->GetDocument();
1305 ScMarkData& rMark = pViewData->GetMarkData();
1307 if ( rMark.IsMarked() || rMark.IsMultiMarked() )
1308 pSheet = pDoc->GetSelectionStyle( rMark ); // MarkToMulti isn't necessary
1309 else
1310 pSheet = pDoc->GetStyle( pViewData->GetCurX(),
1311 pViewData->GetCurY(),
1312 pViewData->GetTabNo() );
1314 return pSheet;
1317 void ScViewFunc::SetStyleSheetToMarked( SfxStyleSheet* pStyleSheet, bool bRecord )
1319 // not editable because of matrix only? attribute OK nonetheless
1320 bool bOnlyNotBecauseOfMatrix;
1321 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
1323 ErrorMessage(STR_PROTECTIONERR);
1324 return;
1327 if ( !pStyleSheet) return;
1328 // -------------------------------------------------------------------
1330 ScViewData* pViewData = GetViewData();
1331 ScDocShell* pDocSh = pViewData->GetDocShell();
1332 ScDocument* pDoc = pDocSh->GetDocument();
1333 ScMarkData aFuncMark( pViewData->GetMarkData() ); // local copy for UnmarkFiltered
1334 ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
1335 SCTAB nTabCount = pDoc->GetTableCount();
1336 if (bRecord && !pDoc->IsUndoEnabled())
1337 bRecord = false;
1339 ScDocShellModificator aModificator( *pDocSh );
1341 if ( aFuncMark.IsMarked() || aFuncMark.IsMultiMarked() )
1343 ScRange aMarkRange;
1344 aFuncMark.MarkToMulti();
1345 aFuncMark.GetMultiMarkArea( aMarkRange );
1347 if ( bRecord )
1349 SCTAB nTab = pViewData->GetTabNo();
1350 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1351 pUndoDoc->InitUndo( pDoc, nTab, nTab );
1352 ScMarkData::iterator itr = aFuncMark.begin(), itrEnd = aFuncMark.end();
1353 for (; itr != itrEnd; ++itr)
1354 if (*itr != nTab)
1355 pUndoDoc->AddUndoTab( *itr, *itr );
1357 ScRange aCopyRange = aMarkRange;
1358 aCopyRange.aStart.SetTab(0);
1359 aCopyRange.aEnd.SetTab(nTabCount-1);
1360 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, true, pUndoDoc, &aFuncMark );
1361 aFuncMark.MarkToMulti();
1363 OUString aName = pStyleSheet->GetName();
1364 pDocSh->GetUndoManager()->AddUndoAction(
1365 new ScUndoSelectionStyle( pDocSh, aFuncMark, aMarkRange, aName, pUndoDoc ) );
1368 pDoc->ApplySelectionStyle( (ScStyleSheet&)*pStyleSheet, aFuncMark );
1370 if (!AdjustBlockHeight())
1371 pViewData->GetDocShell()->PostPaint( aMarkRange, PAINT_GRID );
1373 aFuncMark.MarkToSimple();
1375 else
1377 SCCOL nCol = pViewData->GetCurX();
1378 SCROW nRow = pViewData->GetCurY();
1379 SCTAB nTab = pViewData->GetTabNo();
1381 if ( bRecord )
1383 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1384 pUndoDoc->InitUndo( pDoc, nTab, nTab );
1385 ScMarkData::iterator itr = aFuncMark.begin(), itrEnd = aFuncMark.end();
1386 for (; itr != itrEnd; ++itr)
1387 if (*itr != nTab)
1388 pUndoDoc->AddUndoTab( *itr, *itr );
1390 ScRange aCopyRange( nCol, nRow, 0, nCol, nRow, nTabCount-1 );
1391 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, false, pUndoDoc );
1393 ScRange aMarkRange ( nCol, nRow, nTab );
1394 ScMarkData aUndoMark = aFuncMark;
1395 aUndoMark.SetMultiMarkArea( aMarkRange );
1397 OUString aName = pStyleSheet->GetName();
1398 pDocSh->GetUndoManager()->AddUndoAction(
1399 new ScUndoSelectionStyle( pDocSh, aUndoMark, aMarkRange, aName, pUndoDoc ) );
1402 ScMarkData::iterator itr = aFuncMark.begin(), itrEnd = aFuncMark.end();
1403 for (; itr != itrEnd; ++itr)
1404 pDoc->ApplyStyle( nCol, nRow, *itr, (ScStyleSheet&)*pStyleSheet );
1406 if (!AdjustBlockHeight())
1407 pViewData->GetDocShell()->PostPaintCell( nCol, nRow, nTab );
1411 aModificator.SetDocumentModified();
1413 StartFormatArea();
1417 void ScViewFunc::RemoveStyleSheetInUse( const SfxStyleSheetBase* pStyleSheet )
1419 if ( !pStyleSheet) return;
1420 // -------------------------------------------------------------------
1422 ScViewData* pViewData = GetViewData();
1423 ScDocument* pDoc = pViewData->GetDocument();
1424 ScDocShell* pDocSh = pViewData->GetDocShell();
1426 ScDocShellModificator aModificator( *pDocSh );
1428 VirtualDevice aVirtDev;
1429 aVirtDev.SetMapMode(MAP_PIXEL);
1430 pDoc->StyleSheetChanged( pStyleSheet, true, &aVirtDev,
1431 pViewData->GetPPTX(),
1432 pViewData->GetPPTY(),
1433 pViewData->GetZoomX(),
1434 pViewData->GetZoomY() );
1436 pDocSh->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID|PAINT_LEFT );
1437 aModificator.SetDocumentModified();
1439 ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
1440 if (pHdl)
1441 pHdl->ForgetLastPattern();
1444 void ScViewFunc::UpdateStyleSheetInUse( const SfxStyleSheetBase* pStyleSheet )
1446 if ( !pStyleSheet) return;
1447 // -------------------------------------------------------------------
1449 ScViewData* pViewData = GetViewData();
1450 ScDocument* pDoc = pViewData->GetDocument();
1451 ScDocShell* pDocSh = pViewData->GetDocShell();
1453 ScDocShellModificator aModificator( *pDocSh );
1455 VirtualDevice aVirtDev;
1456 aVirtDev.SetMapMode(MAP_PIXEL);
1457 pDoc->StyleSheetChanged( pStyleSheet, false, &aVirtDev,
1458 pViewData->GetPPTX(),
1459 pViewData->GetPPTY(),
1460 pViewData->GetZoomX(),
1461 pViewData->GetZoomY() );
1463 pDocSh->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID|PAINT_LEFT );
1464 aModificator.SetDocumentModified();
1466 ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
1467 if (pHdl)
1468 pHdl->ForgetLastPattern();
1471 // insert cells - undo OK
1473 bool ScViewFunc::InsertCells( InsCellCmd eCmd, bool bRecord, bool bPartOfPaste )
1475 ScRange aRange;
1476 if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE)
1478 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1479 const ScMarkData& rMark = GetViewData()->GetMarkData();
1480 bool bSuccess = pDocSh->GetDocFunc().InsertCells( aRange, &rMark, eCmd, bRecord, false, bPartOfPaste );
1481 if (bSuccess)
1483 pDocSh->UpdateOle(GetViewData());
1484 CellContentChanged();
1485 ResetAutoSpell();
1487 if ( eCmd == INS_INSROWS || eCmd == INS_INSCOLS )
1489 OUString aOperation = ( eCmd == INS_INSROWS) ?
1490 OUString("insert-rows"):
1491 OUString("insert-columns");
1492 HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh, aRange, aOperation);
1495 return bSuccess;
1497 else
1499 ErrorMessage(STR_NOMULTISELECT);
1500 return false;
1504 // delete cells - undo OK
1506 void ScViewFunc::DeleteCells( DelCellCmd eCmd, bool bRecord )
1508 ScRange aRange;
1509 if ( GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
1511 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1512 const ScMarkData& rMark = GetViewData()->GetMarkData();
1514 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
1515 // #i94841# [Collaboration] if deleting rows is rejected, the content is sometimes wrong
1516 if ( pDocSh->IsDocShared() && ( eCmd == DEL_DELROWS || eCmd == DEL_DELCOLS ) )
1518 ScRange aDelRange( aRange.aStart );
1519 SCCOLROW nCount = 0;
1520 if ( eCmd == DEL_DELROWS )
1522 nCount = sal::static_int_cast< SCCOLROW >( aRange.aEnd.Row() - aRange.aStart.Row() + 1 );
1524 else
1526 nCount = sal::static_int_cast< SCCOLROW >( aRange.aEnd.Col() - aRange.aStart.Col() + 1 );
1528 while ( nCount > 0 )
1530 pDocSh->GetDocFunc().DeleteCells( aDelRange, &rMark, eCmd, bRecord, false );
1531 --nCount;
1534 else
1535 #endif
1537 pDocSh->GetDocFunc().DeleteCells( aRange, &rMark, eCmd, bRecord, false );
1540 pDocSh->UpdateOle(GetViewData());
1541 CellContentChanged();
1542 ResetAutoSpell();
1544 if ( eCmd == DEL_DELROWS || eCmd == DEL_DELCOLS )
1546 OUString aOperation = ( eCmd == DEL_DELROWS) ?
1547 OUString("delete-rows"):
1548 OUString("delete-columns");
1549 HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh, aRange, aOperation);
1552 // put cursor directly behind deleted range
1553 SCCOL nCurX = GetViewData()->GetCurX();
1554 SCROW nCurY = GetViewData()->GetCurY();
1555 if ( eCmd==DEL_CELLSLEFT || eCmd==DEL_DELCOLS )
1556 nCurX = aRange.aStart.Col();
1557 else
1558 nCurY = aRange.aStart.Row();
1559 SetCursor( nCurX, nCurY );
1561 else
1563 if (eCmd == DEL_DELCOLS)
1564 DeleteMulti( false, bRecord );
1565 else if (eCmd == DEL_DELROWS)
1566 DeleteMulti( true, bRecord );
1567 else
1568 ErrorMessage(STR_NOMULTISELECT);
1571 Unmark();
1574 void ScViewFunc::DeleteMulti( bool bRows, bool bRecord )
1576 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1577 ScDocShellModificator aModificator( *pDocSh );
1578 SCTAB nTab = GetViewData()->GetTabNo();
1579 ScDocument* pDoc = pDocSh->GetDocument();
1580 ScMarkData aFuncMark( GetViewData()->GetMarkData() ); // local copy for UnmarkFiltered
1581 ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
1583 if (bRecord && !pDoc->IsUndoEnabled())
1584 bRecord = false;
1585 SCCOLROW* pRanges = new SCCOLROW[MAXCOLROWCOUNT];
1586 SCCOLROW nRangeCnt = bRows ? aFuncMark.GetMarkRowRanges( pRanges ) :
1587 aFuncMark.GetMarkColumnRanges( pRanges );
1588 if (nRangeCnt == 0)
1590 pRanges[0] = pRanges[1] = bRows ? static_cast<SCCOLROW>(GetViewData()->GetCurY()) : static_cast<SCCOLROW>(GetViewData()->GetCurX());
1591 nRangeCnt = 1;
1594 // test if allowed
1596 SCCOLROW* pOneRange = pRanges;
1597 sal_uInt16 nErrorId = 0;
1598 bool bNeedRefresh = false;
1599 SCCOLROW nRangeNo;
1600 for (nRangeNo=0; nRangeNo<nRangeCnt && !nErrorId; nRangeNo++)
1602 SCCOLROW nStart = *(pOneRange++);
1603 SCCOLROW nEnd = *(pOneRange++);
1605 SCCOL nStartCol, nEndCol;
1606 SCROW nStartRow, nEndRow;
1607 if ( bRows )
1609 nStartCol = 0;
1610 nEndCol = MAXCOL;
1611 nStartRow = static_cast<SCROW>(nStart);
1612 nEndRow = static_cast<SCROW>(nEnd);
1614 else
1616 nStartCol = static_cast<SCCOL>(nStart);
1617 nEndCol = static_cast<SCCOL>(nEnd);
1618 nStartRow = 0;
1619 nEndRow = MAXROW;
1622 // cell protection (only needed for first range, as all following cells are moved)
1623 if ( nRangeNo == 0 )
1625 // test to the end of the sheet
1626 ScEditableTester aTester( pDoc, nTab, nStartCol, nStartRow, MAXCOL, MAXROW );
1627 if (!aTester.IsEditable())
1628 nErrorId = aTester.GetMessageId();
1631 // merged cells
1632 SCCOL nMergeStartX = nStartCol;
1633 SCROW nMergeStartY = nStartRow;
1634 SCCOL nMergeEndX = nEndCol;
1635 SCROW nMergeEndY = nEndRow;
1636 pDoc->ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, nTab );
1637 pDoc->ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, nTab );
1639 if ( nMergeStartX != nStartCol || nMergeStartY != nStartRow )
1641 // Disallow deleting parts of a merged cell.
1642 // Deleting the start is allowed (merge is removed), so the end doesn't have to be checked.
1644 nErrorId = STR_MSSG_DELETECELLS_0;
1646 if ( nMergeEndX != nEndCol || nMergeEndY != nEndRow )
1648 // detect if the start of a merged cell is deleted, so the merge flags can be refreshed
1650 bNeedRefresh = true;
1654 if ( nErrorId )
1656 ErrorMessage( nErrorId );
1657 delete[] pRanges;
1658 return;
1661 // proceed
1663 WaitObject aWait( GetFrameWin() ); // important for TrackFormulas in UpdateReference
1665 ScDocument* pUndoDoc = NULL;
1666 ScRefUndoData* pUndoData = NULL;
1667 if (bRecord)
1669 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1670 pUndoDoc->InitUndo( pDoc, nTab, nTab, !bRows, bRows ); // row height
1672 pOneRange = pRanges;
1673 for (nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
1675 SCCOLROW nStart = *(pOneRange++);
1676 SCCOLROW nEnd = *(pOneRange++);
1677 if (bRows)
1678 pDoc->CopyToDocument( 0,nStart,nTab, MAXCOL,nEnd,nTab, IDF_ALL,false,pUndoDoc );
1679 else
1680 pDoc->CopyToDocument( static_cast<SCCOL>(nStart),0,nTab,
1681 static_cast<SCCOL>(nEnd),MAXROW,nTab,
1682 IDF_ALL,false,pUndoDoc );
1685 // all Formulas because of references
1686 SCTAB nTabCount = pDoc->GetTableCount();
1687 pUndoDoc->AddUndoTab( 0, nTabCount-1, false, false );
1688 pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,MAXTAB, IDF_FORMULA,false,pUndoDoc );
1690 pUndoData = new ScRefUndoData( pDoc );
1692 pDoc->BeginDrawUndo();
1695 pOneRange = &pRanges[2*nRangeCnt]; // backwards
1696 for (nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
1698 SCCOLROW nEnd = *(--pOneRange);
1699 SCCOLROW nStart = *(--pOneRange);
1701 if (bRows)
1702 pDoc->DeleteRow( 0,nTab, MAXCOL,nTab, nStart, static_cast<SCSIZE>(nEnd-nStart+1) );
1703 else
1704 pDoc->DeleteCol( 0,nTab, MAXROW,nTab, static_cast<SCCOL>(nStart), static_cast<SCSIZE>(nEnd-nStart+1) );
1707 if (bNeedRefresh)
1709 SCCOLROW nFirstStart = pRanges[0];
1710 SCCOL nStartCol = bRows ? 0 : static_cast<SCCOL>(nFirstStart);
1711 SCROW nStartRow = bRows ? static_cast<SCROW>(nFirstStart) : 0;
1712 SCCOL nEndCol = MAXCOL;
1713 SCROW nEndRow = MAXROW;
1715 pDoc->RemoveFlagsTab( nStartCol, nStartRow, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
1716 pDoc->ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow, nTab, true );
1719 if (bRecord)
1721 pDocSh->GetUndoManager()->AddUndoAction(
1722 new ScUndoDeleteMulti( pDocSh, bRows, bNeedRefresh, nTab, pRanges, nRangeCnt,
1723 pUndoDoc, pUndoData ) );
1726 if (!AdjustRowHeight(0, MAXROW))
1728 if (bRows)
1729 pDocSh->PostPaint( 0,pRanges[0],nTab, MAXCOL,MAXROW,nTab, PAINT_GRID | PAINT_LEFT );
1730 else
1731 pDocSh->PostPaint( static_cast<SCCOL>(pRanges[0]),0,nTab,
1732 MAXCOL,MAXROW,nTab, PAINT_GRID | PAINT_TOP );
1735 ResetAutoSpell();
1736 aModificator.SetDocumentModified();
1738 CellContentChanged();
1740 // put cursor directly behind the first deleted range
1741 SCCOL nCurX = GetViewData()->GetCurX();
1742 SCROW nCurY = GetViewData()->GetCurY();
1743 if ( bRows )
1744 nCurY = pRanges[0];
1745 else
1746 nCurX = static_cast<SCCOL>(pRanges[0]);
1747 SetCursor( nCurX, nCurY );
1749 delete[] pRanges;
1751 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
1754 // delete contents
1756 void ScViewFunc::DeleteContents( sal_uInt16 nFlags, bool bRecord )
1758 ScViewData* pViewData = GetViewData();
1759 pViewData->SetPasteMode( SC_PASTE_NONE );
1760 pViewData->GetViewShell()->UpdateCopySourceOverlay();
1762 // not editable because of matrix only? attribute OK nonetheless
1763 bool bOnlyNotBecauseOfMatrix;
1764 bool bEditable = SelectionEditable( &bOnlyNotBecauseOfMatrix );
1765 if ( !bEditable )
1767 if ( !(bOnlyNotBecauseOfMatrix &&
1768 ((nFlags & (IDF_ATTRIB | IDF_EDITATTR)) == nFlags)) )
1770 ErrorMessage(bOnlyNotBecauseOfMatrix ? STR_MATRIXFRAGMENTERR : STR_PROTECTIONERR);
1771 return;
1775 ScRange aMarkRange;
1776 bool bSimple = false;
1778 ScDocument* pDoc = GetViewData()->GetDocument();
1779 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1780 ScMarkData aFuncMark( GetViewData()->GetMarkData() ); // local copy for UnmarkFiltered
1781 ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
1783 if (bRecord && !pDoc->IsUndoEnabled())
1784 bRecord = false;
1786 ScDocShellModificator aModificator( *pDocSh );
1788 if ( !aFuncMark.IsMarked() && !aFuncMark.IsMultiMarked() )
1790 aMarkRange.aStart.SetCol(GetViewData()->GetCurX());
1791 aMarkRange.aStart.SetRow(GetViewData()->GetCurY());
1792 aMarkRange.aStart.SetTab(GetViewData()->GetTabNo());
1793 aMarkRange.aEnd = aMarkRange.aStart;
1794 if ( pDoc->HasAttrib( aMarkRange, HASATTR_MERGED ) )
1796 aFuncMark.SetMarkArea( aMarkRange );
1798 else
1799 bSimple = true;
1802 aFuncMark.SetMarking(false); // for MarkToMulti
1803 aFuncMark.MarkToSimple(); // before bMulti test below
1805 OSL_ENSURE( aFuncMark.IsMarked() || aFuncMark.IsMultiMarked() || bSimple, "delete what?" );
1807 ScDocument* pUndoDoc = NULL;
1808 bool bMulti = !bSimple && aFuncMark.IsMultiMarked();
1809 if (!bSimple)
1811 aFuncMark.MarkToMulti();
1812 aFuncMark.GetMultiMarkArea( aMarkRange );
1814 ScRange aExtendedRange(aMarkRange);
1815 if (!bSimple)
1817 if ( pDoc->ExtendMerge( aExtendedRange, true ) )
1818 bMulti = false;
1821 // no objects on protected tabs
1822 bool bObjects = false;
1823 if ( nFlags & IDF_OBJECTS )
1825 bObjects = true;
1826 ScMarkData::iterator itr = aFuncMark.begin(), itrEnd = aFuncMark.end();
1827 for (; itr != itrEnd; ++itr)
1828 if (pDoc->IsTabProtected(*itr))
1829 bObjects = false;
1832 sal_uInt16 nExtFlags = 0; // extra flags are needed only if attributes are deleted
1833 if ( nFlags & IDF_ATTRIB )
1834 pDocSh->UpdatePaintExt( nExtFlags, aMarkRange );
1836 // order op opeeration:
1837 // 1) BeginDrawUndo
1838 // 2) delete objects (DrawUndo is filled)
1839 // 3) copy contents for undo
1840 // 4) delete contents
1841 // 5) add undo-action
1843 bool bDrawUndo = bObjects || ( nFlags & IDF_NOTE ); // needed for shown notes
1844 if ( bDrawUndo && bRecord )
1845 pDoc->BeginDrawUndo();
1847 if (bObjects)
1849 if (bMulti)
1850 pDoc->DeleteObjectsInSelection( aFuncMark );
1851 else
1852 pDoc->DeleteObjectsInArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
1853 /*!*/ aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(),
1854 aFuncMark );
1857 if ( bRecord )
1859 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1860 SCTAB nTab = aMarkRange.aStart.Tab();
1861 pUndoDoc->InitUndo( pDoc, nTab, nTab );
1862 SCTAB nTabCount = pDoc->GetTableCount();
1863 ScMarkData::iterator itr = aFuncMark.begin(), itrEnd = aFuncMark.end();
1864 for (; itr != itrEnd; ++itr)
1865 if (*itr != nTab)
1866 pUndoDoc->AddUndoTab( *itr, *itr );
1867 ScRange aCopyRange = aExtendedRange;
1868 aCopyRange.aStart.SetTab(0);
1869 aCopyRange.aEnd.SetTab(nTabCount-1);
1871 // in case of "Format/Standard" copy all attributes, because CopyToDocument
1872 // with IDF_HARDATTR only is too time-consuming:
1873 sal_uInt16 nUndoDocFlags = nFlags;
1874 if (nFlags & IDF_ATTRIB)
1875 nUndoDocFlags |= IDF_ATTRIB;
1876 if (nFlags & IDF_EDITATTR) // Edit-Engine-Attribute
1877 nUndoDocFlags |= IDF_STRING; // -> cells will be changed
1878 if (nFlags & IDF_NOTE)
1879 nUndoDocFlags |= IDF_CONTENTS; // copy all cells with their notes
1880 // do not copy note captions to undo document
1881 nUndoDocFlags |= IDF_NOCAPTIONS;
1882 pDoc->CopyToDocument( aCopyRange, nUndoDocFlags, bMulti, pUndoDoc, &aFuncMark );
1885 HideAllCursors(); // for if summary is cancelled
1886 if (bSimple)
1887 pDoc->DeleteArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
1888 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(),
1889 aFuncMark, nFlags );
1890 else
1892 pDoc->DeleteSelection( nFlags, aFuncMark );
1895 if ( bRecord )
1897 pDocSh->GetUndoManager()->AddUndoAction(
1898 new ScUndoDeleteContents( pDocSh, aFuncMark, aExtendedRange,
1899 pUndoDoc, bMulti, nFlags, bDrawUndo ) );
1902 if (!AdjustRowHeight( aExtendedRange.aStart.Row(), aExtendedRange.aEnd.Row() ))
1903 pDocSh->PostPaint( aExtendedRange, PAINT_GRID, nExtFlags );
1905 pDocSh->UpdateOle(GetViewData());
1907 if (ScModelObj *pModelObj = HelperNotifyChanges::getMustPropagateChangesModel(*pDocSh))
1909 ScRangeList aChangeRanges;
1910 if ( bSimple )
1912 aChangeRanges.Append( aMarkRange );
1914 else
1916 aFuncMark.FillRangeListWithMarks( &aChangeRanges, false );
1918 HelperNotifyChanges::Notify(*pModelObj, aChangeRanges);
1921 aModificator.SetDocumentModified();
1922 CellContentChanged();
1923 ShowAllCursors();
1925 if ( nFlags & IDF_ATTRIB )
1927 if ( nFlags & IDF_CONTENTS )
1928 ForgetFormatArea();
1929 else
1930 StartFormatArea(); // delete attribute is also attribute-change
1934 // column width/row height (via header) - undo OK
1936 void ScViewFunc::SetWidthOrHeight( bool bWidth, SCCOLROW nRangeCnt, SCCOLROW* pRanges,
1937 ScSizeMode eMode, sal_uInt16 nSizeTwips,
1938 bool bRecord, bool bPaint, ScMarkData* pMarkData )
1940 if (nRangeCnt == 0)
1941 return;
1943 // use view's mark if none specified
1944 if ( !pMarkData )
1945 pMarkData = &GetViewData()->GetMarkData();
1947 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1948 ScDocument* pDoc = pDocSh->GetDocument();
1949 SCTAB nFirstTab = pMarkData->GetFirstSelected();
1950 SCTAB nCurTab = GetViewData()->GetTabNo();
1951 SCTAB nTab;
1952 if (bRecord && !pDoc->IsUndoEnabled())
1953 bRecord = false;
1955 ScDocShellModificator aModificator( *pDocSh );
1957 bool bAllowed = true;
1958 ScMarkData::iterator itr = pMarkData->begin(), itrEnd = pMarkData->end();
1959 for (; itr != itrEnd && bAllowed; ++itr)
1960 for ( SCCOLROW i=0; i<nRangeCnt && bAllowed; i++ )
1962 bool bOnlyMatrix;
1963 if (bWidth)
1964 bAllowed = pDoc->IsBlockEditable( *itr,
1965 static_cast<SCCOL>(pRanges[2*i]),0,
1966 static_cast<SCCOL>(pRanges[2*i+1]),MAXROW,
1967 &bOnlyMatrix ) || bOnlyMatrix;
1968 else
1969 bAllowed = pDoc->IsBlockEditable( *itr, 0,pRanges[2*i],
1970 MAXCOL,pRanges[2*i+1], &bOnlyMatrix ) ||
1971 bOnlyMatrix;
1974 // Allow users to resize cols/rows in readonly docs despite the r/o state.
1975 // It is frustrating to be unable to see content in mis-sized cells.
1976 if( !bAllowed && !pDocSh->IsReadOnly() )
1978 ErrorMessage(STR_PROTECTIONERR);
1979 return;
1982 SCCOLROW nStart = pRanges[0];
1983 SCCOLROW nEnd = pRanges[2*nRangeCnt-1];
1985 bool bFormula = false;
1986 if ( eMode == SC_SIZE_OPTIMAL )
1988 const ScViewOptions& rOpts = GetViewData()->GetOptions();
1989 bFormula = rOpts.GetOption( VOPT_FORMULAS );
1992 ScDocument* pUndoDoc = NULL;
1993 ScOutlineTable* pUndoTab = NULL;
1994 SCCOLROW* pUndoRanges = NULL;
1996 if ( bRecord )
1998 pDoc->BeginDrawUndo(); // Drawing Updates
2000 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2001 itr = pMarkData->begin();
2002 for (; itr != itrEnd; ++itr)
2004 if (bWidth)
2006 if ( *itr == nFirstTab )
2007 pUndoDoc->InitUndo( pDoc, *itr, *itr, true, false );
2008 else
2009 pUndoDoc->AddUndoTab( *itr, *itr, true, false );
2010 pDoc->CopyToDocument( static_cast<SCCOL>(nStart), 0, *itr,
2011 static_cast<SCCOL>(nEnd), MAXROW, *itr, IDF_NONE,
2012 false, pUndoDoc );
2014 else
2016 if ( *itr == nFirstTab )
2017 pUndoDoc->InitUndo( pDoc, *itr, *itr, false, true );
2018 else
2019 pUndoDoc->AddUndoTab( *itr, *itr, false, true );
2020 pDoc->CopyToDocument( 0, nStart, *itr, MAXCOL, nEnd, *itr, IDF_NONE, false, pUndoDoc );
2024 pUndoRanges = new SCCOLROW[ 2*nRangeCnt ];
2025 memcpy( pUndoRanges, pRanges, 2*nRangeCnt*sizeof(SCCOLROW) );
2027 //! outlines from all tab?
2028 ScOutlineTable* pTable = pDoc->GetOutlineTable( nCurTab );
2029 if (pTable)
2030 pUndoTab = new ScOutlineTable( *pTable );
2033 if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
2034 pMarkData->MarkToMulti();
2036 bool bShow = nSizeTwips > 0 || eMode != SC_SIZE_DIRECT;
2037 bool bOutline = false;
2039 itr = pMarkData->begin();
2040 for (; itr != itrEnd; ++itr)
2042 nTab = *itr;
2043 const SCCOLROW* pTabRanges = pRanges;
2045 for (SCCOLROW nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
2047 SCCOLROW nStartNo = *(pTabRanges++);
2048 SCCOLROW nEndNo = *(pTabRanges++);
2050 if ( !bWidth ) // height always blockwise
2052 if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
2054 bool bAll = ( eMode==SC_SIZE_OPTIMAL );
2055 if (!bAll)
2057 // delete CR_MANUALSIZE for all in range,
2058 // then SetOptimalHeight with bShrink = FALSE
2059 for (SCROW nRow = nStartNo; nRow <= nEndNo; ++nRow)
2061 SCROW nLastRow = nRow;
2062 if (pDoc->RowHidden(nRow, nTab, NULL, &nLastRow))
2064 nRow = nLastRow;
2065 continue;
2068 sal_uInt8 nOld = pDoc->GetRowFlags(nRow, nTab);
2069 if (nOld & CR_MANUALSIZE)
2070 pDoc->SetRowFlags(nRow, nTab, nOld & ~CR_MANUALSIZE);
2074 double nPPTX = GetViewData()->GetPPTX();
2075 double nPPTY = GetViewData()->GetPPTY();
2076 Fraction aZoomX = GetViewData()->GetZoomX();
2077 Fraction aZoomY = GetViewData()->GetZoomY();
2079 ScSizeDeviceProvider aProv(pDocSh);
2080 if (aProv.IsPrinter())
2082 nPPTX = aProv.GetPPTX();
2083 nPPTY = aProv.GetPPTY();
2084 aZoomX = aZoomY = Fraction( 1, 1 );
2087 pDoc->SetOptimalHeight( nStartNo, nEndNo, nTab, nSizeTwips, aProv.GetDevice(),
2088 nPPTX, nPPTY, aZoomX, aZoomY, bAll );
2089 if (bAll)
2090 pDoc->ShowRows( nStartNo, nEndNo, nTab, true );
2092 // Manual-Flag already (re)set in SetOptimalHeight in case of bAll=sal_True
2093 // (set for Extra-Height, else reset).
2095 else if ( eMode==SC_SIZE_DIRECT )
2097 if (nSizeTwips)
2099 pDoc->SetRowHeightRange( nStartNo, nEndNo, nTab, nSizeTwips );
2100 pDoc->SetManualHeight( nStartNo, nEndNo, nTab, true ); // height was set manually
2102 pDoc->ShowRows( nStartNo, nEndNo, nTab, nSizeTwips != 0 );
2104 else if ( eMode==SC_SIZE_SHOW )
2106 pDoc->ShowRows( nStartNo, nEndNo, nTab, true );
2109 else // column width
2111 for (SCCOL nCol=static_cast<SCCOL>(nStartNo); nCol<=static_cast<SCCOL>(nEndNo); nCol++)
2113 if ( eMode != SC_SIZE_VISOPT || !pDoc->ColHidden(nCol, nTab) )
2115 sal_uInt16 nThisSize = nSizeTwips;
2117 if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
2118 nThisSize = nSizeTwips + GetOptimalColWidth( nCol, nTab, bFormula );
2119 if ( nThisSize )
2120 pDoc->SetColWidth( nCol, nTab, nThisSize );
2122 pDoc->ShowCol( nCol, nTab, bShow );
2127 // adjust outline
2129 if (bWidth)
2131 if ( pDoc->UpdateOutlineCol( static_cast<SCCOL>(nStartNo),
2132 static_cast<SCCOL>(nEndNo), nTab, bShow ) )
2133 bOutline = true;
2135 else
2137 if ( pDoc->UpdateOutlineRow( nStartNo, nEndNo, nTab, bShow ) )
2138 bOutline = true;
2141 pDoc->SetDrawPageSize(nTab);
2145 if (!bOutline)
2146 DELETEZ(pUndoTab);
2148 if (bRecord)
2150 pDocSh->GetUndoManager()->AddUndoAction(
2151 new ScUndoWidthOrHeight( pDocSh, *pMarkData,
2152 nStart, nCurTab, nEnd, nCurTab,
2153 pUndoDoc, nRangeCnt, pUndoRanges,
2154 pUndoTab, eMode, nSizeTwips, bWidth ) );
2157 // fdo#36247 Ensure that the drawing layer's map mode scaling factors match
2158 // the new heights and widths.
2159 GetViewData()->GetView()->RefreshZoom();
2161 itr = pMarkData->begin();
2162 for (; itr != itrEnd; ++itr)
2163 pDoc->UpdatePageBreaks( *itr );
2165 GetViewData()->GetView()->UpdateScrollBars();
2167 if (bPaint)
2169 itr = pMarkData->begin();
2170 for (; itr != itrEnd; ++itr)
2172 nTab = *itr;
2173 if (bWidth)
2175 if (pDoc->HasAttrib( static_cast<SCCOL>(nStart),0,nTab,
2176 static_cast<SCCOL>(nEnd),MAXROW,nTab,
2177 HASATTR_MERGED | HASATTR_OVERLAPPED ))
2178 nStart = 0;
2179 if (nStart > 0) // go upwards because of Lines and cursor
2180 --nStart;
2181 pDocSh->PostPaint( static_cast<SCCOL>(nStart), 0, nTab,
2182 MAXCOL, MAXROW, nTab, PAINT_GRID | PAINT_TOP );
2184 else
2186 if (pDoc->HasAttrib( 0,nStart,nTab, MAXCOL,nEnd,nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ))
2187 nStart = 0;
2188 if (nStart != 0)
2189 --nStart;
2190 pDocSh->PostPaint( 0, nStart, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID | PAINT_LEFT );
2194 pDocSh->UpdateOle(GetViewData());
2195 if( !pDocSh->IsReadOnly() )
2196 aModificator.SetDocumentModified();
2199 if ( bWidth )
2201 if (ScModelObj* pModelObj = HelperNotifyChanges::getMustPropagateChangesModel(*pDocSh))
2203 ScRangeList aChangeRanges;
2204 itr = pMarkData->begin();
2205 for (; itr != itrEnd; ++itr)
2207 nTab = *itr;
2208 const SCCOLROW* pTabRanges = pRanges;
2209 for ( SCCOLROW nRange = 0; nRange < nRangeCnt; ++nRange )
2211 SCCOL nStartCol = static_cast< SCCOL >( *(pTabRanges++) );
2212 SCCOL nEndCol = static_cast< SCCOL >( *(pTabRanges++) );
2213 for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol )
2215 aChangeRanges.Append( ScRange( nCol, 0, nTab ) );
2219 HelperNotifyChanges::Notify(*pModelObj, aChangeRanges, "column-resize");
2224 // column width/row height (via marked range)
2226 void ScViewFunc::SetMarkedWidthOrHeight( bool bWidth, ScSizeMode eMode, sal_uInt16 nSizeTwips,
2227 bool bRecord, bool bPaint )
2229 ScMarkData& rMark = GetViewData()->GetMarkData();
2231 rMark.MarkToMulti();
2232 if (!rMark.IsMultiMarked())
2234 SCCOL nCol = GetViewData()->GetCurX();
2235 SCROW nRow = GetViewData()->GetCurY();
2236 SCTAB nTab = GetViewData()->GetTabNo();
2237 DoneBlockMode();
2238 InitOwnBlockMode();
2239 rMark.SetMultiMarkArea( ScRange( nCol,nRow,nTab ), true );
2240 MarkDataChanged();
2243 SCCOLROW* pRanges = new SCCOLROW[MAXCOLROWCOUNT];
2244 SCCOLROW nRangeCnt = 0;
2246 if ( bWidth )
2247 nRangeCnt = rMark.GetMarkColumnRanges( pRanges );
2248 else
2249 nRangeCnt = rMark.GetMarkRowRanges( pRanges );
2251 SetWidthOrHeight( bWidth, nRangeCnt, pRanges, eMode, nSizeTwips, bRecord, bPaint );
2253 delete[] pRanges;
2254 rMark.MarkToSimple();
2257 void ScViewFunc::ModifyCellSize( ScDirection eDir, bool bOptimal )
2259 //! step size adjustable
2260 // step size is also minumum
2261 sal_uInt16 nStepX = STD_COL_WIDTH / 5;
2262 sal_uInt16 nStepY = ScGlobal::nStdRowHeight;
2264 ScModule* pScMod = SC_MOD();
2265 bool bAnyEdit = pScMod->IsInputMode();
2266 SCCOL nCol = GetViewData()->GetCurX();
2267 SCROW nRow = GetViewData()->GetCurY();
2268 SCTAB nTab = GetViewData()->GetTabNo();
2269 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2270 ScDocument* pDoc = pDocSh->GetDocument();
2272 bool bAllowed, bOnlyMatrix;
2273 if ( eDir == DIR_LEFT || eDir == DIR_RIGHT )
2274 bAllowed = pDoc->IsBlockEditable( nTab, nCol,0, nCol,MAXROW, &bOnlyMatrix );
2275 else
2276 bAllowed = pDoc->IsBlockEditable( nTab, 0,nRow, MAXCOL,nRow, &bOnlyMatrix );
2277 if ( !bAllowed && !bOnlyMatrix )
2279 ErrorMessage(STR_PROTECTIONERR);
2280 return;
2283 HideAllCursors();
2285 sal_uInt16 nWidth = pDoc->GetColWidth( nCol, nTab );
2286 sal_uInt16 nHeight = pDoc->GetRowHeight( nRow, nTab );
2287 SCCOLROW nRange[2];
2288 if ( eDir == DIR_LEFT || eDir == DIR_RIGHT )
2290 if (bOptimal) // width of this single cell
2292 if ( bAnyEdit )
2294 // when editing the actual entered width
2295 ScInputHandler* pHdl = pScMod->GetInputHdl( GetViewData()->GetViewShell() );
2296 if (pHdl)
2298 long nEdit = pHdl->GetTextSize().Width(); // in 0.01 mm
2300 const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
2301 const SvxMarginItem& rMItem =
2302 (const SvxMarginItem&)pPattern->GetItem(ATTR_MARGIN);
2303 sal_uInt16 nMargin = rMItem.GetLeftMargin() + rMItem.GetRightMargin();
2304 if ( ((const SvxHorJustifyItem&) pPattern->
2305 GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_LEFT )
2306 nMargin = sal::static_int_cast<sal_uInt16>(
2307 nMargin + ((const SfxUInt16Item&)pPattern->GetItem(ATTR_INDENT)).GetValue() );
2309 nWidth = (sal_uInt16)(nEdit * pDocSh->GetOutputFactor() / HMM_PER_TWIPS)
2310 + nMargin + STD_EXTRA_WIDTH;
2313 else
2315 double nPPTX = GetViewData()->GetPPTX();
2316 double nPPTY = GetViewData()->GetPPTY();
2317 Fraction aZoomX = GetViewData()->GetZoomX();
2318 Fraction aZoomY = GetViewData()->GetZoomY();
2320 ScSizeDeviceProvider aProv(pDocSh);
2321 if (aProv.IsPrinter())
2323 nPPTX = aProv.GetPPTX();
2324 nPPTY = aProv.GetPPTY();
2325 aZoomX = aZoomY = Fraction( 1, 1 );
2328 long nPixel = pDoc->GetNeededSize( nCol, nRow, nTab, aProv.GetDevice(),
2329 nPPTX, nPPTY, aZoomX, aZoomY, true );
2330 sal_uInt16 nTwips = (sal_uInt16)( nPixel / nPPTX );
2331 if (nTwips != 0)
2332 nWidth = nTwips + STD_EXTRA_WIDTH;
2333 else
2334 nWidth = STD_COL_WIDTH;
2337 else // increment / decrement
2339 if ( eDir == DIR_RIGHT )
2340 nWidth = sal::static_int_cast<sal_uInt16>( nWidth + nStepX );
2341 else if ( nWidth > nStepX )
2342 nWidth = sal::static_int_cast<sal_uInt16>( nWidth - nStepX );
2343 if ( nWidth < nStepX ) nWidth = nStepX;
2344 if ( nWidth > MAX_COL_WIDTH ) nWidth = MAX_COL_WIDTH;
2346 nRange[0] = nRange[1] = nCol;
2347 SetWidthOrHeight( true, 1, nRange, SC_SIZE_DIRECT, nWidth );
2349 // adjust height of this row if width demands/allows this
2351 if (!bAnyEdit)
2353 const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
2354 bool bNeedHeight =
2355 ((const SfxBoolItem&)pPattern->GetItem( ATTR_LINEBREAK )).GetValue() ||
2356 ((const SvxHorJustifyItem&)pPattern->
2357 GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_BLOCK;
2358 if (bNeedHeight)
2359 AdjustRowHeight( nRow, nRow );
2362 else
2364 ScSizeMode eMode;
2365 if (bOptimal)
2367 eMode = SC_SIZE_OPTIMAL;
2368 nHeight = 0;
2370 else
2372 eMode = SC_SIZE_DIRECT;
2373 if ( eDir == DIR_BOTTOM )
2374 nHeight = sal::static_int_cast<sal_uInt16>( nHeight + nStepY );
2375 else if ( nHeight > nStepY )
2376 nHeight = sal::static_int_cast<sal_uInt16>( nHeight - nStepY );
2377 if ( nHeight < nStepY ) nHeight = nStepY;
2378 if ( nHeight > MAX_ROW_HEIGHT ) nHeight = MAX_ROW_HEIGHT;
2380 nRange[0] = nRange[1] = nRow;
2381 SetWidthOrHeight( false, 1, nRange, eMode, nHeight );
2384 if ( bAnyEdit )
2386 UpdateEditView();
2387 if ( pDoc->HasAttrib( nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_NEEDHEIGHT ) )
2389 ScInputHandler* pHdl = pScMod->GetInputHdl( GetViewData()->GetViewShell() );
2390 if (pHdl)
2391 pHdl->SetModified(); // so that the height is adjusted with Enter
2395 ShowAllCursors();
2398 void ScViewFunc::ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect )
2400 if (nTab == TABLEID_DOC)
2401 return;
2403 ScMarkData& rMark = GetViewData()->GetMarkData();
2404 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2405 ScDocument* pDoc = pDocSh->GetDocument();
2406 ScDocFunc &rFunc = pDocSh->GetDocFunc();
2407 bool bUndo(pDoc->IsUndoEnabled());
2409 // modifying several tabs is handled here
2411 if (bUndo)
2413 OUString aUndo = ScGlobal::GetRscString( STR_UNDO_PROTECT_TAB );
2414 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
2417 ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
2418 for (; itr != itrEnd; ++itr)
2419 rFunc.ProtectSheet(*itr, rProtect);
2421 if (bUndo)
2422 pDocSh->GetUndoManager()->LeaveListAction();
2424 UpdateLayerLocks(); //! broadcast to all views
2427 void ScViewFunc::Protect( SCTAB nTab, const OUString& rPassword )
2429 ScMarkData& rMark = GetViewData()->GetMarkData();
2430 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2431 ScDocument* pDoc = pDocSh->GetDocument();
2432 ScDocFunc &rFunc = pDocSh->GetDocFunc();
2433 bool bUndo(pDoc->IsUndoEnabled());
2435 if ( nTab == TABLEID_DOC || rMark.GetSelectCount() <= 1 )
2436 rFunc.Protect( nTab, rPassword, false );
2437 else
2439 // modifying several tabs is handled here
2441 if (bUndo)
2443 OUString aUndo = ScGlobal::GetRscString( STR_UNDO_PROTECT_TAB );
2444 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
2447 ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
2448 for (; itr != itrEnd; ++itr)
2449 rFunc.Protect( *itr, rPassword, false );
2451 if (bUndo)
2452 pDocSh->GetUndoManager()->LeaveListAction();
2455 UpdateLayerLocks(); //! broadcast to all views
2458 bool ScViewFunc::Unprotect( SCTAB nTab, const OUString& rPassword )
2460 ScMarkData& rMark = GetViewData()->GetMarkData();
2461 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2462 ScDocument* pDoc = pDocSh->GetDocument();
2463 ScDocFunc &rFunc = pDocSh->GetDocFunc();
2464 bool bChanged = false;
2465 bool bUndo (pDoc->IsUndoEnabled());
2467 if ( nTab == TABLEID_DOC || rMark.GetSelectCount() <= 1 )
2468 bChanged = rFunc.Unprotect( nTab, rPassword, false );
2469 else
2471 // modifying several tabs is handled here
2473 if (bUndo)
2475 OUString aUndo = ScGlobal::GetRscString( STR_UNDO_UNPROTECT_TAB );
2476 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
2479 ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
2480 for (; itr != itrEnd; ++itr)
2481 if ( rFunc.Unprotect( *itr, rPassword, false ) )
2482 bChanged = true;
2484 if (bUndo)
2485 pDocSh->GetUndoManager()->LeaveListAction();
2488 if (bChanged)
2489 UpdateLayerLocks(); //! broadcast to all views
2491 return bChanged;
2494 void ScViewFunc::SetNoteText( const ScAddress& rPos, const OUString& rNoteText )
2496 GetViewData()->GetDocShell()->GetDocFunc().SetNoteText( rPos, rNoteText, false );
2499 void ScViewFunc::ReplaceNote( const ScAddress& rPos, const OUString& rNoteText, const OUString* pAuthor, const OUString* pDate )
2501 GetViewData()->GetDocShell()->GetDocFunc().ReplaceNote( rPos, rNoteText, pAuthor, pDate, false );
2504 void ScViewFunc::SetNumberFormat( short nFormatType, sal_uLong nAdd )
2506 // not editable because of matrix only? attribute OK nonetheless
2507 bool bOnlyNotBecauseOfMatrix;
2508 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
2510 ErrorMessage(STR_PROTECTIONERR);
2511 return;
2514 sal_uInt32 nNumberFormat = 0;
2515 ScViewData* pViewData = GetViewData();
2516 ScDocument* pDoc = pViewData->GetDocument();
2517 SvNumberFormatter* pNumberFormatter = pDoc->GetFormatTable();
2518 LanguageType eLanguage = ScGlobal::eLnge;
2519 ScPatternAttr aNewAttrs( pDoc->GetPool() );
2521 // always take language from cursor position, even if there is a selection
2523 sal_uInt32 nCurrentNumberFormat;
2524 pDoc->GetNumberFormat( pViewData->GetCurX(),
2525 pViewData->GetCurY(),
2526 pViewData->GetTabNo(),
2527 nCurrentNumberFormat );
2528 const SvNumberformat* pEntry = pNumberFormatter->GetEntry( nCurrentNumberFormat );
2529 if (pEntry)
2530 eLanguage = pEntry->GetLanguage(); // else keep ScGlobal::eLnge
2532 nNumberFormat = pNumberFormatter->GetStandardFormat( nFormatType, eLanguage ) + nAdd;
2534 SfxItemSet& rSet = aNewAttrs.GetItemSet();
2535 rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNumberFormat ) );
2536 // ATTR_LANGUAGE_FORMAT not
2537 ApplySelectionPattern( aNewAttrs, true );
2540 void ScViewFunc::SetNumFmtByStr( const OUString& rCode )
2542 // not editable because of matrix only? attribute OK nonetheless
2543 bool bOnlyNotBecauseOfMatrix;
2544 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
2546 ErrorMessage(STR_PROTECTIONERR);
2547 return;
2550 ScViewData* pViewData = GetViewData();
2551 ScDocument* pDoc = pViewData->GetDocument();
2552 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
2554 // language always from cursor position
2556 sal_uInt32 nCurrentNumberFormat;
2557 pDoc->GetNumberFormat( pViewData->GetCurX(), pViewData->GetCurY(),
2558 pViewData->GetTabNo(), nCurrentNumberFormat );
2559 const SvNumberformat* pEntry = pFormatter->GetEntry( nCurrentNumberFormat );
2560 LanguageType eLanguage = pEntry ? pEntry->GetLanguage() : ScGlobal::eLnge;
2562 // determine index for String
2564 bool bOk = true;
2565 sal_uInt32 nNumberFormat = pFormatter->GetEntryKey( rCode, eLanguage );
2566 if ( nNumberFormat == NUMBERFORMAT_ENTRY_NOT_FOUND )
2568 // enter new
2570 OUString aFormat = rCode; // will be changed
2571 sal_Int32 nErrPos = 0;
2572 short nType = 0; //! ???
2573 bOk = pFormatter->PutEntry( aFormat, nErrPos, nType, nNumberFormat, eLanguage );
2576 if ( bOk ) // valid format?
2578 ScPatternAttr aNewAttrs( pDoc->GetPool() );
2579 SfxItemSet& rSet = aNewAttrs.GetItemSet();
2580 rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNumberFormat ) );
2581 rSet.Put( SvxLanguageItem( eLanguage, ATTR_LANGUAGE_FORMAT ) );
2582 ApplySelectionPattern( aNewAttrs, true );
2585 //! else return error / issue warning ???
2588 void ScViewFunc::ChangeNumFmtDecimals( bool bIncrement )
2590 // not editable because of matrix only? attribute OK nonetheless
2591 bool bOnlyNotBecauseOfMatrix;
2592 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
2594 ErrorMessage(STR_PROTECTIONERR);
2595 return;
2598 ScDocument* pDoc = GetViewData()->GetDocument();
2599 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
2601 SCCOL nCol = GetViewData()->GetCurX();
2602 SCROW nRow = GetViewData()->GetCurY();
2603 SCTAB nTab = GetViewData()->GetTabNo();
2605 sal_uInt32 nOldFormat;
2606 pDoc->GetNumberFormat( nCol, nRow, nTab, nOldFormat );
2607 const SvNumberformat* pOldEntry = pFormatter->GetEntry( nOldFormat );
2608 if (!pOldEntry)
2610 OSL_FAIL("numberformat not found !!!");
2611 return;
2614 // what have we got here?
2616 sal_uInt32 nNewFormat = nOldFormat;
2617 bool bError = false;
2619 LanguageType eLanguage = pOldEntry->GetLanguage();
2620 bool bThousand, bNegRed;
2621 sal_uInt16 nPrecision, nLeading;
2622 pOldEntry->GetFormatSpecialInfo( bThousand, bNegRed, nPrecision, nLeading );
2624 short nOldType = pOldEntry->GetType();
2625 if ( 0 == ( nOldType & (
2626 NUMBERFORMAT_NUMBER | NUMBERFORMAT_CURRENCY | NUMBERFORMAT_PERCENT ) ) )
2628 // date, time, fraction, logical, text can not be changed
2629 //! in case of scientific the Numberformatter also can't
2630 bError = true;
2633 //! SvNumberformat has a Member bStandard, but doesn't disclose it
2634 bool bWasStandard = ( nOldFormat == pFormatter->GetStandardIndex( eLanguage ) );
2635 if (bWasStandard)
2637 // with "Standard" the decimal places depend on cell content
2638 // 0 if empty or text -> no decimal places
2639 double nVal = pDoc->GetValue( ScAddress( nCol, nRow, nTab ) );
2641 // the ways of the Numberformatters are unfathomable, so try:
2642 OUString aOut;
2643 Color* pCol;
2644 ((SvNumberformat*)pOldEntry)->GetOutputString( nVal, aOut, &pCol );
2646 nPrecision = 0;
2647 // 'E' for exponential is fixed in Numberformatter
2648 if ( aOut.indexOf((sal_Unicode)'E') >= 0 )
2649 bError = true; // exponential not changed
2650 else
2652 OUString aDecSep( pFormatter->GetFormatDecimalSep( nOldFormat ) );
2653 sal_Int32 nPos = aOut.indexOf( aDecSep );
2654 if ( nPos >= 0 )
2655 nPrecision = aOut.getLength() - nPos - aDecSep.getLength();
2656 // else keep 0
2660 if (!bError)
2662 if (bIncrement)
2664 if (nPrecision<20)
2665 ++nPrecision; // increment
2666 else
2667 bError = true; // 20 is maximum
2669 else
2671 if (nPrecision)
2672 --nPrecision; // decrement
2673 else
2674 bError = true; // 0 is minumum
2678 if (!bError)
2680 OUString aNewPicture = pFormatter->GenerateFormat(nOldFormat, eLanguage,
2681 bThousand, bNegRed,
2682 nPrecision, nLeading);
2684 nNewFormat = pFormatter->GetEntryKey( aNewPicture, eLanguage );
2685 if ( nNewFormat == NUMBERFORMAT_ENTRY_NOT_FOUND )
2687 sal_Int32 nErrPos = 0;
2688 short nNewType = 0;
2689 bool bOk = pFormatter->PutEntry( aNewPicture, nErrPos,
2690 nNewType, nNewFormat, eLanguage );
2691 OSL_ENSURE( bOk, "incorrect numberformat generated" );
2692 if (!bOk)
2693 bError = true;
2697 if (!bError)
2699 ScPatternAttr aNewAttrs( pDoc->GetPool() );
2700 SfxItemSet& rSet = aNewAttrs.GetItemSet();
2701 rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat ) );
2702 // ATTR_LANGUAGE_FORMAT not
2703 ApplySelectionPattern( aNewAttrs, true );
2707 void ScViewFunc::ChangeIndent( bool bIncrement )
2709 ScViewData* pViewData = GetViewData();
2710 ScDocShell* pDocSh = pViewData->GetDocShell();
2711 ScMarkData& rMark = pViewData->GetMarkData();
2713 ScMarkData aWorkMark = rMark;
2714 ScViewUtil::UnmarkFiltered( aWorkMark, pDocSh->GetDocument() );
2715 aWorkMark.MarkToMulti();
2716 if (!aWorkMark.IsMultiMarked())
2718 SCCOL nCol = pViewData->GetCurX();
2719 SCROW nRow = pViewData->GetCurY();
2720 SCTAB nTab = pViewData->GetTabNo();
2721 aWorkMark.SetMultiMarkArea( ScRange(nCol,nRow,nTab) );
2724 bool bSuccess = pDocSh->GetDocFunc().ChangeIndent( aWorkMark, bIncrement, false );
2725 if (bSuccess)
2727 pDocSh->UpdateOle(pViewData);
2728 StartFormatArea();
2730 // stuff for sidebar panels
2731 SfxBindings& rBindings = GetViewData()->GetBindings();
2732 rBindings.Invalidate( SID_H_ALIGNCELL );
2733 rBindings.Invalidate( SID_ATTR_ALIGN_INDENT );
2737 bool ScViewFunc::InsertName( const OUString& rName, const OUString& rSymbol,
2738 const OUString& rType )
2740 // Type = P,R,C,F (and combinations)
2741 //! undo...
2743 bool bOk = false;
2744 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2745 ScDocument* pDoc = pDocSh->GetDocument();
2746 SCTAB nTab = GetViewData()->GetTabNo();
2747 ScRangeName* pList = pDoc->GetRangeName();
2749 RangeType nType = RT_NAME;
2750 ScRangeData* pNewEntry = new ScRangeData( pDoc, rName, rSymbol,
2751 ScAddress( GetViewData()->GetCurX(), GetViewData()->GetCurY(),
2752 nTab), nType );
2753 OUString aUpType = rType.toAsciiUpperCase();
2754 if ( aUpType.indexOf( 'P' ) != -1 )
2755 nType |= RT_PRINTAREA;
2756 if ( aUpType.indexOf( 'R' ) != -1 )
2757 nType |= RT_ROWHEADER;
2758 if ( aUpType.indexOf( 'C' ) != -1 )
2759 nType |= RT_COLHEADER;
2760 if ( aUpType.indexOf( 'F' ) != -1 )
2761 nType |= RT_CRITERIA;
2762 pNewEntry->AddType(nType);
2764 if ( !pNewEntry->GetErrCode() ) // text valid?
2766 ScDocShellModificator aModificator( *pDocSh );
2768 pDoc->CompileNameFormula( true ); // CreateFormulaString
2770 // input available yet? Then remove beforehand (=change)
2771 ScRangeData* pData = pList->findByUpperName(ScGlobal::pCharClass->uppercase(rName));
2772 if (pData)
2773 { // take old Index
2774 pNewEntry->SetIndex(pData->GetIndex());
2775 pList->erase(*pData);
2778 if ( pList->insert( pNewEntry ) )
2779 bOk = true;
2780 pNewEntry = NULL; // never delete, insert took ownership
2782 pDoc->CompileNameFormula( false ); // CompileFormulaString
2783 aModificator.SetDocumentModified();
2784 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
2787 delete pNewEntry; // if it wasn't inserted
2788 return bOk;
2791 void ScViewFunc::CreateNames( sal_uInt16 nFlags )
2793 bool bDone = false;
2794 ScRange aRange;
2795 if ( GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE )
2796 bDone = GetViewData()->GetDocShell()->GetDocFunc().CreateNames( aRange, nFlags, false );
2798 if (!bDone)
2799 ErrorMessage(STR_CREATENAME_MARKERR);
2802 sal_uInt16 ScViewFunc::GetCreateNameFlags()
2804 sal_uInt16 nFlags = 0;
2806 SCCOL nStartCol, nEndCol;
2807 SCROW nStartRow, nEndRow;
2808 SCTAB nDummy;
2809 if (GetViewData()->GetSimpleArea(nStartCol,nStartRow,nDummy,nEndCol,nEndRow,nDummy) == SC_MARK_SIMPLE)
2811 ScDocument* pDoc = GetViewData()->GetDocument();
2812 SCTAB nTab = GetViewData()->GetTabNo();
2813 bool bOk;
2814 SCCOL i;
2815 SCROW j;
2817 bOk = true;
2818 SCCOL nFirstCol = nStartCol;
2819 SCCOL nLastCol = nEndCol;
2820 if (nStartCol+1 < nEndCol) { ++nFirstCol; --nLastCol; }
2821 for (i=nFirstCol; i<=nLastCol && bOk; i++)
2822 if (!pDoc->HasStringData( i,nStartRow,nTab ))
2823 bOk = false;
2824 if (bOk)
2825 nFlags |= NAME_TOP;
2826 else // Bottom only if not Top
2828 bOk = true;
2829 for (i=nFirstCol; i<=nLastCol && bOk; i++)
2830 if (!pDoc->HasStringData( i,nEndRow,nTab ))
2831 bOk = false;
2832 if (bOk)
2833 nFlags |= NAME_BOTTOM;
2836 bOk = true;
2837 SCROW nFirstRow = nStartRow;
2838 SCROW nLastRow = nEndRow;
2839 if (nStartRow+1 < nEndRow) { ++nFirstRow; --nLastRow; }
2840 for (j=nFirstRow; j<=nLastRow && bOk; j++)
2841 if (!pDoc->HasStringData( nStartCol,j,nTab ))
2842 bOk = false;
2843 if (bOk)
2844 nFlags |= NAME_LEFT;
2845 else // Right only if not Left
2847 bOk = true;
2848 for (j=nFirstRow; j<=nLastRow && bOk; j++)
2849 if (!pDoc->HasStringData( nEndCol,j,nTab ))
2850 bOk = false;
2851 if (bOk)
2852 nFlags |= NAME_RIGHT;
2856 if (nStartCol == nEndCol)
2857 nFlags &= ~( NAME_LEFT | NAME_RIGHT );
2858 if (nStartRow == nEndRow)
2859 nFlags &= ~( NAME_TOP | NAME_BOTTOM );
2861 return nFlags;
2864 void ScViewFunc::InsertNameList()
2866 ScAddress aPos( GetViewData()->GetCurX(), GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
2867 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2868 if ( pDocSh->GetDocFunc().InsertNameList( aPos, false ) )
2869 pDocSh->UpdateOle(GetViewData());
2872 void ScViewFunc::UpdateSelectionArea( const ScMarkData& rSel, ScPatternAttr* pAttr )
2874 ScDocShell* pDocShell = GetViewData()->GetDocShell();
2875 ScRange aMarkRange;
2876 if (rSel.IsMultiMarked() )
2877 rSel.GetMultiMarkArea( aMarkRange );
2878 else
2879 rSel.GetMarkArea( aMarkRange );
2881 bool bSetLines = false;
2882 bool bSetAlign = false;
2883 if ( pAttr )
2885 const SfxItemSet& rNewSet = pAttr->GetItemSet();
2886 bSetLines = rNewSet.GetItemState( ATTR_BORDER, true ) == SFX_ITEM_SET ||
2887 rNewSet.GetItemState( ATTR_SHADOW, true ) == SFX_ITEM_SET;
2888 bSetAlign = rNewSet.GetItemState( ATTR_HOR_JUSTIFY, true ) == SFX_ITEM_SET;
2891 sal_uInt16 nExtFlags = 0;
2892 if ( bSetLines )
2893 nExtFlags |= SC_PF_LINES;
2894 if ( bSetAlign )
2895 nExtFlags |= SC_PF_WHOLEROWS;
2897 SCCOL nStartCol = aMarkRange.aStart.Col();
2898 SCROW nStartRow = aMarkRange.aStart.Row();
2899 SCTAB nStartTab = aMarkRange.aStart.Tab();
2900 SCCOL nEndCol = aMarkRange.aEnd.Col();
2901 SCROW nEndRow = aMarkRange.aEnd.Row();
2902 SCTAB nEndTab = aMarkRange.aEnd.Tab();
2903 pDocShell->PostPaint( nStartCol, nStartRow, nStartTab,
2904 nEndCol, nEndRow, nEndTab,
2905 PAINT_GRID, nExtFlags | SC_PF_TESTMERGE );
2906 ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell();
2907 pTabViewShell->CellContentChanged();
2908 pTabViewShell->AdjustBlockHeight(true, const_cast<ScMarkData*>(&rSel));
2913 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */