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