[Libreoffice-commits] core.git: 3 commits - sc/inc sc/source
Eike Rathke
erack at redhat.com
Thu Apr 9 09:19:55 PDT 2015
sc/inc/compiler.hxx | 4 +
sc/source/core/tool/compiler.cxx | 150 ++++++++++++++++++++++++++-------------
2 files changed, 106 insertions(+), 48 deletions(-)
New commits:
commit d6398719abecfca60db37637490e602222992dc2
Author: Eike Rathke <erack at redhat.com>
Date: Thu Apr 9 18:03:09 2015 +0200
TableRef: correct GetToken() logic
Ensure that only desired tokens are obtained and the resulting new token
is actually the current one upon return.
Change-Id: I624c324b861d8658accf3285cad2cfc5a598b450
diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx
index 3154d57..03baa29 100644
--- a/sc/inc/compiler.hxx
+++ b/sc/inc/compiler.hxx
@@ -386,6 +386,9 @@ public:
bool IsTableRefItem( const OUString& ) const;
bool IsTableRefColumn( const OUString& ) const;
+ /** Calls GetToken() if PeekNextNoSpaces() is of given OpCode. */
+ bool GetTokenIfOpCode( OpCode eOp );
+
/**
* When auto correction is set, the jump command reorder must be enabled.
*/
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index 4cf6f24..a988209 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -4820,6 +4820,14 @@ bool ScCompiler::HandleDbData()
return true;
}
+bool ScCompiler::GetTokenIfOpCode( OpCode eOp )
+{
+ const formula::FormulaToken* p = pArr->PeekNextNoSpaces();
+ if (p && p->GetOpCode() == eOp)
+ return GetToken();
+ return false;
+}
+
/* Documentation on MS-Excel Table structured references:
* https://support.office.com/en-us/article/Use-structured-references-in-Excel-table-formulas-75fb07d3-826a-449c-b76f-363057e3d16f
@@ -4847,7 +4855,6 @@ bool ScCompiler::HandleTableRef()
aDBRange.aEnd.SetTab(aDBRange.aStart.Tab());
ScRange aRange( aDBRange);
ScTokenArray* pNew = new ScTokenArray();
- bool bGotToken = false;
bool bAddRange = true;
bool bForwardToClose = false;
ScTableRefToken::Item eItem = pTR->GetItem();
@@ -4927,22 +4934,27 @@ bool ScCompiler::HandleTableRef()
break;
}
bool bColumnRange = false;
- if (bForwardToClose && (bGotToken = GetToken()) && mpToken->GetOpCode() == ocTableRefOpen)
+ int nLevel = 0;
+ if (bForwardToClose && GetTokenIfOpCode( ocTableRefOpen))
{
- int nLevel = 1;
+ ++nLevel;
enum
{
sOpen,
sItem,
sClose,
sSep,
+ sLast,
sStop
} eState = sOpen;
do
{
- if ((bGotToken = GetToken()))
+ const formula::FormulaToken* p = pArr->PeekNextNoSpaces();
+ if (!p)
+ eState = sStop;
+ else
{
- switch (mpToken->GetOpCode())
+ switch (p->GetOpCode())
{
case ocTableRefOpen:
eState = ((eState == sOpen || eState == sSep) ? sOpen : sStop);
@@ -4961,35 +4973,37 @@ bool ScCompiler::HandleTableRef()
break;
case ocTableRefClose:
eState = ((eState == sItem || eState == sClose) ? sClose : sStop);
- if (--nLevel <= 0)
- {
- if (nLevel < 0)
- SetError( errPair);
- eState = sStop;
- }
+ if (eState != sStop && --nLevel == 0)
+ eState = sLast;
break;
case ocSep:
eState = ((eState == sClose) ? sSep : sStop);
break;
case ocPush:
- if (eState == sOpen &&
- (mpToken->GetType() == svSingleRef || mpToken->GetType() == svDoubleRef))
+ if (eState == sOpen && (p->GetType() == svSingleRef || p->GetType() == svDoubleRef))
+ {
bColumnRange = true;
- eState = sStop;
+ eState = sLast;
+ }
+ else
+ {
+ eState = sStop;
+ }
break;
default:
eState = sStop;
}
+ if (eState != sStop)
+ GetToken();
+ if (eState == sLast)
+ eState = sStop;
}
- } while (bGotToken && eState != sStop);
- if (bGotToken && mpToken->GetOpCode() == ocTableRefClose)
- bGotToken = false; // get next token below in return
+ } while (eState != sStop);
}
if (bAddRange)
{
if (bColumnRange)
{
- bGotToken = false; // obtain at least a close hereafter
// Limit range to specified columns.
ScRange aColRange( ScAddress::INITIALIZE_INVALID );
switch (mpToken->GetType())
@@ -4997,16 +5011,15 @@ bool ScCompiler::HandleTableRef()
case svSingleRef:
{
aColRange.aStart = aColRange.aEnd = mpToken->GetSingleRef()->toAbs( aPos);
- if ( (bGotToken = GetToken()) && mpToken->GetOpCode() == ocTableRefClose &&
- (bGotToken = GetToken()) && mpToken->GetOpCode() == ocRange &&
- (bGotToken = GetToken()) && mpToken->GetOpCode() == ocTableRefOpen &&
- (bGotToken = GetToken()) && mpToken->GetOpCode() == ocPush)
+ if ( GetTokenIfOpCode( ocTableRefClose) && (nLevel--) &&
+ GetTokenIfOpCode( ocRange) &&
+ GetTokenIfOpCode( ocTableRefOpen) && (++nLevel) &&
+ GetTokenIfOpCode( ocPush))
{
if (mpToken->GetType() != svSingleRef)
aColRange = ScRange( ScAddress::INITIALIZE_INVALID);
else
{
- bGotToken = false; // obtain at least a close hereafter
aColRange.aEnd = mpToken->GetSingleRef()->toAbs( aPos);
aColRange.Justify();
}
@@ -5040,27 +5053,19 @@ bool ScCompiler::HandleTableRef()
{
SetError( errNoRef);
}
- if (bColumnRange && !bGotToken)
- {
- if ((bGotToken = GetToken()) && mpToken->GetOpCode() == ocTableRefClose)
- {
- if ((bGotToken = GetToken()) && mpToken->GetOpCode() == ocTableRefClose)
- bGotToken = false; // get next token below in return
- }
- else
- {
- SetError( errPair);
- bGotToken = false; // get next token below in return
- }
- }
}
else
{
SetError( errNoRef);
}
+ while (nLevel-- > 0)
+ {
+ if (!GetTokenIfOpCode( ocTableRefClose))
+ SetError( errPair);
+ }
PushTokenArray( pNew, true );
pNew->Reset();
- return bGotToken ? true : GetToken();
+ return GetToken();
}
return true;
}
commit 3335b46d123053b1228b94207a32bab08cf9d4e3
Author: Eike Rathke <erack at redhat.com>
Date: Thu Apr 9 14:39:52 2015 +0200
TableRef: allow column specifier without item
Change-Id: I1263f190d769254949701b3a257b2af5d6ea61a2
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index c2ebe55..4cf6f24 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -4863,16 +4863,7 @@ bool ScCompiler::HandleTableRef()
aRange.aEnd.IncRow(-1);
if (aRange.aEnd.Row() < aRange.aStart.Row())
bAddRange = false;
-
- // Optional [] may follow.
- if ((bGotToken = GetToken()) && mpToken->GetOpCode() == ocTableRefOpen)
- {
- if ((bGotToken = GetToken()))
- {
- if (mpToken->GetOpCode() == ocTableRefClose)
- bGotToken = false; // get next token below
- }
- }
+ bForwardToClose = true;
}
break;
case ScTableRefToken::ALL:
commit d5e1b41330fdd7341415e6c34f61ec826d20e51b
Author: Eike Rathke <erack at redhat.com>
Date: Thu Apr 9 14:11:46 2015 +0200
TableRef: lookup column specifier
Change-Id: I73109e5a862b2f4bc456dff512bddf5d23586a6d
diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx
index b4b1945..3154d57 100644
--- a/sc/inc/compiler.hxx
+++ b/sc/inc/compiler.hxx
@@ -384,6 +384,7 @@ public:
bool IsErrorConstant( const OUString& ) const;
bool IsTableRefItem( const OUString& ) const;
+ bool IsTableRefColumn( const OUString& ) const;
/**
* When auto correction is set, the jump command reorder must be enabled.
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index d580bb9..c2ebe55 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -3349,6 +3349,56 @@ bool ScCompiler::IsTableRefItem( const OUString& rName ) const
return bItem;
}
+bool ScCompiler::IsTableRefColumn( const OUString& rName ) const
+{
+ // Only called when there actually is a current TableRef, hence
+ // accessing maTableRefs.back() is safe.
+ ScTableRefToken* p = dynamic_cast<ScTableRefToken*>(maTableRefs.back().mxToken.get());
+ assert(p); // not a ScTableRefToken can't be
+
+ ScDBData* pDBData = pDoc->GetDBCollection()->getNamedDBs().findByIndex( p->GetIndex());
+ if (!pDBData)
+ return false;
+
+ // '#', '[', ']' and '\'' are escaped with '\''
+ OUString aName( rName.replaceAll( OUString("'"), OUString()));
+
+ ScRange aRange;
+ pDBData->GetArea( aRange);
+ aRange.aEnd.SetTab( aRange.aStart.Tab());
+ aRange.aEnd.SetRow( aRange.aStart.Row());
+
+ // Quite similar to IsColRowName() but limited to one row of headers.
+ ScCellIterator aIter( pDoc, aRange);
+ for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
+ {
+ CellType eType = aIter.getType();
+ bool bOk = false;
+ if (eType == CELLTYPE_FORMULA)
+ {
+ ScFormulaCell* pFC = aIter.getFormulaCell();
+ bOk = (pFC->GetCode()->GetCodeLen() > 0) && (pFC->aPos != aPos);
+ }
+ else
+ bOk = true;
+
+ if (bOk && aIter.hasString())
+ {
+ OUString aStr = aIter.getString();
+ if (ScGlobal::GetpTransliteration()->isEqual( aStr, aName))
+ {
+ ScSingleRefData aRef;
+ aRef.InitFlags();
+ aRef.SetColRel( true );
+ aRef.SetAddress( aIter.GetPos(), aPos);
+ maRawToken.SetSingleReference( aRef );
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
void ScCompiler::SetAutoCorrection( bool bVal )
{
assert(mbJumpCommandReorder);
@@ -3653,8 +3703,16 @@ bool ScCompiler::NextNewToken( bool bInArray )
do
{
- mbRewind = false;
const OUString aOrg( cSymbol );
+
+ // Check for TableRef column specifier first, it may be anything.
+ if (cSymbol[0] != '#' && !maTableRefs.empty() && maTableRefs.back().mnLevel)
+ {
+ if (IsTableRefColumn( aOrg ))
+ return true;
+ }
+
+ mbRewind = false;
aUpper.clear();
bool bAsciiUpper = false;
More information about the Libreoffice-commits
mailing list