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 <er...@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 <er...@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 <er...@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;
 
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to