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