Bug 140312 - copy & paste treats log2 as a cell (MAJOR)
Summary: copy & paste treats log2 as a cell (MAJOR)
Status: RESOLVED FIXED
Alias: None
Product: calligrasheets
Classification: Applications
Component: general (show other bugs)
Version: unspecified
Platform: openSUSE Linux
: NOR normal
Target Milestone: ---
Assignee: Calligra Sheets (KSpread) Bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-01-19 21:01 UTC by Maciej Pilichowski
Modified: 2007-08-12 22:40 UTC (History)
0 users

See Also:
Latest Commit:
Version Fixed In:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Maciej Pilichowski 2007-01-19 21:01:25 UTC
Version:            (using KDE KDE 3.5.5)
Installed from:    SuSE RPMs

log2 is computed correctly, but copy & paste that cell one down -- you get log3. Copy it below again, log4 and so on.
Comment 1 Stefan Nikolaus 2007-08-03 11:39:50 UTC
Code to blame Cell::encodeFormula() and Cell::decodeFormula(). Rewrite these two to use the formula tokens, in which LOG2 is handled correctly.
Comment 2 Stefan Nikolaus 2007-08-12 22:40:23 UTC
SVN commit 699362 by nikolaus:

Commands	Autofill, Copy & Paste, Cut & Paste
		Rewrite Cell::encodeFormula to use the formula tokens. This ensures, that
		the LOG2() function will not be identified as cell reference and the processing
		should be faster and more reliable than the old algo.

BUG: 140312


 M  +72 -113   Cell.cpp  


--- trunk/koffice/kspread/Cell.cpp #699361:699362
@@ -59,6 +59,7 @@
 #include "Localization.h"
 #include "LoadingInfo.h"
 #include "Map.h"
+#include "NamedAreaManager.h"
 #include "Object.h"
 #include "RowColumnFormat.h"
 #include "Selection.h"
@@ -512,141 +513,99 @@
 }
 
 
