Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <config_features.h>
21 :
22 : #include "scitems.hxx"
23 : #include <editeng/eeitem.hxx>
24 :
25 : #include <sfx2/app.hxx>
26 : #include <svx/algitem.hxx>
27 : #include <editeng/boxitem.hxx>
28 : #include <editeng/editobj.hxx>
29 : #include <editeng/editview.hxx>
30 : #include <editeng/langitem.hxx>
31 : #include <editeng/scripttypeitem.hxx>
32 : #include <editeng/justifyitem.hxx>
33 : #include <sfx2/bindings.hxx>
34 : #include <svl/zforlist.hxx>
35 : #include <svl/zformat.hxx>
36 : #include <vcl/msgbox.hxx>
37 : #include <vcl/virdev.hxx>
38 : #include <vcl/waitobj.hxx>
39 : #include <vcl/wrkwin.hxx>
40 : #include <stdlib.h>
41 :
42 : #include "viewfunc.hxx"
43 : #include "tabvwsh.hxx"
44 : #include "docsh.hxx"
45 : #include "attrib.hxx"
46 : #include "patattr.hxx"
47 : #include "docpool.hxx"
48 : #include "uiitems.hxx"
49 : #include "sc.hrc"
50 : #include "undocell.hxx"
51 : #include "undoblk.hxx"
52 : #include "undotab.hxx"
53 : #include "refundo.hxx"
54 : #include "dbdata.hxx"
55 : #include "olinetab.hxx"
56 : #include "rangeutl.hxx"
57 : #include "rangenam.hxx"
58 : #include "globstr.hrc"
59 : #include "global.hxx"
60 : #include "stlsheet.hxx"
61 : #include "editutil.hxx"
62 : #include "formulacell.hxx"
63 : #include "scresid.hxx"
64 : #include "inputhdl.hxx"
65 : #include "scmod.hxx"
66 : #include "inputopt.hxx"
67 : #include "compiler.hxx"
68 : #include "docfunc.hxx"
69 : #include "appoptio.hxx"
70 : #include "dociter.hxx"
71 : #include "sizedev.hxx"
72 : #include "editable.hxx"
73 : #include "scui_def.hxx"
74 : #include "funcdesc.hxx"
75 : #include "docuno.hxx"
76 : #include "cellsuno.hxx"
77 : #include "tokenarray.hxx"
78 : #include <rowheightcontext.hxx>
79 : #include <docfuncutil.hxx>
80 :
81 : #include <boost/scoped_ptr.hpp>
82 :
83 0 : static void lcl_PostRepaintCondFormat( const ScConditionalFormat *pCondFmt, ScDocShell *pDocSh )
84 : {
85 0 : if( pCondFmt )
86 : {
87 0 : const ScRangeList& rRanges = pCondFmt->GetRange();
88 :
89 0 : pDocSh->PostPaint( rRanges, PAINT_ALL );
90 : }
91 0 : }
92 :
93 348 : ScViewFunc::ScViewFunc( vcl::Window* pParent, ScDocShell& rDocSh, ScTabViewShell* pViewShell ) :
94 : ScTabView( pParent, rDocSh, pViewShell ),
95 348 : bFormatValid( false )
96 : {
97 348 : }
98 :
99 345 : ScViewFunc::~ScViewFunc()
100 : {
101 345 : }
102 :
103 0 : void ScViewFunc::StartFormatArea()
104 : {
105 : // anything to do?
106 0 : if ( !SC_MOD()->GetInputOptions().GetExtendFormat() )
107 0 : return;
108 :
109 : // start only with single cell (marked or cursor position)
110 0 : ScRange aMarkRange;
111 0 : bool bOk = (GetViewData().GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE);
112 0 : if ( bOk && aMarkRange.aStart != aMarkRange.aEnd )
113 0 : bOk = false;
114 :
115 0 : if (bOk)
116 : {
117 0 : bFormatValid = true;
118 0 : aFormatSource = aMarkRange.aStart;
119 0 : aFormatArea = ScRange( aFormatSource );
120 : }
121 : else
122 0 : bFormatValid = false; // discard old range
123 : }
124 :
125 0 : bool ScViewFunc::TestFormatArea( SCCOL nCol, SCROW nRow, SCTAB nTab, bool bAttrChanged )
126 : {
127 : // anything to do?
128 0 : if ( !SC_MOD()->GetInputOptions().GetExtendFormat() )
129 0 : return false;
130 :
131 : // Test: treat input with numberformat (bAttrChanged) always as new Attribute
132 : // (discard old Area ). If not wanted, discard if-statement
133 0 : if ( bAttrChanged )
134 : {
135 0 : StartFormatArea();
136 0 : return false;
137 : }
138 :
139 : //! Test if cell empty ???
140 :
141 0 : bool bFound = false;
142 0 : ScRange aNewRange = aFormatArea;
143 0 : if ( bFormatValid && nTab == aFormatSource.Tab() )
144 : {
145 0 : if ( nRow >= aFormatArea.aStart.Row() && nRow <= aFormatArea.aEnd.Row() )
146 : {
147 : // within range?
148 0 : if ( nCol >= aFormatArea.aStart.Col() && nCol <= aFormatArea.aEnd.Col() )
149 : {
150 0 : bFound = true; // do not change range
151 : }
152 : // left ?
153 0 : if ( nCol+1 == aFormatArea.aStart.Col() )
154 : {
155 0 : bFound = true;
156 0 : aNewRange.aStart.SetCol( nCol );
157 : }
158 : // right ?
159 0 : if ( nCol == aFormatArea.aEnd.Col()+1 )
160 : {
161 0 : bFound = true;
162 0 : aNewRange.aEnd.SetCol( nCol );
163 : }
164 : }
165 0 : if ( nCol >= aFormatArea.aStart.Col() && nCol <= aFormatArea.aEnd.Col() )
166 : {
167 : // top ?
168 0 : if ( nRow+1 == aFormatArea.aStart.Row() )
169 : {
170 0 : bFound = true;
171 0 : aNewRange.aStart.SetRow( nRow );
172 : }
173 : // bottom ?
174 0 : if ( nRow == aFormatArea.aEnd.Row()+1 )
175 : {
176 0 : bFound = true;
177 0 : aNewRange.aEnd.SetRow( nRow );
178 : }
179 : }
180 : }
181 :
182 0 : if (bFound)
183 0 : aFormatArea = aNewRange; // extend
184 : else
185 0 : bFormatValid = false; // outside of range -> break
186 :
187 0 : return bFound;
188 : }
189 :
190 0 : void ScViewFunc::DoAutoAttributes( SCCOL nCol, SCROW nRow, SCTAB nTab,
191 : bool bAttrChanged, bool bAddUndo )
192 : {
193 0 : ScDocShell* pDocSh = GetViewData().GetDocShell();
194 0 : ScDocument& rDoc = pDocSh->GetDocument();
195 0 : if (bAddUndo && !rDoc.IsUndoEnabled())
196 0 : bAddUndo = false;
197 :
198 : const ScPatternAttr* pSource = rDoc.GetPattern(
199 0 : aFormatSource.Col(), aFormatSource.Row(), nTab );
200 0 : if ( !static_cast<const ScMergeAttr&>(pSource->GetItem(ATTR_MERGE)).IsMerged() )
201 : {
202 0 : ScRange aRange( nCol, nRow, nTab, nCol, nRow, nTab );
203 0 : ScMarkData aMark;
204 0 : aMark.SetMarkArea( aRange );
205 :
206 0 : ScDocFunc &rFunc = GetViewData().GetDocFunc();
207 :
208 : // pOldPattern is only valid until call to ApplyAttributes!
209 0 : const ScPatternAttr* pOldPattern = rDoc.GetPattern( nCol, nRow, nTab );
210 0 : const ScStyleSheet* pSrcStyle = pSource->GetStyleSheet();
211 0 : if ( pSrcStyle && pSrcStyle != pOldPattern->GetStyleSheet() )
212 0 : rFunc.ApplyStyle( aMark, pSrcStyle->GetName(), true, false );
213 :
214 0 : rFunc.ApplyAttributes( aMark, *pSource, true, false );
215 : }
216 :
217 0 : if ( bAttrChanged ) // value entered with number format?
218 0 : aFormatSource.Set( nCol, nRow, nTab ); // then set a new source
219 0 : }
220 :
221 : // additional routines
222 :
223 0 : sal_uInt16 ScViewFunc::GetOptimalColWidth( SCCOL nCol, SCTAB nTab, bool bFormula )
224 : {
225 0 : ScDocShell* pDocSh = GetViewData().GetDocShell();
226 0 : ScDocument& rDoc = pDocSh->GetDocument();
227 0 : ScMarkData& rMark = GetViewData().GetMarkData();
228 :
229 0 : double nPPTX = GetViewData().GetPPTX();
230 0 : double nPPTY = GetViewData().GetPPTY();
231 0 : Fraction aZoomX = GetViewData().GetZoomX();
232 0 : Fraction aZoomY = GetViewData().GetZoomY();
233 :
234 0 : ScSizeDeviceProvider aProv(pDocSh);
235 0 : if (aProv.IsPrinter())
236 : {
237 0 : nPPTX = aProv.GetPPTX();
238 0 : nPPTY = aProv.GetPPTY();
239 0 : aZoomX = aZoomY = Fraction( 1, 1 );
240 : }
241 :
242 : sal_uInt16 nTwips = rDoc.GetOptimalColWidth( nCol, nTab, aProv.GetDevice(),
243 0 : nPPTX, nPPTY, aZoomX, aZoomY, bFormula, &rMark );
244 0 : return nTwips;
245 : }
246 :
247 1780 : bool ScViewFunc::SelectionEditable( bool* pOnlyNotBecauseOfMatrix /* = NULL */ )
248 : {
249 : bool bRet;
250 1780 : ScDocument* pDoc = GetViewData().GetDocument();
251 1780 : ScMarkData& rMark = GetViewData().GetMarkData();
252 1780 : if (rMark.IsMarked() || rMark.IsMultiMarked())
253 10 : bRet = pDoc->IsSelectionEditable( rMark, pOnlyNotBecauseOfMatrix );
254 : else
255 : {
256 1770 : SCCOL nCol = GetViewData().GetCurX();
257 1770 : SCROW nRow = GetViewData().GetCurY();
258 1770 : SCTAB nTab = GetViewData().GetTabNo();
259 : bRet = pDoc->IsBlockEditable( nTab, nCol, nRow, nCol, nRow,
260 1770 : pOnlyNotBecauseOfMatrix );
261 : }
262 1780 : return bRet;
263 : }
264 :
265 : #ifndef LRU_MAX
266 : #define LRU_MAX 10
267 : #endif
268 :
269 0 : static bool lcl_FunctionKnown( sal_uInt16 nOpCode )
270 : {
271 0 : const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList();
272 0 : if ( pFuncList )
273 : {
274 0 : sal_uLong nCount = pFuncList->GetCount();
275 0 : for (sal_uLong i=0; i<nCount; i++)
276 0 : if ( pFuncList->GetFunction(i)->nFIndex == nOpCode )
277 0 : return true;
278 : }
279 0 : return false;
280 : }
281 :
282 0 : static bool lcl_AddFunction( ScAppOptions& rAppOpt, sal_uInt16 nOpCode )
283 : {
284 0 : sal_uInt16 nOldCount = rAppOpt.GetLRUFuncListCount();
285 0 : sal_uInt16* pOldList = rAppOpt.GetLRUFuncList();
286 : sal_uInt16 nPos;
287 0 : for (nPos=0; nPos<nOldCount; nPos++)
288 0 : if (pOldList[nPos] == nOpCode) // is the function already in the list?
289 : {
290 0 : if ( nPos == 0 )
291 0 : return false; // already at the top -> no change
292 :
293 : // count doesn't change, so the original array is modified
294 :
295 0 : for (sal_uInt16 nCopy=nPos; nCopy>0; nCopy--)
296 0 : pOldList[nCopy] = pOldList[nCopy-1];
297 0 : pOldList[0] = nOpCode;
298 :
299 0 : return true; // list has changed
300 : }
301 :
302 0 : if ( !lcl_FunctionKnown( nOpCode ) )
303 0 : return false; // not in function list -> no change
304 :
305 0 : sal_uInt16 nNewCount = std::min( (sal_uInt16)(nOldCount + 1), (sal_uInt16)LRU_MAX );
306 : sal_uInt16 nNewList[LRU_MAX];
307 0 : nNewList[0] = nOpCode;
308 0 : for (nPos=1; nPos<nNewCount; nPos++)
309 0 : nNewList[nPos] = pOldList[nPos-1];
310 0 : rAppOpt.SetLRUFuncList( nNewList, nNewCount );
311 :
312 0 : return true; // list has changed
313 : }
314 :
315 : namespace HelperNotifyChanges
316 : {
317 0 : void NotifyIfChangesListeners(ScDocShell &rDocShell, ScMarkData& rMark, SCCOL nCol, SCROW nRow,
318 : const OUString &rType = OUString("cell-change"))
319 : {
320 0 : if (ScModelObj *pModelObj = getMustPropagateChangesModel(rDocShell))
321 : {
322 0 : ScRangeList aChangeRanges;
323 0 : ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
324 0 : for (; itr != itrEnd; ++itr)
325 0 : aChangeRanges.Append( ScRange( nCol, nRow, *itr ) );
326 :
327 0 : HelperNotifyChanges::Notify(*pModelObj, aChangeRanges, rType);
328 : }
329 0 : }
330 : }
331 :
332 : // actual functions
333 :
334 : // input - undo OK
335 0 : void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab,
336 : const OUString& rString,
337 : const EditTextObject* pData )
338 : {
339 0 : ScDocument* pDoc = GetViewData().GetDocument();
340 0 : ScMarkData rMark(GetViewData().GetMarkData());
341 0 : bool bRecord = pDoc->IsUndoEnabled();
342 : SCTAB i;
343 :
344 0 : ScDocShell* pDocSh = GetViewData().GetDocShell();
345 0 : ScDocFunc &rFunc = GetViewData().GetDocFunc();
346 0 : ScDocShellModificator aModificator( *pDocSh );
347 :
348 0 : ScEditableTester aTester( pDoc, nCol,nRow, nCol,nRow, rMark );
349 0 : if (!aTester.IsEditable())
350 : {
351 0 : ErrorMessage(aTester.GetMessageId());
352 0 : PaintArea(nCol, nRow, nCol, nRow); // possibly the edit-engine is still painted there
353 0 : return;
354 : }
355 :
356 0 : if ( bRecord )
357 0 : rFunc.EnterListAction( STR_UNDO_ENTERDATA );
358 :
359 0 : bool bFormula = false;
360 :
361 : // a single '=' character is handled as string (needed for special filters)
362 0 : if ( rString.getLength() > 1 )
363 : {
364 0 : if ( rString[0] == '=' )
365 : {
366 : // handle as formula
367 0 : bFormula = true;
368 : }
369 0 : else if ( rString[0] == '+' || rString[0] == '-' )
370 : {
371 : // if there is more than one leading '+' or '-' character, remove the additional ones
372 0 : sal_Int32 nIndex = 1;
373 0 : sal_Int32 nLen = rString.getLength();
374 0 : while ( nIndex < nLen && ( rString[ nIndex ] == '+' || rString[ nIndex ] == '-' ) )
375 : {
376 0 : ++nIndex;
377 : }
378 0 : OUString aString = rString.replaceAt( 1, nIndex - 1, "" );
379 :
380 : // if the remaining part without the leading '+' or '-' character
381 : // is non-empty and not a number, handle as formula
382 0 : if ( aString.getLength() > 1 )
383 : {
384 0 : sal_uInt32 nFormat = 0;
385 0 : pDoc->GetNumberFormat( nCol, nRow, nTab, nFormat );
386 0 : SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
387 0 : double fNumber = 0;
388 0 : if ( !pFormatter->IsNumberFormat( aString, nFormat, fNumber ) )
389 : {
390 0 : bFormula = true;
391 : }
392 0 : }
393 : }
394 : }
395 :
396 0 : bool bNumFmtChanged = false;
397 0 : if ( bFormula )
398 : { // formula, compile with autoCorrection
399 0 : i = rMark.GetFirstSelected();
400 0 : ScAddress aPos( nCol, nRow, i );
401 0 : ScCompiler aComp( pDoc, aPos);
402 0 : aComp.SetGrammar(pDoc->GetGrammar());
403 : //2do: enable/disable autoCorrection via calcoptions
404 0 : aComp.SetAutoCorrection( true );
405 0 : if ( rString[0] == '+' || rString[0] == '-' )
406 : {
407 0 : aComp.SetExtendedErrorDetection( ScCompiler::EXTENDED_ERROR_DETECTION_NAME_BREAK );
408 : }
409 0 : OUString aFormula( rString );
410 : ScTokenArray* pArr;
411 : bool bAgain;
412 0 : do
413 : {
414 0 : bAgain = false;
415 0 : bool bAddEqual = false;
416 0 : ScTokenArray* pArrFirst = pArr = aComp.CompileString( aFormula );
417 0 : bool bCorrected = aComp.IsCorrected();
418 0 : if ( bCorrected )
419 : { // try to parse with first parser-correction
420 0 : pArr = aComp.CompileString( aComp.GetCorrectedFormula() );
421 : }
422 0 : if ( !pArr->GetCodeError() )
423 : {
424 0 : bAddEqual = true;
425 0 : aComp.CompileTokenArray();
426 0 : bCorrected |= aComp.IsCorrected();
427 : }
428 0 : if ( bCorrected )
429 : {
430 0 : OUString aCorrectedFormula;
431 0 : if ( bAddEqual )
432 : {
433 0 : aCorrectedFormula = "=" + aComp.GetCorrectedFormula();
434 : }
435 : else
436 0 : aCorrectedFormula = aComp.GetCorrectedFormula();
437 : short nResult;
438 0 : if ( aCorrectedFormula.getLength() == 1 )
439 0 : nResult = RET_NO; // empty formula, just '='
440 : else
441 : {
442 0 : OUString aMessage( ScResId( SCSTR_FORMULA_AUTOCORRECTION ) );
443 0 : aMessage += aCorrectedFormula;
444 0 : nResult = ScopedVclPtr<QueryBox>::Create( GetViewData().GetDialogParent(),
445 : WinBits(WB_YES_NO | WB_DEF_YES),
446 0 : aMessage )->Execute();
447 : }
448 0 : if ( nResult == RET_YES )
449 : {
450 0 : aFormula = aCorrectedFormula;
451 0 : if ( pArr != pArrFirst )
452 0 : delete pArrFirst;
453 0 : bAgain = true;
454 : }
455 : else
456 : {
457 0 : if ( pArr != pArrFirst )
458 : {
459 0 : delete pArr;
460 0 : pArr = pArrFirst;
461 : }
462 0 : }
463 : }
464 : } while ( bAgain );
465 : // to be used in multiple tabs, the formula must be compiled anew
466 : // via ScFormulaCell copy-ctor because of RangeNames,
467 : // the same code-array for all cells is not possible.
468 : // If the array has an error, (it) must be RPN-erased in the newly generated
469 : // cellst and the error be set explicitly, so that
470 : // via FormulaCell copy-ctor and Interpreter it will be, when possible,
471 : // ironed out again, too intelligent.. e.g.: =1))
472 0 : sal_uInt16 nError = pArr->GetCodeError();
473 0 : if ( !nError )
474 : {
475 : // update list of recent functions with all functions that
476 : // are not within parentheses
477 :
478 0 : ScModule* pScMod = SC_MOD();
479 0 : ScAppOptions aAppOpt = pScMod->GetAppOptions();
480 0 : bool bOptChanged = false;
481 :
482 0 : formula::FormulaToken** ppToken = pArr->GetArray();
483 0 : sal_uInt16 nTokens = pArr->GetLen();
484 0 : sal_uInt16 nLevel = 0;
485 0 : for (sal_uInt16 nTP=0; nTP<nTokens; nTP++)
486 : {
487 0 : formula::FormulaToken* pTok = ppToken[nTP];
488 0 : OpCode eOp = pTok->GetOpCode();
489 0 : if ( eOp == ocOpen )
490 0 : ++nLevel;
491 0 : else if ( eOp == ocClose && nLevel )
492 0 : --nLevel;
493 0 : if ( nLevel == 0 && pTok->IsFunction() &&
494 0 : lcl_AddFunction( aAppOpt, sal::static_int_cast<sal_uInt16>( eOp ) ) )
495 0 : bOptChanged = true;
496 : }
497 :
498 0 : if ( bOptChanged )
499 : {
500 0 : pScMod->SetAppOptions(aAppOpt);
501 0 : ScModule::RecentFunctionsChanged();
502 0 : }
503 : }
504 :
505 0 : ScFormulaCell aCell(pDoc, aPos, *pArr, formula::FormulaGrammar::GRAM_DEFAULT, MM_NONE);
506 0 : delete pArr;
507 :
508 0 : SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
509 0 : ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
510 0 : for (; itr != itrEnd; ++itr)
511 : {
512 0 : i = *itr;
513 0 : aPos.SetTab( i );
514 : sal_uLong nIndex = (sal_uLong) static_cast<const SfxUInt32Item*>( pDoc->GetAttr(
515 0 : nCol, nRow, i, ATTR_VALUE_FORMAT ))->GetValue();
516 0 : if ( pFormatter->GetType( nIndex ) == css::util::NumberFormat::TEXT ||
517 0 : ( ( rString[0] == '+' || rString[0] == '-' ) && nError && rString == aFormula ) )
518 : {
519 0 : if ( pData )
520 : {
521 : // A clone of pData will be stored in the cell.
522 0 : rFunc.SetEditCell(aPos, *pData, true);
523 : }
524 : else
525 0 : rFunc.SetStringCell(aPos, aFormula, true);
526 : }
527 : else
528 : {
529 0 : ScFormulaCell* pCell = new ScFormulaCell( aCell, *pDoc, aPos );
530 0 : if ( nError )
531 : {
532 0 : pCell->GetCode()->DelRPN();
533 0 : pCell->SetErrCode( nError );
534 0 : if(pCell->GetCode()->IsHyperLink())
535 0 : pCell->GetCode()->SetHyperLink(false);
536 : }
537 0 : rFunc.SetFormulaCell(aPos, pCell, true);
538 : }
539 0 : }
540 : }
541 : else
542 : {
543 0 : ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
544 0 : for ( ; itr != itrEnd; ++itr )
545 : {
546 0 : bool bNumFmtSet = false;
547 0 : rFunc.SetNormalString( bNumFmtSet, ScAddress( nCol, nRow, *itr ), rString, false );
548 0 : if (bNumFmtSet)
549 : {
550 : /* FIXME: if set on any sheet results in changed only on
551 : * sheet nTab for TestFormatArea() and DoAutoAttributes() */
552 0 : bNumFmtChanged = true;
553 : }
554 : }
555 : }
556 :
557 0 : bool bAutoFormat = TestFormatArea(nCol, nRow, nTab, bNumFmtChanged);
558 :
559 0 : if (bAutoFormat)
560 0 : DoAutoAttributes(nCol, nRow, nTab, bNumFmtChanged, bRecord);
561 :
562 0 : pDocSh->UpdateOle(&GetViewData());
563 :
564 0 : HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh, rMark, nCol, nRow);
565 :
566 0 : if ( bRecord )
567 0 : rFunc.EndListAction();
568 :
569 0 : aModificator.SetDocumentModified();
570 0 : lcl_PostRepaintCondFormat( pDoc->GetCondFormat( nCol, nRow, nTab ), pDocSh );
571 : }
572 :
573 : // enter value in single cell (on nTab only)
574 :
575 0 : void ScViewFunc::EnterValue( SCCOL nCol, SCROW nRow, SCTAB nTab, const double& rValue )
576 : {
577 0 : ScDocument* pDoc = GetViewData().GetDocument();
578 0 : ScDocShell* pDocSh = GetViewData().GetDocShell();
579 :
580 0 : if ( pDoc && pDocSh )
581 : {
582 0 : bool bUndo(pDoc->IsUndoEnabled());
583 0 : ScDocShellModificator aModificator( *pDocSh );
584 :
585 0 : ScEditableTester aTester( pDoc, nTab, nCol,nRow, nCol,nRow );
586 0 : if (aTester.IsEditable())
587 : {
588 0 : ScAddress aPos( nCol, nRow, nTab );
589 0 : ScCellValue aUndoCell;
590 0 : if (bUndo)
591 0 : aUndoCell.assign(*pDoc, aPos);
592 :
593 0 : pDoc->SetValue( nCol, nRow, nTab, rValue );
594 :
595 : // because of ChangeTrack after change in document
596 0 : if (bUndo)
597 : {
598 0 : pDocSh->GetUndoManager()->AddUndoAction(
599 0 : new ScUndoEnterValue(pDocSh, aPos, aUndoCell, rValue));
600 : }
601 :
602 0 : pDocSh->PostPaintCell( aPos );
603 0 : pDocSh->UpdateOle(&GetViewData());
604 0 : aModificator.SetDocumentModified();
605 : }
606 : else
607 0 : ErrorMessage(aTester.GetMessageId());
608 : }
609 0 : }
610 :
611 0 : void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab,
612 : const EditTextObject& rData, bool bTestSimple )
613 : {
614 0 : ScDocShell* pDocSh = GetViewData().GetDocShell();
615 0 : ScMarkData& rMark = GetViewData().GetMarkData();
616 0 : ScDocument& rDoc = pDocSh->GetDocument();
617 0 : bool bRecord = rDoc.IsUndoEnabled();
618 :
619 0 : ScDocShellModificator aModificator( *pDocSh );
620 :
621 0 : ScEditableTester aTester( &rDoc, nTab, nCol,nRow, nCol,nRow );
622 0 : if (aTester.IsEditable())
623 : {
624 :
625 : // test for attribute
626 :
627 0 : bool bSimple = false;
628 0 : bool bCommon = false;
629 0 : boost::scoped_ptr<ScPatternAttr> pCellAttrs;
630 0 : OUString aString;
631 :
632 0 : const ScPatternAttr* pOldPattern = rDoc.GetPattern( nCol, nRow, nTab );
633 0 : ScTabEditEngine aEngine( *pOldPattern, rDoc.GetEnginePool() );
634 0 : aEngine.SetText(rData);
635 :
636 0 : if (bTestSimple) // test, if simple string without attribute
637 : {
638 0 : ScEditAttrTester aAttrTester( &aEngine );
639 0 : bSimple = !aAttrTester.NeedsObject();
640 0 : bCommon = aAttrTester.NeedsCellAttr();
641 :
642 : // formulas have to be recognized even if they're formatted
643 : // (but commmon attributes are still collected)
644 :
645 0 : if ( !bSimple && aEngine.GetParagraphCount() == 1 )
646 : {
647 0 : OUString aParStr(aEngine.GetText( 0 ));
648 0 : if ( aParStr[0] == '=' )
649 0 : bSimple = true;
650 : }
651 :
652 0 : if (bCommon) // attribute for tab
653 : {
654 0 : pCellAttrs.reset(new ScPatternAttr( *pOldPattern ));
655 0 : pCellAttrs->GetFromEditItemSet( &aAttrTester.GetAttribs() );
656 : //! remove common attributes from EditEngine?
657 0 : }
658 : }
659 :
660 : // #i97726# always get text for "repeat" of undo action
661 0 : aString = ScEditUtil::GetSpaceDelimitedString(aEngine);
662 :
663 : // undo
664 :
665 0 : EditTextObject* pUndoData = NULL;
666 0 : ScUndoEnterData::ValuesType aOldValues;
667 :
668 0 : if (bRecord && !bSimple)
669 : {
670 0 : ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
671 0 : for (; itr != itrEnd; ++itr)
672 : {
673 0 : ScUndoEnterData::Value aOldValue;
674 0 : aOldValue.mnTab = *itr;
675 0 : aOldValue.maCell.assign(rDoc, ScAddress(nCol, nRow, *itr));
676 0 : aOldValues.push_back(aOldValue);
677 0 : }
678 :
679 0 : pUndoData = rData.Clone();
680 : }
681 :
682 : // enter data
683 :
684 0 : if (bCommon)
685 0 : rDoc.ApplyPattern(nCol,nRow,nTab,*pCellAttrs); //! undo
686 :
687 0 : if (bSimple)
688 : {
689 0 : if (bCommon)
690 0 : AdjustRowHeight(nRow,nRow);
691 :
692 0 : EnterData(nCol,nRow,nTab,aString);
693 : }
694 : else
695 : {
696 0 : ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
697 0 : for (; itr != itrEnd; ++itr)
698 : {
699 0 : ScAddress aPos(nCol, nRow, *itr);
700 0 : rDoc.SetEditText(aPos, rData, rDoc.GetEditPool());
701 : }
702 :
703 0 : if ( bRecord )
704 : { // because of ChangeTrack current first
705 0 : pDocSh->GetUndoManager()->AddUndoAction(
706 0 : new ScUndoEnterData(pDocSh, ScAddress(nCol,nRow,nTab), aOldValues, aString, pUndoData));
707 : }
708 :
709 0 : HideAllCursors();
710 :
711 0 : AdjustRowHeight(nRow,nRow);
712 :
713 0 : itr = rMark.begin();
714 0 : for (; itr != itrEnd; ++itr)
715 0 : pDocSh->PostPaintCell( nCol, nRow, *itr );
716 :
717 0 : ShowAllCursors();
718 :
719 0 : pDocSh->UpdateOle(&GetViewData());
720 :
721 0 : HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh, rMark, nCol, nRow);
722 :
723 0 : aModificator.SetDocumentModified();
724 : }
725 0 : lcl_PostRepaintCondFormat( rDoc.GetCondFormat( nCol, nRow, nTab ), pDocSh );
726 : }
727 : else
728 : {
729 0 : ErrorMessage(aTester.GetMessageId());
730 0 : PaintArea( nCol, nRow, nCol, nRow ); // possibly the edit-engine is still painted there
731 0 : }
732 0 : }
733 :
734 0 : void ScViewFunc::EnterDataAtCursor( const OUString& rString )
735 : {
736 0 : SCCOL nPosX = GetViewData().GetCurX();
737 0 : SCROW nPosY = GetViewData().GetCurY();
738 0 : SCTAB nTab = GetViewData().GetTabNo();
739 :
740 0 : EnterData( nPosX, nPosY, nTab, rString );
741 0 : }
742 :
743 0 : void ScViewFunc::EnterMatrix( const OUString& rString, ::formula::FormulaGrammar::Grammar eGram )
744 : {
745 0 : ScViewData& rData = GetViewData();
746 0 : const ScMarkData& rMark = rData.GetMarkData();
747 0 : if ( !rMark.IsMarked() && !rMark.IsMultiMarked() )
748 : {
749 : // nothing marked -> temporarily calculate block
750 : // with size of result formula to get the size
751 :
752 0 : ScDocument* pDoc = rData.GetDocument();
753 0 : SCCOL nCol = rData.GetCurX();
754 0 : SCROW nRow = rData.GetCurY();
755 0 : SCTAB nTab = rData.GetTabNo();
756 0 : ScFormulaCell aFormCell( pDoc, ScAddress(nCol,nRow,nTab), rString, eGram, MM_FORMULA );
757 :
758 : SCSIZE nSizeX;
759 : SCSIZE nSizeY;
760 0 : aFormCell.GetResultDimensions( nSizeX, nSizeY );
761 0 : if ( nSizeX != 0 && nSizeY != 0 &&
762 0 : nCol+nSizeX-1 <= sal::static_int_cast<SCSIZE>(MAXCOL) &&
763 0 : nRow+nSizeY-1 <= sal::static_int_cast<SCSIZE>(MAXROW) )
764 : {
765 : ScRange aResult( nCol, nRow, nTab,
766 0 : sal::static_int_cast<SCCOL>(nCol+nSizeX-1),
767 0 : sal::static_int_cast<SCROW>(nRow+nSizeY-1), nTab );
768 0 : MarkRange( aResult, false );
769 0 : }
770 : }
771 :
772 0 : ScRange aRange;
773 0 : if (rData.GetSimpleArea(aRange) == SC_MARK_SIMPLE)
774 : {
775 0 : ScDocShell* pDocSh = rData.GetDocShell();
776 0 : bool bSuccess = pDocSh->GetDocFunc().EnterMatrix(
777 0 : aRange, &rMark, NULL, rString, false, false, EMPTY_OUSTRING, eGram );
778 0 : if (bSuccess)
779 0 : pDocSh->UpdateOle(&GetViewData());
780 : }
781 : else
782 0 : ErrorMessage(STR_NOMULTISELECT);
783 0 : }
784 :
785 1715 : SvtScriptType ScViewFunc::GetSelectionScriptType()
786 : {
787 1715 : SvtScriptType nScript = SvtScriptType::NONE;
788 :
789 1715 : ScDocument* pDoc = GetViewData().GetDocument();
790 1715 : const ScMarkData& rMark = GetViewData().GetMarkData();
791 1715 : if ( !rMark.IsMarked() && !rMark.IsMultiMarked() )
792 : {
793 : // no selection -> cursor
794 :
795 1695 : nScript = pDoc->GetScriptType( GetViewData().GetCurX(),
796 3390 : GetViewData().GetCurY(), GetViewData().GetTabNo());
797 : }
798 : else
799 : {
800 20 : ScRangeList aRanges;
801 20 : rMark.FillRangeListWithMarks( &aRanges, false );
802 20 : nScript = pDoc->GetRangeScriptType(aRanges);
803 : }
804 :
805 1715 : if (nScript == SvtScriptType::NONE)
806 1641 : nScript = ScGlobal::GetDefaultScriptType();
807 :
808 1715 : return nScript;
809 : }
810 :
811 9668 : const ScPatternAttr* ScViewFunc::GetSelectionPattern()
812 : {
813 : // Don't use UnmarkFiltered in slot state functions, for performance reasons.
814 : // The displayed state is always that of the whole selection including filtered rows.
815 :
816 9668 : const ScMarkData& rMark = GetViewData().GetMarkData();
817 9668 : ScDocument* pDoc = GetViewData().GetDocument();
818 9668 : if ( rMark.IsMarked() || rMark.IsMultiMarked() )
819 : {
820 : // MarkToMulti is no longer necessary for pDoc->GetSelectionPattern
821 20 : const ScPatternAttr* pAttr = pDoc->GetSelectionPattern( rMark );
822 20 : return pAttr;
823 : }
824 : else
825 : {
826 9648 : SCCOL nCol = GetViewData().GetCurX();
827 9648 : SCROW nRow = GetViewData().GetCurY();
828 9648 : SCTAB nTab = GetViewData().GetTabNo();
829 :
830 9648 : ScMarkData aTempMark( rMark ); // copy sheet selection
831 9648 : aTempMark.SetMarkArea( ScRange( nCol, nRow, nTab ) );
832 9648 : const ScPatternAttr* pAttr = pDoc->GetSelectionPattern( aTempMark );
833 9648 : return pAttr;
834 : }
835 : }
836 :
837 680 : void ScViewFunc::GetSelectionFrame( SvxBoxItem& rLineOuter,
838 : SvxBoxInfoItem& rLineInner )
839 : {
840 680 : ScDocument* pDoc = GetViewData().GetDocument();
841 680 : const ScMarkData& rMark = GetViewData().GetMarkData();
842 :
843 680 : if ( rMark.IsMarked() || rMark.IsMultiMarked() )
844 : {
845 20 : if ( rMark.IsMultiMarked() )
846 : {
847 0 : ScMarkData aNewMark( rMark ); // use local copy for MarkToSimple
848 0 : aNewMark.MarkToSimple(); // simple block is needed for GetSelectionFrame
849 0 : pDoc->GetSelectionFrame( aNewMark, rLineOuter, rLineInner );
850 : }
851 : else
852 20 : pDoc->GetSelectionFrame( rMark, rLineOuter, rLineInner );
853 : }
854 : else
855 : {
856 : const ScPatternAttr* pAttrs =
857 660 : pDoc->GetPattern( GetViewData().GetCurX(),
858 660 : GetViewData().GetCurY(),
859 1980 : GetViewData().GetTabNo() );
860 :
861 660 : rLineOuter = static_cast<const SvxBoxItem&> (pAttrs->GetItem( ATTR_BORDER ));
862 660 : rLineInner = static_cast<const SvxBoxInfoItem&>(pAttrs->GetItem( ATTR_BORDER_INNER ));
863 660 : rLineInner.SetTable(false);
864 660 : rLineInner.SetDist(true);
865 660 : rLineInner.SetMinDist(false);
866 : }
867 680 : }
868 :
869 : // apply attribute - undo OK
870 : //
871 : // complete set ( ATTR_STARTINDEX, ATTR_ENDINDEX )
872 :
873 0 : void ScViewFunc::ApplyAttributes( const SfxItemSet* pDialogSet,
874 : const SfxItemSet* pOldSet,
875 : bool bRecord )
876 : {
877 : // not editable because of matrix only? attribute OK nonetheless
878 : bool bOnlyNotBecauseOfMatrix;
879 0 : if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
880 : {
881 0 : ErrorMessage(STR_PROTECTIONERR);
882 0 : return;
883 : }
884 :
885 0 : ScPatternAttr aOldAttrs( new SfxItemSet(*pOldSet) );
886 0 : ScPatternAttr aNewAttrs( new SfxItemSet(*pDialogSet) );
887 0 : aNewAttrs.DeleteUnchanged( &aOldAttrs );
888 :
889 0 : if ( pDialogSet->GetItemState( ATTR_VALUE_FORMAT ) == SfxItemState::SET )
890 : { // don't reset to default SYSTEM GENERAL if not intended
891 : sal_uInt32 nOldFormat =
892 0 : static_cast<const SfxUInt32Item&>(pOldSet->Get( ATTR_VALUE_FORMAT )).GetValue();
893 : sal_uInt32 nNewFormat =
894 0 : static_cast<const SfxUInt32Item&>(pDialogSet->Get( ATTR_VALUE_FORMAT )).GetValue();
895 0 : if ( nNewFormat != nOldFormat )
896 : {
897 : SvNumberFormatter* pFormatter =
898 0 : GetViewData().GetDocument()->GetFormatTable();
899 0 : const SvNumberformat* pOldEntry = pFormatter->GetEntry( nOldFormat );
900 : LanguageType eOldLang =
901 0 : pOldEntry ? pOldEntry->GetLanguage() : LANGUAGE_DONTKNOW;
902 0 : const SvNumberformat* pNewEntry = pFormatter->GetEntry( nNewFormat );
903 : LanguageType eNewLang =
904 0 : pNewEntry ? pNewEntry->GetLanguage() : LANGUAGE_DONTKNOW;
905 0 : if ( eNewLang != eOldLang )
906 : {
907 0 : aNewAttrs.GetItemSet().Put(
908 0 : SvxLanguageItem( eNewLang, ATTR_LANGUAGE_FORMAT ) );
909 :
910 : // only the language has changed -> do not touch numberformat-attribute
911 0 : sal_uInt32 nNewMod = nNewFormat % SV_COUNTRY_LANGUAGE_OFFSET;
912 0 : if ( nNewMod == ( nOldFormat % SV_COUNTRY_LANGUAGE_OFFSET ) &&
913 : nNewMod <= SV_MAX_ANZ_STANDARD_FORMATE )
914 0 : aNewAttrs.GetItemSet().ClearItem( ATTR_VALUE_FORMAT );
915 : }
916 : }
917 : }
918 :
919 0 : const SvxBoxItem* pOldOuter = static_cast<const SvxBoxItem*> (&pOldSet->Get( ATTR_BORDER ));
920 0 : const SvxBoxItem* pNewOuter = static_cast<const SvxBoxItem*> (&pDialogSet->Get( ATTR_BORDER ));
921 0 : const SvxBoxInfoItem* pOldInner = static_cast<const SvxBoxInfoItem*> (&pOldSet->Get( ATTR_BORDER_INNER ));
922 0 : const SvxBoxInfoItem* pNewInner = static_cast<const SvxBoxInfoItem*> (&pDialogSet->Get( ATTR_BORDER_INNER ));
923 0 : SfxItemSet& rNewSet = aNewAttrs.GetItemSet();
924 0 : SfxItemPool* pNewPool = rNewSet.GetPool();
925 :
926 0 : pNewPool->Put( *pNewOuter ); // don't delete yet
927 0 : pNewPool->Put( *pNewInner );
928 0 : rNewSet.ClearItem( ATTR_BORDER );
929 0 : rNewSet.ClearItem( ATTR_BORDER_INNER );
930 :
931 : /*
932 : * establish whether border attribute is to be set:
933 : * 1. new != old
934 : * 2. is one of the borders not-DontCare (since 238.f: IsxxValid())
935 : *
936 : */
937 :
938 0 : bool bFrame = (pDialogSet->GetItemState( ATTR_BORDER ) != SfxItemState::DEFAULT)
939 0 : || (pDialogSet->GetItemState( ATTR_BORDER_INNER ) != SfxItemState::DEFAULT);
940 :
941 0 : if ( pNewOuter==pOldOuter && pNewInner==pOldInner )
942 0 : bFrame = false;
943 :
944 : // this should be intercepted by the pool: ?!??!??
945 :
946 0 : if ( bFrame && pNewOuter && pNewInner )
947 0 : if ( *pNewOuter == *pOldOuter && *pNewInner == *pOldInner )
948 0 : bFrame = false;
949 :
950 0 : if ( pNewInner )
951 : {
952 : bFrame = bFrame
953 0 : && ( pNewInner->IsValid(SvxBoxInfoItemValidFlags::LEFT)
954 0 : || pNewInner->IsValid(SvxBoxInfoItemValidFlags::RIGHT)
955 0 : || pNewInner->IsValid(SvxBoxInfoItemValidFlags::TOP)
956 0 : || pNewInner->IsValid(SvxBoxInfoItemValidFlags::BOTTOM)
957 0 : || pNewInner->IsValid(SvxBoxInfoItemValidFlags::HORI)
958 0 : || pNewInner->IsValid(SvxBoxInfoItemValidFlags::VERT) );
959 : }
960 : else
961 0 : bFrame = false;
962 :
963 0 : if (!bFrame)
964 0 : ApplySelectionPattern( aNewAttrs, bRecord ); // standard only
965 : else
966 : {
967 : // if new items are default-items, overwrite the old items:
968 :
969 0 : bool bDefNewOuter = ( SFX_ITEMS_STATICDEFAULT == pNewOuter->GetKind() );
970 0 : bool bDefNewInner = ( SFX_ITEMS_STATICDEFAULT == pNewInner->GetKind() );
971 :
972 : ApplyPatternLines( aNewAttrs,
973 : bDefNewOuter ? pOldOuter : pNewOuter,
974 : bDefNewInner ? pOldInner : pNewInner,
975 0 : bRecord );
976 : }
977 :
978 0 : pNewPool->Remove( *pNewOuter ); // release
979 0 : pNewPool->Remove( *pNewInner );
980 :
981 : // adjust height
982 0 : AdjustBlockHeight();
983 :
984 : // CellContentChanged is called in ApplySelectionPattern / ApplyPatternLines
985 : }
986 :
987 0 : void ScViewFunc::ApplyAttr( const SfxPoolItem& rAttrItem )
988 : {
989 : // not editable because of matrix only? attribute OK nonetheless
990 : bool bOnlyNotBecauseOfMatrix;
991 0 : if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
992 : {
993 0 : ErrorMessage(STR_PROTECTIONERR);
994 0 : return;
995 : }
996 :
997 0 : ScPatternAttr aNewAttrs( new SfxItemSet( *GetViewData().GetDocument()->GetPool(),
998 0 : ATTR_PATTERN_START, ATTR_PATTERN_END ) );
999 :
1000 0 : aNewAttrs.GetItemSet().Put( rAttrItem );
1001 : // if justify is set (with Buttons), always indentation 0
1002 0 : if ( rAttrItem.Which() == ATTR_HOR_JUSTIFY )
1003 0 : aNewAttrs.GetItemSet().Put( SfxUInt16Item( ATTR_INDENT, 0 ) );
1004 0 : ApplySelectionPattern( aNewAttrs );
1005 :
1006 0 : AdjustBlockHeight();
1007 :
1008 : // CellContentChanged is called in ApplySelectionPattern
1009 : }
1010 :
1011 : // patterns and borders
1012 :
1013 0 : void ScViewFunc::ApplyPatternLines( const ScPatternAttr& rAttr, const SvxBoxItem* pNewOuter,
1014 : const SvxBoxInfoItem* pNewInner, bool bRecord )
1015 : {
1016 0 : ScDocument* pDoc = GetViewData().GetDocument();
1017 0 : ScMarkData aFuncMark( GetViewData().GetMarkData() ); // local copy for UnmarkFiltered
1018 0 : ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
1019 0 : if (bRecord && !pDoc->IsUndoEnabled())
1020 0 : bRecord = false;
1021 :
1022 0 : ScRange aMarkRange;
1023 0 : aFuncMark.MarkToSimple();
1024 0 : bool bMulti = aFuncMark.IsMultiMarked();
1025 0 : if (bMulti)
1026 0 : aFuncMark.GetMultiMarkArea( aMarkRange );
1027 0 : else if (aFuncMark.IsMarked())
1028 0 : aFuncMark.GetMarkArea( aMarkRange );
1029 : else
1030 : {
1031 0 : aMarkRange = ScRange( GetViewData().GetCurX(),
1032 0 : GetViewData().GetCurY(), GetViewData().GetTabNo() );
1033 0 : DoneBlockMode();
1034 0 : InitOwnBlockMode();
1035 0 : aFuncMark.SetMarkArea(aMarkRange);
1036 0 : MarkDataChanged();
1037 : }
1038 :
1039 0 : ScDocShell* pDocSh = GetViewData().GetDocShell();
1040 :
1041 0 : ScDocShellModificator aModificator( *pDocSh );
1042 :
1043 0 : if (bRecord)
1044 : {
1045 0 : ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1046 0 : SCTAB nStartTab = aMarkRange.aStart.Tab();
1047 0 : SCTAB nTabCount = pDoc->GetTableCount();
1048 0 : pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
1049 0 : ScMarkData::iterator itr = aFuncMark.begin(), itrEnd = aFuncMark.end();
1050 0 : for (; itr != itrEnd; ++itr)
1051 0 : if (*itr != nStartTab)
1052 0 : pUndoDoc->AddUndoTab( *itr, *itr );
1053 :
1054 0 : ScRange aCopyRange = aMarkRange;
1055 0 : aCopyRange.aStart.SetTab(0);
1056 0 : aCopyRange.aEnd.SetTab(nTabCount-1);
1057 0 : pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pUndoDoc, &aFuncMark );
1058 :
1059 0 : pDocSh->GetUndoManager()->AddUndoAction(
1060 : new ScUndoSelectionAttr(
1061 : pDocSh, aFuncMark,
1062 0 : aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), aMarkRange.aStart.Tab(),
1063 0 : aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), aMarkRange.aEnd.Tab(),
1064 0 : pUndoDoc, bMulti, &rAttr, pNewOuter, pNewInner ) );
1065 : }
1066 :
1067 0 : sal_uInt16 nExt = SC_PF_TESTMERGE;
1068 0 : pDocSh->UpdatePaintExt( nExt, aMarkRange ); // content before the change
1069 :
1070 0 : pDoc->ApplySelectionFrame( aFuncMark, pNewOuter, pNewInner );
1071 :
1072 0 : pDocSh->UpdatePaintExt( nExt, aMarkRange ); // content after the change
1073 :
1074 0 : aFuncMark.MarkToMulti();
1075 0 : pDoc->ApplySelectionPattern( rAttr, aFuncMark );
1076 :
1077 0 : pDocSh->PostPaint( aMarkRange, PAINT_GRID, nExt );
1078 0 : pDocSh->UpdateOle(&GetViewData());
1079 0 : aModificator.SetDocumentModified();
1080 0 : CellContentChanged();
1081 :
1082 0 : StartFormatArea();
1083 0 : }
1084 :
1085 : // pattern only
1086 :
1087 0 : void ScViewFunc::ApplySelectionPattern( const ScPatternAttr& rAttr,
1088 : bool bRecord, bool bCursorOnly )
1089 : {
1090 0 : ScViewData& rViewData = GetViewData();
1091 0 : ScDocShell* pDocSh = rViewData.GetDocShell();
1092 0 : ScDocument& rDoc = pDocSh->GetDocument();
1093 0 : ScMarkData aFuncMark( rViewData.GetMarkData() ); // local copy for UnmarkFiltered
1094 0 : ScViewUtil::UnmarkFiltered( aFuncMark, &rDoc );
1095 :
1096 0 : if (bRecord && !rDoc.IsUndoEnabled())
1097 0 : bRecord = false;
1098 :
1099 : // State from old ItemSet doesn't matter for paint flags, as any change will be
1100 : // from SfxItemState::SET in the new ItemSet (default is ignored in ApplyPattern).
1101 : // New alignment is checked (check in PostPaint isn't enough) in case a right
1102 : // alignment is changed to left.
1103 0 : const SfxItemSet& rNewSet = rAttr.GetItemSet();
1104 0 : bool bSetLines = rNewSet.GetItemState( ATTR_BORDER, true ) == SfxItemState::SET ||
1105 0 : rNewSet.GetItemState( ATTR_SHADOW, true ) == SfxItemState::SET;
1106 0 : bool bSetAlign = rNewSet.GetItemState( ATTR_HOR_JUSTIFY, true ) == SfxItemState::SET;
1107 :
1108 0 : sal_uInt16 nExtFlags = 0;
1109 0 : if ( bSetLines )
1110 0 : nExtFlags |= SC_PF_LINES;
1111 0 : if ( bSetAlign )
1112 0 : nExtFlags |= SC_PF_WHOLEROWS;
1113 :
1114 0 : ScDocShellModificator aModificator( *pDocSh );
1115 :
1116 0 : bool bMulti = aFuncMark.IsMultiMarked();
1117 0 : aFuncMark.MarkToMulti();
1118 0 : bool bOnlyTab = (!aFuncMark.IsMultiMarked() && !bCursorOnly && aFuncMark.GetSelectCount() > 1);
1119 0 : if (bOnlyTab)
1120 : {
1121 0 : SCCOL nCol = rViewData.GetCurX();
1122 0 : SCROW nRow = rViewData.GetCurY();
1123 0 : SCTAB nTab = rViewData.GetTabNo();
1124 0 : aFuncMark.SetMarkArea(ScRange(nCol,nRow,nTab));
1125 0 : aFuncMark.MarkToMulti();
1126 : }
1127 :
1128 0 : ScRangeList aChangeRanges;
1129 :
1130 0 : if (aFuncMark.IsMultiMarked() && !bCursorOnly)
1131 : {
1132 0 : ScRange aMarkRange;
1133 0 : aFuncMark.GetMultiMarkArea( aMarkRange );
1134 0 : SCTAB nTabCount = rDoc.GetTableCount();
1135 0 : ScMarkData::iterator itr = aFuncMark.begin(), itrEnd = aFuncMark.end();
1136 0 : for (; itr != itrEnd; ++itr)
1137 : {
1138 0 : ScRange aChangeRange( aMarkRange );
1139 0 : aChangeRange.aStart.SetTab( *itr );
1140 0 : aChangeRange.aEnd.SetTab( *itr );
1141 0 : aChangeRanges.Append( aChangeRange );
1142 : }
1143 :
1144 0 : SCCOL nStartCol = aMarkRange.aStart.Col();
1145 0 : SCROW nStartRow = aMarkRange.aStart.Row();
1146 0 : SCTAB nStartTab = aMarkRange.aStart.Tab();
1147 0 : SCCOL nEndCol = aMarkRange.aEnd.Col();
1148 0 : SCROW nEndRow = aMarkRange.aEnd.Row();
1149 0 : SCTAB nEndTab = aMarkRange.aEnd.Tab();
1150 :
1151 0 : ScUndoSelectionAttr* pUndoAttr = NULL;
1152 0 : ScEditDataArray* pEditDataArray = NULL;
1153 0 : if (bRecord)
1154 : {
1155 0 : ScRange aCopyRange = aMarkRange;
1156 0 : aCopyRange.aStart.SetTab(0);
1157 0 : aCopyRange.aEnd.SetTab(nTabCount-1);
1158 :
1159 0 : ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1160 0 : pUndoDoc->InitUndo( &rDoc, nStartTab, nStartTab );
1161 0 : itr = aFuncMark.begin();
1162 0 : for (; itr != itrEnd; ++itr)
1163 0 : if (*itr != nStartTab)
1164 0 : pUndoDoc->AddUndoTab( *itr, *itr );
1165 0 : rDoc.CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pUndoDoc, &aFuncMark );
1166 :
1167 0 : aFuncMark.MarkToMulti();
1168 :
1169 : pUndoAttr = new ScUndoSelectionAttr(
1170 : pDocSh, aFuncMark, nStartCol, nStartRow, nStartTab,
1171 0 : nEndCol, nEndRow, nEndTab, pUndoDoc, bMulti, &rAttr );
1172 0 : pDocSh->GetUndoManager()->AddUndoAction(pUndoAttr);
1173 0 : pEditDataArray = pUndoAttr->GetDataArray();
1174 : }
1175 :
1176 0 : rDoc.ApplySelectionPattern( rAttr, aFuncMark, pEditDataArray );
1177 :
1178 : pDocSh->PostPaint( nStartCol, nStartRow, nStartTab,
1179 : nEndCol, nEndRow, nEndTab,
1180 0 : PAINT_GRID, nExtFlags | SC_PF_TESTMERGE );
1181 0 : pDocSh->UpdateOle(&GetViewData());
1182 0 : aModificator.SetDocumentModified();
1183 0 : CellContentChanged();
1184 : }
1185 : else // single cell - simpler undo
1186 : {
1187 0 : SCCOL nCol = rViewData.GetCurX();
1188 0 : SCROW nRow = rViewData.GetCurY();
1189 0 : SCTAB nTab = rViewData.GetTabNo();
1190 :
1191 0 : EditTextObject* pOldEditData = NULL;
1192 0 : EditTextObject* pNewEditData = NULL;
1193 0 : ScAddress aPos(nCol, nRow, nTab);
1194 0 : if (rDoc.GetCellType(aPos) == CELLTYPE_EDIT)
1195 : {
1196 0 : const EditTextObject* pEditObj = rDoc.GetEditText(aPos);
1197 0 : pOldEditData = pEditObj ? pEditObj->Clone() : NULL;
1198 0 : rDoc.RemoveEditTextCharAttribs(aPos, rAttr);
1199 0 : pEditObj = rDoc.GetEditText(aPos);
1200 0 : pNewEditData = pEditObj ? pEditObj->Clone() : NULL;
1201 : }
1202 :
1203 0 : aChangeRanges.Append(aPos);
1204 0 : boost::scoped_ptr<ScPatternAttr> pOldPat(new ScPatternAttr(*rDoc.GetPattern( nCol, nRow, nTab )));
1205 :
1206 0 : rDoc.ApplyPattern( nCol, nRow, nTab, rAttr );
1207 :
1208 0 : const ScPatternAttr* pNewPat = rDoc.GetPattern( nCol, nRow, nTab );
1209 :
1210 0 : if (bRecord)
1211 : {
1212 : ScUndoCursorAttr* pUndo = new ScUndoCursorAttr(
1213 0 : pDocSh, nCol, nRow, nTab, pOldPat.get(), pNewPat, &rAttr, false );
1214 0 : pUndo->SetEditData(pOldEditData, pNewEditData);
1215 0 : pDocSh->GetUndoManager()->AddUndoAction(pUndo);
1216 : }
1217 0 : pOldPat.reset(); // is copied in undo (Pool)
1218 :
1219 0 : pDocSh->PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PAINT_GRID, nExtFlags | SC_PF_TESTMERGE );
1220 0 : pDocSh->UpdateOle(&GetViewData());
1221 0 : aModificator.SetDocumentModified();
1222 0 : CellContentChanged();
1223 : }
1224 :
1225 0 : ScModelObj* pModelObj = HelperNotifyChanges::getMustPropagateChangesModel(*pDocSh);
1226 0 : if (pModelObj)
1227 : {
1228 0 : ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aProperties;
1229 0 : sal_Int32 nCount = 0;
1230 0 : const SfxItemPropertyMap& rMap = ScCellObj::GetCellPropertyMap();
1231 0 : PropertyEntryVector_t aPropVector = rMap.getPropertyEntries();
1232 0 : for ( sal_uInt16 nWhich = ATTR_PATTERN_START; nWhich <= ATTR_PATTERN_END; ++nWhich )
1233 : {
1234 0 : const SfxPoolItem* pItem = 0;
1235 0 : if ( rNewSet.GetItemState( nWhich, true, &pItem ) == SfxItemState::SET && pItem )
1236 : {
1237 0 : PropertyEntryVector_t::const_iterator aIt = aPropVector.begin();
1238 0 : while ( aIt != aPropVector.end())
1239 : {
1240 0 : if ( aIt->nWID == nWhich )
1241 : {
1242 0 : ::com::sun::star::uno::Any aVal;
1243 0 : pItem->QueryValue( aVal, aIt->nMemberId );
1244 0 : aProperties.realloc( nCount + 1 );
1245 0 : aProperties[ nCount ].Name = aIt->sName;
1246 0 : aProperties[ nCount ].Value <<= aVal;
1247 0 : ++nCount;
1248 : }
1249 0 : ++aIt;
1250 : }
1251 : }
1252 : }
1253 0 : HelperNotifyChanges::Notify(*pModelObj, aChangeRanges, "attribute", aProperties);
1254 : }
1255 :
1256 0 : StartFormatArea();
1257 0 : }
1258 :
1259 0 : void ScViewFunc::ApplyUserItemSet( const SfxItemSet& rItemSet )
1260 : {
1261 : // ItemSet from UI, may have different pool
1262 :
1263 : bool bOnlyNotBecauseOfMatrix;
1264 0 : if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
1265 : {
1266 0 : ErrorMessage(STR_PROTECTIONERR);
1267 0 : return;
1268 : }
1269 :
1270 0 : ScPatternAttr aNewAttrs( GetViewData().GetDocument()->GetPool() );
1271 0 : SfxItemSet& rNewSet = aNewAttrs.GetItemSet();
1272 0 : rNewSet.Put( rItemSet, false );
1273 0 : ApplySelectionPattern( aNewAttrs );
1274 :
1275 0 : AdjustBlockHeight();
1276 : }
1277 :
1278 108 : const SfxStyleSheet* ScViewFunc::GetStyleSheetFromMarked()
1279 : {
1280 : // Don't use UnmarkFiltered in slot state functions, for performance reasons.
1281 : // The displayed state is always that of the whole selection including filtered rows.
1282 :
1283 108 : const ScStyleSheet* pSheet = NULL;
1284 108 : ScViewData& rViewData = GetViewData();
1285 108 : ScDocument* pDoc = rViewData.GetDocument();
1286 108 : ScMarkData& rMark = rViewData.GetMarkData();
1287 :
1288 108 : if ( rMark.IsMarked() || rMark.IsMultiMarked() )
1289 16 : pSheet = pDoc->GetSelectionStyle( rMark ); // MarkToMulti isn't necessary
1290 : else
1291 92 : pSheet = pDoc->GetStyle( rViewData.GetCurX(),
1292 : rViewData.GetCurY(),
1293 184 : rViewData.GetTabNo() );
1294 :
1295 108 : return pSheet;
1296 : }
1297 :
1298 0 : void ScViewFunc::SetStyleSheetToMarked( SfxStyleSheet* pStyleSheet, bool bRecord )
1299 : {
1300 : // not editable because of matrix only? attribute OK nonetheless
1301 : bool bOnlyNotBecauseOfMatrix;
1302 0 : if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
1303 : {
1304 0 : ErrorMessage(STR_PROTECTIONERR);
1305 0 : return;
1306 : }
1307 :
1308 0 : if ( !pStyleSheet) return;
1309 :
1310 0 : ScViewData& rViewData = GetViewData();
1311 0 : ScDocShell* pDocSh = rViewData.GetDocShell();
1312 0 : ScDocument& rDoc = pDocSh->GetDocument();
1313 0 : ScMarkData aFuncMark( rViewData.GetMarkData() ); // local copy for UnmarkFiltered
1314 0 : ScViewUtil::UnmarkFiltered( aFuncMark, &rDoc );
1315 0 : SCTAB nTabCount = rDoc.GetTableCount();
1316 0 : if (bRecord && !rDoc.IsUndoEnabled())
1317 0 : bRecord = false;
1318 :
1319 0 : ScDocShellModificator aModificator( *pDocSh );
1320 :
1321 0 : if ( aFuncMark.IsMarked() || aFuncMark.IsMultiMarked() )
1322 : {
1323 0 : ScRange aMarkRange;
1324 0 : aFuncMark.MarkToMulti();
1325 0 : aFuncMark.GetMultiMarkArea( aMarkRange );
1326 :
1327 0 : if ( bRecord )
1328 : {
1329 0 : SCTAB nTab = rViewData.GetTabNo();
1330 0 : ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1331 0 : pUndoDoc->InitUndo( &rDoc, nTab, nTab );
1332 0 : ScMarkData::iterator itr = aFuncMark.begin(), itrEnd = aFuncMark.end();
1333 0 : for (; itr != itrEnd; ++itr)
1334 0 : if (*itr != nTab)
1335 0 : pUndoDoc->AddUndoTab( *itr, *itr );
1336 :
1337 0 : ScRange aCopyRange = aMarkRange;
1338 0 : aCopyRange.aStart.SetTab(0);
1339 0 : aCopyRange.aEnd.SetTab(nTabCount-1);
1340 0 : rDoc.CopyToDocument( aCopyRange, IDF_ATTRIB, true, pUndoDoc, &aFuncMark );
1341 0 : aFuncMark.MarkToMulti();
1342 :
1343 0 : OUString aName = pStyleSheet->GetName();
1344 0 : pDocSh->GetUndoManager()->AddUndoAction(
1345 0 : new ScUndoSelectionStyle( pDocSh, aFuncMark, aMarkRange, aName, pUndoDoc ) );
1346 : }
1347 :
1348 0 : rDoc.ApplySelectionStyle( static_cast<ScStyleSheet&>(*pStyleSheet), aFuncMark );
1349 :
1350 0 : if (!AdjustBlockHeight())
1351 0 : rViewData.GetDocShell()->PostPaint( aMarkRange, PAINT_GRID );
1352 :
1353 0 : aFuncMark.MarkToSimple();
1354 : }
1355 : else
1356 : {
1357 0 : SCCOL nCol = rViewData.GetCurX();
1358 0 : SCROW nRow = rViewData.GetCurY();
1359 0 : SCTAB nTab = rViewData.GetTabNo();
1360 :
1361 0 : if ( bRecord )
1362 : {
1363 0 : ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1364 0 : pUndoDoc->InitUndo( &rDoc, nTab, nTab );
1365 0 : ScMarkData::iterator itr = aFuncMark.begin(), itrEnd = aFuncMark.end();
1366 0 : for (; itr != itrEnd; ++itr)
1367 0 : if (*itr != nTab)
1368 0 : pUndoDoc->AddUndoTab( *itr, *itr );
1369 :
1370 0 : ScRange aCopyRange( nCol, nRow, 0, nCol, nRow, nTabCount-1 );
1371 0 : rDoc.CopyToDocument( aCopyRange, IDF_ATTRIB, false, pUndoDoc );
1372 :
1373 0 : ScRange aMarkRange ( nCol, nRow, nTab );
1374 0 : ScMarkData aUndoMark = aFuncMark;
1375 0 : aUndoMark.SetMultiMarkArea( aMarkRange );
1376 :
1377 0 : OUString aName = pStyleSheet->GetName();
1378 0 : pDocSh->GetUndoManager()->AddUndoAction(
1379 0 : new ScUndoSelectionStyle( pDocSh, aUndoMark, aMarkRange, aName, pUndoDoc ) );
1380 : }
1381 :
1382 0 : ScMarkData::iterator itr = aFuncMark.begin(), itrEnd = aFuncMark.end();
1383 0 : for (; itr != itrEnd; ++itr)
1384 0 : rDoc.ApplyStyle( nCol, nRow, *itr, static_cast<ScStyleSheet&>(*pStyleSheet) );
1385 :
1386 0 : if (!AdjustBlockHeight())
1387 0 : rViewData.GetDocShell()->PostPaintCell( nCol, nRow, nTab );
1388 :
1389 : }
1390 :
1391 0 : aModificator.SetDocumentModified();
1392 :
1393 0 : StartFormatArea();
1394 : }
1395 :
1396 0 : void ScViewFunc::RemoveStyleSheetInUse( const SfxStyleSheetBase* pStyleSheet )
1397 : {
1398 0 : if ( !pStyleSheet) return;
1399 :
1400 0 : ScViewData& rViewData = GetViewData();
1401 0 : ScDocument* pDoc = rViewData.GetDocument();
1402 0 : ScDocShell* pDocSh = rViewData.GetDocShell();
1403 :
1404 0 : ScDocShellModificator aModificator( *pDocSh );
1405 :
1406 0 : ScopedVclPtrInstance< VirtualDevice > pVirtDev;
1407 0 : pVirtDev->SetMapMode(MAP_PIXEL);
1408 : pDoc->StyleSheetChanged( pStyleSheet, true, pVirtDev,
1409 : rViewData.GetPPTX(),
1410 : rViewData.GetPPTY(),
1411 0 : rViewData.GetZoomX(),
1412 0 : rViewData.GetZoomY() );
1413 :
1414 0 : pDocSh->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID|PAINT_LEFT );
1415 0 : aModificator.SetDocumentModified();
1416 :
1417 0 : ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
1418 0 : if (pHdl)
1419 0 : pHdl->ForgetLastPattern();
1420 : }
1421 :
1422 0 : void ScViewFunc::UpdateStyleSheetInUse( const SfxStyleSheetBase* pStyleSheet )
1423 : {
1424 0 : if ( !pStyleSheet) return;
1425 :
1426 0 : ScViewData& rViewData = GetViewData();
1427 0 : ScDocument* pDoc = rViewData.GetDocument();
1428 0 : ScDocShell* pDocSh = rViewData.GetDocShell();
1429 :
1430 0 : ScDocShellModificator aModificator( *pDocSh );
1431 :
1432 0 : ScopedVclPtrInstance< VirtualDevice > pVirtDev;
1433 0 : pVirtDev->SetMapMode(MAP_PIXEL);
1434 : pDoc->StyleSheetChanged( pStyleSheet, false, pVirtDev,
1435 : rViewData.GetPPTX(),
1436 : rViewData.GetPPTY(),
1437 0 : rViewData.GetZoomX(),
1438 0 : rViewData.GetZoomY() );
1439 :
1440 0 : pDocSh->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID|PAINT_LEFT );
1441 0 : aModificator.SetDocumentModified();
1442 :
1443 0 : ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
1444 0 : if (pHdl)
1445 0 : pHdl->ForgetLastPattern();
1446 : }
1447 :
1448 : // insert cells - undo OK
1449 :
1450 0 : bool ScViewFunc::InsertCells( InsCellCmd eCmd, bool bRecord, bool bPartOfPaste )
1451 : {
1452 0 : ScRange aRange;
1453 0 : if (GetViewData().GetSimpleArea(aRange) == SC_MARK_SIMPLE)
1454 : {
1455 0 : ScDocShell* pDocSh = GetViewData().GetDocShell();
1456 0 : const ScMarkData& rMark = GetViewData().GetMarkData();
1457 0 : bool bSuccess = pDocSh->GetDocFunc().InsertCells( aRange, &rMark, eCmd, bRecord, false, bPartOfPaste );
1458 0 : if (bSuccess)
1459 : {
1460 0 : pDocSh->UpdateOle(&GetViewData());
1461 0 : CellContentChanged();
1462 0 : ResetAutoSpell();
1463 :
1464 0 : if ( eCmd == INS_INSROWS_BEFORE || eCmd == INS_INSCOLS_BEFORE || eCmd == INS_INSROWS_AFTER || eCmd == INS_INSCOLS_AFTER )
1465 : {
1466 0 : OUString aOperation = ( eCmd == INS_INSROWS_BEFORE || eCmd == INS_INSROWS_AFTER ) ?
1467 : OUString("insert-rows"):
1468 0 : OUString("insert-columns");
1469 0 : HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh, aRange, aOperation);
1470 : }
1471 : }
1472 0 : return bSuccess;
1473 : }
1474 : else
1475 : {
1476 0 : ErrorMessage(STR_NOMULTISELECT);
1477 0 : return false;
1478 : }
1479 : }
1480 :
1481 : // delete cells - undo OK
1482 :
1483 0 : void ScViewFunc::DeleteCells( DelCellCmd eCmd, bool bRecord )
1484 : {
1485 0 : ScRange aRange;
1486 0 : if ( GetViewData().GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
1487 : {
1488 0 : ScDocShell* pDocSh = GetViewData().GetDocShell();
1489 0 : const ScMarkData& rMark = GetViewData().GetMarkData();
1490 :
1491 : #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
1492 : // #i94841# [Collaboration] if deleting rows is rejected, the content is sometimes wrong
1493 0 : if ( pDocSh->IsDocShared() && ( eCmd == DEL_DELROWS || eCmd == DEL_DELCOLS ) )
1494 : {
1495 0 : ScRange aDelRange( aRange.aStart );
1496 0 : SCCOLROW nCount = 0;
1497 0 : if ( eCmd == DEL_DELROWS )
1498 : {
1499 0 : nCount = sal::static_int_cast< SCCOLROW >( aRange.aEnd.Row() - aRange.aStart.Row() + 1 );
1500 : }
1501 : else
1502 : {
1503 0 : nCount = sal::static_int_cast< SCCOLROW >( aRange.aEnd.Col() - aRange.aStart.Col() + 1 );
1504 : }
1505 0 : while ( nCount > 0 )
1506 : {
1507 0 : pDocSh->GetDocFunc().DeleteCells( aDelRange, &rMark, eCmd, bRecord, false );
1508 0 : --nCount;
1509 : }
1510 : }
1511 : else
1512 : #endif
1513 : {
1514 0 : pDocSh->GetDocFunc().DeleteCells( aRange, &rMark, eCmd, bRecord, false );
1515 : }
1516 :
1517 0 : pDocSh->UpdateOle(&GetViewData());
1518 0 : CellContentChanged();
1519 0 : ResetAutoSpell();
1520 :
1521 0 : if ( eCmd == DEL_DELROWS || eCmd == DEL_DELCOLS )
1522 : {
1523 : OUString aOperation = ( eCmd == DEL_DELROWS) ?
1524 : OUString("delete-rows"):
1525 0 : OUString("delete-columns");
1526 0 : HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh, aRange, aOperation);
1527 : }
1528 :
1529 : // put cursor directly behind deleted range
1530 0 : SCCOL nCurX = GetViewData().GetCurX();
1531 0 : SCROW nCurY = GetViewData().GetCurY();
1532 0 : if ( eCmd==DEL_CELLSLEFT || eCmd==DEL_DELCOLS )
1533 0 : nCurX = aRange.aStart.Col();
1534 : else
1535 0 : nCurY = aRange.aStart.Row();
1536 0 : SetCursor( nCurX, nCurY );
1537 : }
1538 : else
1539 : {
1540 0 : if (eCmd == DEL_DELCOLS)
1541 0 : DeleteMulti( false, bRecord );
1542 0 : else if (eCmd == DEL_DELROWS)
1543 0 : DeleteMulti( true, bRecord );
1544 : else
1545 0 : ErrorMessage(STR_NOMULTISELECT);
1546 : }
1547 :
1548 0 : Unmark();
1549 0 : }
1550 :
1551 0 : void ScViewFunc::DeleteMulti( bool bRows, bool bRecord )
1552 : {
1553 0 : ScDocShell* pDocSh = GetViewData().GetDocShell();
1554 0 : ScDocShellModificator aModificator( *pDocSh );
1555 0 : SCTAB nTab = GetViewData().GetTabNo();
1556 0 : ScDocument& rDoc = pDocSh->GetDocument();
1557 0 : ScMarkData aFuncMark( GetViewData().GetMarkData() ); // local copy for UnmarkFiltered
1558 0 : ScViewUtil::UnmarkFiltered( aFuncMark, &rDoc );
1559 :
1560 0 : if (!rDoc.IsUndoEnabled())
1561 0 : bRecord = false;
1562 :
1563 0 : std::vector<sc::ColRowSpan> aSpans;
1564 0 : if (bRows)
1565 0 : aSpans = aFuncMark.GetMarkedRowSpans();
1566 : else
1567 0 : aSpans = aFuncMark.GetMarkedColSpans();
1568 :
1569 0 : if (aSpans.empty())
1570 : {
1571 0 : SCCOLROW nCurPos = bRows ? GetViewData().GetCurY() : GetViewData().GetCurX();
1572 0 : aSpans.push_back(sc::ColRowSpan(nCurPos, nCurPos));
1573 : }
1574 :
1575 : // test if allowed
1576 :
1577 0 : sal_uInt16 nErrorId = 0;
1578 0 : bool bNeedRefresh = false;
1579 0 : for (size_t i = 0, n = aSpans.size(); i < n && !nErrorId; ++i)
1580 : {
1581 0 : SCCOLROW nStart = aSpans[i].mnStart;
1582 0 : SCCOLROW nEnd = aSpans[i].mnEnd;
1583 :
1584 : SCCOL nStartCol, nEndCol;
1585 : SCROW nStartRow, nEndRow;
1586 0 : if ( bRows )
1587 : {
1588 0 : nStartCol = 0;
1589 0 : nEndCol = MAXCOL;
1590 0 : nStartRow = static_cast<SCROW>(nStart);
1591 0 : nEndRow = static_cast<SCROW>(nEnd);
1592 : }
1593 : else
1594 : {
1595 0 : nStartCol = static_cast<SCCOL>(nStart);
1596 0 : nEndCol = static_cast<SCCOL>(nEnd);
1597 0 : nStartRow = 0;
1598 0 : nEndRow = MAXROW;
1599 : }
1600 :
1601 : // cell protection (only needed for first range, as all following cells are moved)
1602 0 : if (i == 0)
1603 : {
1604 : // test to the end of the sheet
1605 0 : ScEditableTester aTester( &rDoc, nTab, nStartCol, nStartRow, MAXCOL, MAXROW );
1606 0 : if (!aTester.IsEditable())
1607 0 : nErrorId = aTester.GetMessageId();
1608 : }
1609 :
1610 : // merged cells
1611 0 : SCCOL nMergeStartX = nStartCol;
1612 0 : SCROW nMergeStartY = nStartRow;
1613 0 : SCCOL nMergeEndX = nEndCol;
1614 0 : SCROW nMergeEndY = nEndRow;
1615 0 : rDoc.ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, nTab );
1616 0 : rDoc.ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, nTab );
1617 :
1618 0 : if ( nMergeStartX != nStartCol || nMergeStartY != nStartRow )
1619 : {
1620 : // Disallow deleting parts of a merged cell.
1621 : // Deleting the start is allowed (merge is removed), so the end doesn't have to be checked.
1622 :
1623 0 : nErrorId = STR_MSSG_DELETECELLS_0;
1624 : }
1625 0 : if ( nMergeEndX != nEndCol || nMergeEndY != nEndRow )
1626 : {
1627 : // detect if the start of a merged cell is deleted, so the merge flags can be refreshed
1628 :
1629 0 : bNeedRefresh = true;
1630 : }
1631 : }
1632 :
1633 0 : if ( nErrorId )
1634 : {
1635 0 : ErrorMessage( nErrorId );
1636 0 : return;
1637 : }
1638 :
1639 : // proceed
1640 :
1641 0 : WaitObject aWait( GetFrameWin() ); // important for TrackFormulas in UpdateReference
1642 :
1643 0 : ScDocument* pUndoDoc = NULL;
1644 0 : ScRefUndoData* pUndoData = NULL;
1645 0 : if (bRecord)
1646 : {
1647 0 : pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1648 0 : pUndoDoc->InitUndo( &rDoc, nTab, nTab, !bRows, bRows ); // row height
1649 :
1650 0 : for (size_t i = 0, n = aSpans.size(); i < n; ++i)
1651 : {
1652 0 : SCCOLROW nStart = aSpans[i].mnStart;
1653 0 : SCCOLROW nEnd = aSpans[i].mnEnd;
1654 0 : if (bRows)
1655 0 : rDoc.CopyToDocument( 0,nStart,nTab, MAXCOL,nEnd,nTab, IDF_ALL,false,pUndoDoc );
1656 : else
1657 : rDoc.CopyToDocument( static_cast<SCCOL>(nStart),0,nTab,
1658 : static_cast<SCCOL>(nEnd),MAXROW,nTab,
1659 0 : IDF_ALL,false,pUndoDoc );
1660 : }
1661 :
1662 : // all Formulas because of references
1663 0 : SCTAB nTabCount = rDoc.GetTableCount();
1664 0 : pUndoDoc->AddUndoTab( 0, nTabCount-1, false, false );
1665 0 : rDoc.CopyToDocument( 0,0,0, MAXCOL,MAXROW,MAXTAB, IDF_FORMULA,false,pUndoDoc );
1666 :
1667 0 : pUndoData = new ScRefUndoData( &rDoc );
1668 :
1669 0 : rDoc.BeginDrawUndo();
1670 : }
1671 :
1672 0 : std::vector<sc::ColRowSpan>::const_reverse_iterator ri = aSpans.rbegin(), riEnd = aSpans.rend();
1673 0 : for (; ri != riEnd; ++ri)
1674 : {
1675 0 : SCCOLROW nEnd = ri->mnEnd;
1676 0 : SCCOLROW nStart = ri->mnStart;
1677 :
1678 0 : if (bRows)
1679 0 : rDoc.DeleteRow( 0,nTab, MAXCOL,nTab, nStart, static_cast<SCSIZE>(nEnd-nStart+1) );
1680 : else
1681 0 : rDoc.DeleteCol( 0,nTab, MAXROW,nTab, static_cast<SCCOL>(nStart), static_cast<SCSIZE>(nEnd-nStart+1) );
1682 : }
1683 :
1684 0 : if (bNeedRefresh)
1685 : {
1686 0 : SCCOLROW nFirstStart = aSpans[0].mnStart;
1687 0 : SCCOL nStartCol = bRows ? 0 : static_cast<SCCOL>(nFirstStart);
1688 0 : SCROW nStartRow = bRows ? static_cast<SCROW>(nFirstStart) : 0;
1689 0 : SCCOL nEndCol = MAXCOL;
1690 0 : SCROW nEndRow = MAXROW;
1691 :
1692 0 : rDoc.RemoveFlagsTab( nStartCol, nStartRow, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
1693 0 : rDoc.ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow, nTab, true );
1694 : }
1695 :
1696 0 : if (bRecord)
1697 : {
1698 0 : pDocSh->GetUndoManager()->AddUndoAction(
1699 : new ScUndoDeleteMulti(
1700 0 : pDocSh, bRows, bNeedRefresh, nTab, aSpans, pUndoDoc, pUndoData));
1701 : }
1702 :
1703 0 : if (!AdjustRowHeight(0, MAXROW))
1704 : {
1705 0 : if (bRows)
1706 : {
1707 : pDocSh->PostPaint(
1708 0 : 0, aSpans[0].mnStart, nTab,
1709 0 : MAXCOL, MAXROW, nTab, (PAINT_GRID | PAINT_LEFT));
1710 : }
1711 : else
1712 : {
1713 : pDocSh->PostPaint(
1714 0 : static_cast<SCCOL>(aSpans[0].mnStart), 0, nTab,
1715 0 : MAXCOL, MAXROW, nTab, (PAINT_GRID | PAINT_TOP));
1716 : }
1717 : }
1718 :
1719 0 : ResetAutoSpell();
1720 0 : aModificator.SetDocumentModified();
1721 :
1722 0 : CellContentChanged();
1723 :
1724 : // put cursor directly behind the first deleted range
1725 0 : SCCOL nCurX = GetViewData().GetCurX();
1726 0 : SCROW nCurY = GetViewData().GetCurY();
1727 0 : if ( bRows )
1728 0 : nCurY = aSpans[0].mnStart;
1729 : else
1730 0 : nCurX = static_cast<SCCOL>(aSpans[0].mnStart);
1731 0 : SetCursor( nCurX, nCurY );
1732 :
1733 0 : SfxGetpApp()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
1734 : }
1735 :
1736 : // delete contents
1737 :
1738 0 : void ScViewFunc::DeleteContents( InsertDeleteFlags nFlags, bool bRecord )
1739 : {
1740 0 : ScViewData& rViewData = GetViewData();
1741 0 : rViewData.SetPasteMode( SC_PASTE_NONE );
1742 0 : rViewData.GetViewShell()->UpdateCopySourceOverlay();
1743 :
1744 : // not editable because of matrix only? attribute OK nonetheless
1745 : bool bOnlyNotBecauseOfMatrix;
1746 0 : bool bEditable = SelectionEditable( &bOnlyNotBecauseOfMatrix );
1747 0 : if ( !bEditable )
1748 : {
1749 0 : if ( !(bOnlyNotBecauseOfMatrix &&
1750 0 : ((nFlags & (IDF_ATTRIB | IDF_EDITATTR)) == nFlags)) )
1751 : {
1752 0 : ErrorMessage(bOnlyNotBecauseOfMatrix ? STR_MATRIXFRAGMENTERR : STR_PROTECTIONERR);
1753 0 : return;
1754 : }
1755 : }
1756 :
1757 0 : ScRange aMarkRange;
1758 0 : bool bSimple = false;
1759 :
1760 0 : ScDocument* pDoc = GetViewData().GetDocument();
1761 0 : ScDocShell* pDocSh = GetViewData().GetDocShell();
1762 0 : ScMarkData aFuncMark( GetViewData().GetMarkData() ); // local copy for UnmarkFiltered
1763 0 : ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
1764 :
1765 0 : if (bRecord && !pDoc->IsUndoEnabled())
1766 0 : bRecord = false;
1767 :
1768 0 : if ( !aFuncMark.IsMarked() && !aFuncMark.IsMultiMarked() )
1769 : {
1770 0 : aMarkRange.aStart.SetCol(GetViewData().GetCurX());
1771 0 : aMarkRange.aStart.SetRow(GetViewData().GetCurY());
1772 0 : aMarkRange.aStart.SetTab(GetViewData().GetTabNo());
1773 0 : aMarkRange.aEnd = aMarkRange.aStart;
1774 0 : if ( pDoc->HasAttrib( aMarkRange, HASATTR_MERGED ) )
1775 : {
1776 0 : aFuncMark.SetMarkArea( aMarkRange );
1777 : }
1778 : else
1779 0 : bSimple = true;
1780 : }
1781 :
1782 0 : HideAllCursors(); // for if summary is cancelled
1783 :
1784 0 : ScDocFunc& rDocFunc = pDocSh->GetDocFunc();
1785 0 : if (bSimple)
1786 0 : rDocFunc.DeleteCell(aMarkRange.aStart, aFuncMark, nFlags, bRecord, false);
1787 : else
1788 0 : rDocFunc.DeleteContents(aFuncMark, nFlags, bRecord, false);
1789 :
1790 0 : pDocSh->UpdateOle(&GetViewData());
1791 :
1792 0 : if (ScModelObj *pModelObj = HelperNotifyChanges::getMustPropagateChangesModel(*pDocSh))
1793 : {
1794 0 : ScRangeList aChangeRanges;
1795 0 : if ( bSimple )
1796 : {
1797 0 : aChangeRanges.Append( aMarkRange );
1798 : }
1799 : else
1800 : {
1801 0 : aFuncMark.FillRangeListWithMarks( &aChangeRanges, false );
1802 : }
1803 0 : HelperNotifyChanges::Notify(*pModelObj, aChangeRanges);
1804 : }
1805 :
1806 0 : CellContentChanged();
1807 0 : ShowAllCursors();
1808 :
1809 0 : if ( nFlags & IDF_ATTRIB )
1810 : {
1811 0 : if ( nFlags & IDF_CONTENTS )
1812 0 : ForgetFormatArea();
1813 : else
1814 0 : StartFormatArea(); // delete attribute is also attribute-change
1815 0 : }
1816 : }
1817 :
1818 : // column width/row height (via header) - undo OK
1819 :
1820 0 : void ScViewFunc::SetWidthOrHeight(
1821 : bool bWidth, const std::vector<sc::ColRowSpan>& rRanges, ScSizeMode eMode,
1822 : sal_uInt16 nSizeTwips, bool bRecord, bool bPaint, ScMarkData* pMarkData )
1823 : {
1824 0 : if (rRanges.empty())
1825 0 : return;
1826 :
1827 : // use view's mark if none specified
1828 0 : if ( !pMarkData )
1829 0 : pMarkData = &GetViewData().GetMarkData();
1830 :
1831 0 : ScDocShell* pDocSh = GetViewData().GetDocShell();
1832 0 : ScDocument& rDoc = pDocSh->GetDocument();
1833 0 : SCTAB nFirstTab = pMarkData->GetFirstSelected();
1834 0 : SCTAB nCurTab = GetViewData().GetTabNo();
1835 : SCTAB nTab;
1836 0 : if (bRecord && !rDoc.IsUndoEnabled())
1837 0 : bRecord = false;
1838 :
1839 0 : ScDocShellModificator aModificator( *pDocSh );
1840 :
1841 0 : bool bAllowed = true;
1842 0 : ScMarkData::iterator itr = pMarkData->begin(), itrEnd = pMarkData->end();
1843 0 : for (; itr != itrEnd && bAllowed; ++itr)
1844 : {
1845 0 : for (size_t i = 0, n = rRanges.size(); i < n && bAllowed; ++i)
1846 : {
1847 : bool bOnlyMatrix;
1848 0 : if (bWidth)
1849 : {
1850 : bAllowed = rDoc.IsBlockEditable(
1851 0 : *itr, rRanges[i].mnStart, 0, rRanges[i].mnEnd, MAXROW,
1852 0 : &bOnlyMatrix ) || bOnlyMatrix;
1853 : }
1854 : else
1855 : {
1856 : bAllowed = rDoc.IsBlockEditable(
1857 0 : *itr, 0, rRanges[i].mnStart, MAXCOL,rRanges[i].mnEnd, &bOnlyMatrix) || bOnlyMatrix;
1858 : }
1859 : }
1860 : }
1861 :
1862 : // Allow users to resize cols/rows in readonly docs despite the r/o state.
1863 : // It is frustrating to be unable to see content in mis-sized cells.
1864 0 : if( !bAllowed && !pDocSh->IsReadOnly() )
1865 : {
1866 0 : ErrorMessage(STR_PROTECTIONERR);
1867 0 : return;
1868 : }
1869 :
1870 0 : SCCOLROW nStart = rRanges[0].mnStart;
1871 0 : SCCOLROW nEnd = rRanges[0].mnEnd;
1872 :
1873 0 : bool bFormula = false;
1874 0 : if ( eMode == SC_SIZE_OPTIMAL )
1875 : {
1876 0 : const ScViewOptions& rOpts = GetViewData().GetOptions();
1877 0 : bFormula = rOpts.GetOption( VOPT_FORMULAS );
1878 : }
1879 :
1880 0 : ScDocument* pUndoDoc = NULL;
1881 0 : ScOutlineTable* pUndoTab = NULL;
1882 0 : std::vector<sc::ColRowSpan> aUndoRanges;
1883 :
1884 0 : if ( bRecord )
1885 : {
1886 0 : rDoc.BeginDrawUndo(); // Drawing Updates
1887 :
1888 0 : pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1889 0 : itr = pMarkData->begin();
1890 0 : for (; itr != itrEnd; ++itr)
1891 : {
1892 0 : if (bWidth)
1893 : {
1894 0 : if ( *itr == nFirstTab )
1895 0 : pUndoDoc->InitUndo( &rDoc, *itr, *itr, true, false );
1896 : else
1897 0 : pUndoDoc->AddUndoTab( *itr, *itr, true, false );
1898 0 : rDoc.CopyToDocument( static_cast<SCCOL>(nStart), 0, *itr,
1899 0 : static_cast<SCCOL>(nEnd), MAXROW, *itr, IDF_NONE,
1900 0 : false, pUndoDoc );
1901 : }
1902 : else
1903 : {
1904 0 : if ( *itr == nFirstTab )
1905 0 : pUndoDoc->InitUndo( &rDoc, *itr, *itr, false, true );
1906 : else
1907 0 : pUndoDoc->AddUndoTab( *itr, *itr, false, true );
1908 0 : rDoc.CopyToDocument( 0, nStart, *itr, MAXCOL, nEnd, *itr, IDF_NONE, false, pUndoDoc );
1909 : }
1910 : }
1911 :
1912 0 : aUndoRanges = rRanges;
1913 :
1914 : //! outlines from all tab?
1915 0 : ScOutlineTable* pTable = rDoc.GetOutlineTable( nCurTab );
1916 0 : if (pTable)
1917 0 : pUndoTab = new ScOutlineTable( *pTable );
1918 : }
1919 :
1920 0 : if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
1921 0 : pMarkData->MarkToMulti();
1922 :
1923 0 : bool bShow = nSizeTwips > 0 || eMode != SC_SIZE_DIRECT;
1924 0 : bool bOutline = false;
1925 :
1926 0 : itr = pMarkData->begin();
1927 0 : for (; itr != itrEnd; ++itr)
1928 : {
1929 0 : nTab = *itr;
1930 :
1931 0 : for (size_t i = 0, n = rRanges.size(); i < n; ++i)
1932 : {
1933 0 : SCCOLROW nStartNo = rRanges[i].mnStart;
1934 0 : SCCOLROW nEndNo = rRanges[i].mnEnd;
1935 :
1936 0 : if ( !bWidth ) // height always blockwise
1937 : {
1938 0 : if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
1939 : {
1940 0 : bool bAll = ( eMode==SC_SIZE_OPTIMAL );
1941 0 : if (!bAll)
1942 : {
1943 : // delete CR_MANUALSIZE for all in range,
1944 : // then SetOptimalHeight with bShrink = FALSE
1945 0 : for (SCROW nRow = nStartNo; nRow <= nEndNo; ++nRow)
1946 : {
1947 0 : SCROW nLastRow = nRow;
1948 0 : if (rDoc.RowHidden(nRow, nTab, NULL, &nLastRow))
1949 : {
1950 0 : nRow = nLastRow;
1951 0 : continue;
1952 : }
1953 :
1954 0 : sal_uInt8 nOld = rDoc.GetRowFlags(nRow, nTab);
1955 0 : if (nOld & CR_MANUALSIZE)
1956 0 : rDoc.SetRowFlags(nRow, nTab, nOld & ~CR_MANUALSIZE);
1957 : }
1958 : }
1959 :
1960 0 : double nPPTX = GetViewData().GetPPTX();
1961 0 : double nPPTY = GetViewData().GetPPTY();
1962 0 : Fraction aZoomX = GetViewData().GetZoomX();
1963 0 : Fraction aZoomY = GetViewData().GetZoomY();
1964 :
1965 0 : ScSizeDeviceProvider aProv(pDocSh);
1966 0 : if (aProv.IsPrinter())
1967 : {
1968 0 : nPPTX = aProv.GetPPTX();
1969 0 : nPPTY = aProv.GetPPTY();
1970 0 : aZoomX = aZoomY = Fraction( 1, 1 );
1971 : }
1972 :
1973 0 : sc::RowHeightContext aCxt(nPPTX, nPPTY, aZoomX, aZoomY, aProv.GetDevice());
1974 0 : aCxt.setForceAutoSize(bAll);
1975 0 : aCxt.setExtraHeight(nSizeTwips);
1976 0 : rDoc.SetOptimalHeight(aCxt, nStartNo, nEndNo, nTab);
1977 0 : if (bAll)
1978 0 : rDoc.ShowRows( nStartNo, nEndNo, nTab, true );
1979 :
1980 : // Manual-Flag already (re)set in SetOptimalHeight in case of bAll=sal_True
1981 : // (set for Extra-Height, else reset).
1982 : }
1983 0 : else if ( eMode==SC_SIZE_DIRECT )
1984 : {
1985 0 : if (nSizeTwips)
1986 : {
1987 0 : rDoc.SetRowHeightRange( nStartNo, nEndNo, nTab, nSizeTwips );
1988 0 : rDoc.SetManualHeight( nStartNo, nEndNo, nTab, true ); // height was set manually
1989 : }
1990 0 : rDoc.ShowRows( nStartNo, nEndNo, nTab, nSizeTwips != 0 );
1991 : }
1992 0 : else if ( eMode==SC_SIZE_SHOW )
1993 : {
1994 0 : rDoc.ShowRows( nStartNo, nEndNo, nTab, true );
1995 : }
1996 : }
1997 : else // column width
1998 : {
1999 0 : for (SCCOL nCol=static_cast<SCCOL>(nStartNo); nCol<=static_cast<SCCOL>(nEndNo); nCol++)
2000 : {
2001 0 : if ( eMode != SC_SIZE_VISOPT || !rDoc.ColHidden(nCol, nTab) )
2002 : {
2003 0 : sal_uInt16 nThisSize = nSizeTwips;
2004 :
2005 0 : if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
2006 0 : nThisSize = nSizeTwips + GetOptimalColWidth( nCol, nTab, bFormula );
2007 0 : if ( nThisSize )
2008 0 : rDoc.SetColWidth( nCol, nTab, nThisSize );
2009 :
2010 0 : rDoc.ShowCol( nCol, nTab, bShow );
2011 : }
2012 : }
2013 : }
2014 :
2015 : // adjust outline
2016 :
2017 0 : if (bWidth)
2018 : {
2019 0 : if ( rDoc.UpdateOutlineCol( static_cast<SCCOL>(nStartNo),
2020 0 : static_cast<SCCOL>(nEndNo), nTab, bShow ) )
2021 0 : bOutline = true;
2022 : }
2023 : else
2024 : {
2025 0 : if ( rDoc.UpdateOutlineRow( nStartNo, nEndNo, nTab, bShow ) )
2026 0 : bOutline = true;
2027 : }
2028 : }
2029 0 : rDoc.SetDrawPageSize(nTab);
2030 : }
2031 :
2032 0 : if (!bOutline)
2033 0 : DELETEZ(pUndoTab);
2034 :
2035 0 : if (bRecord)
2036 : {
2037 0 : pDocSh->GetUndoManager()->AddUndoAction(
2038 : new ScUndoWidthOrHeight(
2039 : pDocSh, *pMarkData, nStart, nCurTab, nEnd, nCurTab,
2040 0 : pUndoDoc, aUndoRanges, pUndoTab, eMode, nSizeTwips, bWidth));
2041 : }
2042 :
2043 : // fdo#36247 Ensure that the drawing layer's map mode scaling factors match
2044 : // the new heights and widths.
2045 0 : GetViewData().GetView()->RefreshZoom();
2046 :
2047 0 : itr = pMarkData->begin();
2048 0 : for (; itr != itrEnd; ++itr)
2049 0 : rDoc.UpdatePageBreaks( *itr );
2050 :
2051 0 : GetViewData().GetView()->UpdateScrollBars();
2052 :
2053 0 : if (bPaint)
2054 : {
2055 0 : itr = pMarkData->begin();
2056 0 : for (; itr != itrEnd; ++itr)
2057 : {
2058 0 : nTab = *itr;
2059 0 : if (bWidth)
2060 : {
2061 0 : if (rDoc.HasAttrib( static_cast<SCCOL>(nStart),0,nTab,
2062 : static_cast<SCCOL>(nEnd),MAXROW,nTab,
2063 0 : HASATTR_MERGED | HASATTR_OVERLAPPED ))
2064 0 : nStart = 0;
2065 0 : if (nStart > 0) // go upwards because of Lines and cursor
2066 0 : --nStart;
2067 : pDocSh->PostPaint( static_cast<SCCOL>(nStart), 0, nTab,
2068 0 : MAXCOL, MAXROW, nTab, PAINT_GRID | PAINT_TOP );
2069 : }
2070 : else
2071 : {
2072 0 : if (rDoc.HasAttrib( 0,nStart,nTab, MAXCOL,nEnd,nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ))
2073 0 : nStart = 0;
2074 0 : if (nStart != 0)
2075 0 : --nStart;
2076 0 : pDocSh->PostPaint( 0, nStart, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID | PAINT_LEFT );
2077 : }
2078 : }
2079 :
2080 0 : pDocSh->UpdateOle(&GetViewData());
2081 0 : if( !pDocSh->IsReadOnly() )
2082 0 : aModificator.SetDocumentModified();
2083 : }
2084 :
2085 0 : if ( bWidth )
2086 : {
2087 0 : if (ScModelObj* pModelObj = HelperNotifyChanges::getMustPropagateChangesModel(*pDocSh))
2088 : {
2089 0 : ScRangeList aChangeRanges;
2090 0 : itr = pMarkData->begin();
2091 0 : for (; itr != itrEnd; ++itr)
2092 : {
2093 0 : nTab = *itr;
2094 0 : for (size_t i = 0, n = rRanges.size(); i < n; ++i)
2095 : {
2096 0 : SCCOL nStartCol = rRanges[i].mnStart;
2097 0 : SCCOL nEndCol = rRanges[i].mnEnd;
2098 0 : for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol )
2099 : {
2100 0 : aChangeRanges.Append( ScRange( nCol, 0, nTab ) );
2101 : }
2102 : }
2103 : }
2104 0 : HelperNotifyChanges::Notify(*pModelObj, aChangeRanges, "column-resize");
2105 : }
2106 0 : }
2107 : }
2108 :
2109 : // column width/row height (via marked range)
2110 :
2111 0 : void ScViewFunc::SetMarkedWidthOrHeight( bool bWidth, ScSizeMode eMode, sal_uInt16 nSizeTwips,
2112 : bool bRecord, bool bPaint )
2113 : {
2114 0 : ScMarkData& rMark = GetViewData().GetMarkData();
2115 :
2116 0 : rMark.MarkToMulti();
2117 0 : if (!rMark.IsMultiMarked())
2118 : {
2119 0 : SCCOL nCol = GetViewData().GetCurX();
2120 0 : SCROW nRow = GetViewData().GetCurY();
2121 0 : SCTAB nTab = GetViewData().GetTabNo();
2122 0 : DoneBlockMode();
2123 0 : InitOwnBlockMode();
2124 0 : rMark.SetMultiMarkArea( ScRange( nCol,nRow,nTab ), true );
2125 0 : MarkDataChanged();
2126 : }
2127 :
2128 : std::vector<sc::ColRowSpan> aRanges =
2129 0 : bWidth ? rMark.GetMarkedColSpans() : rMark.GetMarkedRowSpans();
2130 :
2131 0 : SetWidthOrHeight(bWidth, aRanges, eMode, nSizeTwips, bRecord, bPaint);
2132 :
2133 0 : rMark.MarkToSimple();
2134 0 : }
2135 :
2136 0 : void ScViewFunc::ModifyCellSize( ScDirection eDir, bool bOptimal )
2137 : {
2138 : //! step size adjustable
2139 : // step size is also minimum
2140 0 : sal_uInt16 nStepX = STD_COL_WIDTH / 5;
2141 0 : sal_uInt16 nStepY = ScGlobal::nStdRowHeight;
2142 :
2143 0 : ScModule* pScMod = SC_MOD();
2144 0 : bool bAnyEdit = pScMod->IsInputMode();
2145 0 : SCCOL nCol = GetViewData().GetCurX();
2146 0 : SCROW nRow = GetViewData().GetCurY();
2147 0 : SCTAB nTab = GetViewData().GetTabNo();
2148 0 : ScDocShell* pDocSh = GetViewData().GetDocShell();
2149 0 : ScDocument& rDoc = pDocSh->GetDocument();
2150 :
2151 : bool bAllowed, bOnlyMatrix;
2152 0 : if ( eDir == DIR_LEFT || eDir == DIR_RIGHT )
2153 0 : bAllowed = rDoc.IsBlockEditable( nTab, nCol,0, nCol,MAXROW, &bOnlyMatrix );
2154 : else
2155 0 : bAllowed = rDoc.IsBlockEditable( nTab, 0,nRow, MAXCOL,nRow, &bOnlyMatrix );
2156 0 : if ( !bAllowed && !bOnlyMatrix )
2157 : {
2158 0 : ErrorMessage(STR_PROTECTIONERR);
2159 0 : return;
2160 : }
2161 :
2162 0 : HideAllCursors();
2163 :
2164 0 : sal_uInt16 nWidth = rDoc.GetColWidth( nCol, nTab );
2165 0 : sal_uInt16 nHeight = rDoc.GetRowHeight( nRow, nTab );
2166 0 : std::vector<sc::ColRowSpan> aRange(1, sc::ColRowSpan(0,0));
2167 0 : if ( eDir == DIR_LEFT || eDir == DIR_RIGHT )
2168 : {
2169 0 : if (bOptimal) // width of this single cell
2170 : {
2171 0 : if ( bAnyEdit )
2172 : {
2173 : // when editing the actual entered width
2174 0 : ScInputHandler* pHdl = pScMod->GetInputHdl( GetViewData().GetViewShell() );
2175 0 : if (pHdl)
2176 : {
2177 0 : long nEdit = pHdl->GetTextSize().Width(); // in 0.01 mm
2178 :
2179 0 : const ScPatternAttr* pPattern = rDoc.GetPattern( nCol, nRow, nTab );
2180 : const SvxMarginItem& rMItem =
2181 0 : static_cast<const SvxMarginItem&>(pPattern->GetItem(ATTR_MARGIN));
2182 0 : sal_uInt16 nMargin = rMItem.GetLeftMargin() + rMItem.GetRightMargin();
2183 0 : if ( static_cast<const SvxHorJustifyItem&>( pPattern->
2184 0 : GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_LEFT )
2185 : nMargin = sal::static_int_cast<sal_uInt16>(
2186 0 : nMargin + static_cast<const SfxUInt16Item&>(pPattern->GetItem(ATTR_INDENT)).GetValue() );
2187 :
2188 0 : nWidth = (sal_uInt16)(nEdit * pDocSh->GetOutputFactor() / HMM_PER_TWIPS)
2189 0 : + nMargin + STD_EXTRA_WIDTH;
2190 : }
2191 : }
2192 : else
2193 : {
2194 0 : double nPPTX = GetViewData().GetPPTX();
2195 0 : double nPPTY = GetViewData().GetPPTY();
2196 0 : Fraction aZoomX = GetViewData().GetZoomX();
2197 0 : Fraction aZoomY = GetViewData().GetZoomY();
2198 :
2199 0 : ScSizeDeviceProvider aProv(pDocSh);
2200 0 : if (aProv.IsPrinter())
2201 : {
2202 0 : nPPTX = aProv.GetPPTX();
2203 0 : nPPTY = aProv.GetPPTY();
2204 0 : aZoomX = aZoomY = Fraction( 1, 1 );
2205 : }
2206 :
2207 : long nPixel = rDoc.GetNeededSize( nCol, nRow, nTab, aProv.GetDevice(),
2208 0 : nPPTX, nPPTY, aZoomX, aZoomY, true );
2209 0 : sal_uInt16 nTwips = (sal_uInt16)( nPixel / nPPTX );
2210 0 : if (nTwips != 0)
2211 0 : nWidth = nTwips + STD_EXTRA_WIDTH;
2212 : else
2213 0 : nWidth = STD_COL_WIDTH;
2214 : }
2215 : }
2216 : else // increment / decrement
2217 : {
2218 0 : if ( eDir == DIR_RIGHT )
2219 0 : nWidth = sal::static_int_cast<sal_uInt16>( nWidth + nStepX );
2220 0 : else if ( nWidth > nStepX )
2221 0 : nWidth = sal::static_int_cast<sal_uInt16>( nWidth - nStepX );
2222 0 : if ( nWidth < nStepX ) nWidth = nStepX;
2223 0 : if ( nWidth > MAX_COL_WIDTH ) nWidth = MAX_COL_WIDTH;
2224 : }
2225 0 : aRange[0].mnStart = nCol;
2226 0 : aRange[0].mnEnd = nCol;
2227 0 : SetWidthOrHeight(true, aRange, SC_SIZE_DIRECT, nWidth);
2228 :
2229 : // adjust height of this row if width demands/allows this
2230 :
2231 0 : if (!bAnyEdit)
2232 : {
2233 0 : const ScPatternAttr* pPattern = rDoc.GetPattern( nCol, nRow, nTab );
2234 : bool bNeedHeight =
2235 0 : static_cast<const SfxBoolItem&>(pPattern->GetItem( ATTR_LINEBREAK )).GetValue() ||
2236 : static_cast<const SvxHorJustifyItem&>(pPattern->
2237 0 : GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_BLOCK;
2238 0 : if (bNeedHeight)
2239 0 : AdjustRowHeight( nRow, nRow );
2240 0 : }
2241 : }
2242 : else
2243 : {
2244 : ScSizeMode eMode;
2245 0 : if (bOptimal)
2246 : {
2247 0 : eMode = SC_SIZE_OPTIMAL;
2248 0 : nHeight = 0;
2249 : }
2250 : else
2251 : {
2252 0 : eMode = SC_SIZE_DIRECT;
2253 0 : if ( eDir == DIR_BOTTOM )
2254 0 : nHeight = sal::static_int_cast<sal_uInt16>( nHeight + nStepY );
2255 0 : else if ( nHeight > nStepY )
2256 0 : nHeight = sal::static_int_cast<sal_uInt16>( nHeight - nStepY );
2257 0 : if ( nHeight < nStepY ) nHeight = nStepY;
2258 0 : if ( nHeight > MAX_ROW_HEIGHT ) nHeight = MAX_ROW_HEIGHT;
2259 : }
2260 0 : aRange[0].mnStart = nRow;
2261 0 : aRange[0].mnEnd = nRow;
2262 0 : SetWidthOrHeight(false, aRange, eMode, nHeight);
2263 : }
2264 :
2265 0 : if ( bAnyEdit )
2266 : {
2267 0 : UpdateEditView();
2268 0 : if ( rDoc.HasAttrib( nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_NEEDHEIGHT ) )
2269 : {
2270 0 : ScInputHandler* pHdl = pScMod->GetInputHdl( GetViewData().GetViewShell() );
2271 0 : if (pHdl)
2272 0 : pHdl->SetModified(); // so that the height is adjusted with Enter
2273 : }
2274 : }
2275 :
2276 0 : ShowAllCursors();
2277 : }
2278 :
2279 0 : void ScViewFunc::ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect )
2280 : {
2281 0 : if (nTab == TABLEID_DOC)
2282 0 : return;
2283 :
2284 0 : ScMarkData& rMark = GetViewData().GetMarkData();
2285 0 : ScDocShell* pDocSh = GetViewData().GetDocShell();
2286 0 : ScDocument& rDoc = pDocSh->GetDocument();
2287 0 : ScDocFunc &rFunc = pDocSh->GetDocFunc();
2288 0 : bool bUndo(rDoc.IsUndoEnabled());
2289 :
2290 : // modifying several tabs is handled here
2291 :
2292 0 : if (bUndo)
2293 : {
2294 0 : OUString aUndo = ScGlobal::GetRscString( STR_UNDO_PROTECT_TAB );
2295 0 : pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
2296 : }
2297 :
2298 0 : ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
2299 0 : for (; itr != itrEnd; ++itr)
2300 0 : rFunc.ProtectSheet(*itr, rProtect);
2301 :
2302 0 : if (bUndo)
2303 0 : pDocSh->GetUndoManager()->LeaveListAction();
2304 :
2305 0 : UpdateLayerLocks(); //! broadcast to all views
2306 : }
2307 :
2308 0 : void ScViewFunc::Protect( SCTAB nTab, const OUString& rPassword )
2309 : {
2310 0 : ScMarkData& rMark = GetViewData().GetMarkData();
2311 0 : ScDocShell* pDocSh = GetViewData().GetDocShell();
2312 0 : ScDocument& rDoc = pDocSh->GetDocument();
2313 0 : ScDocFunc &rFunc = pDocSh->GetDocFunc();
2314 0 : bool bUndo(rDoc.IsUndoEnabled());
2315 :
2316 0 : if ( nTab == TABLEID_DOC || rMark.GetSelectCount() <= 1 )
2317 0 : rFunc.Protect( nTab, rPassword, false );
2318 : else
2319 : {
2320 : // modifying several tabs is handled here
2321 :
2322 0 : if (bUndo)
2323 : {
2324 0 : OUString aUndo = ScGlobal::GetRscString( STR_UNDO_PROTECT_TAB );
2325 0 : pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
2326 : }
2327 :
2328 0 : ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
2329 0 : for (; itr != itrEnd; ++itr)
2330 0 : rFunc.Protect( *itr, rPassword, false );
2331 :
2332 0 : if (bUndo)
2333 0 : pDocSh->GetUndoManager()->LeaveListAction();
2334 : }
2335 :
2336 0 : UpdateLayerLocks(); //! broadcast to all views
2337 0 : }
2338 :
2339 0 : bool ScViewFunc::Unprotect( SCTAB nTab, const OUString& rPassword )
2340 : {
2341 0 : ScMarkData& rMark = GetViewData().GetMarkData();
2342 0 : ScDocShell* pDocSh = GetViewData().GetDocShell();
2343 0 : ScDocument& rDoc = pDocSh->GetDocument();
2344 0 : ScDocFunc &rFunc = pDocSh->GetDocFunc();
2345 0 : bool bChanged = false;
2346 0 : bool bUndo (rDoc.IsUndoEnabled());
2347 :
2348 0 : if ( nTab == TABLEID_DOC || rMark.GetSelectCount() <= 1 )
2349 0 : bChanged = rFunc.Unprotect( nTab, rPassword, false );
2350 : else
2351 : {
2352 : // modifying several tabs is handled here
2353 :
2354 0 : if (bUndo)
2355 : {
2356 0 : OUString aUndo = ScGlobal::GetRscString( STR_UNDO_UNPROTECT_TAB );
2357 0 : pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
2358 : }
2359 :
2360 0 : ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
2361 0 : for (; itr != itrEnd; ++itr)
2362 0 : if ( rFunc.Unprotect( *itr, rPassword, false ) )
2363 0 : bChanged = true;
2364 :
2365 0 : if (bUndo)
2366 0 : pDocSh->GetUndoManager()->LeaveListAction();
2367 : }
2368 :
2369 0 : if (bChanged)
2370 0 : UpdateLayerLocks(); //! broadcast to all views
2371 :
2372 0 : return bChanged;
2373 : }
2374 :
2375 0 : void ScViewFunc::SetNoteText( const ScAddress& rPos, const OUString& rNoteText )
2376 : {
2377 0 : GetViewData().GetDocShell()->GetDocFunc().SetNoteText( rPos, rNoteText, false );
2378 0 : }
2379 :
2380 0 : void ScViewFunc::ReplaceNote( const ScAddress& rPos, const OUString& rNoteText, const OUString* pAuthor, const OUString* pDate )
2381 : {
2382 0 : GetViewData().GetDocShell()->GetDocFunc().ReplaceNote( rPos, rNoteText, pAuthor, pDate, false );
2383 0 : }
2384 :
2385 0 : void ScViewFunc::SetNumberFormat( short nFormatType, sal_uLong nAdd )
2386 : {
2387 : // not editable because of matrix only? attribute OK nonetheless
2388 : bool bOnlyNotBecauseOfMatrix;
2389 0 : if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
2390 : {
2391 0 : ErrorMessage(STR_PROTECTIONERR);
2392 0 : return;
2393 : }
2394 :
2395 0 : sal_uInt32 nNumberFormat = 0;
2396 0 : ScViewData& rViewData = GetViewData();
2397 0 : ScDocument* pDoc = rViewData.GetDocument();
2398 0 : SvNumberFormatter* pNumberFormatter = pDoc->GetFormatTable();
2399 0 : LanguageType eLanguage = ScGlobal::eLnge;
2400 0 : ScPatternAttr aNewAttrs( pDoc->GetPool() );
2401 :
2402 : // always take language from cursor position, even if there is a selection
2403 :
2404 : sal_uInt32 nCurrentNumberFormat;
2405 0 : pDoc->GetNumberFormat( rViewData.GetCurX(),
2406 : rViewData.GetCurY(),
2407 0 : rViewData.GetTabNo(),
2408 0 : nCurrentNumberFormat );
2409 0 : const SvNumberformat* pEntry = pNumberFormatter->GetEntry( nCurrentNumberFormat );
2410 0 : if (pEntry)
2411 0 : eLanguage = pEntry->GetLanguage(); // else keep ScGlobal::eLnge
2412 :
2413 0 : nNumberFormat = pNumberFormatter->GetStandardFormat( nFormatType, eLanguage ) + nAdd;
2414 :
2415 0 : SfxItemSet& rSet = aNewAttrs.GetItemSet();
2416 0 : rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNumberFormat ) );
2417 : // ATTR_LANGUAGE_FORMAT not
2418 0 : ApplySelectionPattern( aNewAttrs, true );
2419 : }
2420 :
2421 0 : void ScViewFunc::SetNumFmtByStr( const OUString& rCode )
2422 : {
2423 : // not editable because of matrix only? attribute OK nonetheless
2424 : bool bOnlyNotBecauseOfMatrix;
2425 0 : if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
2426 : {
2427 0 : ErrorMessage(STR_PROTECTIONERR);
2428 0 : return;
2429 : }
2430 :
2431 0 : ScViewData& rViewData = GetViewData();
2432 0 : ScDocument* pDoc = rViewData.GetDocument();
2433 0 : SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
2434 :
2435 : // language always from cursor position
2436 :
2437 : sal_uInt32 nCurrentNumberFormat;
2438 0 : pDoc->GetNumberFormat( rViewData.GetCurX(), rViewData.GetCurY(),
2439 0 : rViewData.GetTabNo(), nCurrentNumberFormat );
2440 0 : const SvNumberformat* pEntry = pFormatter->GetEntry( nCurrentNumberFormat );
2441 0 : LanguageType eLanguage = pEntry ? pEntry->GetLanguage() : ScGlobal::eLnge;
2442 :
2443 : // determine index for String
2444 :
2445 0 : bool bOk = true;
2446 0 : sal_uInt32 nNumberFormat = pFormatter->GetEntryKey( rCode, eLanguage );
2447 0 : if ( nNumberFormat == NUMBERFORMAT_ENTRY_NOT_FOUND )
2448 : {
2449 : // enter new
2450 :
2451 0 : OUString aFormat = rCode; // will be changed
2452 0 : sal_Int32 nErrPos = 0;
2453 0 : short nType = 0; //! ???
2454 0 : bOk = pFormatter->PutEntry( aFormat, nErrPos, nType, nNumberFormat, eLanguage );
2455 : }
2456 :
2457 0 : if ( bOk ) // valid format?
2458 : {
2459 0 : ScPatternAttr aNewAttrs( pDoc->GetPool() );
2460 0 : SfxItemSet& rSet = aNewAttrs.GetItemSet();
2461 0 : rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNumberFormat ) );
2462 0 : rSet.Put( SvxLanguageItem( eLanguage, ATTR_LANGUAGE_FORMAT ) );
2463 0 : ApplySelectionPattern( aNewAttrs, true );
2464 : }
2465 :
2466 : //! else return error / issue warning ???
2467 : }
2468 :
2469 0 : void ScViewFunc::ChangeNumFmtDecimals( bool bIncrement )
2470 : {
2471 : // not editable because of matrix only? attribute OK nonetheless
2472 : bool bOnlyNotBecauseOfMatrix;
2473 0 : if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
2474 : {
2475 0 : ErrorMessage(STR_PROTECTIONERR);
2476 0 : return;
2477 : }
2478 :
2479 0 : ScDocument* pDoc = GetViewData().GetDocument();
2480 0 : SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
2481 :
2482 0 : SCCOL nCol = GetViewData().GetCurX();
2483 0 : SCROW nRow = GetViewData().GetCurY();
2484 0 : SCTAB nTab = GetViewData().GetTabNo();
2485 :
2486 : sal_uInt32 nOldFormat;
2487 0 : pDoc->GetNumberFormat( nCol, nRow, nTab, nOldFormat );
2488 0 : const SvNumberformat* pOldEntry = pFormatter->GetEntry( nOldFormat );
2489 0 : if (!pOldEntry)
2490 : {
2491 : OSL_FAIL("numberformat not found !!!");
2492 0 : return;
2493 : }
2494 :
2495 : // what have we got here?
2496 :
2497 0 : sal_uInt32 nNewFormat = nOldFormat;
2498 0 : bool bError = false;
2499 :
2500 0 : LanguageType eLanguage = pOldEntry->GetLanguage();
2501 : bool bThousand, bNegRed;
2502 : sal_uInt16 nPrecision, nLeading;
2503 0 : pOldEntry->GetFormatSpecialInfo( bThousand, bNegRed, nPrecision, nLeading );
2504 :
2505 0 : short nOldType = pOldEntry->GetType();
2506 0 : if ( 0 == ( nOldType & (
2507 : css::util::NumberFormat::NUMBER | css::util::NumberFormat::CURRENCY | css::util::NumberFormat::PERCENT | css::util::NumberFormat::SCIENTIFIC ) ) )
2508 : {
2509 : // date, time, fraction, logical, text can not be changed
2510 0 : bError = true;
2511 : }
2512 :
2513 : //! SvNumberformat has a Member bStandard, but doesn't disclose it
2514 0 : bool bWasStandard = ( nOldFormat == pFormatter->GetStandardIndex( eLanguage ) );
2515 0 : OUString sExponentialStandardFormat = "";
2516 0 : if (bWasStandard)
2517 : {
2518 : // with "Standard" the decimal places depend on cell content
2519 : // 0 if empty or text -> no decimal places
2520 0 : double nVal = pDoc->GetValue( ScAddress( nCol, nRow, nTab ) );
2521 :
2522 : // the ways of the Numberformatters are unfathomable, so try:
2523 0 : OUString aOut;
2524 : Color* pCol;
2525 0 : const_cast<SvNumberformat*>(pOldEntry)->GetOutputString( nVal, aOut, &pCol );
2526 :
2527 0 : nPrecision = 0;
2528 : // 'E' for exponential is fixed in Numberformatter
2529 0 : sal_Int32 nIndexE = aOut.indexOf((sal_Unicode)'E');
2530 0 : if ( nIndexE >= 0 )
2531 : {
2532 0 : sExponentialStandardFormat = aOut.copy( nIndexE ).replace( '-', '+' );
2533 0 : for ( sal_Int32 i=1 ; i<sExponentialStandardFormat.getLength() ; i++ )
2534 : {
2535 0 : if ( sExponentialStandardFormat[i] >= '1' && sExponentialStandardFormat[i] <= '9' )
2536 0 : sExponentialStandardFormat = sExponentialStandardFormat.replaceAt( i, 1, OUString( "0" ) );
2537 : }
2538 0 : aOut = aOut.copy( 0, nIndexE ); // remove exponential part
2539 : }
2540 0 : OUString aDecSep( pFormatter->GetFormatDecimalSep( nOldFormat ) );
2541 0 : sal_Int32 nPos = aOut.indexOf( aDecSep );
2542 0 : if ( nPos >= 0 )
2543 0 : nPrecision = aOut.getLength() - nPos - aDecSep.getLength();
2544 : // else keep 0
2545 : }
2546 :
2547 0 : if (!bError)
2548 : {
2549 0 : if (bIncrement)
2550 : {
2551 0 : if (nPrecision<20)
2552 0 : ++nPrecision; // increment
2553 : else
2554 0 : bError = true; // 20 is maximum
2555 : }
2556 : else
2557 : {
2558 0 : if (nPrecision)
2559 0 : --nPrecision; // decrement
2560 : else
2561 0 : bError = true; // 0 is minimum
2562 : }
2563 : }
2564 :
2565 0 : if (!bError)
2566 : {
2567 : OUString aNewPicture = pFormatter->GenerateFormat(nOldFormat, eLanguage,
2568 : bThousand, bNegRed,
2569 : nPrecision, nLeading)
2570 0 : + sExponentialStandardFormat;
2571 :
2572 0 : nNewFormat = pFormatter->GetEntryKey( aNewPicture, eLanguage );
2573 0 : if ( nNewFormat == NUMBERFORMAT_ENTRY_NOT_FOUND )
2574 : {
2575 0 : sal_Int32 nErrPos = 0;
2576 0 : short nNewType = 0;
2577 : bool bOk = pFormatter->PutEntry( aNewPicture, nErrPos,
2578 0 : nNewType, nNewFormat, eLanguage );
2579 : OSL_ENSURE( bOk, "incorrect numberformat generated" );
2580 0 : if (!bOk)
2581 0 : bError = true;
2582 0 : }
2583 : }
2584 :
2585 0 : if (!bError)
2586 : {
2587 0 : ScPatternAttr aNewAttrs( pDoc->GetPool() );
2588 0 : SfxItemSet& rSet = aNewAttrs.GetItemSet();
2589 0 : rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat ) );
2590 : // ATTR_LANGUAGE_FORMAT not
2591 0 : ApplySelectionPattern( aNewAttrs, true );
2592 0 : }
2593 : }
2594 :
2595 0 : void ScViewFunc::ChangeIndent( bool bIncrement )
2596 : {
2597 0 : ScViewData& rViewData = GetViewData();
2598 0 : ScDocShell* pDocSh = rViewData.GetDocShell();
2599 0 : ScMarkData& rMark = rViewData.GetMarkData();
2600 :
2601 0 : ScMarkData aWorkMark = rMark;
2602 0 : ScViewUtil::UnmarkFiltered( aWorkMark, &pDocSh->GetDocument() );
2603 0 : aWorkMark.MarkToMulti();
2604 0 : if (!aWorkMark.IsMultiMarked())
2605 : {
2606 0 : SCCOL nCol = rViewData.GetCurX();
2607 0 : SCROW nRow = rViewData.GetCurY();
2608 0 : SCTAB nTab = rViewData.GetTabNo();
2609 0 : aWorkMark.SetMultiMarkArea( ScRange(nCol,nRow,nTab) );
2610 : }
2611 :
2612 0 : bool bSuccess = pDocSh->GetDocFunc().ChangeIndent( aWorkMark, bIncrement, false );
2613 0 : if (bSuccess)
2614 : {
2615 0 : pDocSh->UpdateOle(&rViewData);
2616 0 : StartFormatArea();
2617 :
2618 : // stuff for sidebar panels
2619 0 : SfxBindings& rBindings = GetViewData().GetBindings();
2620 0 : rBindings.Invalidate( SID_H_ALIGNCELL );
2621 0 : rBindings.Invalidate( SID_ATTR_ALIGN_INDENT );
2622 0 : }
2623 0 : }
2624 :
2625 0 : bool ScViewFunc::InsertName( const OUString& rName, const OUString& rSymbol,
2626 : const OUString& rType )
2627 : {
2628 : // Type = P,R,C,F (and combinations)
2629 : //! undo...
2630 :
2631 0 : bool bOk = false;
2632 0 : ScDocShell* pDocSh = GetViewData().GetDocShell();
2633 0 : ScDocument& rDoc = pDocSh->GetDocument();
2634 0 : SCTAB nTab = GetViewData().GetTabNo();
2635 0 : ScRangeName* pList = rDoc.GetRangeName();
2636 :
2637 0 : RangeType nType = RT_NAME;
2638 : ScRangeData* pNewEntry = new ScRangeData( &rDoc, rName, rSymbol,
2639 0 : ScAddress( GetViewData().GetCurX(), GetViewData().GetCurY(),
2640 0 : nTab), nType );
2641 0 : OUString aUpType = rType.toAsciiUpperCase();
2642 0 : if ( aUpType.indexOf( 'P' ) != -1 )
2643 0 : nType |= RT_PRINTAREA;
2644 0 : if ( aUpType.indexOf( 'R' ) != -1 )
2645 0 : nType |= RT_ROWHEADER;
2646 0 : if ( aUpType.indexOf( 'C' ) != -1 )
2647 0 : nType |= RT_COLHEADER;
2648 0 : if ( aUpType.indexOf( 'F' ) != -1 )
2649 0 : nType |= RT_CRITERIA;
2650 0 : pNewEntry->AddType(nType);
2651 :
2652 0 : if ( !pNewEntry->GetErrCode() ) // text valid?
2653 : {
2654 0 : ScDocShellModificator aModificator( *pDocSh );
2655 :
2656 0 : rDoc.PreprocessRangeNameUpdate();
2657 :
2658 : // input available yet? Then remove beforehand (=change)
2659 0 : ScRangeData* pData = pList->findByUpperName(ScGlobal::pCharClass->uppercase(rName));
2660 0 : if (pData)
2661 : { // take old Index
2662 0 : pNewEntry->SetIndex(pData->GetIndex());
2663 0 : pList->erase(*pData);
2664 : }
2665 :
2666 0 : if ( pList->insert( pNewEntry ) )
2667 0 : bOk = true;
2668 0 : pNewEntry = NULL; // never delete, insert took ownership
2669 :
2670 0 : rDoc.CompileHybridFormula();
2671 :
2672 0 : aModificator.SetDocumentModified();
2673 0 : SfxGetpApp()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
2674 : }
2675 :
2676 0 : delete pNewEntry; // if it wasn't inserted
2677 0 : return bOk;
2678 : }
2679 :
2680 0 : void ScViewFunc::CreateNames( sal_uInt16 nFlags )
2681 : {
2682 0 : bool bDone = false;
2683 0 : ScRange aRange;
2684 0 : if ( GetViewData().GetSimpleArea(aRange) == SC_MARK_SIMPLE )
2685 0 : bDone = GetViewData().GetDocShell()->GetDocFunc().CreateNames( aRange, nFlags, false );
2686 :
2687 0 : if (!bDone)
2688 0 : ErrorMessage(STR_CREATENAME_MARKERR);
2689 0 : }
2690 :
2691 0 : sal_uInt16 ScViewFunc::GetCreateNameFlags()
2692 : {
2693 0 : sal_uInt16 nFlags = 0;
2694 :
2695 : SCCOL nStartCol, nEndCol;
2696 : SCROW nStartRow, nEndRow;
2697 : SCTAB nDummy;
2698 0 : if (GetViewData().GetSimpleArea(nStartCol,nStartRow,nDummy,nEndCol,nEndRow,nDummy) == SC_MARK_SIMPLE)
2699 : {
2700 0 : ScDocument* pDoc = GetViewData().GetDocument();
2701 0 : SCTAB nTab = GetViewData().GetTabNo();
2702 : bool bOk;
2703 : SCCOL i;
2704 : SCROW j;
2705 :
2706 0 : bOk = true;
2707 0 : SCCOL nFirstCol = nStartCol;
2708 0 : SCCOL nLastCol = nEndCol;
2709 0 : if (nStartCol+1 < nEndCol) { ++nFirstCol; --nLastCol; }
2710 0 : for (i=nFirstCol; i<=nLastCol && bOk; i++)
2711 0 : if (!pDoc->HasStringData( i,nStartRow,nTab ))
2712 0 : bOk = false;
2713 0 : if (bOk)
2714 0 : nFlags |= NAME_TOP;
2715 : else // Bottom only if not Top
2716 : {
2717 0 : bOk = true;
2718 0 : for (i=nFirstCol; i<=nLastCol && bOk; i++)
2719 0 : if (!pDoc->HasStringData( i,nEndRow,nTab ))
2720 0 : bOk = false;
2721 0 : if (bOk)
2722 0 : nFlags |= NAME_BOTTOM;
2723 : }
2724 :
2725 0 : bOk = true;
2726 0 : SCROW nFirstRow = nStartRow;
2727 0 : SCROW nLastRow = nEndRow;
2728 0 : if (nStartRow+1 < nEndRow) { ++nFirstRow; --nLastRow; }
2729 0 : for (j=nFirstRow; j<=nLastRow && bOk; j++)
2730 0 : if (!pDoc->HasStringData( nStartCol,j,nTab ))
2731 0 : bOk = false;
2732 0 : if (bOk)
2733 0 : nFlags |= NAME_LEFT;
2734 : else // Right only if not Left
2735 : {
2736 0 : bOk = true;
2737 0 : for (j=nFirstRow; j<=nLastRow && bOk; j++)
2738 0 : if (!pDoc->HasStringData( nEndCol,j,nTab ))
2739 0 : bOk = false;
2740 0 : if (bOk)
2741 0 : nFlags |= NAME_RIGHT;
2742 : }
2743 : }
2744 :
2745 0 : if (nStartCol == nEndCol)
2746 0 : nFlags &= ~( NAME_LEFT | NAME_RIGHT );
2747 0 : if (nStartRow == nEndRow)
2748 0 : nFlags &= ~( NAME_TOP | NAME_BOTTOM );
2749 :
2750 0 : return nFlags;
2751 : }
2752 :
2753 0 : void ScViewFunc::InsertNameList()
2754 : {
2755 0 : ScAddress aPos( GetViewData().GetCurX(), GetViewData().GetCurY(), GetViewData().GetTabNo() );
2756 0 : ScDocShell* pDocSh = GetViewData().GetDocShell();
2757 0 : if ( pDocSh->GetDocFunc().InsertNameList( aPos, false ) )
2758 0 : pDocSh->UpdateOle(&GetViewData());
2759 0 : }
2760 :
2761 0 : void ScViewFunc::UpdateSelectionArea( const ScMarkData& rSel, ScPatternAttr* pAttr )
2762 : {
2763 0 : ScDocShell* pDocShell = GetViewData().GetDocShell();
2764 0 : ScRange aMarkRange;
2765 0 : if (rSel.IsMultiMarked() )
2766 0 : rSel.GetMultiMarkArea( aMarkRange );
2767 : else
2768 0 : rSel.GetMarkArea( aMarkRange );
2769 :
2770 0 : bool bSetLines = false;
2771 0 : bool bSetAlign = false;
2772 0 : if ( pAttr )
2773 : {
2774 0 : const SfxItemSet& rNewSet = pAttr->GetItemSet();
2775 0 : bSetLines = rNewSet.GetItemState( ATTR_BORDER, true ) == SfxItemState::SET ||
2776 0 : rNewSet.GetItemState( ATTR_SHADOW, true ) == SfxItemState::SET;
2777 0 : bSetAlign = rNewSet.GetItemState( ATTR_HOR_JUSTIFY, true ) == SfxItemState::SET;
2778 : }
2779 :
2780 0 : sal_uInt16 nExtFlags = 0;
2781 0 : if ( bSetLines )
2782 0 : nExtFlags |= SC_PF_LINES;
2783 0 : if ( bSetAlign )
2784 0 : nExtFlags |= SC_PF_WHOLEROWS;
2785 :
2786 0 : SCCOL nStartCol = aMarkRange.aStart.Col();
2787 0 : SCROW nStartRow = aMarkRange.aStart.Row();
2788 0 : SCTAB nStartTab = aMarkRange.aStart.Tab();
2789 0 : SCCOL nEndCol = aMarkRange.aEnd.Col();
2790 0 : SCROW nEndRow = aMarkRange.aEnd.Row();
2791 0 : SCTAB nEndTab = aMarkRange.aEnd.Tab();
2792 : pDocShell->PostPaint( nStartCol, nStartRow, nStartTab,
2793 : nEndCol, nEndRow, nEndTab,
2794 0 : PAINT_GRID, nExtFlags | SC_PF_TESTMERGE );
2795 0 : ScTabViewShell* pTabViewShell = GetViewData().GetViewShell();
2796 0 : pTabViewShell->AdjustBlockHeight(false, const_cast<ScMarkData*>(&rSel));
2797 156 : }
2798 :
2799 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|