fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / ui / view / viewfunc.cxx
blob1bb22683d8c4bc1ca236e8b695ebd2672a44c8f4
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"
78 #include <rowheightcontext.hxx>
79 #include <docfuncutil.hxx>
81 #include <boost/scoped_ptr.hpp>
83 static void lcl_PostRepaintCondFormat( const ScConditionalFormat *pCondFmt, ScDocShell *pDocSh )
85 if( pCondFmt )
87 const ScRangeList& rRanges = pCondFmt->GetRange();
89 pDocSh->PostPaint( rRanges, PAINT_ALL );
93 ScViewFunc::ScViewFunc( vcl::Window* pParent, ScDocShell& rDocSh, ScTabViewShell* pViewShell ) :
94 ScTabView( pParent, rDocSh, pViewShell ),
95 bFormatValid( false )
99 ScViewFunc::~ScViewFunc()
103 void ScViewFunc::StartFormatArea()
105 // anything to do?
106 if ( !SC_MOD()->GetInputOptions().GetExtendFormat() )
107 return;
109 // start only with single cell (marked or cursor position)
110 ScRange aMarkRange;
111 bool bOk = (GetViewData().GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE);
112 if ( bOk && aMarkRange.aStart != aMarkRange.aEnd )
113 bOk = false;
115 if (bOk)
117 bFormatValid = true;
118 aFormatSource = aMarkRange.aStart;
119 aFormatArea = ScRange( aFormatSource );
121 else
122 bFormatValid = false; // discard old range
125 bool ScViewFunc::TestFormatArea( SCCOL nCol, SCROW nRow, SCTAB nTab, bool bAttrChanged )
127 // anything to do?
128 if ( !SC_MOD()->GetInputOptions().GetExtendFormat() )
129 return false;
131 // Test: treat input with numberformat (bAttrChanged) always as new Attribute
132 // (discard old Area ). If not wanted, discard if-statement
133 if ( bAttrChanged )
135 StartFormatArea();
136 return false;
139 //! Test if cell empty ???
141 bool bFound = false;
142 ScRange aNewRange = aFormatArea;
143 if ( bFormatValid && nTab == aFormatSource.Tab() )
145 if ( nRow >= aFormatArea.aStart.Row() && nRow <= aFormatArea.aEnd.Row() )
147 // within range?
148 if ( nCol >= aFormatArea.aStart.Col() && nCol <= aFormatArea.aEnd.Col() )
150 bFound = true; // do not change range
152 // left ?
153 if ( nCol+1 == aFormatArea.aStart.Col() )
155 bFound = true;
156 aNewRange.aStart.SetCol( nCol );
158 // right ?
159 if ( nCol == aFormatArea.aEnd.Col()+1 )
161 bFound = true;
162 aNewRange.aEnd.SetCol( nCol );
165 if ( nCol >= aFormatArea.aStart.Col() && nCol <= aFormatArea.aEnd.Col() )
167 // top ?
168 if ( nRow+1 == aFormatArea.aStart.Row() )
170 bFound = true;
171 aNewRange.aStart.SetRow( nRow );
173 // bottom ?
174 if ( nRow == aFormatArea.aEnd.Row()+1 )
176 bFound = true;
177 aNewRange.aEnd.SetRow( nRow );
182 if (bFound)
183 aFormatArea = aNewRange; // extend
184 else
185 bFormatValid = false; // outside of range -> break
187 return bFound;
190 void ScViewFunc::DoAutoAttributes( SCCOL nCol, SCROW nRow, SCTAB nTab,
191 bool bAttrChanged, bool bAddUndo )
193 ScDocShell* pDocSh = GetViewData().GetDocShell();
194 ScDocument& rDoc = pDocSh->GetDocument();
195 if (bAddUndo && !rDoc.IsUndoEnabled())
196 bAddUndo = false;
198 const ScPatternAttr* pSource = rDoc.GetPattern(
199 aFormatSource.Col(), aFormatSource.Row(), nTab );
200 if ( !static_cast<const ScMergeAttr&>(pSource->GetItem(ATTR_MERGE)).IsMerged() )
202 ScRange aRange( nCol, nRow, nTab, nCol, nRow, nTab );
203 ScMarkData aMark;
204 aMark.SetMarkArea( aRange );
206 ScDocFunc &rFunc = GetViewData().GetDocFunc();
208 // pOldPattern is only valid until call to ApplyAttributes!
209 const ScPatternAttr* pOldPattern = rDoc.GetPattern( nCol, nRow, nTab );
210 const ScStyleSheet* pSrcStyle = pSource->GetStyleSheet();
211 if ( pSrcStyle && pSrcStyle != pOldPattern->GetStyleSheet() )
212 rFunc.ApplyStyle( aMark, pSrcStyle->GetName(), true, false );
214 rFunc.ApplyAttributes( aMark, *pSource, true, false );
217 if ( bAttrChanged ) // value entered with number format?
218 aFormatSource.Set( nCol, nRow, nTab ); // then set a new source
221 // additional routines
223 sal_uInt16 ScViewFunc::GetOptimalColWidth( SCCOL nCol, SCTAB nTab, bool bFormula )
225 ScDocShell* pDocSh = GetViewData().GetDocShell();
226 ScDocument& rDoc = pDocSh->GetDocument();
227 ScMarkData& rMark = GetViewData().GetMarkData();
229 double nPPTX = GetViewData().GetPPTX();
230 double nPPTY = GetViewData().GetPPTY();
231 Fraction aZoomX = GetViewData().GetZoomX();
232 Fraction aZoomY = GetViewData().GetZoomY();
234 ScSizeDeviceProvider aProv(pDocSh);
235 if (aProv.IsPrinter())
237 nPPTX = aProv.GetPPTX();
238 nPPTY = aProv.GetPPTY();
239 aZoomX = aZoomY = Fraction( 1, 1 );
242 sal_uInt16 nTwips = rDoc.GetOptimalColWidth( nCol, nTab, aProv.GetDevice(),
243 nPPTX, nPPTY, aZoomX, aZoomY, bFormula, &rMark );
244 return nTwips;
247 bool ScViewFunc::SelectionEditable( bool* pOnlyNotBecauseOfMatrix /* = NULL */ )
249 bool bRet;
250 ScDocument* pDoc = GetViewData().GetDocument();
251 ScMarkData& rMark = GetViewData().GetMarkData();
252 if (rMark.IsMarked() || rMark.IsMultiMarked())
253 bRet = pDoc->IsSelectionEditable( rMark, pOnlyNotBecauseOfMatrix );
254 else
256 SCCOL nCol = GetViewData().GetCurX();
257 SCROW nRow = GetViewData().GetCurY();
258 SCTAB nTab = GetViewData().GetTabNo();
259 bRet = pDoc->IsBlockEditable( nTab, nCol, nRow, nCol, nRow,
260 pOnlyNotBecauseOfMatrix );
262 return bRet;
265 #ifndef LRU_MAX
266 #define LRU_MAX 10
267 #endif
269 static bool lcl_FunctionKnown( sal_uInt16 nOpCode )
271 const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList();
272 if ( pFuncList )
274 sal_uLong nCount = pFuncList->GetCount();
275 for (sal_uLong i=0; i<nCount; i++)
276 if ( pFuncList->GetFunction(i)->nFIndex == nOpCode )
277 return true;
279 return false;
282 static bool lcl_AddFunction( ScAppOptions& rAppOpt, sal_uInt16 nOpCode )
284 sal_uInt16 nOldCount = rAppOpt.GetLRUFuncListCount();
285 sal_uInt16* pOldList = rAppOpt.GetLRUFuncList();
286 sal_uInt16 nPos;
287 for (nPos=0; nPos<nOldCount; nPos++)
288 if (pOldList[nPos] == nOpCode) // is the function already in the list?
290 if ( nPos == 0 )
291 return false; // already at the top -> no change
293 // count doesn't change, so the original array is modified
295 for (sal_uInt16 nCopy=nPos; nCopy>0; nCopy--)
296 pOldList[nCopy] = pOldList[nCopy-1];
297 pOldList[0] = nOpCode;
299 return true; // list has changed
302 if ( !lcl_FunctionKnown( nOpCode ) )
303 return false; // not in function list -> no change
305 sal_uInt16 nNewCount = std::min( (sal_uInt16)(nOldCount + 1), (sal_uInt16)LRU_MAX );
306 sal_uInt16 nNewList[LRU_MAX];
307 nNewList[0] = nOpCode;
308 for (nPos=1; nPos<nNewCount; nPos++)
309 nNewList[nPos] = pOldList[nPos-1];
310 rAppOpt.SetLRUFuncList( nNewList, nNewCount );
312 return true; // list has changed
315 namespace HelperNotifyChanges
317 void NotifyIfChangesListeners(ScDocShell &rDocShell, ScMarkData& rMark, SCCOL nCol, SCROW nRow,
318 const OUString &rType = OUString("cell-change"))
320 if (ScModelObj *pModelObj = getMustPropagateChangesModel(rDocShell))
322 ScRangeList aChangeRanges;
323 ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
324 for (; itr != itrEnd; ++itr)
325 aChangeRanges.Append( ScRange( nCol, nRow, *itr ) );
327 HelperNotifyChanges::Notify(*pModelObj, aChangeRanges, rType);
332 // actual functions
334 // input - undo OK
335 void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab,
336 const OUString& rString,
337 const EditTextObject* pData )
339 ScDocument* pDoc = GetViewData().GetDocument();
340 ScMarkData rMark(GetViewData().GetMarkData());
341 bool bRecord = pDoc->IsUndoEnabled();
342 SCTAB i;
344 ScDocShell* pDocSh = GetViewData().GetDocShell();
345 ScDocFunc &rFunc = GetViewData().GetDocFunc();
346 ScDocShellModificator aModificator( *pDocSh );
348 ScEditableTester aTester( pDoc, nCol,nRow, nCol,nRow, rMark );
349 if (!aTester.IsEditable())
351 ErrorMessage(aTester.GetMessageId());
352 PaintArea(nCol, nRow, nCol, nRow); // possibly the edit-engine is still painted there
353 return;
356 if ( bRecord )
357 rFunc.EnterListAction( STR_UNDO_ENTERDATA );
359 bool bFormula = false;
361 // a single '=' character is handled as string (needed for special filters)
362 if ( rString.getLength() > 1 )
364 if ( rString[0] == '=' )
366 // handle as formula
367 bFormula = true;
369 else if ( rString[0] == '+' || rString[0] == '-' )
371 // if there is more than one leading '+' or '-' character, remove the additional ones
372 sal_Int32 nIndex = 1;
373 sal_Int32 nLen = rString.getLength();
374 while ( nIndex < nLen && ( rString[ nIndex ] == '+' || rString[ nIndex ] == '-' ) )
376 ++nIndex;
378 OUString aString = rString.replaceAt( 1, nIndex - 1, "" );
380 // if the remaining part without the leading '+' or '-' character
381 // is non-empty and not a number, handle as formula
382 if ( aString.getLength() > 1 )
384 sal_uInt32 nFormat = 0;
385 pDoc->GetNumberFormat( nCol, nRow, nTab, nFormat );
386 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
387 double fNumber = 0;
388 if ( !pFormatter->IsNumberFormat( aString, nFormat, fNumber ) )
390 bFormula = true;
396 bool bNumFmtChanged = false;
397 if ( bFormula )
398 { // formula, compile with autoCorrection
399 i = rMark.GetFirstSelected();
400 ScAddress aPos( nCol, nRow, i );
401 ScCompiler aComp( pDoc, aPos);
402 aComp.SetGrammar(pDoc->GetGrammar());
403 //2do: enable/disable autoCorrection via calcoptions
404 aComp.SetAutoCorrection( true );
405 if ( rString[0] == '+' || rString[0] == '-' )
407 aComp.SetExtendedErrorDetection( ScCompiler::EXTENDED_ERROR_DETECTION_NAME_BREAK );
409 OUString aFormula( rString );
410 ScTokenArray* pArr;
411 bool bAgain;
414 bAgain = false;
415 bool bAddEqual = false;
416 ScTokenArray* pArrFirst = pArr = aComp.CompileString( aFormula );
417 bool bCorrected = aComp.IsCorrected();
418 if ( bCorrected )
419 { // try to parse with first parser-correction
420 pArr = aComp.CompileString( aComp.GetCorrectedFormula() );
422 if ( !pArr->GetCodeError() )
424 bAddEqual = true;
425 aComp.CompileTokenArray();
426 bCorrected |= aComp.IsCorrected();
428 if ( bCorrected )
430 OUString aCorrectedFormula;
431 if ( bAddEqual )
433 aCorrectedFormula = "=" + aComp.GetCorrectedFormula();
435 else
436 aCorrectedFormula = aComp.GetCorrectedFormula();
437 short nResult;
438 if ( aCorrectedFormula.getLength() == 1 )
439 nResult = RET_NO; // empty formula, just '='
440 else
442 OUString aMessage( ScResId( SCSTR_FORMULA_AUTOCORRECTION ) );
443 aMessage += aCorrectedFormula;
444 nResult = ScopedVclPtr<QueryBox>::Create( GetViewData().GetDialogParent(),
445 WinBits(WB_YES_NO | WB_DEF_YES),
446 aMessage )->Execute();
448 if ( nResult == RET_YES )
450 aFormula = aCorrectedFormula;
451 if ( pArr != pArrFirst )
452 delete pArrFirst;
453 bAgain = true;
455 else
457 if ( pArr != pArrFirst )
459 delete pArr;
460 pArr = pArrFirst;
464 } while ( bAgain );
465 // to be used in multiple tabs, the formula must be compiled anew
466 // via ScFormulaCell copy-ctor because of RangeNames,
467 // the same code-array for all cells is not possible.
468 // If the array has an error, (it) must be RPN-erased in the newly generated
469 // cellst and the error be set explicitly, so that
470 // via FormulaCell copy-ctor and Interpreter it will be, when possible,
471 // ironed out again, too intelligent.. e.g.: =1))
472 sal_uInt16 nError = pArr->GetCodeError();
473 if ( !nError )
475 // update list of recent functions with all functions that
476 // are not within parentheses
478 ScModule* pScMod = SC_MOD();
479 ScAppOptions aAppOpt = pScMod->GetAppOptions();
480 bool bOptChanged = false;
482 formula::FormulaToken** ppToken = pArr->GetArray();
483 sal_uInt16 nTokens = pArr->GetLen();
484 sal_uInt16 nLevel = 0;
485 for (sal_uInt16 nTP=0; nTP<nTokens; nTP++)
487 formula::FormulaToken* pTok = ppToken[nTP];
488 OpCode eOp = pTok->GetOpCode();
489 if ( eOp == ocOpen )
490 ++nLevel;
491 else if ( eOp == ocClose && nLevel )
492 --nLevel;
493 if ( nLevel == 0 && pTok->IsFunction() &&
494 lcl_AddFunction( aAppOpt, sal::static_int_cast<sal_uInt16>( eOp ) ) )
495 bOptChanged = true;
498 if ( bOptChanged )
500 pScMod->SetAppOptions(aAppOpt);
501 ScModule::RecentFunctionsChanged();
505 ScFormulaCell aCell(pDoc, aPos, *pArr, formula::FormulaGrammar::GRAM_DEFAULT, MM_NONE);
506 delete pArr;
508 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
509 ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
510 for (; itr != itrEnd; ++itr)
512 i = *itr;
513 aPos.SetTab( i );
514 sal_uLong nIndex = (sal_uLong) static_cast<const SfxUInt32Item*>( pDoc->GetAttr(
515 nCol, nRow, i, ATTR_VALUE_FORMAT ))->GetValue();
516 if ( pFormatter->GetType( nIndex ) == css::util::NumberFormat::TEXT ||
517 ( ( rString[0] == '+' || rString[0] == '-' ) && nError && rString == aFormula ) )
519 if ( pData )
521 // A clone of pData will be stored in the cell.
522 rFunc.SetEditCell(aPos, *pData, true);
524 else
525 rFunc.SetStringCell(aPos, aFormula, true);
527 else
529 ScFormulaCell* pCell = new ScFormulaCell( aCell, *pDoc, aPos );
530 if ( nError )
532 pCell->GetCode()->DelRPN();
533 pCell->SetErrCode( nError );
534 if(pCell->GetCode()->IsHyperLink())
535 pCell->GetCode()->SetHyperLink(false);
537 rFunc.SetFormulaCell(aPos, pCell, true);
541 else
543 ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
544 for ( ; itr != itrEnd; ++itr )
546 bool bNumFmtSet = false;
547 rFunc.SetNormalString( bNumFmtSet, ScAddress( nCol, nRow, *itr ), rString, false );
548 if (bNumFmtSet)
550 /* FIXME: if set on any sheet results in changed only on
551 * sheet nTab for TestFormatArea() and DoAutoAttributes() */
552 bNumFmtChanged = true;
557 bool bAutoFormat = TestFormatArea(nCol, nRow, nTab, bNumFmtChanged);
559 if (bAutoFormat)
560 DoAutoAttributes(nCol, nRow, nTab, bNumFmtChanged, bRecord);
562 pDocSh->UpdateOle(&GetViewData());
564 HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh, rMark, nCol, nRow);
566 if ( bRecord )
567 rFunc.EndListAction();
569 aModificator.SetDocumentModified();
570 lcl_PostRepaintCondFormat( pDoc->GetCondFormat( nCol, nRow, nTab ), pDocSh );
573 // enter value in single cell (on nTab only)
575 void ScViewFunc::EnterValue( SCCOL nCol, SCROW nRow, SCTAB nTab, const double& rValue )
577 ScDocument* pDoc = GetViewData().GetDocument();
578 ScDocShell* pDocSh = GetViewData().GetDocShell();
580 if ( pDoc && pDocSh )
582 bool bUndo(pDoc->IsUndoEnabled());
583 ScDocShellModificator aModificator( *pDocSh );
585 ScEditableTester aTester( pDoc, nTab, nCol,nRow, nCol,nRow );
586 if (aTester.IsEditable())
588 ScAddress aPos( nCol, nRow, nTab );
589 ScCellValue aUndoCell;
590 if (bUndo)
591 aUndoCell.assign(*pDoc, aPos);
593 pDoc->SetValue( nCol, nRow, nTab, rValue );
595 // because of ChangeTrack after change in document
596 if (bUndo)
598 pDocSh->GetUndoManager()->AddUndoAction(
599 new ScUndoEnterValue(pDocSh, aPos, aUndoCell, rValue));
602 pDocSh->PostPaintCell( aPos );
603 pDocSh->UpdateOle(&GetViewData());
604 aModificator.SetDocumentModified();
606 else
607 ErrorMessage(aTester.GetMessageId());
611 void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab,
612 const EditTextObject& rData, bool bTestSimple )
614 ScDocShell* pDocSh = GetViewData().GetDocShell();
615 ScMarkData& rMark = GetViewData().GetMarkData();
616 ScDocument& rDoc = pDocSh->GetDocument();
617 bool bRecord = rDoc.IsUndoEnabled();
619 ScDocShellModificator aModificator( *pDocSh );
621 ScEditableTester aTester( &rDoc, nTab, nCol,nRow, nCol,nRow );
622 if (aTester.IsEditable())
625 // test for attribute
627 bool bSimple = false;
628 bool bCommon = false;
629 boost::scoped_ptr<ScPatternAttr> pCellAttrs;
630 OUString aString;
632 const ScPatternAttr* pOldPattern = rDoc.GetPattern( nCol, nRow, nTab );
633 ScTabEditEngine aEngine( *pOldPattern, rDoc.GetEnginePool() );
634 aEngine.SetText(rData);
636 if (bTestSimple) // test, if simple string without attribute
638 ScEditAttrTester aAttrTester( &aEngine );
639 bSimple = !aAttrTester.NeedsObject();
640 bCommon = aAttrTester.NeedsCellAttr();
642 // formulas have to be recognized even if they're formatted
643 // (but commmon attributes are still collected)
645 if ( !bSimple && aEngine.GetParagraphCount() == 1 )
647 OUString aParStr(aEngine.GetText( 0 ));
648 if ( aParStr[0] == '=' )
649 bSimple = true;
652 if (bCommon) // attribute for tab
654 pCellAttrs.reset(new ScPatternAttr( *pOldPattern ));
655 pCellAttrs->GetFromEditItemSet( &aAttrTester.GetAttribs() );
656 //! remove common attributes from EditEngine?
660 // #i97726# always get text for "repeat" of undo action
661 aString = ScEditUtil::GetSpaceDelimitedString(aEngine);
663 // undo
665 EditTextObject* pUndoData = NULL;
666 ScUndoEnterData::ValuesType aOldValues;
668 if (bRecord && !bSimple)
670 ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
671 for (; itr != itrEnd; ++itr)
673 ScUndoEnterData::Value aOldValue;
674 aOldValue.mnTab = *itr;
675 aOldValue.maCell.assign(rDoc, ScAddress(nCol, nRow, *itr));
676 aOldValues.push_back(aOldValue);
679 pUndoData = rData.Clone();
682 // enter data
684 if (bCommon)
685 rDoc.ApplyPattern(nCol,nRow,nTab,*pCellAttrs); //! undo
687 if (bSimple)
689 if (bCommon)
690 AdjustRowHeight(nRow,nRow);
692 EnterData(nCol,nRow,nTab,aString);
694 else
696 ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
697 for (; itr != itrEnd; ++itr)
699 ScAddress aPos(nCol, nRow, *itr);
700 rDoc.SetEditText(aPos, rData, rDoc.GetEditPool());
703 if ( bRecord )
704 { // because of ChangeTrack current first
705 pDocSh->GetUndoManager()->AddUndoAction(
706 new ScUndoEnterData(pDocSh, ScAddress(nCol,nRow,nTab), aOldValues, aString, pUndoData));
709 HideAllCursors();
711 AdjustRowHeight(nRow,nRow);
713 itr = rMark.begin();
714 for (; itr != itrEnd; ++itr)
715 pDocSh->PostPaintCell( nCol, nRow, *itr );
717 ShowAllCursors();
719 pDocSh->UpdateOle(&GetViewData());
721 HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh, rMark, nCol, nRow);
723 aModificator.SetDocumentModified();
725 lcl_PostRepaintCondFormat( rDoc.GetCondFormat( nCol, nRow, nTab ), pDocSh );
727 else
729 ErrorMessage(aTester.GetMessageId());
730 PaintArea( nCol, nRow, nCol, nRow ); // possibly the edit-engine is still painted there
734 void ScViewFunc::EnterDataAtCursor( const OUString& rString )
736 SCCOL nPosX = GetViewData().GetCurX();
737 SCROW nPosY = GetViewData().GetCurY();
738 SCTAB nTab = GetViewData().GetTabNo();
740 EnterData( nPosX, nPosY, nTab, rString );
743 void ScViewFunc::EnterMatrix( const OUString& rString, ::formula::FormulaGrammar::Grammar eGram )
745 ScViewData& rData = GetViewData();
746 const ScMarkData& rMark = rData.GetMarkData();
747 if ( !rMark.IsMarked() && !rMark.IsMultiMarked() )
749 // nothing marked -> temporarily calculate block
750 // with size of result formula to get the size
752 ScDocument* pDoc = rData.GetDocument();
753 SCCOL nCol = rData.GetCurX();
754 SCROW nRow = rData.GetCurY();
755 SCTAB nTab = rData.GetTabNo();
756 ScFormulaCell aFormCell( pDoc, ScAddress(nCol,nRow,nTab), rString, eGram, MM_FORMULA );
758 SCSIZE nSizeX;
759 SCSIZE nSizeY;
760 aFormCell.GetResultDimensions( nSizeX, nSizeY );
761 if ( nSizeX != 0 && nSizeY != 0 &&
762 nCol+nSizeX-1 <= sal::static_int_cast<SCSIZE>(MAXCOL) &&
763 nRow+nSizeY-1 <= sal::static_int_cast<SCSIZE>(MAXROW) )
765 ScRange aResult( nCol, nRow, nTab,
766 sal::static_int_cast<SCCOL>(nCol+nSizeX-1),
767 sal::static_int_cast<SCROW>(nRow+nSizeY-1), nTab );
768 MarkRange( aResult, false );
772 ScRange aRange;
773 if (rData.GetSimpleArea(aRange) == SC_MARK_SIMPLE)
775 ScDocShell* pDocSh = rData.GetDocShell();
776 bool bSuccess = pDocSh->GetDocFunc().EnterMatrix(
777 aRange, &rMark, NULL, rString, false, false, EMPTY_OUSTRING, eGram );
778 if (bSuccess)
779 pDocSh->UpdateOle(&GetViewData());
781 else
782 ErrorMessage(STR_NOMULTISELECT);
785 SvtScriptType ScViewFunc::GetSelectionScriptType()
787 SvtScriptType nScript = SvtScriptType::NONE;
789 ScDocument* pDoc = GetViewData().GetDocument();
790 const ScMarkData& rMark = GetViewData().GetMarkData();
791 if ( !rMark.IsMarked() && !rMark.IsMultiMarked() )
793 // no selection -> cursor
795 nScript = pDoc->GetScriptType( GetViewData().GetCurX(),
796 GetViewData().GetCurY(), GetViewData().GetTabNo());
798 else
800 ScRangeList aRanges;
801 rMark.FillRangeListWithMarks( &aRanges, false );
802 nScript = pDoc->GetRangeScriptType(aRanges);
805 if (nScript == SvtScriptType::NONE)
806 nScript = ScGlobal::GetDefaultScriptType();
808 return nScript;
811 const ScPatternAttr* ScViewFunc::GetSelectionPattern()
813 // Don't use UnmarkFiltered in slot state functions, for performance reasons.
814 // The displayed state is always that of the whole selection including filtered rows.
816 const ScMarkData& rMark = GetViewData().GetMarkData();
817 ScDocument* pDoc = GetViewData().GetDocument();
818 if ( rMark.IsMarked() || rMark.IsMultiMarked() )
820 // MarkToMulti is no longer necessary for pDoc->GetSelectionPattern
821 const ScPatternAttr* pAttr = pDoc->GetSelectionPattern( rMark );
822 return pAttr;
824 else
826 SCCOL nCol = GetViewData().GetCurX();
827 SCROW nRow = GetViewData().GetCurY();
828 SCTAB nTab = GetViewData().GetTabNo();
830 ScMarkData aTempMark( rMark ); // copy sheet selection
831 aTempMark.SetMarkArea( ScRange( nCol, nRow, nTab ) );
832 const ScPatternAttr* pAttr = pDoc->GetSelectionPattern( aTempMark );
833 return pAttr;
837 void ScViewFunc::GetSelectionFrame( SvxBoxItem& rLineOuter,
838 SvxBoxInfoItem& rLineInner )
840 ScDocument* pDoc = GetViewData().GetDocument();
841 const ScMarkData& rMark = GetViewData().GetMarkData();
843 if ( rMark.IsMarked() || rMark.IsMultiMarked() )
845 if ( rMark.IsMultiMarked() )
847 ScMarkData aNewMark( rMark ); // use local copy for MarkToSimple
848 aNewMark.MarkToSimple(); // simple block is needed for GetSelectionFrame
849 pDoc->GetSelectionFrame( aNewMark, rLineOuter, rLineInner );
851 else
852 pDoc->GetSelectionFrame( rMark, rLineOuter, rLineInner );
854 else
856 const ScPatternAttr* pAttrs =
857 pDoc->GetPattern( GetViewData().GetCurX(),
858 GetViewData().GetCurY(),
859 GetViewData().GetTabNo() );
861 rLineOuter = static_cast<const SvxBoxItem&> (pAttrs->GetItem( ATTR_BORDER ));
862 rLineInner = static_cast<const SvxBoxInfoItem&>(pAttrs->GetItem( ATTR_BORDER_INNER ));
863 rLineInner.SetTable(false);
864 rLineInner.SetDist(true);
865 rLineInner.SetMinDist(false);
869 // apply attribute - undo OK
871 // complete set ( ATTR_STARTINDEX, ATTR_ENDINDEX )
873 void ScViewFunc::ApplyAttributes( const SfxItemSet* pDialogSet,
874 const SfxItemSet* pOldSet,
875 bool bRecord )
877 // not editable because of matrix only? attribute OK nonetheless
878 bool bOnlyNotBecauseOfMatrix;
879 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
881 ErrorMessage(STR_PROTECTIONERR);
882 return;
885 ScPatternAttr aOldAttrs( new SfxItemSet(*pOldSet) );
886 ScPatternAttr aNewAttrs( new SfxItemSet(*pDialogSet) );
887 aNewAttrs.DeleteUnchanged( &aOldAttrs );
889 if ( pDialogSet->GetItemState( ATTR_VALUE_FORMAT ) == SfxItemState::SET )
890 { // don't reset to default SYSTEM GENERAL if not intended
891 sal_uInt32 nOldFormat =
892 static_cast<const SfxUInt32Item&>(pOldSet->Get( ATTR_VALUE_FORMAT )).GetValue();
893 sal_uInt32 nNewFormat =
894 static_cast<const SfxUInt32Item&>(pDialogSet->Get( ATTR_VALUE_FORMAT )).GetValue();
895 if ( nNewFormat != nOldFormat )
897 SvNumberFormatter* pFormatter =
898 GetViewData().GetDocument()->GetFormatTable();
899 const SvNumberformat* pOldEntry = pFormatter->GetEntry( nOldFormat );
900 LanguageType eOldLang =
901 pOldEntry ? pOldEntry->GetLanguage() : LANGUAGE_DONTKNOW;
902 const SvNumberformat* pNewEntry = pFormatter->GetEntry( nNewFormat );
903 LanguageType eNewLang =
904 pNewEntry ? pNewEntry->GetLanguage() : LANGUAGE_DONTKNOW;
905 if ( eNewLang != eOldLang )
907 aNewAttrs.GetItemSet().Put(
908 SvxLanguageItem( eNewLang, ATTR_LANGUAGE_FORMAT ) );
910 // only the language has changed -> do not touch numberformat-attribute
911 sal_uInt32 nNewMod = nNewFormat % SV_COUNTRY_LANGUAGE_OFFSET;
912 if ( nNewMod == ( nOldFormat % SV_COUNTRY_LANGUAGE_OFFSET ) &&
913 nNewMod <= SV_MAX_ANZ_STANDARD_FORMATE )
914 aNewAttrs.GetItemSet().ClearItem( ATTR_VALUE_FORMAT );
919 const SvxBoxItem* pOldOuter = static_cast<const SvxBoxItem*> (&pOldSet->Get( ATTR_BORDER ));
920 const SvxBoxItem* pNewOuter = static_cast<const SvxBoxItem*> (&pDialogSet->Get( ATTR_BORDER ));
921 const SvxBoxInfoItem* pOldInner = static_cast<const SvxBoxInfoItem*> (&pOldSet->Get( ATTR_BORDER_INNER ));
922 const SvxBoxInfoItem* pNewInner = static_cast<const SvxBoxInfoItem*> (&pDialogSet->Get( ATTR_BORDER_INNER ));
923 SfxItemSet& rNewSet = aNewAttrs.GetItemSet();
924 SfxItemPool* pNewPool = rNewSet.GetPool();
926 pNewPool->Put( *pNewOuter ); // don't delete yet
927 pNewPool->Put( *pNewInner );
928 rNewSet.ClearItem( ATTR_BORDER );
929 rNewSet.ClearItem( ATTR_BORDER_INNER );
932 * establish whether border attribute is to be set:
933 * 1. new != old
934 * 2. is one of the borders not-DontCare (since 238.f: IsxxValid())
938 bool bFrame = (pDialogSet->GetItemState( ATTR_BORDER ) != SfxItemState::DEFAULT)
939 || (pDialogSet->GetItemState( ATTR_BORDER_INNER ) != SfxItemState::DEFAULT);
941 if ( pNewOuter==pOldOuter && pNewInner==pOldInner )
942 bFrame = false;
944 // this should be intercepted by the pool: ?!??!??
946 if ( bFrame && pNewOuter && pNewInner )
947 if ( *pNewOuter == *pOldOuter && *pNewInner == *pOldInner )
948 bFrame = false;
950 if ( pNewInner )
952 bFrame = bFrame
953 && ( pNewInner->IsValid(SvxBoxInfoItemValidFlags::LEFT)
954 || pNewInner->IsValid(SvxBoxInfoItemValidFlags::RIGHT)
955 || pNewInner->IsValid(SvxBoxInfoItemValidFlags::TOP)
956 || pNewInner->IsValid(SvxBoxInfoItemValidFlags::BOTTOM)
957 || pNewInner->IsValid(SvxBoxInfoItemValidFlags::HORI)
958 || pNewInner->IsValid(SvxBoxInfoItemValidFlags::VERT) );
960 else
961 bFrame = false;
963 if (!bFrame)
964 ApplySelectionPattern( aNewAttrs, bRecord ); // standard only
965 else
967 // if new items are default-items, overwrite the old items:
969 bool bDefNewOuter = ( SFX_ITEMS_STATICDEFAULT == pNewOuter->GetKind() );
970 bool bDefNewInner = ( SFX_ITEMS_STATICDEFAULT == pNewInner->GetKind() );
972 ApplyPatternLines( aNewAttrs,
973 bDefNewOuter ? pOldOuter : pNewOuter,
974 bDefNewInner ? pOldInner : pNewInner,
975 bRecord );
978 pNewPool->Remove( *pNewOuter ); // release
979 pNewPool->Remove( *pNewInner );
981 // adjust height
982 AdjustBlockHeight();
984 // CellContentChanged is called in ApplySelectionPattern / ApplyPatternLines
987 void ScViewFunc::ApplyAttr( const SfxPoolItem& rAttrItem )
989 // not editable because of matrix only? attribute OK nonetheless
990 bool bOnlyNotBecauseOfMatrix;
991 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
993 ErrorMessage(STR_PROTECTIONERR);
994 return;
997 ScPatternAttr aNewAttrs( new SfxItemSet( *GetViewData().GetDocument()->GetPool(),
998 ATTR_PATTERN_START, ATTR_PATTERN_END ) );
1000 aNewAttrs.GetItemSet().Put( rAttrItem );
1001 // if justify is set (with Buttons), always indentation 0
1002 if ( rAttrItem.Which() == ATTR_HOR_JUSTIFY )
1003 aNewAttrs.GetItemSet().Put( SfxUInt16Item( ATTR_INDENT, 0 ) );
1004 ApplySelectionPattern( aNewAttrs );
1006 AdjustBlockHeight();
1008 // CellContentChanged is called in ApplySelectionPattern
1011 // patterns and borders
1013 void ScViewFunc::ApplyPatternLines( const ScPatternAttr& rAttr, const SvxBoxItem* pNewOuter,
1014 const SvxBoxInfoItem* pNewInner, bool bRecord )
1016 ScDocument* pDoc = GetViewData().GetDocument();
1017 ScMarkData aFuncMark( GetViewData().GetMarkData() ); // local copy for UnmarkFiltered
1018 ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
1019 if (bRecord && !pDoc->IsUndoEnabled())
1020 bRecord = false;
1022 ScRange aMarkRange;
1023 aFuncMark.MarkToSimple();
1024 bool bMulti = aFuncMark.IsMultiMarked();
1025 if (bMulti)
1026 aFuncMark.GetMultiMarkArea( aMarkRange );
1027 else if (aFuncMark.IsMarked())
1028 aFuncMark.GetMarkArea( aMarkRange );
1029 else
1031 aMarkRange = ScRange( GetViewData().GetCurX(),
1032 GetViewData().GetCurY(), GetViewData().GetTabNo() );
1033 DoneBlockMode();
1034 InitOwnBlockMode();
1035 aFuncMark.SetMarkArea(aMarkRange);
1036 MarkDataChanged();
1039 ScDocShell* pDocSh = GetViewData().GetDocShell();
1041 ScDocShellModificator aModificator( *pDocSh );
1043 if (bRecord)
1045 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1046 SCTAB nStartTab = aMarkRange.aStart.Tab();
1047 SCTAB nTabCount = pDoc->GetTableCount();
1048 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
1049 ScMarkData::iterator itr = aFuncMark.begin(), itrEnd = aFuncMark.end();
1050 for (; itr != itrEnd; ++itr)
1051 if (*itr != nStartTab)
1052 pUndoDoc->AddUndoTab( *itr, *itr );
1054 ScRange aCopyRange = aMarkRange;
1055 aCopyRange.aStart.SetTab(0);
1056 aCopyRange.aEnd.SetTab(nTabCount-1);
1057 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pUndoDoc, &aFuncMark );
1059 pDocSh->GetUndoManager()->AddUndoAction(
1060 new ScUndoSelectionAttr(
1061 pDocSh, aFuncMark,
1062 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), aMarkRange.aStart.Tab(),
1063 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), aMarkRange.aEnd.Tab(),
1064 pUndoDoc, bMulti, &rAttr, pNewOuter, pNewInner ) );
1067 sal_uInt16 nExt = SC_PF_TESTMERGE;
1068 pDocSh->UpdatePaintExt( nExt, aMarkRange ); // content before the change
1070 pDoc->ApplySelectionFrame( aFuncMark, pNewOuter, pNewInner );
1072 pDocSh->UpdatePaintExt( nExt, aMarkRange ); // content after the change
1074 aFuncMark.MarkToMulti();
1075 pDoc->ApplySelectionPattern( rAttr, aFuncMark );
1077 pDocSh->PostPaint( aMarkRange, PAINT_GRID, nExt );
1078 pDocSh->UpdateOle(&GetViewData());
1079 aModificator.SetDocumentModified();
1080 CellContentChanged();
1082 StartFormatArea();
1085 // pattern only
1087 void ScViewFunc::ApplySelectionPattern( const ScPatternAttr& rAttr,
1088 bool bRecord, bool bCursorOnly )
1090 ScViewData& rViewData = GetViewData();
1091 ScDocShell* pDocSh = rViewData.GetDocShell();
1092 ScDocument& rDoc = pDocSh->GetDocument();
1093 ScMarkData aFuncMark( rViewData.GetMarkData() ); // local copy for UnmarkFiltered
1094 ScViewUtil::UnmarkFiltered( aFuncMark, &rDoc );
1096 if (bRecord && !rDoc.IsUndoEnabled())
1097 bRecord = false;
1099 // State from old ItemSet doesn't matter for paint flags, as any change will be
1100 // from SfxItemState::SET in the new ItemSet (default is ignored in ApplyPattern).
1101 // New alignment is checked (check in PostPaint isn't enough) in case a right
1102 // alignment is changed to left.
1103 const SfxItemSet& rNewSet = rAttr.GetItemSet();
1104 bool bSetLines = rNewSet.GetItemState( ATTR_BORDER, true ) == SfxItemState::SET ||
1105 rNewSet.GetItemState( ATTR_SHADOW, true ) == SfxItemState::SET;
1106 bool bSetAlign = rNewSet.GetItemState( ATTR_HOR_JUSTIFY, true ) == SfxItemState::SET;
1108 sal_uInt16 nExtFlags = 0;
1109 if ( bSetLines )
1110 nExtFlags |= SC_PF_LINES;
1111 if ( bSetAlign )
1112 nExtFlags |= SC_PF_WHOLEROWS;
1114 ScDocShellModificator aModificator( *pDocSh );
1116 bool bMulti = aFuncMark.IsMultiMarked();
1117 aFuncMark.MarkToMulti();
1118 bool bOnlyTab = (!aFuncMark.IsMultiMarked() && !bCursorOnly && aFuncMark.GetSelectCount() > 1);
1119 if (bOnlyTab)
1121 SCCOL nCol = rViewData.GetCurX();
1122 SCROW nRow = rViewData.GetCurY();
1123 SCTAB nTab = rViewData.GetTabNo();
1124 aFuncMark.SetMarkArea(ScRange(nCol,nRow,nTab));
1125 aFuncMark.MarkToMulti();
1128 ScRangeList aChangeRanges;
1130 if (aFuncMark.IsMultiMarked() && !bCursorOnly)
1132 ScRange aMarkRange;
1133 aFuncMark.GetMultiMarkArea( aMarkRange );
1134 SCTAB nTabCount = rDoc.GetTableCount();
1135 ScMarkData::iterator itr = aFuncMark.begin(), itrEnd = aFuncMark.end();
1136 for (; itr != itrEnd; ++itr)
1138 ScRange aChangeRange( aMarkRange );
1139 aChangeRange.aStart.SetTab( *itr );
1140 aChangeRange.aEnd.SetTab( *itr );
1141 aChangeRanges.Append( aChangeRange );
1144 SCCOL nStartCol = aMarkRange.aStart.Col();
1145 SCROW nStartRow = aMarkRange.aStart.Row();
1146 SCTAB nStartTab = aMarkRange.aStart.Tab();
1147 SCCOL nEndCol = aMarkRange.aEnd.Col();
1148 SCROW nEndRow = aMarkRange.aEnd.Row();
1149 SCTAB nEndTab = aMarkRange.aEnd.Tab();
1151 ScUndoSelectionAttr* pUndoAttr = NULL;
1152 ScEditDataArray* pEditDataArray = NULL;
1153 if (bRecord)
1155 ScRange aCopyRange = aMarkRange;
1156 aCopyRange.aStart.SetTab(0);
1157 aCopyRange.aEnd.SetTab(nTabCount-1);
1159 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1160 pUndoDoc->InitUndo( &rDoc, nStartTab, nStartTab );
1161 itr = aFuncMark.begin();
1162 for (; itr != itrEnd; ++itr)
1163 if (*itr != nStartTab)
1164 pUndoDoc->AddUndoTab( *itr, *itr );
1165 rDoc.CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pUndoDoc, &aFuncMark );
1167 aFuncMark.MarkToMulti();
1169 pUndoAttr = new ScUndoSelectionAttr(
1170 pDocSh, aFuncMark, nStartCol, nStartRow, nStartTab,
1171 nEndCol, nEndRow, nEndTab, pUndoDoc, bMulti, &rAttr );
1172 pDocSh->GetUndoManager()->AddUndoAction(pUndoAttr);
1173 pEditDataArray = pUndoAttr->GetDataArray();
1176 rDoc.ApplySelectionPattern( rAttr, aFuncMark, pEditDataArray );
1178 pDocSh->PostPaint( nStartCol, nStartRow, nStartTab,
1179 nEndCol, nEndRow, nEndTab,
1180 PAINT_GRID, nExtFlags | SC_PF_TESTMERGE );
1181 pDocSh->UpdateOle(&GetViewData());
1182 aModificator.SetDocumentModified();
1183 CellContentChanged();
1185 else // single cell - simpler undo
1187 SCCOL nCol = rViewData.GetCurX();
1188 SCROW nRow = rViewData.GetCurY();
1189 SCTAB nTab = rViewData.GetTabNo();
1191 EditTextObject* pOldEditData = NULL;
1192 EditTextObject* pNewEditData = NULL;
1193 ScAddress aPos(nCol, nRow, nTab);
1194 if (rDoc.GetCellType(aPos) == CELLTYPE_EDIT)
1196 const EditTextObject* pEditObj = rDoc.GetEditText(aPos);
1197 pOldEditData = pEditObj ? pEditObj->Clone() : NULL;
1198 rDoc.RemoveEditTextCharAttribs(aPos, rAttr);
1199 pEditObj = rDoc.GetEditText(aPos);
1200 pNewEditData = pEditObj ? pEditObj->Clone() : NULL;
1203 aChangeRanges.Append(aPos);
1204 boost::scoped_ptr<ScPatternAttr> pOldPat(new ScPatternAttr(*rDoc.GetPattern( nCol, nRow, nTab )));
1206 rDoc.ApplyPattern( nCol, nRow, nTab, rAttr );
1208 const ScPatternAttr* pNewPat = rDoc.GetPattern( nCol, nRow, nTab );
1210 if (bRecord)
1212 ScUndoCursorAttr* pUndo = new ScUndoCursorAttr(
1213 pDocSh, nCol, nRow, nTab, pOldPat.get(), pNewPat, &rAttr, false );
1214 pUndo->SetEditData(pOldEditData, pNewEditData);
1215 pDocSh->GetUndoManager()->AddUndoAction(pUndo);
1217 pOldPat.reset(); // is copied in undo (Pool)
1219 pDocSh->PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PAINT_GRID, nExtFlags | SC_PF_TESTMERGE );
1220 pDocSh->UpdateOle(&GetViewData());
1221 aModificator.SetDocumentModified();
1222 CellContentChanged();
1225 ScModelObj* pModelObj = HelperNotifyChanges::getMustPropagateChangesModel(*pDocSh);
1226 if (pModelObj)
1228 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aProperties;
1229 sal_Int32 nCount = 0;
1230 const SfxItemPropertyMap& rMap = ScCellObj::GetCellPropertyMap();
1231 PropertyEntryVector_t aPropVector = rMap.getPropertyEntries();
1232 for ( sal_uInt16 nWhich = ATTR_PATTERN_START; nWhich <= ATTR_PATTERN_END; ++nWhich )
1234 const SfxPoolItem* pItem = 0;
1235 if ( rNewSet.GetItemState( nWhich, true, &pItem ) == SfxItemState::SET && pItem )
1237 PropertyEntryVector_t::const_iterator aIt = aPropVector.begin();
1238 while ( aIt != aPropVector.end())
1240 if ( aIt->nWID == nWhich )
1242 ::com::sun::star::uno::Any aVal;
1243 pItem->QueryValue( aVal, aIt->nMemberId );
1244 aProperties.realloc( nCount + 1 );
1245 aProperties[ nCount ].Name = aIt->sName;
1246 aProperties[ nCount ].Value <<= aVal;
1247 ++nCount;
1249 ++aIt;
1253 HelperNotifyChanges::Notify(*pModelObj, aChangeRanges, "attribute", aProperties);
1256 StartFormatArea();
1259 void ScViewFunc::ApplyUserItemSet( const SfxItemSet& rItemSet )
1261 // ItemSet from UI, may have different pool
1263 bool bOnlyNotBecauseOfMatrix;
1264 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
1266 ErrorMessage(STR_PROTECTIONERR);
1267 return;
1270 ScPatternAttr aNewAttrs( GetViewData().GetDocument()->GetPool() );
1271 SfxItemSet& rNewSet = aNewAttrs.GetItemSet();
1272 rNewSet.Put( rItemSet, false );
1273 ApplySelectionPattern( aNewAttrs );
1275 AdjustBlockHeight();
1278 const SfxStyleSheet* ScViewFunc::GetStyleSheetFromMarked()
1280 // Don't use UnmarkFiltered in slot state functions, for performance reasons.
1281 // The displayed state is always that of the whole selection including filtered rows.
1283 const ScStyleSheet* pSheet = NULL;
1284 ScViewData& rViewData = GetViewData();
1285 ScDocument* pDoc = rViewData.GetDocument();
1286 ScMarkData& rMark = rViewData.GetMarkData();
1288 if ( rMark.IsMarked() || rMark.IsMultiMarked() )
1289 pSheet = pDoc->GetSelectionStyle( rMark ); // MarkToMulti isn't necessary
1290 else
1291 pSheet = pDoc->GetStyle( rViewData.GetCurX(),
1292 rViewData.GetCurY(),
1293 rViewData.GetTabNo() );
1295 return pSheet;
1298 void ScViewFunc::SetStyleSheetToMarked( SfxStyleSheet* pStyleSheet, bool bRecord )
1300 // not editable because of matrix only? attribute OK nonetheless
1301 bool bOnlyNotBecauseOfMatrix;
1302 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
1304 ErrorMessage(STR_PROTECTIONERR);
1305 return;
1308 if ( !pStyleSheet) return;
1310 ScViewData& rViewData = GetViewData();
1311 ScDocShell* pDocSh = rViewData.GetDocShell();
1312 ScDocument& rDoc = pDocSh->GetDocument();
1313 ScMarkData aFuncMark( rViewData.GetMarkData() ); // local copy for UnmarkFiltered
1314 ScViewUtil::UnmarkFiltered( aFuncMark, &rDoc );
1315 SCTAB nTabCount = rDoc.GetTableCount();
1316 if (bRecord && !rDoc.IsUndoEnabled())
1317 bRecord = false;
1319 ScDocShellModificator aModificator( *pDocSh );
1321 if ( aFuncMark.IsMarked() || aFuncMark.IsMultiMarked() )
1323 ScRange aMarkRange;
1324 aFuncMark.MarkToMulti();
1325 aFuncMark.GetMultiMarkArea( aMarkRange );
1327 if ( bRecord )
1329 SCTAB nTab = rViewData.GetTabNo();
1330 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1331 pUndoDoc->InitUndo( &rDoc, nTab, nTab );
1332 ScMarkData::iterator itr = aFuncMark.begin(), itrEnd = aFuncMark.end();
1333 for (; itr != itrEnd; ++itr)
1334 if (*itr != nTab)
1335 pUndoDoc->AddUndoTab( *itr, *itr );
1337 ScRange aCopyRange = aMarkRange;
1338 aCopyRange.aStart.SetTab(0);
1339 aCopyRange.aEnd.SetTab(nTabCount-1);
1340 rDoc.CopyToDocument( aCopyRange, IDF_ATTRIB, true, pUndoDoc, &aFuncMark );
1341 aFuncMark.MarkToMulti();
1343 OUString aName = pStyleSheet->GetName();
1344 pDocSh->GetUndoManager()->AddUndoAction(
1345 new ScUndoSelectionStyle( pDocSh, aFuncMark, aMarkRange, aName, pUndoDoc ) );
1348 rDoc.ApplySelectionStyle( static_cast<ScStyleSheet&>(*pStyleSheet), aFuncMark );
1350 if (!AdjustBlockHeight())
1351 rViewData.GetDocShell()->PostPaint( aMarkRange, PAINT_GRID );
1353 aFuncMark.MarkToSimple();
1355 else
1357 SCCOL nCol = rViewData.GetCurX();
1358 SCROW nRow = rViewData.GetCurY();
1359 SCTAB nTab = rViewData.GetTabNo();
1361 if ( bRecord )
1363 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1364 pUndoDoc->InitUndo( &rDoc, nTab, nTab );
1365 ScMarkData::iterator itr = aFuncMark.begin(), itrEnd = aFuncMark.end();
1366 for (; itr != itrEnd; ++itr)
1367 if (*itr != nTab)
1368 pUndoDoc->AddUndoTab( *itr, *itr );
1370 ScRange aCopyRange( nCol, nRow, 0, nCol, nRow, nTabCount-1 );
1371 rDoc.CopyToDocument( aCopyRange, IDF_ATTRIB, false, pUndoDoc );
1373 ScRange aMarkRange ( nCol, nRow, nTab );
1374 ScMarkData aUndoMark = aFuncMark;
1375 aUndoMark.SetMultiMarkArea( aMarkRange );
1377 OUString aName = pStyleSheet->GetName();
1378 pDocSh->GetUndoManager()->AddUndoAction(
1379 new ScUndoSelectionStyle( pDocSh, aUndoMark, aMarkRange, aName, pUndoDoc ) );
1382 ScMarkData::iterator itr = aFuncMark.begin(), itrEnd = aFuncMark.end();
1383 for (; itr != itrEnd; ++itr)
1384 rDoc.ApplyStyle( nCol, nRow, *itr, static_cast<ScStyleSheet&>(*pStyleSheet) );
1386 if (!AdjustBlockHeight())
1387 rViewData.GetDocShell()->PostPaintCell( nCol, nRow, nTab );
1391 aModificator.SetDocumentModified();
1393 StartFormatArea();
1396 void ScViewFunc::RemoveStyleSheetInUse( const SfxStyleSheetBase* pStyleSheet )
1398 if ( !pStyleSheet) return;
1400 ScViewData& rViewData = GetViewData();
1401 ScDocument* pDoc = rViewData.GetDocument();
1402 ScDocShell* pDocSh = rViewData.GetDocShell();
1404 ScDocShellModificator aModificator( *pDocSh );
1406 ScopedVclPtrInstance< VirtualDevice > pVirtDev;
1407 pVirtDev->SetMapMode(MAP_PIXEL);
1408 pDoc->StyleSheetChanged( pStyleSheet, true, pVirtDev,
1409 rViewData.GetPPTX(),
1410 rViewData.GetPPTY(),
1411 rViewData.GetZoomX(),
1412 rViewData.GetZoomY() );
1414 pDocSh->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID|PAINT_LEFT );
1415 aModificator.SetDocumentModified();
1417 ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
1418 if (pHdl)
1419 pHdl->ForgetLastPattern();
1422 void ScViewFunc::UpdateStyleSheetInUse( const SfxStyleSheetBase* pStyleSheet )
1424 if ( !pStyleSheet) return;
1426 ScViewData& rViewData = GetViewData();
1427 ScDocument* pDoc = rViewData.GetDocument();
1428 ScDocShell* pDocSh = rViewData.GetDocShell();
1430 ScDocShellModificator aModificator( *pDocSh );
1432 ScopedVclPtrInstance< VirtualDevice > pVirtDev;
1433 pVirtDev->SetMapMode(MAP_PIXEL);
1434 pDoc->StyleSheetChanged( pStyleSheet, false, pVirtDev,
1435 rViewData.GetPPTX(),
1436 rViewData.GetPPTY(),
1437 rViewData.GetZoomX(),
1438 rViewData.GetZoomY() );
1440 pDocSh->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID|PAINT_LEFT );
1441 aModificator.SetDocumentModified();
1443 ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
1444 if (pHdl)
1445 pHdl->ForgetLastPattern();
1448 // insert cells - undo OK
1450 bool ScViewFunc::InsertCells( InsCellCmd eCmd, bool bRecord, bool bPartOfPaste )
1452 ScRange aRange;
1453 if (GetViewData().GetSimpleArea(aRange) == SC_MARK_SIMPLE)
1455 ScDocShell* pDocSh = GetViewData().GetDocShell();
1456 const ScMarkData& rMark = GetViewData().GetMarkData();
1457 bool bSuccess = pDocSh->GetDocFunc().InsertCells( aRange, &rMark, eCmd, bRecord, false, bPartOfPaste );
1458 if (bSuccess)
1460 pDocSh->UpdateOle(&GetViewData());
1461 CellContentChanged();
1462 ResetAutoSpell();
1464 if ( eCmd == INS_INSROWS || eCmd == INS_INSCOLS )
1466 OUString aOperation = ( eCmd == INS_INSROWS) ?
1467 OUString("insert-rows"):
1468 OUString("insert-columns");
1469 HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh, aRange, aOperation);
1472 return bSuccess;
1474 else
1476 ErrorMessage(STR_NOMULTISELECT);
1477 return false;
1481 // delete cells - undo OK
1483 void ScViewFunc::DeleteCells( DelCellCmd eCmd, bool bRecord )
1485 ScRange aRange;
1486 if ( GetViewData().GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
1488 ScDocShell* pDocSh = GetViewData().GetDocShell();
1489 const ScMarkData& rMark = GetViewData().GetMarkData();
1491 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
1492 // #i94841# [Collaboration] if deleting rows is rejected, the content is sometimes wrong
1493 if ( pDocSh->IsDocShared() && ( eCmd == DEL_DELROWS || eCmd == DEL_DELCOLS ) )
1495 ScRange aDelRange( aRange.aStart );
1496 SCCOLROW nCount = 0;
1497 if ( eCmd == DEL_DELROWS )
1499 nCount = sal::static_int_cast< SCCOLROW >( aRange.aEnd.Row() - aRange.aStart.Row() + 1 );
1501 else
1503 nCount = sal::static_int_cast< SCCOLROW >( aRange.aEnd.Col() - aRange.aStart.Col() + 1 );
1505 while ( nCount > 0 )
1507 pDocSh->GetDocFunc().DeleteCells( aDelRange, &rMark, eCmd, bRecord, false );
1508 --nCount;
1511 else
1512 #endif
1514 pDocSh->GetDocFunc().DeleteCells( aRange, &rMark, eCmd, bRecord, false );
1517 pDocSh->UpdateOle(&GetViewData());
1518 CellContentChanged();
1519 ResetAutoSpell();
1521 if ( eCmd == DEL_DELROWS || eCmd == DEL_DELCOLS )
1523 OUString aOperation = ( eCmd == DEL_DELROWS) ?
1524 OUString("delete-rows"):
1525 OUString("delete-columns");
1526 HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh, aRange, aOperation);
1529 // put cursor directly behind deleted range
1530 SCCOL nCurX = GetViewData().GetCurX();
1531 SCROW nCurY = GetViewData().GetCurY();
1532 if ( eCmd==DEL_CELLSLEFT || eCmd==DEL_DELCOLS )
1533 nCurX = aRange.aStart.Col();
1534 else
1535 nCurY = aRange.aStart.Row();
1536 SetCursor( nCurX, nCurY );
1538 else
1540 if (eCmd == DEL_DELCOLS)
1541 DeleteMulti( false, bRecord );
1542 else if (eCmd == DEL_DELROWS)
1543 DeleteMulti( true, bRecord );
1544 else
1545 ErrorMessage(STR_NOMULTISELECT);
1548 Unmark();
1551 void ScViewFunc::DeleteMulti( bool bRows, bool bRecord )
1553 ScDocShell* pDocSh = GetViewData().GetDocShell();
1554 ScDocShellModificator aModificator( *pDocSh );
1555 SCTAB nTab = GetViewData().GetTabNo();
1556 ScDocument& rDoc = pDocSh->GetDocument();
1557 ScMarkData aFuncMark( GetViewData().GetMarkData() ); // local copy for UnmarkFiltered
1558 ScViewUtil::UnmarkFiltered( aFuncMark, &rDoc );
1560 if (!rDoc.IsUndoEnabled())
1561 bRecord = false;
1563 std::vector<sc::ColRowSpan> aSpans;
1564 if (bRows)
1565 aSpans = aFuncMark.GetMarkedRowSpans();
1566 else
1567 aSpans = aFuncMark.GetMarkedColSpans();
1569 if (aSpans.empty())
1571 SCCOLROW nCurPos = bRows ? GetViewData().GetCurY() : GetViewData().GetCurX();
1572 aSpans.push_back(sc::ColRowSpan(nCurPos, nCurPos));
1575 // test if allowed
1577 sal_uInt16 nErrorId = 0;
1578 bool bNeedRefresh = false;
1579 for (size_t i = 0, n = aSpans.size(); i < n && !nErrorId; ++i)
1581 SCCOLROW nStart = aSpans[i].mnStart;
1582 SCCOLROW nEnd = aSpans[i].mnEnd;
1584 SCCOL nStartCol, nEndCol;
1585 SCROW nStartRow, nEndRow;
1586 if ( bRows )
1588 nStartCol = 0;
1589 nEndCol = MAXCOL;
1590 nStartRow = static_cast<SCROW>(nStart);
1591 nEndRow = static_cast<SCROW>(nEnd);
1593 else
1595 nStartCol = static_cast<SCCOL>(nStart);
1596 nEndCol = static_cast<SCCOL>(nEnd);
1597 nStartRow = 0;
1598 nEndRow = MAXROW;
1601 // cell protection (only needed for first range, as all following cells are moved)
1602 if (i == 0)
1604 // test to the end of the sheet
1605 ScEditableTester aTester( &rDoc, nTab, nStartCol, nStartRow, MAXCOL, MAXROW );
1606 if (!aTester.IsEditable())
1607 nErrorId = aTester.GetMessageId();
1610 // merged cells
1611 SCCOL nMergeStartX = nStartCol;
1612 SCROW nMergeStartY = nStartRow;
1613 SCCOL nMergeEndX = nEndCol;
1614 SCROW nMergeEndY = nEndRow;
1615 rDoc.ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, nTab );
1616 rDoc.ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, nTab );
1618 if ( nMergeStartX != nStartCol || nMergeStartY != nStartRow )
1620 // Disallow deleting parts of a merged cell.
1621 // Deleting the start is allowed (merge is removed), so the end doesn't have to be checked.
1623 nErrorId = STR_MSSG_DELETECELLS_0;
1625 if ( nMergeEndX != nEndCol || nMergeEndY != nEndRow )
1627 // detect if the start of a merged cell is deleted, so the merge flags can be refreshed
1629 bNeedRefresh = true;
1633 if ( nErrorId )
1635 ErrorMessage( nErrorId );
1636 return;
1639 // proceed
1641 WaitObject aWait( GetFrameWin() ); // important for TrackFormulas in UpdateReference
1643 ScDocument* pUndoDoc = NULL;
1644 ScRefUndoData* pUndoData = NULL;
1645 if (bRecord)
1647 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1648 pUndoDoc->InitUndo( &rDoc, nTab, nTab, !bRows, bRows ); // row height
1650 for (size_t i = 0, n = aSpans.size(); i < n; ++i)
1652 SCCOLROW nStart = aSpans[i].mnStart;
1653 SCCOLROW nEnd = aSpans[i].mnEnd;
1654 if (bRows)
1655 rDoc.CopyToDocument( 0,nStart,nTab, MAXCOL,nEnd,nTab, IDF_ALL,false,pUndoDoc );
1656 else
1657 rDoc.CopyToDocument( static_cast<SCCOL>(nStart),0,nTab,
1658 static_cast<SCCOL>(nEnd),MAXROW,nTab,
1659 IDF_ALL,false,pUndoDoc );
1662 // all Formulas because of references
1663 SCTAB nTabCount = rDoc.GetTableCount();
1664 pUndoDoc->AddUndoTab( 0, nTabCount-1, false, false );
1665 rDoc.CopyToDocument( 0,0,0, MAXCOL,MAXROW,MAXTAB, IDF_FORMULA,false,pUndoDoc );
1667 pUndoData = new ScRefUndoData( &rDoc );
1669 rDoc.BeginDrawUndo();
1672 std::vector<sc::ColRowSpan>::const_reverse_iterator ri = aSpans.rbegin(), riEnd = aSpans.rend();
1673 for (; ri != riEnd; ++ri)
1675 SCCOLROW nEnd = ri->mnEnd;
1676 SCCOLROW nStart = ri->mnStart;
1678 if (bRows)
1679 rDoc.DeleteRow( 0,nTab, MAXCOL,nTab, nStart, static_cast<SCSIZE>(nEnd-nStart+1) );
1680 else
1681 rDoc.DeleteCol( 0,nTab, MAXROW,nTab, static_cast<SCCOL>(nStart), static_cast<SCSIZE>(nEnd-nStart+1) );
1684 if (bNeedRefresh)
1686 SCCOLROW nFirstStart = aSpans[0].mnStart;
1687 SCCOL nStartCol = bRows ? 0 : static_cast<SCCOL>(nFirstStart);
1688 SCROW nStartRow = bRows ? static_cast<SCROW>(nFirstStart) : 0;
1689 SCCOL nEndCol = MAXCOL;
1690 SCROW nEndRow = MAXROW;
1692 rDoc.RemoveFlagsTab( nStartCol, nStartRow, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
1693 rDoc.ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow, nTab, true );
1696 if (bRecord)
1698 pDocSh->GetUndoManager()->AddUndoAction(
1699 new ScUndoDeleteMulti(
1700 pDocSh, bRows, bNeedRefresh, nTab, aSpans, pUndoDoc, pUndoData));
1703 if (!AdjustRowHeight(0, MAXROW))
1705 if (bRows)
1707 pDocSh->PostPaint(
1708 0, aSpans[0].mnStart, nTab,
1709 MAXCOL, MAXROW, nTab, (PAINT_GRID | PAINT_LEFT));
1711 else
1713 pDocSh->PostPaint(
1714 static_cast<SCCOL>(aSpans[0].mnStart), 0, nTab,
1715 MAXCOL, MAXROW, nTab, (PAINT_GRID | PAINT_TOP));
1719 ResetAutoSpell();
1720 aModificator.SetDocumentModified();
1722 CellContentChanged();
1724 // put cursor directly behind the first deleted range
1725 SCCOL nCurX = GetViewData().GetCurX();
1726 SCROW nCurY = GetViewData().GetCurY();
1727 if ( bRows )
1728 nCurY = aSpans[0].mnStart;
1729 else
1730 nCurX = static_cast<SCCOL>(aSpans[0].mnStart);
1731 SetCursor( nCurX, nCurY );
1733 SfxGetpApp()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
1736 // delete contents
1738 void ScViewFunc::DeleteContents( InsertDeleteFlags nFlags, bool bRecord )
1740 ScViewData& rViewData = GetViewData();
1741 rViewData.SetPasteMode( SC_PASTE_NONE );
1742 rViewData.GetViewShell()->UpdateCopySourceOverlay();
1744 // not editable because of matrix only? attribute OK nonetheless
1745 bool bOnlyNotBecauseOfMatrix;
1746 bool bEditable = SelectionEditable( &bOnlyNotBecauseOfMatrix );
1747 if ( !bEditable )
1749 if ( !(bOnlyNotBecauseOfMatrix &&
1750 ((nFlags & (IDF_ATTRIB | IDF_EDITATTR)) == nFlags)) )
1752 ErrorMessage(bOnlyNotBecauseOfMatrix ? STR_MATRIXFRAGMENTERR : STR_PROTECTIONERR);
1753 return;
1757 ScRange aMarkRange;
1758 bool bSimple = false;
1760 ScDocument* pDoc = GetViewData().GetDocument();
1761 ScDocShell* pDocSh = GetViewData().GetDocShell();
1762 ScMarkData aFuncMark( GetViewData().GetMarkData() ); // local copy for UnmarkFiltered
1763 ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
1765 if (bRecord && !pDoc->IsUndoEnabled())
1766 bRecord = false;
1768 if ( !aFuncMark.IsMarked() && !aFuncMark.IsMultiMarked() )
1770 aMarkRange.aStart.SetCol(GetViewData().GetCurX());
1771 aMarkRange.aStart.SetRow(GetViewData().GetCurY());
1772 aMarkRange.aStart.SetTab(GetViewData().GetTabNo());
1773 aMarkRange.aEnd = aMarkRange.aStart;
1774 if ( pDoc->HasAttrib( aMarkRange, HASATTR_MERGED ) )
1776 aFuncMark.SetMarkArea( aMarkRange );
1778 else
1779 bSimple = true;
1782 HideAllCursors(); // for if summary is cancelled
1784 ScDocFunc& rDocFunc = pDocSh->GetDocFunc();
1785 if (bSimple)
1786 rDocFunc.DeleteCell(aMarkRange.aStart, aFuncMark, nFlags, bRecord, false);
1787 else
1788 rDocFunc.DeleteContents(aFuncMark, nFlags, bRecord, false);
1790 pDocSh->UpdateOle(&GetViewData());
1792 if (ScModelObj *pModelObj = HelperNotifyChanges::getMustPropagateChangesModel(*pDocSh))
1794 ScRangeList aChangeRanges;
1795 if ( bSimple )
1797 aChangeRanges.Append( aMarkRange );
1799 else
1801 aFuncMark.FillRangeListWithMarks( &aChangeRanges, false );
1803 HelperNotifyChanges::Notify(*pModelObj, aChangeRanges);
1806 CellContentChanged();
1807 ShowAllCursors();
1809 if ( nFlags & IDF_ATTRIB )
1811 if ( nFlags & IDF_CONTENTS )
1812 ForgetFormatArea();
1813 else
1814 StartFormatArea(); // delete attribute is also attribute-change
1818 // column width/row height (via header) - undo OK
1820 void ScViewFunc::SetWidthOrHeight(
1821 bool bWidth, const std::vector<sc::ColRowSpan>& rRanges, ScSizeMode eMode,
1822 sal_uInt16 nSizeTwips, bool bRecord, bool bPaint, ScMarkData* pMarkData )
1824 if (rRanges.empty())
1825 return;
1827 // Use view's mark if none specified, but do not modify the original data,
1828 // i.e. no MarkToMulti() on that.
1829 ScMarkData aMarkData( pMarkData ? *pMarkData : GetViewData().GetMarkData());
1831 ScDocShell* pDocSh = GetViewData().GetDocShell();
1832 ScDocument& rDoc = pDocSh->GetDocument();
1833 SCTAB nFirstTab = aMarkData.GetFirstSelected();
1834 SCTAB nCurTab = GetViewData().GetTabNo();
1835 SCTAB nTab;
1836 if (bRecord && !rDoc.IsUndoEnabled())
1837 bRecord = false;
1839 ScDocShellModificator aModificator( *pDocSh );
1841 bool bAllowed = true;
1842 ScMarkData::iterator itr = aMarkData.begin(), itrEnd = aMarkData.end();
1843 for (; itr != itrEnd && bAllowed; ++itr)
1845 for (size_t i = 0, n = rRanges.size(); i < n && bAllowed; ++i)
1847 bool bOnlyMatrix;
1848 if (bWidth)
1850 bAllowed = rDoc.IsBlockEditable(
1851 *itr, rRanges[i].mnStart, 0, rRanges[i].mnEnd, MAXROW,
1852 &bOnlyMatrix ) || bOnlyMatrix;
1854 else
1856 bAllowed = rDoc.IsBlockEditable(
1857 *itr, 0, rRanges[i].mnStart, MAXCOL,rRanges[i].mnEnd, &bOnlyMatrix) || bOnlyMatrix;
1862 // Allow users to resize cols/rows in readonly docs despite the r/o state.
1863 // It is frustrating to be unable to see content in mis-sized cells.
1864 if( !bAllowed && !pDocSh->IsReadOnly() )
1866 ErrorMessage(STR_PROTECTIONERR);
1867 return;
1870 SCCOLROW nStart = rRanges[0].mnStart;
1871 SCCOLROW nEnd = rRanges[0].mnEnd;
1873 bool bFormula = false;
1874 if ( eMode == SC_SIZE_OPTIMAL )
1876 const ScViewOptions& rOpts = GetViewData().GetOptions();
1877 bFormula = rOpts.GetOption( VOPT_FORMULAS );
1880 ScDocument* pUndoDoc = NULL;
1881 ScOutlineTable* pUndoTab = NULL;
1882 std::vector<sc::ColRowSpan> aUndoRanges;
1884 if ( bRecord )
1886 rDoc.BeginDrawUndo(); // Drawing Updates
1888 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1889 itr = aMarkData.begin();
1890 for (; itr != itrEnd; ++itr)
1892 if (bWidth)
1894 if ( *itr == nFirstTab )
1895 pUndoDoc->InitUndo( &rDoc, *itr, *itr, true, false );
1896 else
1897 pUndoDoc->AddUndoTab( *itr, *itr, true, false );
1898 rDoc.CopyToDocument( static_cast<SCCOL>(nStart), 0, *itr,
1899 static_cast<SCCOL>(nEnd), MAXROW, *itr, IDF_NONE,
1900 false, pUndoDoc );
1902 else
1904 if ( *itr == nFirstTab )
1905 pUndoDoc->InitUndo( &rDoc, *itr, *itr, false, true );
1906 else
1907 pUndoDoc->AddUndoTab( *itr, *itr, false, true );
1908 rDoc.CopyToDocument( 0, nStart, *itr, MAXCOL, nEnd, *itr, IDF_NONE, false, pUndoDoc );
1912 aUndoRanges = rRanges;
1914 //! outlines from all tab?
1915 ScOutlineTable* pTable = rDoc.GetOutlineTable( nCurTab );
1916 if (pTable)
1917 pUndoTab = new ScOutlineTable( *pTable );
1920 if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
1921 aMarkData.MarkToMulti();
1923 bool bShow = nSizeTwips > 0 || eMode != SC_SIZE_DIRECT;
1924 bool bOutline = false;
1926 itr = aMarkData.begin();
1927 for (; itr != itrEnd; ++itr)
1929 nTab = *itr;
1931 for (size_t i = 0, n = rRanges.size(); i < n; ++i)
1933 SCCOLROW nStartNo = rRanges[i].mnStart;
1934 SCCOLROW nEndNo = rRanges[i].mnEnd;
1936 if ( !bWidth ) // height always blockwise
1938 if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
1940 bool bAll = ( eMode==SC_SIZE_OPTIMAL );
1941 if (!bAll)
1943 // delete CR_MANUALSIZE for all in range,
1944 // then SetOptimalHeight with bShrink = FALSE
1945 for (SCROW nRow = nStartNo; nRow <= nEndNo; ++nRow)
1947 SCROW nLastRow = nRow;
1948 if (rDoc.RowHidden(nRow, nTab, NULL, &nLastRow))
1950 nRow = nLastRow;
1951 continue;
1954 sal_uInt8 nOld = rDoc.GetRowFlags(nRow, nTab);
1955 if (nOld & CR_MANUALSIZE)
1956 rDoc.SetRowFlags(nRow, nTab, nOld & ~CR_MANUALSIZE);
1960 double nPPTX = GetViewData().GetPPTX();
1961 double nPPTY = GetViewData().GetPPTY();
1962 Fraction aZoomX = GetViewData().GetZoomX();
1963 Fraction aZoomY = GetViewData().GetZoomY();
1965 ScSizeDeviceProvider aProv(pDocSh);
1966 if (aProv.IsPrinter())
1968 nPPTX = aProv.GetPPTX();
1969 nPPTY = aProv.GetPPTY();
1970 aZoomX = aZoomY = Fraction( 1, 1 );
1973 sc::RowHeightContext aCxt(nPPTX, nPPTY, aZoomX, aZoomY, aProv.GetDevice());
1974 aCxt.setForceAutoSize(bAll);
1975 aCxt.setExtraHeight(nSizeTwips);
1976 rDoc.SetOptimalHeight(aCxt, nStartNo, nEndNo, nTab);
1977 if (bAll)
1978 rDoc.ShowRows( nStartNo, nEndNo, nTab, true );
1980 // Manual-Flag already (re)set in SetOptimalHeight in case of bAll=sal_True
1981 // (set for Extra-Height, else reset).
1983 else if ( eMode==SC_SIZE_DIRECT )
1985 if (nSizeTwips)
1987 rDoc.SetRowHeightRange( nStartNo, nEndNo, nTab, nSizeTwips );
1988 rDoc.SetManualHeight( nStartNo, nEndNo, nTab, true ); // height was set manually
1990 rDoc.ShowRows( nStartNo, nEndNo, nTab, nSizeTwips != 0 );
1992 else if ( eMode==SC_SIZE_SHOW )
1994 rDoc.ShowRows( nStartNo, nEndNo, nTab, true );
1997 else // column width
1999 for (SCCOL nCol=static_cast<SCCOL>(nStartNo); nCol<=static_cast<SCCOL>(nEndNo); nCol++)
2001 if ( eMode != SC_SIZE_VISOPT || !rDoc.ColHidden(nCol, nTab) )
2003 sal_uInt16 nThisSize = nSizeTwips;
2005 if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
2006 nThisSize = nSizeTwips + GetOptimalColWidth( nCol, nTab, bFormula );
2007 if ( nThisSize )
2008 rDoc.SetColWidth( nCol, nTab, nThisSize );
2010 rDoc.ShowCol( nCol, nTab, bShow );
2015 // adjust outline
2017 if (bWidth)
2019 if ( rDoc.UpdateOutlineCol( static_cast<SCCOL>(nStartNo),
2020 static_cast<SCCOL>(nEndNo), nTab, bShow ) )
2021 bOutline = true;
2023 else
2025 if ( rDoc.UpdateOutlineRow( nStartNo, nEndNo, nTab, bShow ) )
2026 bOutline = true;
2029 rDoc.SetDrawPageSize(nTab);
2032 if (!bOutline)
2033 DELETEZ(pUndoTab);
2035 if (bRecord)
2037 pDocSh->GetUndoManager()->AddUndoAction(
2038 new ScUndoWidthOrHeight(
2039 pDocSh, aMarkData, nStart, nCurTab, nEnd, nCurTab,
2040 pUndoDoc, aUndoRanges, pUndoTab, eMode, nSizeTwips, bWidth));
2043 // fdo#36247 Ensure that the drawing layer's map mode scaling factors match
2044 // the new heights and widths.
2045 GetViewData().GetView()->RefreshZoom();
2047 itr = aMarkData.begin();
2048 for (; itr != itrEnd; ++itr)
2049 rDoc.UpdatePageBreaks( *itr );
2051 GetViewData().GetView()->UpdateScrollBars();
2053 if (bPaint)
2055 itr = aMarkData.begin();
2056 for (; itr != itrEnd; ++itr)
2058 nTab = *itr;
2059 if (bWidth)
2061 if (rDoc.HasAttrib( static_cast<SCCOL>(nStart),0,nTab,
2062 static_cast<SCCOL>(nEnd),MAXROW,nTab,
2063 HASATTR_MERGED | HASATTR_OVERLAPPED ))
2064 nStart = 0;
2065 if (nStart > 0) // go upwards because of Lines and cursor
2066 --nStart;
2067 pDocSh->PostPaint( static_cast<SCCOL>(nStart), 0, nTab,
2068 MAXCOL, MAXROW, nTab, PAINT_GRID | PAINT_TOP );
2070 else
2072 if (rDoc.HasAttrib( 0,nStart,nTab, MAXCOL,nEnd,nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ))
2073 nStart = 0;
2074 if (nStart != 0)
2075 --nStart;
2076 pDocSh->PostPaint( 0, nStart, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID | PAINT_LEFT );
2080 pDocSh->UpdateOle(&GetViewData());
2081 if( !pDocSh->IsReadOnly() )
2082 aModificator.SetDocumentModified();
2085 if ( bWidth )
2087 if (ScModelObj* pModelObj = HelperNotifyChanges::getMustPropagateChangesModel(*pDocSh))
2089 ScRangeList aChangeRanges;
2090 itr = aMarkData.begin();
2091 for (; itr != itrEnd; ++itr)
2093 nTab = *itr;
2094 for (size_t i = 0, n = rRanges.size(); i < n; ++i)
2096 SCCOL nStartCol = rRanges[i].mnStart;
2097 SCCOL nEndCol = rRanges[i].mnEnd;
2098 for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol )
2100 aChangeRanges.Append( ScRange( nCol, 0, nTab ) );
2104 HelperNotifyChanges::Notify(*pModelObj, aChangeRanges, "column-resize");
2109 // column width/row height (via marked range)
2111 void ScViewFunc::SetMarkedWidthOrHeight( bool bWidth, ScSizeMode eMode, sal_uInt16 nSizeTwips,
2112 bool bRecord, bool bPaint )
2114 ScMarkData& rMark = GetViewData().GetMarkData();
2116 rMark.MarkToMulti();
2117 if (!rMark.IsMultiMarked())
2119 SCCOL nCol = GetViewData().GetCurX();
2120 SCROW nRow = GetViewData().GetCurY();
2121 SCTAB nTab = GetViewData().GetTabNo();
2122 DoneBlockMode();
2123 InitOwnBlockMode();
2124 rMark.SetMultiMarkArea( ScRange( nCol,nRow,nTab ), true );
2125 MarkDataChanged();
2128 std::vector<sc::ColRowSpan> aRanges =
2129 bWidth ? rMark.GetMarkedColSpans() : rMark.GetMarkedRowSpans();
2131 SetWidthOrHeight(bWidth, aRanges, eMode, nSizeTwips, bRecord, bPaint);
2133 rMark.MarkToSimple();
2136 void ScViewFunc::ModifyCellSize( ScDirection eDir, bool bOptimal )
2138 //! step size adjustable
2139 // step size is also minimum
2140 sal_uInt16 nStepX = STD_COL_WIDTH / 5;
2141 sal_uInt16 nStepY = ScGlobal::nStdRowHeight;
2143 ScModule* pScMod = SC_MOD();
2144 bool bAnyEdit = pScMod->IsInputMode();
2145 SCCOL nCol = GetViewData().GetCurX();
2146 SCROW nRow = GetViewData().GetCurY();
2147 SCTAB nTab = GetViewData().GetTabNo();
2148 ScDocShell* pDocSh = GetViewData().GetDocShell();
2149 ScDocument& rDoc = pDocSh->GetDocument();
2151 bool bAllowed, bOnlyMatrix;
2152 if ( eDir == DIR_LEFT || eDir == DIR_RIGHT )
2153 bAllowed = rDoc.IsBlockEditable( nTab, nCol,0, nCol,MAXROW, &bOnlyMatrix );
2154 else
2155 bAllowed = rDoc.IsBlockEditable( nTab, 0,nRow, MAXCOL,nRow, &bOnlyMatrix );
2156 if ( !bAllowed && !bOnlyMatrix )
2158 ErrorMessage(STR_PROTECTIONERR);
2159 return;
2162 HideAllCursors();
2164 sal_uInt16 nWidth = rDoc.GetColWidth( nCol, nTab );
2165 sal_uInt16 nHeight = rDoc.GetRowHeight( nRow, nTab );
2166 std::vector<sc::ColRowSpan> aRange(1, sc::ColRowSpan(0,0));
2167 if ( eDir == DIR_LEFT || eDir == DIR_RIGHT )
2169 if (bOptimal) // width of this single cell
2171 if ( bAnyEdit )
2173 // when editing the actual entered width
2174 ScInputHandler* pHdl = pScMod->GetInputHdl( GetViewData().GetViewShell() );
2175 if (pHdl)
2177 long nEdit = pHdl->GetTextSize().Width(); // in 0.01 mm
2179 const ScPatternAttr* pPattern = rDoc.GetPattern( nCol, nRow, nTab );
2180 const SvxMarginItem& rMItem =
2181 static_cast<const SvxMarginItem&>(pPattern->GetItem(ATTR_MARGIN));
2182 sal_uInt16 nMargin = rMItem.GetLeftMargin() + rMItem.GetRightMargin();
2183 if ( static_cast<const SvxHorJustifyItem&>( pPattern->
2184 GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_LEFT )
2185 nMargin = sal::static_int_cast<sal_uInt16>(
2186 nMargin + static_cast<const SfxUInt16Item&>(pPattern->GetItem(ATTR_INDENT)).GetValue() );
2188 nWidth = (sal_uInt16)(nEdit * pDocSh->GetOutputFactor() / HMM_PER_TWIPS)
2189 + nMargin + STD_EXTRA_WIDTH;
2192 else
2194 double nPPTX = GetViewData().GetPPTX();
2195 double nPPTY = GetViewData().GetPPTY();
2196 Fraction aZoomX = GetViewData().GetZoomX();
2197 Fraction aZoomY = GetViewData().GetZoomY();
2199 ScSizeDeviceProvider aProv(pDocSh);
2200 if (aProv.IsPrinter())
2202 nPPTX = aProv.GetPPTX();
2203 nPPTY = aProv.GetPPTY();
2204 aZoomX = aZoomY = Fraction( 1, 1 );
2207 long nPixel = rDoc.GetNeededSize( nCol, nRow, nTab, aProv.GetDevice(),
2208 nPPTX, nPPTY, aZoomX, aZoomY, true );
2209 sal_uInt16 nTwips = (sal_uInt16)( nPixel / nPPTX );
2210 if (nTwips != 0)
2211 nWidth = nTwips + STD_EXTRA_WIDTH;
2212 else
2213 nWidth = STD_COL_WIDTH;
2216 else // increment / decrement
2218 if ( eDir == DIR_RIGHT )
2219 nWidth = sal::static_int_cast<sal_uInt16>( nWidth + nStepX );
2220 else if ( nWidth > nStepX )
2221 nWidth = sal::static_int_cast<sal_uInt16>( nWidth - nStepX );
2222 if ( nWidth < nStepX ) nWidth = nStepX;
2223 if ( nWidth > MAX_COL_WIDTH ) nWidth = MAX_COL_WIDTH;
2225 aRange[0].mnStart = nCol;
2226 aRange[0].mnEnd = nCol;
2227 SetWidthOrHeight(true, aRange, SC_SIZE_DIRECT, nWidth);
2229 // adjust height of this row if width demands/allows this
2231 if (!bAnyEdit)
2233 const ScPatternAttr* pPattern = rDoc.GetPattern( nCol, nRow, nTab );
2234 bool bNeedHeight =
2235 static_cast<const SfxBoolItem&>(pPattern->GetItem( ATTR_LINEBREAK )).GetValue() ||
2236 static_cast<const SvxHorJustifyItem&>(pPattern->
2237 GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_BLOCK;
2238 if (bNeedHeight)
2239 AdjustRowHeight( nRow, nRow );
2242 else
2244 ScSizeMode eMode;
2245 if (bOptimal)
2247 eMode = SC_SIZE_OPTIMAL;
2248 nHeight = 0;
2250 else
2252 eMode = SC_SIZE_DIRECT;
2253 if ( eDir == DIR_BOTTOM )
2254 nHeight = sal::static_int_cast<sal_uInt16>( nHeight + nStepY );
2255 else if ( nHeight > nStepY )
2256 nHeight = sal::static_int_cast<sal_uInt16>( nHeight - nStepY );
2257 if ( nHeight < nStepY ) nHeight = nStepY;
2258 if ( nHeight > MAX_ROW_HEIGHT ) nHeight = MAX_ROW_HEIGHT;
2260 aRange[0].mnStart = nRow;
2261 aRange[0].mnEnd = nRow;
2262 SetWidthOrHeight(false, aRange, eMode, nHeight);
2265 if ( bAnyEdit )
2267 UpdateEditView();
2268 if ( rDoc.HasAttrib( nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_NEEDHEIGHT ) )
2270 ScInputHandler* pHdl = pScMod->GetInputHdl( GetViewData().GetViewShell() );
2271 if (pHdl)
2272 pHdl->SetModified(); // so that the height is adjusted with Enter
2276 ShowAllCursors();
2279 void ScViewFunc::ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect )
2281 if (nTab == TABLEID_DOC)
2282 return;
2284 ScMarkData& rMark = GetViewData().GetMarkData();
2285 ScDocShell* pDocSh = GetViewData().GetDocShell();
2286 ScDocument& rDoc = pDocSh->GetDocument();
2287 ScDocFunc &rFunc = pDocSh->GetDocFunc();
2288 bool bUndo(rDoc.IsUndoEnabled());
2290 // modifying several tabs is handled here
2292 if (bUndo)
2294 OUString aUndo = ScGlobal::GetRscString( STR_UNDO_PROTECT_TAB );
2295 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
2298 ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
2299 for (; itr != itrEnd; ++itr)
2300 rFunc.ProtectSheet(*itr, rProtect);
2302 if (bUndo)
2303 pDocSh->GetUndoManager()->LeaveListAction();
2305 UpdateLayerLocks(); //! broadcast to all views
2308 void ScViewFunc::Protect( SCTAB nTab, const OUString& rPassword )
2310 ScMarkData& rMark = GetViewData().GetMarkData();
2311 ScDocShell* pDocSh = GetViewData().GetDocShell();
2312 ScDocument& rDoc = pDocSh->GetDocument();
2313 ScDocFunc &rFunc = pDocSh->GetDocFunc();
2314 bool bUndo(rDoc.IsUndoEnabled());
2316 if ( nTab == TABLEID_DOC || rMark.GetSelectCount() <= 1 )
2317 rFunc.Protect( nTab, rPassword, false );
2318 else
2320 // modifying several tabs is handled here
2322 if (bUndo)
2324 OUString aUndo = ScGlobal::GetRscString( STR_UNDO_PROTECT_TAB );
2325 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
2328 ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
2329 for (; itr != itrEnd; ++itr)
2330 rFunc.Protect( *itr, rPassword, false );
2332 if (bUndo)
2333 pDocSh->GetUndoManager()->LeaveListAction();
2336 UpdateLayerLocks(); //! broadcast to all views
2339 bool ScViewFunc::Unprotect( SCTAB nTab, const OUString& rPassword )
2341 ScMarkData& rMark = GetViewData().GetMarkData();
2342 ScDocShell* pDocSh = GetViewData().GetDocShell();
2343 ScDocument& rDoc = pDocSh->GetDocument();
2344 ScDocFunc &rFunc = pDocSh->GetDocFunc();
2345 bool bChanged = false;
2346 bool bUndo (rDoc.IsUndoEnabled());
2348 if ( nTab == TABLEID_DOC || rMark.GetSelectCount() <= 1 )
2349 bChanged = rFunc.Unprotect( nTab, rPassword, false );
2350 else
2352 // modifying several tabs is handled here
2354 if (bUndo)
2356 OUString aUndo = ScGlobal::GetRscString( STR_UNDO_UNPROTECT_TAB );
2357 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
2360 ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
2361 for (; itr != itrEnd; ++itr)
2362 if ( rFunc.Unprotect( *itr, rPassword, false ) )
2363 bChanged = true;
2365 if (bUndo)
2366 pDocSh->GetUndoManager()->LeaveListAction();
2369 if (bChanged)
2370 UpdateLayerLocks(); //! broadcast to all views
2372 return bChanged;
2375 void ScViewFunc::SetNoteText( const ScAddress& rPos, const OUString& rNoteText )
2377 GetViewData().GetDocShell()->GetDocFunc().SetNoteText( rPos, rNoteText, false );
2380 void ScViewFunc::ReplaceNote( const ScAddress& rPos, const OUString& rNoteText, const OUString* pAuthor, const OUString* pDate )
2382 GetViewData().GetDocShell()->GetDocFunc().ReplaceNote( rPos, rNoteText, pAuthor, pDate, false );
2385 void ScViewFunc::SetNumberFormat( short nFormatType, sal_uLong nAdd )
2387 // not editable because of matrix only? attribute OK nonetheless
2388 bool bOnlyNotBecauseOfMatrix;
2389 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
2391 ErrorMessage(STR_PROTECTIONERR);
2392 return;
2395 sal_uInt32 nNumberFormat = 0;
2396 ScViewData& rViewData = GetViewData();
2397 ScDocument* pDoc = rViewData.GetDocument();
2398 SvNumberFormatter* pNumberFormatter = pDoc->GetFormatTable();
2399 LanguageType eLanguage = ScGlobal::eLnge;
2400 ScPatternAttr aNewAttrs( pDoc->GetPool() );
2402 // always take language from cursor position, even if there is a selection
2404 sal_uInt32 nCurrentNumberFormat;
2405 pDoc->GetNumberFormat( rViewData.GetCurX(),
2406 rViewData.GetCurY(),
2407 rViewData.GetTabNo(),
2408 nCurrentNumberFormat );
2409 const SvNumberformat* pEntry = pNumberFormatter->GetEntry( nCurrentNumberFormat );
2410 if (pEntry)
2411 eLanguage = pEntry->GetLanguage(); // else keep ScGlobal::eLnge
2413 nNumberFormat = pNumberFormatter->GetStandardFormat( nFormatType, eLanguage ) + nAdd;
2415 SfxItemSet& rSet = aNewAttrs.GetItemSet();
2416 rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNumberFormat ) );
2417 // ATTR_LANGUAGE_FORMAT not
2418 ApplySelectionPattern( aNewAttrs, true );
2421 void ScViewFunc::SetNumFmtByStr( const OUString& rCode )
2423 // not editable because of matrix only? attribute OK nonetheless
2424 bool bOnlyNotBecauseOfMatrix;
2425 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
2427 ErrorMessage(STR_PROTECTIONERR);
2428 return;
2431 ScViewData& rViewData = GetViewData();
2432 ScDocument* pDoc = rViewData.GetDocument();
2433 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
2435 // language always from cursor position
2437 sal_uInt32 nCurrentNumberFormat;
2438 pDoc->GetNumberFormat( rViewData.GetCurX(), rViewData.GetCurY(),
2439 rViewData.GetTabNo(), nCurrentNumberFormat );
2440 const SvNumberformat* pEntry = pFormatter->GetEntry( nCurrentNumberFormat );
2441 LanguageType eLanguage = pEntry ? pEntry->GetLanguage() : ScGlobal::eLnge;
2443 // determine index for String
2445 bool bOk = true;
2446 sal_uInt32 nNumberFormat = pFormatter->GetEntryKey( rCode, eLanguage );
2447 if ( nNumberFormat == NUMBERFORMAT_ENTRY_NOT_FOUND )
2449 // enter new
2451 OUString aFormat = rCode; // will be changed
2452 sal_Int32 nErrPos = 0;
2453 short nType = 0; //! ???
2454 bOk = pFormatter->PutEntry( aFormat, nErrPos, nType, nNumberFormat, eLanguage );
2457 if ( bOk ) // valid format?
2459 ScPatternAttr aNewAttrs( pDoc->GetPool() );
2460 SfxItemSet& rSet = aNewAttrs.GetItemSet();
2461 rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNumberFormat ) );
2462 rSet.Put( SvxLanguageItem( eLanguage, ATTR_LANGUAGE_FORMAT ) );
2463 ApplySelectionPattern( aNewAttrs, true );
2466 //! else return error / issue warning ???
2469 void ScViewFunc::ChangeNumFmtDecimals( bool bIncrement )
2471 // not editable because of matrix only? attribute OK nonetheless
2472 bool bOnlyNotBecauseOfMatrix;
2473 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
2475 ErrorMessage(STR_PROTECTIONERR);
2476 return;
2479 ScDocument* pDoc = GetViewData().GetDocument();
2480 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
2482 SCCOL nCol = GetViewData().GetCurX();
2483 SCROW nRow = GetViewData().GetCurY();
2484 SCTAB nTab = GetViewData().GetTabNo();
2486 sal_uInt32 nOldFormat;
2487 pDoc->GetNumberFormat( nCol, nRow, nTab, nOldFormat );
2488 const SvNumberformat* pOldEntry = pFormatter->GetEntry( nOldFormat );
2489 if (!pOldEntry)
2491 OSL_FAIL("numberformat not found !!!");
2492 return;
2495 // what have we got here?
2497 sal_uInt32 nNewFormat = nOldFormat;
2498 bool bError = false;
2500 LanguageType eLanguage = pOldEntry->GetLanguage();
2501 bool bThousand, bNegRed;
2502 sal_uInt16 nPrecision, nLeading;
2503 pOldEntry->GetFormatSpecialInfo( bThousand, bNegRed, nPrecision, nLeading );
2505 short nOldType = pOldEntry->GetType();
2506 if ( 0 == ( nOldType & (
2507 css::util::NumberFormat::NUMBER | css::util::NumberFormat::CURRENCY | css::util::NumberFormat::PERCENT | css::util::NumberFormat::SCIENTIFIC ) ) )
2509 // date, time, fraction, logical, text can not be changed
2510 bError = true;
2513 //! SvNumberformat has a Member bStandard, but doesn't disclose it
2514 bool bWasStandard = ( nOldFormat == pFormatter->GetStandardIndex( eLanguage ) );
2515 OUString sExponentialStandardFormat = "";
2516 if (bWasStandard)
2518 // with "Standard" the decimal places depend on cell content
2519 // 0 if empty or text -> no decimal places
2520 double nVal = pDoc->GetValue( ScAddress( nCol, nRow, nTab ) );
2522 // the ways of the Numberformatters are unfathomable, so try:
2523 OUString aOut;
2524 Color* pCol;
2525 const_cast<SvNumberformat*>(pOldEntry)->GetOutputString( nVal, aOut, &pCol );
2527 nPrecision = 0;
2528 // 'E' for exponential is fixed in Numberformatter
2529 sal_Int32 nIndexE = aOut.indexOf((sal_Unicode)'E');
2530 if ( nIndexE >= 0 )
2532 sExponentialStandardFormat = aOut.copy( nIndexE ).replace( '-', '+' );
2533 for ( sal_Int32 i=1 ; i<sExponentialStandardFormat.getLength() ; i++ )
2535 if ( sExponentialStandardFormat[i] >= '1' && sExponentialStandardFormat[i] <= '9' )
2536 sExponentialStandardFormat = sExponentialStandardFormat.replaceAt( i, 1, OUString( "0" ) );
2538 aOut = aOut.copy( 0, nIndexE ); // remove exponential part
2540 OUString aDecSep( pFormatter->GetFormatDecimalSep( nOldFormat ) );
2541 sal_Int32 nPos = aOut.indexOf( aDecSep );
2542 if ( nPos >= 0 )
2543 nPrecision = aOut.getLength() - nPos - aDecSep.getLength();
2544 // else keep 0
2546 else
2548 if ( (nOldType & css::util::NumberFormat::SCIENTIFIC) && !bThousand &&
2549 (pOldEntry->GetFormatIntegerDigits()%3 == 0) && pOldEntry->GetFormatIntegerDigits() > 0 )
2550 bThousand = true;
2553 if (!bError)
2555 if (bIncrement)
2557 if (nPrecision<20)
2558 ++nPrecision; // increment
2559 else
2560 bError = true; // 20 is maximum
2562 else
2564 if (nPrecision)
2565 --nPrecision; // decrement
2566 else
2567 bError = true; // 0 is minimum
2571 if (!bError)
2573 OUString aNewPicture = pFormatter->GenerateFormat(nOldFormat, eLanguage,
2574 bThousand, bNegRed,
2575 nPrecision, nLeading)
2576 + sExponentialStandardFormat;
2578 nNewFormat = pFormatter->GetEntryKey( aNewPicture, eLanguage );
2579 if ( nNewFormat == NUMBERFORMAT_ENTRY_NOT_FOUND )
2581 sal_Int32 nErrPos = 0;
2582 short nNewType = 0;
2583 bool bOk = pFormatter->PutEntry( aNewPicture, nErrPos,
2584 nNewType, nNewFormat, eLanguage );
2585 OSL_ENSURE( bOk, "incorrect numberformat generated" );
2586 if (!bOk)
2587 bError = true;
2591 if (!bError)
2593 ScPatternAttr aNewAttrs( pDoc->GetPool() );
2594 SfxItemSet& rSet = aNewAttrs.GetItemSet();
2595 rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat ) );
2596 // ATTR_LANGUAGE_FORMAT not
2597 ApplySelectionPattern( aNewAttrs, true );
2601 void ScViewFunc::ChangeIndent( bool bIncrement )
2603 ScViewData& rViewData = GetViewData();
2604 ScDocShell* pDocSh = rViewData.GetDocShell();
2605 ScMarkData& rMark = rViewData.GetMarkData();
2607 ScMarkData aWorkMark = rMark;
2608 ScViewUtil::UnmarkFiltered( aWorkMark, &pDocSh->GetDocument() );
2609 aWorkMark.MarkToMulti();
2610 if (!aWorkMark.IsMultiMarked())
2612 SCCOL nCol = rViewData.GetCurX();
2613 SCROW nRow = rViewData.GetCurY();
2614 SCTAB nTab = rViewData.GetTabNo();
2615 aWorkMark.SetMultiMarkArea( ScRange(nCol,nRow,nTab) );
2618 bool bSuccess = pDocSh->GetDocFunc().ChangeIndent( aWorkMark, bIncrement, false );
2619 if (bSuccess)
2621 pDocSh->UpdateOle(&rViewData);
2622 StartFormatArea();
2624 // stuff for sidebar panels
2625 SfxBindings& rBindings = GetViewData().GetBindings();
2626 rBindings.Invalidate( SID_H_ALIGNCELL );
2627 rBindings.Invalidate( SID_ATTR_ALIGN_INDENT );
2631 bool ScViewFunc::InsertName( const OUString& rName, const OUString& rSymbol,
2632 const OUString& rType )
2634 // Type = P,R,C,F (and combinations)
2635 //! undo...
2637 bool bOk = false;
2638 ScDocShell* pDocSh = GetViewData().GetDocShell();
2639 ScDocument& rDoc = pDocSh->GetDocument();
2640 SCTAB nTab = GetViewData().GetTabNo();
2641 ScRangeName* pList = rDoc.GetRangeName();
2643 RangeType nType = RT_NAME;
2644 ScRangeData* pNewEntry = new ScRangeData( &rDoc, rName, rSymbol,
2645 ScAddress( GetViewData().GetCurX(), GetViewData().GetCurY(),
2646 nTab), nType );
2647 OUString aUpType = rType.toAsciiUpperCase();
2648 if ( aUpType.indexOf( 'P' ) != -1 )
2649 nType |= RT_PRINTAREA;
2650 if ( aUpType.indexOf( 'R' ) != -1 )
2651 nType |= RT_ROWHEADER;
2652 if ( aUpType.indexOf( 'C' ) != -1 )
2653 nType |= RT_COLHEADER;
2654 if ( aUpType.indexOf( 'F' ) != -1 )
2655 nType |= RT_CRITERIA;
2656 pNewEntry->AddType(nType);
2658 if ( !pNewEntry->GetErrCode() ) // text valid?
2660 ScDocShellModificator aModificator( *pDocSh );
2662 rDoc.PreprocessRangeNameUpdate();
2664 // input available yet? Then remove beforehand (=change)
2665 ScRangeData* pData = pList->findByUpperName(ScGlobal::pCharClass->uppercase(rName));
2666 if (pData)
2667 { // take old Index
2668 pNewEntry->SetIndex(pData->GetIndex());
2669 pList->erase(*pData);
2672 if ( pList->insert( pNewEntry ) )
2673 bOk = true;
2674 pNewEntry = NULL; // never delete, insert took ownership
2676 rDoc.CompileHybridFormula();
2678 aModificator.SetDocumentModified();
2679 SfxGetpApp()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
2682 delete pNewEntry; // if it wasn't inserted
2683 return bOk;
2686 void ScViewFunc::CreateNames( sal_uInt16 nFlags )
2688 bool bDone = false;
2689 ScRange aRange;
2690 if ( GetViewData().GetSimpleArea(aRange) == SC_MARK_SIMPLE )
2691 bDone = GetViewData().GetDocShell()->GetDocFunc().CreateNames( aRange, nFlags, false );
2693 if (!bDone)
2694 ErrorMessage(STR_CREATENAME_MARKERR);
2697 sal_uInt16 ScViewFunc::GetCreateNameFlags()
2699 sal_uInt16 nFlags = 0;
2701 SCCOL nStartCol, nEndCol;
2702 SCROW nStartRow, nEndRow;
2703 SCTAB nDummy;
2704 if (GetViewData().GetSimpleArea(nStartCol,nStartRow,nDummy,nEndCol,nEndRow,nDummy) == SC_MARK_SIMPLE)
2706 ScDocument* pDoc = GetViewData().GetDocument();
2707 SCTAB nTab = GetViewData().GetTabNo();
2708 bool bOk;
2709 SCCOL i;
2710 SCROW j;
2712 bOk = true;
2713 SCCOL nFirstCol = nStartCol;
2714 SCCOL nLastCol = nEndCol;
2715 if (nStartCol+1 < nEndCol) { ++nFirstCol; --nLastCol; }
2716 for (i=nFirstCol; i<=nLastCol && bOk; i++)
2717 if (!pDoc->HasStringData( i,nStartRow,nTab ))
2718 bOk = false;
2719 if (bOk)
2720 nFlags |= NAME_TOP;
2721 else // Bottom only if not Top
2723 bOk = true;
2724 for (i=nFirstCol; i<=nLastCol && bOk; i++)
2725 if (!pDoc->HasStringData( i,nEndRow,nTab ))
2726 bOk = false;
2727 if (bOk)
2728 nFlags |= NAME_BOTTOM;
2731 bOk = true;
2732 SCROW nFirstRow = nStartRow;
2733 SCROW nLastRow = nEndRow;
2734 if (nStartRow+1 < nEndRow) { ++nFirstRow; --nLastRow; }
2735 for (j=nFirstRow; j<=nLastRow && bOk; j++)
2736 if (!pDoc->HasStringData( nStartCol,j,nTab ))
2737 bOk = false;
2738 if (bOk)
2739 nFlags |= NAME_LEFT;
2740 else // Right only if not Left
2742 bOk = true;
2743 for (j=nFirstRow; j<=nLastRow && bOk; j++)
2744 if (!pDoc->HasStringData( nEndCol,j,nTab ))
2745 bOk = false;
2746 if (bOk)
2747 nFlags |= NAME_RIGHT;
2751 if (nStartCol == nEndCol)
2752 nFlags &= ~( NAME_LEFT | NAME_RIGHT );
2753 if (nStartRow == nEndRow)
2754 nFlags &= ~( NAME_TOP | NAME_BOTTOM );
2756 return nFlags;
2759 void ScViewFunc::InsertNameList()
2761 ScAddress aPos( GetViewData().GetCurX(), GetViewData().GetCurY(), GetViewData().GetTabNo() );
2762 ScDocShell* pDocSh = GetViewData().GetDocShell();
2763 if ( pDocSh->GetDocFunc().InsertNameList( aPos, false ) )
2764 pDocSh->UpdateOle(&GetViewData());
2767 void ScViewFunc::UpdateSelectionArea( const ScMarkData& rSel, ScPatternAttr* pAttr )
2769 ScDocShell* pDocShell = GetViewData().GetDocShell();
2770 ScRange aMarkRange;
2771 if (rSel.IsMultiMarked() )
2772 rSel.GetMultiMarkArea( aMarkRange );
2773 else
2774 rSel.GetMarkArea( aMarkRange );
2776 bool bSetLines = false;
2777 bool bSetAlign = false;
2778 if ( pAttr )
2780 const SfxItemSet& rNewSet = pAttr->GetItemSet();
2781 bSetLines = rNewSet.GetItemState( ATTR_BORDER, true ) == SfxItemState::SET ||
2782 rNewSet.GetItemState( ATTR_SHADOW, true ) == SfxItemState::SET;
2783 bSetAlign = rNewSet.GetItemState( ATTR_HOR_JUSTIFY, true ) == SfxItemState::SET;
2786 sal_uInt16 nExtFlags = 0;
2787 if ( bSetLines )
2788 nExtFlags |= SC_PF_LINES;
2789 if ( bSetAlign )
2790 nExtFlags |= SC_PF_WHOLEROWS;
2792 SCCOL nStartCol = aMarkRange.aStart.Col();
2793 SCROW nStartRow = aMarkRange.aStart.Row();
2794 SCTAB nStartTab = aMarkRange.aStart.Tab();
2795 SCCOL nEndCol = aMarkRange.aEnd.Col();
2796 SCROW nEndRow = aMarkRange.aEnd.Row();
2797 SCTAB nEndTab = aMarkRange.aEnd.Tab();
2798 pDocShell->PostPaint( nStartCol, nStartRow, nStartTab,
2799 nEndCol, nEndRow, nEndTab,
2800 PAINT_GRID, nExtFlags | SC_PF_TESTMERGE );
2801 ScTabViewShell* pTabViewShell = GetViewData().GetViewShell();
2802 pTabViewShell->AdjustBlockHeight(false, const_cast<ScMarkData*>(&rSel));
2805 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */