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