summaryrefslogtreecommitdiff
path: root/sc/source/ui/view/viewfunc.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/ui/view/viewfunc.cxx')
-rw-r--r--sc/source/ui/view/viewfunc.cxx3018
1 files changed, 3018 insertions, 0 deletions
diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
new file mode 100644
index 000000000000..231eb4e67562
--- /dev/null
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -0,0 +1,3018 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sc.hxx"
+
+
+
+//------------------------------------------------------------------
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "scitems.hxx"
+#include <editeng/eeitem.hxx>
+
+#include <sfx2/app.hxx>
+#include <svx/algitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/editobj.hxx>
+#include <editeng/editview.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/scripttypeitem.hxx>
+#include <sfx2/bindings.hxx>
+#include <svl/zforlist.hxx>
+#include <svl/zformat.hxx>
+#include <vcl/msgbox.hxx>
+#include <vcl/sound.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/waitobj.hxx>
+#include <vcl/wrkwin.hxx>
+#include <stdlib.h> // qsort
+
+#include "viewfunc.hxx"
+#include "tabvwsh.hxx"
+#include "docsh.hxx"
+#include "attrib.hxx"
+#include "patattr.hxx"
+#include "docpool.hxx"
+#include "uiitems.hxx"
+#include "sc.hrc"
+#include "undocell.hxx"
+#include "undoblk.hxx"
+#include "undotab.hxx"
+#include "refundo.hxx"
+#include "dbcolect.hxx"
+#include "olinetab.hxx"
+#include "rangeutl.hxx"
+#include "rangenam.hxx"
+#include "globstr.hrc"
+#include "global.hxx"
+#include "stlsheet.hxx"
+#include "editutil.hxx"
+//CHINA001 #include "namecrea.hxx" // wegen Flags
+#include "cell.hxx"
+#include "scresid.hxx"
+#include "inputhdl.hxx"
+#include "scmod.hxx"
+#include "inputopt.hxx"
+#include "compiler.hxx"
+#include "docfunc.hxx"
+#include "appoptio.hxx"
+#include "dociter.hxx"
+#include "sizedev.hxx"
+#include "editable.hxx"
+#include "scui_def.hxx" //CHINA001
+#include "funcdesc.hxx"
+#include "docuno.hxx"
+#include "cellsuno.hxx"
+//==================================================================
+
+ScViewFunc::ScViewFunc( Window* pParent, ScDocShell& rDocSh, ScTabViewShell* pViewShell ) :
+ ScTabView( pParent, rDocSh, pViewShell ),
+ bFormatValid( FALSE )
+{
+}
+
+//UNUSED2008-05 ScViewFunc::ScViewFunc( Window* pParent, const ScViewFunc& rViewFunc, ScTabViewShell* pViewShell ) :
+//UNUSED2008-05 ScTabView( pParent, rViewFunc, pViewShell ),
+//UNUSED2008-05 bFormatValid( FALSE )
+//UNUSED2008-05 {
+//UNUSED2008-05 }
+
+ScViewFunc::~ScViewFunc()
+{
+}
+
+//------------------------------------------------------------------------------------
+
+void ScViewFunc::StartFormatArea()
+{
+ // ueberhaupt aktiviert?
+ if ( !SC_MOD()->GetInputOptions().GetExtendFormat() )
+ return;
+
+ // start only with single cell (marked or cursor position)
+ ScRange aMarkRange;
+ BOOL bOk = (GetViewData()->GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE);
+ if ( bOk && aMarkRange.aStart != aMarkRange.aEnd )
+ bOk = FALSE;
+
+ if (bOk)
+ {
+ bFormatValid = TRUE;
+ aFormatSource = aMarkRange.aStart;
+ aFormatArea = ScRange( aFormatSource );
+ }
+ else
+ bFormatValid = FALSE; // keinen alten Bereich behalten
+}
+
+BOOL ScViewFunc::TestFormatArea( SCCOL nCol, SCROW nRow, SCTAB nTab, BOOL bAttrChanged )
+{
+ // ueberhaupt aktiviert?
+ if ( !SC_MOD()->GetInputOptions().GetExtendFormat() )
+ return FALSE;
+
+ // Test: Eingabe mit Zahlformat (bAttrChanged) immer als neue Attributierung behandeln
+ // (alte Area verwerfen). Wenn das nicht gewollt ist, den if-Teil weglassen:
+ if ( bAttrChanged )
+ {
+ StartFormatArea();
+ return FALSE;
+ }
+
+ //! Abfrage, ob Zelle leer war ???
+
+ BOOL bFound = FALSE;
+ ScRange aNewRange = aFormatArea;
+ if ( bFormatValid && nTab == aFormatSource.Tab() )
+ {
+ if ( nRow >= aFormatArea.aStart.Row() && nRow <= aFormatArea.aEnd.Row() )
+ {
+ // innerhalb ?
+ if ( nCol >= aFormatArea.aStart.Col() && nCol <= aFormatArea.aEnd.Col() )
+ {
+ bFound = TRUE; // Bereich nicht aendern
+ }
+ // links ?
+ if ( nCol+1 == aFormatArea.aStart.Col() )
+ {
+ bFound = TRUE;
+ aNewRange.aStart.SetCol( nCol );
+ }
+ // rechts ?
+ if ( nCol == aFormatArea.aEnd.Col()+1 )
+ {
+ bFound = TRUE;
+ aNewRange.aEnd.SetCol( nCol );
+ }
+ }
+ if ( nCol >= aFormatArea.aStart.Col() && nCol <= aFormatArea.aEnd.Col() )
+ {
+ // oben ?
+ if ( nRow+1 == aFormatArea.aStart.Row() )
+ {
+ bFound = TRUE;
+ aNewRange.aStart.SetRow( nRow );
+ }
+ // unten ?
+ if ( nRow == aFormatArea.aEnd.Row()+1 )
+ {
+ bFound = TRUE;
+ aNewRange.aEnd.SetRow( nRow );
+ }
+ }
+ }
+
+ if (bFound)
+ aFormatArea = aNewRange; // erweitern
+ else
+ {
+ bFormatValid = FALSE; // ausserhalb -> abbrechen
+ if ( bAttrChanged ) // Wert mit Zahlformat eingegeben?
+ StartFormatArea(); // dann ggf. neu starten
+ }
+
+ return bFound;
+}
+
+void ScViewFunc::DoAutoAttributes( SCCOL nCol, SCROW nRow, SCTAB nTab,
+ BOOL bAttrChanged, BOOL bAddUndo )
+{
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+ ScDocument* pDoc = pDocSh->GetDocument();
+ if (bAddUndo && !pDoc->IsUndoEnabled())
+ bAddUndo = FALSE;
+
+ const ScPatternAttr* pSource = pDoc->GetPattern(
+ aFormatSource.Col(), aFormatSource.Row(), nTab );
+ if ( !((const ScMergeAttr&)pSource->GetItem(ATTR_MERGE)).IsMerged() )
+ {
+ const ScPatternAttr* pDocOld = pDoc->GetPattern( nCol, nRow, nTab );
+ // pDocOld ist nur bis zum Apply... gueltig!
+
+ ScPatternAttr* pOldPattern = NULL;
+ if ( bAddUndo )
+ pOldPattern = new ScPatternAttr( *pDocOld );
+
+ const ScStyleSheet* pSrcStyle = pSource->GetStyleSheet();
+ if ( pSrcStyle && pSrcStyle != pDocOld->GetStyleSheet() )
+ pDoc->ApplyStyle( nCol, nRow, nTab, *pSrcStyle );
+ pDoc->ApplyPattern( nCol, nRow, nTab, *pSource );
+ AdjustRowHeight( nRow, nRow, TRUE ); //! nicht doppelt ?
+
+ if ( bAddUndo )
+ {
+ const ScPatternAttr* pNewPattern = pDoc->GetPattern( nCol, nRow, nTab );
+
+ pDocSh->GetUndoManager()->AddUndoAction(
+ new ScUndoCursorAttr( pDocSh, nCol, nRow, nTab,
+ pOldPattern, pNewPattern, pSource,
+ TRUE ) );
+
+ delete pOldPattern; // wird im Undo kopiert (Pool)
+ }
+ }
+
+ if ( bAttrChanged ) // Wert mit Zahlformat eingegeben?
+ aFormatSource.Set( nCol, nRow, nTab ); // dann als neue Quelle
+}
+
+//------------------------------------------------------------------------------------
+
+// Hilfsroutinen
+
+USHORT ScViewFunc::GetOptimalColWidth( SCCOL nCol, SCTAB nTab, BOOL bFormula )
+{
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+ ScDocument* pDoc = pDocSh->GetDocument();
+ ScMarkData& rMark = GetViewData()->GetMarkData();
+
+ double nPPTX = GetViewData()->GetPPTX();
+ double nPPTY = GetViewData()->GetPPTY();
+ Fraction aZoomX = GetViewData()->GetZoomX();
+ Fraction aZoomY = GetViewData()->GetZoomY();
+
+ ScSizeDeviceProvider aProv(pDocSh);
+ if (aProv.IsPrinter())
+ {
+ nPPTX = aProv.GetPPTX();
+ nPPTY = aProv.GetPPTY();
+ aZoomX = aZoomY = Fraction( 1, 1 );
+ }
+
+ USHORT nTwips = pDoc->GetOptimalColWidth( nCol, nTab, aProv.GetDevice(),
+ nPPTX, nPPTY, aZoomX, aZoomY, bFormula, &rMark );
+ return nTwips;
+}
+
+BOOL ScViewFunc::SelectionEditable( BOOL* pOnlyNotBecauseOfMatrix /* = NULL */ )
+{
+ BOOL bRet;
+ ScDocument* pDoc = GetViewData()->GetDocument();
+ ScMarkData& rMark = GetViewData()->GetMarkData();
+ if (rMark.IsMarked() || rMark.IsMultiMarked())
+ bRet = pDoc->IsSelectionEditable( rMark, pOnlyNotBecauseOfMatrix );
+ else
+ {
+ SCCOL nCol = GetViewData()->GetCurX();
+ SCROW nRow = GetViewData()->GetCurY();
+ SCTAB nTab = GetViewData()->GetTabNo();
+ bRet = pDoc->IsBlockEditable( nTab, nCol, nRow, nCol, nRow,
+ pOnlyNotBecauseOfMatrix );
+ }
+ return bRet;
+}
+
+#ifndef LRU_MAX
+#define LRU_MAX 10
+#endif
+
+BOOL lcl_FunctionKnown( USHORT nOpCode )
+{
+ const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList();
+ if ( pFuncList )
+ {
+ ULONG nCount = pFuncList->GetCount();
+ for (ULONG i=0; i<nCount; i++)
+ if ( pFuncList->GetFunction(i)->nFIndex == nOpCode )
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL lcl_AddFunction( ScAppOptions& rAppOpt, USHORT nOpCode )
+{
+ USHORT nOldCount = rAppOpt.GetLRUFuncListCount();
+ USHORT* pOldList = rAppOpt.GetLRUFuncList();
+ USHORT nPos;
+ for (nPos=0; nPos<nOldCount; nPos++)
+ if (pOldList[nPos] == nOpCode) // is the function already in the list?
+ {
+ if ( nPos == 0 )
+ return FALSE; // already at the top -> no change
+
+ // count doesn't change, so the original array is modified
+
+ for (USHORT nCopy=nPos; nCopy>0; nCopy--)
+ pOldList[nCopy] = pOldList[nCopy-1];
+ pOldList[0] = nOpCode;
+
+ return TRUE; // list has changed
+ }
+
+ if ( !lcl_FunctionKnown( nOpCode ) )
+ return FALSE; // not in function list -> no change
+
+ USHORT nNewCount = Min( (USHORT)(nOldCount + 1), (USHORT)LRU_MAX );
+ USHORT nNewList[LRU_MAX];
+ nNewList[0] = nOpCode;
+ for (nPos=1; nPos<nNewCount; nPos++)
+ nNewList[nPos] = pOldList[nPos-1];
+ rAppOpt.SetLRUFuncList( nNewList, nNewCount );
+
+ return TRUE; // list has changed
+}
+
+// eigentliche Funktionen
+
+// Eingabe - Undo OK
+
+void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rString,
+ BOOL bRecord, const EditTextObject* pData )
+{
+ ScDocument* pDoc = GetViewData()->GetDocument();
+ ScMarkData& rMark = GetViewData()->GetMarkData();
+ SCTAB nTabCount = pDoc->GetTableCount();
+ SCTAB nSelCount = rMark.GetSelectCount();
+ SCTAB i;
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+ ScDocShellModificator aModificator( *pDocSh );
+
+ ScEditableTester aTester( pDoc, nCol,nRow, nCol,nRow, rMark );
+ if (aTester.IsEditable())
+ {
+ BOOL bEditDeleted = FALSE;
+ BYTE nOldScript = 0;
+
+ ScBaseCell** ppOldCells = NULL;
+ BOOL* pHasFormat = NULL;
+ ULONG* pOldFormats = NULL;
+ SCTAB* pTabs = NULL;
+ SCTAB nUndoPos = 0;
+ EditTextObject* pUndoData = NULL;
+ if ( bRecord )
+ {
+ ppOldCells = new ScBaseCell*[nSelCount];
+ pHasFormat = new BOOL[nSelCount];
+ pOldFormats = new ULONG[nSelCount];
+ pTabs = new SCTAB[nSelCount];
+ nUndoPos = 0;
+
+ for (i=0; i<nTabCount; i++)
+ if (rMark.GetTableSelect(i))
+ {
+ pTabs[nUndoPos] = i;
+ ScBaseCell* pDocCell;
+ pDoc->GetCell( nCol, nRow, i, pDocCell );
+ if ( pDocCell )
+ {
+ ppOldCells[nUndoPos] = pDocCell->CloneWithoutNote( *pDoc );
+ if ( pDocCell->GetCellType() == CELLTYPE_EDIT )
+ bEditDeleted = TRUE;
+
+ BYTE nDocScript = pDoc->GetScriptType( nCol, nRow, i, pDocCell );
+ if ( nOldScript == 0 )
+ nOldScript = nDocScript;
+ else if ( nDocScript != nOldScript )
+ bEditDeleted = TRUE;
+ }
+ else
+ {
+ ppOldCells[nUndoPos] = NULL;
+ }
+
+ const SfxPoolItem* pItem;
+ const ScPatternAttr* pPattern = pDoc->GetPattern(nCol, nRow, i);
+ if ( SFX_ITEM_SET == pPattern->GetItemSet().GetItemState(
+ ATTR_VALUE_FORMAT,FALSE,&pItem) )
+ {
+ pHasFormat[nUndoPos] = TRUE;
+ pOldFormats[nUndoPos] = ((const SfxUInt32Item*)pItem)->GetValue();
+ }
+ else
+ pHasFormat[nUndoPos] = FALSE;
+
+ ++nUndoPos;
+ }
+
+ DBG_ASSERT( nUndoPos==nSelCount, "nUndoPos!=nSelCount" );
+
+ pUndoData = ( pData ? pData->Clone() : NULL );
+ }
+
+ bool bFormula = false;
+
+ // a single '=' character is handled as string (needed for special filters)
+ if ( rString.Len() > 1 )
+ {
+ if ( rString.GetChar(0) == '=' )
+ {
+ // handle as formula
+ bFormula = true;
+ }
+ else if ( rString.GetChar(0) == '+' || rString.GetChar(0) == '-' )
+ {
+ // if there is more than one leading '+' or '-' character, remove the additional ones
+ String aString( rString );
+ xub_StrLen nIndex = 1;
+ xub_StrLen nLen = aString.Len();
+ while ( nIndex < nLen && ( aString.GetChar( nIndex ) == '+' || aString.GetChar( nIndex ) == '-' ) )
+ {
+ ++nIndex;
+ }
+ aString.Erase( 1, nIndex - 1 );
+
+ // if the remaining part without the leading '+' or '-' character
+ // is non-empty and not a number, handle as formula
+ if ( aString.Len() > 1 )
+ {
+ sal_uInt32 nFormat = 0;
+ pDoc->GetNumberFormat( nCol, nRow, nTab, nFormat );
+ SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
+ double fNumber = 0;
+ if ( !pFormatter->IsNumberFormat( aString, nFormat, fNumber ) )
+ {
+ bFormula = true;
+ }
+ }
+ }
+ }
+
+ BOOL bNumFmtChanged = FALSE;
+ if ( bFormula )
+ { // Formel, compile mit AutoCorrection
+ for (i=0; i<nTabCount; i++)
+ if (rMark.GetTableSelect(i))
+ break;
+ ScAddress aPos( nCol, nRow, i );
+ ScCompiler aComp( pDoc, aPos);
+ aComp.SetGrammar(pDoc->GetGrammar());
+//2do: AutoCorrection via CalcOptions abschaltbar machen
+ aComp.SetAutoCorrection( TRUE );
+ if ( rString.GetChar(0) == '+' || rString.GetChar(0) == '-' )
+ {
+ aComp.SetExtendedErrorDetection( true );
+ }
+ String aFormula( rString );
+ ScTokenArray* pArr;
+ BOOL bAgain;
+ do
+ {
+ bAgain = FALSE;
+ BOOL bAddEqual = FALSE;
+ ScTokenArray* pArrFirst = pArr = aComp.CompileString( aFormula );
+ BOOL bCorrected = aComp.IsCorrected();
+ if ( bCorrected )
+ { // probieren, mit erster Parser-Korrektur neu zu parsen
+ pArr = aComp.CompileString( aComp.GetCorrectedFormula() );
+ }
+ if ( !pArr->GetCodeError() )
+ {
+ bAddEqual = TRUE;
+ aComp.CompileTokenArray();
+ bCorrected |= aComp.IsCorrected();
+ }
+ if ( bCorrected )
+ {
+ String aCorrectedFormula;
+ if ( bAddEqual )
+ {
+ aCorrectedFormula = '=';
+ aCorrectedFormula += aComp.GetCorrectedFormula();
+ }
+ else
+ aCorrectedFormula = aComp.GetCorrectedFormula();
+ short nResult;
+ if ( aCorrectedFormula.Len() == 1 )
+ nResult = RET_NO; // leere Formel, nur '='
+ else
+ {
+ String aMessage( ScResId( SCSTR_FORMULA_AUTOCORRECTION ) );
+ aMessage += aCorrectedFormula;
+ nResult = QueryBox( GetViewData()->GetDialogParent(),
+ WinBits(WB_YES_NO | WB_DEF_YES),
+ aMessage ).Execute();
+ }
+ if ( nResult == RET_YES )
+ {
+ aFormula = aCorrectedFormula;
+ if ( pArr != pArrFirst )
+ delete pArrFirst;
+ bAgain = TRUE;
+ }
+ else
+ {
+ if ( pArr != pArrFirst )
+ {
+ delete pArr;
+ pArr = pArrFirst;
+ }
+ }
+ }
+ } while ( bAgain );
+ // um in mehreren Tabellen eingesetzt zu werden, muss die Formel
+ // via ScFormulaCell copy-ctor evtl. wegen RangeNames neu kompiliert
+ // werden, gleiches Code-Array fuer alle Zellen geht nicht.
+ // Wenn das Array einen Fehler enthaelt, muss in den neu erzeugten
+ // Zellen RPN geloescht und der Fehler explizit gesetzt werden, da
+ // via FormulaCell copy-ctor und Interpreter das, wenn moeglich,
+ // wieder glattgebuegelt wird, zu intelligent.. z.B.: =1))
+ USHORT nError = pArr->GetCodeError();
+ if ( !nError )
+ {
+ // #68693# update list of recent functions with all functions that
+ // are not within parentheses
+
+ ScModule* pScMod = SC_MOD();
+ ScAppOptions aAppOpt = pScMod->GetAppOptions();
+ BOOL bOptChanged = FALSE;
+
+ formula::FormulaToken** ppToken = pArr->GetArray();
+ USHORT nTokens = pArr->GetLen();
+ USHORT nLevel = 0;
+ for (USHORT nTP=0; nTP<nTokens; nTP++)
+ {
+ formula::FormulaToken* pTok = ppToken[nTP];
+ OpCode eOp = pTok->GetOpCode();
+ if ( eOp == ocOpen )
+ ++nLevel;
+ else if ( eOp == ocClose && nLevel )
+ --nLevel;
+ if ( nLevel == 0 && pTok->IsFunction() &&
+ lcl_AddFunction( aAppOpt, sal::static_int_cast<USHORT>( eOp ) ) )
+ bOptChanged = TRUE;
+ }
+
+ if ( bOptChanged )
+ {
+ pScMod->SetAppOptions(aAppOpt);
+ pScMod->RecentFunctionsChanged();
+ }
+ }
+
+ ScFormulaCell aCell( pDoc, aPos, pArr,formula::FormulaGrammar::GRAM_DEFAULT, MM_NONE );
+ delete pArr;
+ BOOL bAutoCalc = pDoc->GetAutoCalc();
+ SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
+ for ( ; i<nTabCount; i++)
+ {
+ if (rMark.GetTableSelect(i))
+ {
+ aPos.SetTab( i );
+ ULONG nIndex = (ULONG) ((SfxUInt32Item*) pDoc->GetAttr(
+ nCol, nRow, i, ATTR_VALUE_FORMAT ))->GetValue();
+ if ( pFormatter->GetType( nIndex ) == NUMBERFORMAT_TEXT ||
+ ( ( rString.GetChar(0) == '+' || rString.GetChar(0) == '-' ) && nError && rString.Equals( aFormula ) ) )
+ {
+ if ( pData )
+ {
+ ScEditCell* pCell = new ScEditCell( pData, pDoc, NULL );
+ pDoc->PutCell( aPos, pCell );
+ }
+ else
+ {
+ ScStringCell* pCell = new ScStringCell( aFormula );
+ pDoc->PutCell( aPos, pCell );
+ }
+ }
+ else
+ {
+ DELETEZ(pUndoData);
+ ScFormulaCell* pCell = new ScFormulaCell( aCell, *pDoc, aPos );
+ if ( nError )
+ {
+ pCell->GetCode()->DelRPN();
+ pCell->SetErrCode( nError );
+ if(pCell->GetCode()->IsHyperLink())
+ pCell->GetCode()->SetHyperLink(FALSE);
+ }
+ pDoc->PutCell( aPos, pCell );
+ if ( !bAutoCalc )
+ { // einmal nur die Zelle berechnen und wieder dirty setzen
+ pCell->Interpret();
+ pCell->SetDirtyVar();
+ pDoc->PutInFormulaTree( pCell );
+ }
+ }
+
+ }
+ }
+ }
+ else
+ {
+ for (i=0; i<nTabCount; i++)
+ if (rMark.GetTableSelect(i))
+ if (pDoc->SetString( nCol, nRow, i, rString ))
+ bNumFmtChanged = TRUE;
+ }
+
+ // row height must be changed if new text has a different script type
+ for (i=0; i<nTabCount && !bEditDeleted; i++)
+ if (rMark.GetTableSelect(i))
+ if ( pDoc->GetScriptType( nCol, nRow, i ) != nOldScript )
+ bEditDeleted = TRUE;
+
+ HideAllCursors();
+
+ if (bEditDeleted || pDoc->HasAttrib( nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_NEEDHEIGHT ))
+ AdjustRowHeight(nRow,nRow);
+
+ BOOL bAutoFormat = TestFormatArea(nCol, nRow, nTab, bNumFmtChanged);
+ if (bAutoFormat)
+ DoAutoAttributes(nCol, nRow, nTab, bNumFmtChanged, bRecord);
+
+ if ( bRecord )
+ { // wg. ChangeTrack erst jetzt
+ pDocSh->GetUndoManager()->AddUndoAction(
+ new ScUndoEnterData( pDocSh, nCol, nRow, nTab, nUndoPos, pTabs,
+ ppOldCells, pHasFormat, pOldFormats,
+ rString, pUndoData ) );
+ }
+
+ for (i=0; i<nTabCount; i++)
+ if (rMark.GetTableSelect(i))
+ pDocSh->PostPaintCell( nCol, nRow, i );
+
+ ShowAllCursors();
+
+ pDocSh->UpdateOle(GetViewData());
+
+ // #i97876# Spreadsheet data changes are not notified
+ ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
+ if ( pModelObj && pModelObj->HasChangesListeners() )
+ {
+ ScRangeList aChangeRanges;
+ for ( i = 0; i < nTabCount; ++i )
+ {
+ if ( rMark.GetTableSelect( i ) )
+ {
+ aChangeRanges.Append( ScRange( nCol, nRow, i ) );
+ }
+ }
+ pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges );
+ }
+
+ aModificator.SetDocumentModified();
+ }
+ else
+ {
+ ErrorMessage(aTester.GetMessageId());
+ PaintArea( nCol, nRow, nCol, nRow ); // da steht evtl. noch die Edit-Engine
+ }
+}
+
+// Wert in einzele Zelle eintragen (nur auf nTab)
+
+void ScViewFunc::EnterValue( SCCOL nCol, SCROW nRow, SCTAB nTab, const double& rValue )
+{
+ ScDocument* pDoc = GetViewData()->GetDocument();
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+ BOOL bUndo (pDoc->IsUndoEnabled());
+
+ if ( pDoc && pDocSh )
+ {
+ ScDocShellModificator aModificator( *pDocSh );
+
+ ScEditableTester aTester( pDoc, nTab, nCol,nRow, nCol,nRow );
+ if (aTester.IsEditable())
+ {
+ ScAddress aPos( nCol, nRow, nTab );
+ ScBaseCell* pOldCell = pDoc->GetCell( aPos );
+ BOOL bNeedHeight = ( pOldCell && pOldCell->GetCellType() == CELLTYPE_EDIT )
+ || pDoc->HasAttrib(
+ nCol,nRow,nTab, nCol,nRow,nTab, HASATTR_NEEDHEIGHT );
+
+ // Undo
+ ScBaseCell* pUndoCell = (bUndo && pOldCell) ? pOldCell->CloneWithoutNote( *pDoc ) : 0;
+
+ pDoc->SetValue( nCol, nRow, nTab, rValue );
+
+ // wg. ChangeTrack nach Aenderung im Dokument
+ if (bUndo)
+ {
+ pDocSh->GetUndoManager()->AddUndoAction(
+ new ScUndoEnterValue( pDocSh, aPos, pUndoCell, rValue, bNeedHeight ) );
+ }
+
+/*! Zeilenhoehe anpassen? Dann auch bei Undo...
+ if (bNeedHeight)
+ AdjustRowHeight(nRow,nRow);
+*/
+
+ pDocSh->PostPaintCell( aPos );
+ pDocSh->UpdateOle(GetViewData());
+ aModificator.SetDocumentModified();
+ }
+ else
+ ErrorMessage(aTester.GetMessageId());
+ }
+}
+
+void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const EditTextObject* pData,
+ BOOL bRecord, BOOL bTestSimple )
+{
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+ ScMarkData& rMark = GetViewData()->GetMarkData();
+ ScDocument* pDoc = pDocSh->GetDocument();
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+
+ ScDocShellModificator aModificator( *pDocSh );
+
+ ScEditableTester aTester( pDoc, nTab, nCol,nRow, nCol,nRow );
+ if (aTester.IsEditable())
+ {
+ //
+ // Test auf Attribute
+ //
+ BOOL bSimple = FALSE;
+ BOOL bCommon = FALSE;
+ ScPatternAttr* pCellAttrs = NULL;
+ EditTextObject* pNewData = NULL;
+ String aString;
+
+ const ScPatternAttr* pOldPattern = pDoc->GetPattern( nCol, nRow, nTab );
+ ScTabEditEngine aEngine( *pOldPattern, pDoc->GetEnginePool() );
+ aEngine.SetText(*pData);
+
+ if (bTestSimple) // Testen, ob einfacher String ohne Attribute
+ {
+ ScEditAttrTester aAttrTester( &aEngine );
+ bSimple = !aAttrTester.NeedsObject();
+ bCommon = aAttrTester.NeedsCellAttr();
+
+ // formulas have to be recognized even if they're formatted
+ // (but commmon attributes are still collected)
+
+ if ( !bSimple && aEngine.GetParagraphCount() == 1 )
+ {
+ String aParStr = aEngine.GetText( (USHORT) 0 );
+ if ( aParStr.GetChar(0) == '=' )
+ bSimple = TRUE;
+ }
+
+ if (bCommon) // Attribute fuer Tabelle
+ {
+ pCellAttrs = new ScPatternAttr( *pOldPattern );
+ pCellAttrs->GetFromEditItemSet( &aAttrTester.GetAttribs() );
+ //! remove common attributes from EditEngine?
+ }
+ }
+
+ // #i97726# always get text for "repeat" of undo action
+ aString = ScEditUtil::GetSpaceDelimitedString(aEngine);
+
+ //
+ // Undo
+ //
+
+ SCTAB nTabCount = pDoc->GetTableCount();
+ SCTAB nSelCount = rMark.GetSelectCount();
+ SCTAB i;
+ ScBaseCell** ppOldCells = NULL;
+ SCTAB* pTabs = NULL;
+ SCTAB nPos = 0;
+ EditTextObject* pUndoData = NULL;
+ if (bRecord && !bSimple)
+ {
+ ppOldCells = new ScBaseCell*[nSelCount];
+ pTabs = new SCTAB[nSelCount];
+ nPos = 0;
+
+ for (i=0; i<nTabCount; i++)
+ if (rMark.GetTableSelect(i))
+ {
+ pTabs[nPos] = i;
+ ScBaseCell* pDocCell;
+ pDoc->GetCell( nCol, nRow, i, pDocCell );
+ ppOldCells[nPos] = pDocCell ? pDocCell->CloneWithoutNote( *pDoc ) : 0;
+ ++nPos;
+ }
+
+ DBG_ASSERT( nPos==nSelCount, "nPos!=nSelCount" );
+
+ pUndoData = pData->Clone();
+ }
+
+ //
+ // Daten eintragen
+ //
+
+ if (bCommon)
+ pDoc->ApplyPattern(nCol,nRow,nTab,*pCellAttrs); //! Undo
+
+ if (bSimple)
+ {
+ if (bCommon)
+ AdjustRowHeight(nRow,nRow);
+
+ EnterData(nCol,nRow,nTab,aString,bRecord);
+ }
+ else
+ {
+ for (i=0; i<nTabCount; i++)
+ if (rMark.GetTableSelect(i))
+ pDoc->PutCell( nCol, nRow, i, new ScEditCell( pData, pDoc, NULL ) );
+
+ if ( bRecord )
+ { // wg. ChangeTrack erst jetzt
+ pDocSh->GetUndoManager()->AddUndoAction(
+ new ScUndoEnterData( pDocSh, nCol, nRow, nTab, nPos, pTabs,
+ ppOldCells, NULL, NULL, aString,
+ pUndoData ) );
+ }
+
+ HideAllCursors();
+
+ AdjustRowHeight(nRow,nRow);
+
+ for (i=0; i<nTabCount; i++)
+ if (rMark.GetTableSelect(i))
+ pDocSh->PostPaintCell( nCol, nRow, i );
+
+ ShowAllCursors();
+
+ pDocSh->UpdateOle(GetViewData());
+
+ // #i97876# Spreadsheet data changes are not notified
+ ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
+ if ( pModelObj && pModelObj->HasChangesListeners() )
+ {
+ ScRangeList aChangeRanges;
+ for ( i = 0; i < nTabCount; ++i )
+ {
+ if ( rMark.GetTableSelect( i ) )
+ {
+ aChangeRanges.Append( ScRange( nCol, nRow, i ) );
+ }
+ }
+ pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges );
+ }
+
+ aModificator.SetDocumentModified();
+ }
+
+ delete pCellAttrs;
+ delete pNewData;
+ }
+ else
+ {
+ ErrorMessage(aTester.GetMessageId());
+ PaintArea( nCol, nRow, nCol, nRow ); // da steht evtl. noch die Edit-Engine
+ }
+}
+
+void ScViewFunc::EnterDataAtCursor( const String& rString )
+{
+ SCCOL nPosX = GetViewData()->GetCurX();
+ SCROW nPosY = GetViewData()->GetCurY();
+ SCTAB nTab = GetViewData()->GetTabNo();
+
+ EnterData( nPosX, nPosY, nTab, rString );
+}
+
+void ScViewFunc::EnterMatrix( const String& rString )
+{
+ ScViewData* pData = GetViewData();
+ const ScMarkData& rMark = pData->GetMarkData();
+ if ( !rMark.IsMarked() && !rMark.IsMultiMarked() )
+ {
+ // nichts markiert -> automatisch Block mit Groesse des Ergebnisses
+ // Formel temporaer berechnen, um an die Groesse heranzukommen
+
+ ScDocument* pDoc = pData->GetDocument();
+ SCCOL nCol = pData->GetCurX();
+ SCROW nRow = pData->GetCurY();
+ SCTAB nTab = pData->GetTabNo();
+ ScFormulaCell aFormCell( pDoc, ScAddress(nCol,nRow,nTab), rString,formula::FormulaGrammar::GRAM_DEFAULT, MM_FORMULA );
+
+ SCSIZE nSizeX;
+ SCSIZE nSizeY;
+ aFormCell.GetResultDimensions( nSizeX, nSizeY );
+ if ( nSizeX != 0 && nSizeY != 0 &&
+ nCol+nSizeX-1 <= sal::static_int_cast<SCSIZE>(MAXCOL) &&
+ nRow+nSizeY-1 <= sal::static_int_cast<SCSIZE>(MAXROW) )
+ {
+ ScRange aResult( nCol, nRow, nTab,
+ sal::static_int_cast<SCCOL>(nCol+nSizeX-1),
+ sal::static_int_cast<SCROW>(nRow+nSizeY-1), nTab );
+ MarkRange( aResult, FALSE );
+ }
+ }
+
+ ScRange aRange;
+ if (pData->GetSimpleArea(aRange) == SC_MARK_SIMPLE)
+ {
+ ScDocShell* pDocSh = pData->GetDocShell();
+ BOOL bSuccess = pDocSh->GetDocFunc().EnterMatrix( aRange, &rMark, NULL, rString, FALSE, FALSE, EMPTY_STRING, formula::FormulaGrammar::GRAM_DEFAULT );
+ if (bSuccess)
+ pDocSh->UpdateOle(GetViewData());
+ }
+ else
+ ErrorMessage(STR_NOMULTISELECT);
+}
+
+BYTE ScViewFunc::GetSelectionScriptType()
+{
+ BYTE nScript = 0;
+
+ ScDocument* pDoc = GetViewData()->GetDocument();
+ const ScMarkData& rMark = GetViewData()->GetMarkData();
+ if ( !rMark.IsMarked() && !rMark.IsMultiMarked() )
+ {
+ // no selection -> cursor
+
+ nScript = pDoc->GetScriptType( GetViewData()->GetCurX(),
+ GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
+ }
+ else
+ {
+ ScRangeList aRanges;
+ rMark.FillRangeListWithMarks( &aRanges, FALSE );
+ ULONG nCount = aRanges.Count();
+ for (ULONG i=0; i<nCount; i++)
+ {
+ ScRange aRange = *aRanges.GetObject(i);
+ ScCellIterator aIter( pDoc, aRange );
+ ScBaseCell* pCell = aIter.GetFirst();
+ while ( pCell )
+ {
+ nScript |= pDoc->GetScriptType( aIter.GetCol(), aIter.GetRow(), aIter.GetTab(), pCell );
+ pCell = aIter.GetNext();
+ }
+ }
+ }
+
+ if (nScript == 0)
+ nScript = ScGlobal::GetDefaultScriptType();
+
+ return nScript;
+}
+
+const ScPatternAttr* ScViewFunc::GetSelectionPattern()
+{
+ // Don't use UnmarkFiltered in slot state functions, for performance reasons.
+ // The displayed state is always that of the whole selection including filtered rows.
+
+ const ScMarkData& rMark = GetViewData()->GetMarkData();
+ ScDocument* pDoc = GetViewData()->GetDocument();
+ if ( rMark.IsMarked() || rMark.IsMultiMarked() )
+ {
+ // MarkToMulti is no longer necessary for pDoc->GetSelectionPattern
+ const ScPatternAttr* pAttr = pDoc->GetSelectionPattern( rMark );
+ return pAttr;
+ }
+ else
+ {
+ SCCOL nCol = GetViewData()->GetCurX();
+ SCROW nRow = GetViewData()->GetCurY();
+ SCTAB nTab = GetViewData()->GetTabNo();
+
+ ScMarkData aTempMark( rMark ); // copy sheet selection
+ aTempMark.SetMarkArea( ScRange( nCol, nRow, nTab ) );
+ const ScPatternAttr* pAttr = pDoc->GetSelectionPattern( aTempMark );
+ return pAttr;
+ }
+}
+
+void ScViewFunc::GetSelectionFrame( SvxBoxItem& rLineOuter,
+ SvxBoxInfoItem& rLineInner )
+{
+ ScDocument* pDoc = GetViewData()->GetDocument();
+ const ScMarkData& rMark = GetViewData()->GetMarkData();
+
+ if ( rMark.IsMarked() || rMark.IsMultiMarked() )
+ {
+ if ( rMark.IsMultiMarked() )
+ {
+ ScMarkData aNewMark( rMark ); // use local copy for MarkToSimple
+ aNewMark.MarkToSimple(); // simple block is needed for GetSelectionFrame
+ pDoc->GetSelectionFrame( aNewMark, rLineOuter, rLineInner );
+ }
+ else
+ pDoc->GetSelectionFrame( rMark, rLineOuter, rLineInner );
+ }
+ else
+ {
+ const ScPatternAttr* pAttrs =
+ pDoc->GetPattern( GetViewData()->GetCurX(),
+ GetViewData()->GetCurY(),
+ GetViewData()->GetTabNo() );
+
+ rLineOuter = (const SvxBoxItem&) (pAttrs->GetItem( ATTR_BORDER ));
+ rLineInner = (const SvxBoxInfoItem&)(pAttrs->GetItem( ATTR_BORDER_INNER ));
+ rLineInner.SetTable(FALSE);
+ rLineInner.SetDist(TRUE);
+ rLineInner.SetMinDist(FALSE);
+ }
+}
+
+//
+// Attribute anwenden - Undo OK
+//
+// kompletter Set ( ATTR_STARTINDEX, ATTR_ENDINDEX )
+//
+
+void ScViewFunc::ApplyAttributes( const SfxItemSet* pDialogSet,
+ const SfxItemSet* pOldSet,
+ BOOL bRecord )
+{
+ // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
+ BOOL bOnlyNotBecauseOfMatrix;
+ if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
+ {
+ ErrorMessage(STR_PROTECTIONERR);
+ return;
+ }
+
+ ScPatternAttr aOldAttrs( new SfxItemSet(*pOldSet) );
+ ScPatternAttr aNewAttrs( new SfxItemSet(*pDialogSet) );
+ aNewAttrs.DeleteUnchanged( &aOldAttrs );
+
+ if ( pDialogSet->GetItemState( ATTR_VALUE_FORMAT ) == SFX_ITEM_SET )
+ { // #82521# don't reset to default SYSTEM GENERAL if not intended
+ sal_uInt32 nOldFormat =
+ ((const SfxUInt32Item&)pOldSet->Get( ATTR_VALUE_FORMAT )).GetValue();
+ sal_uInt32 nNewFormat =
+ ((const SfxUInt32Item&)pDialogSet->Get( ATTR_VALUE_FORMAT )).GetValue();
+ if ( nNewFormat != nOldFormat )
+ {
+ SvNumberFormatter* pFormatter =
+ GetViewData()->GetDocument()->GetFormatTable();
+ const SvNumberformat* pOldEntry = pFormatter->GetEntry( nOldFormat );
+ LanguageType eOldLang =
+ pOldEntry ? pOldEntry->GetLanguage() : LANGUAGE_DONTKNOW;
+ const SvNumberformat* pNewEntry = pFormatter->GetEntry( nNewFormat );
+ LanguageType eNewLang =
+ pNewEntry ? pNewEntry->GetLanguage() : LANGUAGE_DONTKNOW;
+ if ( eNewLang != eOldLang )
+ {
+ aNewAttrs.GetItemSet().Put(
+ SvxLanguageItem( eNewLang, ATTR_LANGUAGE_FORMAT ) );
+
+ // #40606# nur die Sprache geaendert -> Zahlformat-Attribut nicht anfassen
+ sal_uInt32 nNewMod = nNewFormat % SV_COUNTRY_LANGUAGE_OFFSET;
+ if ( nNewMod == ( nOldFormat % SV_COUNTRY_LANGUAGE_OFFSET ) &&
+ nNewMod <= SV_MAX_ANZ_STANDARD_FORMATE )
+ aNewAttrs.GetItemSet().ClearItem( ATTR_VALUE_FORMAT );
+ }
+ }
+ }
+
+ const SvxBoxItem* pOldOuter = (const SvxBoxItem*) &pOldSet->Get( ATTR_BORDER );
+ const SvxBoxItem* pNewOuter = (const SvxBoxItem*) &pDialogSet->Get( ATTR_BORDER );
+ const SvxBoxInfoItem* pOldInner = (const SvxBoxInfoItem*) &pOldSet->Get( ATTR_BORDER_INNER );
+ const SvxBoxInfoItem* pNewInner = (const SvxBoxInfoItem*) &pDialogSet->Get( ATTR_BORDER_INNER );
+ SfxItemSet& rNewSet = aNewAttrs.GetItemSet();
+ SfxItemPool* pNewPool = rNewSet.GetPool();
+
+ pNewPool->Put( *pNewOuter ); // noch nicht loeschen
+ pNewPool->Put( *pNewInner );
+ rNewSet.ClearItem( ATTR_BORDER );
+ rNewSet.ClearItem( ATTR_BORDER_INNER );
+
+ /*
+ * Feststellen, ob Rahmenattribute zu setzen sind:
+ * 1. Neu != Alt
+ * 2. Ist eine der Linien nicht-DontCare (seit 238.f: IsxxValid())
+ *
+ */
+
+ BOOL bFrame = (pDialogSet->GetItemState( ATTR_BORDER ) != SFX_ITEM_DEFAULT)
+ || (pDialogSet->GetItemState( ATTR_BORDER_INNER ) != SFX_ITEM_DEFAULT);
+
+ if ( pNewOuter==pOldOuter && pNewInner==pOldInner )
+ bFrame = FALSE;
+
+ // das sollte doch der Pool abfangen: ?!??!??
+
+ if ( bFrame && pNewOuter && pNewInner )
+ if ( *pNewOuter == *pOldOuter && *pNewInner == *pOldInner )
+ bFrame = FALSE;
+
+ if ( pNewInner )
+ {
+ bFrame = bFrame
+ && ( pNewInner->IsValid(VALID_LEFT)
+ || pNewInner->IsValid(VALID_RIGHT)
+ || pNewInner->IsValid(VALID_TOP)
+ || pNewInner->IsValid(VALID_BOTTOM)
+ || pNewInner->IsValid(VALID_HORI)
+ || pNewInner->IsValid(VALID_VERT) );
+ }
+ else
+ bFrame = FALSE;
+
+ if (!bFrame)
+ ApplySelectionPattern( aNewAttrs, bRecord ); // nur normale
+ else
+ {
+ // wenn neue Items Default-Items sind, so muessen die
+ // alten Items geputtet werden:
+
+ BOOL bDefNewOuter = ( SFX_ITEMS_STATICDEFAULT == pNewOuter->GetKind() );
+ BOOL bDefNewInner = ( SFX_ITEMS_STATICDEFAULT == pNewInner->GetKind() );
+
+ ApplyPatternLines( aNewAttrs,
+ bDefNewOuter ? pOldOuter : pNewOuter,
+ bDefNewInner ? pOldInner : pNewInner,
+ bRecord );
+ }
+
+ pNewPool->Remove( *pNewOuter ); // freigeben
+ pNewPool->Remove( *pNewInner );
+
+ // Hoehen anpassen
+ AdjustBlockHeight();
+
+ // CellContentChanged wird von ApplySelectionPattern / ApplyPatternLines gerufen
+}
+
+void ScViewFunc::ApplyAttr( const SfxPoolItem& rAttrItem )
+{
+ // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
+ BOOL bOnlyNotBecauseOfMatrix;
+ if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
+ {
+ ErrorMessage(STR_PROTECTIONERR);
+ return;
+ }
+
+ ScPatternAttr aNewAttrs( new SfxItemSet( *GetViewData()->GetDocument()->GetPool(),
+ ATTR_PATTERN_START, ATTR_PATTERN_END ) );
+
+ aNewAttrs.GetItemSet().Put( rAttrItem );
+ // Wenn Ausrichtung eingestellt wird (ueber Buttons), immer Einzug 0
+ if ( rAttrItem.Which() == ATTR_HOR_JUSTIFY )
+ aNewAttrs.GetItemSet().Put( SfxUInt16Item( ATTR_INDENT, 0 ) );
+ ApplySelectionPattern( aNewAttrs );
+
+ AdjustBlockHeight();
+
+ // CellContentChanged wird von ApplySelectionPattern gerufen
+}
+
+
+// Pattern und Rahmen
+
+void ScViewFunc::ApplyPatternLines( const ScPatternAttr& rAttr, const SvxBoxItem* pNewOuter,
+ const SvxBoxInfoItem* pNewInner, BOOL bRecord )
+{
+ ScDocument* pDoc = GetViewData()->GetDocument();
+ ScMarkData aFuncMark( GetViewData()->GetMarkData() ); // local copy for UnmarkFiltered
+ ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+
+ ScRange aMarkRange;
+ aFuncMark.MarkToSimple();
+ BOOL bMulti = aFuncMark.IsMultiMarked();
+ if (bMulti)
+ aFuncMark.GetMultiMarkArea( aMarkRange );
+ else if (aFuncMark.IsMarked())
+ aFuncMark.GetMarkArea( aMarkRange );
+ else
+ {
+ aMarkRange = ScRange( GetViewData()->GetCurX(),
+ GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
+ DoneBlockMode();
+ InitOwnBlockMode();
+ aFuncMark.SetMarkArea(aMarkRange);
+ MarkDataChanged();
+ }
+
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+
+ ScDocShellModificator aModificator( *pDocSh );
+
+ if (bRecord)
+ {
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ SCTAB nStartTab = aMarkRange.aStart.Tab();
+ SCTAB nTabCount = pDoc->GetTableCount();
+ pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
+ for (SCTAB i=0; i<nTabCount; i++)
+ if (i != nStartTab && aFuncMark.GetTableSelect(i))
+ pUndoDoc->AddUndoTab( i, i );
+
+ ScRange aCopyRange = aMarkRange;
+ aCopyRange.aStart.SetTab(0);
+ aCopyRange.aEnd.SetTab(nTabCount-1);
+ pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pUndoDoc, &aFuncMark );
+
+ pDocSh->GetUndoManager()->AddUndoAction(
+ new ScUndoSelectionAttr(
+ pDocSh, aFuncMark,
+ aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), aMarkRange.aStart.Tab(),
+ aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), aMarkRange.aEnd.Tab(),
+ pUndoDoc, bMulti, &rAttr, pNewOuter, pNewInner ) );
+ }
+
+ USHORT nExt = SC_PF_TESTMERGE;
+ pDocSh->UpdatePaintExt( nExt, aMarkRange ); // content before the change
+
+ pDoc->ApplySelectionFrame( aFuncMark, pNewOuter, pNewInner );
+
+ pDocSh->UpdatePaintExt( nExt, aMarkRange ); // content after the change
+
+ aFuncMark.MarkToMulti();
+ pDoc->ApplySelectionPattern( rAttr, aFuncMark );
+
+ pDocSh->PostPaint( aMarkRange, PAINT_GRID, nExt );
+ pDocSh->UpdateOle(GetViewData());
+ aModificator.SetDocumentModified();
+ CellContentChanged();
+
+ StartFormatArea();
+}
+
+// nur Pattern
+
+void ScViewFunc::ApplySelectionPattern( const ScPatternAttr& rAttr,
+ BOOL bRecord, BOOL bCursorOnly )
+{
+ ScViewData* pViewData = GetViewData();
+ ScDocShell* pDocSh = pViewData->GetDocShell();
+ ScDocument* pDoc = pDocSh->GetDocument();
+ ScMarkData aFuncMark( pViewData->GetMarkData() ); // local copy for UnmarkFiltered
+ ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+
+ // State from old ItemSet doesn't matter for paint flags, as any change will be
+ // from SFX_ITEM_SET in the new ItemSet (default is ignored in ApplyPattern).
+ // New alignment is checked (check in PostPaint isn't enough) in case a right
+ // alignment is changed to left.
+ const SfxItemSet& rNewSet = rAttr.GetItemSet();
+ BOOL bSetLines = rNewSet.GetItemState( ATTR_BORDER, TRUE ) == SFX_ITEM_SET ||
+ rNewSet.GetItemState( ATTR_SHADOW, TRUE ) == SFX_ITEM_SET;
+ BOOL bSetAlign = rNewSet.GetItemState( ATTR_HOR_JUSTIFY, TRUE ) == SFX_ITEM_SET;
+
+ USHORT nExtFlags = 0;
+ if ( bSetLines )
+ nExtFlags |= SC_PF_LINES;
+ if ( bSetAlign )
+ nExtFlags |= SC_PF_WHOLEROWS;
+
+ ScDocShellModificator aModificator( *pDocSh );
+
+ BOOL bMulti = aFuncMark.IsMultiMarked();
+ aFuncMark.MarkToMulti();
+ BOOL bOnlyTab = (!aFuncMark.IsMultiMarked() && !bCursorOnly && aFuncMark.GetSelectCount() > 1);
+ if (bOnlyTab)
+ {
+ SCCOL nCol = pViewData->GetCurX();
+ SCROW nRow = pViewData->GetCurY();
+ SCTAB nTab = pViewData->GetTabNo();
+ aFuncMark.SetMarkArea(ScRange(nCol,nRow,nTab));
+ aFuncMark.MarkToMulti();
+ }
+
+ ScRangeList aChangeRanges;
+
+ if (aFuncMark.IsMultiMarked() && !bCursorOnly)
+ {
+ ScRange aMarkRange;
+ aFuncMark.GetMultiMarkArea( aMarkRange );
+ SCTAB nTabCount = pDoc->GetTableCount();
+ for ( SCTAB i = 0; i < nTabCount; ++i )
+ {
+ if ( aFuncMark.GetTableSelect( i ) )
+ {
+ ScRange aChangeRange( aMarkRange );
+ aChangeRange.aStart.SetTab( i );
+ aChangeRange.aEnd.SetTab( i );
+ aChangeRanges.Append( aChangeRange );
+ }
+ }
+
+ SCCOL nStartCol = aMarkRange.aStart.Col();
+ SCROW nStartRow = aMarkRange.aStart.Row();
+ SCTAB nStartTab = aMarkRange.aStart.Tab();
+ SCCOL nEndCol = aMarkRange.aEnd.Col();
+ SCROW nEndRow = aMarkRange.aEnd.Row();
+ SCTAB nEndTab = aMarkRange.aEnd.Tab();
+
+ if (bRecord)
+ {
+ ScRange aCopyRange = aMarkRange;
+ aCopyRange.aStart.SetTab(0);
+ aCopyRange.aEnd.SetTab(nTabCount-1);
+
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
+ for (SCTAB i=0; i<nTabCount; i++)
+ if (i != nStartTab && aFuncMark.GetTableSelect(i))
+ pUndoDoc->AddUndoTab( i, i );
+ pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pUndoDoc, &aFuncMark );
+
+ aFuncMark.MarkToMulti();
+
+ pDocSh->GetUndoManager()->AddUndoAction(
+ new ScUndoSelectionAttr(
+ pDocSh, aFuncMark,
+ nStartCol, nStartRow, nStartTab,
+ nEndCol, nEndRow, nEndTab,
+ pUndoDoc, bMulti, &rAttr ) );
+ }
+
+ pDoc->ApplySelectionPattern( rAttr, aFuncMark );
+
+ pDocSh->PostPaint( nStartCol, nStartRow, nStartTab,
+ nEndCol, nEndRow, nEndTab,
+ PAINT_GRID, nExtFlags | SC_PF_TESTMERGE );
+ pDocSh->UpdateOle(GetViewData());
+ aModificator.SetDocumentModified();
+ CellContentChanged();
+ }
+ else // einzelne Zelle - Undo einfacher
+ {
+ SCCOL nCol = pViewData->GetCurX();
+ SCROW nRow = pViewData->GetCurY();
+ SCTAB nTab = pViewData->GetTabNo();
+ aChangeRanges.Append( ScRange( nCol, nRow, nTab ) );
+ ScPatternAttr* pOldPat = new ScPatternAttr(*pDoc->GetPattern( nCol, nRow, nTab ));
+
+ pDoc->ApplyPattern( nCol, nRow, nTab, rAttr );
+
+ const ScPatternAttr* pNewPat = pDoc->GetPattern( nCol, nRow, nTab );
+
+ if (bRecord)
+ {
+ pDocSh->GetUndoManager()->AddUndoAction(
+ new ScUndoCursorAttr( pDocSh,
+ nCol, nRow, nTab,
+ pOldPat, pNewPat, &rAttr,
+ FALSE ) ); // FALSE = nicht automatisch
+ }
+ delete pOldPat; // wird im Undo kopiert (Pool)
+
+ pDocSh->PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PAINT_GRID, nExtFlags | SC_PF_TESTMERGE );
+ pDocSh->UpdateOle(GetViewData());
+ aModificator.SetDocumentModified();
+ CellContentChanged();
+ }
+
+ // #i97876# Spreadsheet data changes are not notified
+ ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
+ if ( pModelObj && pModelObj->HasChangesListeners() )
+ {
+ ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aProperties;
+ sal_Int32 nCount = 0;
+ const SfxItemPropertyMap* pMap = ScCellObj::GetCellPropertyMap();
+ PropertyEntryVector_t aPropVector = pMap->getPropertyEntries();
+ for ( USHORT nWhich = ATTR_PATTERN_START; nWhich <= ATTR_PATTERN_END; ++nWhich )
+ {
+ const SfxPoolItem* pItem = 0;
+ if ( rNewSet.GetItemState( nWhich, TRUE, &pItem ) == SFX_ITEM_SET && pItem )
+ {
+ PropertyEntryVector_t::const_iterator aIt = aPropVector.begin();
+ while ( aIt != aPropVector.end())
+ {
+ if ( aIt->nWID == nWhich )
+ {
+ ::com::sun::star::uno::Any aVal;
+ pItem->QueryValue( aVal, aIt->nMemberId );
+ aProperties.realloc( nCount + 1 );
+ aProperties[ nCount ].Name = aIt->sName;
+ aProperties[ nCount ].Value <<= aVal;
+ ++nCount;
+ }
+ ++aIt;
+ }
+ }
+ }
+ pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "attribute" ) ), aChangeRanges, aProperties );
+ }
+
+ StartFormatArea();
+}
+
+void ScViewFunc::ApplyUserItemSet( const SfxItemSet& rItemSet )
+{
+ // ItemSet from UI, may have different pool
+
+ BOOL bOnlyNotBecauseOfMatrix;
+ if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
+ {
+ ErrorMessage(STR_PROTECTIONERR);
+ return;
+ }
+
+ ScPatternAttr aNewAttrs( GetViewData()->GetDocument()->GetPool() );
+ SfxItemSet& rNewSet = aNewAttrs.GetItemSet();
+ rNewSet.Put( rItemSet, FALSE );
+ ApplySelectionPattern( aNewAttrs );
+
+ AdjustBlockHeight();
+}
+
+const SfxStyleSheet* ScViewFunc::GetStyleSheetFromMarked()
+{
+ // Don't use UnmarkFiltered in slot state functions, for performance reasons.
+ // The displayed state is always that of the whole selection including filtered rows.
+
+ const ScStyleSheet* pSheet = NULL;
+ ScViewData* pViewData = GetViewData();
+ ScDocument* pDoc = pViewData->GetDocument();
+ ScMarkData& rMark = pViewData->GetMarkData();
+
+ if ( rMark.IsMarked() || rMark.IsMultiMarked() )
+ pSheet = pDoc->GetSelectionStyle( rMark ); // MarkToMulti isn't necessary
+ else
+ pSheet = pDoc->GetStyle( pViewData->GetCurX(),
+ pViewData->GetCurY(),
+ pViewData->GetTabNo() );
+
+ return pSheet;
+}
+
+void ScViewFunc::SetStyleSheetToMarked( SfxStyleSheet* pStyleSheet, BOOL bRecord )
+{
+ // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
+ BOOL bOnlyNotBecauseOfMatrix;
+ if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
+ {
+ ErrorMessage(STR_PROTECTIONERR);
+ return;
+ }
+
+ if ( !pStyleSheet) return;
+ // -------------------------------------------------------------------
+
+ ScViewData* pViewData = GetViewData();
+ ScDocShell* pDocSh = pViewData->GetDocShell();
+ ScDocument* pDoc = pDocSh->GetDocument();
+ ScMarkData aFuncMark( pViewData->GetMarkData() ); // local copy for UnmarkFiltered
+ ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
+ SCTAB nTabCount = pDoc->GetTableCount();
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+
+ ScDocShellModificator aModificator( *pDocSh );
+
+ if ( aFuncMark.IsMarked() || aFuncMark.IsMultiMarked() )
+ {
+ ScRange aMarkRange;
+ aFuncMark.MarkToMulti();
+ aFuncMark.GetMultiMarkArea( aMarkRange );
+
+ if ( bRecord )
+ {
+ SCTAB nTab = pViewData->GetTabNo();
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nTab, nTab );
+ for (SCTAB i=0; i<nTabCount; i++)
+ if (i != nTab && aFuncMark.GetTableSelect(i))
+ pUndoDoc->AddUndoTab( i, i );
+
+ ScRange aCopyRange = aMarkRange;
+ aCopyRange.aStart.SetTab(0);
+ aCopyRange.aEnd.SetTab(nTabCount-1);
+ pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, TRUE, pUndoDoc, &aFuncMark );
+ aFuncMark.MarkToMulti();
+
+ String aName = pStyleSheet->GetName();
+ pDocSh->GetUndoManager()->AddUndoAction(
+ new ScUndoSelectionStyle( pDocSh, aFuncMark, aMarkRange, aName, pUndoDoc ) );
+ }
+
+ pDoc->ApplySelectionStyle( (ScStyleSheet&)*pStyleSheet, aFuncMark );
+
+ if (!AdjustBlockHeight())
+ pViewData->GetDocShell()->PostPaint( aMarkRange, PAINT_GRID );
+
+ aFuncMark.MarkToSimple();
+ }
+ else
+ {
+ SCCOL nCol = pViewData->GetCurX();
+ SCROW nRow = pViewData->GetCurY();
+ SCTAB nTab = pViewData->GetTabNo();
+
+ if ( bRecord )
+ {
+ ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nTab, nTab );
+ for (SCTAB i=0; i<nTabCount; i++)
+ if (i != nTab && aFuncMark.GetTableSelect(i))
+ pUndoDoc->AddUndoTab( i, i );
+
+ ScRange aCopyRange( nCol, nRow, 0, nCol, nRow, nTabCount-1 );
+ pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, FALSE, pUndoDoc );
+
+ ScRange aMarkRange ( nCol, nRow, nTab );
+ ScMarkData aUndoMark = aFuncMark;
+ aUndoMark.SetMultiMarkArea( aMarkRange );
+
+ String aName = pStyleSheet->GetName();
+ pDocSh->GetUndoManager()->AddUndoAction(
+ new ScUndoSelectionStyle( pDocSh, aUndoMark, aMarkRange, aName, pUndoDoc ) );
+ }
+
+ for (SCTAB i=0; i<nTabCount; i++)
+ if (aFuncMark.GetTableSelect(i))
+ pDoc->ApplyStyle( nCol, nRow, i, (ScStyleSheet&)*pStyleSheet );
+
+ if (!AdjustBlockHeight())
+ pViewData->GetDocShell()->PostPaintCell( nCol, nRow, nTab );
+
+ }
+
+ aModificator.SetDocumentModified();
+
+ StartFormatArea();
+}
+
+
+void ScViewFunc::RemoveStyleSheetInUse( SfxStyleSheet* pStyleSheet )
+{
+ if ( !pStyleSheet) return;
+ // -------------------------------------------------------------------
+
+ ScViewData* pViewData = GetViewData();
+ ScDocument* pDoc = pViewData->GetDocument();
+ ScDocShell* pDocSh = pViewData->GetDocShell();
+
+ ScDocShellModificator aModificator( *pDocSh );
+
+ VirtualDevice aVirtDev;
+ aVirtDev.SetMapMode(MAP_PIXEL);
+ pDoc->StyleSheetChanged( pStyleSheet, TRUE, &aVirtDev,
+ pViewData->GetPPTX(),
+ pViewData->GetPPTY(),
+ pViewData->GetZoomX(),
+ pViewData->GetZoomY() );
+
+ pDocSh->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID|PAINT_LEFT );
+ aModificator.SetDocumentModified();
+
+ ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
+ if (pHdl)
+ pHdl->ForgetLastPattern();
+}
+
+void ScViewFunc::UpdateStyleSheetInUse( SfxStyleSheet* pStyleSheet )
+{
+ if ( !pStyleSheet) return;
+ // -------------------------------------------------------------------
+
+ ScViewData* pViewData = GetViewData();
+ ScDocument* pDoc = pViewData->GetDocument();
+ ScDocShell* pDocSh = pViewData->GetDocShell();
+
+ ScDocShellModificator aModificator( *pDocSh );
+
+ VirtualDevice aVirtDev;
+ aVirtDev.SetMapMode(MAP_PIXEL);
+ pDoc->StyleSheetChanged( pStyleSheet, FALSE, &aVirtDev,
+ pViewData->GetPPTX(),
+ pViewData->GetPPTY(),
+ pViewData->GetZoomX(),
+ pViewData->GetZoomY() );
+
+ pDocSh->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID|PAINT_LEFT );
+ aModificator.SetDocumentModified();
+
+ ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
+ if (pHdl)
+ pHdl->ForgetLastPattern();
+}
+
+// Zellen einfuegen - Undo OK
+
+BOOL ScViewFunc::InsertCells( InsCellCmd eCmd, BOOL bRecord, BOOL bPartOfPaste )
+{
+ ScRange aRange;
+ if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE)
+ {
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+ const ScMarkData& rMark = GetViewData()->GetMarkData();
+ BOOL bSuccess = pDocSh->GetDocFunc().InsertCells( aRange, &rMark, eCmd, bRecord, FALSE, bPartOfPaste );
+ if (bSuccess)
+ {
+ pDocSh->UpdateOle(GetViewData());
+ CellContentChanged();
+
+ // #i97876# Spreadsheet data changes are not notified
+ ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
+ if ( pModelObj && pModelObj->HasChangesListeners() )
+ {
+ if ( eCmd == INS_INSROWS || eCmd == INS_INSCOLS )
+ {
+ ScRangeList aChangeRanges;
+ aChangeRanges.Append( aRange );
+ ::rtl::OUString aOperation = ( eCmd == INS_INSROWS ?
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert-rows" ) ) :
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert-columns" ) ) );
+ pModelObj->NotifyChanges( aOperation, aChangeRanges );
+ }
+ }
+ }
+ return bSuccess;
+ }
+ else
+ {
+ ErrorMessage(STR_NOMULTISELECT);
+ return FALSE;
+ }
+}
+
+// Zellen loeschen - Undo OK
+
+void ScViewFunc::DeleteCells( DelCellCmd eCmd, BOOL bRecord )
+{
+ ScRange aRange;
+ if ( GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
+ {
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+ const ScMarkData& rMark = GetViewData()->GetMarkData();
+
+ // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
+ if ( pDocSh->IsDocShared() && ( eCmd == DEL_DELROWS || eCmd == DEL_DELCOLS ) )
+ {
+ ScRange aDelRange( aRange.aStart );
+ SCCOLROW nCount = 0;
+ if ( eCmd == DEL_DELROWS )
+ {
+ nCount = sal::static_int_cast< SCCOLROW >( aRange.aEnd.Row() - aRange.aStart.Row() + 1 );
+ }
+ else
+ {
+ nCount = sal::static_int_cast< SCCOLROW >( aRange.aEnd.Col() - aRange.aStart.Col() + 1 );
+ }
+ while ( nCount > 0 )
+ {
+ pDocSh->GetDocFunc().DeleteCells( aDelRange, &rMark, eCmd, bRecord, FALSE );
+ --nCount;
+ }
+ }
+ else
+ {
+ pDocSh->GetDocFunc().DeleteCells( aRange, &rMark, eCmd, bRecord, FALSE );
+ }
+
+ pDocSh->UpdateOle(GetViewData());
+ CellContentChanged();
+
+ // #i97876# Spreadsheet data changes are not notified
+ ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
+ if ( pModelObj && pModelObj->HasChangesListeners() )
+ {
+ if ( eCmd == DEL_DELROWS || eCmd == DEL_DELCOLS )
+ {
+ ScRangeList aChangeRanges;
+ aChangeRanges.Append( aRange );
+ ::rtl::OUString aOperation = ( eCmd == DEL_DELROWS ?
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete-rows" ) ) :
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete-columns" ) ) );
+ pModelObj->NotifyChanges( aOperation, aChangeRanges );
+ }
+ }
+
+ // #58106# Cursor direkt hinter den geloeschten Bereich setzen
+ SCCOL nCurX = GetViewData()->GetCurX();
+ SCROW nCurY = GetViewData()->GetCurY();
+ if ( eCmd==DEL_CELLSLEFT || eCmd==DEL_DELCOLS )
+ nCurX = aRange.aStart.Col();
+ else
+ nCurY = aRange.aStart.Row();
+ SetCursor( nCurX, nCurY );
+ }
+ else
+ {
+ if (eCmd == DEL_DELCOLS)
+ DeleteMulti( FALSE, bRecord );
+ else if (eCmd == DEL_DELROWS)
+ DeleteMulti( TRUE, bRecord );
+ else
+ ErrorMessage(STR_NOMULTISELECT);
+ }
+
+ Unmark();
+}
+
+void ScViewFunc::DeleteMulti( BOOL bRows, BOOL bRecord )
+{
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+ ScDocShellModificator aModificator( *pDocSh );
+ SCTAB nTab = GetViewData()->GetTabNo();
+ ScDocument* pDoc = pDocSh->GetDocument();
+ ScMarkData aFuncMark( GetViewData()->GetMarkData() ); // local copy for UnmarkFiltered
+ ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+ SCCOLROW* pRanges = new SCCOLROW[MAXCOLROWCOUNT];
+ SCCOLROW nRangeCnt = bRows ? aFuncMark.GetMarkRowRanges( pRanges ) :
+ aFuncMark.GetMarkColumnRanges( pRanges );
+ if (nRangeCnt == 0)
+ {
+ pRanges[0] = pRanges[1] = bRows ? static_cast<SCCOLROW>(GetViewData()->GetCurY()) : static_cast<SCCOLROW>(GetViewData()->GetCurX());
+ nRangeCnt = 1;
+ }
+
+ // Test ob erlaubt
+
+ SCCOLROW* pOneRange = pRanges;
+ USHORT nErrorId = 0;
+ BOOL bNeedRefresh = FALSE;
+ SCCOLROW nRangeNo;
+ for (nRangeNo=0; nRangeNo<nRangeCnt && !nErrorId; nRangeNo++)
+ {
+ SCCOLROW nStart = *(pOneRange++);
+ SCCOLROW nEnd = *(pOneRange++);
+
+ SCCOL nStartCol, nEndCol;
+ SCROW nStartRow, nEndRow;
+ if ( bRows )
+ {
+ nStartCol = 0;
+ nEndCol = MAXCOL;
+ nStartRow = static_cast<SCROW>(nStart);
+ nEndRow = static_cast<SCROW>(nEnd);
+ }
+ else
+ {
+ nStartCol = static_cast<SCCOL>(nStart);
+ nEndCol = static_cast<SCCOL>(nEnd);
+ nStartRow = 0;
+ nEndRow = MAXROW;
+ }
+
+ // cell protection (only needed for first range, as all following cells are moved)
+ if ( nRangeNo == 0 )
+ {
+ // test to the end of the sheet
+ ScEditableTester aTester( pDoc, nTab, nStartCol, nStartRow, MAXCOL, MAXROW );
+ if (!aTester.IsEditable())
+ nErrorId = aTester.GetMessageId();
+ }
+
+ // merged cells
+ SCCOL nMergeStartX = nStartCol;
+ SCROW nMergeStartY = nStartRow;
+ SCCOL nMergeEndX = nEndCol;
+ SCROW nMergeEndY = nEndRow;
+ pDoc->ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, nTab );
+ pDoc->ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, nTab );
+
+ if ( nMergeStartX != nStartCol || nMergeStartY != nStartRow )
+ {
+ // Disallow deleting parts of a merged cell.
+ // Deleting the start is allowed (merge is removed), so the end doesn't have to be checked.
+
+ nErrorId = STR_MSSG_DELETECELLS_0;
+ }
+ if ( nMergeEndX != nEndCol || nMergeEndY != nEndRow )
+ {
+ // detect if the start of a merged cell is deleted, so the merge flags can be refreshed
+
+ bNeedRefresh = TRUE;
+ }
+ }
+
+ if ( nErrorId )
+ {
+ ErrorMessage( nErrorId );
+ delete[] pRanges;
+ return;
+ }
+
+ // ausfuehren
+
+ WaitObject aWait( GetFrameWin() ); // wichtig wegen TrackFormulas bei UpdateReference
+
+ ScDocument* pUndoDoc = NULL;
+ ScRefUndoData* pUndoData = NULL;
+ if (bRecord)
+ {
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, !bRows, bRows ); // Zeilenhoehen
+
+ pOneRange = pRanges;
+ for (nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
+ {
+ SCCOLROW nStart = *(pOneRange++);
+ SCCOLROW nEnd = *(pOneRange++);
+ if (bRows)
+ pDoc->CopyToDocument( 0,nStart,nTab, MAXCOL,nEnd,nTab, IDF_ALL,FALSE,pUndoDoc );
+ else
+ pDoc->CopyToDocument( static_cast<SCCOL>(nStart),0,nTab,
+ static_cast<SCCOL>(nEnd),MAXROW,nTab,
+ IDF_ALL,FALSE,pUndoDoc );
+ }
+
+ // alle Formeln wegen Referenzen
+ SCTAB nTabCount = pDoc->GetTableCount();
+ pUndoDoc->AddUndoTab( 0, nTabCount-1, FALSE, FALSE );
+ pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,MAXTAB, IDF_FORMULA,FALSE,pUndoDoc );
+
+ pUndoData = new ScRefUndoData( pDoc );
+
+ pDoc->BeginDrawUndo();
+ }
+
+ pOneRange = &pRanges[2*nRangeCnt]; // rueckwaerts
+ for (nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
+ {
+ SCCOLROW nEnd = *(--pOneRange);
+ SCCOLROW nStart = *(--pOneRange);
+
+ if (bRows)
+ pDoc->DeleteRow( 0,nTab, MAXCOL,nTab, nStart, static_cast<SCSIZE>(nEnd-nStart+1) );
+ else
+ pDoc->DeleteCol( 0,nTab, MAXROW,nTab, static_cast<SCCOL>(nStart), static_cast<SCSIZE>(nEnd-nStart+1) );
+ }
+
+ if (bNeedRefresh)
+ {
+ SCCOLROW nFirstStart = pRanges[0];
+ SCCOL nStartCol = bRows ? 0 : static_cast<SCCOL>(nFirstStart);
+ SCROW nStartRow = bRows ? static_cast<SCROW>(nFirstStart) : 0;
+ SCCOL nEndCol = MAXCOL;
+ SCROW nEndRow = MAXROW;
+
+ pDoc->RemoveFlagsTab( nStartCol, nStartRow, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
+ pDoc->ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow, nTab, TRUE );
+ }
+
+ if (bRecord)
+ {
+ pDocSh->GetUndoManager()->AddUndoAction(
+ new ScUndoDeleteMulti( pDocSh, bRows, bNeedRefresh, nTab, pRanges, nRangeCnt,
+ pUndoDoc, pUndoData ) );
+ }
+
+ if (!AdjustRowHeight(0, MAXROW))
+ {
+ if (bRows)
+ pDocSh->PostPaint( 0,pRanges[0],nTab, MAXCOL,MAXROW,nTab, PAINT_GRID | PAINT_LEFT );
+ else
+ pDocSh->PostPaint( static_cast<SCCOL>(pRanges[0]),0,nTab,
+ MAXCOL,MAXROW,nTab, PAINT_GRID | PAINT_TOP );
+ }
+ aModificator.SetDocumentModified();
+
+ CellContentChanged();
+
+ // #58106# Cursor direkt hinter den ersten geloeschten Bereich setzen
+ SCCOL nCurX = GetViewData()->GetCurX();
+ SCROW nCurY = GetViewData()->GetCurY();
+ if ( bRows )
+ nCurY = pRanges[0];
+ else
+ nCurX = static_cast<SCCOL>(pRanges[0]);
+ SetCursor( nCurX, nCurY );
+
+ delete[] pRanges;
+
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
+}
+
+// Inhalte loeschen
+
+void ScViewFunc::DeleteContents( USHORT nFlags, BOOL bRecord )
+{
+ // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
+ BOOL bOnlyNotBecauseOfMatrix;
+ BOOL bEditable = SelectionEditable( &bOnlyNotBecauseOfMatrix );
+ if ( !bEditable )
+ {
+ if ( !(bOnlyNotBecauseOfMatrix &&
+ ((nFlags & (IDF_ATTRIB | IDF_EDITATTR)) == nFlags)) )
+ {
+ ErrorMessage(bOnlyNotBecauseOfMatrix ? STR_MATRIXFRAGMENTERR : STR_PROTECTIONERR);
+ return;
+ }
+ }
+
+ ScRange aMarkRange;
+ BOOL bSimple = FALSE;
+
+ ScDocument* pDoc = GetViewData()->GetDocument();
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+ ScMarkData aFuncMark( GetViewData()->GetMarkData() ); // local copy for UnmarkFiltered
+ ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
+
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+
+ ScDocShellModificator aModificator( *pDocSh );
+
+ if ( !aFuncMark.IsMarked() && !aFuncMark.IsMultiMarked() )
+ {
+ aMarkRange.aStart.SetCol(GetViewData()->GetCurX());
+ aMarkRange.aStart.SetRow(GetViewData()->GetCurY());
+ aMarkRange.aStart.SetTab(GetViewData()->GetTabNo());
+ aMarkRange.aEnd = aMarkRange.aStart;
+ if ( pDoc->HasAttrib( aMarkRange, HASATTR_MERGED ) )
+ {
+// InitOwnBlockMode();
+ aFuncMark.SetMarkArea( aMarkRange );
+ }
+ else
+ bSimple = TRUE;
+ }
+
+ aFuncMark.SetMarking(FALSE); // for MarkToMulti
+ aFuncMark.MarkToSimple(); // before bMulti test below
+
+ DBG_ASSERT( aFuncMark.IsMarked() || aFuncMark.IsMultiMarked() || bSimple, "delete what?" );
+
+ ScDocument* pUndoDoc = NULL;
+ BOOL bMulti = !bSimple && aFuncMark.IsMultiMarked();
+ if (!bSimple)
+ {
+ aFuncMark.MarkToMulti();
+ aFuncMark.GetMultiMarkArea( aMarkRange );
+ }
+ ScRange aExtendedRange(aMarkRange);
+ if (!bSimple)
+ {
+ if ( pDoc->ExtendMerge( aExtendedRange, TRUE ) )
+ bMulti = FALSE;
+ }
+
+ // keine Objekte auf geschuetzten Tabellen
+ BOOL bObjects = FALSE;
+ if ( nFlags & IDF_OBJECTS )
+ {
+ bObjects = TRUE;
+ SCTAB nTabCount = pDoc->GetTableCount();
+ for (SCTAB nTab=0; nTab<nTabCount; nTab++)
+ if (aFuncMark.GetTableSelect(nTab) && pDoc->IsTabProtected(nTab))
+ bObjects = FALSE;
+ }
+
+ USHORT nExtFlags = 0; // extra flags are needed only if attributes are deleted
+ if ( nFlags & IDF_ATTRIB )
+ pDocSh->UpdatePaintExt( nExtFlags, aMarkRange );
+
+ // Reihenfolge:
+ // 1) BeginDrawUndo
+ // 2) Objekte loeschen (DrawUndo wird gefuellt)
+ // 3) Inhalte fuer Undo kopieren
+ // 4) Inhalte loeschen
+ // 5) Undo-Aktion anlegen
+
+ BOOL bDrawUndo = bObjects || ( nFlags & IDF_NOTE ); // needed for shown notes
+ if ( bDrawUndo && bRecord )
+ pDoc->BeginDrawUndo();
+
+ if (bObjects)
+ {
+ if (bMulti)
+ pDoc->DeleteObjectsInSelection( aFuncMark );
+ else
+ pDoc->DeleteObjectsInArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
+/*!*/ aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(),
+ aFuncMark );
+ }
+
+ if ( bRecord )
+ {
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ SCTAB nTab = aMarkRange.aStart.Tab();
+ pUndoDoc->InitUndo( pDoc, nTab, nTab );
+ SCTAB nTabCount = pDoc->GetTableCount();
+ for (SCTAB i=0; i<nTabCount; i++)
+ if (i != nTab && aFuncMark.GetTableSelect(i))
+ pUndoDoc->AddUndoTab( i, i );
+ ScRange aCopyRange = aExtendedRange;
+ aCopyRange.aStart.SetTab(0);
+ aCopyRange.aEnd.SetTab(nTabCount-1);
+
+ // bei "Format/Standard" alle Attribute kopieren, weil CopyToDocument
+ // nur mit IDF_HARDATTR zu langsam ist:
+ USHORT nUndoDocFlags = nFlags;
+ if (nFlags & IDF_ATTRIB)
+ nUndoDocFlags |= IDF_ATTRIB;
+ if (nFlags & IDF_EDITATTR) // Edit-Engine-Attribute
+ nUndoDocFlags |= IDF_STRING; // -> Zellen werden geaendert
+ if (nFlags & IDF_NOTE)
+ nUndoDocFlags |= IDF_CONTENTS; // #68795# copy all cells with their notes
+ // do not copy note captions to undo document
+ nUndoDocFlags |= IDF_NOCAPTIONS;
+ pDoc->CopyToDocument( aCopyRange, nUndoDocFlags, bMulti, pUndoDoc, &aFuncMark );
+ }
+
+ HideAllCursors(); // falls Zusammenfassung aufgehoben wird
+ if (bSimple)
+ pDoc->DeleteArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
+ aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(),
+ aFuncMark, nFlags );
+ else
+ {
+ pDoc->DeleteSelection( nFlags, aFuncMark );
+// aFuncMark.MarkToSimple();
+ }
+
+ if ( bRecord )
+ {
+ pDocSh->GetUndoManager()->AddUndoAction(
+ new ScUndoDeleteContents( pDocSh, aFuncMark, aExtendedRange,
+ pUndoDoc, bMulti, nFlags, bDrawUndo ) );
+ }
+
+ if (!AdjustRowHeight( aExtendedRange.aStart.Row(), aExtendedRange.aEnd.Row() ))
+ pDocSh->PostPaint( aExtendedRange, PAINT_GRID, nExtFlags );
+
+ pDocSh->UpdateOle(GetViewData());
+
+ // #i97876# Spreadsheet data changes are not notified
+ ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
+ if ( pModelObj && pModelObj->HasChangesListeners() )
+ {
+ ScRangeList aChangeRanges;
+ if ( bSimple )
+ {
+ aChangeRanges.Append( aMarkRange );
+ }
+ else
+ {
+ aFuncMark.FillRangeListWithMarks( &aChangeRanges, FALSE );
+ }
+ pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges );
+ }
+
+ aModificator.SetDocumentModified();
+ CellContentChanged();
+ ShowAllCursors();
+
+ if ( nFlags & IDF_ATTRIB )
+ {
+ if ( nFlags & IDF_CONTENTS )
+ ForgetFormatArea();
+ else
+ StartFormatArea(); // Attribute loeschen ist auch Attributierung
+ }
+}
+
+// Spaltenbreiten/Zeilenhoehen (ueber Header) - Undo OK
+
+void ScViewFunc::SetWidthOrHeight( BOOL bWidth, SCCOLROW nRangeCnt, SCCOLROW* pRanges,
+ ScSizeMode eMode, USHORT nSizeTwips,
+ BOOL bRecord, BOOL bPaint, ScMarkData* pMarkData )
+{
+ if (nRangeCnt == 0)
+ return;
+
+ // use view's mark if none specified
+ if ( !pMarkData )
+ pMarkData = &GetViewData()->GetMarkData();
+
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+ ScDocument* pDoc = pDocSh->GetDocument();
+ SCTAB nTabCount = pDoc->GetTableCount();
+ SCTAB nFirstTab = pMarkData->GetFirstSelected();
+ SCTAB nCurTab = GetViewData()->GetTabNo();
+ SCTAB nTab;
+ if (bRecord && !pDoc->IsUndoEnabled())
+ bRecord = FALSE;
+
+ ScDocShellModificator aModificator( *pDocSh );
+
+ BOOL bAllowed = TRUE;
+ for (nTab=0; nTab<nTabCount && bAllowed; nTab++)
+ if (pMarkData->GetTableSelect(nTab))
+ {
+ for ( SCCOLROW i=0; i<nRangeCnt && bAllowed; i++ )
+ {
+ BOOL bOnlyMatrix;
+ if (bWidth)
+ bAllowed = pDoc->IsBlockEditable( nTab,
+ static_cast<SCCOL>(pRanges[2*i]),0,
+ static_cast<SCCOL>(pRanges[2*i+1]),MAXROW,
+ &bOnlyMatrix ) || bOnlyMatrix;
+ else
+ bAllowed = pDoc->IsBlockEditable( nTab, 0,pRanges[2*i],
+ MAXCOL,pRanges[2*i+1], &bOnlyMatrix ) ||
+ bOnlyMatrix;
+ }
+ }
+ if ( !bAllowed )
+ {
+ ErrorMessage(STR_PROTECTIONERR);
+ return;
+ }
+
+ SCCOLROW nStart = pRanges[0];
+ SCCOLROW nEnd = pRanges[2*nRangeCnt-1];
+
+ BOOL bFormula = FALSE;
+ if ( eMode == SC_SIZE_OPTIMAL )
+ {
+ const ScViewOptions& rOpts = GetViewData()->GetOptions();
+ bFormula = rOpts.GetOption( VOPT_FORMULAS );
+ }
+
+ ScDocument* pUndoDoc = NULL;
+ ScOutlineTable* pUndoTab = NULL;
+ SCCOLROW* pUndoRanges = NULL;
+
+ if ( bRecord )
+ {
+ pDoc->BeginDrawUndo(); // Drawing Updates
+
+ pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+ for (nTab=0; nTab<nTabCount; nTab++)
+ if (pMarkData->GetTableSelect(nTab))
+ {
+ if (bWidth)
+ {
+ if ( nTab == nFirstTab )
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, TRUE, FALSE );
+ else
+ pUndoDoc->AddUndoTab( nTab, nTab, TRUE, FALSE );
+ pDoc->CopyToDocument( static_cast<SCCOL>(nStart), 0, nTab,
+ static_cast<SCCOL>(nEnd), MAXROW, nTab, IDF_NONE,
+ FALSE, pUndoDoc );
+ }
+ else
+ {
+ if ( nTab == nFirstTab )
+ pUndoDoc->InitUndo( pDoc, nTab, nTab, FALSE, TRUE );
+ else
+ pUndoDoc->AddUndoTab( nTab, nTab, FALSE, TRUE );
+ pDoc->CopyToDocument( 0, nStart, nTab, MAXCOL, nEnd, nTab, IDF_NONE, FALSE, pUndoDoc );
+ }
+ }
+
+ pUndoRanges = new SCCOLROW[ 2*nRangeCnt ];
+ memmove( pUndoRanges, pRanges, 2*nRangeCnt*sizeof(SCCOLROW) );
+
+ //! outlines from all tables?
+ ScOutlineTable* pTable = pDoc->GetOutlineTable( nCurTab );
+ if (pTable)
+ pUndoTab = new ScOutlineTable( *pTable );
+ }
+
+ if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
+ pMarkData->MarkToMulti();
+
+ BOOL bShow = nSizeTwips > 0 || eMode != SC_SIZE_DIRECT;
+ BOOL bOutline = FALSE;
+
+ for (nTab=0; nTab<nTabCount; nTab++)
+ if (pMarkData->GetTableSelect(nTab))
+ {
+ const SCCOLROW* pTabRanges = pRanges;
+
+ pDoc->IncSizeRecalcLevel( nTab ); // nicht fuer jede Spalte einzeln
+ pDoc->InitializeNoteCaptions( nTab );
+ for (SCCOLROW nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
+ {
+ SCCOLROW nStartNo = *(pTabRanges++);
+ SCCOLROW nEndNo = *(pTabRanges++);
+
+ if ( !bWidth ) // Hoehen immer blockweise
+ {
+ if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
+ {
+ BOOL bAll = ( eMode==SC_SIZE_OPTIMAL );
+ if (!bAll)
+ {
+ // fuer alle eingeblendeten CR_MANUALSIZE loeschen,
+ // dann SetOptimalHeight mit bShrink = FALSE
+ for (SCROW nRow = nStartNo; nRow <= nEndNo; ++nRow)
+ {
+ SCROW nLastRow = nRow;
+ if (pDoc->RowHidden(nRow, nTab, NULL, &nLastRow))
+ {
+ nRow = nLastRow;
+ continue;
+ }
+
+ BYTE nOld = pDoc->GetRowFlags(nRow, nTab);
+ if (nOld & CR_MANUALSIZE)
+ pDoc->SetRowFlags(nRow, nTab, nOld & ~CR_MANUALSIZE);
+ }
+ }
+
+ double nPPTX = GetViewData()->GetPPTX();
+ double nPPTY = GetViewData()->GetPPTY();
+ Fraction aZoomX = GetViewData()->GetZoomX();
+ Fraction aZoomY = GetViewData()->GetZoomY();
+
+ ScSizeDeviceProvider aProv(pDocSh);
+ if (aProv.IsPrinter())
+ {
+ nPPTX = aProv.GetPPTX();
+ nPPTY = aProv.GetPPTY();
+ aZoomX = aZoomY = Fraction( 1, 1 );
+ }
+
+ pDoc->SetOptimalHeight( nStartNo, nEndNo, nTab, nSizeTwips, aProv.GetDevice(),
+ nPPTX, nPPTY, aZoomX, aZoomY, bAll );
+ if (bAll)
+ pDoc->ShowRows( nStartNo, nEndNo, nTab, TRUE );
+
+ // Manual-Flag wird bei bAll=TRUE schon in SetOptimalHeight gesetzt
+ // (an bei Extra-Height, sonst aus).
+ }
+ else if ( eMode==SC_SIZE_DIRECT )
+ {
+ if (nSizeTwips)
+ {
+ pDoc->SetRowHeightRange( nStartNo, nEndNo, nTab, nSizeTwips );
+ pDoc->SetManualHeight( nStartNo, nEndNo, nTab, TRUE ); // height was set manually
+ }
+ pDoc->ShowRows( nStartNo, nEndNo, nTab, nSizeTwips != 0 );
+ }
+ else if ( eMode==SC_SIZE_SHOW )
+ {
+ pDoc->ShowRows( nStartNo, nEndNo, nTab, TRUE );
+ }
+ }
+ else // Spaltenbreiten
+ {
+ for (SCCOL nCol=static_cast<SCCOL>(nStartNo); nCol<=static_cast<SCCOL>(nEndNo); nCol++)
+ {
+ if ( eMode != SC_SIZE_VISOPT || !pDoc->ColHidden(nCol, nTab) )
+ {
+ USHORT nThisSize = nSizeTwips;
+
+ if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
+ nThisSize = nSizeTwips + GetOptimalColWidth( nCol, nTab, bFormula );
+ if ( nThisSize )
+ pDoc->SetColWidth( nCol, nTab, nThisSize );
+
+ pDoc->ShowCol( nCol, nTab, bShow );
+ }
+ }
+ }
+
+ // Outline anpassen
+
+ if (bWidth)
+ {
+ if ( pDoc->UpdateOutlineCol( static_cast<SCCOL>(nStartNo),
+ static_cast<SCCOL>(nEndNo), nTab, bShow ) )
+ bOutline = TRUE;
+ }
+ else
+ {
+ if ( pDoc->UpdateOutlineRow( nStartNo, nEndNo, nTab, bShow ) )
+ bOutline = TRUE;
+ }
+ }
+ pDoc->DecSizeRecalcLevel( nTab ); // nicht fuer jede Spalte einzeln
+ }
+
+
+ if (!bOutline)
+ DELETEZ(pUndoTab);
+
+ if (bRecord)
+ {
+ pDocSh->GetUndoManager()->AddUndoAction(
+ new ScUndoWidthOrHeight( pDocSh, *pMarkData,
+ nStart, nCurTab, nEnd, nCurTab,
+ pUndoDoc, nRangeCnt, pUndoRanges,
+ pUndoTab, eMode, nSizeTwips, bWidth ) );
+ }
+
+ for (nTab=0; nTab<nTabCount; nTab++)
+ if (pMarkData->GetTableSelect(nTab))
+ pDoc->UpdatePageBreaks( nTab );
+
+ GetViewData()->GetView()->UpdateScrollBars();
+
+ if (bPaint)
+ {
+ HideCursor();
+
+ for (nTab=0; nTab<nTabCount; nTab++)
+ if (pMarkData->GetTableSelect(nTab))
+ {
+ if (bWidth)
+ {
+ if (pDoc->HasAttrib( static_cast<SCCOL>(nStart),0,nTab,
+ static_cast<SCCOL>(nEnd),MAXROW,nTab,
+ HASATTR_MERGED | HASATTR_OVERLAPPED ))
+ nStart = 0;
+ if (nStart > 0) // weiter oben anfangen wegen Linien und Cursor
+ --nStart;
+ pDocSh->PostPaint( static_cast<SCCOL>(nStart), 0, nTab,
+ MAXCOL, MAXROW, nTab, PAINT_GRID | PAINT_TOP );
+ }
+ else
+ {
+ if (pDoc->HasAttrib( 0,nStart,nTab, MAXCOL,nEnd,nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ))
+ nStart = 0;
+ if (nStart != 0)
+ --nStart;
+ pDocSh->PostPaint( 0, nStart, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID | PAINT_LEFT );
+ }
+ }
+
+ pDocSh->UpdateOle(GetViewData());
+ aModificator.SetDocumentModified();
+
+ ShowCursor();
+ }
+
+ // #i97876# Spreadsheet data changes are not notified
+ if ( bWidth )
+ {
+ ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
+ if ( pModelObj && pModelObj->HasChangesListeners() )
+ {
+ ScRangeList aChangeRanges;
+ for ( nTab = 0; nTab < nTabCount; ++nTab )
+ {
+ if ( pMarkData->GetTableSelect( nTab ) )
+ {
+ const SCCOLROW* pTabRanges = pRanges;
+ for ( SCCOLROW nRange = 0; nRange < nRangeCnt; ++nRange )
+ {
+ SCCOL nStartCol = static_cast< SCCOL >( *(pTabRanges++) );
+ SCCOL nEndCol = static_cast< SCCOL >( *(pTabRanges++) );
+ for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol )
+ {
+ aChangeRanges.Append( ScRange( nCol, 0, nTab ) );
+ }
+ }
+ }
+ }
+ pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "column-resize" ) ), aChangeRanges );
+ }
+ }
+}
+
+// Spaltenbreiten/Zeilenhoehen (ueber Blockmarken)
+
+void ScViewFunc::SetMarkedWidthOrHeight( BOOL bWidth, ScSizeMode eMode, USHORT nSizeTwips,
+ BOOL bRecord, BOOL bPaint )
+{
+ ScMarkData& rMark = GetViewData()->GetMarkData();
+
+ rMark.MarkToMulti();
+ if (!rMark.IsMultiMarked())
+ {
+ SCCOL nCol = GetViewData()->GetCurX();
+ SCROW nRow = GetViewData()->GetCurY();
+ SCTAB nTab = GetViewData()->GetTabNo();
+ DoneBlockMode();
+ InitOwnBlockMode();
+ rMark.SetMultiMarkArea( ScRange( nCol,nRow,nTab ), TRUE );
+ MarkDataChanged();
+ }
+
+ SCCOLROW* pRanges = new SCCOLROW[MAXCOLROWCOUNT];
+ SCCOLROW nRangeCnt = 0;
+
+ if ( bWidth )
+ nRangeCnt = rMark.GetMarkColumnRanges( pRanges );
+ else
+ nRangeCnt = rMark.GetMarkRowRanges( pRanges );
+
+ SetWidthOrHeight( bWidth, nRangeCnt, pRanges, eMode, nSizeTwips, bRecord, bPaint );
+
+ delete[] pRanges;
+ rMark.MarkToSimple();
+}
+
+void ScViewFunc::ModifyCellSize( ScDirection eDir, BOOL bOptimal )
+{
+ //! Schrittweiten einstellbar
+ // Schrittweite ist auch Minimum
+ USHORT nStepX = STD_COL_WIDTH / 5;
+ USHORT nStepY = ScGlobal::nStdRowHeight;
+
+ ScModule* pScMod = SC_MOD();
+ BOOL bAnyEdit = pScMod->IsInputMode();
+ SCCOL nCol = GetViewData()->GetCurX();
+ SCROW nRow = GetViewData()->GetCurY();
+ SCTAB nTab = GetViewData()->GetTabNo();
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+ ScDocument* pDoc = pDocSh->GetDocument();
+
+ BOOL bAllowed, bOnlyMatrix;
+ if ( eDir == DIR_LEFT || eDir == DIR_RIGHT )
+ bAllowed = pDoc->IsBlockEditable( nTab, nCol,0, nCol,MAXROW, &bOnlyMatrix );
+ else
+ bAllowed = pDoc->IsBlockEditable( nTab, 0,nRow, MAXCOL,nRow, &bOnlyMatrix );
+ if ( !bAllowed && !bOnlyMatrix )
+ {
+ ErrorMessage(STR_PROTECTIONERR);
+ return;
+ }
+
+ HideAllCursors();
+
+ USHORT nWidth = pDoc->GetColWidth( nCol, nTab );
+ USHORT nHeight = pDoc->GetRowHeight( nRow, nTab );
+ SCCOLROW nRange[2];
+ if ( eDir == DIR_LEFT || eDir == DIR_RIGHT )
+ {
+ if (bOptimal) // Breite dieser einen Zelle
+ {
+ if ( bAnyEdit )
+ {
+ // beim Editieren die aktuelle Breite der Eingabe
+ ScInputHandler* pHdl = pScMod->GetInputHdl( GetViewData()->GetViewShell() );
+ if (pHdl)
+ {
+ long nEdit = pHdl->GetTextSize().Width(); // in 1/100mm
+
+ const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
+ const SvxMarginItem& rMItem =
+ (const SvxMarginItem&)pPattern->GetItem(ATTR_MARGIN);
+ USHORT nMargin = rMItem.GetLeftMargin() + rMItem.GetRightMargin();
+ if ( ((const SvxHorJustifyItem&) pPattern->
+ GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_LEFT )
+ nMargin = sal::static_int_cast<USHORT>(
+ nMargin + ((const SfxUInt16Item&)pPattern->GetItem(ATTR_INDENT)).GetValue() );
+
+ nWidth = (USHORT)(nEdit * pDocSh->GetOutputFactor() / HMM_PER_TWIPS)
+ + nMargin + STD_EXTRA_WIDTH;
+ }
+ }
+ else
+ {
+ double nPPTX = GetViewData()->GetPPTX();
+ double nPPTY = GetViewData()->GetPPTY();
+ Fraction aZoomX = GetViewData()->GetZoomX();
+ Fraction aZoomY = GetViewData()->GetZoomY();
+
+ ScSizeDeviceProvider aProv(pDocSh);
+ if (aProv.IsPrinter())
+ {
+ nPPTX = aProv.GetPPTX();
+ nPPTY = aProv.GetPPTY();
+ aZoomX = aZoomY = Fraction( 1, 1 );
+ }
+
+ long nPixel = pDoc->GetNeededSize( nCol, nRow, nTab, aProv.GetDevice(),
+ nPPTX, nPPTY, aZoomX, aZoomY, TRUE );
+ USHORT nTwips = (USHORT)( nPixel / nPPTX );
+ if (nTwips != 0)
+ nWidth = nTwips + STD_EXTRA_WIDTH;
+ else
+ nWidth = STD_COL_WIDTH;
+ }
+ }
+ else // vergroessern / verkleinern
+ {
+ if ( eDir == DIR_RIGHT )
+ nWidth = sal::static_int_cast<USHORT>( nWidth + nStepX );
+ else if ( nWidth > nStepX )
+ nWidth = sal::static_int_cast<USHORT>( nWidth - nStepX );
+ if ( nWidth < nStepX ) nWidth = nStepX;
+ if ( nWidth > MAX_COL_WIDTH ) nWidth = MAX_COL_WIDTH;
+ }
+ nRange[0] = nRange[1] = nCol;
+ SetWidthOrHeight( TRUE, 1, nRange, SC_SIZE_DIRECT, nWidth );
+
+ // hier bei Breite auch Hoehe anpassen (nur die eine Zeile)
+
+ if (!bAnyEdit)
+ {
+ const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
+ BOOL bNeedHeight =
+ ((const SfxBoolItem&)pPattern->GetItem( ATTR_LINEBREAK )).GetValue() ||
+ ((const SvxHorJustifyItem&)pPattern->
+ GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_BLOCK;
+ if (bNeedHeight)
+ AdjustRowHeight( nRow, nRow );
+ }
+ }
+ else
+ {
+ ScSizeMode eMode;
+ if (bOptimal)
+ {
+ eMode = SC_SIZE_OPTIMAL;
+ nHeight = 0;
+ }
+ else
+ {
+ eMode = SC_SIZE_DIRECT;
+ if ( eDir == DIR_BOTTOM )
+ nHeight = sal::static_int_cast<USHORT>( nHeight + nStepY );
+ else if ( nHeight > nStepY )
+ nHeight = sal::static_int_cast<USHORT>( nHeight - nStepY );
+ if ( nHeight < nStepY ) nHeight = nStepY;
+ if ( nHeight > MAX_COL_HEIGHT ) nHeight = MAX_COL_HEIGHT;
+ //! MAX_COL_HEIGHT umbenennen in MAX_ROW_HEIGHT in global.hxx !!!!!!
+ }
+ nRange[0] = nRange[1] = nRow;
+ SetWidthOrHeight( FALSE, 1, nRange, eMode, nHeight );
+ }
+
+ if ( bAnyEdit )
+ {
+ UpdateEditView();
+ if ( pDoc->HasAttrib( nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_NEEDHEIGHT ) )
+ {
+ ScInputHandler* pHdl = pScMod->GetInputHdl( GetViewData()->GetViewShell() );
+ if (pHdl)
+ pHdl->SetModified(); // damit bei Enter die Hoehe angepasst wird
+ }
+ }
+
+ ShowAllCursors();
+}
+
+void ScViewFunc::ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect )
+{
+ if (nTab == TABLEID_DOC)
+ return;
+
+ ScMarkData& rMark = GetViewData()->GetMarkData();
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+ ScDocument* pDoc = pDocSh->GetDocument();
+ ScDocFunc aFunc(*pDocSh);
+ bool bUndo(pDoc->IsUndoEnabled());
+
+ // modifying several tables is handled here
+
+ if (bUndo)
+ {
+ String aUndo = ScGlobal::GetRscString( STR_UNDO_PROTECT_TAB );
+ pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
+ }
+
+ SCTAB nCount = pDocSh->GetDocument()->GetTableCount();
+ for ( SCTAB i=0; i<nCount; i++ )
+ if ( rMark.GetTableSelect(i) )
+ aFunc.ProtectSheet(i, rProtect);
+
+ if (bUndo)
+ pDocSh->GetUndoManager()->LeaveListAction();
+
+ UpdateLayerLocks(); //! broadcast to all views
+}
+
+void ScViewFunc::Protect( SCTAB nTab, const String& rPassword )
+{
+ ScMarkData& rMark = GetViewData()->GetMarkData();
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+ ScDocument* pDoc = pDocSh->GetDocument();
+ ScDocFunc aFunc(*pDocSh);
+ BOOL bUndo(pDoc->IsUndoEnabled());
+
+ if ( nTab == TABLEID_DOC || rMark.GetSelectCount() <= 1 )
+ aFunc.Protect( nTab, rPassword, FALSE );
+ else
+ {
+ // modifying several tables is handled here
+
+ if (bUndo)
+ {
+ String aUndo = ScGlobal::GetRscString( STR_UNDO_PROTECT_TAB );
+ pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
+ }
+
+ SCTAB nCount = pDocSh->GetDocument()->GetTableCount();
+ for ( SCTAB i=0; i<nCount; i++ )
+ if ( rMark.GetTableSelect(i) )
+ aFunc.Protect( i, rPassword, FALSE );
+
+ if (bUndo)
+ pDocSh->GetUndoManager()->LeaveListAction();
+ }
+
+ UpdateLayerLocks(); //! broadcast to all views
+}
+
+BOOL ScViewFunc::Unprotect( SCTAB nTab, const String& rPassword )
+{
+ ScMarkData& rMark = GetViewData()->GetMarkData();
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+ ScDocument* pDoc = pDocSh->GetDocument();
+ ScDocFunc aFunc(*pDocSh);
+ BOOL bChanged = FALSE;
+ BOOL bUndo (pDoc->IsUndoEnabled());
+
+ if ( nTab == TABLEID_DOC || rMark.GetSelectCount() <= 1 )
+ bChanged = aFunc.Unprotect( nTab, rPassword, FALSE );
+ else
+ {
+ // modifying several tables is handled here
+
+ if (bUndo)
+ {
+ String aUndo = ScGlobal::GetRscString( STR_UNDO_UNPROTECT_TAB );
+ pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
+ }
+
+ SCTAB nCount = pDocSh->GetDocument()->GetTableCount();
+ for ( SCTAB i=0; i<nCount; i++ )
+ if ( rMark.GetTableSelect(i) )
+ if ( aFunc.Unprotect( i, rPassword, FALSE ) )
+ bChanged = TRUE;
+
+ if (bUndo)
+ pDocSh->GetUndoManager()->LeaveListAction();
+ }
+
+ if (bChanged)
+ UpdateLayerLocks(); //! broadcast to all views
+
+ return bChanged;
+}
+
+void ScViewFunc::SetNoteText( const ScAddress& rPos, const String& rNoteText )
+{
+ GetViewData()->GetDocShell()->GetDocFunc().SetNoteText( rPos, rNoteText, FALSE );
+}
+
+void ScViewFunc::ReplaceNote( const ScAddress& rPos, const String& rNoteText, const String* pAuthor, const String* pDate )
+{
+ GetViewData()->GetDocShell()->GetDocFunc().ReplaceNote( rPos, rNoteText, pAuthor, pDate, FALSE );
+}
+
+void ScViewFunc::SetNumberFormat( short nFormatType, ULONG nAdd )
+{
+ // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
+ BOOL bOnlyNotBecauseOfMatrix;
+ if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
+ {
+ ErrorMessage(STR_PROTECTIONERR);
+ return;
+ }
+
+ sal_uInt32 nNumberFormat = 0;
+ ScViewData* pViewData = GetViewData();
+ ScDocument* pDoc = pViewData->GetDocument();
+ SvNumberFormatter* pNumberFormatter = pDoc->GetFormatTable();
+ LanguageType eLanguage = ScGlobal::eLnge;
+ ScPatternAttr aNewAttrs( pDoc->GetPool() );
+
+ // #67936# always take language from cursor position, even if there is a selection
+
+ sal_uInt32 nCurrentNumberFormat;
+ pDoc->GetNumberFormat( pViewData->GetCurX(),
+ pViewData->GetCurY(),
+ pViewData->GetTabNo(),
+ nCurrentNumberFormat );
+ const SvNumberformat* pEntry = pNumberFormatter->GetEntry( nCurrentNumberFormat );
+ if (pEntry)
+ eLanguage = pEntry->GetLanguage(); // sonst ScGlobal::eLnge behalten
+
+ nNumberFormat = pNumberFormatter->GetStandardFormat( nFormatType, eLanguage ) + nAdd;
+
+ SfxItemSet& rSet = aNewAttrs.GetItemSet();
+ rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNumberFormat ) );
+ // ATTR_LANGUAGE_FORMAT nicht
+ ApplySelectionPattern( aNewAttrs, TRUE );
+}
+
+void ScViewFunc::SetNumFmtByStr( const String& rCode )
+{
+ // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
+ BOOL bOnlyNotBecauseOfMatrix;
+ if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
+ {
+ ErrorMessage(STR_PROTECTIONERR);
+ return;
+ }
+
+ ScViewData* pViewData = GetViewData();
+ ScDocument* pDoc = pViewData->GetDocument();
+ SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
+
+ // Sprache immer von Cursorposition
+
+ sal_uInt32 nCurrentNumberFormat;
+ pDoc->GetNumberFormat( pViewData->GetCurX(), pViewData->GetCurY(),
+ pViewData->GetTabNo(), nCurrentNumberFormat );
+ const SvNumberformat* pEntry = pFormatter->GetEntry( nCurrentNumberFormat );
+ LanguageType eLanguage = pEntry ? pEntry->GetLanguage() : ScGlobal::eLnge;
+
+ // Index fuer String bestimmen
+
+ BOOL bOk = TRUE;
+ sal_uInt32 nNumberFormat = pFormatter->GetEntryKey( rCode, eLanguage );
+ if ( nNumberFormat == NUMBERFORMAT_ENTRY_NOT_FOUND )
+ {
+ // neu eintragen
+
+ String aFormat = rCode; // wird veraendert
+ xub_StrLen nErrPos = 0;
+ short nType = 0; //! ???
+ bOk = pFormatter->PutEntry( aFormat, nErrPos, nType, nNumberFormat, eLanguage );
+ }
+
+ if ( bOk ) // gueltiges Format?
+ {
+ ScPatternAttr aNewAttrs( pDoc->GetPool() );
+ SfxItemSet& rSet = aNewAttrs.GetItemSet();
+ rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNumberFormat ) );
+ rSet.Put( SvxLanguageItem( eLanguage, ATTR_LANGUAGE_FORMAT ) );
+ ApplySelectionPattern( aNewAttrs, TRUE );
+ }
+
+ //! sonst Fehler zuerueckgeben / Meldung ausgeben ???
+}
+
+void ScViewFunc::ChangeNumFmtDecimals( BOOL bIncrement )
+{
+ // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
+ BOOL bOnlyNotBecauseOfMatrix;
+ if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
+ {
+ ErrorMessage(STR_PROTECTIONERR);
+ return;
+ }
+
+ ScDocument* pDoc = GetViewData()->GetDocument();
+ SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
+
+ SCCOL nCol = GetViewData()->GetCurX();
+ SCROW nRow = GetViewData()->GetCurY();
+ SCTAB nTab = GetViewData()->GetTabNo();
+
+ sal_uInt32 nOldFormat;
+ pDoc->GetNumberFormat( nCol, nRow, nTab, nOldFormat );
+ const SvNumberformat* pOldEntry = pFormatter->GetEntry( nOldFormat );
+ if (!pOldEntry)
+ {
+ DBG_ERROR("Zahlformat nicht gefunden !!!");
+ return;
+ }
+
+ // was haben wir denn da?
+
+ sal_uInt32 nNewFormat = nOldFormat;
+ BOOL bError = FALSE;
+
+ LanguageType eLanguage = pOldEntry->GetLanguage();
+ BOOL bThousand, bNegRed;
+ USHORT nPrecision, nLeading;
+ pOldEntry->GetFormatSpecialInfo( bThousand, bNegRed, nPrecision, nLeading );
+
+ short nOldType = pOldEntry->GetType();
+ if ( 0 == ( nOldType & (
+ NUMBERFORMAT_NUMBER | NUMBERFORMAT_CURRENCY | NUMBERFORMAT_PERCENT ) ) )
+ {
+ // Datum, Zeit, Bruch, logisch, Text kann nicht angepasst werden
+ //! bei Wisssenschaftlich kann es der Numberformatter auch nicht
+ bError = TRUE;
+ }
+
+ //! Das SvNumberformat hat einen Member bStandard, verraet ihn aber nicht
+ BOOL bWasStandard = ( nOldFormat == pFormatter->GetStandardIndex( eLanguage ) );
+ if (bWasStandard)
+ {
+ // bei "Standard" die Nachkommastellen abhaengig vom Zellinhalt
+ // 0 bei leer oder Text -> keine Nachkommastellen
+ double nVal = pDoc->GetValue( ScAddress( nCol, nRow, nTab ) );
+
+ // Die Wege des Numberformatters sind unergruendlich, darum ausprobieren:
+ String aOut;
+ Color* pCol;
+ ((SvNumberformat*)pOldEntry)->GetOutputString( nVal, aOut, &pCol );
+
+ nPrecision = 0;
+ // 'E' fuer Exponential ist fest im Numberformatter
+ if ( aOut.Search('E') != STRING_NOTFOUND )
+ bError = TRUE; // Exponential nicht veraendern
+ else
+ {
+ String aDecSep( pFormatter->GetFormatDecimalSep( nOldFormat ) );
+ xub_StrLen nPos = aOut.Search( aDecSep );
+ if ( nPos != STRING_NOTFOUND )
+ nPrecision = aOut.Len() - nPos - aDecSep.Len();
+ // sonst 0 behalten
+ }
+ }
+
+ if (!bError)
+ {
+ if (bIncrement)
+ {
+ if (nPrecision<20)
+ ++nPrecision; // erhoehen
+ else
+ bError = TRUE; // 20 ist Maximum
+ }
+ else
+ {
+ if (nPrecision)
+ --nPrecision; // vermindern
+ else
+ bError = TRUE; // weniger als 0 geht nicht
+ }
+ }
+
+ if (!bError)
+ {
+ String aNewPicture;
+ pFormatter->GenerateFormat( aNewPicture, nOldFormat, eLanguage,
+ bThousand, bNegRed, nPrecision, nLeading );
+
+ nNewFormat = pFormatter->GetEntryKey( aNewPicture, eLanguage );
+ if ( nNewFormat == NUMBERFORMAT_ENTRY_NOT_FOUND )
+ {
+ xub_StrLen nErrPos = 0;
+ short nNewType = 0;
+ BOOL bOk = pFormatter->PutEntry( aNewPicture, nErrPos,
+ nNewType, nNewFormat, eLanguage );
+ DBG_ASSERT( bOk, "falsches Zahlformat generiert" );
+ if (!bOk)
+ bError = TRUE;
+ }
+ }
+
+ if (!bError)
+ {
+ ScPatternAttr aNewAttrs( pDoc->GetPool() );
+ SfxItemSet& rSet = aNewAttrs.GetItemSet();
+ rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat ) );
+ // ATTR_LANGUAGE_FORMAT nicht
+ ApplySelectionPattern( aNewAttrs, TRUE );
+ }
+ else
+ Sound::Beep(); // war nix
+}
+
+void ScViewFunc::ChangeIndent( BOOL bIncrement )
+{
+ ScViewData* pViewData = GetViewData();
+ ScDocShell* pDocSh = pViewData->GetDocShell();
+ ScMarkData& rMark = pViewData->GetMarkData();
+
+ ScMarkData aWorkMark = rMark;
+ ScViewUtil::UnmarkFiltered( aWorkMark, pDocSh->GetDocument() );
+ aWorkMark.MarkToMulti();
+ if (!aWorkMark.IsMultiMarked())
+ {
+ SCCOL nCol = pViewData->GetCurX();
+ SCROW nRow = pViewData->GetCurY();
+ SCTAB nTab = pViewData->GetTabNo();
+ aWorkMark.SetMultiMarkArea( ScRange(nCol,nRow,nTab) );
+ }
+
+ BOOL bSuccess = pDocSh->GetDocFunc().ChangeIndent( aWorkMark, bIncrement, FALSE );
+ if (bSuccess)
+ {
+ pDocSh->UpdateOle(pViewData);
+ StartFormatArea();
+ }
+}
+
+BOOL ScViewFunc::InsertName( const String& rName, const String& rSymbol,
+ const String& rType )
+{
+ // Type = P,R,C,F (und Kombinationen)
+ //! Undo...
+
+ BOOL bOk = FALSE;
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+ ScDocument* pDoc = pDocSh->GetDocument();
+ SCTAB nTab = GetViewData()->GetTabNo();
+ ScRangeName* pList = pDoc->GetRangeName();
+
+ RangeType nType = RT_NAME;
+ ScRangeData* pNewEntry = new ScRangeData( pDoc, rName, rSymbol,
+ ScAddress( GetViewData()->GetCurX(), GetViewData()->GetCurY(),
+ nTab), nType );
+ String aUpType = rType;
+ aUpType.ToUpperAscii();
+ if ( aUpType.Search( 'P' ) != STRING_NOTFOUND )
+ nType |= RT_PRINTAREA;
+ if ( aUpType.Search( 'R' ) != STRING_NOTFOUND )
+ nType |= RT_ROWHEADER;
+ if ( aUpType.Search( 'C' ) != STRING_NOTFOUND )
+ nType |= RT_COLHEADER;
+ if ( aUpType.Search( 'F' ) != STRING_NOTFOUND )
+ nType |= RT_CRITERIA;
+ pNewEntry->AddType(nType);
+
+ if ( !pNewEntry->GetErrCode() ) // Text gueltig?
+ {
+ ScDocShellModificator aModificator( *pDocSh );
+
+ pDoc->CompileNameFormula( TRUE ); // CreateFormulaString
+
+ // Eintrag bereits vorhanden? Dann vorher entfernen (=Aendern)
+ USHORT nFoundAt;
+ if ( pList->SearchName( rName, nFoundAt ) )
+ { // alten Index uebernehmen
+ pNewEntry->SetIndex( ((ScRangeData*)pList->At(nFoundAt))->GetIndex() );
+ pList->AtFree( nFoundAt );
+ }
+
+ if ( pList->Insert( pNewEntry ) )
+ {
+ pNewEntry = NULL; // nicht loeschen
+ bOk = TRUE;
+ }
+
+ pDoc->CompileNameFormula( FALSE ); // CompileFormulaString
+ aModificator.SetDocumentModified();
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
+ }
+
+ delete pNewEntry; // wenn er nicht eingefuegt wurde
+ return bOk;
+}
+
+void ScViewFunc::CreateNames( USHORT nFlags )
+{
+ BOOL bDone = FALSE;
+ ScRange aRange;
+ if ( GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE )
+ bDone = GetViewData()->GetDocShell()->GetDocFunc().CreateNames( aRange, nFlags, FALSE );
+
+ if (!bDone)
+ ErrorMessage(STR_CREATENAME_MARKERR);
+}
+
+USHORT ScViewFunc::GetCreateNameFlags()
+{
+ USHORT nFlags = 0;
+
+ SCCOL nStartCol, nEndCol;
+ SCROW nStartRow, nEndRow;
+ SCTAB nDummy;
+ if (GetViewData()->GetSimpleArea(nStartCol,nStartRow,nDummy,nEndCol,nEndRow,nDummy) == SC_MARK_SIMPLE)
+ {
+ ScDocument* pDoc = GetViewData()->GetDocument();
+ SCTAB nTab = GetViewData()->GetTabNo();
+ BOOL bOk;
+ SCCOL i;
+ SCROW j;
+
+ bOk = TRUE;
+ SCCOL nFirstCol = nStartCol;
+ SCCOL nLastCol = nEndCol;
+ if (nStartCol+1 < nEndCol) { ++nFirstCol; --nLastCol; }
+ for (i=nFirstCol; i<=nLastCol && bOk; i++)
+ if (!pDoc->HasStringData( i,nStartRow,nTab ))
+ bOk = FALSE;
+ if (bOk)
+ nFlags |= NAME_TOP;
+ else // Bottom nur wenn nicht Top
+ {
+ bOk = TRUE;
+ for (i=nFirstCol; i<=nLastCol && bOk; i++)
+ if (!pDoc->HasStringData( i,nEndRow,nTab ))
+ bOk = FALSE;
+ if (bOk)
+ nFlags |= NAME_BOTTOM;
+ }
+
+ bOk = TRUE;
+ SCROW nFirstRow = nStartRow;
+ SCROW nLastRow = nEndRow;
+ if (nStartRow+1 < nEndRow) { ++nFirstRow; --nLastRow; }
+ for (j=nFirstRow; j<=nLastRow && bOk; j++)
+ if (!pDoc->HasStringData( nStartCol,j,nTab ))
+ bOk = FALSE;
+ if (bOk)
+ nFlags |= NAME_LEFT;
+ else // Right nur wenn nicht Left
+ {
+ bOk = TRUE;
+ for (j=nFirstRow; j<=nLastRow && bOk; j++)
+ if (!pDoc->HasStringData( nEndCol,j,nTab ))
+ bOk = FALSE;
+ if (bOk)
+ nFlags |= NAME_RIGHT;
+ }
+ }
+
+ if (nStartCol == nEndCol)
+ nFlags &= ~( NAME_LEFT | NAME_RIGHT );
+ if (nStartRow == nEndRow)
+ nFlags &= ~( NAME_TOP | NAME_BOTTOM );
+
+ return nFlags;
+}
+
+void ScViewFunc::InsertNameList()
+{
+ ScAddress aPos( GetViewData()->GetCurX(), GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
+ ScDocShell* pDocSh = GetViewData()->GetDocShell();
+ if ( pDocSh->GetDocFunc().InsertNameList( aPos, FALSE ) )
+ pDocSh->UpdateOle(GetViewData());
+}
+
+
+
+