summaryrefslogtreecommitdiff
path: root/sc/source/core
diff options
context:
space:
mode:
authorKurt Zenker <kz@openoffice.org>2008-03-06 14:23:29 +0000
committerKurt Zenker <kz@openoffice.org>2008-03-06 14:23:29 +0000
commit6938e140b1c9635fd9f86f7a2ab43e6a47fa73ad (patch)
treeffb84f0a18edfb39d5a3a706323d67e4c81439e5 /sc/source/core
parent36b7e07ba1fe766157182ac725b45b9713d5dabc (diff)
INTEGRATION: CWS odff (1.39.60); FILE MERGED
2008/02/27 18:30:09 er 1.39.60.12: RESYNC: (1.39-1.40); FILE MERGED 2008/02/15 14:23:03 er 1.39.60.11: #i81063# grammar here, grammar there, grammar everywhere 2008/02/07 19:37:07 er 1.39.60.10: #i81063# introduce StorageGrammar per document 2008/01/31 15:34:22 er 1.39.60.9: #i32340# ScFormulaResult, third wave 2008/01/25 14:19:41 er 1.39.60.8: #i32340# ScFormulaResult, start differentiating between compiler/code token error and interpreter/result error; make iterations work with result errors 2008/01/24 20:42:16 er 1.39.60.7: #i32340# ScFormulaResult, handle error code and matrix clone 2008/01/24 16:41:00 er 1.39.60.6: #i32340# variable cell result ScFormulaResult, second wave 2008/01/21 23:07:27 er 1.39.60.5: GetResultDimensions: MSVC didn't get it that pMat _can't_ be used unitialized here 2008/01/17 17:31:33 er 1.39.60.4: #i32340# variable cell result ScFormulaResult, first wave 2008/01/08 19:30:27 er 1.39.60.3: get rid of distracting binfilter legacy 2007/11/29 19:06:46 er 1.39.60.2: #i4904# range operator ocRange 2007/09/06 10:43:07 er 1.39.60.1: #i81063# new ScGrammar; get rid of SetCompileEnglish, SetCompileXML, GetEnglishFormula, ...
Diffstat (limited to 'sc/source/core')
-rw-r--r--sc/source/core/data/cell.cxx591
1 files changed, 230 insertions, 361 deletions
diff --git a/sc/source/core/data/cell.cxx b/sc/source/core/data/cell.cxx
index 8a688bd5de00..4ffe9e676f1e 100644
--- a/sc/source/core/data/cell.cxx
+++ b/sc/source/core/data/cell.cxx
@@ -4,9 +4,9 @@
*
* $RCSfile: cell.cxx,v $
*
- * $Revision: 1.40 $
+ * $Revision: 1.41 $
*
- * last change: $Author: rt $ $Date: 2008-01-29 15:16:00 $
+ * last change: $Author: kz $ $Date: 2008-03-06 15:23:29 $
*
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1.
@@ -400,6 +400,32 @@ void ScBaseCell::EndListeningTo( ScDocument* pDoc, ScTokenArray* pArr,
}
+USHORT ScBaseCell::GetErrorCode() const
+{
+ switch ( eCellType )
+ {
+ case CELLTYPE_FORMULA :
+ return ((ScFormulaCell*)this)->GetErrCode();
+ default:
+ return 0;
+ }
+}
+
+
+BOOL ScBaseCell::HasEmptyData() const
+{
+ switch ( eCellType )
+ {
+ case CELLTYPE_NOTE :
+ return TRUE;
+ case CELLTYPE_FORMULA :
+ return ((ScFormulaCell*)this)->IsEmpty();
+ default:
+ return FALSE;
+ }
+}
+
+
BOOL ScBaseCell::HasValueData() const
{
switch ( eCellType )
@@ -533,20 +559,17 @@ BOOL ScBaseCell::CellEqual( const ScBaseCell* pCell1, const ScBaseCell* pCell2 )
ScFormulaCell::ScFormulaCell() :
ScBaseCell( CELLTYPE_FORMULA ),
- nErgValue( 0.0 ),
+ eTempGrammar( ScGrammar::GRAM_DEFAULT),
pCode( NULL ),
pDocument( NULL ),
- xMatrix( NULL ),
pPrevious(0),
pNext(0),
pPreviousTrack(0),
pNextTrack(0),
nFormatIndex(0),
- nMatCols(0),
- nMatRows(0),
- nSeenInIteration(0),
nFormatType( NUMBERFORMAT_NUMBER ),
- bIsValue( TRUE ),
+ nSeenInIteration(0),
+ cMatrixFlag ( MM_NONE ),
bDirty( FALSE ),
bChanged( FALSE ),
bRunning( FALSE ),
@@ -556,30 +579,26 @@ ScFormulaCell::ScFormulaCell() :
bInChangeTrack( FALSE ),
bTableOpDirty( FALSE ),
bNeedListening( FALSE ),
- cMatrixFlag ( MM_NONE ),
aPos(0,0,0)
{
}
ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
const String& rFormula,
- ScAddress::Convention eConv,
+ const ScGrammar::Grammar eGrammar,
BYTE cMatInd ) :
ScBaseCell( CELLTYPE_FORMULA ),
- nErgValue( 0.0 ),
+ eTempGrammar( eGrammar),
pCode( NULL ),
pDocument( pDoc ),
- xMatrix( NULL ),
pPrevious(0),
pNext(0),
pPreviousTrack(0),
pNextTrack(0),
nFormatIndex(0),
- nMatCols(0),
- nMatRows(0),
- nSeenInIteration(0),
nFormatType( NUMBERFORMAT_NUMBER ),
- bIsValue( TRUE ),
+ nSeenInIteration(0),
+ cMatrixFlag ( cMatInd ),
bDirty( TRUE ), // -> wg. Benutzung im Fkt.AutoPiloten, war: cMatInd != 0
bChanged( FALSE ),
bRunning( FALSE ),
@@ -589,31 +608,28 @@ ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
bInChangeTrack( FALSE ),
bTableOpDirty( FALSE ),
bNeedListening( FALSE ),
- cMatrixFlag ( cMatInd ),
aPos( rPos )
{
- Compile( rFormula, TRUE, eConv ); // bNoListening, erledigt Insert
+ Compile( rFormula, TRUE, eGrammar ); // bNoListening, Insert does that
}
// Wird von den Importfiltern verwendet
ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
- const ScTokenArray* pArr, BYTE cInd ) :
+ const ScTokenArray* pArr,
+ const ScGrammar::Grammar eGrammar, BYTE cInd ) :
ScBaseCell( CELLTYPE_FORMULA ),
- nErgValue( 0.0 ),
+ eTempGrammar( eGrammar),
pCode( pArr ? new ScTokenArray( *pArr ) : new ScTokenArray ),
pDocument( pDoc ),
- xMatrix ( NULL ),
pPrevious(0),
pNext(0),
pPreviousTrack(0),
pNextTrack(0),
nFormatIndex(0),
- nMatCols(0),
- nMatRows(0),
- nSeenInIteration(0),
nFormatType( NUMBERFORMAT_NUMBER ),
- bIsValue( TRUE ),
+ nSeenInIteration(0),
+ cMatrixFlag ( cInd ),
bDirty( NULL != pArr ), // -> wg. Benutzung im Fkt.AutoPiloten, war: cInd != 0
bChanged( FALSE ),
bRunning( FALSE ),
@@ -623,13 +639,12 @@ ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
bInChangeTrack( FALSE ),
bTableOpDirty( FALSE ),
bNeedListening( FALSE ),
- cMatrixFlag ( cInd ),
aPos( rPos )
{
// UPN-Array erzeugen
- if( pCode->GetLen() && !pCode->GetError() && !pCode->GetCodeLen() )
+ if( pCode->GetLen() && !pCode->GetCodeError() && !pCode->GetCodeLen() )
{
- ScCompiler aComp(pDocument, aPos, *pCode);
+ ScCompiler aComp( pDocument, aPos, *pCode, eTempGrammar);
bSubTotal = aComp.CompileTokenArray();
nFormatType = aComp.GetNumFormatType();
}
@@ -645,20 +660,17 @@ ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rNewPos,
const ScFormulaCell& rScFormulaCell, USHORT nCopyFlags ) :
ScBaseCell( rScFormulaCell, pDoc ),
SvtListener(),
- aErgString( rScFormulaCell.aErgString ),
- nErgValue( rScFormulaCell.nErgValue ),
- nErgConv( rScFormulaCell.nErgConv ),
+ aResult( rScFormulaCell.aResult ),
+ eTempGrammar( rScFormulaCell.eTempGrammar),
pDocument( pDoc ),
pPrevious(0),
pNext(0),
pPreviousTrack(0),
pNextTrack(0),
nFormatIndex( pDoc == rScFormulaCell.pDocument ? rScFormulaCell.nFormatIndex : 0 ),
- nMatCols( rScFormulaCell.nMatCols ),
- nMatRows( rScFormulaCell.nMatRows ),
- nSeenInIteration(0),
nFormatType( rScFormulaCell.nFormatType ),
- bIsValue( rScFormulaCell.bIsValue ),
+ nSeenInIteration(0),
+ cMatrixFlag ( rScFormulaCell.cMatrixFlag ),
bDirty( rScFormulaCell.bDirty ),
bChanged( rScFormulaCell.bChanged ),
bRunning( FALSE ),
@@ -668,13 +680,8 @@ ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rNewPos,
bInChangeTrack( FALSE ),
bTableOpDirty( FALSE ),
bNeedListening( FALSE ),
- cMatrixFlag ( rScFormulaCell.cMatrixFlag ),
aPos( rNewPos )
{
- if (rScFormulaCell.xMatrix)
- xMatrix = rScFormulaCell.xMatrix->Clone();
- else
- xMatrix = NULL;
pCode = rScFormulaCell.pCode->Clone();
if ( nCopyFlags & 0x0001 )
@@ -683,9 +690,9 @@ ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rNewPos,
// evtl. Fehler zuruecksetzen und neu kompilieren
// nicht im Clipboard - da muss das Fehlerflag erhalten bleiben
// Spezialfall Laenge=0: als Fehlerzelle erzeugt, dann auch Fehler behalten
- if ( pCode->GetError() && !pDocument->IsClipboard() && pCode->GetLen() )
+ if ( pCode->GetCodeError() && !pDocument->IsClipboard() && pCode->GetLen() )
{
- pCode->SetError( 0 );
+ pCode->SetCodeError( 0 );
bCompile = TRUE;
}
//! Compile ColRowNames on URM_MOVE/URM_COPY _after_ UpdateReference
@@ -719,135 +726,19 @@ ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rNewPos,
{
if ( !bCompileLater && bClipMode )
{
- pCode->Reset();
- bCompileLater = (pCode->GetNextColRowName() != NULL);
+ // Merging ranges needs the actual positions after UpdateReference.
+ // ColRowNames need new lookup after positions are adjusted.
+ bCompileLater = pCode->HasOpCode( ocRange) || pCode->HasOpCode( ocColRowName);
}
if ( !bCompileLater )
{
- // bNoListening, bei in Clip/Undo sowieso nicht,
- // bei aus Clip auch nicht, sondern nach Insert(Clone) und UpdateReference
+ // bNoListening, not at all if in Clipboard/Undo,
+ // and not from Clipboard either, instead after Insert(Clone) and UpdateReference.
CompileTokenArray( TRUE );
}
}
}
-// +---+---+---+---+---+---+---+---+
-// | |Str|Num|Dir|cMatrix|
-// +---+---+---+---+---+---+---+---+
-
-ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
- SvStream& rStream, ScMultipleReadHeader& rHdr ) :
- ScBaseCell( CELLTYPE_FORMULA ),
- nErgValue( 0.0 ),
- pCode( new ScTokenArray ),
- pDocument( pDoc ),
- xMatrix ( NULL ),
- pPrevious(0),
- pNext(0),
- pPreviousTrack(0),
- pNextTrack(0),
- nFormatIndex(0),
- nMatCols(0),
- nMatRows(0),
- nSeenInIteration(0),
- nFormatType( 0 ),
- bIsValue( TRUE ),
- bDirty( FALSE ),
- bChanged( FALSE ),
- bRunning( FALSE ),
- bCompile( FALSE ),
- bSubTotal( FALSE ),
- bIsIterCell( FALSE ),
- bInChangeTrack( FALSE ),
- bTableOpDirty( FALSE ),
- bNeedListening( FALSE ),
- aPos( rPos )
-{
-// ScReadHeader aHdr( rStream );
- rHdr.StartEntry();
-
- USHORT nVer = (USHORT) pDoc->GetSrcVersion();
-
- if( nVer >= SC_NUMFMT )
- {
- BYTE cData;
- rStream >> cData;
-#ifndef PRODUCT
-// static BOOL bShown = 0;
-// if ( !bShown && SOFFICE_FILEFORMAT_NOW > SOFFICE_FILEFORMAT_50 )
-// {
-// bShown = 1;
-// DBG_ERRORFILE( "bei inkompatiblem FileFormat den FormatIndex umheben!" );
-// }
-#endif
- if( cData & 0x0F )
- {
- BYTE nSkip = cData & 0x0F;
- if ( (cData & 0x10) && nSkip >= sizeof(UINT32) )
- {
- UINT32 n;
- rStream >> n;
- nFormatIndex = n;
- nSkip -= sizeof(UINT32);
- }
- if ( nSkip )
- rStream.SeekRel( nSkip );
- }
- BYTE cFlags;
- rStream >> cFlags >> nFormatType;
- cMatrixFlag = (BYTE) ( cFlags & 0x03 );
- bDirty = BOOL( ( cFlags & 0x04 ) != 0 );
- if( cFlags & 0x08 )
- rStream >> nErgValue;
- if( cFlags & 0x10 )
- {
- rStream.ReadByteString( aErgString, rStream.GetStreamCharSet() );
- nErgConv = ScAddress::CONV_OOO;
- bIsValue = FALSE;
- }
- pCode->Load( rStream, nVer, aPos );
- if ( (cFlags & 0x18) == 0 )
- bDirty = TRUE; // #67161# no result stored => recalc
- if( cFlags & 0x20 )
- bSubTotal = TRUE;
- else if ( nVer < SC_SUBTOTAL_BUGFIX )
- { // #65285# in alten Dokumenten war Flag nicht gesetzt, wenn Formel
- // manuell eingegeben wurde (nicht via Daten->Teilergebnisse)
- if ( pCode->HasOpCodeRPN( ocSubTotal ) )
- {
- bDirty = TRUE; // neu berechnen
- bSubTotal = TRUE;
- }
- }
-#if SC_ROWLIMIT_STREAM_ACCESS
-#error address types changed!
- if ( cMatrixFlag == MM_FORMULA && rHdr.BytesLeft() )
- rStream >> nMatCols >> nMatRows;
-#endif
- }
- else
- {
- UINT16 nCodeLen;
- if( pDoc->GetSrcVersion() >= SC_FORMULA_LCLVER )
- rStream.SeekRel( 2 );
- rStream >> cMatrixFlag >> nCodeLen;
- if( cMatrixFlag == 5 )
- cMatrixFlag = 0;
- cMatrixFlag &= 3;
- if( nCodeLen )
- pCode->Load30( rStream, aPos );
- // Wir koennen hier bei Calc 3.0-Docs noch kein UPN-Array
- // erzeugen, da die Named Ranges noch nicht eingelesen sind
- }
-
- rHdr.EndEntry();
-
- // after loading, it must be known if ocMacro is in any formula
- // (for macro warning, and to insert the hidden view)
- if ( !pDoc->GetHasMacroFunc() && pCode->HasOpCodeRPN( ocMacro ) )
- pDoc->SetHasMacroFunc( TRUE );
-}
-
BOOL lcl_IsBeyond( ScTokenArray* pCode, SCROW nMaxRow )
{
ScToken* t;
@@ -860,75 +751,6 @@ BOOL lcl_IsBeyond( ScTokenArray* pCode, SCROW nMaxRow )
return FALSE;
}
-void ScFormulaCell::Save( SvStream& rStream, ScMultipleWriteHeader& rHdr ) const
-{
- SCROW nSaveMaxRow = pDocument->GetSrcMaxRow();
- if ( nSaveMaxRow < MAXROW && lcl_IsBeyond( pCode, nSaveMaxRow ) )
- {
- // Zelle mit Ref-Error erzeugen und speichern
- // StartEntry/EndEntry passiert beim Speichern der neuen Zelle
-
- SingleRefData aRef;
- aRef.InitAddress(ScAddress());
- aRef.SetColRel(TRUE);
- aRef.SetColDeleted(TRUE);
- aRef.SetRowRel(TRUE);
- aRef.SetRowDeleted(TRUE);
- aRef.CalcRelFromAbs(aPos);
- ScTokenArray aArr;
- aArr.AddSingleReference(aRef);
- aArr.AddOpCode(ocStop);
- ScFormulaCell* pErrCell = new ScFormulaCell( pDocument, aPos, &aArr );
- pErrCell->Save( rStream, rHdr );
- delete pErrCell;
-
- pDocument->SetLostData(); // Warnung ausgeben
- return;
- }
-
- rHdr.StartEntry();
-
- if ( bIsValue && !pCode->GetError() && !::rtl::math::isFinite( nErgValue ) )
- {
- DBG_ERRORFILE( msgDbgInfinity );
- pCode->SetError( errIllegalFPOperation );
- }
- BYTE cFlags = cMatrixFlag & 0x03;
- if( bDirty )
- cFlags |= 0x04;
- // Daten speichern?
- if( pCode->IsRecalcModeNormal() && !pCode->GetError() )
- cFlags |= bIsValue ? 0x08 : 0x10;
- if ( bSubTotal )
- cFlags |= 0x20;
-#ifndef PRODUCT
- static BOOL bShown = 0;
- if ( !bShown && rStream.GetVersion() > SOFFICE_FILEFORMAT_50 )
- {
- bShown = 1;
- DBG_ERRORFILE( "bei inkompatiblem FileFormat den FormatIndex umheben!" );
- }
-// rStream << (BYTE) 0x00;
-#endif
-#if SC_ROWLIMIT_STREAM_ACCESS
-#error address types changed!
- if ( nFormatIndex )
- rStream << (BYTE) (0x10 | sizeof(UINT32)) << nFormatIndex;
- else
- rStream << (BYTE) 0x00;
- rStream << cFlags << (UINT16) nFormatType;
- if( cFlags & 0x08 )
- rStream << nErgValue;
- if( cFlags & 0x10 )
- rStream.WriteByteString( aErgString, rStream.GetStreamCharSet() );
- pCode->Store( rStream, aPos );
- if ( cMatrixFlag == MM_FORMULA )
- rStream << nMatCols << nMatRows;
-
-#endif
- rHdr.EndEntry();
-}
-
ScBaseCell* ScFormulaCell::Clone( ScDocument* pDoc, const ScAddress& rPos,
BOOL bNoListening ) const
{
@@ -938,56 +760,94 @@ ScBaseCell* ScFormulaCell::Clone( ScDocument* pDoc, const ScAddress& rPos,
return pCell;
}
-void ScFormulaCell::GetFormula( String& rFormula, ScAddress::Convention eConv ) const
+void ScFormulaCell::GetFormula( rtl::OUStringBuffer& rBuffer,
+ const ScGrammar::Grammar eGrammar ) const
{
- if( pCode->GetError() && !pCode->GetLen() )
+ if( pCode->GetCodeError() && !pCode->GetLen() )
{
- rFormula = ScGlobal::GetErrorString( pCode->GetError() ); return;
+ rBuffer = rtl::OUStringBuffer( ScGlobal::GetErrorString( pCode->GetCodeError()));
+ return;
}
else if( cMatrixFlag == MM_REFERENCE )
{
- // Referenz auf eine andere Zelle, die eine Matrixformel enthaelt
+ // Reference to another cell that contains a matrix formula.
pCode->Reset();
ScToken* p = pCode->GetNextReferenceRPN();
if( p )
{
- ScBaseCell* pCell = NULL;
- if ( !IsInChangeTrack() )
- {
- SingleRefData& rRef = p->GetSingleRef();
- rRef.CalcAbsIfRel( aPos );
- if ( rRef.Valid() )
- pCell = pDocument->GetCell( ScAddress( rRef.nCol,
- rRef.nRow, rRef.nTab ) );
- }
+ /* FIXME: original GetFormula() code obtained
+ * pCell only if (!this->IsInChangeTrack()),
+ * GetEnglishFormula() omitted that test.
+ * Can we live without in all cases? */
+ ScBaseCell* pCell;
+ SingleRefData& rRef = p->GetSingleRef();
+ rRef.CalcAbsIfRel( aPos );
+ if ( rRef.Valid() )
+ pCell = pDocument->GetCell( ScAddress( rRef.nCol,
+ rRef.nRow, rRef.nTab ) );
+ else
+ pCell = NULL;
if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA)
{
- ((ScFormulaCell*)pCell)->GetFormula(rFormula, eConv);
+ ((ScFormulaCell*)pCell)->GetFormula( rBuffer, eGrammar);
return;
}
+ else if (ScGrammar::isPODF( eGrammar))
+ GetFormulaForPof( rBuffer, aPos, eGrammar);
else
{
- ScCompiler aComp( pDocument, aPos, *pCode );
- aComp.CreateStringFromTokenArray( rFormula );
+ ScCompiler aComp( pDocument, aPos, *pCode, eGrammar);
+ aComp.CreateStringFromTokenArray( rBuffer );
}
}
else
{
- DBG_ERROR("ScFormulaCell::GetFormula: Keine Matrix");
+ DBG_ERROR("ScFormulaCell::GetFormula: not a matrix");
}
}
+ else if (ScGrammar::isPODF( eGrammar))
+ GetFormulaForPof( rBuffer, aPos, eGrammar);
else
{
- ScCompiler aComp( pDocument, aPos, *pCode );
- aComp.CreateStringFromTokenArray( rFormula );
+ ScCompiler aComp( pDocument, aPos, *pCode, eGrammar);
+ aComp.CreateStringFromTokenArray( rBuffer );
}
- rFormula.Insert( '=',0 );
+ sal_Unicode ch('=');
+ rBuffer.insert( 0, &ch, 1 );
if( cMatrixFlag )
{
- rFormula.Insert('{', 0);
- rFormula += '}';
+ sal_Unicode ch2('{');
+ rBuffer.insert( 0, &ch2, 1);
+ rBuffer.append( sal_Unicode('}'));
+ }
+}
+
+void ScFormulaCell::GetFormula( String& rFormula, const ScGrammar::Grammar eGrammar ) const
+{
+ rtl::OUStringBuffer rBuffer( rFormula );
+ GetFormula( rBuffer, eGrammar );
+ rFormula = rBuffer;
+}
+
+
+void ScFormulaCell::GetFormulaForPof( rtl::OUStringBuffer &rBuffer,
+ const ScAddress &rPos, const ScGrammar::Grammar eGrammar ) const
+{
+ ScTokenArray *pCompileCode = pCode;
+ if (ScGrammar::isPODF( eGrammar))
+ {
+ /* Scan pCode [ token array ! ] for missing args &
+ re-write if present */
+ if (pCode->NeedsPofRewrite())
+ pCompileCode = pCode->RewriteMissingToPof();
}
+
+ ScCompiler aComp( pDocument, rPos, *pCompileCode, eGrammar);
+ aComp.CreateStringFromTokenArray( rBuffer );
+
+ if ( pCompileCode != pCode )
+ delete pCompileCode;
}
void ScFormulaCell::GetResultDimensions( SCSIZE& rCols, SCSIZE& rRows )
@@ -995,8 +855,10 @@ void ScFormulaCell::GetResultDimensions( SCSIZE& rCols, SCSIZE& rRows )
if (IsDirtyOrInTableOpDirty() && pDocument->GetAutoCalc())
Interpret();
- if ( !pCode->GetError() && xMatrix )
- xMatrix->GetDimensions( rCols, rRows );
+ const ScMatrix* pMat = NULL;
+ if (!pCode->GetCodeError() && aResult.GetType() == svMatrixCell &&
+ ((pMat = aResult.GetToken()->GetMatrix()) != 0))
+ pMat->GetDimensions( rCols, rRows );
else
{
rCols = 0;
@@ -1005,7 +867,7 @@ void ScFormulaCell::GetResultDimensions( SCSIZE& rCols, SCSIZE& rRows )
}
void ScFormulaCell::Compile( const String& rFormula, BOOL bNoListening,
- ScAddress::Convention eConv )
+ const ScGrammar::Grammar eGrammar )
{
if ( pDocument->IsClipOrUndo() ) return;
BOOL bWasInFormulaTree = pDocument->IsInFormulaTree( this );
@@ -1015,15 +877,13 @@ void ScFormulaCell::Compile( const String& rFormula, BOOL bNoListening,
if ( pCode )
pCode->Clear();
ScTokenArray* pCodeOld = pCode;
- ScCompiler aComp(pDocument, aPos);
- if ( pDocument->IsImportingXML() )
- aComp.SetCompileEnglish( TRUE );
- pCode = aComp.CompileString( rFormula, eConv );
+ ScCompiler aComp( pDocument, aPos, eGrammar);
+ pCode = aComp.CompileString( rFormula );
if ( pCodeOld )
delete pCodeOld;
- if( !pCode->GetError() )
+ if( !pCode->GetCodeError() )
{
- if ( !pCode->GetLen() && aErgString.Len() && rFormula == aErgString )
+ if ( !pCode->GetLen() && aResult.GetHybridFormula().Len() && rFormula == aResult.GetHybridFormula() )
{ // #65994# nicht rekursiv CompileTokenArray/Compile/CompileTokenArray
if ( rFormula.GetChar(0) == '=' )
pCode->AddBad( rFormula.GetBuffer() + 1 );
@@ -1046,17 +906,17 @@ void ScFormulaCell::Compile( const String& rFormula, BOOL bNoListening,
void ScFormulaCell::CompileTokenArray( BOOL bNoListening )
{
- // Noch nicht compiliert?
- if( !pCode->GetLen() && aErgString.Len() )
- Compile( aErgString, bNoListening, nErgConv );
- else if( bCompile && !pDocument->IsClipOrUndo() && !pCode->GetError() )
+ // Not already compiled?
+ if( !pCode->GetLen() && aResult.GetHybridFormula().Len() )
+ Compile( aResult.GetHybridFormula(), bNoListening, eTempGrammar);
+ else if( bCompile && !pDocument->IsClipOrUndo() && !pCode->GetCodeError() )
{
- // RPN-Laenge kann sich aendern
+ // RPN length may get changed
BOOL bWasInFormulaTree = pDocument->IsInFormulaTree( this );
if ( bWasInFormulaTree )
pDocument->RemoveFromFormulaTree( this );
- // Laden aus Filter? Dann noch nix machen!
+ // Loading from within filter? No listening yet!
if( pDocument->IsInsertingFromOtherDoc() )
bNoListening = TRUE;
@@ -1064,13 +924,12 @@ void ScFormulaCell::CompileTokenArray( BOOL bNoListening )
EndListeningTo( pDocument );
ScCompiler aComp(pDocument, aPos, *pCode );
bSubTotal = aComp.CompileTokenArray();
- if( !pCode->GetError() )
+ if( !pCode->GetCodeError() )
{
nFormatType = aComp.GetNumFormatType();
nFormatIndex = 0;
bChanged = TRUE;
- nErgValue = 0.0;
- aErgString.Erase();
+ aResult.SetToken( NULL);
bCompile = FALSE;
if ( !bNoListening )
StartListeningTo( pDocument );
@@ -1090,9 +949,7 @@ void ScFormulaCell::CompileXML( ScProgress& rProgress )
return ;
}
- ScCompiler aComp( pDocument, aPos, *pCode );
- aComp.SetCompileEnglish( TRUE );
- aComp.SetImportXML( TRUE );
+ ScCompiler aComp( pDocument, aPos, *pCode, eTempGrammar);
String aFormula;
aComp.CreateStringFromTokenArray( aFormula );
pDocument->DecXMLImportedFormulaCount( aFormula.Len() );
@@ -1103,7 +960,7 @@ void ScFormulaCell::CompileXML( ScProgress& rProgress )
ScTokenArray* pCodeOld = pCode;
pCode = aComp.CompileString( aFormula );
delete pCodeOld;
- if( !pCode->GetError() )
+ if( !pCode->GetCodeError() )
{
if ( !pCode->GetLen() )
{
@@ -1113,7 +970,7 @@ void ScFormulaCell::CompileXML( ScProgress& rProgress )
pCode->AddBad( aFormula.GetBuffer() );
}
bSubTotal = aComp.CompileTokenArray();
- if( !pCode->GetError() )
+ if( !pCode->GetCodeError() )
{
nFormatType = aComp.GetNumFormatType();
nFormatIndex = 0;
@@ -1141,16 +998,16 @@ void ScFormulaCell::CalcAfterLoad()
BOOL bNewCompiled = FALSE;
// Falls ein Calc 1.0-Doc eingelesen wird, haben wir ein Ergebnis,
// aber kein TokenArray
- if( !pCode->GetLen() && aErgString.Len() )
+ if( !pCode->GetLen() && aResult.GetHybridFormula().Len() )
{
- Compile( aErgString, TRUE, nErgConv );
- aErgString.Erase();
+ Compile( aResult.GetHybridFormula(), TRUE, eTempGrammar);
+ aResult.SetToken( NULL);
bDirty = TRUE;
bNewCompiled = TRUE;
}
// Das UPN-Array wird nicht erzeugt, wenn ein Calc 3.0-Doc eingelesen
// wurde, da die RangeNames erst jetzt existieren.
- if( pCode->GetLen() && !pCode->GetCodeLen() && !pCode->GetError() )
+ if( pCode->GetLen() && !pCode->GetCodeLen() && !pCode->GetCodeError() )
{
ScCompiler aComp(pDocument, aPos, *pCode);
bSubTotal = aComp.CompileTokenArray();
@@ -1164,11 +1021,10 @@ void ScFormulaCell::CalcAfterLoad()
// gespeichert werden, woraufhin spaeter im NumberFormatter die BLC Lib
// bei einem fabs(-NAN) abstuerzt (#32739#)
// hier fuer alle Systeme ausbuegeln, damit da auch Err503 steht
- if ( bIsValue && !::rtl::math::isFinite( nErgValue ) )
+ if ( aResult.IsValue() && !::rtl::math::isFinite( aResult.GetDouble() ) )
{
DBG_ERRORFILE("Formelzelle INFINITY !!! Woher kommt das Dokument?");
- nErgValue = 0.0;
- pCode->SetError( errIllegalFPOperation );
+ aResult.SetResultError( errIllegalFPOperation );
bDirty = TRUE;
}
// DoubleRefs bei binaeren Operatoren waren vor v5.0 immer Matrix,
@@ -1177,13 +1033,12 @@ void ScFormulaCell::CalcAfterLoad()
GetMatrixFlag() == MM_NONE && pCode->HasMatrixDoubleRefOps() )
{
cMatrixFlag = MM_FORMULA;
- nMatCols = 1;
- nMatRows = 1;
+ SetMatColsRows( 1, 1);
}
// Muss die Zelle berechnet werden?
// Nach Load koennen Zellen einen Fehlercode enthalten, auch dann
// Listener starten und ggbf. neu berechnen wenn nicht RECALCMODE_NORMAL
- if( !bNewCompiled || !pCode->GetError() )
+ if( !bNewCompiled || !pCode->GetCodeError() )
{
StartListeningTo( pDocument );
if( !pCode->IsRecalcModeNormal() )
@@ -1338,12 +1193,12 @@ void ScFormulaCell::Interpret()
if (!pDocument->GetDocOptions().IsIter())
{
- pCode->SetError( errCircularReference );
+ aResult.SetResultError( errCircularReference );
return;
}
- if (pCode->GetError() == errCircularReference)
- pCode->SetError( 0 );
+ if (aResult.GetResultError() == errCircularReference)
+ aResult.SetResultError( 0 );
// Start or add to iteration list.
if (!pDocument->GetRecursionHelper().IsDoingIteration() ||
@@ -1379,8 +1234,7 @@ void ScFormulaCell::Interpret()
{
if (rRecursionHelper.GetRecursionCount() > 0 ||
!rRecursionHelper.IsDoingRecursion())
- rRecursionHelper.Insert( this, bOldRunning, bIsValue, nErgValue,
- aErgString);
+ rRecursionHelper.Insert( this, bOldRunning, aResult);
bool bIterationFromRecursion = false;
bool bResumeIteration = false;
do
@@ -1422,12 +1276,7 @@ void ScFormulaCell::Interpret()
{
if (!pIterCell->bDirty || aIter == aOldStart)
{
- pIterCell->bIsValue =
- (*aIter).bPreviousNumeric;
- pIterCell->nErgValue =
- (*aIter).fPreviousResult;
- pIterCell->aErgString =
- (*aIter).aPreviousString;
+ pIterCell->aResult = (*aIter).aPreviousResult;
}
--pIterCell->nSeenInIteration;
}
@@ -1467,9 +1316,7 @@ void ScFormulaCell::Interpret()
rRecursionHelper.GetIteration() !=
pIterCell->GetSeenInIteration())
{
- (*aIter).bPreviousNumeric = pIterCell->bIsValue;
- (*aIter).fPreviousResult = pIterCell->nErgValue;
- (*aIter).aPreviousString = pIterCell->aErgString;
+ (*aIter).aPreviousResult = pIterCell->aResult;
pIterCell->InterpretTail( SCITP_FROM_ITERATION);
}
rDone = rDone && !pIterCell->IsDirtyOrInTableOpDirty();
@@ -1512,7 +1359,7 @@ void ScFormulaCell::Interpret()
// single cells did.
pIterCell->bDirty = FALSE;
pIterCell->bTableOpDirty = FALSE;
- pIterCell->pCode->SetError( errNoConvergence);
+ pIterCell->aResult.SetResultError( errNoConvergence);
pIterCell->bChanged = TRUE;
pIterCell->SetTextWidth( TEXTWIDTH_DIRTY);
pIterCell->SetScriptType( SC_SCRIPTTYPE_UNKNOWN);
@@ -1589,7 +1436,7 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam )
}
} aRecursionCounter( pDocument->GetRecursionHelper(), this);
nSeenInIteration = pDocument->GetRecursionHelper().GetIteration();
- if( !pCode->GetCodeLen() && !pCode->GetError() )
+ if( !pCode->GetCodeLen() && !pCode->GetCodeError() )
{
// #i11719# no UPN and no error and no token code but result string present
// => interpretation of this cell during name-compilation and unknown names
@@ -1598,9 +1445,9 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam )
// This should only be a temporary condition and, since we set an
// error, if ran into it again we'd bump into the dirty-clearing
// condition further down.
- if ( !pCode->GetLen() && aErgString.Len() )
+ if ( !pCode->GetLen() && aResult.GetHybridFormula().Len() )
{
- pCode->SetError( errNoCode );
+ pCode->SetCodeError( errNoCode );
// This is worth an assertion; if encountered in daily work
// documents we might need another solution. Or just confirm correctness.
DBG_ERRORFILE( "ScFormulaCell::Interpret: no UPN, no error, no token, but string" );
@@ -1628,23 +1475,19 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam )
pDocument->IncInterpretLevel();
ScInterpreter* p = new ScInterpreter( this, pDocument, aPos, *pCode );
StackCleaner aStackCleaner( pDocument, p);
- USHORT nOldErrCode = pCode->GetError();
+ USHORT nOldErrCode = aResult.GetResultError();
if ( nSeenInIteration == 0 )
{ // Only the first time
// With bChanged=FALSE, if a newly compiled cell has a result of
// 0.0, no change is detected and the cell will not be repainted.
// bChanged = FALSE;
- if (nOldErrCode == errNoConvergence &&
- pDocument->GetDocOptions().IsIter())
- pCode->SetError( 0 );
+ aResult.SetResultError( 0 );
}
- if ( xMatrix )
- xMatrix = NULL;
- switch ( pCode->GetError() )
+ switch ( aResult.GetResultError() )
{
- case errCircularReference : // wird neu festgestellt
- pCode->SetError( 0 );
+ case errCircularReference : // will be determined again if so
+ aResult.SetResultError( 0 );
break;
}
@@ -1658,25 +1501,26 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam )
return;
}
bRunning = bOldRunning;
+
// Do not create a HyperLink() cell if the formula results in an error.
- if( pCode->GetError() && pCode->IsHyperLink())
+ if( p->GetError() && pCode->IsHyperLink())
pCode->SetHyperLink(FALSE);
- if( pCode->GetError() && pCode->GetError() != errCircularReference)
+ if( p->GetError() && p->GetError() != errCircularReference)
{
bDirty = FALSE;
bTableOpDirty = FALSE;
bChanged = TRUE;
- bIsValue = TRUE;
}
if (eTailParam == SCITP_FROM_ITERATION && IsDirtyOrInTableOpDirty())
{
+ bool bIsValue = aResult.IsValue(); // the previous type
// Did it converge?
if ((bIsValue && p->GetResultType() == svDouble && fabs(
- p->GetNumResult() - nErgValue) <=
+ p->GetNumResult() - aResult.GetDouble()) <=
pDocument->GetDocOptions().GetIterEps()) ||
(!bIsValue && p->GetResultType() == svString &&
- p->GetStringResult() == aErgString))
+ p->GetStringResult() == aResult.GetString()))
{
// A convergence in the first iteration doesn't necessarily
// mean that it's done, it may be because not all related cells
@@ -1694,32 +1538,10 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam )
}
}
- switch( p->GetResultType() )
- {
- case svDouble:
- if( nErgValue != p->GetNumResult() || !bIsValue )
- {
- bChanged = TRUE;
- bIsValue = TRUE;
- nErgValue = p->GetNumResult();
- }
- break;
- case svString:
- if( aErgString != p->GetStringResult() || bIsValue )
- {
- bChanged = TRUE;
- bIsValue = FALSE;
- aErgString = p->GetStringResult();
- }
- break;
- default:
- ; // nothing
- }
-
- // Neuer Fehlercode?
- if( !bChanged && pCode->GetError() != nOldErrCode )
+ // New error code?
+ if( p->GetError() != nOldErrCode )
bChanged = TRUE;
- // Anderes Zahlenformat?
+ // Different number format?
if( nFormatType != p->GetRetFormatType() )
{
nFormatType = p->GetRetFormatType();
@@ -1730,8 +1552,24 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam )
nFormatIndex = p->GetRetFormatIndex();
bChanged = TRUE;
}
- // Genauigkeit wie angezeigt?
- if ( bIsValue && !pCode->GetError()
+
+ // In case of changes just obtain the result, no temporary and
+ // comparison needed anymore.
+ if (bChanged)
+ aResult.SetToken( p->GetResultToken());
+ else
+ {
+ ScFormulaResult aNewResult( p->GetResultToken());
+ StackVar eOld = aResult.GetCellResultType();
+ StackVar eNew = aNewResult.GetCellResultType();
+ bChanged = (eOld != eNew ||
+ (eNew == svDouble && aResult.GetDouble() != aNewResult.GetDouble()) ||
+ (eNew == svString && aResult.GetString() != aNewResult.GetString()));
+ aResult.Assign( aNewResult);
+ }
+
+ // Precision as shown?
+ if ( aResult.IsValue() && !p->GetError()
&& pDocument->GetDocOptions().IsCalcAsShown()
&& nFormatType != NUMBERFORMAT_DATE
&& nFormatType != NUMBERFORMAT_TIME
@@ -1743,20 +1581,20 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam )
if ( (nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
nFormat = ScGlobal::GetStandardFormat(
*pDocument->GetFormatTable(), nFormat, nFormatType );
- nErgValue = pDocument->RoundValueAsShown( nErgValue, nFormat );
+ aResult.SetDouble( pDocument->RoundValueAsShown(
+ aResult.GetDouble(), nFormat));
}
if (eTailParam == SCITP_NORMAL)
{
bDirty = FALSE;
bTableOpDirty = FALSE;
}
- xMatrix = p->GetMatrixResult();
- if( xMatrix )
+ if( aResult.GetMatrix().Is() )
{
// If the formula wasn't entered as a matrix formula, live on with
- // the upper left corner and let the interpreter delete the matrix.
+ // the upper left corner and let reference counting delete the matrix.
if( cMatrixFlag != MM_FORMULA && !pCode->IsHyperLink() )
- xMatrix = NULL;
+ aResult.SetToken( aResult.GetCellResultToken());
}
if( bChanged )
{
@@ -1766,11 +1604,11 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam )
if ( !pCode->IsRecalcModeAlways() )
pDocument->RemoveFromFormulaTree( this );
#ifndef PRODUCT
- if ( bIsValue && !pCode->GetError() && !::rtl::math::isFinite( nErgValue ) )
+ if ( aResult.IsValue() && !p->GetError() && !::rtl::math::isFinite( aResult.GetDouble() ) )
{
DBG_ERRORFILE( msgDbgInfinity );
- nErgValue = 0.0;
- pCode->SetError( errIllegalFPOperation );
+ aResult.SetToken( NULL);
+ aResult.SetResultError( errIllegalFPOperation );
}
#endif
@@ -1795,19 +1633,43 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam )
else
{
// Zelle bei Compiler-Fehlern nicht ewig auf dirty stehenlassen
- DBG_ASSERT( pCode->GetError(), "kein UPN-Code und kein Fehler ?!?!" );
+ DBG_ASSERT( pCode->GetCodeError(), "kein UPN-Code und kein Fehler ?!?!" );
bDirty = FALSE;
bTableOpDirty = FALSE;
}
}
+void ScFormulaCell::SetMatColsRows( SCCOL nCols, SCROW nRows )
+{
+ ScMatrixFormulaCellToken* pMat = aResult.GetMatrixFormulaCellTokenNonConst();
+ if (pMat)
+ pMat->SetMatColsRows( nCols, nRows);
+ else if (nCols || nRows)
+ aResult.SetToken( new ScMatrixFormulaCellToken( nCols, nRows));
+}
+
+
+void ScFormulaCell::GetMatColsRows( SCCOL & nCols, SCROW & nRows ) const
+{
+ const ScMatrixFormulaCellToken* pMat = aResult.GetMatrixFormulaCellToken();
+ if (pMat)
+ pMat->GetMatColsRows( nCols, nRows);
+ else
+ {
+ nCols = 0;
+ nRows = 0;
+ }
+}
+
+
ULONG ScFormulaCell::GetStandardFormat( SvNumberFormatter& rFormatter, ULONG nFormat ) const
{
if ( nFormatIndex && (nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
return nFormatIndex;
- if ( bIsValue ) //! nicht IsValue()
- return ScGlobal::GetStandardFormat( nErgValue, rFormatter, nFormat, nFormatType );
+ //! not ScFormulaCell::IsValue(), that could reinterpret the formula again.
+ if ( aResult.IsValue() )
+ return ScGlobal::GetStandardFormat( aResult.GetDouble(), rFormatter, nFormat, nFormatType );
else
return ScGlobal::GetStandardFormat( rFormatter, nFormat, nFormatType );
}
@@ -1912,8 +1774,14 @@ BOOL ScFormulaCell::IsDirtyOrInTableOpDirty() const
void ScFormulaCell::SetErrCode( USHORT n )
{
- pCode->SetError( n );
- bIsValue = FALSE;
+ /* FIXME: check the numerous places where ScTokenArray::GetCodeError() is
+ * used whether it is solely for transport of a simple result error and get
+ * rid of that abuse. */
+ pCode->SetCodeError( n );
+ // Hard set errors are transported as result type value per convention,
+ // e.g. via clipboard. ScFormulaResult::IsValue() and
+ // ScFormulaResult::GetDouble() handle that.
+ aResult.SetResultError( n );
}
void ScFormulaCell::AddRecalcMode( ScRecalcMode nBits )
@@ -1954,11 +1822,12 @@ void ScFormulaCell::GetURLResult( String& rURL, String& rCellText )
GetString( aCellString );
pFormatter->GetOutputString( aCellString, nCellFormat, rCellText, &pColor );
}
- if(xMatrix)
+ ScConstMatrixRef xMat( aResult.GetMatrix());
+ if (xMat)
{
ScMatValType nMatValType;
// determine if the matrix result is a string or value.
- const ScMatrixValue* pMatVal = xMatrix->Get(0, 1, nMatValType);
+ const ScMatrixValue* pMatVal = xMat->Get(0, 1, nMatValType);
if (pMatVal)
{
if (!ScMatrix::IsValueType( nMatValType))