-QString Cell::encodeFormula( bool _era, int _col, int _row ) const
+QString Cell::encodeFormula( bool fixedReferences, int _col, int _row ) const
 {
-    if ( _col == -1 )
+    if (!isFormula())
+        return QString();
+    if (_col == -1)
         _col = d->column;
-    if ( _row == -1 )
+    if (_row == -1)
         _row = d->row;
 
-    QString erg = "";
-
-    if ( userInput().isEmpty() )
-        return QString();
-
-    const QString userInput = this->userInput();
-
-    bool fix1 = false;
-    bool fix2 = false;
-    bool onNumber = false;
-    unsigned int pos = 0;
-    const unsigned int length = userInput.length();
-
-    // All this can surely be made 10 times faster, but I just "ported" it to QString
-    // without any attempt to optimize things -- this is really brittle (Werner)
-    while ( pos < length )
+    QString result('=');
+    const Tokens tokens = formula().tokens();
+    for (int i = 0; i < tokens.count(); ++i)
     {
-        if ( userInput[pos] == '"' )
+        const Token token = tokens[i];
+        switch (token.type())
         {
-            erg += userInput[pos++];
-            while ( pos < length && userInput[pos] != '"' )  // till the end of the world^H^H^H "string"
+            case Token::Cell:
+            case Token::Range:
             {
-                erg += userInput[pos++];
-                // Allow escaped double quotes (\")
-                if ( pos < length && userInput[pos] == '\\' && userInput[pos+1] == '"' )
+                if (doc()->namedAreaManager()->contains(token.text()))
                 {
-                    erg += userInput[pos++];
-                    erg += userInput[pos++];
+                    result.append(token.text()); // simply keep the area name
+                    break;
                 }
-            }
-            if ( pos < length )  // also copy the trailing double quote
-                erg += userInput[pos++];
-
-            onNumber = false;
-        }
-        else if ( userInput[pos].isDigit() )
-        {
-          erg += userInput[pos++];
-          fix1 = fix2 = false;
-          onNumber = true;
-        }
-        else if ( userInput[pos] != '$' && !userInput[pos].isLetter() )
-        {
-            erg += userInput[pos++];
-            fix1 = fix2 = false;
-            onNumber = false;
-        }
-        else
-        {
-            QString tmp = "";
-            if ( userInput[pos] == '$' )
-            {
-                tmp = '$';
-                pos++;
-                fix1 = true;
-            }
-            if ( userInput[pos].isLetter() )
-            {
-                QString buffer;
-                unsigned int pos2 = 0;
-                while ( pos < length && userInput[pos].isLetter() )
+                const Region region(token.text(), doc()->map());
+                // Actually, a contiguous region, but the fixation is needed
+                Region::ConstIterator end = region.constEnd();
+                for (Region::ConstIterator it = region.constBegin(); it != end; ++it)
                 {
-                    tmp += userInput[pos];
-                    buffer[pos2++] = userInput[pos++];
-                }
-                if ( pos < length && userInput[pos] == '$' )
-                {
-                    tmp += '$';
-                    pos++;
-                    fix2 = true;
-                }
-                if ( pos < length && userInput[pos].isDigit() )
-                {
-                    const unsigned int oldPos = pos;
-                    while ( pos < length && userInput[pos].isDigit() ) ++pos;
-                    int row = 0;
-                    if ( pos != oldPos )
-                        row = userInput.mid(oldPos, pos-oldPos).toInt();
-                    // Is it a sheet name || is it a function name like DEC2HEX
-                    /* or if we're parsing a number, this could just be the
-                       exponential part of it  (1.23E4) */
-                    if ( pos < length &&
-                         ( ( userInput[pos] == '!' ) ||
-                         userInput[pos].isLetter() ||
-                         onNumber ) )
+                    if (!(*it)->isValid())
+                        continue;
+                    if ((*it)->type() == Region::Element::Point)
                     {
-                        erg += tmp;
-                        fix1 = fix2 = false;
-                        pos = oldPos;
+                        if ((*it)->sheet())
+                            result.append((*it)->sheet()->sheetName() + '!');
+                        const QPoint pos = (*it)->rect().topLeft();
+                        if ((*it)->isColumnFixed())
+                            result.append(QString("$%1").arg(pos.x()));
+                        else if (fixedReferences)
+                            result.append(QChar(0xA7) + QString("%1").arg(pos.x()));
+                        else
+                            result.append(QString("#%1").arg(pos.x() - _col));
+                        if ((*it)->isRowFixed())
+                            result.append(QString("$%1#").arg(pos.y()));
+                        else if (fixedReferences)
+                            result.append(QChar(0xA7) + QString("%1#").arg(pos.y()));
+                        else
+                            result.append(QString("#%1#").arg(pos.y() - _row));
                     }
-                    else // It must be a cell identifier
+                    else // ((*it)->type() == Region::Range)
                     {
-                        //now calculate the row as integer value
-                        int col = 0;
-                        col = Util::decodeColumnLabelText( buffer );
-                        if ( fix1 )
-                            erg += QString( "$%1" ).arg( col );
+                        if ((*it)->sheet())
+                            result.append((*it)->sheet()->sheetName() + '!');
+                        QPoint pos = (*it)->rect().topLeft();
+                        if ((*it)->isLeftFixed())
+                            result.append(QString("$%1").arg(pos.x()));
+                        else if (fixedReferences)
+                            result.append(QChar(0xA7) + QString("%1").arg(pos.x()));
                         else
-                            if (_era)
-                                erg += QChar(0xA7) + QString( "%1" ).arg( col );
-                            else
-                                erg += QString( "#%1" ).arg( col - _col );
-
-                        if ( fix2 )
-                            erg += QString( "$%1#").arg( row );
+                            result.append(QString("#%1").arg(pos.x() - _col));
+                        if ((*it)->isTopFixed())
+                            result.append(QString("$%1#").arg(pos.y()));
+                        else if (fixedReferences)
+                            result.append(QChar(0xA7) + QString("%1#").arg(pos.y()));
                         else
-                            if (_era)
-                                erg += QChar(0xA7) + QString( "%1#" ).arg( row );
-                            else
-                                erg += QString( "#%1#" ).arg( row - _row );
+                            result.append(QString("#%1#").arg(pos.y() - _row));
+                        result.append(':');
+                        pos = (*it)->rect().bottomRight();
+                        if ((*it)->isRightFixed())
+                            result.append(QString("$%1").arg(pos.x()));
+                        else if (fixedReferences)
+                            result.append(QChar(0xA7) + QString("%1").arg(pos.x()));
+                        else
+                            result.append(QString("#%1").arg(pos.x() - _col));
+                        if ((*it)->isBottomFixed())
+                            result.append(QString("$%1#").arg(pos.y()));
+                        else if (fixedReferences)
+                            result.append(QChar(0xA7) + QString("%1#").arg(pos.y()));
+                        else
+                            result.append(QString("#%1#").arg(pos.y() - _row));
                     }
                 }
-                else
-                {
-                    erg += tmp;
-                    fix1 = fix2 = false;
-                }
+                break;
             }
-            else
+            default:
             {
-                erg += tmp;
-                fix1 = false;
+                result.append(token.text());
+                break;
             }
-            onNumber = false;
         }
     }
-
-    return erg;
+    kDebug() << k_funcinfo << result;
+    return result;
 }
 
 QString Cell::decodeFormula( const QString &_text, int _col, int _row) const