>> Attached patch adds formula XOR to calc.
>> Possibly the function ought to be included in one or more arrays of 
>> functions that are or are not known in Excel, Lotus, Qpro.

> [...] However, you attached a patch for DATEDIF instead of XOR ;-)

This time the patch is the one that covers XOR.

Winfried
From 45326af955b020cc861148c7c1c95449dab858f4 Mon Sep 17 00:00:00 2001
From: Winfried Donkers <o...@dci-electronics.nl>
Date: Wed, 6 Jun 2012 16:33:38 +0200
Subject: [PATCH] fdo#50488 added calc formula XOR as in ODFF1.2

Change-Id: I89c3267d479d5f034ad25ff879d1df8f90b84a55
---
 formula/inc/formula/compiler.hrc               |    3 +-
 formula/inc/formula/opcode.hxx                 |    1 +
 formula/source/core/api/FormulaCompiler.cxx    |   10 ++-
 formula/source/core/api/token.cxx              |    2 +-
 formula/source/core/resource/core_resource.src |    5 +
 sc/inc/helpids.h                               |    2 +-
 sc/qa/unit/ucalc.cxx                           |    1 +
 sc/source/core/inc/interpre.hxx                |    1 +
 sc/source/core/tool/interpr1.cxx               |  105 ++++++++++++++++++++++++
 sc/source/core/tool/interpr4.cxx               |    1 +
 sc/source/core/tool/parclass.cxx               |    2 +
 sc/source/filter/oox/formulabase.cxx           |    2 +-
 sc/source/ui/src/scfuncs.src                   |   24 ++++++
 sc/source/ui/vba/vbawsfunction.cxx             |    2 +-
 sc/util/hidother.src                           |    1 +
 15 files changed, 153 insertions(+), 9 deletions(-)

diff --git a/formula/inc/formula/compiler.hrc b/formula/inc/formula/compiler.hrc
index a2d4bb5..54ded84 100644
--- a/formula/inc/formula/compiler.hrc
+++ b/formula/inc/formula/compiler.hrc
@@ -89,7 +89,8 @@
 #define SC_OPCODE_INTERSECT          54
 #define SC_OPCODE_UNION              55
 #define SC_OPCODE_RANGE              56
-#define SC_OPCODE_STOP_BIN_OP        57
+#define SC_OPCODE_XOR                57
+#define SC_OPCODE_STOP_BIN_OP        58
 
 /* NOTE: binary and unary operators must be in sequence for compiler! */
 
diff --git a/formula/inc/formula/opcode.hxx b/formula/inc/formula/opcode.hxx
index a1543dd..16b12ec 100644
--- a/formula/inc/formula/opcode.hxx
+++ b/formula/inc/formula/opcode.hxx
@@ -89,6 +89,7 @@ enum OpCodeEnum
         ocGreaterEqual      = SC_OPCODE_GREATER_EQUAL,
         ocAnd               = SC_OPCODE_AND,
         ocOr                = SC_OPCODE_OR,
+        ocXor               = SC_OPCODE_XOR,
         ocIntersect         = SC_OPCODE_INTERSECT,
         ocUnion             = SC_OPCODE_UNION,
         ocRange             = SC_OPCODE_RANGE,
diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx
index 9e82422..e2de107 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -76,6 +76,7 @@ short lcl_GetRetFormat( OpCode eOpCode )
         case ocGreaterEqual:
         case ocAnd:
         case ocOr:
+        case ocXor:
         case ocNot:
         case ocTrue:
         case ocFalse:
@@ -1128,6 +1129,7 @@ void FormulaCompiler::Factor()
                 || eOp == ocMacro
                 || eOp == ocAnd
                 || eOp == ocOr
+                || eOp == ocXor
                 || eOp == ocBad
                 || ( eOp >= ocInternalBegin && eOp <= ocInternalEnd )
                 || (bCompileForFAP && ((eOp == ocIf) || (eOp == ocChose)))
@@ -1440,7 +1442,7 @@ OpCode FormulaCompiler::Expression()
         return ocStop;      //! generate token instead?
     }
     NotLine();
