1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
42 #include "viewfunc.hxx"
43 #include "tabvwsh.hxx"
46 #include "patattr.hxx"
47 #include "docpool.hxx"
48 #include "uiitems.hxx"
50 #include "undocell.hxx"
51 #include "undoblk.hxx"
52 #include "undotab.hxx"
53 #include "refundo.hxx"
55 #include "olinetab.hxx"
56 #include "rangeutl.hxx"
57 #include "rangenam.hxx"
58 #include "globstr.hrc"
60 #include "stlsheet.hxx"
61 #include "editutil.hxx"
62 #include "formulacell.hxx"
63 #include "scresid.hxx"
64 #include "inputhdl.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"
76 #include "cellsuno.hxx"
77 #include "tokenarray.hxx"
80 //==================================================================
82 static void lcl_PostRepaintCondFormat( const ScConditionalFormat
*pCondFmt
, ScDocShell
*pDocSh
)
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
),
101 ScViewFunc::~ScViewFunc()
105 //------------------------------------------------------------------------------------
107 void ScViewFunc::StartFormatArea()
110 if ( !SC_MOD()->GetInputOptions().GetExtendFormat() )
113 // start only with single cell (marked or cursor position)
115 bool bOk
= (GetViewData()->GetSimpleArea( aMarkRange
) == SC_MARK_SIMPLE
);
116 if ( bOk
&& aMarkRange
.aStart
!= aMarkRange
.aEnd
)
122 aFormatSource
= aMarkRange
.aStart
;
123 aFormatArea
= ScRange( aFormatSource
);
126 bFormatValid
= false; // discard old range
129 bool ScViewFunc::TestFormatArea( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, bool bAttrChanged
)
132 if ( !SC_MOD()->GetInputOptions().GetExtendFormat() )
135 // Test: treat input with numberformat (bAttrChanged) always as new Attribute
136 // (discard old Area ). If not not wanted, discard if-statement
143 //! Test if cell empty ???
146 ScRange aNewRange
= aFormatArea
;
147 if ( bFormatValid
&& nTab
== aFormatSource
.Tab() )
149 if ( nRow
>= aFormatArea
.aStart
.Row() && nRow
<= aFormatArea
.aEnd
.Row() )
152 if ( nCol
>= aFormatArea
.aStart
.Col() && nCol
<= aFormatArea
.aEnd
.Col() )
154 bFound
= true; // do not change range
157 if ( nCol
+1 == aFormatArea
.aStart
.Col() )
160 aNewRange
.aStart
.SetCol( nCol
);
163 if ( nCol
== aFormatArea
.aEnd
.Col()+1 )
166 aNewRange
.aEnd
.SetCol( nCol
);
169 if ( nCol
>= aFormatArea
.aStart
.Col() && nCol
<= aFormatArea
.aEnd
.Col() )
172 if ( nRow
+1 == aFormatArea
.aStart
.Row() )
175 aNewRange
.aStart
.SetRow( nRow
);
178 if ( nRow
== aFormatArea
.aEnd
.Row()+1 )
181 aNewRange
.aEnd
.SetRow( nRow
);
187 aFormatArea
= aNewRange
; // extend
190 bFormatValid
= false; // outdside of range -> break
191 if ( bAttrChanged
) // if value entered with numberformat?
192 StartFormatArea(); // then start again
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())
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
);
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
);
257 bool ScViewFunc::SelectionEditable( bool* pOnlyNotBecauseOfMatrix
/* = NULL */ )
260 ScDocument
* pDoc
= GetViewData()->GetDocument();
261 ScMarkData
& rMark
= GetViewData()->GetMarkData();
262 if (rMark
.IsMarked() || rMark
.IsMultiMarked())
263 bRet
= pDoc
->IsSelectionEditable( rMark
, pOnlyNotBecauseOfMatrix
);
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
);
279 static sal_Bool
lcl_FunctionKnown( sal_uInt16 nOpCode
)
281 const ScFunctionList
* pFuncList
= ScGlobal::GetStarCalcFunctionList();
284 sal_uLong nCount
= pFuncList
->GetCount();
285 for (sal_uLong i
=0; i
<nCount
; i
++)
286 if ( pFuncList
->GetFunction(i
)->nFIndex
== nOpCode
)
292 static sal_Bool
lcl_AddFunction( ScAppOptions
& rAppOpt
, sal_uInt16 nOpCode
)
294 sal_uInt16 nOldCount
= rAppOpt
.GetLRUFuncListCount();
295 sal_uInt16
* pOldList
= rAppOpt
.GetLRUFuncList();
297 for (nPos
=0; nPos
<nOldCount
; nPos
++)
298 if (pOldList
[nPos
] == nOpCode
) // is the function already in the list?
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
);
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();
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())
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] == '=' )
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
] == '-' ) )
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();
394 if ( !pFormatter
->IsNumberFormat( aString
, nFormat
, fNumber
) )
402 bool bNumFmtChanged
= false;
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
);
421 bool bAddEqual
= false;
422 ScTokenArray
* pArrFirst
= pArr
= aComp
.CompileString( aFormula
);
423 bool bCorrected
= aComp
.IsCorrected();
425 { // try to parse with first parser-correction
426 pArr
= aComp
.CompileString( aComp
.GetCorrectedFormula() );
428 if ( !pArr
->GetCodeError() )
431 aComp
.CompileTokenArray();
432 bCorrected
|= aComp
.IsCorrected();
436 OUString aCorrectedFormula
;
439 aCorrectedFormula
= "=" + aComp
.GetCorrectedFormula();
442 aCorrectedFormula
= aComp
.GetCorrectedFormula();
444 if ( aCorrectedFormula
.getLength() == 1 )
445 nResult
= RET_NO
; // empty formula, just '='
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
)
463 if ( pArr
!= pArrFirst
)
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();
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();
497 else if ( eOp
== ocClose
&& nLevel
)
499 if ( nLevel
== 0 && pTok
->IsFunction() &&
500 lcl_AddFunction( aAppOpt
, sal::static_int_cast
<sal_uInt16
>( eOp
) ) )
506 pScMod
->SetAppOptions(aAppOpt
);
507 pScMod
->RecentFunctionsChanged();
511 ScFormulaCell
aCell(pDoc
, aPos
, *pArr
, formula::FormulaGrammar::GRAM_DEFAULT
, MM_NONE
);
514 SvNumberFormatter
* pFormatter
= pDoc
->GetFormatTable();
515 ScMarkData::iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
516 for (; itr
!= itrEnd
; ++itr
)
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
) )
527 // A clone of pData will be stored in the cell.
528 rFunc
.SetEditCell(aPos
, *pData
, true);
531 rFunc
.SetStringCell(aPos
, aFormula
, true);
535 ScFormulaCell
* pCell
= new ScFormulaCell( aCell
, *pDoc
, aPos
);
538 pCell
->GetCode()->DelRPN();
539 pCell
->SetErrCode( nError
);
540 if(pCell
->GetCode()->IsHyperLink())
541 pCell
->GetCode()->SetHyperLink(false);
543 rFunc
.SetFormulaCell(aPos
, pCell
, true);
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 );
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
);
566 DoAutoAttributes(nCol
, nRow
, nTab
, bNumFmtChanged
, bRecord
);
568 pDocSh
->UpdateOle(GetViewData());
570 HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh
, rMark
, nCol
, nRow
);
573 rFunc
.EndListAction();
575 aModificator
.SetDocumentModified();
576 lcl_PostRepaintCondFormat( pDoc
->GetCondFormat( nCol
, nRow
, nTab
), pDocSh
);
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
;
603 aUndoCell
.assign(*pDoc
, aPos
);
605 pDoc
->SetValue( nCol
, nRow
, nTab
, rValue
);
607 // because of ChangeTrack after change in document
610 pDocSh
->GetUndoManager()->AddUndoAction(
611 new ScUndoEnterValue(pDocSh
, aPos
, aUndoCell
, rValue
));
614 pDocSh
->PostPaintCell( aPos
);
615 pDocSh
->UpdateOle(GetViewData());
616 aModificator
.SetDocumentModified();
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
;
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] == '=' )
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
);
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();
701 pDoc
->ApplyPattern(nCol
,nRow
,nTab
,*pCellAttrs
); //! undo
706 AdjustRowHeight(nRow
,nRow
);
708 EnterData(nCol
,nRow
,nTab
,aString
);
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());
720 { // because of ChangeTrack current first
721 pDocSh
->GetUndoManager()->AddUndoAction(
722 new ScUndoEnterData(pDocSh
, ScAddress(nCol
,nRow
,nTab
), aOldValues
, aString
, pUndoData
));
727 AdjustRowHeight(nRow
,nRow
);
730 for (; itr
!= itrEnd
; ++itr
)
731 pDocSh
->PostPaintCell( nCol
, nRow
, *itr
);
735 pDocSh
->UpdateOle(GetViewData());
737 HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh
, rMark
, nCol
, nRow
);
739 aModificator
.SetDocumentModified();
741 lcl_PostRepaintCondFormat( pDoc
->GetCondFormat( nCol
, nRow
, nTab
), pDocSh
);
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
);
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 );
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
);
797 pDocSh
->UpdateOle(GetViewData());
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());
819 rMark
.FillRangeListWithMarks( &aRanges
, false );
820 nScript
= pDoc
->GetRangeScriptType(aRanges
);
824 nScript
= ScGlobal::GetDefaultScriptType();
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
);
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
);
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
);
870 pDoc
->GetSelectionFrame( rMark
, rLineOuter
, rLineInner
);
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
,
897 // not editable because of matrix only? attribute OK nonetheless
898 bool bOnlyNotBecauseOfMatrix
;
899 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix
) && !bOnlyNotBecauseOfMatrix
)
901 ErrorMessage(STR_PROTECTIONERR
);
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:
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
)
964 // this should be intercepted by the pool: ?!??!??
966 if ( bFrame
&& pNewOuter
&& pNewInner
)
967 if ( *pNewOuter
== *pOldOuter
&& *pNewInner
== *pOldInner
)
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
) );
984 ApplySelectionPattern( aNewAttrs
, bRecord
); // standard only
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
,
998 pNewPool
->Remove( *pNewOuter
); // release
999 pNewPool
->Remove( *pNewInner
);
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
);
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())
1044 aFuncMark
.MarkToSimple();
1045 bool bMulti
= aFuncMark
.IsMultiMarked();
1047 aFuncMark
.GetMultiMarkArea( aMarkRange
);
1048 else if (aFuncMark
.IsMarked())
1049 aFuncMark
.GetMarkArea( aMarkRange
);
1052 aMarkRange
= ScRange( GetViewData()->GetCurX(),
1053 GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
1056 aFuncMark
.SetMarkArea(aMarkRange
);
1060 ScDocShell
* pDocSh
= GetViewData()->GetDocShell();
1062 ScDocShellModificator
aModificator( *pDocSh
);
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(
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();
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())
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;
1131 nExtFlags
|= SC_PF_LINES
;
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);
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
)
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
;
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
);
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
);
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
;
1272 HelperNotifyChanges::Notify(*pModelObj
, aChangeRanges
, "attribute", aProperties
);
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
);
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
1310 pSheet
= pDoc
->GetStyle( pViewData
->GetCurX(),
1311 pViewData
->GetCurY(),
1312 pViewData
->GetTabNo() );
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
);
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())
1339 ScDocShellModificator
aModificator( *pDocSh
);
1341 if ( aFuncMark
.IsMarked() || aFuncMark
.IsMultiMarked() )
1344 aFuncMark
.MarkToMulti();
1345 aFuncMark
.GetMultiMarkArea( aMarkRange
);
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
)
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();
1377 SCCOL nCol
= pViewData
->GetCurX();
1378 SCROW nRow
= pViewData
->GetCurY();
1379 SCTAB nTab
= pViewData
->GetTabNo();
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
)
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();
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();
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();
1468 pHdl
->ForgetLastPattern();
1471 // insert cells - undo OK
1473 bool ScViewFunc::InsertCells( InsCellCmd eCmd
, bool bRecord
, bool bPartOfPaste
)
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
);
1483 pDocSh
->UpdateOle(GetViewData());
1484 CellContentChanged();
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
);
1499 ErrorMessage(STR_NOMULTISELECT
);
1504 // delete cells - undo OK
1506 void ScViewFunc::DeleteCells( DelCellCmd eCmd
, bool bRecord
)
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 );
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 );
1537 pDocSh
->GetDocFunc().DeleteCells( aRange
, &rMark
, eCmd
, bRecord
, false );
1540 pDocSh
->UpdateOle(GetViewData());
1541 CellContentChanged();
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();
1558 nCurY
= aRange
.aStart
.Row();
1559 SetCursor( nCurX
, nCurY
);
1563 if (eCmd
== DEL_DELCOLS
)
1564 DeleteMulti( false, bRecord
);
1565 else if (eCmd
== DEL_DELROWS
)
1566 DeleteMulti( true, bRecord
);
1568 ErrorMessage(STR_NOMULTISELECT
);
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())
1585 SCCOLROW
* pRanges
= new SCCOLROW
[MAXCOLROWCOUNT
];
1586 SCCOLROW nRangeCnt
= bRows
? aFuncMark
.GetMarkRowRanges( pRanges
) :
1587 aFuncMark
.GetMarkColumnRanges( pRanges
);
1590 pRanges
[0] = pRanges
[1] = bRows
? static_cast<SCCOLROW
>(GetViewData()->GetCurY()) : static_cast<SCCOLROW
>(GetViewData()->GetCurX());
1596 SCCOLROW
* pOneRange
= pRanges
;
1597 sal_uInt16 nErrorId
= 0;
1598 bool bNeedRefresh
= false;
1600 for (nRangeNo
=0; nRangeNo
<nRangeCnt
&& !nErrorId
; nRangeNo
++)
1602 SCCOLROW nStart
= *(pOneRange
++);
1603 SCCOLROW nEnd
= *(pOneRange
++);
1605 SCCOL nStartCol
, nEndCol
;
1606 SCROW nStartRow
, nEndRow
;
1611 nStartRow
= static_cast<SCROW
>(nStart
);
1612 nEndRow
= static_cast<SCROW
>(nEnd
);
1616 nStartCol
= static_cast<SCCOL
>(nStart
);
1617 nEndCol
= static_cast<SCCOL
>(nEnd
);
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();
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;
1656 ErrorMessage( nErrorId
);
1663 WaitObject
aWait( GetFrameWin() ); // important for TrackFormulas in UpdateReference
1665 ScDocument
* pUndoDoc
= NULL
;
1666 ScRefUndoData
* pUndoData
= NULL
;
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
++);
1678 pDoc
->CopyToDocument( 0,nStart
,nTab
, MAXCOL
,nEnd
,nTab
, IDF_ALL
,false,pUndoDoc
);
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
);
1702 pDoc
->DeleteRow( 0,nTab
, MAXCOL
,nTab
, nStart
, static_cast<SCSIZE
>(nEnd
-nStart
+1) );
1704 pDoc
->DeleteCol( 0,nTab
, MAXROW
,nTab
, static_cast<SCCOL
>(nStart
), static_cast<SCSIZE
>(nEnd
-nStart
+1) );
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 );
1721 pDocSh
->GetUndoManager()->AddUndoAction(
1722 new ScUndoDeleteMulti( pDocSh
, bRows
, bNeedRefresh
, nTab
, pRanges
, nRangeCnt
,
1723 pUndoDoc
, pUndoData
) );
1726 if (!AdjustRowHeight(0, MAXROW
))
1729 pDocSh
->PostPaint( 0,pRanges
[0],nTab
, MAXCOL
,MAXROW
,nTab
, PAINT_GRID
| PAINT_LEFT
);
1731 pDocSh
->PostPaint( static_cast<SCCOL
>(pRanges
[0]),0,nTab
,
1732 MAXCOL
,MAXROW
,nTab
, PAINT_GRID
| PAINT_TOP
);
1736 aModificator
.SetDocumentModified();
1738 CellContentChanged();
1740 // put cursor directly behind the first deleted range
1741 SCCOL nCurX
= GetViewData()->GetCurX();
1742 SCROW nCurY
= GetViewData()->GetCurY();
1746 nCurX
= static_cast<SCCOL
>(pRanges
[0]);
1747 SetCursor( nCurX
, nCurY
);
1751 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED
) );
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
);
1767 if ( !(bOnlyNotBecauseOfMatrix
&&
1768 ((nFlags
& (IDF_ATTRIB
| IDF_EDITATTR
)) == nFlags
)) )
1770 ErrorMessage(bOnlyNotBecauseOfMatrix
? STR_MATRIXFRAGMENTERR
: STR_PROTECTIONERR
);
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())
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
);
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();
1811 aFuncMark
.MarkToMulti();
1812 aFuncMark
.GetMultiMarkArea( aMarkRange
);
1814 ScRange
aExtendedRange(aMarkRange
);
1817 if ( pDoc
->ExtendMerge( aExtendedRange
, true ) )
1821 // no objects on protected tabs
1822 bool bObjects
= false;
1823 if ( nFlags
& IDF_OBJECTS
)
1826 ScMarkData::iterator itr
= aFuncMark
.begin(), itrEnd
= aFuncMark
.end();
1827 for (; itr
!= itrEnd
; ++itr
)
1828 if (pDoc
->IsTabProtected(*itr
))
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:
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();
1850 pDoc
->DeleteObjectsInSelection( aFuncMark
);
1852 pDoc
->DeleteObjectsInArea( aMarkRange
.aStart
.Col(), aMarkRange
.aStart
.Row(),
1853 /*!*/ aMarkRange
.aEnd
.Col(), aMarkRange
.aEnd
.Row(),
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
)
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
1887 pDoc
->DeleteArea( aMarkRange
.aStart
.Col(), aMarkRange
.aStart
.Row(),
1888 aMarkRange
.aEnd
.Col(), aMarkRange
.aEnd
.Row(),
1889 aFuncMark
, nFlags
);
1892 pDoc
->DeleteSelection( nFlags
, aFuncMark
);
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
;
1912 aChangeRanges
.Append( aMarkRange
);
1916 aFuncMark
.FillRangeListWithMarks( &aChangeRanges
, false );
1918 HelperNotifyChanges::Notify(*pModelObj
, aChangeRanges
);
1921 aModificator
.SetDocumentModified();
1922 CellContentChanged();
1925 if ( nFlags
& IDF_ATTRIB
)
1927 if ( nFlags
& IDF_CONTENTS
)
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
)
1943 // use view's mark if none specified
1945 pMarkData
= &GetViewData()->GetMarkData();
1947 ScDocShell
* pDocSh
= GetViewData()->GetDocShell();
1948 ScDocument
* pDoc
= pDocSh
->GetDocument();
1949 SCTAB nFirstTab
= pMarkData
->GetFirstSelected();
1950 SCTAB nCurTab
= GetViewData()->GetTabNo();
1952 if (bRecord
&& !pDoc
->IsUndoEnabled())
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
++ )
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
;
1969 bAllowed
= pDoc
->IsBlockEditable( *itr
, 0,pRanges
[2*i
],
1970 MAXCOL
,pRanges
[2*i
+1], &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
);
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
;
1998 pDoc
->BeginDrawUndo(); // Drawing Updates
2000 pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
2001 itr
= pMarkData
->begin();
2002 for (; itr
!= itrEnd
; ++itr
)
2006 if ( *itr
== nFirstTab
)
2007 pUndoDoc
->InitUndo( pDoc
, *itr
, *itr
, true, false );
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
,
2016 if ( *itr
== nFirstTab
)
2017 pUndoDoc
->InitUndo( pDoc
, *itr
, *itr
, false, true );
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
);
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
)
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
);
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
))
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
);
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
)
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
);
2120 pDoc
->SetColWidth( nCol
, nTab
, nThisSize
);
2122 pDoc
->ShowCol( nCol
, nTab
, bShow
);
2131 if ( pDoc
->UpdateOutlineCol( static_cast<SCCOL
>(nStartNo
),
2132 static_cast<SCCOL
>(nEndNo
), nTab
, bShow
) )
2137 if ( pDoc
->UpdateOutlineRow( nStartNo
, nEndNo
, nTab
, bShow
) )
2141 pDoc
->SetDrawPageSize(nTab
);
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();
2169 itr
= pMarkData
->begin();
2170 for (; itr
!= itrEnd
; ++itr
)
2175 if (pDoc
->HasAttrib( static_cast<SCCOL
>(nStart
),0,nTab
,
2176 static_cast<SCCOL
>(nEnd
),MAXROW
,nTab
,
2177 HASATTR_MERGED
| HASATTR_OVERLAPPED
))
2179 if (nStart
> 0) // go upwards because of Lines and cursor
2181 pDocSh
->PostPaint( static_cast<SCCOL
>(nStart
), 0, nTab
,
2182 MAXCOL
, MAXROW
, nTab
, PAINT_GRID
| PAINT_TOP
);
2186 if (pDoc
->HasAttrib( 0,nStart
,nTab
, MAXCOL
,nEnd
,nTab
, HASATTR_MERGED
| HASATTR_OVERLAPPED
))
2190 pDocSh
->PostPaint( 0, nStart
, nTab
, MAXCOL
, MAXROW
, nTab
, PAINT_GRID
| PAINT_LEFT
);
2194 pDocSh
->UpdateOle(GetViewData());
2195 if( !pDocSh
->IsReadOnly() )
2196 aModificator
.SetDocumentModified();
2201 if (ScModelObj
* pModelObj
= HelperNotifyChanges::getMustPropagateChangesModel(*pDocSh
))
2203 ScRangeList aChangeRanges
;
2204 itr
= pMarkData
->begin();
2205 for (; itr
!= itrEnd
; ++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();
2239 rMark
.SetMultiMarkArea( ScRange( nCol
,nRow
,nTab
), true );
2243 SCCOLROW
* pRanges
= new SCCOLROW
[MAXCOLROWCOUNT
];
2244 SCCOLROW nRangeCnt
= 0;
2247 nRangeCnt
= rMark
.GetMarkColumnRanges( pRanges
);
2249 nRangeCnt
= rMark
.GetMarkRowRanges( pRanges
);
2251 SetWidthOrHeight( bWidth
, nRangeCnt
, pRanges
, eMode
, nSizeTwips
, bRecord
, bPaint
);
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
);
2276 bAllowed
= pDoc
->IsBlockEditable( nTab
, 0,nRow
, MAXCOL
,nRow
, &bOnlyMatrix
);
2277 if ( !bAllowed
&& !bOnlyMatrix
)
2279 ErrorMessage(STR_PROTECTIONERR
);
2285 sal_uInt16 nWidth
= pDoc
->GetColWidth( nCol
, nTab
);
2286 sal_uInt16 nHeight
= pDoc
->GetRowHeight( nRow
, nTab
);
2288 if ( eDir
== DIR_LEFT
|| eDir
== DIR_RIGHT
)
2290 if (bOptimal
) // width of this single cell
2294 // when editing the actual entered width
2295 ScInputHandler
* pHdl
= pScMod
->GetInputHdl( GetViewData()->GetViewShell() );
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
;
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
);
2332 nWidth
= nTwips
+ STD_EXTRA_WIDTH
;
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
2353 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( nCol
, nRow
, nTab
);
2355 ((const SfxBoolItem
&)pPattern
->GetItem( ATTR_LINEBREAK
)).GetValue() ||
2356 ((const SvxHorJustifyItem
&)pPattern
->
2357 GetItem( ATTR_HOR_JUSTIFY
)).GetValue() == SVX_HOR_JUSTIFY_BLOCK
;
2359 AdjustRowHeight( nRow
, nRow
);
2367 eMode
= SC_SIZE_OPTIMAL
;
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
);
2387 if ( pDoc
->HasAttrib( nCol
, nRow
, nTab
, nCol
, nRow
, nTab
, HASATTR_NEEDHEIGHT
) )
2389 ScInputHandler
* pHdl
= pScMod
->GetInputHdl( GetViewData()->GetViewShell() );
2391 pHdl
->SetModified(); // so that the height is adjusted with Enter
2398 void ScViewFunc::ProtectSheet( SCTAB nTab
, const ScTableProtection
& rProtect
)
2400 if (nTab
== TABLEID_DOC
)
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
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
);
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 );
2439 // modifying several tabs is handled here
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 );
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 );
2471 // modifying several tabs is handled here
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 ) )
2485 pDocSh
->GetUndoManager()->LeaveListAction();
2489 UpdateLayerLocks(); //! broadcast to all views
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
);
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
);
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
);
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
2565 sal_uInt32 nNumberFormat
= pFormatter
->GetEntryKey( rCode
, eLanguage
);
2566 if ( nNumberFormat
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
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
);
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
);
2610 OSL_FAIL("numberformat not found !!!");
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
2633 //! SvNumberformat has a Member bStandard, but doesn't disclose it
2634 bool bWasStandard
= ( nOldFormat
== pFormatter
->GetStandardIndex( eLanguage
) );
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:
2644 ((SvNumberformat
*)pOldEntry
)->GetOutputString( nVal
, aOut
, &pCol
);
2647 // 'E' for exponential is fixed in Numberformatter
2648 if ( aOut
.indexOf((sal_Unicode
)'E') >= 0 )
2649 bError
= true; // exponential not changed
2652 OUString
aDecSep( pFormatter
->GetFormatDecimalSep( nOldFormat
) );
2653 sal_Int32 nPos
= aOut
.indexOf( aDecSep
);
2655 nPrecision
= aOut
.getLength() - nPos
- aDecSep
.getLength();
2665 ++nPrecision
; // increment
2667 bError
= true; // 20 is maximum
2672 --nPrecision
; // decrement
2674 bError
= true; // 0 is minumum
2680 OUString aNewPicture
= pFormatter
->GenerateFormat(nOldFormat
, eLanguage
,
2682 nPrecision
, nLeading
);
2684 nNewFormat
= pFormatter
->GetEntryKey( aNewPicture
, eLanguage
);
2685 if ( nNewFormat
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
2687 sal_Int32 nErrPos
= 0;
2689 bool bOk
= pFormatter
->PutEntry( aNewPicture
, nErrPos
,
2690 nNewType
, nNewFormat
, eLanguage
);
2691 OSL_ENSURE( bOk
, "incorrect numberformat generated" );
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 );
2727 pDocSh
->UpdateOle(pViewData
);
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)
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(),
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
));
2774 pNewEntry
->SetIndex(pData
->GetIndex());
2775 pList
->erase(*pData
);
2778 if ( pList
->insert( pNewEntry
) )
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
2791 void ScViewFunc::CreateNames( sal_uInt16 nFlags
)
2795 if ( GetViewData()->GetSimpleArea(aRange
) == SC_MARK_SIMPLE
)
2796 bDone
= GetViewData()->GetDocShell()->GetDocFunc().CreateNames( aRange
, nFlags
, false );
2799 ErrorMessage(STR_CREATENAME_MARKERR
);
2802 sal_uInt16
ScViewFunc::GetCreateNameFlags()
2804 sal_uInt16 nFlags
= 0;
2806 SCCOL nStartCol
, nEndCol
;
2807 SCROW nStartRow
, nEndRow
;
2809 if (GetViewData()->GetSimpleArea(nStartCol
,nStartRow
,nDummy
,nEndCol
,nEndRow
,nDummy
) == SC_MARK_SIMPLE
)
2811 ScDocument
* pDoc
= GetViewData()->GetDocument();
2812 SCTAB nTab
= GetViewData()->GetTabNo();
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
))
2826 else // Bottom only if not Top
2829 for (i
=nFirstCol
; i
<=nLastCol
&& bOk
; i
++)
2830 if (!pDoc
->HasStringData( i
,nEndRow
,nTab
))
2833 nFlags
|= NAME_BOTTOM
;
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
))
2844 nFlags
|= NAME_LEFT
;
2845 else // Right only if not Left
2848 for (j
=nFirstRow
; j
<=nLastRow
&& bOk
; j
++)
2849 if (!pDoc
->HasStringData( nEndCol
,j
,nTab
))
2852 nFlags
|= NAME_RIGHT
;
2856 if (nStartCol
== nEndCol
)
2857 nFlags
&= ~( NAME_LEFT
| NAME_RIGHT
);
2858 if (nStartRow
== nEndRow
)
2859 nFlags
&= ~( NAME_TOP
| NAME_BOTTOM
);
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();
2876 if (rSel
.IsMultiMarked() )
2877 rSel
.GetMultiMarkArea( aMarkRange
);
2879 rSel
.GetMarkArea( aMarkRange
);
2881 bool bSetLines
= false;
2882 bool bSetAlign
= false;
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;
2893 nExtFlags
|= SC_PF_LINES
;
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: */