/************************************************************************* * * 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 * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // 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( sal_False ) { } //UNUSED2008-05 ScViewFunc::ScViewFunc( Window* pParent, const ScViewFunc& rViewFunc, ScTabViewShell* pViewShell ) : //UNUSED2008-05 ScTabView( pParent, rViewFunc, pViewShell ), //UNUSED2008-05 bFormatValid( sal_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; sal_Bool bOk = (GetViewData()->GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE); if ( bOk && aMarkRange.aStart != aMarkRange.aEnd ) bOk = sal_False; if (bOk) { bFormatValid = sal_True; aFormatSource = aMarkRange.aStart; aFormatArea = ScRange( aFormatSource ); } else bFormatValid = sal_False; // keinen alten Bereich behalten } sal_Bool ScViewFunc::TestFormatArea( SCCOL nCol, SCROW nRow, SCTAB nTab, sal_Bool bAttrChanged ) { // ueberhaupt aktiviert? if ( !SC_MOD()->GetInputOptions().GetExtendFormat() ) return sal_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 sal_False; } //! Abfrage, ob Zelle leer war ??? sal_Bool bFound = sal_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 = sal_True; // Bereich nicht aendern } // links ? if ( nCol+1 == aFormatArea.aStart.Col() ) { bFound = sal_True; aNewRange.aStart.SetCol( nCol ); } // rechts ? if ( nCol == aFormatArea.aEnd.Col()+1 ) { bFound = sal_True; aNewRange.aEnd.SetCol( nCol ); } } if ( nCol >= aFormatArea.aStart.Col() && nCol <= aFormatArea.aEnd.Col() ) { // oben ? if ( nRow+1 == aFormatArea.aStart.Row() ) { bFound = sal_True; aNewRange.aStart.SetRow( nRow ); } // unten ? if ( nRow == aFormatArea.aEnd.Row()+1 ) { bFound = sal_True; aNewRange.aEnd.SetRow( nRow ); } } } if (bFound) aFormatArea = aNewRange; // erweitern else { bFormatValid = sal_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, sal_Bool bAttrChanged, sal_Bool bAddUndo ) { ScDocShell* pDocSh = GetViewData()->GetDocShell(); ScDocument* pDoc = pDocSh->GetDocument(); if (bAddUndo && !pDoc->IsUndoEnabled()) bAddUndo = sal_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, sal_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, sal_True ) ); delete pOldPattern; // wird im Undo kopiert (Pool) } } if ( bAttrChanged ) // Wert mit Zahlformat eingegeben? aFormatSource.Set( nCol, nRow, nTab ); // dann als neue Quelle } //------------------------------------------------------------------------------------ // Hilfsroutinen sal_uInt16 ScViewFunc::GetOptimalColWidth( SCCOL nCol, SCTAB nTab, sal_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 ); } sal_uInt16 nTwips = pDoc->GetOptimalColWidth( nCol, nTab, aProv.GetDevice(), nPPTX, nPPTY, aZoomX, aZoomY, bFormula, &rMark ); return nTwips; } sal_Bool ScViewFunc::SelectionEditable( sal_Bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) { sal_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 sal_Bool lcl_FunctionKnown( sal_uInt16 nOpCode ) { const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList(); if ( pFuncList ) { sal_uLong nCount = pFuncList->GetCount(); for (sal_uLong i=0; iGetFunction(i)->nFIndex == nOpCode ) return sal_True; } return sal_False; } sal_Bool lcl_AddFunction( ScAppOptions& rAppOpt, sal_uInt16 nOpCode ) { sal_uInt16 nOldCount = rAppOpt.GetLRUFuncListCount(); sal_uInt16* pOldList = rAppOpt.GetLRUFuncList(); sal_uInt16 nPos; for (nPos=0; nPos no change // count doesn't change, so the original array is modified for (sal_uInt16 nCopy=nPos; nCopy>0; nCopy--) pOldList[nCopy] = pOldList[nCopy-1]; pOldList[0] = nOpCode; return sal_True; // list has changed } if ( !lcl_FunctionKnown( nOpCode ) ) return sal_False; // not in function list -> no change sal_uInt16 nNewCount = Min( (sal_uInt16)(nOldCount + 1), (sal_uInt16)LRU_MAX ); sal_uInt16 nNewList[LRU_MAX]; nNewList[0] = nOpCode; for (nPos=1; nPosGetDocument(); ScMarkData& rMark = GetViewData()->GetMarkData(); SCTAB nTabCount = pDoc->GetTableCount(); SCTAB nSelCount = rMark.GetSelectCount(); SCTAB i; if (bRecord && !pDoc->IsUndoEnabled()) bRecord = sal_False; ScDocShell* pDocSh = GetViewData()->GetDocShell(); ScDocShellModificator aModificator( *pDocSh ); ScEditableTester aTester( pDoc, nCol,nRow, nCol,nRow, rMark ); if (aTester.IsEditable()) { sal_Bool bEditDeleted = sal_False; sal_uInt8 nOldScript = 0; ScBaseCell** ppOldCells = NULL; sal_Bool* pHasFormat = NULL; sal_uLong* pOldFormats = NULL; SCTAB* pTabs = NULL; SCTAB nUndoPos = 0; EditTextObject* pUndoData = NULL; if ( bRecord ) { ppOldCells = new ScBaseCell*[nSelCount]; pHasFormat = new sal_Bool[nSelCount]; pOldFormats = new sal_uLong[nSelCount]; pTabs = new SCTAB[nSelCount]; nUndoPos = 0; for (i=0; iGetCell( nCol, nRow, i, pDocCell ); if ( pDocCell ) { ppOldCells[nUndoPos] = pDocCell->CloneWithoutNote( *pDoc ); if ( pDocCell->GetCellType() == CELLTYPE_EDIT ) bEditDeleted = sal_True; sal_uInt8 nDocScript = pDoc->GetScriptType( nCol, nRow, i, pDocCell ); if ( nOldScript == 0 ) nOldScript = nDocScript; else if ( nDocScript != nOldScript ) bEditDeleted = sal_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,sal_False,&pItem) ) { pHasFormat[nUndoPos] = sal_True; pOldFormats[nUndoPos] = ((const SfxUInt32Item*)pItem)->GetValue(); } else pHasFormat[nUndoPos] = sal_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; } } } } sal_Bool bNumFmtChanged = sal_False; if ( bFormula ) { // Formel, compile mit AutoCorrection for (i=0; iGetGrammar()); //2do: AutoCorrection via CalcOptions abschaltbar machen aComp.SetAutoCorrection( sal_True ); if ( rString.GetChar(0) == '+' || rString.GetChar(0) == '-' ) { aComp.SetExtendedErrorDetection( true ); } String aFormula( rString ); ScTokenArray* pArr; sal_Bool bAgain; do { bAgain = sal_False; sal_Bool bAddEqual = sal_False; ScTokenArray* pArrFirst = pArr = aComp.CompileString( aFormula ); sal_Bool bCorrected = aComp.IsCorrected(); if ( bCorrected ) { // probieren, mit erster Parser-Korrektur neu zu parsen pArr = aComp.CompileString( aComp.GetCorrectedFormula() ); } if ( !pArr->GetCodeError() ) { bAddEqual = sal_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 = sal_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)) sal_uInt16 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(); sal_Bool bOptChanged = sal_False; formula::FormulaToken** ppToken = pArr->GetArray(); sal_uInt16 nTokens = pArr->GetLen(); sal_uInt16 nLevel = 0; for (sal_uInt16 nTP=0; nTPGetOpCode(); if ( eOp == ocOpen ) ++nLevel; else if ( eOp == ocClose && nLevel ) --nLevel; if ( nLevel == 0 && pTok->IsFunction() && lcl_AddFunction( aAppOpt, sal::static_int_cast( eOp ) ) ) bOptChanged = sal_True; } if ( bOptChanged ) { pScMod->SetAppOptions(aAppOpt); pScMod->RecentFunctionsChanged(); } } ScFormulaCell aCell( pDoc, aPos, pArr,formula::FormulaGrammar::GRAM_DEFAULT, MM_NONE ); delete pArr; sal_Bool bAutoCalc = pDoc->GetAutoCalc(); SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); for ( ; iGetAttr( 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(sal_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; iSetString( nCol, nRow, i, rString )) bNumFmtChanged = sal_True; } // row height must be changed if new text has a different script type for (i=0; iGetScriptType( nCol, nRow, i ) != nOldScript ) bEditDeleted = sal_True; HideAllCursors(); if (bEditDeleted || pDoc->HasAttrib( nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_NEEDHEIGHT )) AdjustRowHeight(nRow,nRow); sal_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; iPostPaintCell( 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(); sal_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 ); sal_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, sal_Bool bRecord, sal_Bool bTestSimple ) { ScDocShell* pDocSh = GetViewData()->GetDocShell(); ScMarkData& rMark = GetViewData()->GetMarkData(); ScDocument* pDoc = pDocSh->GetDocument(); if (bRecord && !pDoc->IsUndoEnabled()) bRecord = sal_False; ScDocShellModificator aModificator( *pDocSh ); ScEditableTester aTester( pDoc, nTab, nCol,nRow, nCol,nRow ); if (aTester.IsEditable()) { // // Test auf Attribute // sal_Bool bSimple = sal_False; sal_Bool bCommon = sal_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( (sal_uInt16) 0 ); if ( aParStr.GetChar(0) == '=' ) bSimple = sal_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; iGetCell( 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; iPutCell( 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; iPostPaintCell( 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(MAXCOL) && nRow+nSizeY-1 <= sal::static_int_cast(MAXROW) ) { ScRange aResult( nCol, nRow, nTab, sal::static_int_cast(nCol+nSizeX-1), sal::static_int_cast(nRow+nSizeY-1), nTab ); MarkRange( aResult, sal_False ); } } ScRange aRange; if (pData->GetSimpleArea(aRange) == SC_MARK_SIMPLE) { ScDocShell* pDocSh = pData->GetDocShell(); sal_Bool bSuccess = pDocSh->GetDocFunc().EnterMatrix( aRange, &rMark, NULL, rString, sal_False, sal_False, EMPTY_STRING, formula::FormulaGrammar::GRAM_DEFAULT ); if (bSuccess) pDocSh->UpdateOle(GetViewData()); } else ErrorMessage(STR_NOMULTISELECT); } sal_uInt8 ScViewFunc::GetSelectionScriptType() { sal_uInt8 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, sal_False ); sal_uLong nCount = aRanges.Count(); for (sal_uLong i=0; iGetScriptType( 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(sal_False); rLineInner.SetDist(sal_True); rLineInner.SetMinDist(sal_False); } } // // Attribute anwenden - Undo OK // // kompletter Set ( ATTR_STARTINDEX, ATTR_ENDINDEX ) // void ScViewFunc::ApplyAttributes( const SfxItemSet* pDialogSet, const SfxItemSet* pOldSet, sal_Bool bRecord ) { // nur wegen Matrix nicht editierbar? Attribute trotzdem ok sal_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()) * */ sal_Bool bFrame = (pDialogSet->GetItemState( ATTR_BORDER ) != SFX_ITEM_DEFAULT) || (pDialogSet->GetItemState( ATTR_BORDER_INNER ) != SFX_ITEM_DEFAULT); if ( pNewOuter==pOldOuter && pNewInner==pOldInner ) bFrame = sal_False; // das sollte doch der Pool abfangen: ?!??!?? if ( bFrame && pNewOuter && pNewInner ) if ( *pNewOuter == *pOldOuter && *pNewInner == *pOldInner ) bFrame = sal_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 = sal_False; if (!bFrame) ApplySelectionPattern( aNewAttrs, bRecord ); // nur normale else { // wenn neue Items Default-Items sind, so muessen die // alten Items geputtet werden: sal_Bool bDefNewOuter = ( SFX_ITEMS_STATICDEFAULT == pNewOuter->GetKind() ); sal_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 sal_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, sal_Bool bRecord ) { ScDocument* pDoc = GetViewData()->GetDocument(); ScMarkData aFuncMark( GetViewData()->GetMarkData() ); // local copy for UnmarkFiltered ScViewUtil::UnmarkFiltered( aFuncMark, pDoc ); if (bRecord && !pDoc->IsUndoEnabled()) bRecord = sal_False; ScRange aMarkRange; aFuncMark.MarkToSimple(); sal_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; iAddUndoTab( 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 ) ); } sal_uInt16 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, sal_Bool bRecord, sal_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 = sal_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(); sal_Bool bSetLines = rNewSet.GetItemState( ATTR_BORDER, sal_True ) == SFX_ITEM_SET || rNewSet.GetItemState( ATTR_SHADOW, sal_True ) == SFX_ITEM_SET; sal_Bool bSetAlign = rNewSet.GetItemState( ATTR_HOR_JUSTIFY, sal_True ) == SFX_ITEM_SET; sal_uInt16 nExtFlags = 0; if ( bSetLines ) nExtFlags |= SC_PF_LINES; if ( bSetAlign ) nExtFlags |= SC_PF_WHOLEROWS; ScDocShellModificator aModificator( *pDocSh ); sal_Bool bMulti = aFuncMark.IsMultiMarked(); aFuncMark.MarkToMulti(); sal_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; iAddUndoTab( 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, sal_False ) ); // sal_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 ( sal_uInt16 nWhich = ATTR_PATTERN_START; nWhich <= ATTR_PATTERN_END; ++nWhich ) { const SfxPoolItem* pItem = 0; if ( rNewSet.GetItemState( nWhich, sal_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 sal_Bool bOnlyNotBecauseOfMatrix; if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix ) { ErrorMessage(STR_PROTECTIONERR); return; } ScPatternAttr aNewAttrs( GetViewData()->GetDocument()->GetPool() ); SfxItemSet& rNewSet = aNewAttrs.GetItemSet(); rNewSet.Put( rItemSet, sal_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, sal_Bool bRecord ) { // nur wegen Matrix nicht editierbar? Attribute trotzdem ok sal_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 = sal_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; iAddUndoTab( i, i ); ScRange aCopyRange = aMarkRange; aCopyRange.aStart.SetTab(0); aCopyRange.aEnd.SetTab(nTabCount-1); pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, sal_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; iAddUndoTab( i, i ); ScRange aCopyRange( nCol, nRow, 0, nCol, nRow, nTabCount-1 ); pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, sal_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; iApplyStyle( nCol, nRow, i, (ScStyleSheet&)*pStyleSheet ); if (!AdjustBlockHeight()) pViewData->GetDocShell()->PostPaintCell( nCol, nRow, nTab ); } aModificator.SetDocumentModified(); StartFormatArea(); } void ScViewFunc::RemoveStyleSheetInUse( const SfxStyleSheetBase* 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, sal_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( const SfxStyleSheetBase* 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, sal_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 sal_Bool ScViewFunc::InsertCells( InsCellCmd eCmd, sal_Bool bRecord, sal_Bool bPartOfPaste ) { ScRange aRange; if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE) { ScDocShell* pDocSh = GetViewData()->GetDocShell(); const ScMarkData& rMark = GetViewData()->GetMarkData(); sal_Bool bSuccess = pDocSh->GetDocFunc().InsertCells( aRange, &rMark, eCmd, bRecord, sal_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 sal_False; } } // Zellen loeschen - Undo OK void ScViewFunc::DeleteCells( DelCellCmd eCmd, sal_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, sal_False ); --nCount; } } else { pDocSh->GetDocFunc().DeleteCells( aRange, &rMark, eCmd, bRecord, sal_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( sal_False, bRecord ); else if (eCmd == DEL_DELROWS) DeleteMulti( sal_True, bRecord ); else ErrorMessage(STR_NOMULTISELECT); } Unmark(); } void ScViewFunc::DeleteMulti( sal_Bool bRows, sal_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 = sal_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(GetViewData()->GetCurY()) : static_cast(GetViewData()->GetCurX()); nRangeCnt = 1; } // Test ob erlaubt SCCOLROW* pOneRange = pRanges; sal_uInt16 nErrorId = 0; sal_Bool bNeedRefresh = sal_False; SCCOLROW nRangeNo; for (nRangeNo=0; nRangeNo(nStart); nEndRow = static_cast(nEnd); } else { nStartCol = static_cast(nStart); nEndCol = static_cast(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 = sal_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; nRangeNoCopyToDocument( 0,nStart,nTab, MAXCOL,nEnd,nTab, IDF_ALL,sal_False,pUndoDoc ); else pDoc->CopyToDocument( static_cast(nStart),0,nTab, static_cast(nEnd),MAXROW,nTab, IDF_ALL,sal_False,pUndoDoc ); } // alle Formeln wegen Referenzen SCTAB nTabCount = pDoc->GetTableCount(); pUndoDoc->AddUndoTab( 0, nTabCount-1, sal_False, sal_False ); pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,MAXTAB, IDF_FORMULA,sal_False,pUndoDoc ); pUndoData = new ScRefUndoData( pDoc ); pDoc->BeginDrawUndo(); } pOneRange = &pRanges[2*nRangeCnt]; // rueckwaerts for (nRangeNo=0; nRangeNoDeleteRow( 0,nTab, MAXCOL,nTab, nStart, static_cast(nEnd-nStart+1) ); else pDoc->DeleteCol( 0,nTab, MAXROW,nTab, static_cast(nStart), static_cast(nEnd-nStart+1) ); } if (bNeedRefresh) { SCCOLROW nFirstStart = pRanges[0]; SCCOL nStartCol = bRows ? 0 : static_cast(nFirstStart); SCROW nStartRow = bRows ? static_cast(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, sal_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(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(pRanges[0]); SetCursor( nCurX, nCurY ); delete[] pRanges; SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); } // Inhalte loeschen void ScViewFunc::DeleteContents( sal_uInt16 nFlags, sal_Bool bRecord ) { // nur wegen Matrix nicht editierbar? Attribute trotzdem ok sal_Bool bOnlyNotBecauseOfMatrix; sal_Bool bEditable = SelectionEditable( &bOnlyNotBecauseOfMatrix ); if ( !bEditable ) { if ( !(bOnlyNotBecauseOfMatrix && ((nFlags & (IDF_ATTRIB | IDF_EDITATTR)) == nFlags)) ) { ErrorMessage(bOnlyNotBecauseOfMatrix ? STR_MATRIXFRAGMENTERR : STR_PROTECTIONERR); return; } } ScRange aMarkRange; sal_Bool bSimple = sal_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 = sal_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 = sal_True; } aFuncMark.SetMarking(sal_False); // for MarkToMulti aFuncMark.MarkToSimple(); // before bMulti test below DBG_ASSERT( aFuncMark.IsMarked() || aFuncMark.IsMultiMarked() || bSimple, "delete what?" ); ScDocument* pUndoDoc = NULL; sal_Bool bMulti = !bSimple && aFuncMark.IsMultiMarked(); if (!bSimple) { aFuncMark.MarkToMulti(); aFuncMark.GetMultiMarkArea( aMarkRange ); } ScRange aExtendedRange(aMarkRange); if (!bSimple) { if ( pDoc->ExtendMerge( aExtendedRange, sal_True ) ) bMulti = sal_False; } // keine Objekte auf geschuetzten Tabellen sal_Bool bObjects = sal_False; if ( nFlags & IDF_OBJECTS ) { bObjects = sal_True; SCTAB nTabCount = pDoc->GetTableCount(); for (SCTAB nTab=0; nTabIsTabProtected(nTab)) bObjects = sal_False; } sal_uInt16 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 sal_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; iAddUndoTab( 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: sal_uInt16 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, sal_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( sal_Bool bWidth, SCCOLROW nRangeCnt, SCCOLROW* pRanges, ScSizeMode eMode, sal_uInt16 nSizeTwips, sal_Bool bRecord, sal_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 = sal_False; ScDocShellModificator aModificator( *pDocSh ); sal_Bool bAllowed = sal_True; for (nTab=0; nTabGetTableSelect(nTab)) { for ( SCCOLROW i=0; iIsBlockEditable( nTab, static_cast(pRanges[2*i]),0, static_cast(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]; sal_Bool bFormula = sal_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; nTabGetTableSelect(nTab)) { if (bWidth) { if ( nTab == nFirstTab ) pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_False ); else pUndoDoc->AddUndoTab( nTab, nTab, sal_True, sal_False ); pDoc->CopyToDocument( static_cast(nStart), 0, nTab, static_cast(nEnd), MAXROW, nTab, IDF_NONE, sal_False, pUndoDoc ); } else { if ( nTab == nFirstTab ) pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_False, sal_True ); else pUndoDoc->AddUndoTab( nTab, nTab, sal_False, sal_True ); pDoc->CopyToDocument( 0, nStart, nTab, MAXCOL, nEnd, nTab, IDF_NONE, sal_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(); sal_Bool bShow = nSizeTwips > 0 || eMode != SC_SIZE_DIRECT; sal_Bool bOutline = sal_False; for (nTab=0; nTabGetTableSelect(nTab)) { const SCCOLROW* pTabRanges = pRanges; pDoc->IncSizeRecalcLevel( nTab ); // nicht fuer jede Spalte einzeln pDoc->InitializeNoteCaptions( nTab ); for (SCCOLROW nRangeNo=0; nRangeNoRowHidden(nRow, nTab, NULL, &nLastRow)) { nRow = nLastRow; continue; } sal_uInt8 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, sal_True ); // Manual-Flag wird bei bAll=sal_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, sal_True ); // height was set manually } pDoc->ShowRows( nStartNo, nEndNo, nTab, nSizeTwips != 0 ); } else if ( eMode==SC_SIZE_SHOW ) { pDoc->ShowRows( nStartNo, nEndNo, nTab, sal_True ); } } else // Spaltenbreiten { for (SCCOL nCol=static_cast(nStartNo); nCol<=static_cast(nEndNo); nCol++) { if ( eMode != SC_SIZE_VISOPT || !pDoc->ColHidden(nCol, nTab) ) { sal_uInt16 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(nStartNo), static_cast(nEndNo), nTab, bShow ) ) bOutline = sal_True; } else { if ( pDoc->UpdateOutlineRow( nStartNo, nEndNo, nTab, bShow ) ) bOutline = sal_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; nTabGetTableSelect(nTab)) pDoc->UpdatePageBreaks( nTab ); GetViewData()->GetView()->UpdateScrollBars(); if (bPaint) { HideCursor(); for (nTab=0; nTabGetTableSelect(nTab)) { if (bWidth) { if (pDoc->HasAttrib( static_cast(nStart),0,nTab, static_cast(nEnd),MAXROW,nTab, HASATTR_MERGED | HASATTR_OVERLAPPED )) nStart = 0; if (nStart > 0) // weiter oben anfangen wegen Linien und Cursor --nStart; pDocSh->PostPaint( static_cast(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( sal_Bool bWidth, ScSizeMode eMode, sal_uInt16 nSizeTwips, sal_Bool bRecord, sal_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 ), sal_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, sal_Bool bOptimal ) { //! Schrittweiten einstellbar // Schrittweite ist auch Minimum sal_uInt16 nStepX = STD_COL_WIDTH / 5; sal_uInt16 nStepY = ScGlobal::nStdRowHeight; ScModule* pScMod = SC_MOD(); sal_Bool bAnyEdit = pScMod->IsInputMode(); SCCOL nCol = GetViewData()->GetCurX(); SCROW nRow = GetViewData()->GetCurY(); SCTAB nTab = GetViewData()->GetTabNo(); ScDocShell* pDocSh = GetViewData()->GetDocShell(); ScDocument* pDoc = pDocSh->GetDocument(); sal_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(); sal_uInt16 nWidth = pDoc->GetColWidth( nCol, nTab ); sal_uInt16 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); sal_uInt16 nMargin = rMItem.GetLeftMargin() + rMItem.GetRightMargin(); if ( ((const SvxHorJustifyItem&) pPattern-> GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_LEFT ) nMargin = sal::static_int_cast( nMargin + ((const SfxUInt16Item&)pPattern->GetItem(ATTR_INDENT)).GetValue() ); nWidth = (sal_uInt16)(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, sal_True ); sal_uInt16 nTwips = (sal_uInt16)( 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( nWidth + nStepX ); else if ( nWidth > nStepX ) nWidth = sal::static_int_cast( nWidth - nStepX ); if ( nWidth < nStepX ) nWidth = nStepX; if ( nWidth > MAX_COL_WIDTH ) nWidth = MAX_COL_WIDTH; } nRange[0] = nRange[1] = nCol; SetWidthOrHeight( sal_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 ); sal_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( nHeight + nStepY ); else if ( nHeight > nStepY ) nHeight = sal::static_int_cast( 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( sal_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; iGetUndoManager()->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); sal_Bool bUndo(pDoc->IsUndoEnabled()); if ( nTab == TABLEID_DOC || rMark.GetSelectCount() <= 1 ) aFunc.Protect( nTab, rPassword, sal_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; iGetUndoManager()->LeaveListAction(); } UpdateLayerLocks(); //! broadcast to all views } sal_Bool ScViewFunc::Unprotect( SCTAB nTab, const String& rPassword ) { ScMarkData& rMark = GetViewData()->GetMarkData(); ScDocShell* pDocSh = GetViewData()->GetDocShell(); ScDocument* pDoc = pDocSh->GetDocument(); ScDocFunc aFunc(*pDocSh); sal_Bool bChanged = sal_False; sal_Bool bUndo (pDoc->IsUndoEnabled()); if ( nTab == TABLEID_DOC || rMark.GetSelectCount() <= 1 ) bChanged = aFunc.Unprotect( nTab, rPassword, sal_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; iGetUndoManager()->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, sal_False ); } void ScViewFunc::ReplaceNote( const ScAddress& rPos, const String& rNoteText, const String* pAuthor, const String* pDate ) { GetViewData()->GetDocShell()->GetDocFunc().ReplaceNote( rPos, rNoteText, pAuthor, pDate, sal_False ); } void ScViewFunc::SetNumberFormat( short nFormatType, sal_uLong nAdd ) { // nur wegen Matrix nicht editierbar? Attribute trotzdem ok sal_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, sal_True ); } void ScViewFunc::SetNumFmtByStr( const String& rCode ) { // nur wegen Matrix nicht editierbar? Attribute trotzdem ok sal_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 sal_Bool bOk = sal_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, sal_True ); } //! sonst Fehler zuerueckgeben / Meldung ausgeben ??? } void ScViewFunc::ChangeNumFmtDecimals( sal_Bool bIncrement ) { // nur wegen Matrix nicht editierbar? Attribute trotzdem ok sal_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; sal_Bool bError = sal_False; LanguageType eLanguage = pOldEntry->GetLanguage(); sal_Bool bThousand, bNegRed; sal_uInt16 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 = sal_True; } //! Das SvNumberformat hat einen Member bStandard, verraet ihn aber nicht sal_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 = sal_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 = sal_True; // 20 ist Maximum } else { if (nPrecision) --nPrecision; // vermindern else bError = sal_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; sal_Bool bOk = pFormatter->PutEntry( aNewPicture, nErrPos, nNewType, nNewFormat, eLanguage ); DBG_ASSERT( bOk, "falsches Zahlformat generiert" ); if (!bOk) bError = sal_True; } } if (!bError) { ScPatternAttr aNewAttrs( pDoc->GetPool() ); SfxItemSet& rSet = aNewAttrs.GetItemSet(); rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat ) ); // ATTR_LANGUAGE_FORMAT nicht ApplySelectionPattern( aNewAttrs, sal_True ); } else Sound::Beep(); // war nix } void ScViewFunc::ChangeIndent( sal_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) ); } sal_Bool bSuccess = pDocSh->GetDocFunc().ChangeIndent( aWorkMark, bIncrement, sal_False ); if (bSuccess) { pDocSh->UpdateOle(pViewData); StartFormatArea(); } } sal_Bool ScViewFunc::InsertName( const String& rName, const String& rSymbol, const String& rType ) { // Type = P,R,C,F (und Kombinationen) //! Undo... sal_Bool bOk = sal_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( sal_True ); // CreateFormulaString // Eintrag bereits vorhanden? Dann vorher entfernen (=Aendern) sal_uInt16 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 = sal_True; } pDoc->CompileNameFormula( sal_False ); // CompileFormulaString aModificator.SetDocumentModified(); SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) ); } delete pNewEntry; // wenn er nicht eingefuegt wurde return bOk; } void ScViewFunc::CreateNames( sal_uInt16 nFlags ) { sal_Bool bDone = sal_False; ScRange aRange; if ( GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE ) bDone = GetViewData()->GetDocShell()->GetDocFunc().CreateNames( aRange, nFlags, sal_False ); if (!bDone) ErrorMessage(STR_CREATENAME_MARKERR); } sal_uInt16 ScViewFunc::GetCreateNameFlags() { sal_uInt16 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(); sal_Bool bOk; SCCOL i; SCROW j; bOk = sal_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 = sal_False; if (bOk) nFlags |= NAME_TOP; else // Bottom nur wenn nicht Top { bOk = sal_True; for (i=nFirstCol; i<=nLastCol && bOk; i++) if (!pDoc->HasStringData( i,nEndRow,nTab )) bOk = sal_False; if (bOk) nFlags |= NAME_BOTTOM; } bOk = sal_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 = sal_False; if (bOk) nFlags |= NAME_LEFT; else // Right nur wenn nicht Left { bOk = sal_True; for (j=nFirstRow; j<=nLastRow && bOk; j++) if (!pDoc->HasStringData( nEndCol,j,nTab )) bOk = sal_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, sal_False ) ) pDocSh->UpdateOle(GetViewData()); }