update ooo310-m15
[ooovba.git] / sc / source / ui / view / viewfunc.cxx
blobea2ddec23592806ba8fe36d037065e6aa8fe651d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: viewfunc.cxx,v $
10 * $Revision: 1.46.18.4 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 //------------------------------------------------------------------
38 // INCLUDE ---------------------------------------------------------------
40 #include "scitems.hxx"
41 #include <svx/eeitem.hxx>
43 #include <sfx2/app.hxx>
44 #include <svx/algitem.hxx>
45 #include <svx/boxitem.hxx>
46 #include <svx/editobj.hxx>
47 #include <svx/editview.hxx>
48 #include <svx/langitem.hxx>
49 #include <svx/scripttypeitem.hxx>
50 #include <sfx2/bindings.hxx>
51 #include <svtools/zforlist.hxx>
52 #include <svtools/zformat.hxx>
53 #include <vcl/msgbox.hxx>
54 #include <vcl/sound.hxx>
55 #include <vcl/virdev.hxx>
56 #include <vcl/waitobj.hxx>
57 #include <vcl/wrkwin.hxx>
58 #include <stdlib.h> // qsort
60 #include "viewfunc.hxx"
61 #include "tabvwsh.hxx"
62 #include "docsh.hxx"
63 #include "attrib.hxx"
64 #include "patattr.hxx"
65 #include "docpool.hxx"
66 #include "uiitems.hxx"
67 #include "sc.hrc"
68 #include "undocell.hxx"
69 #include "undoblk.hxx"
70 #include "undotab.hxx"
71 #include "refundo.hxx"
72 #include "dbcolect.hxx"
73 #include "olinetab.hxx"
74 #include "rangeutl.hxx"
75 #include "rangenam.hxx"
76 #include "globstr.hrc"
77 #include "global.hxx"
78 #include "stlsheet.hxx"
79 #include "editutil.hxx"
80 //CHINA001 #include "namecrea.hxx" // wegen Flags
81 #include "cell.hxx"
82 #include "scresid.hxx"
83 #include "inputhdl.hxx"
84 #include "scmod.hxx"
85 #include "inputopt.hxx"
86 #include "compiler.hxx"
87 #include "docfunc.hxx"
88 #include "appoptio.hxx"
89 #include "dociter.hxx"
90 #include "sizedev.hxx"
91 #include "editable.hxx"
92 #include "scui_def.hxx" //CHINA001
93 #include "funcdesc.hxx"
94 #include "docuno.hxx"
95 #include "cellsuno.hxx"
96 //==================================================================
98 ScViewFunc::ScViewFunc( Window* pParent, ScDocShell& rDocSh, ScTabViewShell* pViewShell ) :
99 ScTabView( pParent, rDocSh, pViewShell ),
100 bFormatValid( FALSE )
104 //UNUSED2008-05 ScViewFunc::ScViewFunc( Window* pParent, const ScViewFunc& rViewFunc, ScTabViewShell* pViewShell ) :
105 //UNUSED2008-05 ScTabView( pParent, rViewFunc, pViewShell ),
106 //UNUSED2008-05 bFormatValid( FALSE )
107 //UNUSED2008-05 {
108 //UNUSED2008-05 }
110 ScViewFunc::~ScViewFunc()
114 //------------------------------------------------------------------------------------
116 void ScViewFunc::StartFormatArea()
118 // ueberhaupt aktiviert?
119 if ( !SC_MOD()->GetInputOptions().GetExtendFormat() )
120 return;
122 // start only with single cell (marked or cursor position)
123 ScRange aMarkRange;
124 BOOL bOk = (GetViewData()->GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE);
125 if ( bOk && aMarkRange.aStart != aMarkRange.aEnd )
126 bOk = FALSE;
128 if (bOk)
130 bFormatValid = TRUE;
131 aFormatSource = aMarkRange.aStart;
132 aFormatArea = ScRange( aFormatSource );
134 else
135 bFormatValid = FALSE; // keinen alten Bereich behalten
138 BOOL ScViewFunc::TestFormatArea( SCCOL nCol, SCROW nRow, SCTAB nTab, BOOL bAttrChanged )
140 // ueberhaupt aktiviert?
141 if ( !SC_MOD()->GetInputOptions().GetExtendFormat() )
142 return FALSE;
144 // Test: Eingabe mit Zahlformat (bAttrChanged) immer als neue Attributierung behandeln
145 // (alte Area verwerfen). Wenn das nicht gewollt ist, den if-Teil weglassen:
146 if ( bAttrChanged )
148 StartFormatArea();
149 return FALSE;
152 //! Abfrage, ob Zelle leer war ???
154 BOOL bFound = FALSE;
155 ScRange aNewRange = aFormatArea;
156 if ( bFormatValid && nTab == aFormatSource.Tab() )
158 if ( nRow >= aFormatArea.aStart.Row() && nRow <= aFormatArea.aEnd.Row() )
160 // innerhalb ?
161 if ( nCol >= aFormatArea.aStart.Col() && nCol <= aFormatArea.aEnd.Col() )
163 bFound = TRUE; // Bereich nicht aendern
165 // links ?
166 if ( nCol+1 == aFormatArea.aStart.Col() )
168 bFound = TRUE;
169 aNewRange.aStart.SetCol( nCol );
171 // rechts ?
172 if ( nCol == aFormatArea.aEnd.Col()+1 )
174 bFound = TRUE;
175 aNewRange.aEnd.SetCol( nCol );
178 if ( nCol >= aFormatArea.aStart.Col() && nCol <= aFormatArea.aEnd.Col() )
180 // oben ?
181 if ( nRow+1 == aFormatArea.aStart.Row() )
183 bFound = TRUE;
184 aNewRange.aStart.SetRow( nRow );
186 // unten ?
187 if ( nRow == aFormatArea.aEnd.Row()+1 )
189 bFound = TRUE;
190 aNewRange.aEnd.SetRow( nRow );
195 if (bFound)
196 aFormatArea = aNewRange; // erweitern
197 else
199 bFormatValid = FALSE; // ausserhalb -> abbrechen
200 if ( bAttrChanged ) // Wert mit Zahlformat eingegeben?
201 StartFormatArea(); // dann ggf. neu starten
204 return bFound;
207 void ScViewFunc::DoAutoAttributes( SCCOL nCol, SCROW nRow, SCTAB nTab,
208 BOOL bAttrChanged, BOOL bAddUndo )
210 ScDocShell* pDocSh = GetViewData()->GetDocShell();
211 ScDocument* pDoc = pDocSh->GetDocument();
212 if (bAddUndo && !pDoc->IsUndoEnabled())
213 bAddUndo = FALSE;
215 const ScPatternAttr* pSource = pDoc->GetPattern(
216 aFormatSource.Col(), aFormatSource.Row(), nTab );
217 if ( !((const ScMergeAttr&)pSource->GetItem(ATTR_MERGE)).IsMerged() )
219 const ScPatternAttr* pDocOld = pDoc->GetPattern( nCol, nRow, nTab );
220 // pDocOld ist nur bis zum Apply... gueltig!
222 ScPatternAttr* pOldPattern = NULL;
223 if ( bAddUndo )
224 pOldPattern = new ScPatternAttr( *pDocOld );
226 const ScStyleSheet* pSrcStyle = pSource->GetStyleSheet();
227 if ( pSrcStyle && pSrcStyle != pDocOld->GetStyleSheet() )
228 pDoc->ApplyStyle( nCol, nRow, nTab, *pSrcStyle );
229 pDoc->ApplyPattern( nCol, nRow, nTab, *pSource );
230 AdjustRowHeight( nRow, nRow, TRUE ); //! nicht doppelt ?
232 if ( bAddUndo )
234 const ScPatternAttr* pNewPattern = pDoc->GetPattern( nCol, nRow, nTab );
236 pDocSh->GetUndoManager()->AddUndoAction(
237 new ScUndoCursorAttr( pDocSh, nCol, nRow, nTab,
238 pOldPattern, pNewPattern, pSource,
239 TRUE ) );
241 delete pOldPattern; // wird im Undo kopiert (Pool)
245 if ( bAttrChanged ) // Wert mit Zahlformat eingegeben?
246 aFormatSource.Set( nCol, nRow, nTab ); // dann als neue Quelle
249 //------------------------------------------------------------------------------------
251 // Hilfsroutinen
253 USHORT ScViewFunc::GetOptimalColWidth( SCCOL nCol, SCTAB nTab, BOOL bFormula )
255 ScDocShell* pDocSh = GetViewData()->GetDocShell();
256 ScDocument* pDoc = pDocSh->GetDocument();
257 ScMarkData& rMark = GetViewData()->GetMarkData();
259 double nPPTX = GetViewData()->GetPPTX();
260 double nPPTY = GetViewData()->GetPPTY();
261 Fraction aZoomX = GetViewData()->GetZoomX();
262 Fraction aZoomY = GetViewData()->GetZoomY();
264 ScSizeDeviceProvider aProv(pDocSh);
265 if (aProv.IsPrinter())
267 nPPTX = aProv.GetPPTX();
268 nPPTY = aProv.GetPPTY();
269 aZoomX = aZoomY = Fraction( 1, 1 );
272 USHORT nTwips = pDoc->GetOptimalColWidth( nCol, nTab, aProv.GetDevice(),
273 nPPTX, nPPTY, aZoomX, aZoomY, bFormula, &rMark );
274 return nTwips;
277 BOOL ScViewFunc::SelectionEditable( BOOL* pOnlyNotBecauseOfMatrix /* = NULL */ )
279 BOOL bRet;
280 ScDocument* pDoc = GetViewData()->GetDocument();
281 ScMarkData& rMark = GetViewData()->GetMarkData();
282 if (rMark.IsMarked() || rMark.IsMultiMarked())
283 bRet = pDoc->IsSelectionEditable( rMark, pOnlyNotBecauseOfMatrix );
284 else
286 SCCOL nCol = GetViewData()->GetCurX();
287 SCROW nRow = GetViewData()->GetCurY();
288 SCTAB nTab = GetViewData()->GetTabNo();
289 bRet = pDoc->IsBlockEditable( nTab, nCol, nRow, nCol, nRow,
290 pOnlyNotBecauseOfMatrix );
292 return bRet;
295 #ifndef LRU_MAX
296 #define LRU_MAX 10
297 #endif
299 BOOL lcl_FunctionKnown( USHORT nOpCode )
301 const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList();
302 if ( pFuncList )
304 ULONG nCount = pFuncList->GetCount();
305 for (ULONG i=0; i<nCount; i++)
306 if ( pFuncList->GetFunction(i)->nFIndex == nOpCode )
307 return TRUE;
309 return FALSE;
312 BOOL lcl_AddFunction( ScAppOptions& rAppOpt, USHORT nOpCode )
314 USHORT nOldCount = rAppOpt.GetLRUFuncListCount();
315 USHORT* pOldList = rAppOpt.GetLRUFuncList();
316 USHORT nPos;
317 for (nPos=0; nPos<nOldCount; nPos++)
318 if (pOldList[nPos] == nOpCode) // is the function already in the list?
320 if ( nPos == 0 )
321 return FALSE; // already at the top -> no change
323 // count doesn't change, so the original array is modified
325 for (USHORT nCopy=nPos; nCopy>0; nCopy--)
326 pOldList[nCopy] = pOldList[nCopy-1];
327 pOldList[0] = nOpCode;
329 return TRUE; // list has changed
332 if ( !lcl_FunctionKnown( nOpCode ) )
333 return FALSE; // not in function list -> no change
335 USHORT nNewCount = Min( (USHORT)(nOldCount + 1), (USHORT)LRU_MAX );
336 USHORT nNewList[LRU_MAX];
337 nNewList[0] = nOpCode;
338 for (nPos=1; nPos<nNewCount; nPos++)
339 nNewList[nPos] = pOldList[nPos-1];
340 rAppOpt.SetLRUFuncList( nNewList, nNewCount );
342 return TRUE; // list has changed
345 // eigentliche Funktionen
347 // Eingabe - Undo OK
349 void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rString,
350 BOOL bRecord, const EditTextObject* pData )
352 ScDocument* pDoc = GetViewData()->GetDocument();
353 ScMarkData& rMark = GetViewData()->GetMarkData();
354 SCTAB nTabCount = pDoc->GetTableCount();
355 SCTAB nSelCount = rMark.GetSelectCount();
356 SCTAB i;
357 if (bRecord && !pDoc->IsUndoEnabled())
358 bRecord = FALSE;
360 ScDocShell* pDocSh = GetViewData()->GetDocShell();
361 ScDocShellModificator aModificator( *pDocSh );
363 ScEditableTester aTester( pDoc, nCol,nRow, nCol,nRow, rMark );
364 if (aTester.IsEditable())
366 BOOL bEditDeleted = FALSE;
367 BYTE nOldScript = 0;
369 ScBaseCell** ppOldCells = NULL;
370 BOOL* pHasFormat = NULL;
371 ULONG* pOldFormats = NULL;
372 SCTAB* pTabs = NULL;
373 SCTAB nUndoPos = 0;
374 EditTextObject* pUndoData = NULL;
375 if ( bRecord )
377 ppOldCells = new ScBaseCell*[nSelCount];
378 pHasFormat = new BOOL[nSelCount];
379 pOldFormats = new ULONG[nSelCount];
380 pTabs = new SCTAB[nSelCount];
381 nUndoPos = 0;
383 for (i=0; i<nTabCount; i++)
384 if (rMark.GetTableSelect(i))
386 pTabs[nUndoPos] = i;
387 ScBaseCell* pDocCell;
388 pDoc->GetCell( nCol, nRow, i, pDocCell );
389 if ( pDocCell )
391 ppOldCells[nUndoPos] = pDocCell->CloneWithoutNote( *pDoc );
392 if ( pDocCell->GetCellType() == CELLTYPE_EDIT )
393 bEditDeleted = TRUE;
395 BYTE nDocScript = pDoc->GetScriptType( nCol, nRow, i, pDocCell );
396 if ( nOldScript == 0 )
397 nOldScript = nDocScript;
398 else if ( nDocScript != nOldScript )
399 bEditDeleted = TRUE;
401 else
403 ppOldCells[nUndoPos] = NULL;
406 const SfxPoolItem* pItem;
407 const ScPatternAttr* pPattern = pDoc->GetPattern(nCol, nRow, i);
408 if ( SFX_ITEM_SET == pPattern->GetItemSet().GetItemState(
409 ATTR_VALUE_FORMAT,FALSE,&pItem) )
411 pHasFormat[nUndoPos] = TRUE;
412 pOldFormats[nUndoPos] = ((const SfxUInt32Item*)pItem)->GetValue();
414 else
415 pHasFormat[nUndoPos] = FALSE;
417 ++nUndoPos;
420 DBG_ASSERT( nUndoPos==nSelCount, "nUndoPos!=nSelCount" );
422 pUndoData = ( pData ? pData->Clone() : NULL );
425 bool bFormula = false;
427 // a single '=' character is handled as string (needed for special filters)
428 if ( rString.Len() > 1 )
430 if ( rString.GetChar(0) == '=' )
432 // handle as formula
433 bFormula = true;
435 else if ( rString.GetChar(0) == '+' || rString.GetChar(0) == '-' )
437 // if there is more than one leading '+' or '-' character, remove the additional ones
438 String aString( rString );
439 xub_StrLen nIndex = 1;
440 xub_StrLen nLen = aString.Len();
441 while ( nIndex < nLen && ( aString.GetChar( nIndex ) == '+' || aString.GetChar( nIndex ) == '-' ) )
443 ++nIndex;
445 aString.Erase( 1, nIndex - 1 );
447 // if the remaining part without the leading '+' or '-' character
448 // is non-empty and not a number, handle as formula
449 if ( aString.Len() > 1 )
451 sal_uInt32 nFormat = 0;
452 pDoc->GetNumberFormat( nCol, nRow, nTab, nFormat );
453 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
454 double fNumber = 0;
455 if ( !pFormatter->IsNumberFormat( aString, nFormat, fNumber ) )
457 bFormula = true;
463 BOOL bNumFmtChanged = FALSE;
464 if ( bFormula )
465 { // Formel, compile mit AutoCorrection
466 for (i=0; i<nTabCount; i++)
467 if (rMark.GetTableSelect(i))
468 break;
469 ScAddress aPos( nCol, nRow, i );
470 ScCompiler aComp( pDoc, aPos);
471 aComp.SetGrammar(pDoc->GetGrammar());
472 //2do: AutoCorrection via CalcOptions abschaltbar machen
473 aComp.SetAutoCorrection( TRUE );
474 if ( rString.GetChar(0) == '+' || rString.GetChar(0) == '-' )
476 aComp.SetExtendedErrorDetection( true );
478 String aFormula( rString );
479 ScTokenArray* pArr;
480 BOOL bAgain;
483 bAgain = FALSE;
484 BOOL bAddEqual = FALSE;
485 ScTokenArray* pArrFirst = pArr = aComp.CompileString( aFormula );
486 BOOL bCorrected = aComp.IsCorrected();
487 if ( bCorrected )
488 { // probieren, mit erster Parser-Korrektur neu zu parsen
489 pArr = aComp.CompileString( aComp.GetCorrectedFormula() );
491 if ( !pArr->GetCodeError() )
493 bAddEqual = TRUE;
494 aComp.CompileTokenArray();
495 bCorrected |= aComp.IsCorrected();
497 if ( bCorrected )
499 String aCorrectedFormula;
500 if ( bAddEqual )
502 aCorrectedFormula = '=';
503 aCorrectedFormula += aComp.GetCorrectedFormula();
505 else
506 aCorrectedFormula = aComp.GetCorrectedFormula();
507 short nResult;
508 if ( aCorrectedFormula.Len() == 1 )
509 nResult = RET_NO; // leere Formel, nur '='
510 else
512 String aMessage( ScResId( SCSTR_FORMULA_AUTOCORRECTION ) );
513 aMessage += aCorrectedFormula;
514 nResult = QueryBox( GetViewData()->GetDialogParent(),
515 WinBits(WB_YES_NO | WB_DEF_YES),
516 aMessage ).Execute();
518 if ( nResult == RET_YES )
520 aFormula = aCorrectedFormula;
521 if ( pArr != pArrFirst )
522 delete pArrFirst;
523 bAgain = TRUE;
525 else
527 if ( pArr != pArrFirst )
529 delete pArr;
530 pArr = pArrFirst;
534 } while ( bAgain );
535 // um in mehreren Tabellen eingesetzt zu werden, muss die Formel
536 // via ScFormulaCell copy-ctor evtl. wegen RangeNames neu kompiliert
537 // werden, gleiches Code-Array fuer alle Zellen geht nicht.
538 // Wenn das Array einen Fehler enthaelt, muss in den neu erzeugten
539 // Zellen RPN geloescht und der Fehler explizit gesetzt werden, da
540 // via FormulaCell copy-ctor und Interpreter das, wenn moeglich,
541 // wieder glattgebuegelt wird, zu intelligent.. z.B.: =1))
542 USHORT nError = pArr->GetCodeError();
543 if ( !nError )
545 // #68693# update list of recent functions with all functions that
546 // are not within parentheses
548 ScModule* pScMod = SC_MOD();
549 ScAppOptions aAppOpt = pScMod->GetAppOptions();
550 BOOL bOptChanged = FALSE;
552 formula::FormulaToken** ppToken = pArr->GetArray();
553 USHORT nTokens = pArr->GetLen();
554 USHORT nLevel = 0;
555 for (USHORT nTP=0; nTP<nTokens; nTP++)
557 formula::FormulaToken* pTok = ppToken[nTP];
558 OpCode eOp = pTok->GetOpCode();
559 if ( eOp == ocOpen )
560 ++nLevel;
561 else if ( eOp == ocClose && nLevel )
562 --nLevel;
563 if ( nLevel == 0 && pTok->IsFunction() &&
564 lcl_AddFunction( aAppOpt, sal::static_int_cast<USHORT>( eOp ) ) )
565 bOptChanged = TRUE;
568 if ( bOptChanged )
570 pScMod->SetAppOptions(aAppOpt);
571 pScMod->RecentFunctionsChanged();
575 ScFormulaCell aCell( pDoc, aPos, pArr,formula::FormulaGrammar::GRAM_DEFAULT, MM_NONE );
576 delete pArr;
577 BOOL bAutoCalc = pDoc->GetAutoCalc();
578 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
579 for ( ; i<nTabCount; i++)
581 if (rMark.GetTableSelect(i))
583 aPos.SetTab( i );
584 ULONG nIndex = (ULONG) ((SfxUInt32Item*) pDoc->GetAttr(
585 nCol, nRow, i, ATTR_VALUE_FORMAT ))->GetValue();
586 if ( pFormatter->GetType( nIndex ) == NUMBERFORMAT_TEXT ||
587 ( ( rString.GetChar(0) == '+' || rString.GetChar(0) == '-' ) && nError && rString.Equals( aFormula ) ) )
589 if ( pData )
591 ScEditCell* pCell = new ScEditCell( pData, pDoc, NULL );
592 pDoc->PutCell( aPos, pCell );
594 else
596 ScStringCell* pCell = new ScStringCell( aFormula );
597 pDoc->PutCell( aPos, pCell );
600 else
602 ScFormulaCell* pCell = new ScFormulaCell( aCell, *pDoc, aPos );
603 if ( nError )
605 pCell->GetCode()->DelRPN();
606 pCell->SetErrCode( nError );
607 if(pCell->GetCode()->IsHyperLink())
608 pCell->GetCode()->SetHyperLink(FALSE);
610 pDoc->PutCell( aPos, pCell );
611 if ( !bAutoCalc )
612 { // einmal nur die Zelle berechnen und wieder dirty setzen
613 pCell->Interpret();
614 pCell->SetDirtyVar();
615 pDoc->PutInFormulaTree( pCell );
622 else
624 for (i=0; i<nTabCount; i++)
625 if (rMark.GetTableSelect(i))
626 if (pDoc->SetString( nCol, nRow, i, rString ))
627 bNumFmtChanged = TRUE;
630 // row height must be changed if new text has a different script type
631 for (i=0; i<nTabCount && !bEditDeleted; i++)
632 if (rMark.GetTableSelect(i))
633 if ( pDoc->GetScriptType( nCol, nRow, i ) != nOldScript )
634 bEditDeleted = TRUE;
636 HideAllCursors();
638 if (bEditDeleted || pDoc->HasAttrib( nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_NEEDHEIGHT ))
639 AdjustRowHeight(nRow,nRow);
641 BOOL bAutoFormat = TestFormatArea(nCol, nRow, nTab, bNumFmtChanged);
642 if (bAutoFormat)
643 DoAutoAttributes(nCol, nRow, nTab, bNumFmtChanged, bRecord);
645 if ( bRecord )
646 { // wg. ChangeTrack erst jetzt
647 pDocSh->GetUndoManager()->AddUndoAction(
648 new ScUndoEnterData( pDocSh, nCol, nRow, nTab, nUndoPos, pTabs,
649 ppOldCells, pHasFormat, pOldFormats,
650 rString, pUndoData ) );
653 for (i=0; i<nTabCount; i++)
654 if (rMark.GetTableSelect(i))
655 pDocSh->PostPaintCell( nCol, nRow, i );
657 ShowAllCursors();
659 pDocSh->UpdateOle(GetViewData());
661 // #i97876# Spreadsheet data changes are not notified
662 ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
663 if ( pModelObj && pModelObj->HasChangesListeners() )
665 ScRangeList aChangeRanges;
666 for ( i = 0; i < nTabCount; ++i )
668 if ( rMark.GetTableSelect( i ) )
670 aChangeRanges.Append( ScRange( nCol, nRow, i ) );
673 pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges );
676 aModificator.SetDocumentModified();
678 else
680 ErrorMessage(aTester.GetMessageId());
681 PaintArea( nCol, nRow, nCol, nRow ); // da steht evtl. noch die Edit-Engine
685 // Wert in einzele Zelle eintragen (nur auf nTab)
687 void ScViewFunc::EnterValue( SCCOL nCol, SCROW nRow, SCTAB nTab, const double& rValue )
689 ScDocument* pDoc = GetViewData()->GetDocument();
690 ScDocShell* pDocSh = GetViewData()->GetDocShell();
691 BOOL bUndo (pDoc->IsUndoEnabled());
693 if ( pDoc && pDocSh )
695 ScDocShellModificator aModificator( *pDocSh );
697 ScEditableTester aTester( pDoc, nTab, nCol,nRow, nCol,nRow );
698 if (aTester.IsEditable())
700 ScAddress aPos( nCol, nRow, nTab );
701 ScBaseCell* pOldCell = pDoc->GetCell( aPos );
702 BOOL bNeedHeight = ( pOldCell && pOldCell->GetCellType() == CELLTYPE_EDIT )
703 || pDoc->HasAttrib(
704 nCol,nRow,nTab, nCol,nRow,nTab, HASATTR_NEEDHEIGHT );
706 // Undo
707 ScBaseCell* pUndoCell = (bUndo && pOldCell) ? pOldCell->CloneWithoutNote( *pDoc ) : 0;
709 pDoc->SetValue( nCol, nRow, nTab, rValue );
711 // wg. ChangeTrack nach Aenderung im Dokument
712 if (bUndo)
714 pDocSh->GetUndoManager()->AddUndoAction(
715 new ScUndoEnterValue( pDocSh, aPos, pUndoCell, rValue, bNeedHeight ) );
718 /*! Zeilenhoehe anpassen? Dann auch bei Undo...
719 if (bNeedHeight)
720 AdjustRowHeight(nRow,nRow);
723 pDocSh->PostPaintCell( aPos );
724 pDocSh->UpdateOle(GetViewData());
725 aModificator.SetDocumentModified();
727 else
728 ErrorMessage(aTester.GetMessageId());
732 void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const EditTextObject* pData,
733 BOOL bRecord, BOOL bTestSimple )
735 ScDocShell* pDocSh = GetViewData()->GetDocShell();
736 ScMarkData& rMark = GetViewData()->GetMarkData();
737 ScDocument* pDoc = pDocSh->GetDocument();
738 if (bRecord && !pDoc->IsUndoEnabled())
739 bRecord = FALSE;
741 ScDocShellModificator aModificator( *pDocSh );
743 ScEditableTester aTester( pDoc, nTab, nCol,nRow, nCol,nRow );
744 if (aTester.IsEditable())
747 // Test auf Attribute
749 BOOL bSimple = FALSE;
750 BOOL bCommon = FALSE;
751 ScPatternAttr* pCellAttrs = NULL;
752 EditTextObject* pNewData = NULL;
753 String aString;
754 if (bTestSimple) // Testen, ob einfacher String ohne Attribute
756 const ScPatternAttr* pOldPattern = pDoc->GetPattern( nCol, nRow, nTab );
757 ScTabEditEngine aEngine( *pOldPattern, pDoc->GetEnginePool() );
758 aEngine.SetText(*pData);
760 ScEditAttrTester aAttrTester( &aEngine );
761 bSimple = !aAttrTester.NeedsObject();
762 bCommon = aAttrTester.NeedsCellAttr();
764 // formulas have to be recognized even if they're formatted
765 // (but commmon attributes are still collected)
767 if ( !bSimple && aEngine.GetParagraphCount() == 1 )
769 String aParStr = aEngine.GetText( (USHORT) 0 );
770 if ( aParStr.GetChar(0) == '=' )
771 bSimple = TRUE;
774 if (bCommon) // Attribute fuer Tabelle
776 pCellAttrs = new ScPatternAttr( *pOldPattern );
777 pCellAttrs->GetFromEditItemSet( &aAttrTester.GetAttribs() );
778 //! remove common attributes from EditEngine?
781 if (bSimple)
782 aString = aEngine.GetText();
786 // Undo
789 SCTAB nTabCount = pDoc->GetTableCount();
790 SCTAB nSelCount = rMark.GetSelectCount();
791 SCTAB i;
792 ScBaseCell** ppOldCells = NULL;
793 SCTAB* pTabs = NULL;
794 SCTAB nPos = 0;
795 EditTextObject* pUndoData = NULL;
796 if (bRecord && !bSimple)
798 ppOldCells = new ScBaseCell*[nSelCount];
799 pTabs = new SCTAB[nSelCount];
800 nPos = 0;
802 for (i=0; i<nTabCount; i++)
803 if (rMark.GetTableSelect(i))
805 pTabs[nPos] = i;
806 ScBaseCell* pDocCell;
807 pDoc->GetCell( nCol, nRow, i, pDocCell );
808 ppOldCells[nPos] = pDocCell ? pDocCell->CloneWithoutNote( *pDoc ) : 0;
809 ++nPos;
812 DBG_ASSERT( nPos==nSelCount, "nPos!=nSelCount" );
814 pUndoData = pData->Clone();
818 // Daten eintragen
821 if (bCommon)
822 pDoc->ApplyPattern(nCol,nRow,nTab,*pCellAttrs); //! Undo
824 if (bSimple)
826 if (bCommon)
827 AdjustRowHeight(nRow,nRow);
829 EnterData(nCol,nRow,nTab,aString,bRecord);
831 else
833 for (i=0; i<nTabCount; i++)
834 if (rMark.GetTableSelect(i))
835 pDoc->PutCell( nCol, nRow, i, new ScEditCell( pData, pDoc, NULL ) );
837 if ( bRecord )
838 { // wg. ChangeTrack erst jetzt
839 pDocSh->GetUndoManager()->AddUndoAction(
840 new ScUndoEnterData( pDocSh, nCol, nRow, nTab, nPos, pTabs,
841 ppOldCells, NULL, NULL, String(),
842 pUndoData ) );
845 HideAllCursors();
847 AdjustRowHeight(nRow,nRow);
849 for (i=0; i<nTabCount; i++)
850 if (rMark.GetTableSelect(i))
851 pDocSh->PostPaintCell( nCol, nRow, i );
853 ShowAllCursors();
855 pDocSh->UpdateOle(GetViewData());
857 // #i97876# Spreadsheet data changes are not notified
858 ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
859 if ( pModelObj && pModelObj->HasChangesListeners() )
861 ScRangeList aChangeRanges;
862 for ( i = 0; i < nTabCount; ++i )
864 if ( rMark.GetTableSelect( i ) )
866 aChangeRanges.Append( ScRange( nCol, nRow, i ) );
869 pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges );
872 aModificator.SetDocumentModified();
875 delete pCellAttrs;
876 delete pNewData;
878 else
880 ErrorMessage(aTester.GetMessageId());
881 PaintArea( nCol, nRow, nCol, nRow ); // da steht evtl. noch die Edit-Engine
885 void ScViewFunc::EnterDataAtCursor( const String& rString )
887 SCCOL nPosX = GetViewData()->GetCurX();
888 SCROW nPosY = GetViewData()->GetCurY();
889 SCTAB nTab = GetViewData()->GetTabNo();
891 EnterData( nPosX, nPosY, nTab, rString );
894 void ScViewFunc::EnterMatrix( const String& rString )
896 ScViewData* pData = GetViewData();
897 const ScMarkData& rMark = pData->GetMarkData();
898 if ( !rMark.IsMarked() && !rMark.IsMultiMarked() )
900 // nichts markiert -> automatisch Block mit Groesse des Ergebnisses
901 // Formel temporaer berechnen, um an die Groesse heranzukommen
903 ScDocument* pDoc = pData->GetDocument();
904 SCCOL nCol = pData->GetCurX();
905 SCROW nRow = pData->GetCurY();
906 SCTAB nTab = pData->GetTabNo();
907 ScFormulaCell aFormCell( pDoc, ScAddress(nCol,nRow,nTab), rString,formula::FormulaGrammar::GRAM_DEFAULT, MM_FORMULA );
909 SCSIZE nSizeX;
910 SCSIZE nSizeY;
911 aFormCell.GetResultDimensions( nSizeX, nSizeY );
912 if ( nSizeX != 0 && nSizeY != 0 &&
913 nCol+nSizeX-1 <= sal::static_int_cast<SCSIZE>(MAXCOL) &&
914 nRow+nSizeY-1 <= sal::static_int_cast<SCSIZE>(MAXROW) )
916 ScRange aResult( nCol, nRow, nTab,
917 sal::static_int_cast<SCCOL>(nCol+nSizeX-1),
918 sal::static_int_cast<SCROW>(nRow+nSizeY-1), nTab );
919 MarkRange( aResult, FALSE );
923 ScRange aRange;
924 if (pData->GetSimpleArea(aRange) == SC_MARK_SIMPLE)
926 ScDocShell* pDocSh = pData->GetDocShell();
927 BOOL bSuccess = pDocSh->GetDocFunc().EnterMatrix( aRange, &rMark, NULL, rString, FALSE, FALSE,formula::FormulaGrammar::GRAM_DEFAULT );
928 if (bSuccess)
929 pDocSh->UpdateOle(GetViewData());
931 else
932 ErrorMessage(STR_NOMULTISELECT);
935 BYTE ScViewFunc::GetSelectionScriptType()
937 BYTE nScript = 0;
939 ScDocument* pDoc = GetViewData()->GetDocument();
940 const ScMarkData& rMark = GetViewData()->GetMarkData();
941 if ( !rMark.IsMarked() && !rMark.IsMultiMarked() )
943 // no selection -> cursor
945 nScript = pDoc->GetScriptType( GetViewData()->GetCurX(),
946 GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
948 else
950 ScRangeList aRanges;
951 rMark.FillRangeListWithMarks( &aRanges, FALSE );
952 ULONG nCount = aRanges.Count();
953 for (ULONG i=0; i<nCount; i++)
955 ScRange aRange = *aRanges.GetObject(i);
956 ScCellIterator aIter( pDoc, aRange );
957 ScBaseCell* pCell = aIter.GetFirst();
958 while ( pCell )
960 nScript |= pDoc->GetScriptType( aIter.GetCol(), aIter.GetRow(), aIter.GetTab(), pCell );
961 pCell = aIter.GetNext();
966 if (nScript == 0)
967 nScript = ScGlobal::GetDefaultScriptType();
969 return nScript;
972 const ScPatternAttr* ScViewFunc::GetSelectionPattern()
974 // Don't use UnmarkFiltered in slot state functions, for performance reasons.
975 // The displayed state is always that of the whole selection including filtered rows.
977 const ScMarkData& rMark = GetViewData()->GetMarkData();
978 ScDocument* pDoc = GetViewData()->GetDocument();
979 if ( rMark.IsMarked() || rMark.IsMultiMarked() )
981 // MarkToMulti is no longer necessary for pDoc->GetSelectionPattern
982 const ScPatternAttr* pAttr = pDoc->GetSelectionPattern( rMark );
983 return pAttr;
985 else
987 SCCOL nCol = GetViewData()->GetCurX();
988 SCROW nRow = GetViewData()->GetCurY();
989 SCTAB nTab = GetViewData()->GetTabNo();
991 ScMarkData aTempMark( rMark ); // copy sheet selection
992 aTempMark.SetMarkArea( ScRange( nCol, nRow, nTab ) );
993 const ScPatternAttr* pAttr = pDoc->GetSelectionPattern( aTempMark );
994 return pAttr;
998 void ScViewFunc::GetSelectionFrame( SvxBoxItem& rLineOuter,
999 SvxBoxInfoItem& rLineInner )
1001 ScDocument* pDoc = GetViewData()->GetDocument();
1002 const ScMarkData& rMark = GetViewData()->GetMarkData();
1004 if ( rMark.IsMarked() || rMark.IsMultiMarked() )
1006 if ( rMark.IsMultiMarked() )
1008 ScMarkData aNewMark( rMark ); // use local copy for MarkToSimple
1009 aNewMark.MarkToSimple(); // simple block is needed for GetSelectionFrame
1010 pDoc->GetSelectionFrame( aNewMark, rLineOuter, rLineInner );
1012 else
1013 pDoc->GetSelectionFrame( rMark, rLineOuter, rLineInner );
1015 else
1017 const ScPatternAttr* pAttrs =
1018 pDoc->GetPattern( GetViewData()->GetCurX(),
1019 GetViewData()->GetCurY(),
1020 GetViewData()->GetTabNo() );
1022 rLineOuter = (const SvxBoxItem&) (pAttrs->GetItem( ATTR_BORDER ));
1023 rLineInner = (const SvxBoxInfoItem&)(pAttrs->GetItem( ATTR_BORDER_INNER ));
1024 rLineInner.SetTable(FALSE);
1025 rLineInner.SetDist(TRUE);
1026 rLineInner.SetMinDist(FALSE);
1031 // Attribute anwenden - Undo OK
1033 // kompletter Set ( ATTR_STARTINDEX, ATTR_ENDINDEX )
1036 void ScViewFunc::ApplyAttributes( const SfxItemSet* pDialogSet,
1037 const SfxItemSet* pOldSet,
1038 BOOL bRecord )
1040 // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
1041 BOOL bOnlyNotBecauseOfMatrix;
1042 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
1044 ErrorMessage(STR_PROTECTIONERR);
1045 return;
1048 ScPatternAttr aOldAttrs( new SfxItemSet(*pOldSet) );
1049 ScPatternAttr aNewAttrs( new SfxItemSet(*pDialogSet) );
1050 aNewAttrs.DeleteUnchanged( &aOldAttrs );
1052 if ( pDialogSet->GetItemState( ATTR_VALUE_FORMAT ) == SFX_ITEM_SET )
1053 { // #82521# don't reset to default SYSTEM GENERAL if not intended
1054 sal_uInt32 nOldFormat =
1055 ((const SfxUInt32Item&)pOldSet->Get( ATTR_VALUE_FORMAT )).GetValue();
1056 sal_uInt32 nNewFormat =
1057 ((const SfxUInt32Item&)pDialogSet->Get( ATTR_VALUE_FORMAT )).GetValue();
1058 if ( nNewFormat != nOldFormat )
1060 SvNumberFormatter* pFormatter =
1061 GetViewData()->GetDocument()->GetFormatTable();
1062 const SvNumberformat* pOldEntry = pFormatter->GetEntry( nOldFormat );
1063 LanguageType eOldLang =
1064 pOldEntry ? pOldEntry->GetLanguage() : LANGUAGE_DONTKNOW;
1065 const SvNumberformat* pNewEntry = pFormatter->GetEntry( nNewFormat );
1066 LanguageType eNewLang =
1067 pNewEntry ? pNewEntry->GetLanguage() : LANGUAGE_DONTKNOW;
1068 if ( eNewLang != eOldLang )
1070 aNewAttrs.GetItemSet().Put(
1071 SvxLanguageItem( eNewLang, ATTR_LANGUAGE_FORMAT ) );
1073 // #40606# nur die Sprache geaendert -> Zahlformat-Attribut nicht anfassen
1074 sal_uInt32 nNewMod = nNewFormat % SV_COUNTRY_LANGUAGE_OFFSET;
1075 if ( nNewMod == ( nOldFormat % SV_COUNTRY_LANGUAGE_OFFSET ) &&
1076 nNewMod <= SV_MAX_ANZ_STANDARD_FORMATE )
1077 aNewAttrs.GetItemSet().ClearItem( ATTR_VALUE_FORMAT );
1082 const SvxBoxItem* pOldOuter = (const SvxBoxItem*) &pOldSet->Get( ATTR_BORDER );
1083 const SvxBoxItem* pNewOuter = (const SvxBoxItem*) &pDialogSet->Get( ATTR_BORDER );
1084 const SvxBoxInfoItem* pOldInner = (const SvxBoxInfoItem*) &pOldSet->Get( ATTR_BORDER_INNER );
1085 const SvxBoxInfoItem* pNewInner = (const SvxBoxInfoItem*) &pDialogSet->Get( ATTR_BORDER_INNER );
1086 SfxItemSet& rNewSet = aNewAttrs.GetItemSet();
1087 SfxItemPool* pNewPool = rNewSet.GetPool();
1089 pNewPool->Put( *pNewOuter ); // noch nicht loeschen
1090 pNewPool->Put( *pNewInner );
1091 rNewSet.ClearItem( ATTR_BORDER );
1092 rNewSet.ClearItem( ATTR_BORDER_INNER );
1095 * Feststellen, ob Rahmenattribute zu setzen sind:
1096 * 1. Neu != Alt
1097 * 2. Ist eine der Linien nicht-DontCare (seit 238.f: IsxxValid())
1101 BOOL bFrame = (pDialogSet->GetItemState( ATTR_BORDER ) != SFX_ITEM_DEFAULT)
1102 || (pDialogSet->GetItemState( ATTR_BORDER_INNER ) != SFX_ITEM_DEFAULT);
1104 if ( pNewOuter==pOldOuter && pNewInner==pOldInner )
1105 bFrame = FALSE;
1107 // das sollte doch der Pool abfangen: ?!??!??
1109 if ( bFrame && pNewOuter && pNewInner )
1110 if ( *pNewOuter == *pOldOuter && *pNewInner == *pOldInner )
1111 bFrame = FALSE;
1113 if ( pNewInner )
1115 bFrame = bFrame
1116 && ( pNewInner->IsValid(VALID_LEFT)
1117 || pNewInner->IsValid(VALID_RIGHT)
1118 || pNewInner->IsValid(VALID_TOP)
1119 || pNewInner->IsValid(VALID_BOTTOM)
1120 || pNewInner->IsValid(VALID_HORI)
1121 || pNewInner->IsValid(VALID_VERT) );
1123 else
1124 bFrame = FALSE;
1126 if (!bFrame)
1127 ApplySelectionPattern( aNewAttrs, bRecord ); // nur normale
1128 else
1130 // wenn neue Items Default-Items sind, so muessen die
1131 // alten Items geputtet werden:
1133 BOOL bDefNewOuter = ( SFX_ITEMS_STATICDEFAULT == pNewOuter->GetKind() );
1134 BOOL bDefNewInner = ( SFX_ITEMS_STATICDEFAULT == pNewInner->GetKind() );
1136 ApplyPatternLines( aNewAttrs,
1137 bDefNewOuter ? pOldOuter : pNewOuter,
1138 bDefNewInner ? pOldInner : pNewInner,
1139 bRecord );
1142 pNewPool->Remove( *pNewOuter ); // freigeben
1143 pNewPool->Remove( *pNewInner );
1145 // Hoehen anpassen
1146 AdjustBlockHeight();
1148 // CellContentChanged wird von ApplySelectionPattern / ApplyPatternLines gerufen
1151 void ScViewFunc::ApplyAttr( const SfxPoolItem& rAttrItem )
1153 // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
1154 BOOL bOnlyNotBecauseOfMatrix;
1155 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
1157 ErrorMessage(STR_PROTECTIONERR);
1158 return;
1161 ScPatternAttr aNewAttrs( new SfxItemSet( *GetViewData()->GetDocument()->GetPool(),
1162 ATTR_PATTERN_START, ATTR_PATTERN_END ) );
1164 aNewAttrs.GetItemSet().Put( rAttrItem );
1165 // Wenn Ausrichtung eingestellt wird (ueber Buttons), immer Einzug 0
1166 if ( rAttrItem.Which() == ATTR_HOR_JUSTIFY )
1167 aNewAttrs.GetItemSet().Put( SfxUInt16Item( ATTR_INDENT, 0 ) );
1168 ApplySelectionPattern( aNewAttrs );
1170 AdjustBlockHeight();
1172 // CellContentChanged wird von ApplySelectionPattern gerufen
1176 // Pattern und Rahmen
1178 void ScViewFunc::ApplyPatternLines( const ScPatternAttr& rAttr, const SvxBoxItem* pNewOuter,
1179 const SvxBoxInfoItem* pNewInner, BOOL bRecord )
1181 ScDocument* pDoc = GetViewData()->GetDocument();
1182 ScMarkData& rMark = GetViewData()->GetMarkData();
1183 if (bRecord && !pDoc->IsUndoEnabled())
1184 bRecord = FALSE;
1186 SCCOL nStartCol;
1187 SCROW nStartRow;
1188 SCTAB nStartTab;
1189 SCCOL nEndCol;
1190 SCROW nEndRow;
1191 SCTAB nEndTab;
1193 ScMarkType eMarkType = GetViewData()->GetSimpleArea( nStartCol, nStartRow,
1194 nStartTab, nEndCol, nEndRow, nEndTab);
1195 if (eMarkType == SC_MARK_SIMPLE || eMarkType == SC_MARK_SIMPLE_FILTERED)
1197 bool bChangeSelection = false;
1198 ScRange aMarkRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab );
1199 if ( eMarkType == SC_MARK_SIMPLE_FILTERED )
1201 ScMarkData aVisibleMark( rMark );
1202 ScViewUtil::UnmarkFiltered( aVisibleMark, pDoc );
1203 ScRangeList aRangeList;
1204 aVisibleMark.FillRangeListWithMarks( &aRangeList, FALSE );
1205 if ( aRangeList.Count() > 0 )
1207 // use the first range of visible cells
1208 // (might also show an error message instead, or, later, allow multiple ranges)
1210 aMarkRange = *aRangeList.GetObject(0);
1212 else // all hidden -> cursor position
1214 aMarkRange.aStart.SetCol(GetViewData()->GetCurX());
1215 aMarkRange.aStart.SetRow(GetViewData()->GetCurY());
1216 aMarkRange.aStart.SetTab(GetViewData()->GetTabNo());
1217 aMarkRange.aEnd = aMarkRange.aStart;
1219 aMarkRange.GetVars( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab );
1220 bChangeSelection = true; // change the selection to only the affected cells
1223 rMark.MarkToSimple(); // not done by GetSimpleArea anymore
1225 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1227 ScDocShellModificator aModificator( *pDocSh );
1229 if (!rMark.IsMarked() || bChangeSelection)
1231 DoneBlockMode();
1232 InitOwnBlockMode();
1233 rMark.SetMarkArea( ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ) );
1234 MarkDataChanged();
1237 if (bRecord)
1239 SCTAB nTabCount = pDoc->GetTableCount();
1240 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1241 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
1242 for (SCTAB i=0; i<nTabCount; i++)
1243 if (i != nStartTab && rMark.GetTableSelect(i))
1244 pUndoDoc->AddUndoTab( i, i );
1245 pDoc->CopyToDocument( nStartCol, nStartRow, 0, nEndCol, nEndRow, nTabCount-1,
1246 IDF_ATTRIB, FALSE, pUndoDoc );
1248 pDocSh->GetUndoManager()->AddUndoAction(
1249 new ScUndoSelectionAttr( pDocSh, rMark,
1250 nStartCol, nStartRow, nStartTab,
1251 nEndCol, nEndRow, nEndTab,
1252 pUndoDoc, FALSE, &rAttr, pNewOuter, pNewInner ) );
1255 USHORT nExt = SC_PF_TESTMERGE;
1256 pDocSh->UpdatePaintExt( nExt, nStartCol, nStartRow, nStartTab,
1257 nEndCol, nEndRow, nEndTab ); // content before the change
1259 pDoc->ApplySelectionFrame( rMark, pNewOuter, pNewInner );
1261 pDocSh->UpdatePaintExt( nExt, nStartCol, nStartRow, nStartTab,
1262 nEndCol, nEndRow, nEndTab ); // content after the change
1264 rMark.MarkToMulti();
1265 pDoc->ApplySelectionPattern( rAttr, rMark );
1267 pDocSh->PostPaint( nStartCol, nStartRow, nStartTab,
1268 nEndCol, nEndRow, nEndTab,
1269 PAINT_GRID, nExt );
1270 pDocSh->UpdateOle(GetViewData());
1271 aModificator.SetDocumentModified();
1272 CellContentChanged();
1273 rMark.MarkToSimple();
1275 else
1276 { // "Rahmen nicht auf Mehrfachselektion"
1277 ErrorMessage(STR_MSSG_APPLYPATTLINES_0);
1280 StartFormatArea();
1283 // nur Pattern
1285 void ScViewFunc::ApplySelectionPattern( const ScPatternAttr& rAttr,
1286 BOOL bRecord, BOOL bCursorOnly )
1288 ScViewData* pViewData = GetViewData();
1289 ScDocShell* pDocSh = pViewData->GetDocShell();
1290 ScDocument* pDoc = pDocSh->GetDocument();
1291 ScMarkData aFuncMark( pViewData->GetMarkData() ); // local copy for UnmarkFiltered
1292 ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
1294 if (bRecord && !pDoc->IsUndoEnabled())
1295 bRecord = FALSE;
1297 // State from old ItemSet doesn't matter for paint flags, as any change will be
1298 // from SFX_ITEM_SET in the new ItemSet (default is ignored in ApplyPattern).
1299 // New alignment is checked (check in PostPaint isn't enough) in case a right
1300 // alignment is changed to left.
1301 const SfxItemSet& rNewSet = rAttr.GetItemSet();
1302 BOOL bSetLines = rNewSet.GetItemState( ATTR_BORDER, TRUE ) == SFX_ITEM_SET ||
1303 rNewSet.GetItemState( ATTR_SHADOW, TRUE ) == SFX_ITEM_SET;
1304 BOOL bSetAlign = rNewSet.GetItemState( ATTR_HOR_JUSTIFY, TRUE ) == SFX_ITEM_SET;
1306 USHORT nExtFlags = 0;
1307 if ( bSetLines )
1308 nExtFlags |= SC_PF_LINES;
1309 if ( bSetAlign )
1310 nExtFlags |= SC_PF_WHOLEROWS;
1312 ScDocShellModificator aModificator( *pDocSh );
1314 BOOL bMulti = aFuncMark.IsMultiMarked();
1315 aFuncMark.MarkToMulti();
1316 BOOL bOnlyTab = (!aFuncMark.IsMultiMarked() && !bCursorOnly && aFuncMark.GetSelectCount() > 1);
1317 if (bOnlyTab)
1319 SCCOL nCol = pViewData->GetCurX();
1320 SCROW nRow = pViewData->GetCurY();
1321 SCTAB nTab = pViewData->GetTabNo();
1322 aFuncMark.SetMarkArea(ScRange(nCol,nRow,nTab));
1323 aFuncMark.MarkToMulti();
1326 ScRangeList aChangeRanges;
1328 if (aFuncMark.IsMultiMarked() && !bCursorOnly)
1330 ScRange aMarkRange;
1331 aFuncMark.GetMultiMarkArea( aMarkRange );
1332 SCTAB nTabCount = pDoc->GetTableCount();
1333 for ( SCTAB i = 0; i < nTabCount; ++i )
1335 if ( aFuncMark.GetTableSelect( i ) )
1337 ScRange aChangeRange( aMarkRange );
1338 aChangeRange.aStart.SetTab( i );
1339 aChangeRange.aEnd.SetTab( i );
1340 aChangeRanges.Append( aChangeRange );
1344 SCCOL nStartCol = aMarkRange.aStart.Col();
1345 SCROW nStartRow = aMarkRange.aStart.Row();
1346 SCTAB nStartTab = aMarkRange.aStart.Tab();
1347 SCCOL nEndCol = aMarkRange.aEnd.Col();
1348 SCROW nEndRow = aMarkRange.aEnd.Row();
1349 SCTAB nEndTab = aMarkRange.aEnd.Tab();
1351 ScUndoSelectionAttr* pUndoAttr = NULL;
1352 ScEditDataArray* pEditDataArray = NULL;
1353 if (bRecord)
1355 ScRange aCopyRange = aMarkRange;
1356 aCopyRange.aStart.SetTab(0);
1357 aCopyRange.aEnd.SetTab(nTabCount-1);
1359 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1360 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
1361 for (SCTAB i=0; i<nTabCount; i++)
1362 if (i != nStartTab && aFuncMark.GetTableSelect(i))
1363 pUndoDoc->AddUndoTab( i, i );
1364 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pUndoDoc, &aFuncMark );
1366 aFuncMark.MarkToMulti();
1368 pUndoAttr = new ScUndoSelectionAttr(
1369 pDocSh, aFuncMark, nStartCol, nStartRow, nStartTab,
1370 nEndCol, nEndRow, nEndTab, pUndoDoc, bMulti, &rAttr );
1371 pDocSh->GetUndoManager()->AddUndoAction(pUndoAttr);
1372 pEditDataArray = pUndoAttr->GetDataArray();
1375 pDoc->ApplySelectionPattern( rAttr, aFuncMark, pEditDataArray );
1377 pDocSh->PostPaint( nStartCol, nStartRow, nStartTab,
1378 nEndCol, nEndRow, nEndTab,
1379 PAINT_GRID, nExtFlags | SC_PF_TESTMERGE );
1380 pDocSh->UpdateOle(GetViewData());
1381 aModificator.SetDocumentModified();
1382 CellContentChanged();
1384 else // einzelne Zelle - Undo einfacher
1386 SCCOL nCol = pViewData->GetCurX();
1387 SCROW nRow = pViewData->GetCurY();
1388 SCTAB nTab = pViewData->GetTabNo();
1390 ScBaseCell* pCell;
1391 pDoc->GetCell(nCol, nRow, nTab, pCell);
1392 EditTextObject* pOldEditData = NULL;
1393 EditTextObject* pNewEditData = NULL;
1394 if (pCell && pCell->GetCellType() == CELLTYPE_EDIT)
1396 ScEditCell* pEditCell = static_cast<ScEditCell*>(pCell);
1397 pOldEditData = pEditCell->GetData()->Clone();
1398 pEditCell->RemoveCharAttribs(rAttr);
1399 pNewEditData = pEditCell->GetData()->Clone();
1402 aChangeRanges.Append( ScRange( nCol, nRow, nTab ) );
1403 ScPatternAttr* pOldPat = new ScPatternAttr(*pDoc->GetPattern( nCol, nRow, nTab ));
1405 pDoc->ApplyPattern( nCol, nRow, nTab, rAttr );
1407 const ScPatternAttr* pNewPat = pDoc->GetPattern( nCol, nRow, nTab );
1409 if (bRecord)
1411 ScUndoCursorAttr* pUndo = new ScUndoCursorAttr(
1412 pDocSh, nCol, nRow, nTab, pOldPat, pNewPat, &rAttr, false );
1413 pUndo->SetEditData(pOldEditData, pNewEditData);
1414 pDocSh->GetUndoManager()->AddUndoAction(pUndo);
1416 delete pOldPat; // wird im Undo kopiert (Pool)
1418 pDocSh->PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PAINT_GRID, nExtFlags | SC_PF_TESTMERGE );
1419 pDocSh->UpdateOle(GetViewData());
1420 aModificator.SetDocumentModified();
1421 CellContentChanged();
1424 // #i97876# Spreadsheet data changes are not notified
1425 ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
1426 if ( pModelObj && pModelObj->HasChangesListeners() )
1428 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aProperties;
1429 sal_Int32 nCount = 0;
1430 for ( USHORT nWhich = ATTR_PATTERN_START; nWhich <= ATTR_PATTERN_END; ++nWhich )
1432 const SfxPoolItem* pItem = 0;
1433 if ( rNewSet.GetItemState( nWhich, TRUE, &pItem ) == SFX_ITEM_SET && pItem )
1435 const SfxItemPropertyMap* pMap = ScCellObj::GetCellPropertyMap();
1436 while ( pMap->pName )
1438 if ( pMap->nWID == nWhich )
1440 ::com::sun::star::uno::Any aVal;
1441 pItem->QueryValue( aVal, pMap->nMemberId );
1442 aProperties.realloc( nCount + 1 );
1443 aProperties[ nCount ].Name = ::rtl::OUString::createFromAscii( pMap->pName );
1444 aProperties[ nCount ].Value <<= aVal;
1445 ++nCount;
1447 ++pMap;
1451 pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "attribute" ) ), aChangeRanges, aProperties );
1454 StartFormatArea();
1457 void ScViewFunc::ApplyUserItemSet( const SfxItemSet& rItemSet )
1459 // ItemSet from UI, may have different pool
1461 BOOL bOnlyNotBecauseOfMatrix;
1462 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
1464 ErrorMessage(STR_PROTECTIONERR);
1465 return;
1468 ScPatternAttr aNewAttrs( GetViewData()->GetDocument()->GetPool() );
1469 SfxItemSet& rNewSet = aNewAttrs.GetItemSet();
1470 rNewSet.Put( rItemSet, FALSE );
1471 ApplySelectionPattern( aNewAttrs );
1473 AdjustBlockHeight();
1476 const SfxStyleSheet* ScViewFunc::GetStyleSheetFromMarked()
1478 // Don't use UnmarkFiltered in slot state functions, for performance reasons.
1479 // The displayed state is always that of the whole selection including filtered rows.
1481 const ScStyleSheet* pSheet = NULL;
1482 ScViewData* pViewData = GetViewData();
1483 ScDocument* pDoc = pViewData->GetDocument();
1484 ScMarkData& rMark = pViewData->GetMarkData();
1486 if ( rMark.IsMarked() || rMark.IsMultiMarked() )
1487 pSheet = pDoc->GetSelectionStyle( rMark ); // MarkToMulti isn't necessary
1488 else
1489 pSheet = pDoc->GetStyle( pViewData->GetCurX(),
1490 pViewData->GetCurY(),
1491 pViewData->GetTabNo() );
1493 return pSheet;
1496 void ScViewFunc::SetStyleSheetToMarked( SfxStyleSheet* pStyleSheet, BOOL bRecord )
1498 // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
1499 BOOL bOnlyNotBecauseOfMatrix;
1500 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
1502 ErrorMessage(STR_PROTECTIONERR);
1503 return;
1506 if ( !pStyleSheet) return;
1507 // -------------------------------------------------------------------
1509 ScViewData* pViewData = GetViewData();
1510 ScDocShell* pDocSh = pViewData->GetDocShell();
1511 ScDocument* pDoc = pDocSh->GetDocument();
1512 ScMarkData aFuncMark( pViewData->GetMarkData() ); // local copy for UnmarkFiltered
1513 ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
1514 SCTAB nTabCount = pDoc->GetTableCount();
1515 if (bRecord && !pDoc->IsUndoEnabled())
1516 bRecord = FALSE;
1518 ScDocShellModificator aModificator( *pDocSh );
1520 if ( aFuncMark.IsMarked() || aFuncMark.IsMultiMarked() )
1522 ScRange aMarkRange;
1523 aFuncMark.MarkToMulti();
1524 aFuncMark.GetMultiMarkArea( aMarkRange );
1526 if ( bRecord )
1528 SCTAB nTab = pViewData->GetTabNo();
1529 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1530 pUndoDoc->InitUndo( pDoc, nTab, nTab );
1531 for (SCTAB i=0; i<nTabCount; i++)
1532 if (i != nTab && aFuncMark.GetTableSelect(i))
1533 pUndoDoc->AddUndoTab( i, i );
1535 ScRange aCopyRange = aMarkRange;
1536 aCopyRange.aStart.SetTab(0);
1537 aCopyRange.aEnd.SetTab(nTabCount-1);
1538 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, TRUE, pUndoDoc, &aFuncMark );
1539 aFuncMark.MarkToMulti();
1541 String aName = pStyleSheet->GetName();
1542 pDocSh->GetUndoManager()->AddUndoAction(
1543 new ScUndoSelectionStyle( pDocSh, aFuncMark, aMarkRange, aName, pUndoDoc ) );
1546 pDoc->ApplySelectionStyle( (ScStyleSheet&)*pStyleSheet, aFuncMark );
1548 if (!AdjustBlockHeight())
1549 pViewData->GetDocShell()->PostPaint( aMarkRange, PAINT_GRID );
1551 aFuncMark.MarkToSimple();
1553 else
1555 SCCOL nCol = pViewData->GetCurX();
1556 SCROW nRow = pViewData->GetCurY();
1557 SCTAB nTab = pViewData->GetTabNo();
1559 if ( bRecord )
1561 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1562 pUndoDoc->InitUndo( pDoc, nTab, nTab );
1563 for (SCTAB i=0; i<nTabCount; i++)
1564 if (i != nTab && aFuncMark.GetTableSelect(i))
1565 pUndoDoc->AddUndoTab( i, i );
1567 ScRange aCopyRange( nCol, nRow, 0, nCol, nRow, nTabCount-1 );
1568 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, FALSE, pUndoDoc );
1570 ScRange aMarkRange ( nCol, nRow, nTab );
1571 ScMarkData aUndoMark = aFuncMark;
1572 aUndoMark.SetMultiMarkArea( aMarkRange );
1574 String aName = pStyleSheet->GetName();
1575 pDocSh->GetUndoManager()->AddUndoAction(
1576 new ScUndoSelectionStyle( pDocSh, aUndoMark, aMarkRange, aName, pUndoDoc ) );
1579 for (SCTAB i=0; i<nTabCount; i++)
1580 if (aFuncMark.GetTableSelect(i))
1581 pDoc->ApplyStyle( nCol, nRow, i, (ScStyleSheet&)*pStyleSheet );
1583 if (!AdjustBlockHeight())
1584 pViewData->GetDocShell()->PostPaintCell( nCol, nRow, nTab );
1588 aModificator.SetDocumentModified();
1590 StartFormatArea();
1594 void ScViewFunc::RemoveStyleSheetInUse( SfxStyleSheet* pStyleSheet )
1596 if ( !pStyleSheet) return;
1597 // -------------------------------------------------------------------
1599 ScViewData* pViewData = GetViewData();
1600 ScDocument* pDoc = pViewData->GetDocument();
1601 ScDocShell* pDocSh = pViewData->GetDocShell();
1603 ScDocShellModificator aModificator( *pDocSh );
1605 VirtualDevice aVirtDev;
1606 aVirtDev.SetMapMode(MAP_PIXEL);
1607 pDoc->StyleSheetChanged( pStyleSheet, TRUE, &aVirtDev,
1608 pViewData->GetPPTX(),
1609 pViewData->GetPPTY(),
1610 pViewData->GetZoomX(),
1611 pViewData->GetZoomY() );
1613 pDocSh->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID|PAINT_LEFT );
1614 aModificator.SetDocumentModified();
1616 ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
1617 if (pHdl)
1618 pHdl->ForgetLastPattern();
1621 void ScViewFunc::UpdateStyleSheetInUse( SfxStyleSheet* pStyleSheet )
1623 if ( !pStyleSheet) return;
1624 // -------------------------------------------------------------------
1626 ScViewData* pViewData = GetViewData();
1627 ScDocument* pDoc = pViewData->GetDocument();
1628 ScDocShell* pDocSh = pViewData->GetDocShell();
1630 ScDocShellModificator aModificator( *pDocSh );
1632 VirtualDevice aVirtDev;
1633 aVirtDev.SetMapMode(MAP_PIXEL);
1634 pDoc->StyleSheetChanged( pStyleSheet, FALSE, &aVirtDev,
1635 pViewData->GetPPTX(),
1636 pViewData->GetPPTY(),
1637 pViewData->GetZoomX(),
1638 pViewData->GetZoomY() );
1640 pDocSh->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID|PAINT_LEFT );
1641 aModificator.SetDocumentModified();
1643 ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
1644 if (pHdl)
1645 pHdl->ForgetLastPattern();
1648 // Zellen einfuegen - Undo OK
1650 BOOL ScViewFunc::InsertCells( InsCellCmd eCmd, BOOL bRecord, BOOL bPartOfPaste )
1652 ScRange aRange;
1653 if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE)
1655 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1656 const ScMarkData& rMark = GetViewData()->GetMarkData();
1657 BOOL bSuccess = pDocSh->GetDocFunc().InsertCells( aRange, &rMark, eCmd, bRecord, FALSE, bPartOfPaste );
1658 if (bSuccess)
1660 pDocSh->UpdateOle(GetViewData());
1661 CellContentChanged();
1663 // #i97876# Spreadsheet data changes are not notified
1664 ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
1665 if ( pModelObj && pModelObj->HasChangesListeners() )
1667 if ( eCmd == INS_INSROWS || eCmd == INS_INSCOLS )
1669 ScRangeList aChangeRanges;
1670 aChangeRanges.Append( aRange );
1671 ::rtl::OUString aOperation = ( eCmd == INS_INSROWS ?
1672 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert-rows" ) ) :
1673 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert-columns" ) ) );
1674 pModelObj->NotifyChanges( aOperation, aChangeRanges );
1678 return bSuccess;
1680 else
1682 ErrorMessage(STR_NOMULTISELECT);
1683 return FALSE;
1687 // Zellen loeschen - Undo OK
1689 void ScViewFunc::DeleteCells( DelCellCmd eCmd, BOOL bRecord )
1691 ScRange aRange;
1692 if ( GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
1694 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1695 const ScMarkData& rMark = GetViewData()->GetMarkData();
1697 // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
1698 if ( pDocSh->IsDocShared() && ( eCmd == DEL_DELROWS || eCmd == DEL_DELCOLS ) )
1700 ScRange aDelRange( aRange.aStart );
1701 SCCOLROW nCount = 0;
1702 if ( eCmd == DEL_DELROWS )
1704 nCount = sal::static_int_cast< SCCOLROW >( aRange.aEnd.Row() - aRange.aStart.Row() + 1 );
1706 else
1708 nCount = sal::static_int_cast< SCCOLROW >( aRange.aEnd.Col() - aRange.aStart.Col() + 1 );
1710 while ( nCount > 0 )
1712 pDocSh->GetDocFunc().DeleteCells( aDelRange, &rMark, eCmd, bRecord, FALSE );
1713 --nCount;
1716 else
1718 pDocSh->GetDocFunc().DeleteCells( aRange, &rMark, eCmd, bRecord, FALSE );
1721 pDocSh->UpdateOle(GetViewData());
1722 CellContentChanged();
1724 // #i97876# Spreadsheet data changes are not notified
1725 ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
1726 if ( pModelObj && pModelObj->HasChangesListeners() )
1728 if ( eCmd == DEL_DELROWS || eCmd == DEL_DELCOLS )
1730 ScRangeList aChangeRanges;
1731 aChangeRanges.Append( aRange );
1732 ::rtl::OUString aOperation = ( eCmd == DEL_DELROWS ?
1733 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete-rows" ) ) :
1734 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete-columns" ) ) );
1735 pModelObj->NotifyChanges( aOperation, aChangeRanges );
1739 // #58106# Cursor direkt hinter den geloeschten Bereich setzen
1740 SCCOL nCurX = GetViewData()->GetCurX();
1741 SCROW nCurY = GetViewData()->GetCurY();
1742 if ( eCmd==DEL_CELLSLEFT || eCmd==DEL_DELCOLS )
1743 nCurX = aRange.aStart.Col();
1744 else
1745 nCurY = aRange.aStart.Row();
1746 SetCursor( nCurX, nCurY );
1748 else
1750 if (eCmd == DEL_DELCOLS)
1751 DeleteMulti( FALSE, bRecord );
1752 else if (eCmd == DEL_DELROWS)
1753 DeleteMulti( TRUE, bRecord );
1754 else
1755 ErrorMessage(STR_NOMULTISELECT);
1758 Unmark();
1761 void ScViewFunc::DeleteMulti( BOOL bRows, BOOL bRecord )
1763 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1764 ScDocShellModificator aModificator( *pDocSh );
1765 SCTAB nTab = GetViewData()->GetTabNo();
1766 ScDocument* pDoc = pDocSh->GetDocument();
1767 ScMarkData aFuncMark( GetViewData()->GetMarkData() ); // local copy for UnmarkFiltered
1768 ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
1770 if (bRecord && !pDoc->IsUndoEnabled())
1771 bRecord = FALSE;
1772 SCCOLROW* pRanges = new SCCOLROW[MAXCOLROWCOUNT];
1773 SCCOLROW nRangeCnt = bRows ? aFuncMark.GetMarkRowRanges( pRanges ) :
1774 aFuncMark.GetMarkColumnRanges( pRanges );
1775 if (nRangeCnt == 0)
1777 pRanges[0] = pRanges[1] = bRows ? static_cast<SCCOLROW>(GetViewData()->GetCurY()) : static_cast<SCCOLROW>(GetViewData()->GetCurX());
1778 nRangeCnt = 1;
1781 // Test ob erlaubt
1783 SCCOLROW* pOneRange = pRanges;
1784 USHORT nErrorId = 0;
1785 BOOL bNeedRefresh = FALSE;
1786 SCCOLROW nRangeNo;
1787 for (nRangeNo=0; nRangeNo<nRangeCnt && !nErrorId; nRangeNo++)
1789 SCCOLROW nStart = *(pOneRange++);
1790 SCCOLROW nEnd = *(pOneRange++);
1792 SCCOL nStartCol, nEndCol;
1793 SCROW nStartRow, nEndRow;
1794 if ( bRows )
1796 nStartCol = 0;
1797 nEndCol = MAXCOL;
1798 nStartRow = static_cast<SCROW>(nStart);
1799 nEndRow = static_cast<SCROW>(nEnd);
1801 else
1803 nStartCol = static_cast<SCCOL>(nStart);
1804 nEndCol = static_cast<SCCOL>(nEnd);
1805 nStartRow = 0;
1806 nEndRow = MAXROW;
1809 // cell protection (only needed for first range, as all following cells are moved)
1810 if ( nRangeNo == 0 )
1812 // test to the end of the sheet
1813 ScEditableTester aTester( pDoc, nTab, nStartCol, nStartRow, MAXCOL, MAXROW );
1814 if (!aTester.IsEditable())
1815 nErrorId = aTester.GetMessageId();
1818 // merged cells
1819 SCCOL nMergeStartX = nStartCol;
1820 SCROW nMergeStartY = nStartRow;
1821 SCCOL nMergeEndX = nEndCol;
1822 SCROW nMergeEndY = nEndRow;
1823 pDoc->ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, nTab );
1824 pDoc->ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, nTab );
1826 if ( nMergeStartX != nStartCol || nMergeStartY != nStartRow )
1828 // Disallow deleting parts of a merged cell.
1829 // Deleting the start is allowed (merge is removed), so the end doesn't have to be checked.
1831 nErrorId = STR_MSSG_DELETECELLS_0;
1833 if ( nMergeEndX != nEndCol || nMergeEndY != nEndRow )
1835 // detect if the start of a merged cell is deleted, so the merge flags can be refreshed
1837 bNeedRefresh = TRUE;
1841 if ( nErrorId )
1843 ErrorMessage( nErrorId );
1844 delete[] pRanges;
1845 return;
1848 // ausfuehren
1850 WaitObject aWait( GetFrameWin() ); // wichtig wegen TrackFormulas bei UpdateReference
1852 ScDocument* pUndoDoc = NULL;
1853 ScRefUndoData* pUndoData = NULL;
1854 if (bRecord)
1856 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1857 pUndoDoc->InitUndo( pDoc, nTab, nTab, !bRows, bRows ); // Zeilenhoehen
1859 pOneRange = pRanges;
1860 for (nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
1862 SCCOLROW nStart = *(pOneRange++);
1863 SCCOLROW nEnd = *(pOneRange++);
1864 if (bRows)
1865 pDoc->CopyToDocument( 0,nStart,nTab, MAXCOL,nEnd,nTab, IDF_ALL,FALSE,pUndoDoc );
1866 else
1867 pDoc->CopyToDocument( static_cast<SCCOL>(nStart),0,nTab,
1868 static_cast<SCCOL>(nEnd),MAXROW,nTab,
1869 IDF_ALL,FALSE,pUndoDoc );
1872 // alle Formeln wegen Referenzen
1873 SCTAB nTabCount = pDoc->GetTableCount();
1874 pUndoDoc->AddUndoTab( 0, nTabCount-1, FALSE, FALSE );
1875 pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,MAXTAB, IDF_FORMULA,FALSE,pUndoDoc );
1877 pUndoData = new ScRefUndoData( pDoc );
1879 pDoc->BeginDrawUndo();
1882 pOneRange = &pRanges[2*nRangeCnt]; // rueckwaerts
1883 for (nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
1885 SCCOLROW nEnd = *(--pOneRange);
1886 SCCOLROW nStart = *(--pOneRange);
1888 if (bRows)
1889 pDoc->DeleteRow( 0,nTab, MAXCOL,nTab, nStart, static_cast<SCSIZE>(nEnd-nStart+1) );
1890 else
1891 pDoc->DeleteCol( 0,nTab, MAXROW,nTab, static_cast<SCCOL>(nStart), static_cast<SCSIZE>(nEnd-nStart+1) );
1894 if (bNeedRefresh)
1896 SCCOLROW nFirstStart = pRanges[0];
1897 SCCOL nStartCol = bRows ? 0 : static_cast<SCCOL>(nFirstStart);
1898 SCROW nStartRow = bRows ? static_cast<SCROW>(nFirstStart) : 0;
1899 SCCOL nEndCol = MAXCOL;
1900 SCROW nEndRow = MAXROW;
1902 pDoc->RemoveFlagsTab( nStartCol, nStartRow, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
1903 pDoc->ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow, nTab, TRUE );
1906 if (bRecord)
1908 pDocSh->GetUndoManager()->AddUndoAction(
1909 new ScUndoDeleteMulti( pDocSh, bRows, bNeedRefresh, nTab, pRanges, nRangeCnt,
1910 pUndoDoc, pUndoData ) );
1913 if (!AdjustRowHeight(0, MAXROW))
1915 if (bRows)
1916 pDocSh->PostPaint( 0,pRanges[0],nTab, MAXCOL,MAXROW,nTab, PAINT_GRID | PAINT_LEFT );
1917 else
1918 pDocSh->PostPaint( static_cast<SCCOL>(pRanges[0]),0,nTab,
1919 MAXCOL,MAXROW,nTab, PAINT_GRID | PAINT_TOP );
1921 aModificator.SetDocumentModified();
1923 CellContentChanged();
1925 // #58106# Cursor direkt hinter den ersten geloeschten Bereich setzen
1926 SCCOL nCurX = GetViewData()->GetCurX();
1927 SCROW nCurY = GetViewData()->GetCurY();
1928 if ( bRows )
1929 nCurY = pRanges[0];
1930 else
1931 nCurX = static_cast<SCCOL>(pRanges[0]);
1932 SetCursor( nCurX, nCurY );
1934 delete[] pRanges;
1936 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
1939 // Inhalte loeschen
1941 void ScViewFunc::DeleteContents( USHORT nFlags, BOOL bRecord )
1943 GetViewData()->SetPasteMode( SC_PASTE_NONE );
1944 // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
1945 BOOL bOnlyNotBecauseOfMatrix;
1946 BOOL bEditable = SelectionEditable( &bOnlyNotBecauseOfMatrix );
1947 if ( !bEditable )
1949 if ( !(bOnlyNotBecauseOfMatrix &&
1950 ((nFlags & (IDF_ATTRIB | IDF_EDITATTR)) == nFlags)) )
1952 ErrorMessage(bOnlyNotBecauseOfMatrix ? STR_MATRIXFRAGMENTERR : STR_PROTECTIONERR);
1953 return;
1957 ScRange aMarkRange;
1958 BOOL bSimple = FALSE;
1960 ScDocument* pDoc = GetViewData()->GetDocument();
1961 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1962 ScMarkData aFuncMark( GetViewData()->GetMarkData() ); // local copy for UnmarkFiltered
1963 ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
1965 if (bRecord && !pDoc->IsUndoEnabled())
1966 bRecord = FALSE;
1968 ScDocShellModificator aModificator( *pDocSh );
1970 if ( !aFuncMark.IsMarked() && !aFuncMark.IsMultiMarked() )
1972 aMarkRange.aStart.SetCol(GetViewData()->GetCurX());
1973 aMarkRange.aStart.SetRow(GetViewData()->GetCurY());
1974 aMarkRange.aStart.SetTab(GetViewData()->GetTabNo());
1975 aMarkRange.aEnd = aMarkRange.aStart;
1976 if ( pDoc->HasAttrib( aMarkRange, HASATTR_MERGED ) )
1978 // InitOwnBlockMode();
1979 aFuncMark.SetMarkArea( aMarkRange );
1981 else
1982 bSimple = TRUE;
1985 aFuncMark.SetMarking(FALSE); // for MarkToMulti
1986 aFuncMark.MarkToSimple(); // before bMulti test below
1988 DBG_ASSERT( aFuncMark.IsMarked() || aFuncMark.IsMultiMarked() || bSimple, "delete what?" );
1990 ScDocument* pUndoDoc = NULL;
1991 BOOL bMulti = !bSimple && aFuncMark.IsMultiMarked();
1992 if (!bSimple)
1994 aFuncMark.MarkToMulti();
1995 aFuncMark.GetMultiMarkArea( aMarkRange );
1997 ScRange aExtendedRange(aMarkRange);
1998 if (!bSimple)
2000 if ( pDoc->ExtendMerge( aExtendedRange, TRUE ) )
2001 bMulti = FALSE;
2004 // keine Objekte auf geschuetzten Tabellen
2005 BOOL bObjects = FALSE;
2006 if ( nFlags & IDF_OBJECTS )
2008 bObjects = TRUE;
2009 SCTAB nTabCount = pDoc->GetTableCount();
2010 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
2011 if (aFuncMark.GetTableSelect(nTab) && pDoc->IsTabProtected(nTab))
2012 bObjects = FALSE;
2015 USHORT nExtFlags = 0; // extra flags are needed only if attributes are deleted
2016 if ( nFlags & IDF_ATTRIB )
2017 pDocSh->UpdatePaintExt( nExtFlags, aMarkRange );
2019 // Reihenfolge:
2020 // 1) BeginDrawUndo
2021 // 2) Objekte loeschen (DrawUndo wird gefuellt)
2022 // 3) Inhalte fuer Undo kopieren
2023 // 4) Inhalte loeschen
2024 // 5) Undo-Aktion anlegen
2026 BOOL bDrawUndo = bObjects || ( nFlags & IDF_NOTE ); // needed for shown notes
2027 if ( bDrawUndo && bRecord )
2028 pDoc->BeginDrawUndo();
2030 if (bObjects)
2032 if (bMulti)
2033 pDoc->DeleteObjectsInSelection( aFuncMark );
2034 else
2035 pDoc->DeleteObjectsInArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
2036 /*!*/ aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(),
2037 aFuncMark );
2040 if ( bRecord )
2042 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2043 SCTAB nTab = aMarkRange.aStart.Tab();
2044 pUndoDoc->InitUndo( pDoc, nTab, nTab );
2045 SCTAB nTabCount = pDoc->GetTableCount();
2046 for (SCTAB i=0; i<nTabCount; i++)
2047 if (i != nTab && aFuncMark.GetTableSelect(i))
2048 pUndoDoc->AddUndoTab( i, i );
2049 ScRange aCopyRange = aExtendedRange;
2050 aCopyRange.aStart.SetTab(0);
2051 aCopyRange.aEnd.SetTab(nTabCount-1);
2053 // bei "Format/Standard" alle Attribute kopieren, weil CopyToDocument
2054 // nur mit IDF_HARDATTR zu langsam ist:
2055 USHORT nUndoDocFlags = nFlags;
2056 if (nFlags & IDF_ATTRIB)
2057 nUndoDocFlags |= IDF_ATTRIB;
2058 if (nFlags & IDF_EDITATTR) // Edit-Engine-Attribute
2059 nUndoDocFlags |= IDF_STRING; // -> Zellen werden geaendert
2060 if (nFlags & IDF_NOTE)
2061 nUndoDocFlags |= IDF_CONTENTS; // #68795# copy all cells with their notes
2062 // do not copy note captions to undo document
2063 nUndoDocFlags |= IDF_NOCAPTIONS;
2064 pDoc->CopyToDocument( aCopyRange, nUndoDocFlags, bMulti, pUndoDoc, &aFuncMark );
2067 HideAllCursors(); // falls Zusammenfassung aufgehoben wird
2068 if (bSimple)
2069 pDoc->DeleteArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
2070 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(),
2071 aFuncMark, nFlags );
2072 else
2074 pDoc->DeleteSelection( nFlags, aFuncMark );
2075 // aFuncMark.MarkToSimple();
2078 if ( bRecord )
2080 pDocSh->GetUndoManager()->AddUndoAction(
2081 new ScUndoDeleteContents( pDocSh, aFuncMark, aExtendedRange,
2082 pUndoDoc, bMulti, nFlags, bDrawUndo ) );
2085 if (!AdjustRowHeight( aExtendedRange.aStart.Row(), aExtendedRange.aEnd.Row() ))
2086 pDocSh->PostPaint( aExtendedRange, PAINT_GRID, nExtFlags );
2088 pDocSh->UpdateOle(GetViewData());
2090 // #i97876# Spreadsheet data changes are not notified
2091 ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
2092 if ( pModelObj && pModelObj->HasChangesListeners() )
2094 ScRangeList aChangeRanges;
2095 if ( bSimple )
2097 aChangeRanges.Append( aMarkRange );
2099 else
2101 aFuncMark.FillRangeListWithMarks( &aChangeRanges, FALSE );
2103 pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges );
2106 aModificator.SetDocumentModified();
2107 CellContentChanged();
2108 ShowAllCursors();
2110 if ( nFlags & IDF_ATTRIB )
2112 if ( nFlags & IDF_CONTENTS )
2113 ForgetFormatArea();
2114 else
2115 StartFormatArea(); // Attribute loeschen ist auch Attributierung
2119 // Spaltenbreiten/Zeilenhoehen (ueber Header) - Undo OK
2121 void ScViewFunc::SetWidthOrHeight( BOOL bWidth, SCCOLROW nRangeCnt, SCCOLROW* pRanges,
2122 ScSizeMode eMode, USHORT nSizeTwips,
2123 BOOL bRecord, BOOL bPaint, ScMarkData* pMarkData )
2125 if (nRangeCnt == 0)
2126 return;
2128 // use view's mark if none specified
2129 if ( !pMarkData )
2130 pMarkData = &GetViewData()->GetMarkData();
2132 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2133 ScDocument* pDoc = pDocSh->GetDocument();
2134 SCTAB nTabCount = pDoc->GetTableCount();
2135 SCTAB nFirstTab = pMarkData->GetFirstSelected();
2136 SCTAB nCurTab = GetViewData()->GetTabNo();
2137 SCTAB nTab;
2138 if (bRecord && !pDoc->IsUndoEnabled())
2139 bRecord = FALSE;
2141 ScDocShellModificator aModificator( *pDocSh );
2143 BOOL bAllowed = TRUE;
2144 for (nTab=0; nTab<nTabCount && bAllowed; nTab++)
2145 if (pMarkData->GetTableSelect(nTab))
2147 for ( SCCOLROW i=0; i<nRangeCnt && bAllowed; i++ )
2149 BOOL bOnlyMatrix;
2150 if (bWidth)
2151 bAllowed = pDoc->IsBlockEditable( nTab,
2152 static_cast<SCCOL>(pRanges[2*i]),0,
2153 static_cast<SCCOL>(pRanges[2*i+1]),MAXROW,
2154 &bOnlyMatrix ) || bOnlyMatrix;
2155 else
2156 bAllowed = pDoc->IsBlockEditable( nTab, 0,pRanges[2*i],
2157 MAXCOL,pRanges[2*i+1], &bOnlyMatrix ) ||
2158 bOnlyMatrix;
2162 // Allow users to resize cols/rows in readonly docs despite the r/o state.
2163 // It is frustrating to be unable to see content in mis-sized cells.
2164 if( !bAllowed && !pDocSh->IsReadOnly() )
2166 ErrorMessage(STR_PROTECTIONERR);
2167 return;
2170 SCCOLROW nStart = pRanges[0];
2171 SCCOLROW nEnd = pRanges[2*nRangeCnt-1];
2173 BOOL bFormula = FALSE;
2174 if ( eMode == SC_SIZE_OPTIMAL )
2176 const ScViewOptions& rOpts = GetViewData()->GetOptions();
2177 bFormula = rOpts.GetOption( VOPT_FORMULAS );
2180 ScDocument* pUndoDoc = NULL;
2181 ScOutlineTable* pUndoTab = NULL;
2182 SCCOLROW* pUndoRanges = NULL;
2184 if ( bRecord )
2186 pDoc->BeginDrawUndo(); // Drawing Updates
2188 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2189 for (nTab=0; nTab<nTabCount; nTab++)
2190 if (pMarkData->GetTableSelect(nTab))
2192 if (bWidth)
2194 if ( nTab == nFirstTab )
2195 pUndoDoc->InitUndo( pDoc, nTab, nTab, TRUE, FALSE );
2196 else
2197 pUndoDoc->AddUndoTab( nTab, nTab, TRUE, FALSE );
2198 pDoc->CopyToDocument( static_cast<SCCOL>(nStart), 0, nTab,
2199 static_cast<SCCOL>(nEnd), MAXROW, nTab, IDF_NONE,
2200 FALSE, pUndoDoc );
2202 else
2204 if ( nTab == nFirstTab )
2205 pUndoDoc->InitUndo( pDoc, nTab, nTab, FALSE, TRUE );
2206 else
2207 pUndoDoc->AddUndoTab( nTab, nTab, FALSE, TRUE );
2208 pDoc->CopyToDocument( 0, nStart, nTab, MAXCOL, nEnd, nTab, IDF_NONE, FALSE, pUndoDoc );
2212 pUndoRanges = new SCCOLROW[ 2*nRangeCnt ];
2213 memmove( pUndoRanges, pRanges, 2*nRangeCnt*sizeof(SCCOLROW) );
2215 //! outlines from all tables?
2216 ScOutlineTable* pTable = pDoc->GetOutlineTable( nCurTab );
2217 if (pTable)
2218 pUndoTab = new ScOutlineTable( *pTable );
2221 if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
2222 pMarkData->MarkToMulti();
2224 BOOL bShow = nSizeTwips > 0 || eMode != SC_SIZE_DIRECT;
2225 BOOL bOutline = FALSE;
2227 for (nTab=0; nTab<nTabCount; nTab++)
2228 if (pMarkData->GetTableSelect(nTab))
2230 const SCCOLROW* pTabRanges = pRanges;
2232 pDoc->IncSizeRecalcLevel( nTab ); // nicht fuer jede Spalte einzeln
2233 for (SCCOLROW nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
2235 SCCOLROW nStartNo = *(pTabRanges++);
2236 SCCOLROW nEndNo = *(pTabRanges++);
2238 if ( !bWidth ) // Hoehen immer blockweise
2240 if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
2242 BOOL bAll = ( eMode==SC_SIZE_OPTIMAL );
2243 if (!bAll)
2245 // fuer alle eingeblendeten CR_MANUALSIZE loeschen,
2246 // dann SetOptimalHeight mit bShrink = FALSE
2247 for (SCROW nRow = nStartNo; nRow <= nEndNo; ++nRow)
2249 SCROW nLastRow = nRow;
2250 if (pDoc->RowHidden(nRow, nTab, NULL, &nLastRow))
2252 nRow = nLastRow;
2253 continue;
2256 BYTE nOld = pDoc->GetRowFlags(nRow, nTab);
2257 if (nOld & CR_MANUALSIZE)
2258 pDoc->SetRowFlags(nRow, nTab, nOld & ~CR_MANUALSIZE);
2262 double nPPTX = GetViewData()->GetPPTX();
2263 double nPPTY = GetViewData()->GetPPTY();
2264 Fraction aZoomX = GetViewData()->GetZoomX();
2265 Fraction aZoomY = GetViewData()->GetZoomY();
2267 ScSizeDeviceProvider aProv(pDocSh);
2268 if (aProv.IsPrinter())
2270 nPPTX = aProv.GetPPTX();
2271 nPPTY = aProv.GetPPTY();
2272 aZoomX = aZoomY = Fraction( 1, 1 );
2275 pDoc->SetOptimalHeight( nStartNo, nEndNo, nTab, nSizeTwips, aProv.GetDevice(),
2276 nPPTX, nPPTY, aZoomX, aZoomY, bAll );
2277 if (bAll)
2278 pDoc->ShowRows( nStartNo, nEndNo, nTab, TRUE );
2280 // Manual-Flag wird bei bAll=TRUE schon in SetOptimalHeight gesetzt
2281 // (an bei Extra-Height, sonst aus).
2283 else if ( eMode==SC_SIZE_DIRECT )
2285 if (nSizeTwips)
2287 pDoc->SetRowHeightRange( nStartNo, nEndNo, nTab, nSizeTwips );
2288 pDoc->SetManualHeight( nStartNo, nEndNo, nTab, TRUE ); // height was set manually
2290 pDoc->ShowRows( nStartNo, nEndNo, nTab, nSizeTwips != 0 );
2292 else if ( eMode==SC_SIZE_SHOW )
2294 pDoc->ShowRows( nStartNo, nEndNo, nTab, TRUE );
2297 else // Spaltenbreiten
2299 for (SCCOL nCol=static_cast<SCCOL>(nStartNo); nCol<=static_cast<SCCOL>(nEndNo); nCol++)
2301 if ( eMode != SC_SIZE_VISOPT || !pDoc->ColHidden(nCol, nTab) )
2303 USHORT nThisSize = nSizeTwips;
2305 if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
2306 nThisSize = nSizeTwips + GetOptimalColWidth( nCol, nTab, bFormula );
2307 if ( nThisSize )
2308 pDoc->SetColWidth( nCol, nTab, nThisSize );
2310 pDoc->ShowCol( nCol, nTab, bShow );
2315 // Outline anpassen
2317 if (bWidth)
2319 if ( pDoc->UpdateOutlineCol( static_cast<SCCOL>(nStartNo),
2320 static_cast<SCCOL>(nEndNo), nTab, bShow ) )
2321 bOutline = TRUE;
2323 else
2325 if ( pDoc->UpdateOutlineRow( nStartNo, nEndNo, nTab, bShow ) )
2326 bOutline = TRUE;
2329 pDoc->DecSizeRecalcLevel( nTab ); // nicht fuer jede Spalte einzeln
2333 if (!bOutline)
2334 DELETEZ(pUndoTab);
2336 if (bRecord)
2338 pDocSh->GetUndoManager()->AddUndoAction(
2339 new ScUndoWidthOrHeight( pDocSh, *pMarkData,
2340 nStart, nCurTab, nEnd, nCurTab,
2341 pUndoDoc, nRangeCnt, pUndoRanges,
2342 pUndoTab, eMode, nSizeTwips, bWidth ) );
2345 for (nTab=0; nTab<nTabCount; nTab++)
2346 if (pMarkData->GetTableSelect(nTab))
2347 pDoc->UpdatePageBreaks( nTab );
2349 GetViewData()->GetView()->UpdateScrollBars();
2351 if (bPaint)
2353 HideCursor();
2355 for (nTab=0; nTab<nTabCount; nTab++)
2356 if (pMarkData->GetTableSelect(nTab))
2358 if (bWidth)
2360 if (pDoc->HasAttrib( static_cast<SCCOL>(nStart),0,nTab,
2361 static_cast<SCCOL>(nEnd),MAXROW,nTab,
2362 HASATTR_MERGED | HASATTR_OVERLAPPED ))
2363 nStart = 0;
2364 if (nStart > 0) // weiter oben anfangen wegen Linien und Cursor
2365 --nStart;
2366 pDocSh->PostPaint( static_cast<SCCOL>(nStart), 0, nTab,
2367 MAXCOL, MAXROW, nTab, PAINT_GRID | PAINT_TOP );
2369 else
2371 if (pDoc->HasAttrib( 0,nStart,nTab, MAXCOL,nEnd,nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ))
2372 nStart = 0;
2373 if (nStart != 0)
2374 --nStart;
2375 pDocSh->PostPaint( 0, nStart, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID | PAINT_LEFT );
2379 pDocSh->UpdateOle(GetViewData());
2380 if( !pDocSh->IsReadOnly() )
2381 aModificator.SetDocumentModified();
2383 ShowCursor();
2386 // #i97876# Spreadsheet data changes are not notified
2387 if ( bWidth )
2389 ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
2390 if ( pModelObj && pModelObj->HasChangesListeners() )
2392 ScRangeList aChangeRanges;
2393 for ( nTab = 0; nTab < nTabCount; ++nTab )
2395 if ( pMarkData->GetTableSelect( nTab ) )
2397 const SCCOLROW* pTabRanges = pRanges;
2398 for ( SCCOLROW nRange = 0; nRange < nRangeCnt; ++nRange )
2400 SCCOL nStartCol = static_cast< SCCOL >( *(pTabRanges++) );
2401 SCCOL nEndCol = static_cast< SCCOL >( *(pTabRanges++) );
2402 for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol )
2404 aChangeRanges.Append( ScRange( nCol, 0, nTab ) );
2409 pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "column-resize" ) ), aChangeRanges );
2414 // Spaltenbreiten/Zeilenhoehen (ueber Blockmarken)
2416 void ScViewFunc::SetMarkedWidthOrHeight( BOOL bWidth, ScSizeMode eMode, USHORT nSizeTwips,
2417 BOOL bRecord, BOOL bPaint )
2419 ScMarkData& rMark = GetViewData()->GetMarkData();
2421 rMark.MarkToMulti();
2422 if (!rMark.IsMultiMarked())
2424 SCCOL nCol = GetViewData()->GetCurX();
2425 SCROW nRow = GetViewData()->GetCurY();
2426 SCTAB nTab = GetViewData()->GetTabNo();
2427 DoneBlockMode();
2428 InitOwnBlockMode();
2429 rMark.SetMultiMarkArea( ScRange( nCol,nRow,nTab ), TRUE );
2430 MarkDataChanged();
2433 SCCOLROW* pRanges = new SCCOLROW[MAXCOLROWCOUNT];
2434 SCCOLROW nRangeCnt = 0;
2436 if ( bWidth )
2437 nRangeCnt = rMark.GetMarkColumnRanges( pRanges );
2438 else
2439 nRangeCnt = rMark.GetMarkRowRanges( pRanges );
2441 SetWidthOrHeight( bWidth, nRangeCnt, pRanges, eMode, nSizeTwips, bRecord, bPaint );
2443 delete[] pRanges;
2444 rMark.MarkToSimple();
2447 void ScViewFunc::ModifyCellSize( ScDirection eDir, BOOL bOptimal )
2449 //! Schrittweiten einstellbar
2450 // Schrittweite ist auch Minimum
2451 USHORT nStepX = STD_COL_WIDTH / 5;
2452 USHORT nStepY = ScGlobal::nStdRowHeight;
2454 ScModule* pScMod = SC_MOD();
2455 BOOL bAnyEdit = pScMod->IsInputMode();
2456 SCCOL nCol = GetViewData()->GetCurX();
2457 SCROW nRow = GetViewData()->GetCurY();
2458 SCTAB nTab = GetViewData()->GetTabNo();
2459 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2460 ScDocument* pDoc = pDocSh->GetDocument();
2462 BOOL bAllowed, bOnlyMatrix;
2463 if ( eDir == DIR_LEFT || eDir == DIR_RIGHT )
2464 bAllowed = pDoc->IsBlockEditable( nTab, nCol,0, nCol,MAXROW, &bOnlyMatrix );
2465 else
2466 bAllowed = pDoc->IsBlockEditable( nTab, 0,nRow, MAXCOL,nRow, &bOnlyMatrix );
2467 if ( !bAllowed && !bOnlyMatrix )
2469 ErrorMessage(STR_PROTECTIONERR);
2470 return;
2473 HideAllCursors();
2475 USHORT nWidth = pDoc->GetColWidth( nCol, nTab );
2476 USHORT nHeight = pDoc->GetRowHeight( nRow, nTab );
2477 SCCOLROW nRange[2];
2478 if ( eDir == DIR_LEFT || eDir == DIR_RIGHT )
2480 if (bOptimal) // Breite dieser einen Zelle
2482 if ( bAnyEdit )
2484 // beim Editieren die aktuelle Breite der Eingabe
2485 ScInputHandler* pHdl = pScMod->GetInputHdl( GetViewData()->GetViewShell() );
2486 if (pHdl)
2488 long nEdit = pHdl->GetTextSize().Width(); // in 1/100mm
2490 const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
2491 const SvxMarginItem& rMItem =
2492 (const SvxMarginItem&)pPattern->GetItem(ATTR_MARGIN);
2493 USHORT nMargin = rMItem.GetLeftMargin() + rMItem.GetRightMargin();
2494 if ( ((const SvxHorJustifyItem&) pPattern->
2495 GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_LEFT )
2496 nMargin = sal::static_int_cast<USHORT>(
2497 nMargin + ((const SfxUInt16Item&)pPattern->GetItem(ATTR_INDENT)).GetValue() );
2499 nWidth = (USHORT)(nEdit * pDocSh->GetOutputFactor() / HMM_PER_TWIPS)
2500 + nMargin + STD_EXTRA_WIDTH;
2503 else
2505 double nPPTX = GetViewData()->GetPPTX();
2506 double nPPTY = GetViewData()->GetPPTY();
2507 Fraction aZoomX = GetViewData()->GetZoomX();
2508 Fraction aZoomY = GetViewData()->GetZoomY();
2510 ScSizeDeviceProvider aProv(pDocSh);
2511 if (aProv.IsPrinter())
2513 nPPTX = aProv.GetPPTX();
2514 nPPTY = aProv.GetPPTY();
2515 aZoomX = aZoomY = Fraction( 1, 1 );
2518 long nPixel = pDoc->GetNeededSize( nCol, nRow, nTab, aProv.GetDevice(),
2519 nPPTX, nPPTY, aZoomX, aZoomY, TRUE );
2520 USHORT nTwips = (USHORT)( nPixel / nPPTX );
2521 if (nTwips != 0)
2522 nWidth = nTwips + STD_EXTRA_WIDTH;
2523 else
2524 nWidth = STD_COL_WIDTH;
2527 else // vergroessern / verkleinern
2529 if ( eDir == DIR_RIGHT )
2530 nWidth = sal::static_int_cast<USHORT>( nWidth + nStepX );
2531 else if ( nWidth > nStepX )
2532 nWidth = sal::static_int_cast<USHORT>( nWidth - nStepX );
2533 if ( nWidth < nStepX ) nWidth = nStepX;
2534 if ( nWidth > MAX_COL_WIDTH ) nWidth = MAX_COL_WIDTH;
2536 nRange[0] = nRange[1] = nCol;
2537 SetWidthOrHeight( TRUE, 1, nRange, SC_SIZE_DIRECT, nWidth );
2539 // hier bei Breite auch Hoehe anpassen (nur die eine Zeile)
2541 if (!bAnyEdit)
2543 const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
2544 BOOL bNeedHeight =
2545 ((const SfxBoolItem&)pPattern->GetItem( ATTR_LINEBREAK )).GetValue() ||
2546 ((const SvxHorJustifyItem&)pPattern->
2547 GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_BLOCK;
2548 if (bNeedHeight)
2549 AdjustRowHeight( nRow, nRow );
2552 else
2554 ScSizeMode eMode;
2555 if (bOptimal)
2557 eMode = SC_SIZE_OPTIMAL;
2558 nHeight = 0;
2560 else
2562 eMode = SC_SIZE_DIRECT;
2563 if ( eDir == DIR_BOTTOM )
2564 nHeight = sal::static_int_cast<USHORT>( nHeight + nStepY );
2565 else if ( nHeight > nStepY )
2566 nHeight = sal::static_int_cast<USHORT>( nHeight - nStepY );
2567 if ( nHeight < nStepY ) nHeight = nStepY;
2568 if ( nHeight > MAX_COL_HEIGHT ) nHeight = MAX_COL_HEIGHT;
2569 //! MAX_COL_HEIGHT umbenennen in MAX_ROW_HEIGHT in global.hxx !!!!!!
2571 nRange[0] = nRange[1] = nRow;
2572 SetWidthOrHeight( FALSE, 1, nRange, eMode, nHeight );
2575 if ( bAnyEdit )
2577 UpdateEditView();
2578 if ( pDoc->HasAttrib( nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_NEEDHEIGHT ) )
2580 ScInputHandler* pHdl = pScMod->GetInputHdl( GetViewData()->GetViewShell() );
2581 if (pHdl)
2582 pHdl->SetModified(); // damit bei Enter die Hoehe angepasst wird
2586 ShowAllCursors();
2589 void ScViewFunc::ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect )
2591 if (nTab == TABLEID_DOC)
2592 return;
2594 ScMarkData& rMark = GetViewData()->GetMarkData();
2595 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2596 ScDocument* pDoc = pDocSh->GetDocument();
2597 ScDocFunc aFunc(*pDocSh);
2598 bool bUndo(pDoc->IsUndoEnabled());
2600 // modifying several tables is handled here
2602 if (bUndo)
2604 String aUndo = ScGlobal::GetRscString( STR_UNDO_PROTECT_TAB );
2605 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
2608 SCTAB nCount = pDocSh->GetDocument()->GetTableCount();
2609 for ( SCTAB i=0; i<nCount; i++ )
2610 if ( rMark.GetTableSelect(i) )
2611 aFunc.ProtectSheet(i, rProtect);
2613 if (bUndo)
2614 pDocSh->GetUndoManager()->LeaveListAction();
2616 UpdateLayerLocks(); //! broadcast to all views
2619 void ScViewFunc::Protect( SCTAB nTab, const String& rPassword )
2621 ScMarkData& rMark = GetViewData()->GetMarkData();
2622 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2623 ScDocument* pDoc = pDocSh->GetDocument();
2624 ScDocFunc aFunc(*pDocSh);
2625 BOOL bUndo(pDoc->IsUndoEnabled());
2627 if ( nTab == TABLEID_DOC || rMark.GetSelectCount() <= 1 )
2628 aFunc.Protect( nTab, rPassword, FALSE );
2629 else
2631 // modifying several tables is handled here
2633 if (bUndo)
2635 String aUndo = ScGlobal::GetRscString( STR_UNDO_PROTECT_TAB );
2636 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
2639 SCTAB nCount = pDocSh->GetDocument()->GetTableCount();
2640 for ( SCTAB i=0; i<nCount; i++ )
2641 if ( rMark.GetTableSelect(i) )
2642 aFunc.Protect( i, rPassword, FALSE );
2644 if (bUndo)
2645 pDocSh->GetUndoManager()->LeaveListAction();
2648 UpdateLayerLocks(); //! broadcast to all views
2651 BOOL ScViewFunc::Unprotect( SCTAB nTab, const String& rPassword )
2653 ScMarkData& rMark = GetViewData()->GetMarkData();
2654 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2655 ScDocument* pDoc = pDocSh->GetDocument();
2656 ScDocFunc aFunc(*pDocSh);
2657 BOOL bChanged = FALSE;
2658 BOOL bUndo (pDoc->IsUndoEnabled());
2660 if ( nTab == TABLEID_DOC || rMark.GetSelectCount() <= 1 )
2661 bChanged = aFunc.Unprotect( nTab, rPassword, FALSE );
2662 else
2664 // modifying several tables is handled here
2666 if (bUndo)
2668 String aUndo = ScGlobal::GetRscString( STR_UNDO_UNPROTECT_TAB );
2669 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
2672 SCTAB nCount = pDocSh->GetDocument()->GetTableCount();
2673 for ( SCTAB i=0; i<nCount; i++ )
2674 if ( rMark.GetTableSelect(i) )
2675 if ( aFunc.Unprotect( i, rPassword, FALSE ) )
2676 bChanged = TRUE;
2678 if (bUndo)
2679 pDocSh->GetUndoManager()->LeaveListAction();
2682 if (bChanged)
2683 UpdateLayerLocks(); //! broadcast to all views
2685 return bChanged;
2688 void ScViewFunc::SetNoteText( const ScAddress& rPos, const String& rNoteText )
2690 GetViewData()->GetDocShell()->GetDocFunc().SetNoteText( rPos, rNoteText, FALSE );
2693 void ScViewFunc::ReplaceNote( const ScAddress& rPos, const String& rNoteText, const String* pAuthor, const String* pDate )
2695 GetViewData()->GetDocShell()->GetDocFunc().ReplaceNote( rPos, rNoteText, pAuthor, pDate, FALSE );
2698 void ScViewFunc::SetNumberFormat( short nFormatType, ULONG nAdd )
2700 // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
2701 BOOL bOnlyNotBecauseOfMatrix;
2702 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
2704 ErrorMessage(STR_PROTECTIONERR);
2705 return;
2708 sal_uInt32 nNumberFormat = 0;
2709 ScViewData* pViewData = GetViewData();
2710 ScDocument* pDoc = pViewData->GetDocument();
2711 SvNumberFormatter* pNumberFormatter = pDoc->GetFormatTable();
2712 LanguageType eLanguage = ScGlobal::eLnge;
2713 ScPatternAttr aNewAttrs( pDoc->GetPool() );
2715 // #67936# always take language from cursor position, even if there is a selection
2717 sal_uInt32 nCurrentNumberFormat;
2718 pDoc->GetNumberFormat( pViewData->GetCurX(),
2719 pViewData->GetCurY(),
2720 pViewData->GetTabNo(),
2721 nCurrentNumberFormat );
2722 const SvNumberformat* pEntry = pNumberFormatter->GetEntry( nCurrentNumberFormat );
2723 if (pEntry)
2724 eLanguage = pEntry->GetLanguage(); // sonst ScGlobal::eLnge behalten
2726 nNumberFormat = pNumberFormatter->GetStandardFormat( nFormatType, eLanguage ) + nAdd;
2728 SfxItemSet& rSet = aNewAttrs.GetItemSet();
2729 rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNumberFormat ) );
2730 // ATTR_LANGUAGE_FORMAT nicht
2731 ApplySelectionPattern( aNewAttrs, TRUE );
2734 void ScViewFunc::SetNumFmtByStr( const String& rCode )
2736 // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
2737 BOOL bOnlyNotBecauseOfMatrix;
2738 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
2740 ErrorMessage(STR_PROTECTIONERR);
2741 return;
2744 ScViewData* pViewData = GetViewData();
2745 ScDocument* pDoc = pViewData->GetDocument();
2746 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
2748 // Sprache immer von Cursorposition
2750 sal_uInt32 nCurrentNumberFormat;
2751 pDoc->GetNumberFormat( pViewData->GetCurX(), pViewData->GetCurY(),
2752 pViewData->GetTabNo(), nCurrentNumberFormat );
2753 const SvNumberformat* pEntry = pFormatter->GetEntry( nCurrentNumberFormat );
2754 LanguageType eLanguage = pEntry ? pEntry->GetLanguage() : ScGlobal::eLnge;
2756 // Index fuer String bestimmen
2758 BOOL bOk = TRUE;
2759 sal_uInt32 nNumberFormat = pFormatter->GetEntryKey( rCode, eLanguage );
2760 if ( nNumberFormat == NUMBERFORMAT_ENTRY_NOT_FOUND )
2762 // neu eintragen
2764 String aFormat = rCode; // wird veraendert
2765 xub_StrLen nErrPos = 0;
2766 short nType = 0; //! ???
2767 bOk = pFormatter->PutEntry( aFormat, nErrPos, nType, nNumberFormat, eLanguage );
2770 if ( bOk ) // gueltiges Format?
2772 ScPatternAttr aNewAttrs( pDoc->GetPool() );
2773 SfxItemSet& rSet = aNewAttrs.GetItemSet();
2774 rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNumberFormat ) );
2775 rSet.Put( SvxLanguageItem( eLanguage, ATTR_LANGUAGE_FORMAT ) );
2776 ApplySelectionPattern( aNewAttrs, TRUE );
2779 //! sonst Fehler zuerueckgeben / Meldung ausgeben ???
2782 void ScViewFunc::ChangeNumFmtDecimals( BOOL bIncrement )
2784 // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
2785 BOOL bOnlyNotBecauseOfMatrix;
2786 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
2788 ErrorMessage(STR_PROTECTIONERR);
2789 return;
2792 ScDocument* pDoc = GetViewData()->GetDocument();
2793 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
2795 SCCOL nCol = GetViewData()->GetCurX();
2796 SCROW nRow = GetViewData()->GetCurY();
2797 SCTAB nTab = GetViewData()->GetTabNo();
2799 sal_uInt32 nOldFormat;
2800 pDoc->GetNumberFormat( nCol, nRow, nTab, nOldFormat );
2801 const SvNumberformat* pOldEntry = pFormatter->GetEntry( nOldFormat );
2802 if (!pOldEntry)
2804 DBG_ERROR("Zahlformat nicht gefunden !!!");
2805 return;
2808 // was haben wir denn da?
2810 sal_uInt32 nNewFormat = nOldFormat;
2811 BOOL bError = FALSE;
2813 LanguageType eLanguage = pOldEntry->GetLanguage();
2814 BOOL bThousand, bNegRed;
2815 USHORT nPrecision, nLeading;
2816 pOldEntry->GetFormatSpecialInfo( bThousand, bNegRed, nPrecision, nLeading );
2818 short nOldType = pOldEntry->GetType();
2819 if ( 0 == ( nOldType & (
2820 NUMBERFORMAT_NUMBER | NUMBERFORMAT_CURRENCY | NUMBERFORMAT_PERCENT ) ) )
2822 // Datum, Zeit, Bruch, logisch, Text kann nicht angepasst werden
2823 //! bei Wisssenschaftlich kann es der Numberformatter auch nicht
2824 bError = TRUE;
2827 //! Das SvNumberformat hat einen Member bStandard, verraet ihn aber nicht
2828 BOOL bWasStandard = ( nOldFormat == pFormatter->GetStandardIndex( eLanguage ) );
2829 if (bWasStandard)
2831 // bei "Standard" die Nachkommastellen abhaengig vom Zellinhalt
2832 // 0 bei leer oder Text -> keine Nachkommastellen
2833 double nVal = pDoc->GetValue( ScAddress( nCol, nRow, nTab ) );
2835 // Die Wege des Numberformatters sind unergruendlich, darum ausprobieren:
2836 String aOut;
2837 Color* pCol;
2838 ((SvNumberformat*)pOldEntry)->GetOutputString( nVal, aOut, &pCol );
2840 nPrecision = 0;
2841 // 'E' fuer Exponential ist fest im Numberformatter
2842 if ( aOut.Search('E') != STRING_NOTFOUND )
2843 bError = TRUE; // Exponential nicht veraendern
2844 else
2846 String aDecSep( pFormatter->GetFormatDecimalSep( nOldFormat ) );
2847 xub_StrLen nPos = aOut.Search( aDecSep );
2848 if ( nPos != STRING_NOTFOUND )
2849 nPrecision = aOut.Len() - nPos - aDecSep.Len();
2850 // sonst 0 behalten
2854 if (!bError)
2856 if (bIncrement)
2858 if (nPrecision<20)
2859 ++nPrecision; // erhoehen
2860 else
2861 bError = TRUE; // 20 ist Maximum
2863 else
2865 if (nPrecision)
2866 --nPrecision; // vermindern
2867 else
2868 bError = TRUE; // weniger als 0 geht nicht
2872 if (!bError)
2874 String aNewPicture;
2875 pFormatter->GenerateFormat( aNewPicture, nOldFormat, eLanguage,
2876 bThousand, bNegRed, nPrecision, nLeading );
2878 nNewFormat = pFormatter->GetEntryKey( aNewPicture, eLanguage );
2879 if ( nNewFormat == NUMBERFORMAT_ENTRY_NOT_FOUND )
2881 xub_StrLen nErrPos = 0;
2882 short nNewType = 0;
2883 BOOL bOk = pFormatter->PutEntry( aNewPicture, nErrPos,
2884 nNewType, nNewFormat, eLanguage );
2885 DBG_ASSERT( bOk, "falsches Zahlformat generiert" );
2886 if (!bOk)
2887 bError = TRUE;
2891 if (!bError)
2893 ScPatternAttr aNewAttrs( pDoc->GetPool() );
2894 SfxItemSet& rSet = aNewAttrs.GetItemSet();
2895 rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat ) );
2896 // ATTR_LANGUAGE_FORMAT nicht
2897 ApplySelectionPattern( aNewAttrs, TRUE );
2899 else
2900 Sound::Beep(); // war nix
2903 void ScViewFunc::ChangeIndent( BOOL bIncrement )
2905 ScViewData* pViewData = GetViewData();
2906 ScDocShell* pDocSh = pViewData->GetDocShell();
2907 ScMarkData& rMark = pViewData->GetMarkData();
2909 ScMarkData aWorkMark = rMark;
2910 ScViewUtil::UnmarkFiltered( aWorkMark, pDocSh->GetDocument() );
2911 aWorkMark.MarkToMulti();
2912 if (!aWorkMark.IsMultiMarked())
2914 SCCOL nCol = pViewData->GetCurX();
2915 SCROW nRow = pViewData->GetCurY();
2916 SCTAB nTab = pViewData->GetTabNo();
2917 aWorkMark.SetMultiMarkArea( ScRange(nCol,nRow,nTab) );
2920 BOOL bSuccess = pDocSh->GetDocFunc().ChangeIndent( aWorkMark, bIncrement, FALSE );
2921 if (bSuccess)
2923 pDocSh->UpdateOle(pViewData);
2924 StartFormatArea();
2928 BOOL ScViewFunc::InsertName( const String& rName, const String& rSymbol,
2929 const String& rType )
2931 // Type = P,R,C,F (und Kombinationen)
2932 //! Undo...
2934 BOOL bOk = FALSE;
2935 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2936 ScDocument* pDoc = pDocSh->GetDocument();
2937 SCTAB nTab = GetViewData()->GetTabNo();
2938 ScRangeName* pList = pDoc->GetRangeName();
2940 RangeType nType = RT_NAME;
2941 ScRangeData* pNewEntry = new ScRangeData( pDoc, rName, rSymbol,
2942 ScAddress( GetViewData()->GetCurX(), GetViewData()->GetCurY(),
2943 nTab), nType );
2944 String aUpType = rType;
2945 aUpType.ToUpperAscii();
2946 if ( aUpType.Search( 'P' ) != STRING_NOTFOUND )
2947 nType |= RT_PRINTAREA;
2948 if ( aUpType.Search( 'R' ) != STRING_NOTFOUND )
2949 nType |= RT_ROWHEADER;
2950 if ( aUpType.Search( 'C' ) != STRING_NOTFOUND )
2951 nType |= RT_COLHEADER;
2952 if ( aUpType.Search( 'F' ) != STRING_NOTFOUND )
2953 nType |= RT_CRITERIA;
2954 pNewEntry->AddType(nType);
2956 if ( !pNewEntry->GetErrCode() ) // Text gueltig?
2958 ScDocShellModificator aModificator( *pDocSh );
2960 pDoc->CompileNameFormula( TRUE ); // CreateFormulaString
2962 // Eintrag bereits vorhanden? Dann vorher entfernen (=Aendern)
2963 USHORT nFoundAt;
2964 if ( pList->SearchName( rName, nFoundAt ) )
2965 { // alten Index uebernehmen
2966 pNewEntry->SetIndex( ((ScRangeData*)pList->At(nFoundAt))->GetIndex() );
2967 pList->AtFree( nFoundAt );
2970 if ( pList->Insert( pNewEntry ) )
2972 pNewEntry = NULL; // nicht loeschen
2973 bOk = TRUE;
2976 pDoc->CompileNameFormula( FALSE ); // CompileFormulaString
2977 aModificator.SetDocumentModified();
2978 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
2981 delete pNewEntry; // wenn er nicht eingefuegt wurde
2982 return bOk;
2985 void ScViewFunc::CreateNames( USHORT nFlags )
2987 BOOL bDone = FALSE;
2988 ScRange aRange;
2989 if ( GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE )
2990 bDone = GetViewData()->GetDocShell()->GetDocFunc().CreateNames( aRange, nFlags, FALSE );
2992 if (!bDone)
2993 ErrorMessage(STR_CREATENAME_MARKERR);
2996 USHORT ScViewFunc::GetCreateNameFlags()
2998 USHORT nFlags = 0;
3000 SCCOL nStartCol, nEndCol;
3001 SCROW nStartRow, nEndRow;
3002 SCTAB nDummy;
3003 if (GetViewData()->GetSimpleArea(nStartCol,nStartRow,nDummy,nEndCol,nEndRow,nDummy) == SC_MARK_SIMPLE)
3005 ScDocument* pDoc = GetViewData()->GetDocument();
3006 SCTAB nTab = GetViewData()->GetTabNo();
3007 BOOL bOk;
3008 SCCOL i;
3009 SCROW j;
3011 bOk = TRUE;
3012 SCCOL nFirstCol = nStartCol;
3013 SCCOL nLastCol = nEndCol;
3014 if (nStartCol+1 < nEndCol) { ++nFirstCol; --nLastCol; }
3015 for (i=nFirstCol; i<=nLastCol && bOk; i++)
3016 if (!pDoc->HasStringData( i,nStartRow,nTab ))
3017 bOk = FALSE;
3018 if (bOk)
3019 nFlags |= NAME_TOP;
3020 else // Bottom nur wenn nicht Top
3022 bOk = TRUE;
3023 for (i=nFirstCol; i<=nLastCol && bOk; i++)
3024 if (!pDoc->HasStringData( i,nEndRow,nTab ))
3025 bOk = FALSE;
3026 if (bOk)
3027 nFlags |= NAME_BOTTOM;
3030 bOk = TRUE;
3031 SCROW nFirstRow = nStartRow;
3032 SCROW nLastRow = nEndRow;
3033 if (nStartRow+1 < nEndRow) { ++nFirstRow; --nLastRow; }
3034 for (j=nFirstRow; j<=nLastRow && bOk; j++)
3035 if (!pDoc->HasStringData( nStartCol,j,nTab ))
3036 bOk = FALSE;
3037 if (bOk)
3038 nFlags |= NAME_LEFT;
3039 else // Right nur wenn nicht Left
3041 bOk = TRUE;
3042 for (j=nFirstRow; j<=nLastRow && bOk; j++)
3043 if (!pDoc->HasStringData( nEndCol,j,nTab ))
3044 bOk = FALSE;
3045 if (bOk)
3046 nFlags |= NAME_RIGHT;
3050 if (nStartCol == nEndCol)
3051 nFlags &= ~( NAME_LEFT | NAME_RIGHT );
3052 if (nStartRow == nEndRow)
3053 nFlags &= ~( NAME_TOP | NAME_BOTTOM );
3055 return nFlags;
3058 void ScViewFunc::InsertNameList()
3060 ScAddress aPos( GetViewData()->GetCurX(), GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
3061 ScDocShell* pDocSh = GetViewData()->GetDocShell();
3062 if ( pDocSh->GetDocFunc().InsertNameList( aPos, FALSE ) )
3063 pDocSh->UpdateOle(GetViewData());