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