| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the 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( 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; i<nCount; i++) |
| if ( pFuncList->GetFunction(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<nOldCount; nPos++) |
| if (pOldList[nPos] == nOpCode) // is the function already in the list? |
| { |
| if ( nPos == 0 ) |
| return sal_False; // already at the top -> 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; nPos<nNewCount; nPos++) |
| nNewList[nPos] = pOldList[nPos-1]; |
| rAppOpt.SetLRUFuncList( nNewList, nNewCount ); |
| |
| return sal_True; // list has changed |
| } |
| |
| // eigentliche Funktionen |
| |
| // Eingabe - Undo OK |
| |
| void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rString, |
| sal_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 = 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; 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 = 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; 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( 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; 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<sal_uInt16>( 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 ( ; i<nTabCount; i++) |
| { |
| if (rMark.GetTableSelect(i)) |
| { |
| aPos.SetTab( i ); |
| sal_uLong nIndex = (sal_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(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; i<nTabCount; i++) |
| if (rMark.GetTableSelect(i)) |
| if (pDoc->SetString( nCol, nRow, i, rString )) |
| bNumFmtChanged = sal_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 = 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; 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(); |
| 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; 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, 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; 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(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; 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 ) ); |
| } |
| |
| 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; 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, |
| 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; 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, 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; 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, 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; 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( 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<SCCOLROW>(GetViewData()->GetCurY()) : static_cast<SCCOLROW>(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<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 = 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; nRangeNo<nRangeCnt; nRangeNo++) |
| { |
| SCCOLROW nStart = *(pOneRange++); |
| SCCOLROW nEnd = *(pOneRange++); |
| if (bRows) |
| pDoc->CopyToDocument( 0,nStart,nTab, MAXCOL,nEnd,nTab, IDF_ALL,sal_False,pUndoDoc ); |
| else |
| pDoc->CopyToDocument( static_cast<SCCOL>(nStart),0,nTab, |
| static_cast<SCCOL>(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; 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, 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<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( 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; nTab<nTabCount; nTab++) |
| if (aFuncMark.GetTableSelect(nTab) && pDoc->IsTabProtected(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; 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: |
| 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; nTab<nTabCount && bAllowed; nTab++) |
| if (pMarkData->GetTableSelect(nTab)) |
| { |
| for ( SCCOLROW i=0; i<nRangeCnt && bAllowed; i++ ) |
| { |
| sal_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]; |
| |
| 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; nTab<nTabCount; nTab++) |
| if (pMarkData->GetTableSelect(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<SCCOL>(nStart), 0, nTab, |
| static_cast<SCCOL>(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; 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 ) |
| { |
| sal_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; |
| } |
| |
| 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<SCCOL>(nStartNo); nCol<=static_cast<SCCOL>(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<SCCOL>(nStartNo), |
| static_cast<SCCOL>(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; 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( 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<sal_uInt16>( |
| 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<sal_uInt16>( nWidth + nStepX ); |
| else if ( nWidth > nStepX ) |
| nWidth = sal::static_int_cast<sal_uInt16>( 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<sal_uInt16>( nHeight + nStepY ); |
| else if ( nHeight > nStepY ) |
| nHeight = sal::static_int_cast<sal_uInt16>( 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; 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); |
| 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; i<nCount; i++ ) |
| if ( rMark.GetTableSelect(i) ) |
| aFunc.Protect( i, rPassword, sal_False ); |
| |
| if (bUndo) |
| pDocSh->GetUndoManager()->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; i<nCount; i++ ) |
| if ( rMark.GetTableSelect(i) ) |
| if ( aFunc.Unprotect( i, rPassword, sal_False ) ) |
| bChanged = sal_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, 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(); |
| |
| // stuff for sidebar panels |
| SfxBindings& rBindings = GetViewData()->GetBindings(); |
| rBindings.Invalidate( SID_H_ALIGNCELL ); |
| rBindings.Invalidate( SID_ATTR_ALIGN_INDENT ); |
| } |
| } |
| |
| 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()); |
| } |
| |
| |
| |
| |