-    while (pToken->GetOpCode() == ocAnd || pToken->GetOpCode() == ocOr)
+    while (pToken->GetOpCode() == ocAnd || pToken->GetOpCode() == ocOr || pToken->GetOpCode() == ocXor)
     {
         FormulaTokenRef p = pToken;
         pToken->SetByte( 2 );       // 2 parameters!
@@ -1617,7 +1619,7 @@ FormulaToken* FormulaCompiler::CreateStringFromToken( rtl::OUStringBuffer& rBuff
     bool bSpaces = false;
     FormulaToken* t = pTokenP;
     OpCode eOp = t->GetOpCode();
-    if( eOp >= ocAnd && eOp <= ocOr )
+    if( eOp >= ocAnd && eOp <= ocXor )
     {
         // AND, OR infix?
         if ( bAllowArrAdvance )
@@ -1822,8 +1824,8 @@ OpCode FormulaCompiler::NextToken()
     else
     {
         // Before an operator there must not be another operator, with the
-        // exception of AND and OR.
-        if ( eOp != ocAnd && eOp != ocOr &&
+        // exception of AND, OR and XOR.
+        if ( eOp != ocAnd && eOp != ocOr && eOp != ocXor &&
                 (SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_BIN_OP )
                 && (eLastOp == ocOpen || eLastOp == ocSep ||
                     (SC_OPCODE_START_BIN_OP <= eLastOp && eLastOp < SC_OPCODE_STOP_UN_OP)))
diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx
index f426a31..fac4cbd 100644
--- a/formula/source/core/api/token.cxx
+++ b/formula/source/core/api/token.cxx
@@ -90,7 +90,7 @@ bool FormulaToken::IsFunction() const
         || (SC_OPCODE_START_2_PAR <= eOp && eOp < SC_OPCODE_STOP_2_PAR)     // x parameters (cByte==0 in
                                                                             // FuncAutoPilot)
         || eOp == ocMacro || eOp == ocExternal                  // macros, AddIns
-        || eOp == ocAnd || eOp == ocOr                          // former binary, now x parameters
+        || eOp == ocAnd || eOp == ocOr || eOp == ocXor          // former binary, now x parameters
         || eOp == ocNot || eOp == ocNeg                         // unary but function
         || (eOp >= ocInternalBegin && eOp <= ocInternalEnd)     // internal
         ));
diff --git a/formula/source/core/resource/core_resource.src b/formula/source/core/resource/core_resource.src
index 1259231..b4ea345 100644
--- a/formula/source/core/resource/core_resource.src
+++ b/formula/source/core/resource/core_resource.src
@@ -56,6 +56,7 @@ Resource RID_STRLIST_FUNCTION_NAMES_ENGLISH_ODFF
     String SC_OPCODE_GREATER_EQUAL { Text = ">=" ; };
     String SC_OPCODE_AND { Text = "AND" ; };
     String SC_OPCODE_OR { Text = "OR" ; };
+    String SC_OPCODE_XOR { Text = "XOR" ; };
     String SC_OPCODE_INTERSECT { Text = "!" ; };
     String SC_OPCODE_UNION { Text = "~" ; };
     String SC_OPCODE_RANGE { Text = ":" ; };
@@ -731,6 +732,10 @@ Resource RID_STRLIST_FUNCTION_NAMES
     {
         Text [ en-US ] = "OR" ;
     };
+    String SC_OPCODE_XOR
+    {
+        Text [ en-US ] = "XOR" ;
+    };
     String SC_OPCODE_INTERSECT { Text = "!" ; };
     String SC_OPCODE_UNION { Text = "~" ; };
     String SC_OPCODE_RANGE { Text = ":" ; };
diff --git a/sc/inc/helpids.h b/sc/inc/helpids.h
index 7c5955c..e966bc3 100644
--- a/sc/inc/helpids.h
+++ b/sc/inc/helpids.h
@@ -88,7 +88,6 @@
 #define HID_SC_FORM_ARGS                                        "SC_HID_SC_FORM_ARGS"
 #define HID_SCPAGE_SORT_FIELDS                                  "SC_HID_SCPAGE_SORT_FIELDS"
 #define HID_SCPAGE_SORT_OPTIONS                                 "SC_HID_SCPAGE_SORT_OPTIONS"
-#define HID_SCPAGE_SORTKEY_FIELDS                               "SC_HID_SCPAGE_SORTKEY_FIELDS"
 #define HID_SCPAGE_SUBT_OPTIONS                                 "SC_HID_SCPAGE_SUBT_OPTIONS"
 #define HID_SCPAGE_SUBT_GROUP                                   "SC_HID_SCPAGE_SUBT_GROUP"
 #define HID_SCPAGE_PROTECTION                                   "SC_HID_SCPAGE_PROTECTION"
@@ -487,6 +486,7 @@
 #define HID_FUNC_WENN                                           "SC_HID_FUNC_WENN"
 #define HID_FUNC_ODER                                           "SC_HID_FUNC_ODER"
 #define HID_FUNC_UND                                            "SC_HID_FUNC_UND"
+#define HID_FUNC_XOR                                            "SC_HID_FUNC_XOR"
 
 #define HID_FUNC_ABS                                            "SC_HID_FUNC_ABS"
 #define HID_FUNC_POTENZ                                         "SC_HID_FUNC_POTENZ"
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index d37e3f1..1db6294 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -3276,6 +3276,7 @@ void Test::testFunctionLists()
         "NOT",
         "OR",
         "TRUE",
+        "XOR",
         0
     };
 
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index c92ad0c..de577ca 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -393,6 +393,7 @@ void ScLessEqual();
 void ScGreaterEqual();
 void ScAnd();
 void ScOr();
+void ScXor();
 void ScNot();
 void ScNeg();
 void ScPercentSign();
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 34675c9..400b73c 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -1385,6 +1385,111 @@ void ScInterpreter::ScOr()
 }
 
 
+void ScInterpreter::ScXor()
+{
+    RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScXor" );
+
+    nFuncFmtType = NUMBERFORMAT_LOGICAL;
+    short nParamCount = GetByte();
+    if ( MustHaveParamCountMin( nParamCount, 1 ) )
+    {
+        bool bHaveValue = false;
+        short nRes = 0;
+        size_t nRefInList = 0;
+        while( nParamCount-- > 0)
+        {
+            if ( !nGlobalError )
+            {
+                switch ( GetStackType() )
+                {
+                    case svDouble :
+                        bHaveValue = true;
+                        if ( PopDouble() != 0.0 )
+                            nRes++;
+                    break;
+                    case svString :
+                        Pop();
+                        SetError( errNoValue );
+                    break;
+                    case svSingleRef :
+                    {
+                        ScAddress aAdr;
+                        PopSingleRef( aAdr );
+                        if ( !nGlobalError )
+                        {
+                            ScBaseCell* pCell = GetCell( aAdr );
+                            if ( HasCellValueData( pCell ) )
+                            {
+                                bHaveValue = true;
+                                if ( GetCellValue( aAdr, pCell ) != 0.0 )
+                                    nRes++;
+                            }
+                            // else: Xcl raises no error here
+                        }
+                    }
+                    break;
+                    case svDoubleRef:
+                    case svRefList:
+                    {
+                        ScRange aRange;
+                        PopDoubleRef( aRange, nParamCount, nRefInList);
+                        if ( !nGlobalError )
+                        {
+                            double fVal;
+                            sal_uInt16 nErr = 0;
+                            ScValueIterator aValIter( pDok, aRange );
+                            if ( aValIter.GetFirst( fVal, nErr ) )
+                            {
+                                bHaveValue = true;
+                                do
+                                {
+                                    if ( fVal != 0.0 )
+                                        nRes++;
+                                } while ( (nErr == 0) &&
+                                    aValIter.GetNext( fVal, nErr ) );
+                            }
+                            SetError( nErr );
+                        }
+                    }
+                    break;
+                    case svExternalSingleRef:
+                    case svExternalDoubleRef:
+                    case svMatrix:
+                    {
+                        bHaveValue = true;
+                        ScMatrixRef pMat = GetMatrix();
+                        if ( pMat )
+                        {
+                            bHaveValue = true;
+                            double fVal = pMat->Or();
+                            sal_uInt16 nErr = GetDoubleErrorValue( fVal );
+                            if ( nErr )
+                            {
+                                SetError( nErr );
+                            }
+                            else
+                                if (fVal != 0.0)
+                                    nRes++;
+                        }
+                        // else: GetMatrix did set errIllegalParameter
+                    }
+                    break;
+                    default:
+                        Pop();
+                        SetError( errIllegalParameter);
+                }
+            }
+            else
+                Pop();
+        }
+        if ( bHaveValue )
+            PushInt( nRes % 2 );
+        else
+            PushNoValue();
+    }
+}
+
+
 void ScInterpreter::ScNeg()
 {
     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScNeg" );
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 4a10201..aeadfe9 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -3810,6 +3810,7 @@ StackVar ScInterpreter::Interpret()
                 case ocGreaterEqual     : ScGreaterEqual();             break;
                 case ocAnd              : ScAnd();                      break;
                 case ocOr               : ScOr();                       break;
+                case ocXor              : ScXor();                      break;
                 case ocIntersect        : ScIntersect();                break;
                 case ocRange            : ScRangeFunc();                break;
                 case ocUnion            : ScUnionFunc();                break;
diff --git a/sc/source/core/tool/parclass.cxx b/sc/source/core/tool/parclass.cxx
index e8509a3..ee2cc4b 100644
--- a/sc/source/core/tool/parclass.cxx
+++ b/sc/source/core/tool/parclass.cxx
@@ -193,6 +193,7 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] =
     { ocVarP,            {{ Reference                                            }, true }},
     { ocVarPA,           {{ Reference                                            }, true }},
     { ocVLookup,         {{ Value, Reference, Value, Value                       }, false }},
+    { ocXor,             {{ Reference                                            }, true }},
     { ocZTest,           {{ Reference, Value, Value                              }, false }},
     // Excel doubts:
     // ocT: Excel says (and handles) Reference, error? This means no position
@@ -498,6 +499,7 @@ void ScParameterClassification::GenerateDocumentation()
                 {
                     case ocAnd:
                     case ocOr:
+                    case ocXor:
                         aToken.SetByte(1);  // (r1)AND(r2) --> AND( r1, ...)
                     break;
                     default:
diff --git a/sc/source/filter/oox/formulabase.cxx b/sc/source/filter/oox/formulabase.cxx
index b80dbfa..a5276eb 100644
--- a/sc/source/filter/oox/formulabase.cxx
+++ b/sc/source/filter/oox/formulabase.cxx
@@ -669,6 +669,7 @@ static const FunctionData saFuncTableBiff5[] =
     { 0,                        "DATESTRING",           352,    352,    1,  1,  V, { VR }, FUNCFLAG_IMPORTONLY },   // not supported in Calc, missing in OOXML spec
     { 0,                        "NUMBERSTRING",         353,    353,    2,  2,  V, { VR }, FUNCFLAG_IMPORTONLY },   // not supported in Calc, missing in OOXML spec
     { "ROMAN",                  "ROMAN",                354,    354,    1,  2,  V, { VR }, 0 },
+    { "XOR",                    "XOR",                  355,    355,    1,  MX, V, { RX }, 0 },
 
     // *** EuroTool add-in ***
 
@@ -762,7 +763,6 @@ static const FunctionData saFuncTableOdf[] =
     { "SKEWP",                  0,                      NOID,   NOID,   1,  MX, V, { RX }, FUNCFLAG_MACROCALLODF },
     { "UNICHAR",                0,                      NOID,   NOID,   1,  1,  V, { VR }, FUNCFLAG_MACROCALLODF },
     { "UNICODE",                0,                      NOID,   NOID,   1,  1,  V, { VR }, FUNCFLAG_MACROCALLODF },
-    { "XOR",                    0,                      NOID,   NOID,   1,  MX, V, { RX }, FUNCFLAG_MACROCALLODF }
 };
 
 // ----------------------------------------------------------------------------
diff --git a/sc/source/ui/src/scfuncs.src b/sc/source/ui/src/scfuncs.src
index 53780de..60f8fca 100644
--- a/sc/source/ui/src/scfuncs.src
+++ b/sc/source/ui/src/scfuncs.src
@@ -2682,6 +2682,30 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS1
             Text [ en-US ] = "Logical value 1, logical value 2,... are 1 to 30 conditions to be tested and which return either TRUE or FALSE." ;
         };
     };
