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 "scitems.hxx"
21 #include <editeng/eeitem.hxx>
23 #include <sfx2/app.hxx>
24 #include <svx/algitem.hxx>
25 #include <editeng/boxitem.hxx>
26 #include <editeng/editobj.hxx>
27 #include <editeng/editview.hxx>
28 #include <editeng/langitem.hxx>
29 #include <editeng/scripttypeitem.hxx>
30 #include <editeng/justifyitem.hxx>
31 #include <sfx2/bindings.hxx>
32 #include <svl/zforlist.hxx>
33 #include <svl/zformat.hxx>
34 #include <vcl/msgbox.hxx>
35 #include <vcl/virdev.hxx>
36 #include <vcl/waitobj.hxx>
37 #include <vcl/wrkwin.hxx>
38 #include <stdlib.h> // qsort
40 #include "viewfunc.hxx"
41 #include "tabvwsh.hxx"
44 #include "patattr.hxx"
45 #include "docpool.hxx"
46 #include "uiitems.hxx"
48 #include "undocell.hxx"
49 #include "undoblk.hxx"
50 #include "undotab.hxx"
51 #include "refundo.hxx"
53 #include "olinetab.hxx"
54 #include "rangeutl.hxx"
55 #include "rangenam.hxx"
56 #include "globstr.hrc"
58 #include "stlsheet.hxx"
59 #include "editutil.hxx"
61 #include "scresid.hxx"
62 #include "inputhdl.hxx"
64 #include "inputopt.hxx"
65 #include "compiler.hxx"
66 #include "docfunc.hxx"
67 #include "appoptio.hxx"
68 #include "dociter.hxx"
69 #include "sizedev.hxx"
70 #include "editable.hxx"
71 #include "scui_def.hxx"
72 #include "funcdesc.hxx"
74 #include "cellsuno.hxx"
75 //==================================================================
77 static void lcl_PostRepaintCondFormat( const ScConditionalFormat
*pCondFmt
, ScDocShell
*pDocSh
)
81 const ScRangeList
& rRanges
= pCondFmt
->GetRange();
83 pDocSh
->PostPaint( rRanges
, PAINT_ALL
);
88 //==================================================================
90 ScViewFunc::ScViewFunc( Window
* pParent
, ScDocShell
& rDocSh
, ScTabViewShell
* pViewShell
) :
91 ScTabView( pParent
, rDocSh
, pViewShell
),
96 ScViewFunc::~ScViewFunc()
100 //------------------------------------------------------------------------------------
102 void ScViewFunc::StartFormatArea()
105 if ( !SC_MOD()->GetInputOptions().GetExtendFormat() )
108 // start only with single cell (marked or cursor position)
110 sal_Bool bOk
= (GetViewData()->GetSimpleArea( aMarkRange
) == SC_MARK_SIMPLE
);
111 if ( bOk
&& aMarkRange
.aStart
!= aMarkRange
.aEnd
)
116 bFormatValid
= sal_True
;
117 aFormatSource
= aMarkRange
.aStart
;
118 aFormatArea
= ScRange( aFormatSource
);
121 bFormatValid
= false; // discard old range
124 sal_Bool
ScViewFunc::TestFormatArea( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, sal_Bool bAttrChanged
)
127 if ( !SC_MOD()->GetInputOptions().GetExtendFormat() )
130 // Test: treat input with numberformat (bAttrChanged) always as new Attribute
131 // (discard old Area ). If not not wanted, discard if-statement
138 //! Test if cell empty ???
140 sal_Bool bFound
= false;
141 ScRange aNewRange
= aFormatArea
;
142 if ( bFormatValid
&& nTab
== aFormatSource
.Tab() )
144 if ( nRow
>= aFormatArea
.aStart
.Row() && nRow
<= aFormatArea
.aEnd
.Row() )
147 if ( nCol
>= aFormatArea
.aStart
.Col() && nCol
<= aFormatArea
.aEnd
.Col() )
149 bFound
= sal_True
; // do not change range
152 if ( nCol
+1 == aFormatArea
.aStart
.Col() )
155 aNewRange
.aStart
.SetCol( nCol
);
158 if ( nCol
== aFormatArea
.aEnd
.Col()+1 )
161 aNewRange
.aEnd
.SetCol( nCol
);
164 if ( nCol
>= aFormatArea
.aStart
.Col() && nCol
<= aFormatArea
.aEnd
.Col() )
167 if ( nRow
+1 == aFormatArea
.aStart
.Row() )
170 aNewRange
.aStart
.SetRow( nRow
);
173 if ( nRow
== aFormatArea
.aEnd
.Row()+1 )
176 aNewRange
.aEnd
.SetRow( nRow
);
182 aFormatArea
= aNewRange
; // extend
185 bFormatValid
= false; // outdside of range -> break
186 if ( bAttrChanged
) // if value entered with numberformat?
187 StartFormatArea(); // then start again
193 void ScViewFunc::DoAutoAttributes( SCCOL nCol
, SCROW nRow
, SCTAB nTab
,
194 sal_Bool bAttrChanged
, sal_Bool bAddUndo
)
196 ScDocShell
* pDocSh
= GetViewData()->GetDocShell();
197 ScDocument
* pDoc
= pDocSh
->GetDocument();
198 if (bAddUndo
&& !pDoc
->IsUndoEnabled())
201 const ScPatternAttr
* pSource
= pDoc
->GetPattern(
202 aFormatSource
.Col(), aFormatSource
.Row(), nTab
);
203 if ( !((const ScMergeAttr
&)pSource
->GetItem(ATTR_MERGE
)).IsMerged() )
205 ScRange
aRange( nCol
, nRow
, nTab
, nCol
, nRow
, nTab
);
207 aMark
.SetMarkArea( aRange
);
209 ScDocFunc
&rFunc
= GetViewData()->GetDocFunc();
211 // pOldPattern is only valid until call to ApplyAttributes!
212 const ScPatternAttr
* pOldPattern
= pDoc
->GetPattern( nCol
, nRow
, nTab
);
213 const ScStyleSheet
* pSrcStyle
= pSource
->GetStyleSheet();
214 if ( pSrcStyle
&& pSrcStyle
!= pOldPattern
->GetStyleSheet() )
215 rFunc
.ApplyStyle( aMark
, pSrcStyle
->GetName(), sal_True
, sal_False
);
217 rFunc
.ApplyAttributes( aMark
, *pSource
, sal_True
, sal_False
);
220 if ( bAttrChanged
) // value entered with number format?
221 aFormatSource
.Set( nCol
, nRow
, nTab
); // then set a new source
224 //------------------------------------------------------------------------------------
226 // additional routines
228 sal_uInt16
ScViewFunc::GetOptimalColWidth( SCCOL nCol
, SCTAB nTab
, sal_Bool bFormula
)
230 ScDocShell
* pDocSh
= GetViewData()->GetDocShell();
231 ScDocument
* pDoc
= pDocSh
->GetDocument();
232 ScMarkData
& rMark
= GetViewData()->GetMarkData();
234 double nPPTX
= GetViewData()->GetPPTX();
235 double nPPTY
= GetViewData()->GetPPTY();
236 Fraction aZoomX
= GetViewData()->GetZoomX();
237 Fraction aZoomY
= GetViewData()->GetZoomY();
239 ScSizeDeviceProvider
aProv(pDocSh
);
240 if (aProv
.IsPrinter())
242 nPPTX
= aProv
.GetPPTX();
243 nPPTY
= aProv
.GetPPTY();
244 aZoomX
= aZoomY
= Fraction( 1, 1 );
247 sal_uInt16 nTwips
= pDoc
->GetOptimalColWidth( nCol
, nTab
, aProv
.GetDevice(),
248 nPPTX
, nPPTY
, aZoomX
, aZoomY
, bFormula
, &rMark
);
252 sal_Bool
ScViewFunc::SelectionEditable( bool* pOnlyNotBecauseOfMatrix
/* = NULL */ )
255 ScDocument
* pDoc
= GetViewData()->GetDocument();
256 ScMarkData
& rMark
= GetViewData()->GetMarkData();
257 if (rMark
.IsMarked() || rMark
.IsMultiMarked())
258 bRet
= pDoc
->IsSelectionEditable( rMark
, pOnlyNotBecauseOfMatrix
);
261 SCCOL nCol
= GetViewData()->GetCurX();
262 SCROW nRow
= GetViewData()->GetCurY();
263 SCTAB nTab
= GetViewData()->GetTabNo();
264 bRet
= pDoc
->IsBlockEditable( nTab
, nCol
, nRow
, nCol
, nRow
,
265 pOnlyNotBecauseOfMatrix
);
274 static sal_Bool
lcl_FunctionKnown( sal_uInt16 nOpCode
)
276 const ScFunctionList
* pFuncList
= ScGlobal::GetStarCalcFunctionList();
279 sal_uLong nCount
= pFuncList
->GetCount();
280 for (sal_uLong i
=0; i
<nCount
; i
++)
281 if ( pFuncList
->GetFunction(i
)->nFIndex
== nOpCode
)
287 static sal_Bool
lcl_AddFunction( ScAppOptions
& rAppOpt
, sal_uInt16 nOpCode
)
289 sal_uInt16 nOldCount
= rAppOpt
.GetLRUFuncListCount();
290 sal_uInt16
* pOldList
= rAppOpt
.GetLRUFuncList();
292 for (nPos
=0; nPos
<nOldCount
; nPos
++)
293 if (pOldList
[nPos
] == nOpCode
) // is the function already in the list?
296 return false; // already at the top -> no change
298 // count doesn't change, so the original array is modified
300 for (sal_uInt16 nCopy
=nPos
; nCopy
>0; nCopy
--)
301 pOldList
[nCopy
] = pOldList
[nCopy
-1];
302 pOldList
[0] = nOpCode
;
304 return sal_True
; // list has changed
307 if ( !lcl_FunctionKnown( nOpCode
) )
308 return false; // not in function list -> no change
310 sal_uInt16 nNewCount
= Min( (sal_uInt16
)(nOldCount
+ 1), (sal_uInt16
)LRU_MAX
);
311 sal_uInt16 nNewList
[LRU_MAX
];
312 nNewList
[0] = nOpCode
;
313 for (nPos
=1; nPos
<nNewCount
; nPos
++)
314 nNewList
[nPos
] = pOldList
[nPos
-1];
315 rAppOpt
.SetLRUFuncList( nNewList
, nNewCount
);
317 return sal_True
; // list has changed
324 void ScViewFunc::EnterData( SCCOL nCol
, SCROW nRow
, SCTAB nTab
,
325 const String
& rString
,
326 const EditTextObject
* pData
)
328 ScDocument
* pDoc
= GetViewData()->GetDocument();
329 ScMarkData
& rMark
= GetViewData()->GetMarkData();
330 bool bRecord
= pDoc
->IsUndoEnabled();
333 ScDocShell
* pDocSh
= GetViewData()->GetDocShell();
334 ScDocFunc
&rFunc
= GetViewData()->GetDocFunc();
335 ScDocShellModificator
aModificator( *pDocSh
);
337 ScEditableTester
aTester( pDoc
, nCol
,nRow
, nCol
,nRow
, rMark
);
338 if (aTester
.IsEditable())
341 rFunc
.EnterListAction( STR_UNDO_ENTERDATA
);
343 bool bFormula
= false;
345 // a single '=' character is handled as string (needed for special filters)
346 if ( rString
.Len() > 1 )
348 if ( rString
.GetChar(0) == '=' )
353 else if ( rString
.GetChar(0) == '+' || rString
.GetChar(0) == '-' )
355 // if there is more than one leading '+' or '-' character, remove the additional ones
356 String
aString( rString
);
357 xub_StrLen nIndex
= 1;
358 xub_StrLen nLen
= aString
.Len();
359 while ( nIndex
< nLen
&& ( aString
.GetChar( nIndex
) == '+' || aString
.GetChar( nIndex
) == '-' ) )
363 aString
.Erase( 1, nIndex
- 1 );
365 // if the remaining part without the leading '+' or '-' character
366 // is non-empty and not a number, handle as formula
367 if ( aString
.Len() > 1 )
369 sal_uInt32 nFormat
= 0;
370 pDoc
->GetNumberFormat( nCol
, nRow
, nTab
, nFormat
);
371 SvNumberFormatter
* pFormatter
= pDoc
->GetFormatTable();
373 if ( !pFormatter
->IsNumberFormat( aString
, nFormat
, fNumber
) )
381 sal_Bool bNumFmtChanged
= false;
383 { // formula, compile with autoCorrection
384 i
= rMark
.GetFirstSelected();
385 ScAddress
aPos( nCol
, nRow
, i
);
386 ScCompiler
aComp( pDoc
, aPos
);
387 aComp
.SetGrammar(pDoc
->GetGrammar());
388 //2do: enable/disable autoCorrection via calcoptions
389 aComp
.SetAutoCorrection( sal_True
);
390 if ( rString
.GetChar(0) == '+' || rString
.GetChar(0) == '-' )
392 aComp
.SetExtendedErrorDetection( ScCompiler::EXTENDED_ERROR_DETECTION_NAME_BREAK
);
394 String
aFormula( rString
);
400 bool bAddEqual
= false;
401 ScTokenArray
* pArrFirst
= pArr
= aComp
.CompileString( aFormula
);
402 bool bCorrected
= aComp
.IsCorrected();
404 { // try to parse with first parser-correction
405 pArr
= aComp
.CompileString( aComp
.GetCorrectedFormula() );
407 if ( !pArr
->GetCodeError() )
410 aComp
.CompileTokenArray();
411 bCorrected
|= aComp
.IsCorrected();
415 String aCorrectedFormula
;
418 aCorrectedFormula
= '=';
419 aCorrectedFormula
+= aComp
.GetCorrectedFormula();
422 aCorrectedFormula
= aComp
.GetCorrectedFormula();
424 if ( aCorrectedFormula
.Len() == 1 )
425 nResult
= RET_NO
; // empty formula, just '='
428 String
aMessage( ScResId( SCSTR_FORMULA_AUTOCORRECTION
) );
429 aMessage
+= aCorrectedFormula
;
430 nResult
= QueryBox( GetViewData()->GetDialogParent(),
431 WinBits(WB_YES_NO
| WB_DEF_YES
),
432 aMessage
).Execute();
434 if ( nResult
== RET_YES
)
436 aFormula
= aCorrectedFormula
;
437 if ( pArr
!= pArrFirst
)
443 if ( pArr
!= pArrFirst
)
451 // to be used in multiple tabs, the formula must be compiled anew
452 // via ScFormulaCell copy-ctor because of RangeNames,
453 // the same code-array for all cells is not possible.
454 // If the array has an error, (it) must be RPN-erased in the newly generated
455 // cellst and the error be set explicitly, so that
456 // via FormulaCell copy-ctor and Interpreter it will be, when possible,
457 // ironed out again, too intelligent.. e.g.: =1))
458 sal_uInt16 nError
= pArr
->GetCodeError();
461 // update list of recent functions with all functions that
462 // are not within parentheses
464 ScModule
* pScMod
= SC_MOD();
465 ScAppOptions aAppOpt
= pScMod
->GetAppOptions();
466 sal_Bool bOptChanged
= false;
468 formula::FormulaToken
** ppToken
= pArr
->GetArray();
469 sal_uInt16 nTokens
= pArr
->GetLen();
470 sal_uInt16 nLevel
= 0;
471 for (sal_uInt16 nTP
=0; nTP
<nTokens
; nTP
++)
473 formula::FormulaToken
* pTok
= ppToken
[nTP
];
474 OpCode eOp
= pTok
->GetOpCode();
477 else if ( eOp
== ocClose
&& nLevel
)
479 if ( nLevel
== 0 && pTok
->IsFunction() &&
480 lcl_AddFunction( aAppOpt
, sal::static_int_cast
<sal_uInt16
>( eOp
) ) )
481 bOptChanged
= sal_True
;
486 pScMod
->SetAppOptions(aAppOpt
);
487 pScMod
->RecentFunctionsChanged();
491 ScFormulaCell
aCell( pDoc
, aPos
, pArr
,formula::FormulaGrammar::GRAM_DEFAULT
, MM_NONE
);
494 SvNumberFormatter
* pFormatter
= pDoc
->GetFormatTable();
495 ScMarkData::iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
496 for (; itr
!= itrEnd
; ++itr
)
500 sal_uLong nIndex
= (sal_uLong
) ((SfxUInt32Item
*) pDoc
->GetAttr(
501 nCol
, nRow
, i
, ATTR_VALUE_FORMAT
))->GetValue();
502 if ( pFormatter
->GetType( nIndex
) == NUMBERFORMAT_TEXT
||
503 ( ( rString
.GetChar(0) == '+' || rString
.GetChar(0) == '-' ) && nError
&& rString
.Equals( aFormula
) ) )
507 pCell
= new ScEditCell( pData
, pDoc
, NULL
);
509 pCell
= new ScStringCell( aFormula
);
510 rFunc
.PutCell( aPos
, pCell
, sal_False
);
514 ScFormulaCell
* pCell
= new ScFormulaCell( aCell
, *pDoc
, aPos
);
517 pCell
->GetCode()->DelRPN();
518 pCell
->SetErrCode( nError
);
519 if(pCell
->GetCode()->IsHyperLink())
520 pCell
->GetCode()->SetHyperLink(false);
522 rFunc
.PutCell( aPos
, pCell
, sal_False
);
528 ScMarkData::iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
529 for ( ; itr
!= itrEnd
; ++itr
)
531 bool bNumFmtSet
= false;
532 rFunc
.SetNormalString( bNumFmtSet
, ScAddress( nCol
, nRow
, *itr
), rString
, sal_False
);
535 /* FIXME: if set on any sheet results in changed only on
536 * sheet nTab for TestFormatArea() and DoAutoAttributes() */
537 bNumFmtChanged
= true;
542 sal_Bool bAutoFormat
= TestFormatArea(nCol
, nRow
, nTab
, bNumFmtChanged
);
545 DoAutoAttributes(nCol
, nRow
, nTab
, bNumFmtChanged
, bRecord
);
547 pDocSh
->UpdateOle(GetViewData());
549 // #i97876# Spreadsheet data changes are not notified
550 ScModelObj
* pModelObj
= ScModelObj::getImplementation( pDocSh
->GetModel() );
551 if ( pModelObj
&& pModelObj
->HasChangesListeners() )
553 ScRangeList aChangeRanges
;
554 ScMarkData::iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
555 for (; itr
!= itrEnd
; ++itr
)
556 aChangeRanges
.Append( ScRange( nCol
, nRow
, *itr
) );
558 pModelObj
->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges
);
562 rFunc
.EndListAction();
564 aModificator
.SetDocumentModified();
565 lcl_PostRepaintCondFormat( pDoc
->GetCondFormat( nCol
, nRow
, nTab
), pDocSh
);
569 ErrorMessage(aTester
.GetMessageId());
570 PaintArea( nCol
, nRow
, nCol
, nRow
); // possibly the edit-engine is still painted there
574 // enter value in single cell (on nTab only)
576 void ScViewFunc::EnterValue( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, const double& rValue
)
578 ScDocument
* pDoc
= GetViewData()->GetDocument();
579 ScDocShell
* pDocSh
= GetViewData()->GetDocShell();
581 if ( pDoc
&& pDocSh
)
583 sal_Bool
bUndo(pDoc
->IsUndoEnabled());
584 ScDocShellModificator
aModificator( *pDocSh
);
586 ScEditableTester
aTester( pDoc
, nTab
, nCol
,nRow
, nCol
,nRow
);
587 if (aTester
.IsEditable())
589 ScAddress
aPos( nCol
, nRow
, nTab
);
590 ScBaseCell
* pOldCell
= pDoc
->GetCell( aPos
);
593 ScBaseCell
* pUndoCell
= (bUndo
&& pOldCell
) ? pOldCell
->Clone( *pDoc
) : 0;
595 pDoc
->SetValue( nCol
, nRow
, nTab
, rValue
);
597 // because of ChangeTrack after change in document
600 pDocSh
->GetUndoManager()->AddUndoAction(
601 new ScUndoEnterValue( pDocSh
, aPos
, pUndoCell
, rValue
) );
604 pDocSh
->PostPaintCell( aPos
);
605 pDocSh
->UpdateOle(GetViewData());
606 aModificator
.SetDocumentModified();
609 ErrorMessage(aTester
.GetMessageId());
613 void ScViewFunc::EnterData( SCCOL nCol
, SCROW nRow
, SCTAB nTab
,
614 const EditTextObject
* pData
, bool bTestSimple
)
616 ScDocShell
* pDocSh
= GetViewData()->GetDocShell();
617 ScMarkData
& rMark
= GetViewData()->GetMarkData();
618 ScDocument
* pDoc
= pDocSh
->GetDocument();
619 bool bRecord
= pDoc
->IsUndoEnabled();
621 ScDocShellModificator
aModificator( *pDocSh
);
623 ScEditableTester
aTester( pDoc
, nTab
, nCol
,nRow
, nCol
,nRow
);
624 if (aTester
.IsEditable())
627 // test for attribute
629 sal_Bool bSimple
= false;
630 sal_Bool bCommon
= false;
631 ScPatternAttr
* pCellAttrs
= NULL
;
632 EditTextObject
* pNewData
= NULL
;
635 const ScPatternAttr
* pOldPattern
= pDoc
->GetPattern( nCol
, nRow
, nTab
);
636 ScTabEditEngine
aEngine( *pOldPattern
, pDoc
->GetEnginePool() );
637 aEngine
.SetText(*pData
);
639 if (bTestSimple
) // test, if simple string without attribute
641 ScEditAttrTester
aAttrTester( &aEngine
);
642 bSimple
= !aAttrTester
.NeedsObject();
643 bCommon
= aAttrTester
.NeedsCellAttr();
645 // formulas have to be recognized even if they're formatted
646 // (but commmon attributes are still collected)
648 if ( !bSimple
&& aEngine
.GetParagraphCount() == 1 )
650 String aParStr
= aEngine
.GetText( (sal_uInt16
) 0 );
651 if ( aParStr
.GetChar(0) == '=' )
655 if (bCommon
) // attribute for tab
657 pCellAttrs
= new ScPatternAttr( *pOldPattern
);
658 pCellAttrs
->GetFromEditItemSet( &aAttrTester
.GetAttribs() );
659 //! remove common attributes from EditEngine?
663 // #i97726# always get text for "repeat" of undo action
664 aString
= ScEditUtil::GetSpaceDelimitedString(aEngine
);
670 SCTAB nSelCount
= rMark
.GetSelectCount();
671 ScBaseCell
** ppOldCells
= NULL
;
674 EditTextObject
* pUndoData
= NULL
;
675 if (bRecord
&& !bSimple
)
677 ppOldCells
= new ScBaseCell
*[nSelCount
];
678 pTabs
= new SCTAB
[nSelCount
];
681 ScMarkData::iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
682 for (; itr
!= itrEnd
; ++itr
)
685 ScBaseCell
* pDocCell
;
686 pDoc
->GetCell( nCol
, nRow
, *itr
, pDocCell
);
687 ppOldCells
[nPos
] = pDocCell
? pDocCell
->Clone( *pDoc
) : 0;
691 OSL_ENSURE( nPos
==nSelCount
, "nPos!=nSelCount" );
693 pUndoData
= pData
->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
)
714 pDoc
->PutCell( nCol
, nRow
, *itr
, new ScEditCell( pData
, pDoc
, NULL
) );
717 { // because of ChangeTrack current first
718 pDocSh
->GetUndoManager()->AddUndoAction(
719 new ScUndoEnterData( pDocSh
, nCol
, nRow
, nTab
, nPos
, pTabs
,
720 ppOldCells
, NULL
, NULL
, aString
,
726 AdjustRowHeight(nRow
,nRow
);
729 for (; itr
!= itrEnd
; ++itr
)
730 pDocSh
->PostPaintCell( nCol
, nRow
, *itr
);
734 pDocSh
->UpdateOle(GetViewData());
736 // #i97876# Spreadsheet data changes are not notified
737 ScModelObj
* pModelObj
= ScModelObj::getImplementation( pDocSh
->GetModel() );
738 if ( pModelObj
&& pModelObj
->HasChangesListeners() )
740 ScRangeList aChangeRanges
;
742 for (; itr
!= itrEnd
; ++itr
)
744 aChangeRanges
.Append( ScRange( nCol
, nRow
, *itr
) );
746 pModelObj
->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges
);
749 aModificator
.SetDocumentModified();
751 lcl_PostRepaintCondFormat( pDoc
->GetCondFormat( nCol
, nRow
, nTab
), pDocSh
);
758 ErrorMessage(aTester
.GetMessageId());
759 PaintArea( nCol
, nRow
, nCol
, nRow
); // possibly the edit-engine is still painted there
763 void ScViewFunc::EnterDataAtCursor( const String
& rString
)
765 SCCOL nPosX
= GetViewData()->GetCurX();
766 SCROW nPosY
= GetViewData()->GetCurY();
767 SCTAB nTab
= GetViewData()->GetTabNo();
769 EnterData( nPosX
, nPosY
, nTab
, rString
);
772 void ScViewFunc::EnterMatrix( const String
& rString
, ::formula::FormulaGrammar::Grammar eGram
)
774 ScViewData
* pData
= GetViewData();
775 const ScMarkData
& rMark
= pData
->GetMarkData();
776 if ( !rMark
.IsMarked() && !rMark
.IsMultiMarked() )
778 // nothing marked -> temporarily calculate block
779 // with size of result formula to get the size
781 ScDocument
* pDoc
= pData
->GetDocument();
782 SCCOL nCol
= pData
->GetCurX();
783 SCROW nRow
= pData
->GetCurY();
784 SCTAB nTab
= pData
->GetTabNo();
785 ScFormulaCell
aFormCell( pDoc
, ScAddress(nCol
,nRow
,nTab
), rString
, eGram
, MM_FORMULA
);
789 aFormCell
.GetResultDimensions( nSizeX
, nSizeY
);
790 if ( nSizeX
!= 0 && nSizeY
!= 0 &&
791 nCol
+nSizeX
-1 <= sal::static_int_cast
<SCSIZE
>(MAXCOL
) &&
792 nRow
+nSizeY
-1 <= sal::static_int_cast
<SCSIZE
>(MAXROW
) )
794 ScRange
aResult( nCol
, nRow
, nTab
,
795 sal::static_int_cast
<SCCOL
>(nCol
+nSizeX
-1),
796 sal::static_int_cast
<SCROW
>(nRow
+nSizeY
-1), nTab
);
797 MarkRange( aResult
, false );
802 if (pData
->GetSimpleArea(aRange
) == SC_MARK_SIMPLE
)
804 ScDocShell
* pDocSh
= pData
->GetDocShell();
805 bool bSuccess
= pDocSh
->GetDocFunc().EnterMatrix(
806 aRange
, &rMark
, NULL
, rString
, false, false, EMPTY_STRING
, eGram
);
808 pDocSh
->UpdateOle(GetViewData());
811 ErrorMessage(STR_NOMULTISELECT
);
814 sal_uInt8
ScViewFunc::GetSelectionScriptType()
816 sal_uInt8 nScript
= 0;
818 ScDocument
* pDoc
= GetViewData()->GetDocument();
819 const ScMarkData
& rMark
= GetViewData()->GetMarkData();
820 if ( !rMark
.IsMarked() && !rMark
.IsMultiMarked() )
822 // no selection -> cursor
824 nScript
= pDoc
->GetScriptType( GetViewData()->GetCurX(),
825 GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
830 rMark
.FillRangeListWithMarks( &aRanges
, false );
831 size_t nCount
= aRanges
.size();
832 for ( size_t i
=0; i
< nCount
; i
++ )
834 ScRange aRange
= *aRanges
[i
];
835 ScCellIterator
aIter( pDoc
, aRange
);
836 ScBaseCell
* pCell
= aIter
.GetFirst();
839 nScript
|= pDoc
->GetScriptType( aIter
.GetCol(), aIter
.GetRow(), aIter
.GetTab(), pCell
);
840 pCell
= aIter
.GetNext();
846 nScript
= ScGlobal::GetDefaultScriptType();
851 const ScPatternAttr
* ScViewFunc::GetSelectionPattern()
853 // Don't use UnmarkFiltered in slot state functions, for performance reasons.
854 // The displayed state is always that of the whole selection including filtered rows.
856 const ScMarkData
& rMark
= GetViewData()->GetMarkData();
857 ScDocument
* pDoc
= GetViewData()->GetDocument();
858 if ( rMark
.IsMarked() || rMark
.IsMultiMarked() )
860 // MarkToMulti is no longer necessary for pDoc->GetSelectionPattern
861 const ScPatternAttr
* pAttr
= pDoc
->GetSelectionPattern( rMark
);
866 SCCOL nCol
= GetViewData()->GetCurX();
867 SCROW nRow
= GetViewData()->GetCurY();
868 SCTAB nTab
= GetViewData()->GetTabNo();
870 ScMarkData
aTempMark( rMark
); // copy sheet selection
871 aTempMark
.SetMarkArea( ScRange( nCol
, nRow
, nTab
) );
872 const ScPatternAttr
* pAttr
= pDoc
->GetSelectionPattern( aTempMark
);
877 void ScViewFunc::GetSelectionFrame( SvxBoxItem
& rLineOuter
,
878 SvxBoxInfoItem
& rLineInner
)
880 ScDocument
* pDoc
= GetViewData()->GetDocument();
881 const ScMarkData
& rMark
= GetViewData()->GetMarkData();
883 if ( rMark
.IsMarked() || rMark
.IsMultiMarked() )
885 if ( rMark
.IsMultiMarked() )
887 ScMarkData
aNewMark( rMark
); // use local copy for MarkToSimple
888 aNewMark
.MarkToSimple(); // simple block is needed for GetSelectionFrame
889 pDoc
->GetSelectionFrame( aNewMark
, rLineOuter
, rLineInner
);
892 pDoc
->GetSelectionFrame( rMark
, rLineOuter
, rLineInner
);
896 const ScPatternAttr
* pAttrs
=
897 pDoc
->GetPattern( GetViewData()->GetCurX(),
898 GetViewData()->GetCurY(),
899 GetViewData()->GetTabNo() );
901 rLineOuter
= (const SvxBoxItem
&) (pAttrs
->GetItem( ATTR_BORDER
));
902 rLineInner
= (const SvxBoxInfoItem
&)(pAttrs
->GetItem( ATTR_BORDER_INNER
));
903 rLineInner
.SetTable(false);
904 rLineInner
.SetDist(sal_True
);
905 rLineInner
.SetMinDist(false);
910 // apply attribute - undo OK
912 // complete set ( ATTR_STARTINDEX, ATTR_ENDINDEX )
915 void ScViewFunc::ApplyAttributes( const SfxItemSet
* pDialogSet
,
916 const SfxItemSet
* pOldSet
,
919 // not editable because of matrix only? attribute OK nonetheless
920 bool bOnlyNotBecauseOfMatrix
;
921 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix
) && !bOnlyNotBecauseOfMatrix
)
923 ErrorMessage(STR_PROTECTIONERR
);
927 ScPatternAttr
aOldAttrs( new SfxItemSet(*pOldSet
) );
928 ScPatternAttr
aNewAttrs( new SfxItemSet(*pDialogSet
) );
929 aNewAttrs
.DeleteUnchanged( &aOldAttrs
);
931 if ( pDialogSet
->GetItemState( ATTR_VALUE_FORMAT
) == SFX_ITEM_SET
)
932 { // don't reset to default SYSTEM GENERAL if not intended
933 sal_uInt32 nOldFormat
=
934 ((const SfxUInt32Item
&)pOldSet
->Get( ATTR_VALUE_FORMAT
)).GetValue();
935 sal_uInt32 nNewFormat
=
936 ((const SfxUInt32Item
&)pDialogSet
->Get( ATTR_VALUE_FORMAT
)).GetValue();
937 if ( nNewFormat
!= nOldFormat
)
939 SvNumberFormatter
* pFormatter
=
940 GetViewData()->GetDocument()->GetFormatTable();
941 const SvNumberformat
* pOldEntry
= pFormatter
->GetEntry( nOldFormat
);
942 LanguageType eOldLang
=
943 pOldEntry
? pOldEntry
->GetLanguage() : LANGUAGE_DONTKNOW
;
944 const SvNumberformat
* pNewEntry
= pFormatter
->GetEntry( nNewFormat
);
945 LanguageType eNewLang
=
946 pNewEntry
? pNewEntry
->GetLanguage() : LANGUAGE_DONTKNOW
;
947 if ( eNewLang
!= eOldLang
)
949 aNewAttrs
.GetItemSet().Put(
950 SvxLanguageItem( eNewLang
, ATTR_LANGUAGE_FORMAT
) );
952 // only the language has changed -> do not touch numberformat-attribute
953 sal_uInt32 nNewMod
= nNewFormat
% SV_COUNTRY_LANGUAGE_OFFSET
;
954 if ( nNewMod
== ( nOldFormat
% SV_COUNTRY_LANGUAGE_OFFSET
) &&
955 nNewMod
<= SV_MAX_ANZ_STANDARD_FORMATE
)
956 aNewAttrs
.GetItemSet().ClearItem( ATTR_VALUE_FORMAT
);
961 const SvxBoxItem
* pOldOuter
= (const SvxBoxItem
*) &pOldSet
->Get( ATTR_BORDER
);
962 const SvxBoxItem
* pNewOuter
= (const SvxBoxItem
*) &pDialogSet
->Get( ATTR_BORDER
);
963 const SvxBoxInfoItem
* pOldInner
= (const SvxBoxInfoItem
*) &pOldSet
->Get( ATTR_BORDER_INNER
);
964 const SvxBoxInfoItem
* pNewInner
= (const SvxBoxInfoItem
*) &pDialogSet
->Get( ATTR_BORDER_INNER
);
965 SfxItemSet
& rNewSet
= aNewAttrs
.GetItemSet();
966 SfxItemPool
* pNewPool
= rNewSet
.GetPool();
968 pNewPool
->Put( *pNewOuter
); // don't delete yet
969 pNewPool
->Put( *pNewInner
);
970 rNewSet
.ClearItem( ATTR_BORDER
);
971 rNewSet
.ClearItem( ATTR_BORDER_INNER
);
974 * establish whether border attribute is to be set:
976 * 2. is one of the borders not-DontCare (since 238.f: IsxxValid())
980 sal_Bool bFrame
= (pDialogSet
->GetItemState( ATTR_BORDER
) != SFX_ITEM_DEFAULT
)
981 || (pDialogSet
->GetItemState( ATTR_BORDER_INNER
) != SFX_ITEM_DEFAULT
);
983 if ( pNewOuter
==pOldOuter
&& pNewInner
==pOldInner
)
986 // this should be intercepted by the pool: ?!??!??
988 if ( bFrame
&& pNewOuter
&& pNewInner
)
989 if ( *pNewOuter
== *pOldOuter
&& *pNewInner
== *pOldInner
)
995 && ( pNewInner
->IsValid(VALID_LEFT
)
996 || pNewInner
->IsValid(VALID_RIGHT
)
997 || pNewInner
->IsValid(VALID_TOP
)
998 || pNewInner
->IsValid(VALID_BOTTOM
)
999 || pNewInner
->IsValid(VALID_HORI
)
1000 || pNewInner
->IsValid(VALID_VERT
) );
1006 ApplySelectionPattern( aNewAttrs
, bRecord
); // standard only
1009 // if new items are default-items, overwrite the old items:
1011 sal_Bool bDefNewOuter
= ( SFX_ITEMS_STATICDEFAULT
== pNewOuter
->GetKind() );
1012 sal_Bool bDefNewInner
= ( SFX_ITEMS_STATICDEFAULT
== pNewInner
->GetKind() );
1014 ApplyPatternLines( aNewAttrs
,
1015 bDefNewOuter
? pOldOuter
: pNewOuter
,
1016 bDefNewInner
? pOldInner
: pNewInner
,
1020 pNewPool
->Remove( *pNewOuter
); // release
1021 pNewPool
->Remove( *pNewInner
);
1024 AdjustBlockHeight();
1026 // CellContentChanged is called in ApplySelectionPattern / ApplyPatternLines
1029 void ScViewFunc::ApplyAttr( const SfxPoolItem
& rAttrItem
)
1031 // not editable because of matrix only? attribute OK nonetheless
1032 bool bOnlyNotBecauseOfMatrix
;
1033 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix
) && !bOnlyNotBecauseOfMatrix
)
1035 ErrorMessage(STR_PROTECTIONERR
);
1039 ScPatternAttr
aNewAttrs( new SfxItemSet( *GetViewData()->GetDocument()->GetPool(),
1040 ATTR_PATTERN_START
, ATTR_PATTERN_END
) );
1042 aNewAttrs
.GetItemSet().Put( rAttrItem
);
1043 // if justify is set (with Buttons), always indentation 0
1044 if ( rAttrItem
.Which() == ATTR_HOR_JUSTIFY
)
1045 aNewAttrs
.GetItemSet().Put( SfxUInt16Item( ATTR_INDENT
, 0 ) );
1046 ApplySelectionPattern( aNewAttrs
);
1048 AdjustBlockHeight();
1050 // CellContentChanged is called in ApplySelectionPattern
1054 // patterns and borders
1056 void ScViewFunc::ApplyPatternLines( const ScPatternAttr
& rAttr
, const SvxBoxItem
* pNewOuter
,
1057 const SvxBoxInfoItem
* pNewInner
, sal_Bool bRecord
)
1059 ScDocument
* pDoc
= GetViewData()->GetDocument();
1060 ScMarkData
aFuncMark( GetViewData()->GetMarkData() ); // local copy for UnmarkFiltered
1061 ScViewUtil::UnmarkFiltered( aFuncMark
, pDoc
);
1062 if (bRecord
&& !pDoc
->IsUndoEnabled())
1066 aFuncMark
.MarkToSimple();
1067 sal_Bool bMulti
= aFuncMark
.IsMultiMarked();
1069 aFuncMark
.GetMultiMarkArea( aMarkRange
);
1070 else if (aFuncMark
.IsMarked())
1071 aFuncMark
.GetMarkArea( aMarkRange
);
1074 aMarkRange
= ScRange( GetViewData()->GetCurX(),
1075 GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
1078 aFuncMark
.SetMarkArea(aMarkRange
);
1082 ScDocShell
* pDocSh
= GetViewData()->GetDocShell();
1084 ScDocShellModificator
aModificator( *pDocSh
);
1088 ScDocument
* pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
1089 SCTAB nStartTab
= aMarkRange
.aStart
.Tab();
1090 SCTAB nTabCount
= pDoc
->GetTableCount();
1091 pUndoDoc
->InitUndo( pDoc
, nStartTab
, nStartTab
);
1092 ScMarkData::iterator itr
= aFuncMark
.begin(), itrEnd
= aFuncMark
.end();
1093 for (; itr
!= itrEnd
; ++itr
)
1094 if (*itr
!= nStartTab
)
1095 pUndoDoc
->AddUndoTab( *itr
, *itr
);
1097 ScRange aCopyRange
= aMarkRange
;
1098 aCopyRange
.aStart
.SetTab(0);
1099 aCopyRange
.aEnd
.SetTab(nTabCount
-1);
1100 pDoc
->CopyToDocument( aCopyRange
, IDF_ATTRIB
, bMulti
, pUndoDoc
, &aFuncMark
);
1102 pDocSh
->GetUndoManager()->AddUndoAction(
1103 new ScUndoSelectionAttr(
1105 aMarkRange
.aStart
.Col(), aMarkRange
.aStart
.Row(), aMarkRange
.aStart
.Tab(),
1106 aMarkRange
.aEnd
.Col(), aMarkRange
.aEnd
.Row(), aMarkRange
.aEnd
.Tab(),
1107 pUndoDoc
, bMulti
, &rAttr
, pNewOuter
, pNewInner
) );
1110 sal_uInt16 nExt
= SC_PF_TESTMERGE
;
1111 pDocSh
->UpdatePaintExt( nExt
, aMarkRange
); // content before the change
1113 pDoc
->ApplySelectionFrame( aFuncMark
, pNewOuter
, pNewInner
);
1115 pDocSh
->UpdatePaintExt( nExt
, aMarkRange
); // content after the change
1117 aFuncMark
.MarkToMulti();
1118 pDoc
->ApplySelectionPattern( rAttr
, aFuncMark
);
1120 pDocSh
->PostPaint( aMarkRange
, PAINT_GRID
, nExt
);
1121 pDocSh
->UpdateOle(GetViewData());
1122 aModificator
.SetDocumentModified();
1123 CellContentChanged();
1130 void ScViewFunc::ApplySelectionPattern( const ScPatternAttr
& rAttr
,
1131 sal_Bool bRecord
, sal_Bool bCursorOnly
)
1133 ScViewData
* pViewData
= GetViewData();
1134 ScDocShell
* pDocSh
= pViewData
->GetDocShell();
1135 ScDocument
* pDoc
= pDocSh
->GetDocument();
1136 ScMarkData
aFuncMark( pViewData
->GetMarkData() ); // local copy for UnmarkFiltered
1137 ScViewUtil::UnmarkFiltered( aFuncMark
, pDoc
);
1139 if (bRecord
&& !pDoc
->IsUndoEnabled())
1142 // State from old ItemSet doesn't matter for paint flags, as any change will be
1143 // from SFX_ITEM_SET in the new ItemSet (default is ignored in ApplyPattern).
1144 // New alignment is checked (check in PostPaint isn't enough) in case a right
1145 // alignment is changed to left.
1146 const SfxItemSet
& rNewSet
= rAttr
.GetItemSet();
1147 sal_Bool bSetLines
= rNewSet
.GetItemState( ATTR_BORDER
, sal_True
) == SFX_ITEM_SET
||
1148 rNewSet
.GetItemState( ATTR_SHADOW
, sal_True
) == SFX_ITEM_SET
;
1149 sal_Bool bSetAlign
= rNewSet
.GetItemState( ATTR_HOR_JUSTIFY
, sal_True
) == SFX_ITEM_SET
;
1151 sal_uInt16 nExtFlags
= 0;
1153 nExtFlags
|= SC_PF_LINES
;
1155 nExtFlags
|= SC_PF_WHOLEROWS
;
1157 ScDocShellModificator
aModificator( *pDocSh
);
1159 sal_Bool bMulti
= aFuncMark
.IsMultiMarked();
1160 aFuncMark
.MarkToMulti();
1161 sal_Bool bOnlyTab
= (!aFuncMark
.IsMultiMarked() && !bCursorOnly
&& aFuncMark
.GetSelectCount() > 1);
1164 SCCOL nCol
= pViewData
->GetCurX();
1165 SCROW nRow
= pViewData
->GetCurY();
1166 SCTAB nTab
= pViewData
->GetTabNo();
1167 aFuncMark
.SetMarkArea(ScRange(nCol
,nRow
,nTab
));
1168 aFuncMark
.MarkToMulti();
1171 ScRangeList aChangeRanges
;
1173 if (aFuncMark
.IsMultiMarked() && !bCursorOnly
)
1176 aFuncMark
.GetMultiMarkArea( aMarkRange
);
1177 SCTAB nTabCount
= pDoc
->GetTableCount();
1178 ScMarkData::iterator itr
= aFuncMark
.begin(), itrEnd
= aFuncMark
.end();
1179 for (; itr
!= itrEnd
; ++itr
)
1181 ScRange
aChangeRange( aMarkRange
);
1182 aChangeRange
.aStart
.SetTab( *itr
);
1183 aChangeRange
.aEnd
.SetTab( *itr
);
1184 aChangeRanges
.Append( aChangeRange
);
1187 SCCOL nStartCol
= aMarkRange
.aStart
.Col();
1188 SCROW nStartRow
= aMarkRange
.aStart
.Row();
1189 SCTAB nStartTab
= aMarkRange
.aStart
.Tab();
1190 SCCOL nEndCol
= aMarkRange
.aEnd
.Col();
1191 SCROW nEndRow
= aMarkRange
.aEnd
.Row();
1192 SCTAB nEndTab
= aMarkRange
.aEnd
.Tab();
1194 ScUndoSelectionAttr
* pUndoAttr
= NULL
;
1195 ScEditDataArray
* pEditDataArray
= NULL
;
1198 ScRange aCopyRange
= aMarkRange
;
1199 aCopyRange
.aStart
.SetTab(0);
1200 aCopyRange
.aEnd
.SetTab(nTabCount
-1);
1202 ScDocument
* pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
1203 pUndoDoc
->InitUndo( pDoc
, nStartTab
, nStartTab
);
1204 itr
= aFuncMark
.begin();
1205 for (; itr
!= itrEnd
; ++itr
)
1206 if (*itr
!= nStartTab
)
1207 pUndoDoc
->AddUndoTab( *itr
, *itr
);
1208 pDoc
->CopyToDocument( aCopyRange
, IDF_ATTRIB
, bMulti
, pUndoDoc
, &aFuncMark
);
1210 aFuncMark
.MarkToMulti();
1212 pUndoAttr
= new ScUndoSelectionAttr(
1213 pDocSh
, aFuncMark
, nStartCol
, nStartRow
, nStartTab
,
1214 nEndCol
, nEndRow
, nEndTab
, pUndoDoc
, bMulti
, &rAttr
);
1215 pDocSh
->GetUndoManager()->AddUndoAction(pUndoAttr
);
1216 pEditDataArray
= pUndoAttr
->GetDataArray();
1219 pDoc
->ApplySelectionPattern( rAttr
, aFuncMark
, pEditDataArray
);
1221 pDocSh
->PostPaint( nStartCol
, nStartRow
, nStartTab
,
1222 nEndCol
, nEndRow
, nEndTab
,
1223 PAINT_GRID
, nExtFlags
| SC_PF_TESTMERGE
);
1224 pDocSh
->UpdateOle(GetViewData());
1225 aModificator
.SetDocumentModified();
1226 CellContentChanged();
1228 else // single cell - simpler undo
1230 SCCOL nCol
= pViewData
->GetCurX();
1231 SCROW nRow
= pViewData
->GetCurY();
1232 SCTAB nTab
= pViewData
->GetTabNo();
1235 pDoc
->GetCell(nCol
, nRow
, nTab
, pCell
);
1236 EditTextObject
* pOldEditData
= NULL
;
1237 EditTextObject
* pNewEditData
= NULL
;
1238 if (pCell
&& pCell
->GetCellType() == CELLTYPE_EDIT
)
1240 ScEditCell
* pEditCell
= static_cast<ScEditCell
*>(pCell
);
1241 pOldEditData
= pEditCell
->GetData()->Clone();
1242 pEditCell
->RemoveCharAttribs(rAttr
);
1243 pNewEditData
= pEditCell
->GetData()->Clone();
1246 aChangeRanges
.Append( ScRange( nCol
, nRow
, nTab
) );
1247 ScPatternAttr
* pOldPat
= new ScPatternAttr(*pDoc
->GetPattern( nCol
, nRow
, nTab
));
1249 pDoc
->ApplyPattern( nCol
, nRow
, nTab
, rAttr
);
1251 const ScPatternAttr
* pNewPat
= pDoc
->GetPattern( nCol
, nRow
, nTab
);
1255 ScUndoCursorAttr
* pUndo
= new ScUndoCursorAttr(
1256 pDocSh
, nCol
, nRow
, nTab
, pOldPat
, pNewPat
, &rAttr
, false );
1257 pUndo
->SetEditData(pOldEditData
, pNewEditData
);
1258 pDocSh
->GetUndoManager()->AddUndoAction(pUndo
);
1260 delete pOldPat
; // is copied in undo (Pool)
1262 pDocSh
->PostPaint( nCol
,nRow
,nTab
, nCol
,nRow
,nTab
, PAINT_GRID
, nExtFlags
| SC_PF_TESTMERGE
);
1263 pDocSh
->UpdateOle(GetViewData());
1264 aModificator
.SetDocumentModified();
1265 CellContentChanged();
1268 // #i97876# Spreadsheet data changes are not notified
1269 ScModelObj
* pModelObj
= ScModelObj::getImplementation( pDocSh
->GetModel() );
1270 if ( pModelObj
&& pModelObj
->HasChangesListeners() )
1272 ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::PropertyValue
> aProperties
;
1273 sal_Int32 nCount
= 0;
1274 const SfxItemPropertyMap
& rMap
= ScCellObj::GetCellPropertyMap();
1275 PropertyEntryVector_t aPropVector
= rMap
.getPropertyEntries();
1276 for ( sal_uInt16 nWhich
= ATTR_PATTERN_START
; nWhich
<= ATTR_PATTERN_END
; ++nWhich
)
1278 const SfxPoolItem
* pItem
= 0;
1279 if ( rNewSet
.GetItemState( nWhich
, sal_True
, &pItem
) == SFX_ITEM_SET
&& pItem
)
1281 PropertyEntryVector_t::const_iterator aIt
= aPropVector
.begin();
1282 while ( aIt
!= aPropVector
.end())
1284 if ( aIt
->nWID
== nWhich
)
1286 ::com::sun::star::uno::Any aVal
;
1287 pItem
->QueryValue( aVal
, aIt
->nMemberId
);
1288 aProperties
.realloc( nCount
+ 1 );
1289 aProperties
[ nCount
].Name
= aIt
->sName
;
1290 aProperties
[ nCount
].Value
<<= aVal
;
1297 pModelObj
->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "attribute" ) ), aChangeRanges
, aProperties
);
1303 void ScViewFunc::ApplyUserItemSet( const SfxItemSet
& rItemSet
)
1305 // ItemSet from UI, may have different pool
1307 bool bOnlyNotBecauseOfMatrix
;
1308 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix
) && !bOnlyNotBecauseOfMatrix
)
1310 ErrorMessage(STR_PROTECTIONERR
);
1314 ScPatternAttr
aNewAttrs( GetViewData()->GetDocument()->GetPool() );
1315 SfxItemSet
& rNewSet
= aNewAttrs
.GetItemSet();
1316 rNewSet
.Put( rItemSet
, false );
1317 ApplySelectionPattern( aNewAttrs
);
1319 AdjustBlockHeight();
1322 const SfxStyleSheet
* ScViewFunc::GetStyleSheetFromMarked()
1324 // Don't use UnmarkFiltered in slot state functions, for performance reasons.
1325 // The displayed state is always that of the whole selection including filtered rows.
1327 const ScStyleSheet
* pSheet
= NULL
;
1328 ScViewData
* pViewData
= GetViewData();
1329 ScDocument
* pDoc
= pViewData
->GetDocument();
1330 ScMarkData
& rMark
= pViewData
->GetMarkData();
1332 if ( rMark
.IsMarked() || rMark
.IsMultiMarked() )
1333 pSheet
= pDoc
->GetSelectionStyle( rMark
); // MarkToMulti isn't necessary
1335 pSheet
= pDoc
->GetStyle( pViewData
->GetCurX(),
1336 pViewData
->GetCurY(),
1337 pViewData
->GetTabNo() );
1342 void ScViewFunc::SetStyleSheetToMarked( SfxStyleSheet
* pStyleSheet
, sal_Bool bRecord
)
1344 // not editable because of matrix only? attribute OK nonetheless
1345 bool bOnlyNotBecauseOfMatrix
;
1346 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix
) && !bOnlyNotBecauseOfMatrix
)
1348 ErrorMessage(STR_PROTECTIONERR
);
1352 if ( !pStyleSheet
) return;
1353 // -------------------------------------------------------------------
1355 ScViewData
* pViewData
= GetViewData();
1356 ScDocShell
* pDocSh
= pViewData
->GetDocShell();
1357 ScDocument
* pDoc
= pDocSh
->GetDocument();
1358 ScMarkData
aFuncMark( pViewData
->GetMarkData() ); // local copy for UnmarkFiltered
1359 ScViewUtil::UnmarkFiltered( aFuncMark
, pDoc
);
1360 SCTAB nTabCount
= pDoc
->GetTableCount();
1361 if (bRecord
&& !pDoc
->IsUndoEnabled())
1364 ScDocShellModificator
aModificator( *pDocSh
);
1366 if ( aFuncMark
.IsMarked() || aFuncMark
.IsMultiMarked() )
1369 aFuncMark
.MarkToMulti();
1370 aFuncMark
.GetMultiMarkArea( aMarkRange
);
1374 SCTAB nTab
= pViewData
->GetTabNo();
1375 ScDocument
* pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
1376 pUndoDoc
->InitUndo( pDoc
, nTab
, nTab
);
1377 ScMarkData::iterator itr
= aFuncMark
.begin(), itrEnd
= aFuncMark
.end();
1378 for (; itr
!= itrEnd
; ++itr
)
1380 pUndoDoc
->AddUndoTab( *itr
, *itr
);
1382 ScRange aCopyRange
= aMarkRange
;
1383 aCopyRange
.aStart
.SetTab(0);
1384 aCopyRange
.aEnd
.SetTab(nTabCount
-1);
1385 pDoc
->CopyToDocument( aCopyRange
, IDF_ATTRIB
, sal_True
, pUndoDoc
, &aFuncMark
);
1386 aFuncMark
.MarkToMulti();
1388 String aName
= pStyleSheet
->GetName();
1389 pDocSh
->GetUndoManager()->AddUndoAction(
1390 new ScUndoSelectionStyle( pDocSh
, aFuncMark
, aMarkRange
, aName
, pUndoDoc
) );
1393 pDoc
->ApplySelectionStyle( (ScStyleSheet
&)*pStyleSheet
, aFuncMark
);
1395 if (!AdjustBlockHeight())
1396 pViewData
->GetDocShell()->PostPaint( aMarkRange
, PAINT_GRID
);
1398 aFuncMark
.MarkToSimple();
1402 SCCOL nCol
= pViewData
->GetCurX();
1403 SCROW nRow
= pViewData
->GetCurY();
1404 SCTAB nTab
= pViewData
->GetTabNo();
1408 ScDocument
* pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
1409 pUndoDoc
->InitUndo( pDoc
, nTab
, nTab
);
1410 ScMarkData::iterator itr
= aFuncMark
.begin(), itrEnd
= aFuncMark
.end();
1411 for (; itr
!= itrEnd
; ++itr
)
1413 pUndoDoc
->AddUndoTab( *itr
, *itr
);
1415 ScRange
aCopyRange( nCol
, nRow
, 0, nCol
, nRow
, nTabCount
-1 );
1416 pDoc
->CopyToDocument( aCopyRange
, IDF_ATTRIB
, false, pUndoDoc
);
1418 ScRange
aMarkRange ( nCol
, nRow
, nTab
);
1419 ScMarkData aUndoMark
= aFuncMark
;
1420 aUndoMark
.SetMultiMarkArea( aMarkRange
);
1422 String aName
= pStyleSheet
->GetName();
1423 pDocSh
->GetUndoManager()->AddUndoAction(
1424 new ScUndoSelectionStyle( pDocSh
, aUndoMark
, aMarkRange
, aName
, pUndoDoc
) );
1427 ScMarkData::iterator itr
= aFuncMark
.begin(), itrEnd
= aFuncMark
.end();
1428 for (; itr
!= itrEnd
; ++itr
)
1429 pDoc
->ApplyStyle( nCol
, nRow
, *itr
, (ScStyleSheet
&)*pStyleSheet
);
1431 if (!AdjustBlockHeight())
1432 pViewData
->GetDocShell()->PostPaintCell( nCol
, nRow
, nTab
);
1436 aModificator
.SetDocumentModified();
1442 void ScViewFunc::RemoveStyleSheetInUse( const SfxStyleSheetBase
* pStyleSheet
)
1444 if ( !pStyleSheet
) return;
1445 // -------------------------------------------------------------------
1447 ScViewData
* pViewData
= GetViewData();
1448 ScDocument
* pDoc
= pViewData
->GetDocument();
1449 ScDocShell
* pDocSh
= pViewData
->GetDocShell();
1451 ScDocShellModificator
aModificator( *pDocSh
);
1453 VirtualDevice aVirtDev
;
1454 aVirtDev
.SetMapMode(MAP_PIXEL
);
1455 pDoc
->StyleSheetChanged( pStyleSheet
, sal_True
, &aVirtDev
,
1456 pViewData
->GetPPTX(),
1457 pViewData
->GetPPTY(),
1458 pViewData
->GetZoomX(),
1459 pViewData
->GetZoomY() );
1461 pDocSh
->PostPaint( 0,0,0, MAXCOL
,MAXROW
,MAXTAB
, PAINT_GRID
|PAINT_LEFT
);
1462 aModificator
.SetDocumentModified();
1464 ScInputHandler
* pHdl
= SC_MOD()->GetInputHdl();
1466 pHdl
->ForgetLastPattern();
1469 void ScViewFunc::UpdateStyleSheetInUse( const SfxStyleSheetBase
* pStyleSheet
)
1471 if ( !pStyleSheet
) return;
1472 // -------------------------------------------------------------------
1474 ScViewData
* pViewData
= GetViewData();
1475 ScDocument
* pDoc
= pViewData
->GetDocument();
1476 ScDocShell
* pDocSh
= pViewData
->GetDocShell();
1478 ScDocShellModificator
aModificator( *pDocSh
);
1480 VirtualDevice aVirtDev
;
1481 aVirtDev
.SetMapMode(MAP_PIXEL
);
1482 pDoc
->StyleSheetChanged( pStyleSheet
, false, &aVirtDev
,
1483 pViewData
->GetPPTX(),
1484 pViewData
->GetPPTY(),
1485 pViewData
->GetZoomX(),
1486 pViewData
->GetZoomY() );
1488 pDocSh
->PostPaint( 0,0,0, MAXCOL
,MAXROW
,MAXTAB
, PAINT_GRID
|PAINT_LEFT
);
1489 aModificator
.SetDocumentModified();
1491 ScInputHandler
* pHdl
= SC_MOD()->GetInputHdl();
1493 pHdl
->ForgetLastPattern();
1496 // insert cells - undo OK
1498 sal_Bool
ScViewFunc::InsertCells( InsCellCmd eCmd
, sal_Bool bRecord
, sal_Bool bPartOfPaste
)
1501 if (GetViewData()->GetSimpleArea(aRange
) == SC_MARK_SIMPLE
)
1503 ScDocShell
* pDocSh
= GetViewData()->GetDocShell();
1504 const ScMarkData
& rMark
= GetViewData()->GetMarkData();
1505 sal_Bool bSuccess
= pDocSh
->GetDocFunc().InsertCells( aRange
, &rMark
, eCmd
, bRecord
, false, bPartOfPaste
);
1508 pDocSh
->UpdateOle(GetViewData());
1509 CellContentChanged();
1511 // #i97876# Spreadsheet data changes are not notified
1512 ScModelObj
* pModelObj
= ScModelObj::getImplementation( pDocSh
->GetModel() );
1513 if ( pModelObj
&& pModelObj
->HasChangesListeners() )
1515 if ( eCmd
== INS_INSROWS
|| eCmd
== INS_INSCOLS
)
1517 ScRangeList aChangeRanges
;
1518 aChangeRanges
.Append( aRange
);
1519 ::rtl::OUString aOperation
= ( eCmd
== INS_INSROWS
?
1520 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert-rows" ) ) :
1521 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert-columns" ) ) );
1522 pModelObj
->NotifyChanges( aOperation
, aChangeRanges
);
1530 ErrorMessage(STR_NOMULTISELECT
);
1535 // delete cells - undo OK
1537 void ScViewFunc::DeleteCells( DelCellCmd eCmd
, sal_Bool bRecord
)
1540 if ( GetViewData()->GetSimpleArea( aRange
) == SC_MARK_SIMPLE
)
1542 ScDocShell
* pDocSh
= GetViewData()->GetDocShell();
1543 const ScMarkData
& rMark
= GetViewData()->GetMarkData();
1545 // #i94841# [Collaboration] if deleting rows is rejected, the content is sometimes wrong
1546 if ( pDocSh
->IsDocShared() && ( eCmd
== DEL_DELROWS
|| eCmd
== DEL_DELCOLS
) )
1548 ScRange
aDelRange( aRange
.aStart
);
1549 SCCOLROW nCount
= 0;
1550 if ( eCmd
== DEL_DELROWS
)
1552 nCount
= sal::static_int_cast
< SCCOLROW
>( aRange
.aEnd
.Row() - aRange
.aStart
.Row() + 1 );
1556 nCount
= sal::static_int_cast
< SCCOLROW
>( aRange
.aEnd
.Col() - aRange
.aStart
.Col() + 1 );
1558 while ( nCount
> 0 )
1560 pDocSh
->GetDocFunc().DeleteCells( aDelRange
, &rMark
, eCmd
, bRecord
, false );
1566 pDocSh
->GetDocFunc().DeleteCells( aRange
, &rMark
, eCmd
, bRecord
, false );
1569 pDocSh
->UpdateOle(GetViewData());
1570 CellContentChanged();
1572 // #i97876# Spreadsheet data changes are not notified
1573 ScModelObj
* pModelObj
= ScModelObj::getImplementation( pDocSh
->GetModel() );
1574 if ( pModelObj
&& pModelObj
->HasChangesListeners() )
1576 if ( eCmd
== DEL_DELROWS
|| eCmd
== DEL_DELCOLS
)
1578 ScRangeList aChangeRanges
;
1579 aChangeRanges
.Append( aRange
);
1580 ::rtl::OUString aOperation
= ( eCmd
== DEL_DELROWS
?
1581 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete-rows" ) ) :
1582 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete-columns" ) ) );
1583 pModelObj
->NotifyChanges( aOperation
, aChangeRanges
);
1587 // put cursor directly behind deleted range
1588 SCCOL nCurX
= GetViewData()->GetCurX();
1589 SCROW nCurY
= GetViewData()->GetCurY();
1590 if ( eCmd
==DEL_CELLSLEFT
|| eCmd
==DEL_DELCOLS
)
1591 nCurX
= aRange
.aStart
.Col();
1593 nCurY
= aRange
.aStart
.Row();
1594 SetCursor( nCurX
, nCurY
);
1598 if (eCmd
== DEL_DELCOLS
)
1599 DeleteMulti( false, bRecord
);
1600 else if (eCmd
== DEL_DELROWS
)
1601 DeleteMulti( sal_True
, bRecord
);
1603 ErrorMessage(STR_NOMULTISELECT
);
1609 void ScViewFunc::DeleteMulti( sal_Bool bRows
, sal_Bool bRecord
)
1611 ScDocShell
* pDocSh
= GetViewData()->GetDocShell();
1612 ScDocShellModificator
aModificator( *pDocSh
);
1613 SCTAB nTab
= GetViewData()->GetTabNo();
1614 ScDocument
* pDoc
= pDocSh
->GetDocument();
1615 ScMarkData
aFuncMark( GetViewData()->GetMarkData() ); // local copy for UnmarkFiltered
1616 ScViewUtil::UnmarkFiltered( aFuncMark
, pDoc
);
1618 if (bRecord
&& !pDoc
->IsUndoEnabled())
1620 SCCOLROW
* pRanges
= new SCCOLROW
[MAXCOLROWCOUNT
];
1621 SCCOLROW nRangeCnt
= bRows
? aFuncMark
.GetMarkRowRanges( pRanges
) :
1622 aFuncMark
.GetMarkColumnRanges( pRanges
);
1625 pRanges
[0] = pRanges
[1] = bRows
? static_cast<SCCOLROW
>(GetViewData()->GetCurY()) : static_cast<SCCOLROW
>(GetViewData()->GetCurX());
1631 SCCOLROW
* pOneRange
= pRanges
;
1632 sal_uInt16 nErrorId
= 0;
1633 sal_Bool bNeedRefresh
= false;
1635 for (nRangeNo
=0; nRangeNo
<nRangeCnt
&& !nErrorId
; nRangeNo
++)
1637 SCCOLROW nStart
= *(pOneRange
++);
1638 SCCOLROW nEnd
= *(pOneRange
++);
1640 SCCOL nStartCol
, nEndCol
;
1641 SCROW nStartRow
, nEndRow
;
1646 nStartRow
= static_cast<SCROW
>(nStart
);
1647 nEndRow
= static_cast<SCROW
>(nEnd
);
1651 nStartCol
= static_cast<SCCOL
>(nStart
);
1652 nEndCol
= static_cast<SCCOL
>(nEnd
);
1657 // cell protection (only needed for first range, as all following cells are moved)
1658 if ( nRangeNo
== 0 )
1660 // test to the end of the sheet
1661 ScEditableTester
aTester( pDoc
, nTab
, nStartCol
, nStartRow
, MAXCOL
, MAXROW
);
1662 if (!aTester
.IsEditable())
1663 nErrorId
= aTester
.GetMessageId();
1667 SCCOL nMergeStartX
= nStartCol
;
1668 SCROW nMergeStartY
= nStartRow
;
1669 SCCOL nMergeEndX
= nEndCol
;
1670 SCROW nMergeEndY
= nEndRow
;
1671 pDoc
->ExtendMerge( nMergeStartX
, nMergeStartY
, nMergeEndX
, nMergeEndY
, nTab
);
1672 pDoc
->ExtendOverlapped( nMergeStartX
, nMergeStartY
, nMergeEndX
, nMergeEndY
, nTab
);
1674 if ( nMergeStartX
!= nStartCol
|| nMergeStartY
!= nStartRow
)
1676 // Disallow deleting parts of a merged cell.
1677 // Deleting the start is allowed (merge is removed), so the end doesn't have to be checked.
1679 nErrorId
= STR_MSSG_DELETECELLS_0
;
1681 if ( nMergeEndX
!= nEndCol
|| nMergeEndY
!= nEndRow
)
1683 // detect if the start of a merged cell is deleted, so the merge flags can be refreshed
1685 bNeedRefresh
= sal_True
;
1691 ErrorMessage( nErrorId
);
1698 WaitObject
aWait( GetFrameWin() ); // important for TrackFormulas in UpdateReference
1700 ScDocument
* pUndoDoc
= NULL
;
1701 ScRefUndoData
* pUndoData
= NULL
;
1704 pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
1705 pUndoDoc
->InitUndo( pDoc
, nTab
, nTab
, !bRows
, bRows
); // row height
1707 pOneRange
= pRanges
;
1708 for (nRangeNo
=0; nRangeNo
<nRangeCnt
; nRangeNo
++)
1710 SCCOLROW nStart
= *(pOneRange
++);
1711 SCCOLROW nEnd
= *(pOneRange
++);
1713 pDoc
->CopyToDocument( 0,nStart
,nTab
, MAXCOL
,nEnd
,nTab
, IDF_ALL
,false,pUndoDoc
);
1715 pDoc
->CopyToDocument( static_cast<SCCOL
>(nStart
),0,nTab
,
1716 static_cast<SCCOL
>(nEnd
),MAXROW
,nTab
,
1717 IDF_ALL
,false,pUndoDoc
);
1720 // all Formulas because of references
1721 SCTAB nTabCount
= pDoc
->GetTableCount();
1722 pUndoDoc
->AddUndoTab( 0, nTabCount
-1, false, false );
1723 pDoc
->CopyToDocument( 0,0,0, MAXCOL
,MAXROW
,MAXTAB
, IDF_FORMULA
,false,pUndoDoc
);
1725 pUndoData
= new ScRefUndoData( pDoc
);
1727 pDoc
->BeginDrawUndo();
1730 pOneRange
= &pRanges
[2*nRangeCnt
]; // backwards
1731 for (nRangeNo
=0; nRangeNo
<nRangeCnt
; nRangeNo
++)
1733 SCCOLROW nEnd
= *(--pOneRange
);
1734 SCCOLROW nStart
= *(--pOneRange
);
1737 pDoc
->DeleteRow( 0,nTab
, MAXCOL
,nTab
, nStart
, static_cast<SCSIZE
>(nEnd
-nStart
+1) );
1739 pDoc
->DeleteCol( 0,nTab
, MAXROW
,nTab
, static_cast<SCCOL
>(nStart
), static_cast<SCSIZE
>(nEnd
-nStart
+1) );
1744 SCCOLROW nFirstStart
= pRanges
[0];
1745 SCCOL nStartCol
= bRows
? 0 : static_cast<SCCOL
>(nFirstStart
);
1746 SCROW nStartRow
= bRows
? static_cast<SCROW
>(nFirstStart
) : 0;
1747 SCCOL nEndCol
= MAXCOL
;
1748 SCROW nEndRow
= MAXROW
;
1750 pDoc
->RemoveFlagsTab( nStartCol
, nStartRow
, nEndCol
, nEndRow
, nTab
, SC_MF_HOR
| SC_MF_VER
);
1751 pDoc
->ExtendMerge( nStartCol
, nStartRow
, nEndCol
, nEndRow
, nTab
, sal_True
);
1756 pDocSh
->GetUndoManager()->AddUndoAction(
1757 new ScUndoDeleteMulti( pDocSh
, bRows
, bNeedRefresh
, nTab
, pRanges
, nRangeCnt
,
1758 pUndoDoc
, pUndoData
) );
1761 if (!AdjustRowHeight(0, MAXROW
))
1764 pDocSh
->PostPaint( 0,pRanges
[0],nTab
, MAXCOL
,MAXROW
,nTab
, PAINT_GRID
| PAINT_LEFT
);
1766 pDocSh
->PostPaint( static_cast<SCCOL
>(pRanges
[0]),0,nTab
,
1767 MAXCOL
,MAXROW
,nTab
, PAINT_GRID
| PAINT_TOP
);
1769 aModificator
.SetDocumentModified();
1771 CellContentChanged();
1773 // put cursor directly behind the first deleted range
1774 SCCOL nCurX
= GetViewData()->GetCurX();
1775 SCROW nCurY
= GetViewData()->GetCurY();
1779 nCurX
= static_cast<SCCOL
>(pRanges
[0]);
1780 SetCursor( nCurX
, nCurY
);
1784 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED
) );
1789 void ScViewFunc::DeleteContents( sal_uInt16 nFlags
, sal_Bool bRecord
)
1791 ScViewData
* pViewData
= GetViewData();
1792 pViewData
->SetPasteMode( SC_PASTE_NONE
);
1793 pViewData
->GetViewShell()->UpdateCopySourceOverlay();
1795 // not editable because of matrix only? attribute OK nonetheless
1796 bool bOnlyNotBecauseOfMatrix
;
1797 sal_Bool bEditable
= SelectionEditable( &bOnlyNotBecauseOfMatrix
);
1800 if ( !(bOnlyNotBecauseOfMatrix
&&
1801 ((nFlags
& (IDF_ATTRIB
| IDF_EDITATTR
)) == nFlags
)) )
1803 ErrorMessage(bOnlyNotBecauseOfMatrix
? STR_MATRIXFRAGMENTERR
: STR_PROTECTIONERR
);
1809 sal_Bool bSimple
= false;
1811 ScDocument
* pDoc
= GetViewData()->GetDocument();
1812 ScDocShell
* pDocSh
= GetViewData()->GetDocShell();
1813 ScMarkData
aFuncMark( GetViewData()->GetMarkData() ); // local copy for UnmarkFiltered
1814 ScViewUtil::UnmarkFiltered( aFuncMark
, pDoc
);
1816 if (bRecord
&& !pDoc
->IsUndoEnabled())
1819 ScDocShellModificator
aModificator( *pDocSh
);
1821 if ( !aFuncMark
.IsMarked() && !aFuncMark
.IsMultiMarked() )
1823 aMarkRange
.aStart
.SetCol(GetViewData()->GetCurX());
1824 aMarkRange
.aStart
.SetRow(GetViewData()->GetCurY());
1825 aMarkRange
.aStart
.SetTab(GetViewData()->GetTabNo());
1826 aMarkRange
.aEnd
= aMarkRange
.aStart
;
1827 if ( pDoc
->HasAttrib( aMarkRange
, HASATTR_MERGED
) )
1829 aFuncMark
.SetMarkArea( aMarkRange
);
1835 aFuncMark
.SetMarking(false); // for MarkToMulti
1836 aFuncMark
.MarkToSimple(); // before bMulti test below
1838 OSL_ENSURE( aFuncMark
.IsMarked() || aFuncMark
.IsMultiMarked() || bSimple
, "delete what?" );
1840 ScDocument
* pUndoDoc
= NULL
;
1841 sal_Bool bMulti
= !bSimple
&& aFuncMark
.IsMultiMarked();
1844 aFuncMark
.MarkToMulti();
1845 aFuncMark
.GetMultiMarkArea( aMarkRange
);
1847 ScRange
aExtendedRange(aMarkRange
);
1850 if ( pDoc
->ExtendMerge( aExtendedRange
, sal_True
) )
1854 // no objects on protected tabs
1855 sal_Bool bObjects
= false;
1856 if ( nFlags
& IDF_OBJECTS
)
1858 bObjects
= sal_True
;
1859 ScMarkData::iterator itr
= aFuncMark
.begin(), itrEnd
= aFuncMark
.end();
1860 for (; itr
!= itrEnd
; ++itr
)
1861 if (pDoc
->IsTabProtected(*itr
))
1865 sal_uInt16 nExtFlags
= 0; // extra flags are needed only if attributes are deleted
1866 if ( nFlags
& IDF_ATTRIB
)
1867 pDocSh
->UpdatePaintExt( nExtFlags
, aMarkRange
);
1869 // order op opeeration:
1871 // 2) delete objects (DrawUndo is filled)
1872 // 3) copy contents for undo
1873 // 4) delete contents
1874 // 5) add undo-action
1876 sal_Bool bDrawUndo
= bObjects
|| ( nFlags
& IDF_NOTE
); // needed for shown notes
1877 if ( bDrawUndo
&& bRecord
)
1878 pDoc
->BeginDrawUndo();
1883 pDoc
->DeleteObjectsInSelection( aFuncMark
);
1885 pDoc
->DeleteObjectsInArea( aMarkRange
.aStart
.Col(), aMarkRange
.aStart
.Row(),
1886 /*!*/ aMarkRange
.aEnd
.Col(), aMarkRange
.aEnd
.Row(),
1892 pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
1893 SCTAB nTab
= aMarkRange
.aStart
.Tab();
1894 pUndoDoc
->InitUndo( pDoc
, nTab
, nTab
);
1895 SCTAB nTabCount
= pDoc
->GetTableCount();
1896 ScMarkData::iterator itr
= aFuncMark
.begin(), itrEnd
= aFuncMark
.end();
1897 for (; itr
!= itrEnd
; ++itr
)
1899 pUndoDoc
->AddUndoTab( *itr
, *itr
);
1900 ScRange aCopyRange
= aExtendedRange
;
1901 aCopyRange
.aStart
.SetTab(0);
1902 aCopyRange
.aEnd
.SetTab(nTabCount
-1);
1904 // in case of "Format/Standard" copy all attributes, because CopyToDocument
1905 // with IDF_HARDATTR only is too time-consuming:
1906 sal_uInt16 nUndoDocFlags
= nFlags
;
1907 if (nFlags
& IDF_ATTRIB
)
1908 nUndoDocFlags
|= IDF_ATTRIB
;
1909 if (nFlags
& IDF_EDITATTR
) // Edit-Engine-Attribute
1910 nUndoDocFlags
|= IDF_STRING
; // -> cells will be changed
1911 if (nFlags
& IDF_NOTE
)
1912 nUndoDocFlags
|= IDF_CONTENTS
; // copy all cells with their notes
1913 // do not copy note captions to undo document
1914 nUndoDocFlags
|= IDF_NOCAPTIONS
;
1915 pDoc
->CopyToDocument( aCopyRange
, nUndoDocFlags
, bMulti
, pUndoDoc
, &aFuncMark
);
1918 HideAllCursors(); // for if summary is cancelled
1920 pDoc
->DeleteArea( aMarkRange
.aStart
.Col(), aMarkRange
.aStart
.Row(),
1921 aMarkRange
.aEnd
.Col(), aMarkRange
.aEnd
.Row(),
1922 aFuncMark
, nFlags
);
1925 pDoc
->DeleteSelection( nFlags
, aFuncMark
);
1930 pDocSh
->GetUndoManager()->AddUndoAction(
1931 new ScUndoDeleteContents( pDocSh
, aFuncMark
, aExtendedRange
,
1932 pUndoDoc
, bMulti
, nFlags
, bDrawUndo
) );
1935 if (!AdjustRowHeight( aExtendedRange
.aStart
.Row(), aExtendedRange
.aEnd
.Row() ))
1936 pDocSh
->PostPaint( aExtendedRange
, PAINT_GRID
, nExtFlags
);
1938 pDocSh
->UpdateOle(GetViewData());
1940 // #i97876# Spreadsheet data changes are not notified
1941 ScModelObj
* pModelObj
= ScModelObj::getImplementation( pDocSh
->GetModel() );
1942 if ( pModelObj
&& pModelObj
->HasChangesListeners() )
1944 ScRangeList aChangeRanges
;
1947 aChangeRanges
.Append( aMarkRange
);
1951 aFuncMark
.FillRangeListWithMarks( &aChangeRanges
, false );
1953 pModelObj
->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges
);
1956 aModificator
.SetDocumentModified();
1957 CellContentChanged();
1960 if ( nFlags
& IDF_ATTRIB
)
1962 if ( nFlags
& IDF_CONTENTS
)
1965 StartFormatArea(); // delete attribute is also attribute-change
1969 // column width/row height (via header) - undo OK
1971 void ScViewFunc::SetWidthOrHeight( sal_Bool bWidth
, SCCOLROW nRangeCnt
, SCCOLROW
* pRanges
,
1972 ScSizeMode eMode
, sal_uInt16 nSizeTwips
,
1973 sal_Bool bRecord
, sal_Bool bPaint
, ScMarkData
* pMarkData
)
1978 // use view's mark if none specified
1980 pMarkData
= &GetViewData()->GetMarkData();
1982 ScDocShell
* pDocSh
= GetViewData()->GetDocShell();
1983 ScDocument
* pDoc
= pDocSh
->GetDocument();
1984 SCTAB nFirstTab
= pMarkData
->GetFirstSelected();
1985 SCTAB nCurTab
= GetViewData()->GetTabNo();
1987 if (bRecord
&& !pDoc
->IsUndoEnabled())
1990 ScDocShellModificator
aModificator( *pDocSh
);
1992 bool bAllowed
= true;
1993 ScMarkData::iterator itr
= pMarkData
->begin(), itrEnd
= pMarkData
->end();
1994 for (; itr
!= itrEnd
&& bAllowed
; ++itr
)
1995 for ( SCCOLROW i
=0; i
<nRangeCnt
&& bAllowed
; i
++ )
1999 bAllowed
= pDoc
->IsBlockEditable( *itr
,
2000 static_cast<SCCOL
>(pRanges
[2*i
]),0,
2001 static_cast<SCCOL
>(pRanges
[2*i
+1]),MAXROW
,
2002 &bOnlyMatrix
) || bOnlyMatrix
;
2004 bAllowed
= pDoc
->IsBlockEditable( *itr
, 0,pRanges
[2*i
],
2005 MAXCOL
,pRanges
[2*i
+1], &bOnlyMatrix
) ||
2009 // Allow users to resize cols/rows in readonly docs despite the r/o state.
2010 // It is frustrating to be unable to see content in mis-sized cells.
2011 if( !bAllowed
&& !pDocSh
->IsReadOnly() )
2013 ErrorMessage(STR_PROTECTIONERR
);
2017 SCCOLROW nStart
= pRanges
[0];
2018 SCCOLROW nEnd
= pRanges
[2*nRangeCnt
-1];
2020 sal_Bool bFormula
= false;
2021 if ( eMode
== SC_SIZE_OPTIMAL
)
2023 const ScViewOptions
& rOpts
= GetViewData()->GetOptions();
2024 bFormula
= rOpts
.GetOption( VOPT_FORMULAS
);
2027 ScDocument
* pUndoDoc
= NULL
;
2028 ScOutlineTable
* pUndoTab
= NULL
;
2029 SCCOLROW
* pUndoRanges
= NULL
;
2033 pDoc
->BeginDrawUndo(); // Drawing Updates
2035 pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
2036 itr
= pMarkData
->begin();
2037 for (; itr
!= itrEnd
; ++itr
)
2041 if ( *itr
== nFirstTab
)
2042 pUndoDoc
->InitUndo( pDoc
, *itr
, *itr
, true, false );
2044 pUndoDoc
->AddUndoTab( *itr
, *itr
, true, false );
2045 pDoc
->CopyToDocument( static_cast<SCCOL
>(nStart
), 0, *itr
,
2046 static_cast<SCCOL
>(nEnd
), MAXROW
, *itr
, IDF_NONE
,
2051 if ( *itr
== nFirstTab
)
2052 pUndoDoc
->InitUndo( pDoc
, *itr
, *itr
, false, true );
2054 pUndoDoc
->AddUndoTab( *itr
, *itr
, false, true );
2055 pDoc
->CopyToDocument( 0, nStart
, *itr
, MAXCOL
, nEnd
, *itr
, IDF_NONE
, false, pUndoDoc
);
2059 pUndoRanges
= new SCCOLROW
[ 2*nRangeCnt
];
2060 memcpy( pUndoRanges
, pRanges
, 2*nRangeCnt
*sizeof(SCCOLROW
) );
2062 //! outlines from all tab?
2063 ScOutlineTable
* pTable
= pDoc
->GetOutlineTable( nCurTab
);
2065 pUndoTab
= new ScOutlineTable( *pTable
);
2068 if ( eMode
==SC_SIZE_OPTIMAL
|| eMode
==SC_SIZE_VISOPT
)
2069 pMarkData
->MarkToMulti();
2071 sal_Bool bShow
= nSizeTwips
> 0 || eMode
!= SC_SIZE_DIRECT
;
2072 sal_Bool bOutline
= false;
2074 itr
= pMarkData
->begin();
2075 for (; itr
!= itrEnd
; ++itr
)
2078 const SCCOLROW
* pTabRanges
= pRanges
;
2080 pDoc
->InitializeNoteCaptions( nTab
);
2081 for (SCCOLROW nRangeNo
=0; nRangeNo
<nRangeCnt
; nRangeNo
++)
2083 SCCOLROW nStartNo
= *(pTabRanges
++);
2084 SCCOLROW nEndNo
= *(pTabRanges
++);
2086 if ( !bWidth
) // height always blockwise
2088 if ( eMode
==SC_SIZE_OPTIMAL
|| eMode
==SC_SIZE_VISOPT
)
2090 sal_Bool bAll
= ( eMode
==SC_SIZE_OPTIMAL
);
2093 // delete CR_MANUALSIZE for all in range,
2094 // then SetOptimalHeight with bShrink = FALSE
2095 for (SCROW nRow
= nStartNo
; nRow
<= nEndNo
; ++nRow
)
2097 SCROW nLastRow
= nRow
;
2098 if (pDoc
->RowHidden(nRow
, nTab
, NULL
, &nLastRow
))
2104 sal_uInt8 nOld
= pDoc
->GetRowFlags(nRow
, nTab
);
2105 if (nOld
& CR_MANUALSIZE
)
2106 pDoc
->SetRowFlags(nRow
, nTab
, nOld
& ~CR_MANUALSIZE
);
2110 double nPPTX
= GetViewData()->GetPPTX();
2111 double nPPTY
= GetViewData()->GetPPTY();
2112 Fraction aZoomX
= GetViewData()->GetZoomX();
2113 Fraction aZoomY
= GetViewData()->GetZoomY();
2115 ScSizeDeviceProvider
aProv(pDocSh
);
2116 if (aProv
.IsPrinter())
2118 nPPTX
= aProv
.GetPPTX();
2119 nPPTY
= aProv
.GetPPTY();
2120 aZoomX
= aZoomY
= Fraction( 1, 1 );
2123 pDoc
->SetOptimalHeight( nStartNo
, nEndNo
, nTab
, nSizeTwips
, aProv
.GetDevice(),
2124 nPPTX
, nPPTY
, aZoomX
, aZoomY
, bAll
);
2126 pDoc
->ShowRows( nStartNo
, nEndNo
, nTab
, sal_True
);
2128 // Manual-Flag already (re)set in SetOptimalHeight in case of bAll=sal_True
2129 // (set for Extra-Height, else reset).
2131 else if ( eMode
==SC_SIZE_DIRECT
)
2135 pDoc
->SetRowHeightRange( nStartNo
, nEndNo
, nTab
, nSizeTwips
);
2136 pDoc
->SetManualHeight( nStartNo
, nEndNo
, nTab
, sal_True
); // height was set manually
2138 pDoc
->ShowRows( nStartNo
, nEndNo
, nTab
, nSizeTwips
!= 0 );
2140 else if ( eMode
==SC_SIZE_SHOW
)
2142 pDoc
->ShowRows( nStartNo
, nEndNo
, nTab
, sal_True
);
2145 else // column width
2147 for (SCCOL nCol
=static_cast<SCCOL
>(nStartNo
); nCol
<=static_cast<SCCOL
>(nEndNo
); nCol
++)
2149 if ( eMode
!= SC_SIZE_VISOPT
|| !pDoc
->ColHidden(nCol
, nTab
) )
2151 sal_uInt16 nThisSize
= nSizeTwips
;
2153 if ( eMode
==SC_SIZE_OPTIMAL
|| eMode
==SC_SIZE_VISOPT
)
2154 nThisSize
= nSizeTwips
+ GetOptimalColWidth( nCol
, nTab
, bFormula
);
2156 pDoc
->SetColWidth( nCol
, nTab
, nThisSize
);
2158 pDoc
->ShowCol( nCol
, nTab
, bShow
);
2167 if ( pDoc
->UpdateOutlineCol( static_cast<SCCOL
>(nStartNo
),
2168 static_cast<SCCOL
>(nEndNo
), nTab
, bShow
) )
2169 bOutline
= sal_True
;
2173 if ( pDoc
->UpdateOutlineRow( nStartNo
, nEndNo
, nTab
, bShow
) )
2174 bOutline
= sal_True
;
2177 pDoc
->SetDrawPageSize(nTab
);
2186 pDocSh
->GetUndoManager()->AddUndoAction(
2187 new ScUndoWidthOrHeight( pDocSh
, *pMarkData
,
2188 nStart
, nCurTab
, nEnd
, nCurTab
,
2189 pUndoDoc
, nRangeCnt
, pUndoRanges
,
2190 pUndoTab
, eMode
, nSizeTwips
, bWidth
) );
2193 // fdo#36247 Ensure that the drawing layer's map mode scaling factors match
2194 // the new heights and widths.
2195 GetViewData()->GetView()->RefreshZoom();
2197 itr
= pMarkData
->begin();
2198 for (; itr
!= itrEnd
; ++itr
)
2199 pDoc
->UpdatePageBreaks( *itr
);
2201 GetViewData()->GetView()->UpdateScrollBars();
2205 itr
= pMarkData
->begin();
2206 for (; itr
!= itrEnd
; ++itr
)
2211 if (pDoc
->HasAttrib( static_cast<SCCOL
>(nStart
),0,nTab
,
2212 static_cast<SCCOL
>(nEnd
),MAXROW
,nTab
,
2213 HASATTR_MERGED
| HASATTR_OVERLAPPED
))
2215 if (nStart
> 0) // go upwards because of Lines and cursor
2217 pDocSh
->PostPaint( static_cast<SCCOL
>(nStart
), 0, nTab
,
2218 MAXCOL
, MAXROW
, nTab
, PAINT_GRID
| PAINT_TOP
);
2222 if (pDoc
->HasAttrib( 0,nStart
,nTab
, MAXCOL
,nEnd
,nTab
, HASATTR_MERGED
| HASATTR_OVERLAPPED
))
2226 pDocSh
->PostPaint( 0, nStart
, nTab
, MAXCOL
, MAXROW
, nTab
, PAINT_GRID
| PAINT_LEFT
);
2230 pDocSh
->UpdateOle(GetViewData());
2231 if( !pDocSh
->IsReadOnly() )
2232 aModificator
.SetDocumentModified();
2235 // #i97876# Spreadsheet data changes are not notified
2238 ScModelObj
* pModelObj
= ScModelObj::getImplementation( pDocSh
->GetModel() );
2239 if ( pModelObj
&& pModelObj
->HasChangesListeners() )
2241 ScRangeList aChangeRanges
;
2242 itr
= pMarkData
->begin();
2243 for (; itr
!= itrEnd
; ++itr
)
2246 const SCCOLROW
* pTabRanges
= pRanges
;
2247 for ( SCCOLROW nRange
= 0; nRange
< nRangeCnt
; ++nRange
)
2249 SCCOL nStartCol
= static_cast< SCCOL
>( *(pTabRanges
++) );
2250 SCCOL nEndCol
= static_cast< SCCOL
>( *(pTabRanges
++) );
2251 for ( SCCOL nCol
= nStartCol
; nCol
<= nEndCol
; ++nCol
)
2253 aChangeRanges
.Append( ScRange( nCol
, 0, nTab
) );
2257 pModelObj
->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "column-resize" ) ), aChangeRanges
);
2262 // column width/row height (via marked range)
2264 void ScViewFunc::SetMarkedWidthOrHeight( sal_Bool bWidth
, ScSizeMode eMode
, sal_uInt16 nSizeTwips
,
2265 sal_Bool bRecord
, sal_Bool bPaint
)
2267 ScMarkData
& rMark
= GetViewData()->GetMarkData();
2269 rMark
.MarkToMulti();
2270 if (!rMark
.IsMultiMarked())
2272 SCCOL nCol
= GetViewData()->GetCurX();
2273 SCROW nRow
= GetViewData()->GetCurY();
2274 SCTAB nTab
= GetViewData()->GetTabNo();
2277 rMark
.SetMultiMarkArea( ScRange( nCol
,nRow
,nTab
), sal_True
);
2281 SCCOLROW
* pRanges
= new SCCOLROW
[MAXCOLROWCOUNT
];
2282 SCCOLROW nRangeCnt
= 0;
2285 nRangeCnt
= rMark
.GetMarkColumnRanges( pRanges
);
2287 nRangeCnt
= rMark
.GetMarkRowRanges( pRanges
);
2289 SetWidthOrHeight( bWidth
, nRangeCnt
, pRanges
, eMode
, nSizeTwips
, bRecord
, bPaint
);
2292 rMark
.MarkToSimple();
2295 void ScViewFunc::ModifyCellSize( ScDirection eDir
, sal_Bool bOptimal
)
2297 //! step size adjustable
2298 // step size is also minumum
2299 sal_uInt16 nStepX
= STD_COL_WIDTH
/ 5;
2300 sal_uInt16 nStepY
= ScGlobal::nStdRowHeight
;
2302 ScModule
* pScMod
= SC_MOD();
2303 sal_Bool bAnyEdit
= pScMod
->IsInputMode();
2304 SCCOL nCol
= GetViewData()->GetCurX();
2305 SCROW nRow
= GetViewData()->GetCurY();
2306 SCTAB nTab
= GetViewData()->GetTabNo();
2307 ScDocShell
* pDocSh
= GetViewData()->GetDocShell();
2308 ScDocument
* pDoc
= pDocSh
->GetDocument();
2310 bool bAllowed
, bOnlyMatrix
;
2311 if ( eDir
== DIR_LEFT
|| eDir
== DIR_RIGHT
)
2312 bAllowed
= pDoc
->IsBlockEditable( nTab
, nCol
,0, nCol
,MAXROW
, &bOnlyMatrix
);
2314 bAllowed
= pDoc
->IsBlockEditable( nTab
, 0,nRow
, MAXCOL
,nRow
, &bOnlyMatrix
);
2315 if ( !bAllowed
&& !bOnlyMatrix
)
2317 ErrorMessage(STR_PROTECTIONERR
);
2323 sal_uInt16 nWidth
= pDoc
->GetColWidth( nCol
, nTab
);
2324 sal_uInt16 nHeight
= pDoc
->GetRowHeight( nRow
, nTab
);
2326 if ( eDir
== DIR_LEFT
|| eDir
== DIR_RIGHT
)
2328 if (bOptimal
) // width of this single cell
2332 // when editing the actual entered width
2333 ScInputHandler
* pHdl
= pScMod
->GetInputHdl( GetViewData()->GetViewShell() );
2336 long nEdit
= pHdl
->GetTextSize().Width(); // in 0.01 mm
2338 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( nCol
, nRow
, nTab
);
2339 const SvxMarginItem
& rMItem
=
2340 (const SvxMarginItem
&)pPattern
->GetItem(ATTR_MARGIN
);
2341 sal_uInt16 nMargin
= rMItem
.GetLeftMargin() + rMItem
.GetRightMargin();
2342 if ( ((const SvxHorJustifyItem
&) pPattern
->
2343 GetItem( ATTR_HOR_JUSTIFY
)).GetValue() == SVX_HOR_JUSTIFY_LEFT
)
2344 nMargin
= sal::static_int_cast
<sal_uInt16
>(
2345 nMargin
+ ((const SfxUInt16Item
&)pPattern
->GetItem(ATTR_INDENT
)).GetValue() );
2347 nWidth
= (sal_uInt16
)(nEdit
* pDocSh
->GetOutputFactor() / HMM_PER_TWIPS
)
2348 + nMargin
+ STD_EXTRA_WIDTH
;
2353 double nPPTX
= GetViewData()->GetPPTX();
2354 double nPPTY
= GetViewData()->GetPPTY();
2355 Fraction aZoomX
= GetViewData()->GetZoomX();
2356 Fraction aZoomY
= GetViewData()->GetZoomY();
2358 ScSizeDeviceProvider
aProv(pDocSh
);
2359 if (aProv
.IsPrinter())
2361 nPPTX
= aProv
.GetPPTX();
2362 nPPTY
= aProv
.GetPPTY();
2363 aZoomX
= aZoomY
= Fraction( 1, 1 );
2366 long nPixel
= pDoc
->GetNeededSize( nCol
, nRow
, nTab
, aProv
.GetDevice(),
2367 nPPTX
, nPPTY
, aZoomX
, aZoomY
, sal_True
);
2368 sal_uInt16 nTwips
= (sal_uInt16
)( nPixel
/ nPPTX
);
2370 nWidth
= nTwips
+ STD_EXTRA_WIDTH
;
2372 nWidth
= STD_COL_WIDTH
;
2375 else // increment / decrement
2377 if ( eDir
== DIR_RIGHT
)
2378 nWidth
= sal::static_int_cast
<sal_uInt16
>( nWidth
+ nStepX
);
2379 else if ( nWidth
> nStepX
)
2380 nWidth
= sal::static_int_cast
<sal_uInt16
>( nWidth
- nStepX
);
2381 if ( nWidth
< nStepX
) nWidth
= nStepX
;
2382 if ( nWidth
> MAX_COL_WIDTH
) nWidth
= MAX_COL_WIDTH
;
2384 nRange
[0] = nRange
[1] = nCol
;
2385 SetWidthOrHeight( sal_True
, 1, nRange
, SC_SIZE_DIRECT
, nWidth
);
2387 // adjust height of this row if width demands/allows this
2391 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( nCol
, nRow
, nTab
);
2392 sal_Bool bNeedHeight
=
2393 ((const SfxBoolItem
&)pPattern
->GetItem( ATTR_LINEBREAK
)).GetValue() ||
2394 ((const SvxHorJustifyItem
&)pPattern
->
2395 GetItem( ATTR_HOR_JUSTIFY
)).GetValue() == SVX_HOR_JUSTIFY_BLOCK
;
2397 AdjustRowHeight( nRow
, nRow
);
2405 eMode
= SC_SIZE_OPTIMAL
;
2410 eMode
= SC_SIZE_DIRECT
;
2411 if ( eDir
== DIR_BOTTOM
)
2412 nHeight
= sal::static_int_cast
<sal_uInt16
>( nHeight
+ nStepY
);
2413 else if ( nHeight
> nStepY
)
2414 nHeight
= sal::static_int_cast
<sal_uInt16
>( nHeight
- nStepY
);
2415 if ( nHeight
< nStepY
) nHeight
= nStepY
;
2416 if ( nHeight
> MAX_ROW_HEIGHT
) nHeight
= MAX_ROW_HEIGHT
;
2418 nRange
[0] = nRange
[1] = nRow
;
2419 SetWidthOrHeight( false, 1, nRange
, eMode
, nHeight
);
2425 if ( pDoc
->HasAttrib( nCol
, nRow
, nTab
, nCol
, nRow
, nTab
, HASATTR_NEEDHEIGHT
) )
2427 ScInputHandler
* pHdl
= pScMod
->GetInputHdl( GetViewData()->GetViewShell() );
2429 pHdl
->SetModified(); // so that the height is adjusted with Enter
2436 void ScViewFunc::ProtectSheet( SCTAB nTab
, const ScTableProtection
& rProtect
)
2438 if (nTab
== TABLEID_DOC
)
2441 ScMarkData
& rMark
= GetViewData()->GetMarkData();
2442 ScDocShell
* pDocSh
= GetViewData()->GetDocShell();
2443 ScDocument
* pDoc
= pDocSh
->GetDocument();
2444 ScDocFunc
&rFunc
= pDocSh
->GetDocFunc();
2445 bool bUndo(pDoc
->IsUndoEnabled());
2447 // modifying several tabs is handled here
2451 String aUndo
= ScGlobal::GetRscString( STR_UNDO_PROTECT_TAB
);
2452 pDocSh
->GetUndoManager()->EnterListAction( aUndo
, aUndo
);
2455 ScMarkData::iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
2456 for (; itr
!= itrEnd
; ++itr
)
2457 rFunc
.ProtectSheet(*itr
, rProtect
);
2460 pDocSh
->GetUndoManager()->LeaveListAction();
2462 UpdateLayerLocks(); //! broadcast to all views
2465 void ScViewFunc::Protect( SCTAB nTab
, const String
& rPassword
)
2467 ScMarkData
& rMark
= GetViewData()->GetMarkData();
2468 ScDocShell
* pDocSh
= GetViewData()->GetDocShell();
2469 ScDocument
* pDoc
= pDocSh
->GetDocument();
2470 ScDocFunc
&rFunc
= pDocSh
->GetDocFunc();
2471 sal_Bool
bUndo(pDoc
->IsUndoEnabled());
2473 if ( nTab
== TABLEID_DOC
|| rMark
.GetSelectCount() <= 1 )
2474 rFunc
.Protect( nTab
, rPassword
, false );
2477 // modifying several tabs is handled here
2481 String aUndo
= ScGlobal::GetRscString( STR_UNDO_PROTECT_TAB
);
2482 pDocSh
->GetUndoManager()->EnterListAction( aUndo
, aUndo
);
2485 ScMarkData::iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
2486 for (; itr
!= itrEnd
; ++itr
)
2487 rFunc
.Protect( *itr
, rPassword
, false );
2490 pDocSh
->GetUndoManager()->LeaveListAction();
2493 UpdateLayerLocks(); //! broadcast to all views
2496 sal_Bool
ScViewFunc::Unprotect( SCTAB nTab
, const String
& rPassword
)
2498 ScMarkData
& rMark
= GetViewData()->GetMarkData();
2499 ScDocShell
* pDocSh
= GetViewData()->GetDocShell();
2500 ScDocument
* pDoc
= pDocSh
->GetDocument();
2501 ScDocFunc
&rFunc
= pDocSh
->GetDocFunc();
2502 sal_Bool bChanged
= false;
2503 sal_Bool
bUndo (pDoc
->IsUndoEnabled());
2505 if ( nTab
== TABLEID_DOC
|| rMark
.GetSelectCount() <= 1 )
2506 bChanged
= rFunc
.Unprotect( nTab
, rPassword
, false );
2509 // modifying several tabs is handled here
2513 String aUndo
= ScGlobal::GetRscString( STR_UNDO_UNPROTECT_TAB
);
2514 pDocSh
->GetUndoManager()->EnterListAction( aUndo
, aUndo
);
2517 ScMarkData::iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
2518 for (; itr
!= itrEnd
; ++itr
)
2519 if ( rFunc
.Unprotect( *itr
, rPassword
, false ) )
2520 bChanged
= sal_True
;
2523 pDocSh
->GetUndoManager()->LeaveListAction();
2527 UpdateLayerLocks(); //! broadcast to all views
2532 void ScViewFunc::SetNoteText( const ScAddress
& rPos
, const String
& rNoteText
)
2534 GetViewData()->GetDocShell()->GetDocFunc().SetNoteText( rPos
, rNoteText
, false );
2537 void ScViewFunc::ReplaceNote( const ScAddress
& rPos
, const String
& rNoteText
, const String
* pAuthor
, const String
* pDate
)
2539 GetViewData()->GetDocShell()->GetDocFunc().ReplaceNote( rPos
, rNoteText
, pAuthor
, pDate
, false );
2542 void ScViewFunc::SetNumberFormat( short nFormatType
, sal_uLong nAdd
)
2544 // not editable because of matrix only? attribute OK nonetheless
2545 bool bOnlyNotBecauseOfMatrix
;
2546 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix
) && !bOnlyNotBecauseOfMatrix
)
2548 ErrorMessage(STR_PROTECTIONERR
);
2552 sal_uInt32 nNumberFormat
= 0;
2553 ScViewData
* pViewData
= GetViewData();
2554 ScDocument
* pDoc
= pViewData
->GetDocument();
2555 SvNumberFormatter
* pNumberFormatter
= pDoc
->GetFormatTable();
2556 LanguageType eLanguage
= ScGlobal::eLnge
;
2557 ScPatternAttr
aNewAttrs( pDoc
->GetPool() );
2559 // always take language from cursor position, even if there is a selection
2561 sal_uInt32 nCurrentNumberFormat
;
2562 pDoc
->GetNumberFormat( pViewData
->GetCurX(),
2563 pViewData
->GetCurY(),
2564 pViewData
->GetTabNo(),
2565 nCurrentNumberFormat
);
2566 const SvNumberformat
* pEntry
= pNumberFormatter
->GetEntry( nCurrentNumberFormat
);
2568 eLanguage
= pEntry
->GetLanguage(); // else keep ScGlobal::eLnge
2570 nNumberFormat
= pNumberFormatter
->GetStandardFormat( nFormatType
, eLanguage
) + nAdd
;
2572 SfxItemSet
& rSet
= aNewAttrs
.GetItemSet();
2573 rSet
.Put( SfxUInt32Item( ATTR_VALUE_FORMAT
, nNumberFormat
) );
2574 // ATTR_LANGUAGE_FORMAT not
2575 ApplySelectionPattern( aNewAttrs
, sal_True
);
2578 void ScViewFunc::SetNumFmtByStr( const String
& rCode
)
2580 // not editable because of matrix only? attribute OK nonetheless
2581 bool bOnlyNotBecauseOfMatrix
;
2582 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix
) && !bOnlyNotBecauseOfMatrix
)
2584 ErrorMessage(STR_PROTECTIONERR
);
2588 ScViewData
* pViewData
= GetViewData();
2589 ScDocument
* pDoc
= pViewData
->GetDocument();
2590 SvNumberFormatter
* pFormatter
= pDoc
->GetFormatTable();
2592 // language always from cursor position
2594 sal_uInt32 nCurrentNumberFormat
;
2595 pDoc
->GetNumberFormat( pViewData
->GetCurX(), pViewData
->GetCurY(),
2596 pViewData
->GetTabNo(), nCurrentNumberFormat
);
2597 const SvNumberformat
* pEntry
= pFormatter
->GetEntry( nCurrentNumberFormat
);
2598 LanguageType eLanguage
= pEntry
? pEntry
->GetLanguage() : ScGlobal::eLnge
;
2600 // determine index for String
2602 sal_Bool bOk
= sal_True
;
2603 sal_uInt32 nNumberFormat
= pFormatter
->GetEntryKey( rCode
, eLanguage
);
2604 if ( nNumberFormat
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
2608 OUString aFormat
= rCode
; // will be changed
2609 sal_Int32 nErrPos
= 0;
2610 short nType
= 0; //! ???
2611 bOk
= pFormatter
->PutEntry( aFormat
, nErrPos
, nType
, nNumberFormat
, eLanguage
);
2614 if ( bOk
) // valid format?
2616 ScPatternAttr
aNewAttrs( pDoc
->GetPool() );
2617 SfxItemSet
& rSet
= aNewAttrs
.GetItemSet();
2618 rSet
.Put( SfxUInt32Item( ATTR_VALUE_FORMAT
, nNumberFormat
) );
2619 rSet
.Put( SvxLanguageItem( eLanguage
, ATTR_LANGUAGE_FORMAT
) );
2620 ApplySelectionPattern( aNewAttrs
, sal_True
);
2623 //! else return error / issue warning ???
2626 void ScViewFunc::ChangeNumFmtDecimals( sal_Bool bIncrement
)
2628 // not editable because of matrix only? attribute OK nonetheless
2629 bool bOnlyNotBecauseOfMatrix
;
2630 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix
) && !bOnlyNotBecauseOfMatrix
)
2632 ErrorMessage(STR_PROTECTIONERR
);
2636 ScDocument
* pDoc
= GetViewData()->GetDocument();
2637 SvNumberFormatter
* pFormatter
= pDoc
->GetFormatTable();
2639 SCCOL nCol
= GetViewData()->GetCurX();
2640 SCROW nRow
= GetViewData()->GetCurY();
2641 SCTAB nTab
= GetViewData()->GetTabNo();
2643 sal_uInt32 nOldFormat
;
2644 pDoc
->GetNumberFormat( nCol
, nRow
, nTab
, nOldFormat
);
2645 const SvNumberformat
* pOldEntry
= pFormatter
->GetEntry( nOldFormat
);
2648 OSL_FAIL("numberformat not found !!!");
2652 // what have we got here?
2654 sal_uInt32 nNewFormat
= nOldFormat
;
2655 sal_Bool bError
= false;
2657 LanguageType eLanguage
= pOldEntry
->GetLanguage();
2658 bool bThousand
, bNegRed
;
2659 sal_uInt16 nPrecision
, nLeading
;
2660 pOldEntry
->GetFormatSpecialInfo( bThousand
, bNegRed
, nPrecision
, nLeading
);
2662 short nOldType
= pOldEntry
->GetType();
2663 if ( 0 == ( nOldType
& (
2664 NUMBERFORMAT_NUMBER
| NUMBERFORMAT_CURRENCY
| NUMBERFORMAT_PERCENT
) ) )
2666 // date, time, fraction, logical, text can not be changed
2667 //! in case of scientific the Numberformatter also can't
2671 //! SvNumberformat has a Member bStandard, but doesn't disclose it
2672 sal_Bool bWasStandard
= ( nOldFormat
== pFormatter
->GetStandardIndex( eLanguage
) );
2675 // with "Standard" the decimal places depend on cell content
2676 // 0 if empty or text -> no decimal places
2677 double nVal
= pDoc
->GetValue( ScAddress( nCol
, nRow
, nTab
) );
2679 // the ways of the Numberformatters are unfathomable, so try:
2682 ((SvNumberformat
*)pOldEntry
)->GetOutputString( nVal
, aOut
, &pCol
);
2685 // 'E' for exponential is fixed in Numberformatter
2686 if ( aOut
.indexOf((sal_Unicode
)'E') >= 0 )
2687 bError
= sal_True
; // exponential not changed
2690 OUString
aDecSep( pFormatter
->GetFormatDecimalSep( nOldFormat
) );
2691 sal_Int32 nPos
= aOut
.indexOf( aDecSep
);
2693 nPrecision
= aOut
.getLength() - nPos
- aDecSep
.getLength();
2703 ++nPrecision
; // increment
2705 bError
= sal_True
; // 20 is maximum
2710 --nPrecision
; // decrement
2712 bError
= sal_True
; // 0 is minumum
2718 OUString aNewPicture
= pFormatter
->GenerateFormat(nOldFormat
, eLanguage
,
2720 nPrecision
, nLeading
);
2722 nNewFormat
= pFormatter
->GetEntryKey( aNewPicture
, eLanguage
);
2723 if ( nNewFormat
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
2725 sal_Int32 nErrPos
= 0;
2727 sal_Bool bOk
= pFormatter
->PutEntry( aNewPicture
, nErrPos
,
2728 nNewType
, nNewFormat
, eLanguage
);
2729 OSL_ENSURE( bOk
, "incorrect numberformat generated" );
2737 ScPatternAttr
aNewAttrs( pDoc
->GetPool() );
2738 SfxItemSet
& rSet
= aNewAttrs
.GetItemSet();
2739 rSet
.Put( SfxUInt32Item( ATTR_VALUE_FORMAT
, nNewFormat
) );
2740 // ATTR_LANGUAGE_FORMAT not
2741 ApplySelectionPattern( aNewAttrs
, sal_True
);
2745 void ScViewFunc::ChangeIndent( sal_Bool bIncrement
)
2747 ScViewData
* pViewData
= GetViewData();
2748 ScDocShell
* pDocSh
= pViewData
->GetDocShell();
2749 ScMarkData
& rMark
= pViewData
->GetMarkData();
2751 ScMarkData aWorkMark
= rMark
;
2752 ScViewUtil::UnmarkFiltered( aWorkMark
, pDocSh
->GetDocument() );
2753 aWorkMark
.MarkToMulti();
2754 if (!aWorkMark
.IsMultiMarked())
2756 SCCOL nCol
= pViewData
->GetCurX();
2757 SCROW nRow
= pViewData
->GetCurY();
2758 SCTAB nTab
= pViewData
->GetTabNo();
2759 aWorkMark
.SetMultiMarkArea( ScRange(nCol
,nRow
,nTab
) );
2762 sal_Bool bSuccess
= pDocSh
->GetDocFunc().ChangeIndent( aWorkMark
, bIncrement
, false );
2765 pDocSh
->UpdateOle(pViewData
);
2770 sal_Bool
ScViewFunc::InsertName( const String
& rName
, const String
& rSymbol
,
2771 const String
& rType
)
2773 // Type = P,R,C,F (and combinations)
2776 sal_Bool bOk
= false;
2777 ScDocShell
* pDocSh
= GetViewData()->GetDocShell();
2778 ScDocument
* pDoc
= pDocSh
->GetDocument();
2779 SCTAB nTab
= GetViewData()->GetTabNo();
2780 ScRangeName
* pList
= pDoc
->GetRangeName();
2782 RangeType nType
= RT_NAME
;
2783 ScRangeData
* pNewEntry
= new ScRangeData( pDoc
, rName
, rSymbol
,
2784 ScAddress( GetViewData()->GetCurX(), GetViewData()->GetCurY(),
2786 String aUpType
= rType
;
2787 aUpType
.ToUpperAscii();
2788 if ( aUpType
.Search( 'P' ) != STRING_NOTFOUND
)
2789 nType
|= RT_PRINTAREA
;
2790 if ( aUpType
.Search( 'R' ) != STRING_NOTFOUND
)
2791 nType
|= RT_ROWHEADER
;
2792 if ( aUpType
.Search( 'C' ) != STRING_NOTFOUND
)
2793 nType
|= RT_COLHEADER
;
2794 if ( aUpType
.Search( 'F' ) != STRING_NOTFOUND
)
2795 nType
|= RT_CRITERIA
;
2796 pNewEntry
->AddType(nType
);
2798 if ( !pNewEntry
->GetErrCode() ) // text valid?
2800 ScDocShellModificator
aModificator( *pDocSh
);
2802 pDoc
->CompileNameFormula( sal_True
); // CreateFormulaString
2804 // input available yet? Then remove beforehand (=change)
2805 ScRangeData
* pData
= pList
->findByUpperName(ScGlobal::pCharClass
->uppercase(rName
));
2808 pNewEntry
->SetIndex(pData
->GetIndex());
2809 pList
->erase(*pData
);
2812 if ( pList
->insert( pNewEntry
) )
2814 pNewEntry
= NULL
; // never delete, insert took ownership
2816 pDoc
->CompileNameFormula( false ); // CompileFormulaString
2817 aModificator
.SetDocumentModified();
2818 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED
) );
2821 delete pNewEntry
; // if it wasn't inserted
2825 void ScViewFunc::CreateNames( sal_uInt16 nFlags
)
2827 sal_Bool bDone
= false;
2829 if ( GetViewData()->GetSimpleArea(aRange
) == SC_MARK_SIMPLE
)
2830 bDone
= GetViewData()->GetDocShell()->GetDocFunc().CreateNames( aRange
, nFlags
, false );
2833 ErrorMessage(STR_CREATENAME_MARKERR
);
2836 sal_uInt16
ScViewFunc::GetCreateNameFlags()
2838 sal_uInt16 nFlags
= 0;
2840 SCCOL nStartCol
, nEndCol
;
2841 SCROW nStartRow
, nEndRow
;
2843 if (GetViewData()->GetSimpleArea(nStartCol
,nStartRow
,nDummy
,nEndCol
,nEndRow
,nDummy
) == SC_MARK_SIMPLE
)
2845 ScDocument
* pDoc
= GetViewData()->GetDocument();
2846 SCTAB nTab
= GetViewData()->GetTabNo();
2852 SCCOL nFirstCol
= nStartCol
;
2853 SCCOL nLastCol
= nEndCol
;
2854 if (nStartCol
+1 < nEndCol
) { ++nFirstCol
; --nLastCol
; }
2855 for (i
=nFirstCol
; i
<=nLastCol
&& bOk
; i
++)
2856 if (!pDoc
->HasStringData( i
,nStartRow
,nTab
))
2860 else // Bottom only if not Top
2863 for (i
=nFirstCol
; i
<=nLastCol
&& bOk
; i
++)
2864 if (!pDoc
->HasStringData( i
,nEndRow
,nTab
))
2867 nFlags
|= NAME_BOTTOM
;
2871 SCROW nFirstRow
= nStartRow
;
2872 SCROW nLastRow
= nEndRow
;
2873 if (nStartRow
+1 < nEndRow
) { ++nFirstRow
; --nLastRow
; }
2874 for (j
=nFirstRow
; j
<=nLastRow
&& bOk
; j
++)
2875 if (!pDoc
->HasStringData( nStartCol
,j
,nTab
))
2878 nFlags
|= NAME_LEFT
;
2879 else // Right only if not Left
2882 for (j
=nFirstRow
; j
<=nLastRow
&& bOk
; j
++)
2883 if (!pDoc
->HasStringData( nEndCol
,j
,nTab
))
2886 nFlags
|= NAME_RIGHT
;
2890 if (nStartCol
== nEndCol
)
2891 nFlags
&= ~( NAME_LEFT
| NAME_RIGHT
);
2892 if (nStartRow
== nEndRow
)
2893 nFlags
&= ~( NAME_TOP
| NAME_BOTTOM
);
2898 void ScViewFunc::InsertNameList()
2900 ScAddress
aPos( GetViewData()->GetCurX(), GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
2901 ScDocShell
* pDocSh
= GetViewData()->GetDocShell();
2902 if ( pDocSh
->GetDocFunc().InsertNameList( aPos
, false ) )
2903 pDocSh
->UpdateOle(GetViewData());
2909 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */