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