+     // -=*# Resource for function XOR (EXKLUSIV ODER) #*=-
+    Resource SC_OPCODE_XOR
+    {
+        String 1 // Description
+        {
+            Text [ en-US ] = "Returns TRUE if one argument is TRUE, but not both." ;
+        };
+        ExtraData =
+        {
+            0;
+            ID_FUNCTION_GRP_LOGIC;
+            U2S( HID_FUNC_XOR );
+            VAR_ARGS;  0;
+            0;
+        };
+        String 2 // Name of Parameter 1
+        {
+            Text [ en-US ] = "Logical value " ;
+        };
+        String 3 // Description of Parameter 1
+        {
+            Text [ en-US ] = "Logical value 1, logical value 2, ... are 1 to 30 conditions to be tested and which returns either TRUE or FALSE." ;
+        };
+    };
      // -=*# Resource for function UND #*=-
     Resource SC_OPCODE_AND
     {
diff --git a/sc/source/ui/vba/vbawsfunction.cxx b/sc/source/ui/vba/vbawsfunction.cxx
index 0692afb..3a236b3 100644
--- a/sc/source/ui/vba/vbawsfunction.cxx
+++ b/sc/source/ui/vba/vbawsfunction.cxx
@@ -201,7 +201,7 @@ ScVbaWSFunction::invoke(const rtl::OUString& FunctionName, const uno::Sequence<
     if( (eOpCode == ocIsEmpty) || (eOpCode == ocIsString) || (eOpCode == ocIsNonString) || (eOpCode == ocIsLogical) ||
         (eOpCode == ocIsRef) || (eOpCode == ocIsValue) || (eOpCode == ocIsFormula) || (eOpCode == ocIsNA) ||
         (eOpCode == ocIsErr) || (eOpCode == ocIsError) || (eOpCode == ocIsEven) || (eOpCode == ocIsOdd) ||
-        (eOpCode == ocAnd) || (eOpCode == ocOr) || (eOpCode == ocNot) || (eOpCode == ocTrue) || (eOpCode == ocFalse) )
+        (eOpCode == ocAnd) || (eOpCode == ocOr) || (eOpCode == ocXor) || (eOpCode == ocNot) || (eOpCode == ocTrue) || (eOpCode == ocFalse) )
     {
         if( aRet.has< AnySeqSeq >() )
         {
diff --git a/sc/util/hidother.src b/sc/util/hidother.src
index 85d36f9..6a56a81 100644
--- a/sc/util/hidother.src
+++ b/sc/util/hidother.src
@@ -160,6 +160,7 @@ hidspecial HID_FUNC_WAHR         { HelpID = HID_FUNC_WAHR; };
 hidspecial HID_FUNC_WENN         { HelpID = HID_FUNC_WENN; };
 hidspecial HID_FUNC_ODER         { HelpID = HID_FUNC_ODER; };
 hidspecial HID_FUNC_UND      { HelpID = HID_FUNC_UND; };
+hidspecial HID_FUNC_XOR      { HelpID = HID_FUNC_XOR; };
 hidspecial HID_FUNC_ABS      { HelpID = HID_FUNC_ABS; };
 hidspecial HID_FUNC_POTENZ       { HelpID = HID_FUNC_POTENZ; };
 hidspecial HID_FUNC_ANZAHLLEEREZELLEN        { HelpID = HID_FUNC_ANZAHLLEEREZELLEN; };
-- 
1.7.7

_______________________________________________
LibreOffice mailing list
LibreOffice@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/libreoffice

Reply via email to