[ooo-build-commit] Branch 'ooo/master' - 2 commits - chart2/source sc/inc sc/source

Jan Holesovsky kendy at kemper.freedesktop.org
Tue Jul 28 17:15:13 PDT 2009


 chart2/source/inc/ChartTypeHelper.hxx              |    2 
 chart2/source/inc/CommonFunctors.hxx               |    5 
 chart2/source/tools/ChartTypeHelper.cxx            |   16 
 chart2/source/tools/DiagramHelper.cxx              |   18 
 chart2/source/tools/TitleHelper.cxx                |   36 +
 chart2/source/view/charttypes/Splines.cxx          |  344 +++++++++-------
 chart2/source/view/diagram/VDiagram.cxx            |   10 
 chart2/source/view/inc/ShapeFactory.hxx            |    2 
 chart2/source/view/inc/Stripe.hxx                  |    2 
 chart2/source/view/main/PlottingPositionHelper.cxx |   34 -
 chart2/source/view/main/ShapeFactory.cxx           |    5 
 chart2/source/view/main/Stripe.cxx                 |   47 +-
 chart2/source/view/main/VDataSeries.cxx            |   26 -
 sc/inc/address.hxx                                 |    6 
 sc/inc/cell.hxx                                    |    9 
 sc/inc/compiler.hxx                                |    2 
 sc/inc/datauno.hxx                                 |   11 
 sc/inc/externalrefmgr.hxx                          |   37 +
 sc/inc/global.hxx                                  |    8 
 sc/inc/pch/precompiled_sc.hxx                      |    3 
 sc/inc/progress.hxx                                |   11 
 sc/inc/refdata.hxx                                 |   21 +
 sc/inc/table.hxx                                   |   35 +
 sc/source/core/data/cell.cxx                       |    2 
 sc/source/core/data/cell2.cxx                      |  268 ++++++++++++
 sc/source/core/data/documen4.cxx                   |   11 
 sc/source/core/data/document.cxx                   |    2 
 sc/source/core/data/table1.cxx                     |   10 
 sc/source/core/data/table2.cxx                     |    4 
 sc/source/core/data/table3.cxx                     |  105 ++++-
 sc/source/core/inc/interpre.hxx                    |   26 +
 sc/source/core/tool/address.cxx                    |   53 +-
 sc/source/core/tool/compiler.cxx                   |  134 ++++--
 sc/source/core/tool/interpr1.cxx                   |  435 ++++++++++++++++++---
 sc/source/core/tool/interpr4.cxx                   |    9 
 sc/source/core/tool/progress.cxx                   |    2 
 sc/source/core/tool/reftokenhelper.cxx             |   55 ++
 sc/source/filter/excel/excimp8.cxx                 |   44 +-
 sc/source/filter/excel/excrecds.cxx                |   32 +
 sc/source/filter/xml/XMLExportDatabaseRanges.cxx   |   50 +-
 sc/source/filter/xml/XMLExportDatabaseRanges.hxx   |   12 
 sc/source/filter/xml/xmldrani.cxx                  |    5 
 sc/source/filter/xml/xmldrani.hxx                  |    6 
 sc/source/filter/xml/xmlfilti.cxx                  |   44 +-
 sc/source/filter/xml/xmlfilti.hxx                  |    9 
 sc/source/ui/app/inputhdl.cxx                      |    5 
 sc/source/ui/docshell/docfunc.cxx                  |    6 
 sc/source/ui/docshell/externalrefmgr.cxx           |   96 +++-
 sc/source/ui/inc/undoblk.hxx                       |   30 +
 sc/source/ui/inc/viewfunc.hxx                      |    1 
 sc/source/ui/src/filter.src                        |   64 ++-
 sc/source/ui/undo/undoblk3.cxx                     |   93 ++++
 sc/source/ui/unoobj/cellsuno.cxx                   |   10 
 sc/source/ui/unoobj/datauno.cxx                    |  158 +++++++
 sc/source/ui/vba/vbarange.cxx                      |   52 +-
 sc/source/ui/view/cellsh1.cxx                      |   27 -
 sc/source/ui/view/viewfun4.cxx                     |  128 ++++++
 sc/source/ui/view/viewfunc.cxx                     |   18 
 58 files changed, 2181 insertions(+), 515 deletions(-)

New commits:
commit 1a1709cea4cc33e45b48243bc81569818634c421
Author: Jens-Heiner Rechtien <hr at openoffice.org>
Date:   Tue Jul 28 10:25:31 2009 +0000

    CWS-TOOLING: integrate CWS chart39
    2009-06-30 16:55:46 +0200 iha  r273522 : #i103209# im-/export attribute xlink:href at chart:chart element + some cleanup in naming
    2009-06-30 16:45:59 +0200 iha  r273521 : #i102701# apply patch for P1 issue on dev300m50 to be able to save again
    2009-06-30 16:32:32 +0200 iha  r273520 : #i103209# im-/export attribute xlink:href at chart:chart element + some cleanup in naming
    2009-06-29 10:04:34 +0200 iha  r273454 : #i103147# ODF, workaround broken files with a missing table:cell-range-address at the plot-area
    2009-06-26 19:31:16 +0200 iha  r273437 : #i103147# ODF, workaround broken files with a missing table:cell-range-address at the plot-area
    2009-06-25 10:36:28 +0200 iha  r273367 : #i101968# text values in data range cause incorrect x values
    2009-06-24 17:34:18 +0200 iha  r273357 : #i102428# x values are wrong in xy-scatter-chart with own data table if empty cells are contained in x values
    2009-06-24 10:16:25 +0200 iha  r273317 : #i99915# wrong matrix translation causes broken chart display for small values
    2009-06-19 17:20:06 +0200 iha  r273174 : #i78025# charts own borders are not completely visible
    2009-06-19 17:18:41 +0200 iha  r273172 : #i102950# don't paint additional borders for charts
    2009-06-11 16:27:54 +0200 iha  r272884 : CWS-TOOLING: rebase CWS chart39 to trunk at 272827 (milestone: DEV300:m50)
    2009-06-09 17:50:10 +0200 iha  r272790 : #i97222# when converting a chart via API to 3D categories get lost and for line,area&xy the stacking mode is wrong
    2009-06-09 16:00:27 +0200 iha  r272775 : #i98319# data point properties get lost while copying charts from calc to impress
    2009-06-09 10:26:51 +0200 iha  r272755 : #i98392# correct orienation of gradient fillings on 3D walls
    2009-05-29 10:35:16 +0200 iha  r272436 : #i100529# Plot missing values - leave gap fails for smoothed lines
    2009-05-04 18:20:31 +0200 iha  r271478 : #i99841# Title with Vertically stacked attribute is wrong after editing
    2009-05-04 18:03:01 +0200 iha  r271477 : #i101050# avoid a corner in closed lines, which are smoothed by spline
    2009-05-04 16:45:18 +0200 iha  r271472 : #i101050# avoid crash in case the normals sequence has less points than the polygon

diff --git a/chart2/source/inc/ChartTypeHelper.hxx b/chart2/source/inc/ChartTypeHelper.hxx
index 6541aee..fb6beef 100644
--- a/chart2/source/inc/ChartTypeHelper.hxx
+++ b/chart2/source/inc/ChartTypeHelper.hxx
@@ -95,6 +95,8 @@ public:
 
     static bool shouldLabelNumberFormatKeyBeDetectedFromYAxis( const ::com::sun::star::uno::Reference<
         ::com::sun::star::chart2::XChartType >& xChartType );
+
+    static bool isSupportingOnlyDeepStackingFor3D( const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartType >& xChartType );
 };
 
 //.............................................................................
diff --git a/chart2/source/inc/CommonFunctors.hxx b/chart2/source/inc/CommonFunctors.hxx
index 4671767..4846caa 100644
--- a/chart2/source/inc/CommonFunctors.hxx
+++ b/chart2/source/inc/CommonFunctors.hxx
@@ -100,8 +100,11 @@ struct OOO_DLLPUBLIC_CHARTTOOLS AnyToString : public ::std::unary_function< ::co
         ::com::sun::star::uno::TypeClass eClass( rAny.getValueType().getTypeClass() );
         if( eClass == ::com::sun::star::uno::TypeClass_DOUBLE )
         {
+            const double* pDouble = reinterpret_cast< const double * >( rAny.getValue() );
+            if( ::rtl::math::isNan(*pDouble) )
+                return ::rtl::OUString();
             return ::rtl::math::doubleToUString(
-                * reinterpret_cast< const double * >( rAny.getValue() ),
+                * pDouble,
                 rtl_math_StringFormat_Automatic,
                 -1, // use maximum decimal places available
                 sal_Char( '.' ), // decimal separator
diff --git a/chart2/source/tools/ChartTypeHelper.cxx b/chart2/source/tools/ChartTypeHelper.cxx
index d371168..452adbd 100644
--- a/chart2/source/tools/ChartTypeHelper.cxx
+++ b/chart2/source/tools/ChartTypeHelper.cxx
@@ -641,6 +641,22 @@ bool ChartTypeHelper::shouldLabelNumberFormatKeyBeDetectedFromYAxis( const uno::
     return bRet;
 }
 
+bool ChartTypeHelper::isSupportingOnlyDeepStackingFor3D( const uno::Reference< XChartType >& xChartType )
+{
+    bool bRet = false;
+    if( !xChartType.is() )
+        return bRet;
+
+    rtl::OUString aChartTypeName = xChartType->getChartType();
+    if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_LINE) ||
+        aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER) ||
+        aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_AREA) )
+    {
+        bRet = true;
+    }
+    return bRet;
+}
+
 //.............................................................................
 } //namespace chart
 //.............................................................................
diff --git a/chart2/source/tools/DiagramHelper.cxx b/chart2/source/tools/DiagramHelper.cxx
index cc6ec1b..4d3578a 100644
--- a/chart2/source/tools/DiagramHelper.cxx
+++ b/chart2/source/tools/DiagramHelper.cxx
@@ -503,8 +503,12 @@ void DiagramHelper::setDimension(
 
     try
     {
-        //change all coordinate systems:
+        bool rbFound = false;
+        bool rbAmbiguous = true;
+        StackMode eStackMode = DiagramHelper::getStackMode( xDiagram, rbFound, rbAmbiguous );
+        bool bIsSupportingOnlyDeepStackingFor3D=false;
 
+        //change all coordinate systems:
         Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY_THROW );
         Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
         for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
@@ -520,6 +524,7 @@ void DiagramHelper::setDimension(
             for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT )
             {
                 Reference< XChartType > xChartType( aChartTypeList[nT], uno::UNO_QUERY );
+                bIsSupportingOnlyDeepStackingFor3D = ChartTypeHelper::isSupportingOnlyDeepStackingFor3D( xChartType );
                 if(!xNewCooSys.is())
                 {
                     xNewCooSys = xChartType->createCoordinateSystem( nNewDimensionCount );
@@ -533,6 +538,12 @@ void DiagramHelper::setDimension(
             // replace the old coordinate system at all places where it was used
             DiagramHelper::replaceCoordinateSystem( xDiagram, xOldCooSys, xNewCooSys );
         }
+
+        //correct stack mode if necessary
+        if( nNewDimensionCount==3 && eStackMode != StackMode_Z_STACKED && bIsSupportingOnlyDeepStackingFor3D )
+            DiagramHelper::setStackMode( xDiagram, StackMode_Z_STACKED );
+        else if( nNewDimensionCount==2 && eStackMode == StackMode_Z_STACKED )
+            DiagramHelper::setStackMode( xDiagram, StackMode_NONE );
     }
     catch( uno::Exception & ex )
     {
@@ -556,6 +567,8 @@ void DiagramHelper::replaceCoordinateSystem(
     {
         try
         {
+            Reference< chart2::data::XLabeledDataSequence > xCategories = DiagramHelper::getCategoriesFromDiagram( xDiagram );
+
             // move chart types of xCooSysToReplace to xReplacement
             Reference< XChartTypeContainer > xCTCntCooSys( xCooSysToReplace, uno::UNO_QUERY_THROW );
             Reference< XChartTypeContainer > xCTCntReplacement( xReplacement, uno::UNO_QUERY_THROW );
@@ -563,6 +576,9 @@ void DiagramHelper::replaceCoordinateSystem(
 
             xCont->removeCoordinateSystem( xCooSysToReplace );
             xCont->addCoordinateSystem( xReplacement );
+
+            if( xCategories.is() )
+                DiagramHelper::setCategoriesToDiagram( xCategories, xDiagram );
         }
         catch( uno::Exception & ex )
         {
diff --git a/chart2/source/tools/TitleHelper.cxx b/chart2/source/tools/TitleHelper.cxx
index 2f7ad4c..bba2cd8 100644
--- a/chart2/source/tools/TitleHelper.cxx
+++ b/chart2/source/tools/TitleHelper.cxx
@@ -36,6 +36,7 @@
 #include "AxisHelper.hxx"
 #include "DiagramHelper.hxx"
 #include <com/sun/star/chart2/XChartDocument.hpp>
+#include <rtl/ustrbuf.hxx>
 
 //.............................................................................
 namespace chart
@@ -269,13 +270,44 @@ void TitleHelper::setCompleteString( const rtl::OUString& rNewText
     if(!xTitle.is())
         return;
 
+    rtl::OUString aNewText = rNewText;
+
+    bool bStacked = false;
+    uno::Reference< beans::XPropertySet > xTitleProperties( xTitle, uno::UNO_QUERY );
+    if( xTitleProperties.is() )
+        xTitleProperties->getPropertyValue( C2U( "StackCharacters" ) ) >>= bStacked;
+
+    if( bStacked )
+    {
+        //#i99841# remove linebreaks that were added for vertical stacking
+        rtl::OUStringBuffer aUnstackedStr;
+        rtl::OUStringBuffer aSource(rNewText);
+
+        bool bBreakIgnored = false;
+        sal_Int32 nLen = rNewText.getLength();       
+        for( sal_Int32 nPos = 0; nPos < nLen; ++nPos )
+        {
+            sal_Unicode aChar = aSource.charAt( nPos );
+            if( aChar != '\n' )
+            {
+                aUnstackedStr.append( aChar );
+                bBreakIgnored = false;
+            }
+            else if( aChar == '\n' && bBreakIgnored )
+                aUnstackedStr.append( aChar );
+            else
+                bBreakIgnored = true;
+        }
+        aNewText = aUnstackedStr.makeStringAndClear();
+    }
+
     uno::Sequence< uno::Reference< XFormattedString > > aNewStringList(1);
 
     uno::Sequence< uno::Reference< XFormattedString > >  aOldStringList = xTitle->getText();
     if( aOldStringList.getLength() )
     {
         aNewStringList[0].set( aOldStringList[0] );
-        aNewStringList[0]->setString( rNewText );
+        aNewStringList[0]->setString( aNewText );
     }
     else
     {
@@ -286,7 +318,7 @@ void TitleHelper::setCompleteString( const rtl::OUString& rNewText
 
         if(xFormattedString.is())
         {
-            xFormattedString->setString( rNewText );
+            xFormattedString->setString( aNewText );
             aNewStringList[0].set( xFormattedString );
             if( pDefaultCharHeight != 0 )
             {
diff --git a/chart2/source/view/charttypes/Splines.cxx b/chart2/source/view/charttypes/Splines.cxx
index 44dbdd6..bc9c0c4 100644
--- a/chart2/source/view/charttypes/Splines.cxx
+++ b/chart2/source/view/charttypes/Splines.cxx
@@ -318,108 +318,133 @@ void SplineCalculater::CalculateCubicSplines(
     , sal_Int32 nGranularity )
 {
     DBG_ASSERT( nGranularity > 0, "Granularity is invalid" );
+
     rResult.SequenceX.realloc(0);
     rResult.SequenceY.realloc(0);
     rResult.SequenceZ.realloc(0);
 
-    if( !rInput.SequenceX.getLength() )
+    sal_Int32 nOuterCount = rInput.SequenceX.getLength();
+    if( !nOuterCount )
         return;
-    if( rInput.SequenceX[0].getLength() <= 1 )
-        return; //we need at least two points
-
-    sal_Int32 nMaxIndexPoints = rInput.SequenceX[0].getLength()-1; // is >=1
-    const double* pOldX = rInput.SequenceX[0].getConstArray();
-    const double* pOldY = rInput.SequenceY[0].getConstArray();
-    const double* pOldZ = rInput.SequenceZ[0].getConstArray();
-
-    // #i13699# The curve gets a parameter and then for each coordinate a
-    // separate spline will be calculated using the parameter as first argument
-    // and the point coordinate as second argument. Therefore the points need
-    // not to be sorted in its x-coordinates. The parameter is sorted by
-    // construction.
-
-    ::std::vector < double > aParameter(nMaxIndexPoints+1);
-    aParameter[0]=0.0;
-    for( sal_Int32 nIndex=1; nIndex<=nMaxIndexPoints; nIndex++ )
-    {
-        // The euclidian distance leads to curve loops for functions having single extreme points
-//         aParameter[nIndex]=aParameter[nIndex-1]+
-//             sqrt( (pOldX[nIndex]-pOldX[nIndex-1])*(pOldX[nIndex]-pOldX[nIndex-1])+
-//                   (pOldY[nIndex]-pOldY[nIndex-1])*(pOldY[nIndex]-pOldY[nIndex-1])+
-//                   (pOldZ[nIndex]-pOldZ[nIndex-1])*(pOldZ[nIndex]-pOldZ[nIndex-1]));
-
-        // use increment of 1 instead
-        aParameter[nIndex]=aParameter[nIndex-1]+1;
-    }
-    // Split the calculation to X, Y and Z coordinate
-    tPointVecType aInputX;
-    aInputX.resize(nMaxIndexPoints+1);
-    tPointVecType aInputY;
-    aInputY.resize(nMaxIndexPoints+1);
-    tPointVecType aInputZ;
-    aInputZ.resize(nMaxIndexPoints+1);
-    for (sal_Int32 nN=0;nN<=nMaxIndexPoints; nN++ )
-    {
-      aInputX[ nN ].first=aParameter[nN];
-      aInputX[ nN ].second=pOldX[ nN ];
-      aInputY[ nN ].first=aParameter[nN];
-      aInputY[ nN ].second=pOldY[ nN ];
-      aInputZ[ nN ].first=aParameter[nN];
-      aInputZ[ nN ].second=pOldZ[ nN ];
-    }
 
-    // generate a spline for each coordinate. It holds the complete
-    // information to calculate each point of the curve
-
-    // generate the kind "natural spline"
-    double fInfty;
-    ::rtl::math::setInf( &fInfty, sal_False );
-    lcl_SplineCalculation aSplineX( aInputX, fInfty, fInfty );
-    lcl_SplineCalculation aSplineY( aInputY, fInfty, fInfty );
-    lcl_SplineCalculation aSplineZ( aInputZ, fInfty, fInfty );
-
-    // fill result polygon with calculated values
-    rResult.SequenceX.realloc(1);
-    rResult.SequenceY.realloc(1);
-    rResult.SequenceZ.realloc(1);
-    rResult.SequenceX[0].realloc( nMaxIndexPoints*nGranularity + 1);
-    rResult.SequenceY[0].realloc( nMaxIndexPoints*nGranularity + 1);
-    rResult.SequenceZ[0].realloc( nMaxIndexPoints*nGranularity + 1);
-
-    double* pNewX = rResult.SequenceX[0].getArray();
-    double* pNewY = rResult.SequenceY[0].getArray();
-    double* pNewZ = rResult.SequenceZ[0].getArray();
-
-    sal_Int32 nNewPointIndex = 0; // Index in result points
-    // needed for inner loop
-    double    fInc;   // step for intermediate points
-    sal_Int32 nj;     // for loop
-    double    fParam; // a intermediate parameter value
-
-    for( sal_Int32 ni = 0; ni < nMaxIndexPoints; ni++ )
-    {
-        // given point is surely a curve point
-        pNewX[nNewPointIndex] = pOldX[ni];
-        pNewY[nNewPointIndex] = pOldY[ni];
-        pNewZ[nNewPointIndex] = pOldZ[ni];
-        nNewPointIndex++;
-
-        // calculate intermediate points
-        fInc = ( aParameter[ ni+1 ] - aParameter[ni] ) / static_cast< double >( nGranularity );
-        for(nj = 1; nj < nGranularity; nj++)
+    rResult.SequenceX.realloc(nOuterCount);
+    rResult.SequenceY.realloc(nOuterCount);
+    rResult.SequenceZ.realloc(nOuterCount);
+
+    for( sal_Int32 nOuter = 0; nOuter < nOuterCount; ++nOuter )
+    {
+        if( rInput.SequenceX[nOuter].getLength() <= 1 )
+            continue; //we need at least two points
+
+        sal_Int32 nMaxIndexPoints = rInput.SequenceX[nOuter].getLength()-1; // is >=1
+        const double* pOldX = rInput.SequenceX[nOuter].getConstArray();
+        const double* pOldY = rInput.SequenceY[nOuter].getConstArray();
+        const double* pOldZ = rInput.SequenceZ[nOuter].getConstArray();
+
+        // #i13699# The curve gets a parameter and then for each coordinate a
+        // separate spline will be calculated using the parameter as first argument
+        // and the point coordinate as second argument. Therefore the points need
+        // not to be sorted in its x-coordinates. The parameter is sorted by
+        // construction.
+
+        ::std::vector < double > aParameter(nMaxIndexPoints+1);
+        aParameter[0]=0.0;
+        for( sal_Int32 nIndex=1; nIndex<=nMaxIndexPoints; nIndex++ )
         {
-            fParam = aParameter[ni] + ( fInc * static_cast< double >( nj ) );
+            // The euclidian distance leads to curve loops for functions having single extreme points
+            //aParameter[nIndex]=aParameter[nIndex-1]+
+            //sqrt( (pOldX[nIndex]-pOldX[nIndex-1])*(pOldX[nIndex]-pOldX[nIndex-1])+
+            //(pOldY[nIndex]-pOldY[nIndex-1])*(pOldY[nIndex]-pOldY[nIndex-1])+
+            //(pOldZ[nIndex]-pOldZ[nIndex-1])*(pOldZ[nIndex]-pOldZ[nIndex-1]));
+
+            // use increment of 1 instead
+            aParameter[nIndex]=aParameter[nIndex-1]+1;
+        }
+        // Split the calculation to X, Y and Z coordinate
+        tPointVecType aInputX;
+        aInputX.resize(nMaxIndexPoints+1);
+        tPointVecType aInputY;
+        aInputY.resize(nMaxIndexPoints+1);
+        tPointVecType aInputZ;
+        aInputZ.resize(nMaxIndexPoints+1);
+        for (sal_Int32 nN=0;nN<=nMaxIndexPoints; nN++ )
+        {
+          aInputX[ nN ].first=aParameter[nN];
+          aInputX[ nN ].second=pOldX[ nN ];
+          aInputY[ nN ].first=aParameter[nN];
+          aInputY[ nN ].second=pOldY[ nN ];
+          aInputZ[ nN ].first=aParameter[nN];
+          aInputZ[ nN ].second=pOldZ[ nN ];
+        }
 
-            pNewX[nNewPointIndex]=aSplineX.GetInterpolatedValue( fParam );
-            pNewY[nNewPointIndex]=aSplineY.GetInterpolatedValue( fParam );
-            pNewZ[nNewPointIndex]=aSplineZ.GetInterpolatedValue( fParam );
+        // generate a spline for each coordinate. It holds the complete
+        // information to calculate each point of the curve
+        double fXDerivation;
+        double fYDerivation;
+        double fZDerivation;
+        if( pOldX[ 0 ] == pOldX[nMaxIndexPoints] &&
+            pOldY[ 0 ] == pOldY[nMaxIndexPoints] &&
+            pOldZ[ 0 ] == pOldZ[nMaxIndexPoints] )
+        {
+            // #i101050# avoid a corner in closed lines, which are smoothed by spline
+            // This derivation are special for parameter of kind 0,1,2,3... If you
+            // change generating parameters (see above), then adapt derivations too.)
+            fXDerivation = 0.5 * (pOldX[1]-pOldX[nMaxIndexPoints-1]);
+            fYDerivation = 0.5 * (pOldY[1]-pOldY[nMaxIndexPoints-1]);
+            fZDerivation = 0.5 * (pOldZ[1]-pOldZ[nMaxIndexPoints-1]);
+        }
+        else // generate the kind "natural spline"
+        {
+            double fInfty;
+            ::rtl::math::setInf( &fInfty, sal_False );
+            fXDerivation = fInfty;
+            fYDerivation = fInfty;
+            fZDerivation = fInfty;
+        }
+        lcl_SplineCalculation aSplineX( aInputX, fXDerivation, fXDerivation );
+        lcl_SplineCalculation aSplineY( aInputY, fYDerivation, fYDerivation );
+        lcl_SplineCalculation aSplineZ( aInputZ, fZDerivation, fZDerivation );
+
+        // fill result polygon with calculated values
+        rResult.SequenceX[nOuter].realloc( nMaxIndexPoints*nGranularity + 1);
+        rResult.SequenceY[nOuter].realloc( nMaxIndexPoints*nGranularity + 1);
+        rResult.SequenceZ[nOuter].realloc( nMaxIndexPoints*nGranularity + 1);
+
+        double* pNewX = rResult.SequenceX[nOuter].getArray();
+        double* pNewY = rResult.SequenceY[nOuter].getArray();
+        double* pNewZ = rResult.SequenceZ[nOuter].getArray();
+
+        sal_Int32 nNewPointIndex = 0; // Index in result points
+        // needed for inner loop
+        double    fInc;   // step for intermediate points
+        sal_Int32 nj;     // for loop
+        double    fParam; // a intermediate parameter value
+
+        for( sal_Int32 ni = 0; ni < nMaxIndexPoints; ni++ )
+        {
+            // given point is surely a curve point
+            pNewX[nNewPointIndex] = pOldX[ni];
+            pNewY[nNewPointIndex] = pOldY[ni];
+            pNewZ[nNewPointIndex] = pOldZ[ni];
             nNewPointIndex++;
+
+            // calculate intermediate points
+            fInc = ( aParameter[ ni+1 ] - aParameter[ni] ) / static_cast< double >( nGranularity );
+            for(nj = 1; nj < nGranularity; nj++)
+            {
+                fParam = aParameter[ni] + ( fInc * static_cast< double >( nj ) );
+
+                pNewX[nNewPointIndex]=aSplineX.GetInterpolatedValue( fParam );
+                pNewY[nNewPointIndex]=aSplineY.GetInterpolatedValue( fParam );
+                pNewZ[nNewPointIndex]=aSplineZ.GetInterpolatedValue( fParam );
+                nNewPointIndex++;
+            }
         }
+        // add last point
+        pNewX[nNewPointIndex] = pOldX[nMaxIndexPoints];
+        pNewY[nNewPointIndex] = pOldY[nMaxIndexPoints];
+        pNewZ[nNewPointIndex] = pOldZ[nMaxIndexPoints];
     }
-    // add last point
-    pNewX[nNewPointIndex] = pOldX[nMaxIndexPoints];
-    pNewY[nNewPointIndex] = pOldY[nMaxIndexPoints];
-    pNewZ[nNewPointIndex] = pOldZ[nMaxIndexPoints];
 }
 
 void SplineCalculater::CalculateBSplines(
@@ -436,80 +461,85 @@ void SplineCalculater::CalculateBSplines(
     rResult.SequenceY.realloc(0);
     rResult.SequenceZ.realloc(0);
     
-    if( !rInput.SequenceX.getLength() )
+    sal_Int32 nOuterCount = rInput.SequenceX.getLength();
+    if( !nOuterCount )
         return; // no input
 
-    if( rInput.SequenceX[0].getLength() <= 1 )
-        return; // need at least 2 control points
-        
-    sal_Int32 n = rInput.SequenceX[0].getLength()-1; // maximum index of control points
-    
-    double fCurveparam =0.0; // parameter for the curve
-    // 0<= fCurveparam < fMaxCurveparam
-    double fMaxCurveparam = 2.0+ n - k;
-    if (fMaxCurveparam <= 0.0)
-        return; // not enough control points for desired spline order
-    
-    if (nGranularity < 1)
-        return; //need at least 1 line for each part beween the control points
+    rResult.SequenceX.realloc(nOuterCount);
+    rResult.SequenceY.realloc(nOuterCount);
+    rResult.SequenceZ.realloc(nOuterCount);
 
-    const double* pOldX = rInput.SequenceX[0].getConstArray();
-    const double* pOldY = rInput.SequenceY[0].getConstArray();
-    const double* pOldZ = rInput.SequenceZ[0].getConstArray();
+    for( sal_Int32 nOuter = 0; nOuter < nOuterCount; ++nOuter )
+    {
+        if( rInput.SequenceX[nOuter].getLength() <= 1 )
+            continue; // need at least 2 control points
         
-    // keep this amount of steps to go well with old version
-    sal_Int32 nNewSectorCount = nGranularity * n;
-    double fCurveStep = fMaxCurveparam/static_cast< double >(nNewSectorCount);
-
-    double *b       = new double [n + k + 1]; // values of blending functions
-
-    const double* t = createTVector(n, k); // knot vector
-
-    rResult.SequenceX.realloc(1);
-    rResult.SequenceY.realloc(1);
-    rResult.SequenceZ.realloc(1);
-    rResult.SequenceX[0].realloc(nNewSectorCount+1);
-    rResult.SequenceY[0].realloc(nNewSectorCount+1);
-    rResult.SequenceZ[0].realloc(nNewSectorCount+1);
-    double* pNewX = rResult.SequenceX[0].getArray();
-    double* pNewY = rResult.SequenceY[0].getArray();
-    double* pNewZ = rResult.SequenceZ[0].getArray();
-    
-    // variables needed inside loop, when calculating one point of output
-    sal_Int32 nPointIndex =0; //index of given contol points
-    double fX=0.0;
-    double fY=0.0;
-    double fZ=0.0; //coordinates of a new BSpline point
-
-    for(sal_Int32 nNewSector=0; nNewSector<nNewSectorCount; nNewSector++)
-    { // in first looping fCurveparam has value 0.0
+        sal_Int32 n = rInput.SequenceX[nOuter].getLength()-1; // maximum index of control points
         
-        // Calculate the values of the blending functions for actual curve parameter
-        BVector(fCurveparam, n, k, b, t);
+        double fCurveparam =0.0; // parameter for the curve
+        // 0<= fCurveparam < fMaxCurveparam
+        double fMaxCurveparam = 2.0+ n - k;
+        if (fMaxCurveparam <= 0.0)
+            return; // not enough control points for desired spline order
         
-        // output point(fCurveparam) = sum over {input point * value of blending function}
-        fX = 0.0;
-        fY = 0.0;
-        fZ = 0.0;
-        for (nPointIndex=0;nPointIndex<=n;nPointIndex++)
-        {
-            fX +=pOldX[nPointIndex]*b[nPointIndex];
-            fY +=pOldY[nPointIndex]*b[nPointIndex];
-            fZ +=pOldZ[nPointIndex]*b[nPointIndex];
-        }
-        pNewX[nNewSector] = fX;
-        pNewY[nNewSector] = fY;
-        pNewZ[nNewSector] = fZ;
+        if (nGranularity < 1)
+            return; //need at least 1 line for each part beween the control points
+
+        const double* pOldX = rInput.SequenceX[nOuter].getConstArray();
+        const double* pOldY = rInput.SequenceY[nOuter].getConstArray();
+        const double* pOldZ = rInput.SequenceZ[nOuter].getConstArray();
+            
+        // keep this amount of steps to go well with old version
+        sal_Int32 nNewSectorCount = nGranularity * n;
+        double fCurveStep = fMaxCurveparam/static_cast< double >(nNewSectorCount);
+
+        double *b       = new double [n + k + 1]; // values of blending functions
+
+        const double* t = createTVector(n, k); // knot vector
+
+        rResult.SequenceX[nOuter].realloc(nNewSectorCount+1);
+        rResult.SequenceY[nOuter].realloc(nNewSectorCount+1);
+        rResult.SequenceZ[nOuter].realloc(nNewSectorCount+1);
+        double* pNewX = rResult.SequenceX[nOuter].getArray();
+        double* pNewY = rResult.SequenceY[nOuter].getArray();
+        double* pNewZ = rResult.SequenceZ[nOuter].getArray();
         
-        fCurveparam += fCurveStep; //for next looping
-    }
-    // add last control point to BSpline curve
-    pNewX[nNewSectorCount] = pOldX[n];
-    pNewY[nNewSectorCount] = pOldY[n];
-    pNewZ[nNewSectorCount] = pOldZ[n];
+        // variables needed inside loop, when calculating one point of output
+        sal_Int32 nPointIndex =0; //index of given contol points
+        double fX=0.0;
+        double fY=0.0;
+        double fZ=0.0; //coordinates of a new BSpline point
+
+        for(sal_Int32 nNewSector=0; nNewSector<nNewSectorCount; nNewSector++)
+        { // in first looping fCurveparam has value 0.0
+            
+            // Calculate the values of the blending functions for actual curve parameter
+            BVector(fCurveparam, n, k, b, t);
+            
+            // output point(fCurveparam) = sum over {input point * value of blending function}
+            fX = 0.0;
+            fY = 0.0;
+            fZ = 0.0;
+            for (nPointIndex=0;nPointIndex<=n;nPointIndex++)
+            {
+                fX +=pOldX[nPointIndex]*b[nPointIndex];
+                fY +=pOldY[nPointIndex]*b[nPointIndex];
+                fZ +=pOldZ[nPointIndex]*b[nPointIndex];
+            }
+            pNewX[nNewSector] = fX;
+            pNewY[nNewSector] = fY;
+            pNewZ[nNewSector] = fZ;
+            
+            fCurveparam += fCurveStep; //for next looping
+        }
+        // add last control point to BSpline curve
+        pNewX[nNewSectorCount] = pOldX[n];
+        pNewY[nNewSectorCount] = pOldY[n];
+        pNewZ[nNewSectorCount] = pOldZ[n];
 
-    delete[] t;
-    delete[] b;
+        delete[] t;
+        delete[] b;
+    }
 }
 
 //.............................................................................
diff --git a/chart2/source/view/diagram/VDiagram.cxx b/chart2/source/view/diagram/VDiagram.cxx
index 23fa74d..31e3408 100644
--- a/chart2/source/view/diagram/VDiagram.cxx
+++ b/chart2/source/view/diagram/VDiagram.cxx
@@ -553,13 +553,13 @@ void VDiagram::createShapes_3d()
             CuboidPlanePosition eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) );
             if( CuboidPlanePosition_Right==eLeftWallPos )
                 xPos = FIXED_SIZE_FOR_3D_CHART_VOLUME;
-            Stripe aStripe( drawing::Position3D(xPos,0,0)
-                , drawing::Direction3D(0,FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
+            Stripe aStripe( drawing::Position3D(xPos,FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
+                , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
                 , drawing::Direction3D(0,0,FIXED_SIZE_FOR_3D_CHART_VOLUME) );
 
             uno::Reference< drawing::XShape > xShape =
                 m_pShapeFactory->createStripe( xWallGroup_Shapes, aStripe
-                    , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), true );
+                    , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), true, true );
             if( !bAddFloorAndWall )
             {
                 //we always need this object as dummy object for correct scene dimensions
@@ -573,9 +573,9 @@ void VDiagram::createShapes_3d()
             CuboidPlanePosition eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) );
             if( CuboidPlanePosition_Front==eBackWallPos )
                     zPos = FIXED_SIZE_FOR_3D_CHART_VOLUME;
-            Stripe aStripe( drawing::Position3D(0,0,zPos)
+            Stripe aStripe( drawing::Position3D(0,FIXED_SIZE_FOR_3D_CHART_VOLUME,zPos)
                 , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0)
-                , drawing::Direction3D(0,FIXED_SIZE_FOR_3D_CHART_VOLUME,0) );
+                , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0) );
 
             uno::Reference< drawing::XShape > xShape =
                 m_pShapeFactory->createStripe(xWallGroup_Shapes, aStripe 
diff --git a/chart2/source/view/inc/ShapeFactory.hxx b/chart2/source/view/inc/ShapeFactory.hxx
index 4c02c0f..a7c88a3 100644
--- a/chart2/source/view/inc/ShapeFactory.hxx
+++ b/chart2/source/view/inc/ShapeFactory.hxx
@@ -122,7 +122,7 @@ public:
                     , const Stripe& rStripe
                     , const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& xSourceProp
                     , const tPropertyNameMap& rPropertyNameMap
-                    , sal_Bool bDoubleSided = true);
+                    , sal_Bool bDoubleSided = true, bool bRotatedTexture=false );
 
     ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
         createArea3D( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget
diff --git a/chart2/source/view/inc/Stripe.hxx b/chart2/source/view/inc/Stripe.hxx
index 2cef24b..c55cfc2 100644
--- a/chart2/source/view/inc/Stripe.hxx
+++ b/chart2/source/view/inc/Stripe.hxx
@@ -65,7 +65,7 @@ public:
 
     ::com::sun::star::uno::Any      getPolyPolygonShape3D() const;
     ::com::sun::star::uno::Any      getNormalsPolygon() const;
-    ::com::sun::star::uno::Any      getTexturePolygon() const;
+    ::com::sun::star::uno::Any      getTexturePolygon( bool bRotatedTexture ) const;
 
     ::com::sun::star::drawing::Position3D GetPosition1() const { return m_aPoint1; }
     ::com::sun::star::drawing::Position3D GetPosition2() const { return m_aPoint2; }
diff --git a/chart2/source/view/main/PlottingPositionHelper.cxx b/chart2/source/view/main/PlottingPositionHelper.cxx
index 6cc74fb..60e1bf8 100644
--- a/chart2/source/view/main/PlottingPositionHelper.cxx
+++ b/chart2/source/view/main/PlottingPositionHelper.cxx
@@ -142,19 +142,6 @@ uno::Reference< XTransformation > PlottingPositionHelper::getTransformationScale
             std::swap(nXAxisOrientation,nYAxisOrientation);
         }
 
-        if( AxisOrientation_MATHEMATICAL==nXAxisOrientation )
-            aMatrix.translate(-MinX, 0.0, 0.0);
-        else
-            aMatrix.translate(-MaxX, 0.0, 0.0);
-        if( AxisOrientation_MATHEMATICAL==nYAxisOrientation )
-            aMatrix.translate(0.0, -MinY, 0.0);
-        else
-            aMatrix.translate(0.0, -MaxY, 0.0);
-        if( AxisOrientation_MATHEMATICAL==nZAxisOrientation )
-            aMatrix.translate(0.0, 0.0, -MaxZ);//z direction in draw is reverse mathematical direction
-        else
-            aMatrix.translate(0.0, 0.0, -MinZ);
-
         double fWidthX = MaxX - MinX;
         double fWidthY = MaxY - MinY;
         double fWidthZ = MaxZ - MinZ;
@@ -163,9 +150,24 @@ uno::Reference< XTransformation > PlottingPositionHelper::getTransformationScale
         double fScaleDirectionY = AxisOrientation_MATHEMATICAL==nYAxisOrientation ? 1.0 : -1.0;
         double fScaleDirectionZ = AxisOrientation_MATHEMATICAL==nZAxisOrientation ? -1.0 : 1.0;
 
-        aMatrix.scale(fScaleDirectionX*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthX,
-            fScaleDirectionY*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthY,
-            fScaleDirectionZ*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthZ);
+        double fScaleX = fScaleDirectionX*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthX;
+        double fScaleY = fScaleDirectionY*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthY;
+        double fScaleZ = fScaleDirectionZ*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthZ;
+
+        aMatrix.scale(fScaleX, fScaleY, fScaleZ);
+
+        if( AxisOrientation_MATHEMATICAL==nXAxisOrientation )
+            aMatrix.translate(-MinX*fScaleX, 0.0, 0.0);
+        else
+            aMatrix.translate(-MaxX*fScaleX, 0.0, 0.0);
+        if( AxisOrientation_MATHEMATICAL==nYAxisOrientation )
+            aMatrix.translate(0.0, -MinY*fScaleY, 0.0);
+        else
+            aMatrix.translate(0.0, -MaxY*fScaleY, 0.0);
+        if( AxisOrientation_MATHEMATICAL==nZAxisOrientation )
+            aMatrix.translate(0.0, 0.0, -MaxZ*fScaleZ);//z direction in draw is reverse mathematical direction
+        else
+            aMatrix.translate(0.0, 0.0, -MinZ*fScaleZ);
 
         aMatrix = m_aMatrixScreenToScene*aMatrix;
 
diff --git a/chart2/source/view/main/ShapeFactory.cxx b/chart2/source/view/main/ShapeFactory.cxx
index c1fa1ce..6563e31 100644
--- a/chart2/source/view/main/ShapeFactory.cxx
+++ b/chart2/source/view/main/ShapeFactory.cxx
@@ -1023,7 +1023,8 @@ uno::Reference< drawing::XShape >
                     , const Stripe& rStripe
                     , const uno::Reference< beans::XPropertySet >& xSourceProp
                     , const tPropertyNameMap& rPropertyNameMap
-                    , sal_Bool bDoubleSided )
+                    , sal_Bool bDoubleSided
+                    , bool bRotatedTexture )
 {
     if( !xTarget.is() )
         return 0;
@@ -1047,7 +1048,7 @@ uno::Reference< drawing::XShape >
 
             //TexturePolygon
             xProp->setPropertyValue( C2U( UNO_NAME_3D_TEXTUREPOLYGON3D )
-                , rStripe.getTexturePolygon() );
+                , rStripe.getTexturePolygon( bRotatedTexture ) );
 
 
             //Normals Polygon
diff --git a/chart2/source/view/main/Stripe.cxx b/chart2/source/view/main/Stripe.cxx
index c10e816..170a4d3 100644
--- a/chart2/source/view/main/Stripe.cxx
+++ b/chart2/source/view/main/Stripe.cxx
@@ -161,7 +161,7 @@ uno::Any Stripe::getNormalsPolygon() const
     return uno::Any( &aPP, ::getCppuType((const drawing::PolyPolygonShape3D*)0) );
 }
 
-uno::Any Stripe::getTexturePolygon() const
+uno::Any Stripe::getTexturePolygon( bool bRotatedTexture ) const
 {
     drawing::PolyPolygonShape3D aPP;
 
@@ -181,22 +181,43 @@ uno::Any Stripe::getTexturePolygon() const
     double* pInnerSequenceY = pOuterSequenceY->getArray();
     double* pInnerSequenceZ = pOuterSequenceZ->getArray();
 
-    *pInnerSequenceX++ = 0.0;
-    *pInnerSequenceY++ = 0.0;
-    *pInnerSequenceZ++ = 0.0;
+    if( !bRotatedTexture )
+    {
+        *pInnerSequenceX++ = 0.0;
+        *pInnerSequenceY++ = 0.0;
+        *pInnerSequenceZ++ = 0.0;
+
+        *pInnerSequenceX++ = 1.0;
+        *pInnerSequenceY++ = 0.0;
+        *pInnerSequenceZ++ = 0.0;
+
+        *pInnerSequenceX++ = 1.0;
+        *pInnerSequenceY++ = 1.0;
+        *pInnerSequenceZ++ = 0.0;
 
-    *pInnerSequenceX++ = 1.0;
-    *pInnerSequenceY++ = 0.0;
-    *pInnerSequenceZ++ = 0.0;
+        *pInnerSequenceX++ = 0.0;
+        *pInnerSequenceY++ = 1.0;
+        *pInnerSequenceZ++ = 0.0;
+    }
+    else
+    {
+        *pInnerSequenceX++ = 1.0;
+        *pInnerSequenceY++ = 0.0;
+        *pInnerSequenceZ++ = 0.0;
 
-    *pInnerSequenceX++ = 1.0;
-    *pInnerSequenceY++ = 1.0;
-    *pInnerSequenceZ++ = 0.0;
+        *pInnerSequenceX++ = 1.0;
+        *pInnerSequenceY++ = 1.0;
+        *pInnerSequenceZ++ = 0.0;
 
-    *pInnerSequenceX++ = 0.0;
-    *pInnerSequenceY++ = 1.0;
-    *pInnerSequenceZ++ = 0.0;
+        *pInnerSequenceX++ = 0.0;
+        *pInnerSequenceY++ = 1.0;
+        *pInnerSequenceZ++ = 0.0;
 
+        *pInnerSequenceX++ = 0.0;
+        *pInnerSequenceY++ = 0.0;
+        *pInnerSequenceZ++ = 0.0;
+    }
+    
     return uno::Any( &aPP, ::getCppuType((const drawing::PolyPolygonShape3D*)0) );
 }
 
diff --git a/chart2/source/view/main/VDataSeries.cxx b/chart2/source/view/main/VDataSeries.cxx
index 9bd489f..0628f09 100644
--- a/chart2/source/view/main/VDataSeries.cxx
+++ b/chart2/source/view/main/VDataSeries.cxx
@@ -124,20 +124,28 @@ struct lcl_LessXOfPoint
     }
 };
 
-void lcl_clearIfTextIsContained( VDataSequence& rData, const uno::Reference<data::XDataSequence>& xDataSequence )
+void lcl_clearIfNoValuesButTextIsContained( VDataSequence& rData, const uno::Reference<data::XDataSequence>& xDataSequence )
 {
+    //#i71686#, #i101968#, #i102428#
+    sal_Int32 nCount = rData.Doubles.getLength();
+    for( sal_Int32 i = 0; i < nCount; ++i )
+    {
+        if( !::rtl::math::isNan( rData.Doubles[i] ) )
+            return;
+    }
+    //no double value is countained
+    //is there any text?
     uno::Sequence< rtl::OUString > aStrings( DataSequenceToStringSequence( xDataSequence ) );
-    for( sal_Int32 i = 0; i < rData.Doubles.getLength(); ++i )
+    sal_Int32 nTextCount = aStrings.getLength();
+    for( sal_Int32 j = 0; j < nTextCount; ++j )
     {
-        if( ::rtl::math::isNan( rData.Doubles[i] ) )
+        if( aStrings[j].getLength() )
         {
-            if( i < aStrings.getLength() && aStrings[i].getLength() )
-            {
-                rData.clear();
-                break;
-            }
+            rData.clear();
+            return;
         }
     }
+    //no content at all
 }
 
 void lcl_maybeReplaceNanWithZero( double& rfValue, sal_Int32 nMissingValueTreatment )
@@ -228,7 +236,7 @@ VDataSeries::VDataSeries( const uno::Reference< XDataSeries >& xDataSeries )
                 if( aRole.equals(C2U("values-x")) )
                 {
                     m_aValues_X.init( xDataSequence );
-                    lcl_clearIfTextIsContained( m_aValues_X, xDataSequence );
+                    lcl_clearIfNoValuesButTextIsContained( m_aValues_X, xDataSequence );
                 }
                 else if( aRole.equals(C2U("values-y")) )
                     m_aValues_Y.init( xDataSequence );
commit cf66e1d3606ddc8da1d93e748e4b07875357d4f0
Author: Jens-Heiner Rechtien <hr at openoffice.org>
Date:   Tue Jul 28 10:04:47 2009 +0000

    CWS-TOOLING: integrate CWS calc51
    2009-07-17 15:47:46 +0200 er  r274098 : #i101544# more thorough reference checking in chart data ranges; also prevent some possible crash if invalid ranges were to be passed to document/cell access.
    2009-07-16 14:20:11 +0200 er  r274051 : #i101544# let ScRefTokenHelper::compileRangeRepresentation() fail on all possible non-reference occasions
    2009-07-07 10:11:40 +0200 nn  r273776 : #i35579# don't use long instead of sal_Int32
    2009-07-03 16:41:39 +0200 nn  r273711 : msvc warnings
    2009-07-03 14:18:45 +0200 nn  r273698 : msvc warning
    2009-07-03 11:30:41 +0200 nn  r273685 : #i35579# move new tokens to the end
    2009-07-03 10:12:55 +0200 nn  r273681 : CWS-TOOLING: rebase CWS calc51 to trunk at 273468 (milestone: DEV300:m51)
    2009-06-30 17:57:30 +0200 nn  r273529 : #i103027# EnterData: if it's a formula, don't pass EditTextObject to undo
    2009-06-29 14:31:18 +0200 er  r273474 : #i101544# #i101645# #i102388# applied diff from CWS dr68ooo311
    2009-06-29 10:30:20 +0200 nn  r273457 : #i103161# DeleteCells: always leave list action
    2009-06-24 16:16:34 +0200 nn  r273353 : gcc warnings
    2009-06-17 11:50:28 +0200 tbe  r273055 : #i35579# Standard filter requires more options
    2009-06-17 11:44:22 +0200 tbe  r273054 : #i35579# Standard filter requires more options
    2009-06-17 11:22:23 +0200 tbe  r273052 : #i35579# Standard filter requires more options
    2009-06-15 18:29:32 +0200 nn  r273006 : #160063# UseFormulaData: check parenthesis position
    2009-06-12 15:41:16 +0200 nn  r272923 : #i99250# handle range lists in DoAutoOutline (patch from dtardon)
    2009-06-11 15:07:05 +0200 nn  r272874 : #i86943# GetNextPos: skip overlapped cells
    2009-06-11 11:17:37 +0200 nn  r272856 : #i97726# EnterData: get text from EditTextObject for repeat string of undo action
    2009-06-10 20:45:07 +0200 nn  r272839 : #i102566# minimum amount of code between updates of calculation progress (patch by cmc)
    2009-06-10 20:22:02 +0200 nn  r272838 : #i69524# PasteFile: specify target for SID_OPENDOC
    2009-06-09 17:33:08 +0200 nn  r272789 : #i16615# absolute/relative reference conversion for cell ranges (patch by gaojingmei)

diff --git a/sc/inc/address.hxx b/sc/inc/address.hxx
index c623c4f..b8d5ece 100644
--- a/sc/inc/address.hxx
+++ b/sc/inc/address.hxx
@@ -791,12 +791,14 @@ template< typename T > void PutInOrder( T& nStart, T& nEnd )
 
 bool ConvertSingleRef( ScDocument* pDoc, const String& rRefString,
         SCTAB nDefTab, ScRefAddress& rRefAddress,
-        const ScAddress::Details& rDetails = ScAddress::detailsOOOa1);
+        const ScAddress::Details& rDetails = ScAddress::detailsOOOa1,
+        ScAddress::ExternalInfo* pExtInfo = NULL );
 
 bool ConvertDoubleRef(ScDocument* pDoc, const String& rRefString,
         SCTAB nDefTab, ScRefAddress& rStartRefAddress,
         ScRefAddress& rEndRefAddress,
-        const ScAddress::Details& rDetails = ScAddress::detailsOOOa1);
+        const ScAddress::Details& rDetails = ScAddress::detailsOOOa1,
+        ScAddress::ExternalInfo* pExtInfo = NULL );
 
 /// append alpha representation of column to buffer
 SC_DLLPUBLIC void ScColToAlpha( rtl::OUStringBuffer& rBuffer, SCCOL nCol);
diff --git a/sc/inc/cell.hxx b/sc/inc/cell.hxx
index 6c5ddcf..4d450d3 100644
--- a/sc/inc/cell.hxx
+++ b/sc/inc/cell.hxx
@@ -387,6 +387,15 @@ public:
     inline USHORT   GetSeenInIteration() const { return nSeenInIteration; }
 
     BOOL			HasOneReference( ScRange& r ) const;
+    /* Checks if the formula contains reference list that can be
+       expressed by one reference (like A1;A2;A3:A5 -> A1:A5). The
+       reference list is not required to be sorted (i.e. A3;A1;A2 is
+       still recognized as A1:A3), but no overlapping is allowed.
+       If one reference is recognized, the rRange is filled.
+
+       It is similar to HasOneReference(), but more general.
+     */
+    bool HasRefListExpressibleAsOneReference(ScRange& rRange) const;
     BOOL			HasRelNameReference() const;
     BOOL			HasColRowName() const;
 
diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx
index c41c15d..39a2e2c 100644
--- a/sc/inc/compiler.hxx
+++ b/sc/inc/compiler.hxx
@@ -311,9 +311,11 @@ private:
     const CharClass*    pCharClass;         // which character classification is used for parseAnyToken
     USHORT      mnPredetectedReference;     // reference when reading ODF, 0 (none), 1 (single) or 2 (double)
     SCsTAB      nMaxTab;                    // last sheet in document
+    sal_Int32   mnRangeOpPosInSymbol;       // if and where a range operator is in symbol
     const Convention *pConv;
     bool        mbCloseBrackets;            // whether to close open brackets automatically, default TRUE
     bool        mbExtendedErrorDetection;
+    bool        mbRewind;                   // whether symbol is to be rewound to some step during lexical analysis
 
     BOOL   NextNewToken(bool bInArray = false);
 
diff --git a/sc/inc/datauno.hxx b/sc/inc/datauno.hxx
index 874820a..3103875 100644
--- a/sc/inc/datauno.hxx
+++ b/sc/inc/datauno.hxx
@@ -50,6 +50,7 @@
 #include <com/sun/star/lang/XUnoTunnel.hpp>
 #include <com/sun/star/container/XNamed.hpp>
 #include <com/sun/star/util/XRefreshable.hpp>
+#include <com/sun/star/sheet/XSheetFilterDescriptor2.hpp>
 #include <cppuhelper/implbase2.hxx>
 #include <cppuhelper/implbase3.hxx>
 #include <cppuhelper/implbase4.hxx>
@@ -340,8 +341,9 @@ public:
 
 //	to uno, all three look the same
 
-class ScFilterDescriptorBase : public cppu::WeakImplHelper3<
+class ScFilterDescriptorBase : public cppu::WeakImplHelper4<
                                     com::sun::star::sheet::XSheetFilterDescriptor,
+                                    com::sun::star::sheet::XSheetFilterDescriptor2,
                                     com::sun::star::beans::XPropertySet,
                                     com::sun::star::lang::XServiceInfo >,
                                public SfxListener
@@ -368,6 +370,13 @@ public:
                                 ::com::sun::star::sheet::TableFilterField >& aFilterFields )
                                     throw(::com::sun::star::uno::RuntimeException);
 
+                            // XSheetFilterDescriptor2
+    virtual ::com::sun::star::uno::Sequence< ::com::sun::star::sheet::TableFilterField2 > SAL_CALL
+                            getFilterFields2() throw(::com::sun::star::uno::RuntimeException);
+    virtual void SAL_CALL	setFilterFields2( const ::com::sun::star::uno::Sequence<
+                                ::com::sun::star::sheet::TableFilterField2 >& aFilterFields )
+                                    throw(::com::sun::star::uno::RuntimeException);
+
                             // XPropertySet
     virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo >
                             SAL_CALL getPropertySetInfo()
diff --git a/sc/inc/externalrefmgr.hxx b/sc/inc/externalrefmgr.hxx
index 1ca3bac..7071f2b 100644
--- a/sc/inc/externalrefmgr.hxx
+++ b/sc/inc/externalrefmgr.hxx
@@ -132,15 +132,27 @@ public:
     class Table
     {
     public:
+
+        enum ReferencedFlag
+        {
+            UNREFERENCED,
+            REFERENCED_MARKED,      // marked as referenced during store to file
+            REFERENCED_PERMANENT    // permanently marked, e.g. from within interpreter
+        };
+
         Table();
         ~Table();
 
         SC_DLLPUBLIC void setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex = 0);
         TokenRef getCell(SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex = NULL) const;
         bool hasRow( SCROW nRow ) const;
-        /// A temporary state used only during store to file.
-        bool isReferenced() const;
+        /** Set/clear referenced status flag only if current status is not 
+            REFERENCED_PERMANENT. */
         void setReferenced( bool bReferenced );
+        /// Unconditionally set the reference status flag.
+        void setReferencedFlag( ReferencedFlag eFlag );
+        ReferencedFlag getReferencedFlag() const;
+        bool isReferenced() const;
         /// Obtain a sorted vector of rows.
         void getAllRows(::std::vector<SCROW>& rRows) const;
         /// Obtain a sorted vector of columns.
@@ -148,8 +160,8 @@ public:
         void getAllNumberFormats(::std::vector<sal_uInt32>& rNumFmts) const;
 
     private:
-        RowsDataType maRows;
-        bool         mbReferenced;
+        RowsDataType   maRows;
+        ReferencedFlag meReferenced;
     };
 
     typedef ::boost::shared_ptr<Table>      TableTypeRef;
@@ -219,9 +231,16 @@ public:
      * Set a table as referenced, used only during store-to-file.
      * @returns <TRUE/> if ALL tables of ALL documents are marked.
      */
-    bool setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName );
+    bool setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName, size_t nSheets, bool bPermanent );
     void setAllCacheTableReferencedStati( bool bReferenced );
     bool areAllCacheTablesReferenced() const;
+
+    /**
+     * Set a table as permanently referenced, to be called if not in 
+     * mark-during-store-to-file cycle.
+     */
+    void setCacheTableReferencedPermanently( sal_uInt16 nFileId, const String& rTabName, size_t nSheets );
+
 private:
     struct ReferencedStatus
     {
@@ -497,10 +516,16 @@ public:
      * Set a table as referenced, used only during store-to-file.
      * @returns <TRUE/> if ALL tables of ALL external documents are marked.
      */
-    bool setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName );
+    bool setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName, size_t nSheets );
     void setAllCacheTableReferencedStati( bool bReferenced );
 
     /**
+     * Set a table as permanently referenced, to be called if not in 
+     * mark-during-store-to-file cycle.
+     */
+    void setCacheTableReferencedPermanently( sal_uInt16 nFileId, const String& rTabName, size_t nSheets );
+
+    /**
      * @returns <TRUE/> if setAllCacheTableReferencedStati(false) was called, 
      * <FALSE/> if setAllCacheTableReferencedStati(true) was called.
      */
diff --git a/sc/inc/global.hxx b/sc/inc/global.hxx
index 7d3d54f..24fcb2e 100644
--- a/sc/inc/global.hxx
+++ b/sc/inc/global.hxx
@@ -728,7 +728,13 @@ enum ScQueryOp
         SC_TOPVAL,
         SC_BOTVAL,
         SC_TOPPERC,
-        SC_BOTPERC
+        SC_BOTPERC,
+        SC_CONTAINS,
+        SC_DOES_NOT_CONTAIN,
+        SC_BEGINS_WITH,
+        SC_DOES_NOT_BEGIN_WITH,
+        SC_ENDS_WITH,
+        SC_DOES_NOT_END_WITH
     };
 
 // -----------------------------------------------------------------------
diff --git a/sc/inc/pch/precompiled_sc.hxx b/sc/inc/pch/precompiled_sc.hxx
index eae881c..40552fd 100644
--- a/sc/inc/pch/precompiled_sc.hxx
+++ b/sc/inc/pch/precompiled_sc.hxx
@@ -36,6 +36,7 @@
 
 #include <algorithm>
 #include <assert.h>
+#include <deque>
 #include <stdarg.h>
 #include <stddef.h>
 #include <stdio.h>
@@ -49,6 +50,8 @@
 #include <new>
 #include <cfloat>
 
+#include <boost/bind.hpp>
+
 #include <basegfx/polygon/b2dpolygon.hxx>
 #include <basegfx/polygon/b3dpolygon.hxx>
 #include <basegfx/polygon/b3dpolypolygon.hxx>
diff --git a/sc/inc/progress.hxx b/sc/inc/progress.hxx
index 0e7f545..7e9bb7c 100644
--- a/sc/inc/progress.hxx
+++ b/sc/inc/progress.hxx
@@ -36,6 +36,17 @@
 
 class ScDocument;
 
+/*
+ * #i102566
+ * Drawing a progress bar update is not cheap, so if we draw it on every
+ * percentage change of 200 calculations we get one progress draw per 2
+ * calculations which is slower than doing the calculations themselves. So as a
+ * rough guide only do an update per MIN_NO_CODES_PER_PROGRESS_UPDATE
+ * calculations
+ */
+#define MIN_NO_CODES_PER_PROGRESS_UPDATE 100
+
+
 class SC_DLLPUBLIC ScProgress
 {
 private:
diff --git a/sc/inc/refdata.hxx b/sc/inc/refdata.hxx
index 933999a..ac289a4 100644
--- a/sc/inc/refdata.hxx
+++ b/sc/inc/refdata.hxx
@@ -109,6 +109,8 @@ struct SC_DLLPUBLIC ScSingleRefData        // Single reference (one address) int
     inline  BOOL IsRelName() const          { return Flags.bRelName; }
 
     inline  BOOL Valid() const;
+    /// In external references nTab is -1
+    inline  bool ValidExternal() const;
 
             void SmartRelAbs( const ScAddress& rPos );
             void CalcRelFromAbs( const ScAddress& rPos );
@@ -147,6 +149,13 @@ inline BOOL ScSingleRefData::Valid() const
             nTab >= 0 && nTab <= MAXTAB;
 }
 
+inline bool ScSingleRefData::ValidExternal() const
+{
+    return  nCol >= 0 && nCol <= MAXCOL &&
+            nRow >= 0 && nRow <= MAXROW &&
+            nTab == -1;
+}
+
 
 struct ScComplexRefData         // Complex reference (a range) into the sheet
 {
@@ -181,6 +190,10 @@ struct ScComplexRefData         // Complex reference (a range) into the sheet
         { return Ref1.IsDeleted() || Ref2.IsDeleted(); }
     inline  BOOL Valid() const
         { return Ref1.Valid() && Ref2.Valid(); }
+    /** In external references nTab is -1 for the start tab and -1 for the end 
+        tab if one sheet, or >=0 if more than one sheets. */
+    inline  bool ValidExternal() const;
+
     /// Absolute references have to be up-to-date when calling this!
     void PutInOrder();
     inline  BOOL operator==( const ScComplexRefData& r ) const
@@ -192,4 +205,12 @@ struct ScComplexRefData         // Complex reference (a range) into the sheet
     ScComplexRefData& Extend( const ScComplexRefData & rRef, const ScAddress & rPos );
 };
 
+inline bool ScComplexRefData::ValidExternal() const
+{
+    return Ref1.ValidExternal() &&
+        Ref2.nCol >= 0 && Ref2.nCol <= MAXCOL &&
+        Ref2.nRow >= 0 && Ref2.nRow <= MAXROW &&
+        Ref2.nTab >= Ref1.nTab;
+}
+
 #endif
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 80a1fce..029403d 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -267,16 +267,28 @@ public:
     void		GetString( SCCOL nCol, SCROW nRow, String& rString );
     void		GetInputString( SCCOL nCol, SCROW nRow, String& rString );
     double		GetValue( const ScAddress& rPos ) const
-                    { return aCol[rPos.Col()].GetValue( rPos.Row() ); }
+                    {
+                        return ValidColRow(rPos.Col(),rPos.Row()) ? 
+                            aCol[rPos.Col()].GetValue( rPos.Row() ) :
+                            0.0;
+                    }
     double		GetValue( SCCOL nCol, SCROW nRow );
     void		GetFormula( SCCOL nCol, SCROW nRow, String& rFormula,
                             BOOL bAsciiExport = FALSE );
 
     CellType	GetCellType( const ScAddress& rPos ) const
-                    { return aCol[rPos.Col()].GetCellType( rPos.Row() ); }
+                    {
+                        return ValidColRow(rPos.Col(),rPos.Row()) ? 
+                            aCol[rPos.Col()].GetCellType( rPos.Row() ) : 
+                            CELLTYPE_NONE;
+                    }
     CellType	GetCellType( SCCOL nCol, SCROW nRow ) const;
     ScBaseCell*	GetCell( const ScAddress& rPos ) const
-                    { return aCol[rPos.Col()].GetCell( rPos.Row() ); }
+                    {
+                        return ValidColRow(rPos.Col(),rPos.Row()) ? 
+                            aCol[rPos.Col()].GetCell( rPos.Row() ) :
+                            NULL;
+                    }
     ScBaseCell*	GetCell( SCCOL nCol, SCROW nRow ) const;
 
     void		GetLastDataPos(SCCOL& rCol, SCROW& rRow) const;
@@ -378,7 +390,11 @@ public:
                                 SCCOL nEndCol, SCROW nEndRow ) const;
 
     USHORT		GetErrCode( const ScAddress& rPos ) const
-                    { return aCol[rPos.Col()].GetErrCode( rPos.Row() ); }
+                    {
+                        return ValidColRow(rPos.Col(),rPos.Row()) ? 
+                            aCol[rPos.Col()].GetErrCode( rPos.Row() ) :
+                            0;
+                    }
 //UNUSED2008-05  USHORT		GetErrCode( SCCOL nCol, SCROW nRow ) const;
 
     void		ResetChanged( const ScRange& rRange );
@@ -454,7 +470,11 @@ public:
     const ScPatternAttr*    GetMostUsedPattern( SCCOL nCol, SCROW nStartRow, SCROW nEndRow ) const;
 
     ULONG					GetNumberFormat( const ScAddress& rPos ) const
-                                { return aCol[rPos.Col()].GetNumberFormat( rPos.Row() ); }
+                                {
+                                    return ValidColRow(rPos.Col(),rPos.Row()) ? 
+                                        aCol[rPos.Col()].GetNumberFormat( rPos.Row() ) :
+                                        0;
+                                }
     ULONG					GetNumberFormat( SCCOL nCol, SCROW nRow ) const;
     void					MergeSelectionPattern( ScMergePatternState& rState,
                                                 const ScMarkData& rMark, BOOL bDeep ) const;
@@ -473,7 +493,10 @@ public:
     void		ApplyPattern( SCCOL nCol, SCROW nRow, const ScPatternAttr& rAttr );
     void		ApplyPatternArea( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, const ScPatternAttr& rAttr );
     void		SetPattern( const ScAddress& rPos, const ScPatternAttr& rAttr, BOOL bPutToPool = FALSE )
-                    { aCol[rPos.Col()].SetPattern( rPos.Row(), rAttr, bPutToPool ); }
+                    {
+                        if (ValidColRow(rPos.Col(),rPos.Row()))
+                            aCol[rPos.Col()].SetPattern( rPos.Row(), rAttr, bPutToPool );
+                    }
     void		SetPattern( SCCOL nCol, SCROW nRow, const ScPatternAttr& rAttr, BOOL bPutToPool = FALSE );
     void		ApplyPatternIfNumberformatIncompatible( const ScRange& rRange,
                             const ScPatternAttr& rPattern, short nNewType );
diff --git a/sc/source/core/data/cell.cxx b/sc/source/core/data/cell.cxx
index 2a33623..08f201d 100644
--- a/sc/source/core/data/cell.cxx
+++ b/sc/source/core/data/cell.cxx
@@ -1701,7 +1701,7 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam )
 
         // Reschedule verlangsamt das ganze erheblich, nur bei Prozentaenderung ausfuehren
         ScProgress::GetInterpretProgress()->SetStateCountDownOnPercent(
-            pDocument->GetFormulaCodeInTree() );
+            pDocument->GetFormulaCodeInTree()/MIN_NO_CODES_PER_PROGRESS_UPDATE );
     }
     else
     {
diff --git a/sc/source/core/data/cell2.cxx b/sc/source/core/data/cell2.cxx
index 7ef1826..13923c5 100644
--- a/sc/source/core/data/cell2.cxx
+++ b/sc/source/core/data/cell2.cxx
@@ -34,6 +34,11 @@
 
 
 // INCLUDE ---------------------------------------------------------------
+#include <algorithm>
+#include <deque>
+
+#include <boost/bind.hpp>
+
 #include <vcl/mapmod.hxx>
 #include <svx/editobj.hxx>
 #include <svx/editstat.hxx>
@@ -175,6 +180,223 @@ void ScEditCell::SetTextObject( const EditTextObject* pObject,
 
 // ============================================================================
 
+namespace
+{
+
+using std::deque;
+
+typedef SCCOLROW(*DimensionSelector)(const ScSingleRefData&);
+
+
+static SCCOLROW lcl_GetCol(const ScSingleRefData& rData)
+{
+    return rData.nCol;
+}
+
+
+static SCCOLROW lcl_GetRow(const ScSingleRefData& rData)
+{
+    return rData.nRow;
+}
+
+
+static SCCOLROW lcl_GetTab(const ScSingleRefData& rData)
+{
+    return rData.nTab;
+}
+
+
+/** Check if both references span the same range in selected dimension.
+ */
+static bool
+lcl_checkRangeDimension(
+        const SingleDoubleRefProvider& rRef1,
+        const SingleDoubleRefProvider& rRef2,
+        const DimensionSelector aWhich)
+{
+    return
+        aWhich(rRef1.Ref1) == aWhich(rRef2.Ref1)
+        && aWhich(rRef1.Ref2) == aWhich(rRef2.Ref2);
+}
+
+
+static bool
+lcl_checkRangeDimensions(
+        const SingleDoubleRefProvider& rRef1,
+        const SingleDoubleRefProvider& rRef2,
+        bool& bCol, bool& bRow, bool& bTab)
+{
+    const bool bSameCols(lcl_checkRangeDimension(rRef1, rRef2, lcl_GetCol));
+    const bool bSameRows(lcl_checkRangeDimension(rRef1, rRef2, lcl_GetRow));
+    const bool bSameTabs(lcl_checkRangeDimension(rRef1, rRef2, lcl_GetTab));
+        
+    // Test if exactly two dimensions are equal
+    if (!(bSameCols ^ bSameRows ^ bSameTabs)
+            && (bSameCols || bSameRows || bSameTabs))
+    {
+        bCol = !bSameCols;
+        bRow = !bSameRows;
+        bTab = !bSameTabs;
+        return true;
+    }
+    return false;
+}
+
+
+/** Check if references in given reference list can possibly
+    form a range. To do that, two of their dimensions must be the same.
+ */
+static bool
+lcl_checkRangeDimensions(
+        const deque<ScToken*>::const_iterator aBegin,
+        const deque<ScToken*>::const_iterator aEnd,
+        bool& bCol, bool& bRow, bool& bTab)
+{
+    deque<ScToken*>::const_iterator aCur(aBegin);
+    ++aCur;
+    const SingleDoubleRefProvider aRef(**aBegin);
+    bool bOk(false);
+    {
+        const SingleDoubleRefProvider aRefCur(**aCur);
+        bOk = lcl_checkRangeDimensions(aRef, aRefCur, bCol, bRow, bTab);
+    }
+    while (bOk && aCur != aEnd)
+    {
+        const SingleDoubleRefProvider aRefCur(**aCur);
+        bool bColTmp(false);
+        bool bRowTmp(false);
+        bool bTabTmp(false);
+        bOk = lcl_checkRangeDimensions(aRef, aRefCur, bColTmp, bRowTmp, bTabTmp);
+        bOk = bOk && (bCol == bColTmp && bRow == bRowTmp && bTab == bTabTmp);
+        ++aCur;
+    }
+
+    if (bOk && aCur == aEnd)
+    {
+        bCol = bCol;
+        bRow = bRow;
+        bTab = bTab;
+        return true;
+    }
+    return false;
+}
+
+
+bool
+lcl_lessReferenceBy(
+        const ScToken* const pRef1, const ScToken* const pRef2,
+        const DimensionSelector aWhich)
+{
+    const SingleDoubleRefProvider rRef1(*pRef1);
+    const SingleDoubleRefProvider rRef2(*pRef2);
+    return aWhich(rRef1.Ref1) < aWhich(rRef2.Ref1);
+}
+
+
+/** Returns true if range denoted by token pRef2 starts immediately after
+    range denoted by token pRef1. Dimension, in which the comparison takes
+    place, is given by aWhich.
+ */
+bool
+lcl_isImmediatelyFollowing(
+        const ScToken* const pRef1, const ScToken* const pRef2,
+        const DimensionSelector aWhich)
+{
+    const SingleDoubleRefProvider rRef1(*pRef1);
+    const SingleDoubleRefProvider rRef2(*pRef2);
+    return aWhich(rRef2.Ref1) - aWhich(rRef1.Ref2) == 1;
+}
+
+
+static bool
+lcl_checkIfAdjacent(
+        const deque<ScToken*>& rReferences,
+        const DimensionSelector aWhich)
+{
+    typedef deque<ScToken*>::const_iterator Iter;
+    Iter aBegin(rReferences.begin());
+    Iter aEnd(rReferences.end());
+    Iter aBegin1(aBegin);
+    ++aBegin1, --aEnd;
+    return std::equal(
+            aBegin, aEnd, aBegin1,
+            boost::bind(lcl_isImmediatelyFollowing, _1, _2, aWhich));
+}
+
+
+static void
+lcl_fillRangeFromRefList(
+        const deque<ScToken*>& rReferences, ScRange& rRange)
+{
+    const ScSingleRefData aStart(
+            SingleDoubleRefProvider(*rReferences.front()).Ref1);
+    rRange.aStart.Set(aStart.nCol, aStart.nRow, aStart.nTab);
+    const ScSingleRefData aEnd(
+            SingleDoubleRefProvider(*rReferences.back()).Ref2);
+    rRange.aEnd.Set(aEnd.nCol, aEnd.nRow, aEnd.nTab);
+}
+
+
+static bool
+lcl_refListFormsOneRange(
+        const ScAddress& aPos, deque<ScToken*>& rReferences,
+        ScRange& rRange)
+{
+    std::for_each(
+            rReferences.begin(), rReferences.end(),
+            bind(&ScToken::CalcAbsIfRel, _1, aPos))
+        ;
+    if (rReferences.size() == 1) {
+        lcl_fillRangeFromRefList(rReferences, rRange);
+        return true;
+    }
+
+    bool bCell(false);
+    bool bRow(false);
+    bool bTab(false);
+    if (lcl_checkRangeDimensions(rReferences.begin(), rReferences.end(),
+            bCell, bRow, bTab))
+    {
+        DimensionSelector aWhich;
+        if (bCell)
+        {
+            aWhich = lcl_GetCol;
+        }
+        else if (bRow)
+        {
+            aWhich = lcl_GetRow;
+        }
+        else if (bTab)
+        {
+            aWhich = lcl_GetTab;
+        }
+        else
+        {
+            OSL_ENSURE(false, "lcl_checkRangeDimensions shouldn't allow that!");
+            aWhich = lcl_GetRow;    // initialize to avoid warning
+        }
+        // Sort the references by start of range
+        std::sort(rReferences.begin(), rReferences.end(),
+                boost::bind(lcl_lessReferenceBy, _1, _2, aWhich));
+        if (lcl_checkIfAdjacent(rReferences, aWhich))
+        {
+            lcl_fillRangeFromRefList(rReferences, rRange);
+            return true;
+        }
+    }
+    return false;
+}
+
+
+bool lcl_isReference(const FormulaToken& rToken)
+{
+    return
+        rToken.GetType() == svSingleRef ||
+        rToken.GetType() == svDoubleRef;
+}
+
+}
+
 BOOL ScFormulaCell::IsEmpty()
 {
     if (IsDirtyOrInTableOpDirty() && pDocument->GetAutoCalc())
@@ -449,6 +671,52 @@ BOOL ScFormulaCell::HasOneReference( ScRange& r ) const
         return FALSE;
 }
 
+bool
+ScFormulaCell::HasRefListExpressibleAsOneReference(ScRange& rRange) const
+{
+    /* If there appears just one reference in the formula, it's the same
+       as HasOneReference(). If there are more of them, they can denote
+       one range if they are (sole) arguments of one function.
+       Union of these references must form one range and their
+       intersection must be empty set.
+    */
+    pCode->Reset();
+    // Get first reference, if any
+    ScToken* const pFirstReference(
+            dynamic_cast<ScToken*>(pCode->GetNextReferenceRPN()));
+    if (pFirstReference)
+    {
+        // Collect all consecutive references, starting by the one
+        // already found
+        std::deque<ScToken*> aReferences;
+        aReferences.push_back(pFirstReference);
+        FormulaToken* pToken(pCode->NextRPN());
+        FormulaToken* pFunction(0);
+        while (pToken)
+        {
+            if (lcl_isReference(*pToken))
+            {
+                aReferences.push_back(dynamic_cast<ScToken*>(pToken));
+                pToken = pCode->NextRPN();
+            }
+            else
+            {
+                if (pToken->IsFunction())
+                {
+                    pFunction = pToken;
+                }
+                break;
+            }
+        }
+        if (pFunction && !pCode->GetNextReferenceRPN()
+                && (pFunction->GetParamCount() == aReferences.size()))
+        {
+            return lcl_refListFormsOneRange(aPos, aReferences, rRange);
+        }
+    }
+    return false;
+}
+
 BOOL ScFormulaCell::HasRelNameReference() const
 {
     pCode->Reset();
diff --git a/sc/source/core/data/documen4.cxx b/sc/source/core/data/documen4.cxx
index 01ce2af..aa90414 100644
--- a/sc/source/core/data/documen4.cxx
+++ b/sc/source/core/data/documen4.cxx
@@ -311,9 +311,16 @@ bool ScDocument::MarkUsedExternalReferences( ScTokenArray & rArr )
                 switch (t->GetType())
                 {
                     case svExternalSingleRef:
-                    case svExternalDoubleRef:
                         bAllMarked = pRefMgr->setCacheTableReferenced( 
-                                t->GetIndex(), t->GetString());
+                                t->GetIndex(), t->GetString(), 1);
+                        break;
+                    case svExternalDoubleRef:
+                        {
+                            const ScComplexRefData& rRef = t->GetDoubleRef();
+                            size_t nSheets = rRef.Ref2.nTab - rRef.Ref1.nTab + 1;
+                            bAllMarked = pRefMgr->setCacheTableReferenced( 
+                                    t->GetIndex(), t->GetString(), nSheets);
+                        }
                         break;
                     case svExternalName:
                         /* TODO: external names aren't supported yet, but would 
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index cd958da..e94a552 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -2484,7 +2484,7 @@ void ScDocument::GetCell( SCCOL nCol, SCROW nRow, SCTAB nTab,
 ScBaseCell* ScDocument::GetCell( const ScAddress& rPos ) const
 {
     SCTAB nTab = rPos.Tab();
-    if ( pTab[nTab] )
+    if (ValidTab(nTab) && pTab[nTab])
         return pTab[nTab]->GetCell( rPos );
 
     DBG_ERROR("GetCell ohne Tabelle");
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index d51b7fd..dc4cc5f 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -870,6 +870,10 @@ BOOL ScTable::ValidNextPos( SCCOL nCol, SCROW nRow, const ScMarkData& rMark,
     if (!ValidCol(nCol) || !ValidRow(nRow))
         return FALSE;
 
+    if (pDocument->HasAttrib(nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_OVERLAPPED))
+        // Skip an overlapped cell.
+        return false;
+
     if (bMarked && !rMark.IsCellMarked(nCol,nRow))
         return FALSE;
 
@@ -912,7 +916,8 @@ void ScTable::GetNextPos( SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY,
     {
         BOOL bUp = ( nMovY < 0 );
         nRow = rMark.GetNextMarked( nCol, nRow, bUp );
-        while ( VALIDROW(nRow) && pRowFlags && (pRowFlags->GetValue(nRow) & CR_HIDDEN) )
+        while ( VALIDROW(nRow) && ((pRowFlags && (pRowFlags->GetValue(nRow) & CR_HIDDEN)) ||
+                pDocument->HasAttrib(nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_OVERLAPPED)) )
         {
             //	#53697# ausgeblendete ueberspringen (s.o.)
             nRow += nMovY;
@@ -941,7 +946,8 @@ void ScTable::GetNextPos( SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY,
             else if (nRow > MAXROW)
                 nRow = 0;
             nRow = rMark.GetNextMarked( nCol, nRow, bUp );
-            while ( VALIDROW(nRow) && pRowFlags && (pRowFlags->GetValue(nRow) & CR_HIDDEN) )
+            while ( VALIDROW(nRow) && ((pRowFlags && (pRowFlags->GetValue(nRow) & CR_HIDDEN)) ||
+                    pDocument->HasAttrib(nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_OVERLAPPED)) )
             {
                 //	#53697# ausgeblendete ueberspringen (s.o.)
                 nRow += nMovY;
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 1bc4d1f..2231ce9 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -2701,7 +2701,7 @@ void ScTable::DoAutoOutline( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SC
                     pCell = aCol[nCol].GetCell( nRow );
                     if (pCell)
                         if ( pCell->GetCellType() == CELLTYPE_FORMULA )
-                            if (((ScFormulaCell*)pCell)->HasOneReference( aRef ))
+                            if (((ScFormulaCell*)pCell)->HasRefListExpressibleAsOneReference( aRef ))
                                 if ( aRef.aStart.Col() == nCol && aRef.aEnd.Col() == nCol &&
                                      aRef.aStart.Tab() == nTab && aRef.aEnd.Tab() == nTab &&
                                      DiffSign( aRef.aStart.Row(), nRow ) ==
@@ -2732,7 +2732,7 @@ void ScTable::DoAutoOutline( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SC
             while ( aIter.Next( nRow, pCell ) && !bFound )
             {
                 if ( pCell->GetCellType() == CELLTYPE_FORMULA )
-                    if (((ScFormulaCell*)pCell)->HasOneReference( aRef ))
+                    if (((ScFormulaCell*)pCell)->HasRefListExpressibleAsOneReference( aRef ))
                         if ( aRef.aStart.Row() == nRow && aRef.aEnd.Row() == nRow &&
                              aRef.aStart.Tab() == nTab && aRef.aEnd.Tab() == nTab &&
                              DiffSign( aRef.aStart.Col(), nCol ) ==
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index dfab329..478aade 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -1022,12 +1022,19 @@ BOOL ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
             }
         }
         else if ( (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL) ||
+                  (rEntry.eOp == SC_CONTAINS || rEntry.eOp == SC_DOES_NOT_CONTAIN || 
+                   rEntry.eOp == SC_BEGINS_WITH || rEntry.eOp == SC_ENDS_WITH ||
+                   rEntry.eOp == SC_DOES_NOT_BEGIN_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH) ||
                 (rEntry.bQueryByString && (pCell ? pCell->HasStringData() :
                                            HasStringData(
                                                static_cast<SCCOL>(rEntry.nField),
                                                nRow))))
         {	// by String
             String	aCellStr;
+            if( rEntry.eOp == SC_CONTAINS || rEntry.eOp == SC_DOES_NOT_CONTAIN
+                || rEntry.eOp == SC_BEGINS_WITH || rEntry.eOp == SC_ENDS_WITH
+                || rEntry.eOp == SC_DOES_NOT_BEGIN_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH )
+                bMatchWholeCell = FALSE;
             if ( pCell )
             {
                 if (pCell->GetCellType() != CELLTYPE_NOTE)
@@ -1040,7 +1047,10 @@ BOOL ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
                 GetInputString( static_cast<SCCOL>(rEntry.nField), nRow, aCellStr );
 
             BOOL bRealRegExp = (rParam.bRegExp && ((rEntry.eOp == SC_EQUAL)
-                || (rEntry.eOp == SC_NOT_EQUAL)));
+                || (rEntry.eOp == SC_NOT_EQUAL) || (rEntry.eOp == SC_CONTAINS) 
+                || (rEntry.eOp == SC_DOES_NOT_CONTAIN) || (rEntry.eOp == SC_BEGINS_WITH)
+                || (rEntry.eOp == SC_ENDS_WITH) || (rEntry.eOp == SC_DOES_NOT_BEGIN_WITH)
+                || (rEntry.eOp == SC_DOES_NOT_END_WITH)));
             BOOL bTestRegExp = (pbTestEqualCondition && rParam.bRegExp
                 && ((rEntry.eOp == SC_LESS_EQUAL)
                     || (rEntry.eOp == SC_GREATER_EQUAL)));
@@ -1048,20 +1058,61 @@ BOOL ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
             {
                 xub_StrLen nStart = 0;
                 xub_StrLen nEnd   = aCellStr.Len();
-                BOOL bMatch = (BOOL) rEntry.GetSearchTextPtr( rParam.bCaseSens )
-                    ->SearchFrwrd( aCellStr, &nStart, &nEnd );
+                
                 // from 614 on, nEnd is behind the found text
+                BOOL bMatch = FALSE;
+                if ( rEntry.eOp == SC_ENDS_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH )
+                {
+                    nEnd = 0;
+                    nStart = aCellStr.Len();
+                    bMatch = (BOOL) rEntry.GetSearchTextPtr( rParam.bCaseSens )
+                        ->SearchBkwrd( aCellStr, &nStart, &nEnd );
+                } 
+                else
+                {
+                    bMatch = (BOOL) rEntry.GetSearchTextPtr( rParam.bCaseSens )
+                        ->SearchFrwrd( aCellStr, &nStart, &nEnd );
+                }
                 if ( bMatch && bMatchWholeCell
                         && (nStart != 0 || nEnd != aCellStr.Len()) )
                     bMatch = FALSE;    // RegExp must match entire cell string
                 if ( bRealRegExp )
-                    bOk = ((rEntry.eOp == SC_NOT_EQUAL) ? !bMatch : bMatch);
+                    switch (rEntry.eOp)
+                {
+                    case SC_EQUAL:
+                    case SC_CONTAINS:
+                        bOk = bMatch;
+                        break;
+                    case SC_NOT_EQUAL:
+                    case SC_DOES_NOT_CONTAIN:
+                        bOk = !bMatch;
+                        break;
+                    case SC_BEGINS_WITH:
+                        bOk = ( bMatch && (nStart == 0) );
+                        break;
+                    case SC_DOES_NOT_BEGIN_WITH:
+                        bOk = !( bMatch && (nStart == 0) );
+                        break;
+                    case SC_ENDS_WITH:
+                        bOk = ( bMatch && (nEnd == aCellStr.Len()) );
+                        break;
+                    case SC_DOES_NOT_END_WITH:
+                        bOk = !( bMatch && (nEnd == aCellStr.Len()) );
+                        break;
+                    default:
+                        {
+                            // added to avoid warnings
+                        }
+                }
                 else
                     bTestEqual = bMatch;
             }
             if ( !bRealRegExp )
             {
-                if ( rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL )
+                if ( rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL
+                    || rEntry.eOp == SC_CONTAINS || rEntry.eOp == SC_DOES_NOT_CONTAIN
+                    || rEntry.eOp == SC_BEGINS_WITH || rEntry.eOp == SC_ENDS_WITH
+                    || rEntry.eOp == SC_DOES_NOT_BEGIN_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH )
                 {
                     if ( !rEntry.bQueryByString && rEntry.pStr->Len() == 0 )
                     {
@@ -1069,22 +1120,54 @@ BOOL ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
                         // the query value is assigned directly, and the string is empty. In that case,
                         // don't find any string (isEqual would find empty string results in formula cells).
                         bOk = FALSE;
+                        if ( rEntry.eOp == SC_NOT_EQUAL )
+                            bOk = !bOk;
                     }
                     else if ( bMatchWholeCell )
+                    {
                         bOk = pTransliteration->isEqual( aCellStr, *rEntry.pStr );
+                        if ( rEntry.eOp == SC_NOT_EQUAL )
+                            bOk = !bOk;
+                    }
                     else
                     {
-                        ::com::sun::star::uno::Sequence< sal_Int32 > xOff;
                         String aCell( pTransliteration->transliterate(
                             aCellStr, ScGlobal::eLnge, 0, aCellStr.Len(),
-                            &xOff ) );
+                            NULL ) );
                         String aQuer( pTransliteration->transliterate(
                             *rEntry.pStr, ScGlobal::eLnge, 0, rEntry.pStr->Len(),
-                            &xOff ) );
-                        bOk = (aCell.Search( aQuer ) != STRING_NOTFOUND);
+                            NULL ) );
+                        xub_StrLen nIndex = (rEntry.eOp == SC_ENDS_WITH 
+                            || rEntry.eOp == SC_DOES_NOT_END_WITH)? (aCell.Len()-aQuer.Len()):0;
+                        xub_StrLen nStrPos = aCell.Search( aQuer, nIndex );
+                        switch (rEntry.eOp)
+                        {
+                        case SC_EQUAL:
+                        case SC_CONTAINS:
+                            bOk = ( nStrPos != STRING_NOTFOUND );
+                            break;
+                        case SC_NOT_EQUAL:
+                        case SC_DOES_NOT_CONTAIN:
+                            bOk = ( nStrPos == STRING_NOTFOUND );
+                            break;
+                        case SC_BEGINS_WITH:
+                            bOk = ( nStrPos == 0 );
+                            break;
+                        case SC_DOES_NOT_BEGIN_WITH:
+                            bOk = ( nStrPos != 0 );
+                            break;
+                        case SC_ENDS_WITH:
+                            bOk = ( nStrPos + aQuer.Len() == aCell.Len() );
+                            break;
+                        case SC_DOES_NOT_END_WITH:
+                            bOk = ( nStrPos + aQuer.Len() != aCell.Len() );
+                            break;
+                        default:
+                            {
+                                // added to avoid warnings
+                            }
+                        }
                     }
-                    if ( rEntry.eOp == SC_NOT_EQUAL )
-                        bOk = !bOk;
                 }
                 else
                 {   // use collator here because data was probably sorted
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index d55a18f..ca21e19 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -70,6 +70,21 @@ struct ScCompare
         }
 };
 
+struct ScCompareOptions
+{
+    ScQueryEntry        aQueryEntry;
+    bool                bRegEx;
+    bool                bMatchWholeCell;
+    bool                bIgnoreCase;
+
+                        ScCompareOptions( ScDocument* pDoc, const ScQueryEntry& rEntry, bool bReg );
+private:
+                        // Not implemented, prevent usage.
+                        ScCompareOptions();
+                        ScCompareOptions( const ScCompareOptions & );
+     ScCompareOptions&  operator=( const ScCompareOptions & );
+};
+
 class ScToken;
 
 #define MAXSTACK      (4096 / sizeof(formula::FormulaToken*))
@@ -356,9 +371,16 @@ void ScChoseJump();
 // Returns true if last jump was executed and result matrix pushed.
 bool JumpMatrix( short nStackLevel );
 
-double CompareFunc( const ScCompare& rComp );
+/** @param pOptions
+        NULL means case sensitivity document option is to be used!
+ */
+double CompareFunc( const ScCompare& rComp, ScCompareOptions* pOptions = NULL );
 double Compare();
-ScMatrixRef CompareMat();
+/** @param pOptions
+        NULL means case sensitivity document option is to be used!
+ */
+ScMatrixRef CompareMat( ScCompareOptions* pOptions = NULL );
+ScMatrixRef QueryMat( ScMatrix* pMat, ScCompareOptions& rOptions );
 void ScEqual();
 void ScNotEqual();
 void ScLess();
diff --git a/sc/source/core/tool/address.cxx b/sc/source/core/tool/address.cxx
index b1f50fe..6d62216 100644
--- a/sc/source/core/tool/address.cxx
+++ b/sc/source/core/tool/address.cxx
@@ -1126,39 +1126,48 @@ lcl_ScAddress_Parse ( const sal_Unicode* p, ScDocument* pDoc, ScAddress& rAddr,
 
 bool ConvertSingleRef( ScDocument* pDoc, const String& rRefString,
                        SCTAB nDefTab, ScRefAddress& rRefAddress,
-                       const ScAddress::Details& rDetails )
+                       const ScAddress::Details& rDetails,
+                       ScAddress::ExternalInfo* pExtInfo /* = NULL */ )
 {
-    ScAddress aAddr( 0, 0, nDefTab );
-    USHORT nRes = lcl_ScAddress_Parse( rRefString.GetBuffer(), pDoc, aAddr, rDetails, NULL );
-    if( nRes & SCA_VALID )
+    bool bRet = false;
+    if (pExtInfo || (ScGlobal::FindUnquoted( rRefString, SC_COMPILER_FILE_TAB_SEP) == STRING_NOTFOUND))
     {
-        rRefAddress.Set( aAddr,
-                ((nRes & SCA_COL_ABSOLUTE) == 0),
-                ((nRes & SCA_ROW_ABSOLUTE) == 0),
-                ((nRes & SCA_TAB_ABSOLUTE) == 0));
-        return TRUE;
+        ScAddress aAddr( 0, 0, nDefTab );
+        USHORT nRes = aAddr.Parse( rRefString, pDoc, rDetails, pExtInfo);
+        if ( nRes & SCA_VALID )
+        {
+            rRefAddress.Set( aAddr,
+                    ((nRes & SCA_COL_ABSOLUTE) == 0),
+                    ((nRes & SCA_ROW_ABSOLUTE) == 0),
+                    ((nRes & SCA_TAB_ABSOLUTE) == 0));
+            bRet = true;
+        }
     }
-    else
-        return FALSE;
+    return bRet;
 }
 
 
 bool ConvertDoubleRef( ScDocument* pDoc, const String& rRefString, SCTAB nDefTab,
                        ScRefAddress& rStartRefAddress, ScRefAddress& rEndRefAddress,
-                       const ScAddress::Details& rDetails )
+                       const ScAddress::Details& rDetails,
+                       ScAddress::ExternalInfo* pExtInfo /* = NULL */ )
 {
-    BOOL bRet = FALSE;
-    // FIXME : This will break for Lotus
-    xub_StrLen nPos = rRefString.Search(':');
-    if (nPos != STRING_NOTFOUND)
+    bool bRet = false;
+    if (pExtInfo || (ScGlobal::FindUnquoted( rRefString, SC_COMPILER_FILE_TAB_SEP) == STRING_NOTFOUND))
     {
-        String aTmp( rRefString );
-        sal_Unicode* p = aTmp.GetBufferAccess();
-        p[ nPos ] = 0;
-        if( ConvertSingleRef( pDoc, p, nDefTab, rStartRefAddress, rDetails ) )
+        ScRange aRange( ScAddress( 0, 0, nDefTab));
+        USHORT nRes = aRange.Parse( rRefString, pDoc, rDetails, pExtInfo);
+        if ( nRes & SCA_VALID )
         {
-            nDefTab = rStartRefAddress.Tab();
-            bRet = ConvertSingleRef( pDoc, p + nPos + 1, nDefTab, rEndRefAddress, rDetails );
+            rStartRefAddress.Set( aRange.aStart,
+                    ((nRes & SCA_COL_ABSOLUTE) == 0),
+                    ((nRes & SCA_ROW_ABSOLUTE) == 0),
+                    ((nRes & SCA_TAB_ABSOLUTE) == 0));
+            rEndRefAddress.Set( aRange.aEnd,
+                    ((nRes & SCA_COL2_ABSOLUTE) == 0),
+                    ((nRes & SCA_ROW2_ABSOLUTE) == 0),
+                    ((nRes & SCA_TAB2_ABSOLUTE) == 0));
+            bRet = true;
         }
     }
     return bRet;
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index 2c52db6..74c8e49 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -1811,9 +1811,11 @@ ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos,ScTokenArra
         aPos( rPos ),
         pCharClass( ScGlobal::pCharClass ),
         mnPredetectedReference(0),
+        mnRangeOpPosInSymbol(-1),
         pConv( pConvOOO_A1 ),
         mbCloseBrackets( true ),
-        mbExtendedErrorDetection( false )
+        mbExtendedErrorDetection( false ),
+        mbRewind( false )
 {
     nMaxTab = pDoc ? pDoc->GetTableCount() - 1 : 0;
 }
@@ -1824,9 +1826,11 @@ ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos)
         aPos( rPos ),
         pCharClass( ScGlobal::pCharClass ),
         mnPredetectedReference(0),
+        mnRangeOpPosInSymbol(-1),
         pConv( pConvOOO_A1 ),
         mbCloseBrackets( true ),
-        mbExtendedErrorDetection( false )
+        mbExtendedErrorDetection( false ),
+        mbRewind( false )
 {
     nMaxTab = pDoc ? pDoc->GetTableCount() - 1 : 0;
 }
@@ -1962,7 +1966,7 @@ xub_StrLen ScCompiler::NextSymbol(bool bInArray)
     sal_Unicode c = *pSrc;
     sal_Unicode cLast = 0;
     bool bQuote = false;
-    bool bRangeOp = false;
+    mnRangeOpPosInSymbol = -1;
     ScanState eState = ssGetChar;
     xub_StrLen nSpaces = 0;
     sal_Unicode cSep = mxSymbols->getSymbol( ocSep).GetChar(0);
@@ -2110,11 +2114,11 @@ Label_MaskStateMachine:
                     else
                         *pSym++ = c;
                 }
-                else if (c == ':' && !bRangeOp)
+                else if (c == ':' && mnRangeOpPosInSymbol < 0)
                 {
                     // One range operator may form Sheet1.A:A, which we need to
                     // pass as one entity to IsReference().
-                    bRangeOp = true;
+                    mnRangeOpPosInSymbol = pSym - &cSymbol[0];
                     if( pSym == &cSymbol[ MAXSTRLEN-1 ] )
                     {
                         SetError(errStringOverflow);
@@ -2409,7 +2413,7 @@ Label_MaskStateMachine:
     {
         nSrcPos = sal::static_int_cast<xub_StrLen>( nSrcPos + nSpaces );
         String aSymbol;
-        bRangeOp = false;
+        mnRangeOpPosInSymbol = -1;
         USHORT nErr = 0;
         do
         {
@@ -2438,9 +2442,9 @@ Label_MaskStateMachine:
                     bi18n = (c == cSheetSep || c == SC_COMPILER_FILE_TAB_SEP);
                 }
                 // One range operator restarts parsing for second reference.
-                if (c == ':' && !bRangeOp)
+                if (c == ':' && mnRangeOpPosInSymbol < 0)
                 {
-                    bRangeOp = true;
+                    mnRangeOpPosInSymbol = aSymbol.Len();
                     bi18n = true;
                 }
                 if ( bi18n )
@@ -2460,6 +2464,14 @@ Label_MaskStateMachine:
         nSrcPos = sal::static_int_cast<xub_StrLen>( pSrc - pStart );
         *pSym = 0;
     }
+    if (mnRangeOpPosInSymbol >= 0 && mnRangeOpPosInSymbol == (pSym-1) - &cSymbol[0])
+    {
+        // This is a trailing range operator, which is nonsense. Will be caught 
+        // in next round.
+        mnRangeOpPosInSymbol = -1;
+        *--pSym = 0;
+        --nSrcPos;
+    }
     if ( bAutoCorrect )
         aCorrectedSymbol = cSymbol;
     if (bAutoIntersection && nSpaces > 1)
@@ -2835,8 +2847,21 @@ BOOL ScCompiler::IsReference( const String& rName )
     // Though the range operator is handled explicitly, when encountering
     // something like Sheet1.A:A we will have to treat it as one entity if it
     // doesn't pass as single cell reference.
-    if (ScGlobal::FindUnquoted( rName, ':') != STRING_NOTFOUND)
-        return IsDoubleReference( rName);
+    if (mnRangeOpPosInSymbol > 0)   // ":foo" would be nonsense
+    {
+        if (IsDoubleReference( rName))
+            return true;
+        // Now try with a symbol up to the range operator, rewind source 
+        // position.
+        sal_Int32 nLen = mnRangeOpPosInSymbol;
+        while (cSymbol[++nLen])
+            ;
+        cSymbol[mnRangeOpPosInSymbol] = 0;
+        nSrcPos -= static_cast<xub_StrLen>(nLen - mnRangeOpPosInSymbol);
+        mnRangeOpPosInSymbol = -1;
+        mbRewind = true;
+        return true;    // end all checks
+    }
     return false;
 }
 
@@ -3551,54 +3576,65 @@ BOOL ScCompiler::NextNewToken( bool bInArray )
     // #42016# Italian ARCTAN.2 resulted in #REF! => IsOpcode() before
     // IsReference().
 
-    const String aOrg( cSymbol );
-
-    if (bAsciiNonAlnum && IsOpCode( aOrg, bInArray ))
-        return true;
-
     String aUpper;
-    bool bAsciiUpper = false;
-    if (bMayBeFuncName)
+
+    do
     {
-        bAsciiUpper = lcl_UpperAsciiOrI18n( aUpper, aOrg, meGrammar);
-        if (IsOpCode( aUpper, bInArray ))
+        mbRewind = false;
+        const String aOrg( cSymbol );
+
+        if (bAsciiNonAlnum && IsOpCode( aOrg, bInArray ))
             return true;
-    }
 
-    // Column 'DM' ("Deutsche Mark", German currency) couldn't be
-    // referred => IsReference() before IsValue().
-    // Preserve case of file names in external references.
-    if (IsReference( aOrg ))
-        return true;
+        aUpper.Erase();
+        bool bAsciiUpper = false;
+        if (bMayBeFuncName)
+        {
+            bAsciiUpper = lcl_UpperAsciiOrI18n( aUpper, aOrg, meGrammar);
+            if (IsOpCode( aUpper, bInArray ))
+                return true;
+        }
+
+        // Column 'DM' ("Deutsche Mark", German currency) couldn't be
+        // referred => IsReference() before IsValue().
+        // Preserve case of file names in external references.
+        if (IsReference( aOrg ))
+        {
+            if (mbRewind)   // Range operator, but no direct reference.
+                continue;   // do; up to range operator.
+            return true;
+        }
 
-    if (!aUpper.Len())
-        bAsciiUpper = lcl_UpperAsciiOrI18n( aUpper, aOrg, meGrammar);
+        if (!aUpper.Len())
+            bAsciiUpper = lcl_UpperAsciiOrI18n( aUpper, aOrg, meGrammar);
 
-    // IsBoolean() before IsValue() to catch inline bools without the kludge
-    //    for inline arrays.
-    if (bAllowBooleans && IsBoolean( aUpper ))
-        return true;
+        // IsBoolean() before IsValue() to catch inline bools without the kludge
+        //    for inline arrays.
+        if (bAllowBooleans && IsBoolean( aUpper ))
+            return true;
 
-    if (IsValue( aUpper ))
-        return true;
+        if (IsValue( aUpper ))
+            return true;
 
-    // User defined names and such do need i18n upper also in ODF.
-    if (bAsciiUpper)
-        aUpper = ScGlobal::pCharClass->upper( aOrg );
+        // User defined names and such do need i18n upper also in ODF.
+        if (bAsciiUpper)
+            aUpper = ScGlobal::pCharClass->upper( aOrg );
 
-    if (IsNamedRange( aUpper ))
-        return true;
-    // Preserve case of file names in external references.
-    if (IsExternalNamedRange( aOrg ))
-        return true;
-    if (IsDBRange( aUpper ))
-        return true;
-    if (IsColRowName( aUpper ))
-        return true;
-    if (bMayBeFuncName && IsMacro( aUpper ))
-        return true;
-    if (bMayBeFuncName && IsOpCode2( aUpper ))
-        return true;
+        if (IsNamedRange( aUpper ))
+            return true;
+        // Preserve case of file names in external references.
+        if (IsExternalNamedRange( aOrg ))
+            return true;
+        if (IsDBRange( aUpper ))
+            return true;
+        if (IsColRowName( aUpper ))
+            return true;
+        if (bMayBeFuncName && IsMacro( aUpper ))
+            return true;
+        if (bMayBeFuncName && IsOpCode2( aUpper ))
+            return true;
+
+    } while (mbRewind);
 
     if ( mbExtendedErrorDetection )
     {
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 0257f63..1007f7e 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -71,6 +71,7 @@
 #include "lookupcache.hxx"
 #include "rangenam.hxx"
 #include "compiler.hxx"
+#include "externalrefmgr.hxx"
 
 #define SC_DOUBLE_MAXVALUE  1.7e307
 
@@ -626,7 +627,20 @@ bool ScInterpreter::JumpMatrix( short nStackLevel )
 }
 
 
-double ScInterpreter::CompareFunc( const ScCompare& rComp )
+ScCompareOptions::ScCompareOptions( ScDocument* pDoc, const ScQueryEntry& rEntry, bool bReg ) :
+    aQueryEntry(rEntry),
+    bRegEx(bReg),
+    bMatchWholeCell(pDoc->GetDocOptions().IsMatchWholeCell()),
+    bIgnoreCase(true)
+{
+    bRegEx = (bRegEx && (aQueryEntry.eOp == SC_EQUAL || aQueryEntry.eOp == SC_NOT_EQUAL));
+    // Interpreter functions usually are case insensitive, except the simple 
+    // comparison operators, for which these options aren't used. Override in 
+    // struct if needed.
+}
+
+
+double ScInterpreter::CompareFunc( const ScCompare& rComp, ScCompareOptions* pOptions )
 {
     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke at sun.com", "ScInterpreter::CompareFunc" );
     // Keep DoubleError if encountered
@@ -698,7 +712,53 @@ double ScInterpreter::CompareFunc( const ScCompare& rComp )
         fRes = 1;   // number is less than string
     else
     {
-        if (pDok->GetDocOptions().IsIgnoreCase())
+        // Both strings.
+        if (pOptions)
+        {
+            // All similar to Sctable::ValidQuery(), *rComp.pVal[1] actually 
+            // is/must be identical to *rEntry.pStr, which is essential for 
+            // regex to work through GetSearchTextPtr().
+            ScQueryEntry& rEntry = pOptions->aQueryEntry;
+            DBG_ASSERT( *rComp.pVal[1] == *rEntry.pStr, "ScInterpreter::CompareFunc: broken options");
+            if (pOptions->bRegEx)
+            {
+                xub_StrLen nStart = 0;
+                xub_StrLen nStop  = rComp.pVal[0]->Len();
+                bool bMatch = rEntry.GetSearchTextPtr( 
+                        !pOptions->bIgnoreCase)->SearchFrwrd( *rComp.pVal[0], 
+                            &nStart, &nStop);
+                if (bMatch && pOptions->bMatchWholeCell && (nStart != 0 || nStop != rComp.pVal[0]->Len()))
+                    bMatch = false;     // RegEx must match entire string.
+                fRes = (bMatch ? 0 : 1);
+            }
+            else if (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL)
+            {
+                ::utl::TransliterationWrapper* pTransliteration = 
+                    (pOptions->bIgnoreCase ? ScGlobal::pTransliteration : 
+                     ScGlobal::pCaseTransliteration);
+                bool bMatch;
+                if (pOptions->bMatchWholeCell)
+                    bMatch = pTransliteration->isEqual( *rComp.pVal[0], *rComp.pVal[1]);
+                else
+                {
+                    String aCell( pTransliteration->transliterate( 
+                                *rComp.pVal[0], ScGlobal::eLnge, 0, 
+                                rComp.pVal[0]->Len(), NULL));
+                    String aQuer( pTransliteration->transliterate( 
+                                *rComp.pVal[1], ScGlobal::eLnge, 0, 
+                                rComp.pVal[1]->Len(), NULL));
+                    bMatch = (aCell.Search( aQuer ) != STRING_NOTFOUND);
+                }
+                fRes = (bMatch ? 0 : 1);
+            }
+            else if (pOptions->bIgnoreCase)
+                fRes = (double) ScGlobal::pCollator->compareString(
+                        *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
+            else
+                fRes = (double) ScGlobal::pCaseCollator->compareString(
+                        *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
+        }
+        else if (pDok->GetDocOptions().IsIgnoreCase())
             fRes = (double) ScGlobal::pCollator->compareString(
                 *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
         else
@@ -763,7 +823,7 @@ double ScInterpreter::Compare()
 }
 
 
-ScMatrixRef ScInterpreter::CompareMat()
+ScMatrixRef ScInterpreter::CompareMat( ScCompareOptions* pOptions )
 {
     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke at sun.com", "ScInterpreter::CompareMat" );
     String aVal1, aVal2;
@@ -855,7 +915,7 @@ ScMatrixRef ScInterpreter::CompareMat()
                                 aComp.bEmpty[i] = FALSE;
                             }
                         }
-                        pResMat->PutDouble( CompareFunc( aComp ), j,k );
+                        pResMat->PutDouble( CompareFunc( aComp, pOptions ), j,k );
                     }
                     else
                         pResMat->PutString( ScGlobal::GetRscString(STR_NO_VALUE), j,k );
@@ -885,7 +945,7 @@ ScMatrixRef ScInterpreter::CompareMat()
                     *aComp.pVal[i] = pMat[i]->GetString(j);
                     aComp.bEmpty[i] = pMat[i]->IsEmpty(j);
                 }
-                pResMat->PutDouble( CompareFunc( aComp ), j );
+                pResMat->PutDouble( CompareFunc( aComp, pOptions ), j );
             }
         }
     }
@@ -894,6 +954,52 @@ ScMatrixRef ScInterpreter::CompareMat()
 }
 
 
+ScMatrixRef ScInterpreter::QueryMat( ScMatrix* pMat, ScCompareOptions& rOptions )
+{
+    short nSaveCurFmtType = nCurFmtType;
+    short nSaveFuncFmtType = nFuncFmtType;
+    PushMatrix( pMat);
+    if (rOptions.aQueryEntry.bQueryByString)
+        PushString( *rOptions.aQueryEntry.pStr);
+    else
+        PushDouble( rOptions.aQueryEntry.nVal);
+    ScMatrixRef pResultMatrix = CompareMat( &rOptions);
+    nCurFmtType = nSaveCurFmtType;
+    nFuncFmtType = nSaveFuncFmtType;
+    if (nGlobalError || !pResultMatrix)
+    {
+        SetError( errIllegalParameter);
+        return pResultMatrix;
+    }
+
+    switch (rOptions.aQueryEntry.eOp)
+    {
+        case SC_EQUAL:
+            pResultMatrix->CompareEqual();
+            break;
+        case SC_LESS:
+            pResultMatrix->CompareLess();
+            break;
+        case SC_GREATER:
+            pResultMatrix->CompareGreater();
+            break;
+        case SC_LESS_EQUAL:
+            pResultMatrix->CompareLessEqual();
+            break;
+        case SC_GREATER_EQUAL:
+            pResultMatrix->CompareGreaterEqual();
+            break;
+        case SC_NOT_EQUAL:
+            pResultMatrix->CompareNotEqual();
+            break;
+        default:
+            SetError( errIllegalArgument);
+            DBG_ERROR1( "ScInterpreter::QueryMat: unhandled comparison operator: %d", (int)rOptions.aQueryEntry.eOp);
+    }
+    return pResultMatrix;
+}
+
+
 void ScInterpreter::ScEqual()
 {
     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke at sun.com", "ScInterpreter::ScEqual" );
@@ -4310,6 +4416,7 @@ void ScInterpreter::ScCountIf()
             SCCOL nCol2;
             SCROW nRow2;
             SCTAB nTab2;
+            ScMatrixRef pQueryMatrix;
             switch ( GetStackType() )
             {
                 case svDoubleRef :
@@ -4326,6 +4433,24 @@ void ScInterpreter::ScCountIf()
                     nRow2 = nRow1;
                     nTab2 = nTab1;
                     break;
+                case svMatrix:
+                    {
+                        pQueryMatrix = PopMatrix();
+                        if (!pQueryMatrix)
+                        {
+                            PushIllegalParameter();
+                            return;
+                        }
+                        nCol1 = 0;
+                        nRow1 = 0;
+                        nTab1 = 0;
+                        SCSIZE nC, nR;
+                        pQueryMatrix->GetDimensions( nC, nR);
+                        nCol2 = static_cast<SCCOL>(nC - 1);
+                        nRow2 = static_cast<SCROW>(nR - 1);
+                        nTab2 = 0;
+                    }
+                    break;
                 default:
                     PushIllegalParameter();
                     return ;
@@ -4367,15 +4492,37 @@ void ScInterpreter::ScCountIf()
                 rParam.nCol1  = nCol1;
                 rParam.nCol2  = nCol2;
                 rEntry.nField = nCol1;
-                ScQueryCellIterator aCellIter(pDok, nTab1, rParam, FALSE);
-                // Entry.nField im Iterator bei Spaltenwechsel weiterschalten
-                aCellIter.SetAdvanceQueryParamEntryField( TRUE );
-                if ( aCellIter.GetFirst() )
+                if (pQueryMatrix)
                 {
-                    do
+                    // Never case-sensitive.
+                    ScCompareOptions aOptions( pDok, rEntry, rParam.bRegExp);
+                    ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions);
+                    if (nGlobalError || !pResultMatrix)
                     {
-                        fSum++;
-                    } while ( aCellIter.GetNext() );
+                        PushIllegalParameter();
+                        return;
+                    }
+
+                    SCSIZE nSize = pResultMatrix->GetElementCount();
+                    for (SCSIZE nIndex = 0; nIndex < nSize; ++nIndex)
+                    {
+                        if (pResultMatrix->IsValue( nIndex) && 
+                                pResultMatrix->GetDouble( nIndex))
+                            ++fSum;
+                    }
+                }
+                else
+                {
+                    ScQueryCellIterator aCellIter(pDok, nTab1, rParam, FALSE);
+                    // Entry.nField im Iterator bei Spaltenwechsel weiterschalten
+                    aCellIter.SetAdvanceQueryParamEntryField( TRUE );
+                    if ( aCellIter.GetFirst() )
+                    {
+                        do
+                        {
+                            fSum++;
+                        } while ( aCellIter.GetNext() );
+                    }
                 }
             }
             else
@@ -4399,6 +4546,7 @@ void ScInterpreter::ScSumIf()
         SCROW nRow3 = 0;
         SCTAB nTab3 = 0;
 
+        ScMatrixRef pSumExtraMatrix;
         bool bSumExtraRange = (nParamCount == 3);
         if (bSumExtraRange)
         {
@@ -4423,6 +4571,10 @@ void ScInterpreter::ScSumIf()
                 case svSingleRef :
                     PopSingleRef( nCol3, nRow3, nTab3 );
                 break;
+                case svMatrix:
+                    pSumExtraMatrix = PopMatrix();
+                    //! nCol3, nRow3, nTab3 remain 0
+                break;
                 default:
                     PushIllegalParameter();
                     return ;
@@ -4498,6 +4650,7 @@ void ScInterpreter::ScSumIf()
             SCCOL nCol2;
             SCROW nRow2;
             SCTAB nTab2;
+            ScMatrixRef pQueryMatrix;
             switch ( GetStackType() )
             {
                 case svRefList :
@@ -4522,13 +4675,31 @@ void ScInterpreter::ScSumIf()
                     nRow2 = nRow1;
                     nTab2 = nTab1;
                     break;
+                case svMatrix:
+                    {
+                        pQueryMatrix = PopMatrix();
+                        if (!pQueryMatrix)
+                        {
+                            PushIllegalParameter();
+                            return;
+                        }
+                        nCol1 = 0;
+                        nRow1 = 0;
+                        nTab1 = 0;
+                        SCSIZE nC, nR;
+                        pQueryMatrix->GetDimensions( nC, nR);
+                        nCol2 = static_cast<SCCOL>(nC - 1);
+                        nRow2 = static_cast<SCROW>(nR - 1);
+                        nTab2 = 0;
+                    }
+                    break;
                 default:
                     PushIllegalParameter();
                     return ;
             }
             if ( nTab1 != nTab2 )
             {
-                PushIllegalParameter();
+                PushIllegalArgument();
                 return;
             }
 
@@ -4544,15 +4715,29 @@ void ScInterpreter::ScSumIf()
                 // instead of the result range.
                 SCCOL nColDelta = nCol2 - nCol1;
                 SCROW nRowDelta = nRow2 - nRow1;
-                if (nCol3 + nColDelta > MAXCOL)
+                SCCOL nMaxCol;
+                SCROW nMaxRow;
+                if (pSumExtraMatrix)
                 {
-                    SCCOL nNewDelta = MAXCOL - nCol3;
+                    SCSIZE nC, nR;
+                    pSumExtraMatrix->GetDimensions( nC, nR);
+                    nMaxCol = static_cast<SCCOL>(nC - 1);
+                    nMaxRow = static_cast<SCROW>(nR - 1);
+                }
+                else
+                {
+                    nMaxCol = MAXCOL;
+                    nMaxRow = MAXROW;
+                }
+                if (nCol3 + nColDelta > nMaxCol)
+                {
+                    SCCOL nNewDelta = nMaxCol - nCol3;
                     nCol2 = nCol1 + nNewDelta;
                 }
 
-                if (nRow3 + nRowDelta > MAXROW)
+                if (nRow3 + nRowDelta > nMaxRow)
                 {
-                    SCROW nNewDelta = MAXROW - nRow3;
+                    SCROW nNewDelta = nMaxRow - nRow3;
                     nRow2 = nRow1 + nNewDelta;
                 }
             }
@@ -4592,30 +4777,119 @@ void ScInterpreter::ScSumIf()
                 rParam.nCol1  = nCol1;
                 rParam.nCol2  = nCol2;
                 rEntry.nField = nCol1;
-                SCCOL nColDiff = nCol3 - nCol1;
-                SCROW nRowDiff = nRow3 - nRow1;
-                ScQueryCellIterator aCellIter(pDok, nTab1, rParam, FALSE);
-                // Increment Entry.nField in iterator when switching to next column.
-                aCellIter.SetAdvanceQueryParamEntryField( TRUE );
-                if ( aCellIter.GetFirst() )
+                SCsCOL nColDiff = nCol3 - nCol1;
+                SCsROW nRowDiff = nRow3 - nRow1;
+                if (pQueryMatrix)
                 {
-                    do
+                    // Never case-sensitive.
+                    ScCompareOptions aOptions( pDok, rEntry, rParam.bRegExp);
+                    ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions);
+                    if (nGlobalError || !pResultMatrix)
                     {
-                        aAdr.SetCol( aCellIter.GetCol() + nColDiff);
-                        aAdr.SetRow( aCellIter.GetRow() + nRowDiff);
-                        ScBaseCell* pCell = GetCell( aAdr );
-                        if ( HasCellValueData(pCell) )
+                        PushIllegalParameter();
+                        return;
+                    }
+
+                    if (pSumExtraMatrix)
+                    {
+                        for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
                         {
-                            fVal = GetCellValue( aAdr, pCell );
-                            if ( bNull && fVal != 0.0 )
+                            for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
                             {
-                                bNull = FALSE;
-                                fMem = fVal;
+                                if (pResultMatrix->IsValue( nCol, nRow) && 
+                                        pResultMatrix->GetDouble( nCol, nRow))
+                                {
+                                    SCSIZE nC = nCol + nColDiff;
+                                    SCSIZE nR = nRow + nRowDiff;
+                                    if (pSumExtraMatrix->IsValue( nC, nR))
+                                    {
+                                        fVal = pSumExtraMatrix->GetDouble( nC, nR);
+                                        if ( bNull && fVal != 0.0 )
+                                        {
+                                            bNull = FALSE;
+                                            fMem = fVal;
+                                        }
+                                        else
+                                            fSum += fVal;
+                                    }
+                                }
                             }
-                            else
-                                fSum += fVal;
                         }
-                    } while ( aCellIter.GetNext() );
+                    }
+                    else
+                    {
+                        for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+                        {
+                            for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
+                            {
+                                if (pResultMatrix->GetDouble( nCol, nRow))
+                                {
+                                    aAdr.SetCol( nCol + nColDiff);
+                                    aAdr.SetRow( nRow + nRowDiff);
+                                    ScBaseCell* pCell = GetCell( aAdr );
+                                    if ( HasCellValueData(pCell) )
+                                    {
+                                        fVal = GetCellValue( aAdr, pCell );
+                                        if ( bNull && fVal != 0.0 )
+                                        {
+                                            bNull = FALSE;
+                                            fMem = fVal;
+                                        }
+                                        else
+                                            fSum += fVal;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                else
+                {
+                    ScQueryCellIterator aCellIter(pDok, nTab1, rParam, FALSE);
+                    // Increment Entry.nField in iterator when switching to next column.
+                    aCellIter.SetAdvanceQueryParamEntryField( TRUE );
+                    if ( aCellIter.GetFirst() )
+                    {
+                        if (pSumExtraMatrix)
+                        {
+                            do
+                            {
+                                SCSIZE nC = aCellIter.GetCol() + nColDiff;
+                                SCSIZE nR = aCellIter.GetRow() + nRowDiff;
+                                if (pSumExtraMatrix->IsValue( nC, nR))
+                                {
+                                    fVal = pSumExtraMatrix->GetDouble( nC, nR);
+                                    if ( bNull && fVal != 0.0 )
+                                    {
+                                        bNull = FALSE;
+                                        fMem = fVal;
+                                    }
+                                    else
+                                        fSum += fVal;
+                                }
+                            } while ( aCellIter.GetNext() );
+                        }
+                        else
+                        {
+                            do
+                            {
+                                aAdr.SetCol( aCellIter.GetCol() + nColDiff);
+                                aAdr.SetRow( aCellIter.GetRow() + nRowDiff);
+                                ScBaseCell* pCell = GetCell( aAdr );
+                                if ( HasCellValueData(pCell) )
+                                {
+                                    fVal = GetCellValue( aAdr, pCell );
+                                    if ( bNull && fVal != 0.0 )
+                                    {
+                                        bNull = FALSE;
+                                        fMem = fVal;
+                                    }
+                                    else
+                                        fSum += fVal;
+                                }
+                            } while ( aCellIter.GetNext() );
+                        }
+                    }
                 }
             }
             else
@@ -5762,6 +6036,52 @@ void ScInterpreter::ScDBVarP()
 }
 
 
+ScTokenArray* lcl_CreateExternalRefTokenArray( const ScAddress& rPos, ScDocument* pDoc, 
+        const ScAddress::ExternalInfo& rExtInfo, const ScRefAddress& rRefAd1, 
+        const ScRefAddress* pRefAd2 )
+{
+    ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
+    size_t nSheets = 1;
+    const String* pRealTab = pRefMgr->getRealTableName( rExtInfo.mnFileId, rExtInfo.maTabName);
+    ScTokenArray* pTokenArray = new ScTokenArray;
+    if (pRefAd2)
+    {
+        ScComplexRefData aRef;
+        aRef.InitRangeRel( ScRange( rRefAd1.GetAddress(), pRefAd2->GetAddress()), rPos);
+        aRef.Ref1.SetColRel( rRefAd1.IsRelCol());
+        aRef.Ref1.SetRowRel( rRefAd1.IsRelRow());
+        aRef.Ref1.SetTabRel( rRefAd1.IsRelTab());
+        aRef.Ref1.SetFlag3D( true);
+        aRef.Ref2.SetColRel( pRefAd2->IsRelCol());
+        aRef.Ref2.SetRowRel( pRefAd2->IsRelRow());
+        aRef.Ref2.SetTabRel( pRefAd2->IsRelTab());
+        nSheets = aRef.Ref2.nTab - aRef.Ref1.nTab + 1;
+        aRef.Ref2.SetFlag3D( nSheets > 1 );
+        pTokenArray->AddExternalDoubleReference( rExtInfo.mnFileId,
+                (pRealTab ? *pRealTab : rExtInfo.maTabName), aRef);
+    }
+    else
+    {
+        ScSingleRefData aRef;
+        aRef.InitAddressRel( rRefAd1.GetAddress(), rPos);
+        aRef.SetColRel( rRefAd1.IsRelCol());
+        aRef.SetRowRel( rRefAd1.IsRelRow());
+        aRef.SetTabRel( rRefAd1.IsRelTab());
+        aRef.SetFlag3D( true);
+        pTokenArray->AddExternalSingleReference( rExtInfo.mnFileId,
+                (pRealTab ? *pRealTab : rExtInfo.maTabName), aRef);
+    }
+    // The indirect usage of the external table can't be detected during the 
+    // store-to-file cycle, mark it as permanently referenced so it gets stored 
+    // even if not directly referenced anywhere.
+    pRefMgr->setCacheTableReferencedPermanently( rExtInfo.mnFileId, 
+            rExtInfo.maTabName, nSheets);
+    ScCompiler aComp( pDoc, rPos, *pTokenArray);
+    aComp.CompileTokenArray();
+    return pTokenArray;
+}
+
+
 void ScInterpreter::ScIndirect()
 {
     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke at sun.com", "ScInterpreter::ScIndirect" );
@@ -5780,15 +6100,46 @@ void ScInterpreter::ScIndirect()
         SCTAB nTab = aPos.Tab();
         String sRefStr( GetString() );
         ScRefAddress aRefAd, aRefAd2;
-        if ( ConvertDoubleRef( pDok, sRefStr, nTab, aRefAd, aRefAd2, aDetails) ||
+        ScAddress::ExternalInfo aExtInfo;
+        if ( ConvertDoubleRef( pDok, sRefStr, nTab, aRefAd, aRefAd2, aDetails, &aExtInfo) ||
                 (bTryXlA1 && ConvertDoubleRef( pDok, sRefStr, nTab, aRefAd,
-                                               aRefAd2, aDetailsXlA1)))
-            PushDoubleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab(),
-                    aRefAd2.Col(), aRefAd2.Row(), aRefAd2.Tab() );
-        else if ( ConvertSingleRef ( pDok, sRefStr, nTab, aRefAd, aDetails) ||
+                                               aRefAd2, aDetailsXlA1, &aExtInfo)))
+        {
+            if (aExtInfo.mbExternal)
+            {
+                /* TODO: future versions should implement a proper subroutine 
+                 * token. This procedure here is a minimally invasive fix for 
+                 * #i101645# in OOo3.1.1 */
+                // Push a subroutine on the instruction code stack that 
+                // resolves the external reference as the next instruction.
+                aCode.Push( lcl_CreateExternalRefTokenArray( aPos, pDok, 
+                            aExtInfo, aRefAd, &aRefAd2));
+                // Signal subroutine call to interpreter.
+                PushTempToken( new FormulaUnknownToken( ocCall));
+            }
+            else
+                PushDoubleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab(),
+                        aRefAd2.Col(), aRefAd2.Row(), aRefAd2.Tab() );
+        }
+        else if ( ConvertSingleRef ( pDok, sRefStr, nTab, aRefAd, aDetails, &aExtInfo) ||
                 (bTryXlA1 && ConvertSingleRef ( pDok, sRefStr, nTab, aRefAd,
-                                                aDetailsXlA1)))
-            PushSingleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab() );
+                                                aDetailsXlA1, &aExtInfo)))
+        {
+            if (aExtInfo.mbExternal)
+            {
+                /* TODO: future versions should implement a proper subroutine 
+                 * token. This procedure here is a minimally invasive fix for 
+                 * #i101645# in OOo3.1.1 */
+                // Push a subroutine on the instruction code stack that 
+                // resolves the external reference as the next instruction.
+                aCode.Push( lcl_CreateExternalRefTokenArray( aPos, pDok, 
+                            aExtInfo, aRefAd, NULL));
+                // Signal subroutine call to interpreter.
+                PushTempToken( new FormulaUnknownToken( ocCall));
+            }
+            else
+                PushSingleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab() );
+        }
         else
         {
             do
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index cd2fccc..cf8dc7e 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -3812,6 +3812,15 @@ StackVar ScInterpreter::Interpret()
                 default : PushError( errUnknownOpCode);                 break;
             }
 
+            // If the function signalled that it pushed a subroutine on the 
+            // instruction code stack instead of a result, continue with  
+            // execution of the subroutine.
+            if (sp > nStackBase && pStack[sp-1]->GetOpCode() == ocCall)
+            {
+                Pop();
+                continue;   // while( ( pCur = aCode.Next() ) != NULL  ...
+            }
+
             // Remember result matrix in case it could be reused.
             if (pTokenMatrixMap && sp && GetStackType() == svMatrix)
                 pTokenMatrixMap->insert( ScTokenMatrixMap::value_type( pCur,
diff --git a/sc/source/core/tool/progress.cxx b/sc/source/core/tool/progress.cxx
index 66e1391..3d0e62c 100644
--- a/sc/source/core/tool/progress.cxx
+++ b/sc/source/core/tool/progress.cxx
@@ -162,7 +162,7 @@ void ScProgress::CreateInterpretProgress( ScDocument* pDoc, BOOL bWait )
             if ( !pGlobalProgress )
                 pInterpretProgress = new ScProgress( pDoc->GetDocumentShell(),
                     ScGlobal::GetRscString( STR_PROGRESS_CALCULATING ),
-                    pDoc->GetFormulaCodeInTree(), FALSE, bWait );
+                    pDoc->GetFormulaCodeInTree()/MIN_NO_CODES_PER_PROGRESS_UPDATE, FALSE, bWait );
             pInterpretDoc = pDoc;
         }
     }
diff --git a/sc/source/core/tool/reftokenhelper.cxx b/sc/source/core/tool/reftokenhelper.cxx
index 0e07819..ed196e0 100644
--- a/sc/source/core/tool/reftokenhelper.cxx
+++ b/sc/source/core/tool/reftokenhelper.cxx
@@ -54,8 +54,9 @@ void ScRefTokenHelper::compileRangeRepresentation(
     const sal_Unicode cSep = ';';
     const sal_Unicode cQuote = '\'';
 
+    bool bFailure = false;
     sal_Int32 nOffset = 0;
-    while (nOffset >= 0)
+    while (nOffset >= 0 && !bFailure)
     {
         OUString aToken;
         ScRangeStringConverter::GetTokenByOffset(aToken, rRangeStr, nOffset, cSep, cQuote);
@@ -66,14 +67,49 @@ void ScRefTokenHelper::compileRangeRepresentation(
         aCompiler.SetGrammar(eGrammar);
         auto_ptr<ScTokenArray> pArray(aCompiler.CompileString(aToken));
 
-        // There should only be one reference per range token.
-        pArray->Reset();
-        FormulaToken* p = pArray->GetNextReference();
-        if (!p)
-            continue;
+        // There MUST be exactly one reference per range token and nothing 
+        // else, and it MUST be a valid reference, not some #REF!
+        USHORT nLen = pArray->GetLen();
+        if (!nLen)
+            continue;   // Should a missing range really be allowed?
+        if (nLen != 1)
+            bFailure = true;
+        else
+        {
+            pArray->Reset();
+            const FormulaToken* p = pArray->GetNextReference();
+            if (!p)
+                bFailure = true;
+            else
+            {
+                const ScToken* pT = static_cast<const ScToken*>(p);
+                switch (pT->GetType())
+                {
+                    case svSingleRef:
+                        if (!pT->GetSingleRef().Valid())
+                            bFailure = true;
+                        break;
+                    case svDoubleRef:
+                        if (!pT->GetDoubleRef().Valid())
+                            bFailure = true;
+                        break;
+                    case svExternalSingleRef:
+                        if (!pT->GetSingleRef().ValidExternal())
+                            bFailure = true;
+                        break;
+                    case svExternalDoubleRef:
+                        if (!pT->GetDoubleRef().ValidExternal())
+                            bFailure = true;
+                        break;
+                    default:
+                        ;
+                }
+                if (!bFailure)
+                    rRefTokens.push_back(
+                            ScSharedTokenRef(static_cast<ScToken*>(p->Clone())));
+            }
+        }
 
-        rRefTokens.push_back(
-            ScSharedTokenRef(static_cast<ScToken*>(p->Clone())));
 #if 0
         switch (p->GetType())
         {
@@ -93,7 +129,10 @@ void ScRefTokenHelper::compileRangeRepresentation(
                 ;
         }
 #endif
+
     }
+    if (bFailure)
+        rRefTokens.clear();
 }
 
 bool ScRefTokenHelper::getRangeFromToken(ScRange& rRange, const ScSharedTokenRef& pToken, bool bExternal)
diff --git a/sc/source/filter/excel/excimp8.cxx b/sc/source/filter/excel/excimp8.cxx
index 59545af..3e2bf21 100644
--- a/sc/source/filter/excel/excimp8.cxx
+++ b/sc/source/filter/excel/excimp8.cxx
@@ -427,6 +427,38 @@ void XclImpAutoFilterData::InsertQueryParam()
     }
 }
 
+static void ExcelQueryToOooQuery( ScQueryEntry& rEntry )
+{
+    if( ( rEntry.eOp != SC_EQUAL && rEntry.eOp != SC_NOT_EQUAL ) || rEntry.pStr == NULL )
+        return;
+    else
+    {
+        xub_StrLen nLen = rEntry.pStr->Len();
+        sal_Unicode nStart = rEntry.pStr->GetChar( 0 );
+        sal_Unicode nEnd   = rEntry.pStr->GetChar( nLen-1 );
+        if( nLen >2 && nStart == '*' && nEnd == '*' )
+        {
+            rEntry.pStr->Erase( nLen-1, 1 );
+            rEntry.pStr->Erase( 0, 1 );
+            rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_CONTAINS : SC_DOES_NOT_CONTAIN;
+        }
+        else if( nLen > 1 && nStart == '*' && nEnd != '*' )
+        {
+            rEntry.pStr->Erase( 0, 1 );
+            rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_ENDS_WITH : SC_DOES_NOT_END_WITH;
+        }
+        else if( nLen > 1 && nStart != '*' && nEnd == '*' )
+        {
+            rEntry.pStr->Erase( nLen-1, 1 );
+            rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_BEGINS_WITH : SC_DOES_NOT_BEGIN_WITH;
+        }
+        else if( nLen == 2 && nStart == '*' && nEnd == '*' )
+        {
+            rEntry.pStr->Erase( 0, 1 );
+        }
+    }
+}
+
 void XclImpAutoFilterData::ReadAutoFilter( XclImpStream& rStrm )
 {
     UINT16 nCol, nFlags;
@@ -464,14 +496,14 @@ void XclImpAutoFilterData::ReadAutoFilter( XclImpStream& rStrm )
         BOOL	bIgnore;
 
         UINT8	nStrLen[ 2 ]	= { 0, 0 };
-        String*	pEntryStr[ 2 ]	= { NULL, NULL };
+        ScQueryEntry *pQueryEntries[ 2 ] = { NULL, NULL };
 
         for( nE = 0; nE < 2; nE++ )
         {
             if( nFirstEmpty < nCount )
             {
                 ScQueryEntry& aEntry = aParam.GetEntry( nFirstEmpty );
-                pEntryStr[ nE ] = aEntry.pStr;
+                pQueryEntries[ nE ] = &aEntry;
                 bIgnore = FALSE;
 
                 rStrm >> nType >> nOper;
@@ -559,8 +591,12 @@ void XclImpAutoFilterData::ReadAutoFilter( XclImpStream& rStrm )
         }
 
         for( nE = 0; nE < 2; nE++ )
-            if( nStrLen[ nE ] && pEntryStr[ nE ] )
-                pEntryStr[ nE ]->Assign( rStrm.ReadUniString( nStrLen[ nE ] ) );
+            if( nStrLen[ nE ] && pQueryEntries[ nE ] )
+            {
+                pQueryEntries[ nE ]->pStr->Assign ( rStrm.ReadUniString( nStrLen[ nE ] ) );
+                ExcelQueryToOooQuery( *pQueryEntries[ nE ] );
+            }
+                
     }
 }
 
diff --git a/sc/source/filter/excel/excrecds.cxx b/sc/source/filter/excel/excrecds.cxx
index a2158ee..4c04725 100644
--- a/sc/source/filter/excel/excrecds.cxx
+++ b/sc/source/filter/excel/excrecds.cxx
@@ -724,7 +724,31 @@ BOOL XclExpAutofilter::AddEntry( const ScQueryEntry& rEntry )
     String	sText;
 
     if( rEntry.pStr )
+    {
         sText.Assign( *rEntry.pStr );
+        switch( rEntry.eOp )
+        {
+            case SC_CONTAINS:
+            case SC_DOES_NOT_CONTAIN:
+            {
+                sText.InsertAscii( "*" , 0 );
+                sText.AppendAscii( "*" );
+            }
+            break;
+            case SC_BEGINS_WITH:
+            case SC_DOES_NOT_BEGIN_WITH:
+                sText.AppendAscii( "*" );
+            break;
+            case SC_ENDS_WITH:
+            case SC_DOES_NOT_END_WITH:
+                sText.InsertAscii( "*" , 0 );
+            break;
+            default:
+            {
+                //nothing
+            }
+        }
+    }
 
     BOOL bLen = sText.Len() > 0;
 
@@ -784,6 +808,14 @@ BOOL XclExpAutofilter::AddEntry( const ScQueryEntry& rEntry )
                     case SC_LESS_EQUAL:		nOper = EXC_AFOPER_LESSEQUAL;		break;
                     case SC_GREATER_EQUAL:	nOper = EXC_AFOPER_GREATEREQUAL;	break;
                     case SC_NOT_EQUAL:		nOper = EXC_AFOPER_NOTEQUAL;		break;
+                    case SC_CONTAINS:
+                    case SC_BEGINS_WITH:
+                    case SC_ENDS_WITH:
+                                            nOper = EXC_AFOPER_EQUAL;           break;
+                    case SC_DOES_NOT_CONTAIN:
+                    case SC_DOES_NOT_BEGIN_WITH:
+                    case SC_DOES_NOT_END_WITH:
+                                            nOper = EXC_AFOPER_NOTEQUAL;        break;
                     default:;
                 }
                 bConflict = !AddCondition( rEntry.eConnect, nType, nOper, fVal, pText );
diff --git a/sc/source/filter/xml/XMLExportDatabaseRanges.cxx b/sc/source/filter/xml/XMLExportDatabaseRanges.cxx
index ea43436..30df39f 100644
--- a/sc/source/filter/xml/XMLExportDatabaseRanges.cxx
+++ b/sc/source/filter/xml/XMLExportDatabaseRanges.cxx
@@ -203,44 +203,56 @@ void ScXMLExportDatabaseRanges::WriteImportDescriptor(const uno::Sequence <beans
     }
 }
 
-rtl::OUString ScXMLExportDatabaseRanges::getOperatorXML(const sheet::FilterOperator aFilterOperator, const sal_Bool bUseRegularExpressions) const
+rtl::OUString ScXMLExportDatabaseRanges::getOperatorXML(const long aFilterOperator, const sal_Bool bUseRegularExpressions) const
 {
     switch (aFilterOperator)
     {
-        case sheet::FilterOperator_EQUAL :
+        case sheet::FilterOperator2::EQUAL :
         {
             if (bUseRegularExpressions)
                 return GetXMLToken(XML_MATCH);
             else
                 return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("="));
         }
-        case sheet::FilterOperator_NOT_EQUAL :
+        case sheet::FilterOperator2::NOT_EQUAL :
         {
             if (bUseRegularExpressions)
                 return GetXMLToken(XML_NOMATCH);
             else
                 return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("!="));
         }
-        case sheet::FilterOperator_BOTTOM_PERCENT :
+        case sheet::FilterOperator2::BOTTOM_PERCENT :
             return GetXMLToken(XML_BOTTOM_PERCENT);
-        case sheet::FilterOperator_BOTTOM_VALUES :
+        case sheet::FilterOperator2::BOTTOM_VALUES :
             return GetXMLToken(XML_BOTTOM_VALUES);
-        case sheet::FilterOperator_EMPTY :
+        case sheet::FilterOperator2::EMPTY :
             return GetXMLToken(XML_EMPTY);
-        case sheet::FilterOperator_GREATER :
+        case sheet::FilterOperator2::GREATER :
             return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">"));
-        case sheet::FilterOperator_GREATER_EQUAL :
+        case sheet::FilterOperator2::GREATER_EQUAL :
             return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">="));
-        case sheet::FilterOperator_LESS :
+        case sheet::FilterOperator2::LESS :
             return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<"));
-        case sheet::FilterOperator_LESS_EQUAL :
+        case sheet::FilterOperator2::LESS_EQUAL :
             return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<="));
-        case sheet::FilterOperator_NOT_EMPTY :
+        case sheet::FilterOperator2::NOT_EMPTY :
             return GetXMLToken(XML_NOEMPTY);
-        case sheet::FilterOperator_TOP_PERCENT :
+        case sheet::FilterOperator2::TOP_PERCENT :
             return GetXMLToken(XML_TOP_PERCENT);
-        case sheet::FilterOperator_TOP_VALUES :
+        case sheet::FilterOperator2::TOP_VALUES :
             return GetXMLToken(XML_TOP_VALUES);
+        case sheet::FilterOperator2::CONTAINS :
+            return GetXMLToken(XML_CONTAINS);
+        case sheet::FilterOperator2::DOES_NOT_CONTAIN :
+            return GetXMLToken(XML_DOES_NOT_CONTAIN);
+        case sheet::FilterOperator2::BEGINS_WITH :
+            return GetXMLToken(XML_BEGINS_WITH);
+        case sheet::FilterOperator2::DOES_NOT_BEGIN_WITH :
+            return GetXMLToken(XML_DOES_NOT_BEGIN_WITH);
+        case sheet::FilterOperator2::ENDS_WITH :
+            return GetXMLToken(XML_ENDS_WITH);
+        case sheet::FilterOperator2::DOES_NOT_END_WITH :
+            return GetXMLToken(XML_DOES_NOT_END_WITH);
         default:
         {
             // added to avoid warnings
@@ -249,7 +261,7 @@ rtl::OUString ScXMLExportDatabaseRanges::getOperatorXML(const sheet::FilterOpera
     return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("="));
 }
 
-void ScXMLExportDatabaseRanges::WriteCondition(const sheet::TableFilterField& aFilterField, sal_Bool bIsCaseSensitive, sal_Bool bUseRegularExpressions)
+void ScXMLExportDatabaseRanges::WriteCondition(const sheet::TableFilterField2& aFilterField, sal_Bool bIsCaseSensitive, sal_Bool bUseRegularExpressions)
 {
     rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FIELD_NUMBER, rtl::OUString::valueOf(aFilterField.Field));
     if (bIsCaseSensitive)
@@ -267,9 +279,9 @@ void ScXMLExportDatabaseRanges::WriteCondition(const sheet::TableFilterField& aF
     SvXMLElementExport aElemC(rExport, XML_NAMESPACE_TABLE, XML_FILTER_CONDITION, sal_True, sal_True);
 }
 
-void ScXMLExportDatabaseRanges::WriteFilterDescriptor(const uno::Reference <sheet::XSheetFilterDescriptor>& xSheetFilterDescriptor, const rtl::OUString sDatabaseRangeName)
+void ScXMLExportDatabaseRanges::WriteFilterDescriptor(const uno::Reference <sheet::XSheetFilterDescriptor2>& xSheetFilterDescriptor, const rtl::OUString sDatabaseRangeName)
 {
-    uno::Sequence <sheet::TableFilterField> aTableFilterFields(xSheetFilterDescriptor->getFilterFields());
+    uno::Sequence< sheet::TableFilterField2 > aTableFilterFields( xSheetFilterDescriptor->getFilterFields2() );
     sal_Int32 nTableFilterFields = aTableFilterFields.getLength();
     if (nTableFilterFields > 0)
     {
@@ -336,7 +348,7 @@ void ScXMLExportDatabaseRanges::WriteFilterDescriptor(const uno::Reference <shee
             else
             {
                 SvXMLElementExport aElemC(rExport, XML_NAMESPACE_TABLE, XML_FILTER_OR, sal_True, sal_True);
-                sheet::TableFilterField aPrevFilterField = aTableFilterFields[0];
+                sheet::TableFilterField2 aPrevFilterField = aTableFilterFields[0];
                 sheet::FilterConnection aConnection = aTableFilterFields[1].Connection;
                 sal_Bool bOpenAndElement;
                 rtl::OUString aName = rExport.GetNamespaceMap().GetQNameByKey(XML_NAMESPACE_TABLE, GetXMLToken(XML_FILTER_AND));
@@ -632,7 +644,9 @@ void ScXMLExportDatabaseRanges::WriteDatabaseRanges(const com::sun::star::uno::R
                                 if (::cppu::any2bool(xPropertySetDatabaseRange->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_STRIPDAT)))))
                                     rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_HAS_PERSISTENT_DATA, XML_FALSE);
                             }
-                            uno::Reference <sheet::XSheetFilterDescriptor> xSheetFilterDescriptor(xDatabaseRange->getFilterDescriptor());
+                            
+                            uno::Reference< sheet::XSheetFilterDescriptor2 > xSheetFilterDescriptor(
+                                    xDatabaseRange->getFilterDescriptor(), uno::UNO_QUERY );
                             uno::Sequence <beans::PropertyValue> aSortProperties(xDatabaseRange->getSortDescriptor());
                             if (xSheetFilterDescriptor.is())
                             {
diff --git a/sc/source/filter/xml/XMLExportDatabaseRanges.hxx b/sc/source/filter/xml/XMLExportDatabaseRanges.hxx
index 123776f..d451cb7 100644
--- a/sc/source/filter/xml/XMLExportDatabaseRanges.hxx
+++ b/sc/source/filter/xml/XMLExportDatabaseRanges.hxx
@@ -33,9 +33,9 @@
 
 #include <com/sun/star/uno/Sequence.h>
 #include <com/sun/star/beans/PropertyValue.hpp>
-#include <com/sun/star/sheet/FilterOperator.hpp>
-#include <com/sun/star/sheet/TableFilterField.hpp>
-#include <com/sun/star/sheet/XSheetFilterDescriptor.hpp>
+#include <com/sun/star/sheet/FilterOperator2.hpp>
+#include <com/sun/star/sheet/TableFilterField2.hpp>
+#include <com/sun/star/sheet/XSheetFilterDescriptor2.hpp>
 #include <com/sun/star/sheet/XSubTotalDescriptor.hpp>
 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
 
@@ -49,9 +49,9 @@ class ScXMLExportDatabaseRanges
     ScDocument*		pDoc;
 
     void WriteImportDescriptor(const com::sun::star::uno::Sequence <com::sun::star::beans::PropertyValue> aImportDescriptor);
-    rtl::OUString getOperatorXML(const com::sun::star::sheet::FilterOperator aFilterOperator, const sal_Bool bUseRegularExpressions) const;
-    void WriteCondition(const com::sun::star::sheet::TableFilterField& aFilterField, sal_Bool bIsCaseSensitive, sal_Bool bUseRegularExpressions);
-    void WriteFilterDescriptor(const com::sun::star::uno::Reference <com::sun::star::sheet::XSheetFilterDescriptor>& xSheetFilterDescriptor, const rtl::OUString sDatabaseRangeName);
+    rtl::OUString getOperatorXML(const long aFilterOperator, const sal_Bool bUseRegularExpressions) const;
+    void WriteCondition(const com::sun::star::sheet::TableFilterField2& aFilterField, sal_Bool bIsCaseSensitive, sal_Bool bUseRegularExpressions);
+    void WriteFilterDescriptor(const com::sun::star::uno::Reference <com::sun::star::sheet::XSheetFilterDescriptor2>& xSheetFilterDescriptor, const rtl::OUString sDatabaseRangeName);
     void WriteSortDescriptor(const com::sun::star::uno::Sequence <com::sun::star::beans::PropertyValue> aSortProperties);
     void WriteSubTotalDescriptor(const com::sun::star::uno::Reference <com::sun::star::sheet::XSubTotalDescriptor> xSubTotalDescriptor, const rtl::OUString sDatabaseRangeName);
 public:
diff --git a/sc/source/filter/xml/xmldrani.cxx b/sc/source/filter/xml/xmldrani.cxx
index 382f1d7..558860e 100644
--- a/sc/source/filter/xml/xmldrani.cxx
+++ b/sc/source/filter/xml/xmldrani.cxx
@@ -381,7 +381,8 @@ void ScXMLDatabaseRangeContext::EndElement()
 
                                 pDBData->SetSortParam(aSortParam);
                             }
-                            uno::Reference <sheet::XSheetFilterDescriptor> xSheetFilterDescriptor(xDatabaseRange->getFilterDescriptor());
+                            uno::Reference< sheet::XSheetFilterDescriptor2 > xSheetFilterDescriptor(
+                                    xDatabaseRange->getFilterDescriptor(), uno::UNO_QUERY );
                             if (xSheetFilterDescriptor.is())
                             {
                                 uno::Reference <beans::XPropertySet> xFilterPropertySet (xSheetFilterDescriptor, uno::UNO_QUERY);
@@ -396,7 +397,7 @@ void ScXMLDatabaseRangeContext::EndElement()
                                     xFilterPropertySet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_USEREGEX)), uno::makeAny(bFilterUseRegularExpressions));
                                     xFilterPropertySet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_OUTPOS)), uno::makeAny(aFilterOutputPosition));
                                 }
-                                xSheetFilterDescriptor->setFilterFields(aFilterFields);
+                                xSheetFilterDescriptor->setFilterFields2(aFilterFields);
                                 if (bFilterConditionSourceRange)
                                 {
                                     ScRange aAdvSource;
diff --git a/sc/source/filter/xml/xmldrani.hxx b/sc/source/filter/xml/xmldrani.hxx
index d1443d7..16b22b7 100644
--- a/sc/source/filter/xml/xmldrani.hxx
+++ b/sc/source/filter/xml/xmldrani.hxx
@@ -36,7 +36,7 @@
 #include <com/sun/star/sheet/SubTotalColumn.hpp>
 #include <com/sun/star/beans/XPropertySet.hpp>
 #include <com/sun/star/beans/PropertyValue.hpp>
-#include <com/sun/star/sheet/TableFilterField.hpp>
+#include <com/sun/star/sheet/TableFilterField2.hpp>
 #include <com/sun/star/table/CellAddress.hpp>
 #include <com/sun/star/table/CellRangeAddress.hpp>
 #include <com/sun/star/table/TableOrientation.hpp>
@@ -79,7 +79,7 @@ class ScXMLDatabaseRangeContext : public SvXMLImportContext
     rtl::OUString	sDatabaseName;
     rtl::OUString	sSourceObject;
     com::sun::star::uno::Sequence <com::sun::star::beans::PropertyValue> aSortSequence;
-    com::sun::star::uno::Sequence <com::sun::star::sheet::TableFilterField> aFilterFields;
+    com::sun::star::uno::Sequence <com::sun::star::sheet::TableFilterField2> aFilterFields;
     std::vector < ScSubTotalRule > aSubTotalRules;
     com::sun::star::table::CellAddress aFilterOutputPosition;
     com::sun::star::table::CellRangeAddress aFilterConditionSourceRangeAddress;
@@ -146,7 +146,7 @@ public:
     void SetFilterIsCaseSensitive(const sal_Bool bTemp) { bFilterIsCaseSensitive = bTemp; }
     void SetFilterSkipDuplicates(const sal_Bool bTemp) { bFilterSkipDuplicates = bTemp; }
     void SetFilterUseRegularExpressions(const sal_Bool bTemp) { bFilterUseRegularExpressions = bTemp; }
-    void SetFilterFields(const com::sun::star::uno::Sequence <com::sun::star::sheet::TableFilterField>& aTemp) { aFilterFields = aTemp; }
+    void SetFilterFields(const com::sun::star::uno::Sequence <com::sun::star::sheet::TableFilterField2>& aTemp) { aFilterFields = aTemp; }
     void SetFilterOutputPosition(const com::sun::star::table::CellAddress& aTemp) { aFilterOutputPosition = aTemp; }
     void SetFilterConditionSourceRangeAddress(const com::sun::star::table::CellRangeAddress& aTemp) { aFilterConditionSourceRangeAddress = aTemp;
                                                                                                     bFilterConditionSourceRange = sal_True; }
diff --git a/sc/source/filter/xml/xmlfilti.cxx b/sc/source/filter/xml/xmlfilti.cxx
index 26d4b24..d3fb512 100644
--- a/sc/source/filter/xml/xmlfilti.cxx
+++ b/sc/source/filter/xml/xmlfilti.cxx
@@ -335,48 +335,60 @@ SvXMLImportContext *ScXMLConditionContext::CreateChildContext( USHORT nPrefix,
     return new SvXMLImportContext( GetImport(), nPrefix, rLName );
 }
 
-void ScXMLConditionContext::getOperatorXML(const rtl::OUString sTempOperator, sheet::FilterOperator& aFilterOperator, sal_Bool& bUseRegularExpressions) const
+void ScXMLConditionContext::getOperatorXML(const rtl::OUString sTempOperator, sal_Int32& aFilterOperator, sal_Bool& bUseRegularExpressions) const
 {
     bUseRegularExpressions = sal_False;
     if (IsXMLToken(sTempOperator, XML_MATCH))
     {
         bUseRegularExpressions = sal_True;
-        aFilterOperator = sheet::FilterOperator_EQUAL;
+        aFilterOperator = sheet::FilterOperator2::EQUAL;
     }
     else if (IsXMLToken(sTempOperator, XML_NOMATCH))
     {
         bUseRegularExpressions = sal_True;
-        aFilterOperator = sheet::FilterOperator_NOT_EQUAL;
+        aFilterOperator = sheet::FilterOperator2::NOT_EQUAL;
     }
     else if (sTempOperator.compareToAscii("=") == 0)
-        aFilterOperator = sheet::FilterOperator_EQUAL;
+        aFilterOperator = sheet::FilterOperator2::EQUAL;
     else if (sTempOperator.compareToAscii("!=") == 0)
-        aFilterOperator = sheet::FilterOperator_NOT_EQUAL;
+        aFilterOperator = sheet::FilterOperator2::NOT_EQUAL;
     else if (IsXMLToken(sTempOperator, XML_BOTTOM_PERCENT))
-        aFilterOperator = sheet::FilterOperator_BOTTOM_PERCENT;
+        aFilterOperator = sheet::FilterOperator2::BOTTOM_PERCENT;
     else if (IsXMLToken(sTempOperator, XML_BOTTOM_VALUES))
-        aFilterOperator = sheet::FilterOperator_BOTTOM_VALUES;
+        aFilterOperator = sheet::FilterOperator2::BOTTOM_VALUES;
     else if (IsXMLToken(sTempOperator, XML_EMPTY))
-        aFilterOperator = sheet::FilterOperator_EMPTY;
+        aFilterOperator = sheet::FilterOperator2::EMPTY;
     else if (sTempOperator.compareToAscii(">") == 0)
-        aFilterOperator = sheet::FilterOperator_GREATER;
+        aFilterOperator = sheet::FilterOperator2::GREATER;
     else if (sTempOperator.compareToAscii(">=") == 0)
-        aFilterOperator = sheet::FilterOperator_GREATER_EQUAL;
+        aFilterOperator = sheet::FilterOperator2::GREATER_EQUAL;
     else if (sTempOperator.compareToAscii("<") == 0)
-        aFilterOperator = sheet::FilterOperator_LESS;
+        aFilterOperator = sheet::FilterOperator2::LESS;
     else if (sTempOperator.compareToAscii("<=") == 0)
-        aFilterOperator = sheet::FilterOperator_LESS_EQUAL;
+        aFilterOperator = sheet::FilterOperator2::LESS_EQUAL;
     else if (IsXMLToken(sTempOperator, XML_NOEMPTY))
-        aFilterOperator = sheet::FilterOperator_NOT_EMPTY;
+        aFilterOperator = sheet::FilterOperator2::NOT_EMPTY;
     else if (IsXMLToken(sTempOperator, XML_TOP_PERCENT))
-        aFilterOperator = sheet::FilterOperator_TOP_PERCENT;
+        aFilterOperator = sheet::FilterOperator2::TOP_PERCENT;
     else if (IsXMLToken(sTempOperator, XML_TOP_VALUES))
-        aFilterOperator = sheet::FilterOperator_TOP_VALUES;
+        aFilterOperator = sheet::FilterOperator2::TOP_VALUES;
+    else if (IsXMLToken(sTempOperator, XML_CONTAINS))
+        aFilterOperator = sheet::FilterOperator2::CONTAINS;
+    else if (IsXMLToken(sTempOperator, XML_DOES_NOT_CONTAIN))
+        aFilterOperator = sheet::FilterOperator2::DOES_NOT_CONTAIN;
+    else if (IsXMLToken(sTempOperator, XML_BEGINS_WITH))
+        aFilterOperator = sheet::FilterOperator2::BEGINS_WITH;
+    else if (IsXMLToken(sTempOperator, XML_DOES_NOT_BEGIN_WITH))
+        aFilterOperator = sheet::FilterOperator2::DOES_NOT_BEGIN_WITH;
+    else if (IsXMLToken(sTempOperator, XML_ENDS_WITH))
+        aFilterOperator = sheet::FilterOperator2::ENDS_WITH;
+    else if (IsXMLToken(sTempOperator, XML_DOES_NOT_END_WITH))
+        aFilterOperator = sheet::FilterOperator2::DOES_NOT_END_WITH;
 }
 
 void ScXMLConditionContext::EndElement()
 {
-    sheet::TableFilterField aFilterField;
+    sheet::TableFilterField2 aFilterField;
     if (pFilterContext->GetConnection())
         aFilterField.Connection = sheet::FilterConnection_OR;
     else
diff --git a/sc/source/filter/xml/xmlfilti.hxx b/sc/source/filter/xml/xmlfilti.hxx
index f9e9943..e9793c6 100644
--- a/sc/source/filter/xml/xmlfilti.hxx
+++ b/sc/source/filter/xml/xmlfilti.hxx
@@ -36,7 +36,8 @@
 #include <com/sun/star/table/CellAddress.hpp>
 #include <com/sun/star/table/CellRangeAddress.hpp>
 #include <com/sun/star/sheet/FilterOperator.hpp>
-#include <com/sun/star/sheet/TableFilterField.hpp>
+#include <com/sun/star/sheet/FilterOperator2.hpp>
+#include <com/sun/star/sheet/TableFilterField2.hpp>
 #include <tools/stack.hxx>
 
 #include "xmldrani.hxx"
@@ -48,7 +49,7 @@ class ScXMLFilterContext : public SvXMLImportContext
 {
     ScXMLDatabaseRangeContext* pDatabaseRangeContext;
 
-    com::sun::star::uno::Sequence <com::sun::star::sheet::TableFilterField> aFilterFields;
+    com::sun::star::uno::Sequence <com::sun::star::sheet::TableFilterField2> aFilterFields;
     com::sun::star::table::CellAddress aOutputPosition;
     com::sun::star::table::CellRangeAddress aConditionSourceRangeAddress;
     sal_Int16	nUserListIndex;
@@ -89,7 +90,7 @@ public:
                             aConnectionOrStack.Push(pTemp);}
     void CloseConnection() { sal_Bool* pTemp = static_cast <sal_Bool*> (aConnectionOrStack.Pop()); bConnectionOr = *pTemp; bNextConnectionOr = *pTemp; delete pTemp;}
     sal_Bool GetConnection() { sal_Bool bTemp = bConnectionOr; bConnectionOr = bNextConnectionOr; return bTemp; }
-    void AddFilterField (const com::sun::star::sheet::TableFilterField aFilterField) { aFilterFields.realloc(aFilterFields.getLength() + 1);
+    void AddFilterField(const com::sun::star::sheet::TableFilterField2 aFilterField) { aFilterFields.realloc(aFilterFields.getLength() + 1);
                                                                                 aFilterFields[aFilterFields.getLength() - 1] = aFilterField; }
 };
 
@@ -171,7 +172,7 @@ public:
                                      const ::com::sun::star::uno::Reference<
                                           ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
 
-    void getOperatorXML(const rtl::OUString sTempOperator, com::sun::star::sheet::FilterOperator& aFilterOperator, sal_Bool& bUseRegularExpressions) const;
+    void getOperatorXML(const rtl::OUString sTempOperator, sal_Int32& aFilterOperator, sal_Bool& bUseRegularExpressions) const;
     virtual void EndElement();
 };
 
diff --git a/sc/source/ui/app/inputhdl.cxx b/sc/source/ui/app/inputhdl.cxx
index d7d1f3c..85104d0 100644
--- a/sc/source/ui/app/inputhdl.cxx
+++ b/sc/source/ui/app/inputhdl.cxx
@@ -741,7 +741,7 @@ void ScInputHandler::ShowTipCursor()
                 nLeftParentPos = lcl_MatchParenthesis( aSelText, aSelText.Len()-1 );
                 if( nLeftParentPos != STRING_NOTFOUND )
                 {
-                    sal_Unicode c = aSelText.GetChar( nLeftParentPos-1 );
+                    sal_Unicode c = ( nLeftParentPos > 0 ) ? aSelText.GetChar( nLeftParentPos-1 ) : 0;
                     if( !((c >= 'A' && c<= 'Z') || (c>= 'a' && c<= 'z' )) )
                         continue;
                     nNextFStart = aHelper.GetFunctionStart( aSelText, nLeftParentPos, TRUE);
@@ -983,7 +983,8 @@ void ScInputHandler::UseFormulaData()
                 if( nLeftParentPos == STRING_NOTFOUND )
                     break;
 
-                sal_Unicode c = aFormula.GetChar( nLeftParentPos-1 );
+                // #160063# nLeftParentPos can be 0 if a parenthesis is inserted before the formula
+                sal_Unicode c = ( nLeftParentPos > 0 ) ? aFormula.GetChar( nLeftParentPos-1 ) : 0;
                 if( !((c >= 'A' && c<= 'Z') || (c>= 'a' && c<= 'z') ) )
                     continue;
                 nNextFStart = aHelper.GetFunctionStart( aFormula, nLeftParentPos, TRUE);
diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx
index 8ff0776..22d764a 100644
--- a/sc/source/ui/docshell/docfunc.cxx
+++ b/sc/source/ui/docshell/docfunc.cxx
@@ -2073,6 +2073,12 @@ BOOL ScDocFunc::DeleteCells( const ScRange& rRange, const ScMarkData* pTabMark,
                 nUndoPos ++;
             }
         }
+
+        if( !bDeletingMerge )
+        {
+            rDocShell.GetUndoManager()->LeaveListAction();
+        }
+
         rDocShell.GetUndoManager()->AddUndoAction( new ScUndoDeleteCells(
             &rDocShell, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ),nUndoPos, pTabs, pScenarios,
             eCmd, pUndoDoc, pUndoData ) );
diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx
index eceb4c4..1f77d2c 100644
--- a/sc/source/ui/docshell/externalrefmgr.cxx
+++ b/sc/source/ui/docshell/externalrefmgr.cxx
@@ -143,7 +143,8 @@ private:
 // ============================================================================
 
 ScExternalRefCache::Table::Table()
-    : mbReferenced( true)   // Prevent accidental data loss due to lack of knowledge.
+    : meReferenced( REFERENCED_MARKED )
+      // Prevent accidental data loss due to lack of knowledge.
 {
 }
 
@@ -151,14 +152,25 @@ ScExternalRefCache::Table::~Table()
 {
 }
 
+void ScExternalRefCache::Table::setReferencedFlag( ScExternalRefCache::Table::ReferencedFlag eFlag )
+{
+    meReferenced = eFlag;
+}
+
 void ScExternalRefCache::Table::setReferenced( bool bReferenced )
 {
-    mbReferenced = bReferenced;
+    if (meReferenced != REFERENCED_PERMANENT)
+        meReferenced = (bReferenced ? REFERENCED_MARKED : UNREFERENCED);
+}
+
+ScExternalRefCache::Table::ReferencedFlag ScExternalRefCache::Table::getReferencedFlag() const
+{
+    return meReferenced;
 }
 
 bool ScExternalRefCache::Table::isReferenced() const
 {
-    return mbReferenced;
+    return meReferenced != UNREFERENCED;
 }
 
 void ScExternalRefCache::Table::setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex)
@@ -737,21 +749,57 @@ bool ScExternalRefCache::setCacheDocReferenced( sal_uInt16 nFileId )
     return areAllCacheTablesReferenced();
 }
 
-bool ScExternalRefCache::setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName )
+bool ScExternalRefCache::setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName, size_t nSheets, bool bPermanent )
 {
-    size_t nIndex = 0;
-    TableTypeRef pTab = getCacheTable( nFileId, rTabName, false, &nIndex);
-    if (pTab.get())
+    DocItem* pDoc = getDocItem(nFileId);
+    if (pDoc)
     {
-        if (!pTab->isReferenced())
+        size_t nIndex = 0;
+        String aTabNameUpper = ScGlobal::pCharClass->upper( rTabName);
+        if (lcl_getTableDataIndex( pDoc->maTableNameIndex, aTabNameUpper, nIndex))
         {
-            pTab->setReferenced( true);
-            addCacheTableToReferenced( nFileId, nIndex);
+            size_t nStop = ::std::min( nIndex + nSheets, pDoc->maTables.size());
+            for (size_t i = nIndex; i < nStop; ++i)
+            {
+                TableTypeRef pTab = pDoc->maTables[i];
+                if (pTab.get())
+                {
+                    Table::ReferencedFlag eNewFlag = (bPermanent ? 
+                            Table::REFERENCED_PERMANENT : 
+                            Table::REFERENCED_MARKED);
+                    Table::ReferencedFlag eOldFlag = pTab->getReferencedFlag();
+                    if (eOldFlag != Table::REFERENCED_PERMANENT && eNewFlag != eOldFlag)
+                    {
+                        pTab->setReferencedFlag( eNewFlag);
+                        addCacheTableToReferenced( nFileId, i);
+                    }
+                }
+            }
         }
     }
     return areAllCacheTablesReferenced();
 }
 
+void ScExternalRefCache::setCacheTableReferencedPermanently( sal_uInt16 nFileId, const String& rTabName, size_t nSheets )
+{
+    DocItem* pDoc = getDocItem(nFileId);
+    if (pDoc)
+    {
+        size_t nIndex = 0;
+        String aTabNameUpper = ScGlobal::pCharClass->upper( rTabName);
+        if (lcl_getTableDataIndex( pDoc->maTableNameIndex, aTabNameUpper, nIndex))
+        {
+            size_t nStop = ::std::min( nIndex + nSheets, pDoc->maTables.size());
+            for (size_t i = nIndex; i < nStop; ++i)
+            {
+                TableTypeRef pTab = pDoc->maTables[i];
+                if (pTab.get())
+                    pTab->setReferencedFlag( Table::REFERENCED_PERMANENT);
+            }
+        }
+    }
+}
+
 void ScExternalRefCache::setAllCacheTableReferencedStati( bool bReferenced )
 {
     if (bReferenced)
@@ -791,9 +839,17 @@ void ScExternalRefCache::setAllCacheTableReferencedStati( bool bReferenced )
                 TableTypeRef & xTab = rDocItem.maTables[i];
                 if (xTab.get())
                 {
-                    xTab->setReferenced( false);
-                    rDocReferenced.maTables[i] = false;
-                    rDocReferenced.mbAllTablesReferenced = false;
+                    if (xTab->getReferencedFlag() == Table::REFERENCED_PERMANENT)
+                        addCacheTableToReferenced( nFileId, i);
+                    else
+                    {
+                        xTab->setReferencedFlag( Table::UNREFERENCED);
+                        rDocReferenced.maTables[i] = false;
+                        rDocReferenced.mbAllTablesReferenced = false;
+                        // An addCacheTableToReferenced() actually may have 
+                        // resulted in mbAllReferenced been set. Clear it.
+                        maReferenced.mbAllReferenced = false;
+                    }
                 }
             }
         }
@@ -1481,9 +1537,19 @@ bool ScExternalRefManager::setCacheDocReferenced( sal_uInt16 nFileId )
     return maRefCache.setCacheDocReferenced( nFileId);
 }
 
-bool ScExternalRefManager::setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName )
+bool ScExternalRefManager::setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName, size_t nSheets )
 {
-    return maRefCache.setCacheTableReferenced( nFileId, rTabName);
+    return maRefCache.setCacheTableReferenced( nFileId, rTabName, nSheets, false);
+}
+
+void ScExternalRefManager::setCacheTableReferencedPermanently( sal_uInt16 nFileId, const String& rTabName, size_t nSheets )
+{
+    if (isInReferenceMarking())
+        // Do all maintenance work.
+        maRefCache.setCacheTableReferenced( nFileId, rTabName, nSheets, true);
+    else
+        // Set only the permanent flag.
+        maRefCache.setCacheTableReferencedPermanently( nFileId, rTabName, nSheets);
 }
 
 void ScExternalRefManager::setAllCacheTableReferencedStati( bool bReferenced )
diff --git a/sc/source/ui/inc/undoblk.hxx b/sc/source/ui/inc/undoblk.hxx
index d20e7bc..6a0a09c 100644
--- a/sc/source/ui/inc/undoblk.hxx
+++ b/sc/source/ui/inc/undoblk.hxx
@@ -36,6 +36,7 @@
 #include "spellparam.hxx"
 
 class ScDocShell;
+class ScBaseCell;
 class ScDocument;
 class ScOutlineTable;
 class ScRangeName;
@@ -592,6 +593,35 @@ private:
     void                    SetChangeTrack();
 };
 
+class ScUndoRefConversion: public ScSimpleUndo
+{
+public:
+                        TYPEINFO();
+                        ScUndoRefConversion( ScDocShell* pNewDocShell,
+                            const ScRange& aMarkRange, const ScMarkData& rMark,
+                            ScDocument* pNewUndoDoc, ScDocument* pNewRedoDoc, BOOL bNewMulti, USHORT nNewFlag);
+    virtual             ~ScUndoRefConversion();
+
+    virtual void        Undo();
+    virtual void        Redo();
+    virtual void        Repeat(SfxRepeatTarget& rTarget);
+    virtual BOOL        CanRepeat(SfxRepeatTarget& rTarget) const;
+
+    virtual String      GetComment() const;
+
+private:
+    ScMarkData          aMarkData;
+    ScDocument*         pUndoDoc;
+    ScDocument*         pRedoDoc;
+    ScRange             aRange;
+    BOOL                bMulti;
+    USHORT              nFlags;
+    ULONG               nStartChangeAction;
+    ULONG               nEndChangeAction;
+
+    void                DoChange( ScDocument* pRefDoc);
+    void                SetChangeTrack();
+};
 
 class ScUndoListNames: public ScBlockUndo
 {
diff --git a/sc/source/ui/inc/viewfunc.hxx b/sc/source/ui/inc/viewfunc.hxx
index 072f832..f3530d5 100644
--- a/sc/source/ui/inc/viewfunc.hxx
+++ b/sc/source/ui/inc/viewfunc.hxx
@@ -303,6 +303,7 @@ public:
 
     void            SetNoteText( const ScAddress& rPos, const String& rNoteText );
     void            ReplaceNote( const ScAddress& rPos, const String& rNoteText, const String* pAuthor, const String* pDate );
+    void            DoRefConversion( BOOL bRecord = TRUE );
 
 //UNUSED2008-05  void            DoSpellingChecker( BOOL bRecord = TRUE );
     void            DoHangulHanjaConversion( BOOL bRecord = TRUE );
diff --git a/sc/source/ui/src/filter.src b/sc/source/ui/src/filter.src
index d328b69..25cc86f 100644
--- a/sc/source/ui/src/filter.src
+++ b/sc/source/ui/src/filter.src
@@ -34,7 +34,7 @@ ModelessDialog RID_SCDLG_FILTER
     HelpId = SID_FILTER ;
     Hide = TRUE ;
     SVLook = TRUE ;
-    Size = MAP_APPFONT ( 251 , 121 ) ;
+    Size = MAP_APPFONT ( 279 , 121 ) ;
     Text [ en-US ] = "Standard Filter" ;
     Moveable = TRUE ;
     Closeable = FALSE ;
@@ -58,7 +58,7 @@ ModelessDialog RID_SCDLG_FILTER
     };
     FixedText FT_VAL
     {
-        Pos = MAP_APPFONT ( 173 , 14 ) ;
+        Pos = MAP_APPFONT ( 201 , 14 ) ;
         Size = MAP_APPFONT ( 60 , 8 ) ;
         Text [ en-US ] = "Value" ;
     };
@@ -150,7 +150,7 @@ ModelessDialog RID_SCDLG_FILTER
     {
         Border = TRUE ;
         Pos = MAP_APPFONT ( 122 , 25 ) ;
-        Size = MAP_APPFONT ( 47 , 145 ) ;
+        Size = MAP_APPFONT ( 75 , 145 ) ;
         TabStop = TRUE ;
         DropDown = TRUE ;
         stringlist [ en-US ] =
@@ -165,13 +165,19 @@ ModelessDialog RID_SCDLG_FILTER
             < "Smallest" ; Default ; > ;
             < "Largest %" ; Default ; > ;
             < "Smallest %" ; Default ; > ;
+            < "Contains" ; Default ; > ;
+            < "Does not contain" ; Default ; > ;
+            < "Begins with" ; Default ; > ;
+            < "Does not begin with" ; Default ; > ;
+            < "Ends with" ; Default ; > ;
+            < "Does not end with" ; Default ; > ;
         };
     };
     ListBox LB_COND2
     {
         Border = TRUE ;
         Pos = MAP_APPFONT ( 122 , 41 ) ;
-        Size = MAP_APPFONT ( 47 , 145 ) ;
+        Size = MAP_APPFONT ( 75 , 145 ) ;
         TabStop = TRUE ;
         DropDown = TRUE ;
         stringlist [ en-US ] =
@@ -186,13 +192,19 @@ ModelessDialog RID_SCDLG_FILTER
             < "Smallest" ; Default ; > ;
             < "Largest %" ; Default ; > ;
             < "Smallest %" ; Default ; > ;
+            < "Contains" ; Default ; > ;
+            < "Does not contain" ; Default ; > ;
+            < "Begins with" ; Default ; > ;
+            < "Does not begin with" ; Default ; > ;
+            < "Ends with" ; Default ; > ;
+            < "Does not end with" ; Default ; > ;
         };
     };
     ListBox LB_COND3
     {
         Border = TRUE ;
         Pos = MAP_APPFONT ( 122 , 57 ) ;
-        Size = MAP_APPFONT ( 47 , 145 ) ;
+        Size = MAP_APPFONT ( 75 , 145 ) ;
         TabStop = TRUE ;
         DropDown = TRUE ;
         stringlist [ en-US ] =
@@ -207,13 +219,19 @@ ModelessDialog RID_SCDLG_FILTER
             < "Smallest" ; Default ; > ;
             < "Largest %" ; Default ; > ;
             < "Smallest %" ; Default ; > ;
+            < "Contains" ; Default ; > ;
+            < "Does not contain" ; Default ; > ;
+            < "Begins with" ; Default ; > ;
+            < "Does not begin with" ; Default ; > ;
+            < "Ends with" ; Default ; > ;
+            < "Does not end with" ; Default ; > ;
         };
     };
     ListBox LB_COND4
     {
         Border = TRUE ;
         Pos = MAP_APPFONT ( 122 , 73 ) ;
-        Size = MAP_APPFONT ( 47 , 145 ) ;
+        Size = MAP_APPFONT ( 75 , 145 ) ;
         TabStop = TRUE ;
         DropDown = TRUE ;
         stringlist [ en-US ] =
@@ -228,39 +246,45 @@ ModelessDialog RID_SCDLG_FILTER
             < "Smallest" ; Default ; > ;
             < "Largest %" ; Default ; > ;
             < "Smallest %" ; Default ; > ;
+            < "Contains" ; Default ; > ;
+            < "Does not contain" ; Default ; > ;
+            < "Begins with" ; Default ; > ;
+            < "Does not begin with" ; Default ; > ;
+            < "Ends with" ; Default ; > ;
+            < "Does not end with" ; Default ; > ;
         };
     };
     ComboBox ED_VAL1
     {
-        Pos = MAP_APPFONT ( 173 , 25 ) ;
+        Pos = MAP_APPFONT ( 201 , 25 ) ;
         Size = MAP_APPFONT ( 60 , 90 ) ;
         TabStop = TRUE ;
         DropDown = TRUE ;
     };
     ComboBox ED_VAL2
     {
-        Pos = MAP_APPFONT ( 173 , 41 ) ;
+        Pos = MAP_APPFONT ( 201 , 41 ) ;
         Size = MAP_APPFONT ( 60 , 90 ) ;
         TabStop = TRUE ;
         DropDown = TRUE ;
     };
     ComboBox ED_VAL3
     {
-        Pos = MAP_APPFONT ( 173 , 57 ) ;
+        Pos = MAP_APPFONT ( 201 , 57 ) ;
         Size = MAP_APPFONT ( 60 , 90 ) ;
         TabStop = TRUE ;
         DropDown = TRUE ;
     };
     ComboBox ED_VAL4
     {
-        Pos = MAP_APPFONT ( 173 , 73 ) ;
+        Pos = MAP_APPFONT ( 201 , 73 ) ;
         Size = MAP_APPFONT ( 60 , 90 ) ;
         TabStop = TRUE ;
         DropDown = TRUE ;
     };
     ScrollBar LB_SCROLL
     {
-        Pos = MAP_APPFONT ( 237, 25 ) ;
+        Pos = MAP_APPFONT ( 265, 25 ) ;
         Size = MAP_APPFONT ( 8 , 60 ) ;
         TabStop = TRUE ;
         VScroll = TRUE ;
@@ -269,7 +293,7 @@ ModelessDialog RID_SCDLG_FILTER
     FixedLine FL_CRITERIA
     {
         Pos = MAP_APPFONT ( 6 , 3 ) ;
-        Size = MAP_APPFONT ( 275 , 8 ) ;
+        Size = MAP_APPFONT ( 267 , 8 ) ;
         Text [ en-US ] = "Filter criteria";
     };
     CheckBox BTN_CASE
@@ -325,7 +349,7 @@ ModelessDialog RID_SCDLG_FILTER
         Border = TRUE ;
         Hide = TRUE ;
         Pos = MAP_APPFONT ( 21 , 170 ) ;
-        Size = MAP_APPFONT ( 90 , 90 ) ;
+        Size = MAP_APPFONT ( 110 , 90 ) ;
         TabStop = TRUE ;
         DropDown = TRUE ;
     };
@@ -333,13 +357,13 @@ ModelessDialog RID_SCDLG_FILTER
     {
         Border = TRUE ;
         Hide = TRUE ;
-        Pos = MAP_APPFONT ( 115 , 170 ) ;
-        Size = MAP_APPFONT ( 104 , 12 ) ;
+        Pos = MAP_APPFONT ( 136 , 170 ) ;
+        Size = MAP_APPFONT ( 110 , 12 ) ;
         TabStop = TRUE ;
     };
     ImageButton RB_COPY_AREA
     {
-        Pos = MAP_APPFONT ( 221 , 169 ) ;
+        Pos = MAP_APPFONT ( 248 , 169 ) ;
         Size = MAP_APPFONT ( 13 , 15 ) ;
         TabStop = FALSE ;
         QuickHelpText [ en-US ] = "Shrink" ;
@@ -348,7 +372,7 @@ ModelessDialog RID_SCDLG_FILTER
     {
         Hide = TRUE ;
         Pos = MAP_APPFONT ( 6 , 118 ) ;
-        Size = MAP_APPFONT ( 239 , 8 ) ;
+        Size = MAP_APPFONT ( 267 , 8 ) ;
     };
     FixedText FT_DBAREA
     {
@@ -367,14 +391,14 @@ ModelessDialog RID_SCDLG_FILTER
     };
     OKButton BTN_OK
     {
-        Pos = MAP_APPFONT ( 141 , 101 ) ;
+        Pos = MAP_APPFONT ( 169 , 101 ) ;
         Size = MAP_APPFONT ( 50 , 14 ) ;
         TabStop = TRUE ;
         DefButton = TRUE ;
     };
     CancelButton BTN_CANCEL
     {
-        Pos = MAP_APPFONT ( 195 , 101 ) ;
+        Pos = MAP_APPFONT ( 223 , 101 ) ;
         Size = MAP_APPFONT ( 50 , 14 ) ;
         TabStop = TRUE ;
     };
@@ -395,7 +419,7 @@ ModelessDialog RID_SCDLG_FILTER
     FixedLine FL_SEPARATOR
     {
         Pos = MAP_APPFONT ( 0 , 91 ) ;
-        Size = MAP_APPFONT ( 251 , 6 ) ;
+        Size = MAP_APPFONT ( 279 , 6 ) ;
     };
 };
  //============================================================================
diff --git a/sc/source/ui/undo/undoblk3.cxx b/sc/source/ui/undo/undoblk3.cxx
index 597241d..879acec 100644
--- a/sc/source/ui/undo/undoblk3.cxx
+++ b/sc/source/ui/undo/undoblk3.cxx
@@ -74,6 +74,7 @@ TYPEINIT1(ScUndoAutoFormat, 		SfxUndoAction);
 TYPEINIT1(ScUndoReplace,			SfxUndoAction);
 TYPEINIT1(ScUndoTabOp,				SfxUndoAction);
 TYPEINIT1(ScUndoConversion,         SfxUndoAction);
+TYPEINIT1(ScUndoRefConversion,      SfxUndoAction);
 TYPEINIT1(ScUndoRefreshLink,		SfxUndoAction);
 TYPEINIT1(ScUndoInsertAreaLink,		SfxUndoAction);
 TYPEINIT1(ScUndoRemoveAreaLink,		SfxUndoAction);
@@ -1527,6 +1528,98 @@ BOOL ScUndoConversion::CanRepeat(SfxRepeatTarget& rTarget) const
 
 
 //============================================================================
+//  class ScUndoRefConversion
+//
+//	cell reference conversion
+
+//----------------------------------------------------------------------------
+
+ScUndoRefConversion::ScUndoRefConversion( ScDocShell* pNewDocShell,
+                                         const ScRange& aMarkRange, const ScMarkData& rMark,
+                                         ScDocument* pNewUndoDoc, ScDocument* pNewRedoDoc, BOOL bNewMulti, USHORT nNewFlag) :
+ScSimpleUndo( pNewDocShell ),
+aMarkData   ( rMark ),
+pUndoDoc	( pNewUndoDoc ),
+pRedoDoc	( pNewRedoDoc ),
+aRange  	( aMarkRange ),
+bMulti      ( bNewMulti ),
+nFlags      ( nNewFlag )
+{
+    SetChangeTrack();
+}
+
+__EXPORT ScUndoRefConversion::~ScUndoRefConversion()
+{
+    delete pUndoDoc;
+    delete pRedoDoc;
+}
+
+String __EXPORT ScUndoRefConversion::GetComment() const
+{
+    return ScGlobal::GetRscString( STR_UNDO_ENTERDATA ); // "Eingabe"
+}
+
+void ScUndoRefConversion::SetChangeTrack()
+{
+    ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack();
+    if ( pChangeTrack && (nFlags & IDF_FORMULA) )
+        pChangeTrack->AppendContentsIfInRefDoc( pUndoDoc,
+            nStartChangeAction, nEndChangeAction );
+    else
+        nStartChangeAction = nEndChangeAction = 0;
+}
+
+void ScUndoRefConversion::DoChange( ScDocument* pRefDoc)
+{
+    ScDocument* pDoc = pDocShell->GetDocument();
+
+    ShowTable(aRange);
+
+    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+    if (pViewShell)
+        pViewShell->SetMarkData( aMarkData );
+
+    ScRange aCopyRange = aRange;
+    SCTAB nTabCount = pDoc->GetTableCount();
+    aCopyRange.aStart.SetTab(0);
+    aCopyRange.aEnd.SetTab(nTabCount-1);
+    pRefDoc->CopyToDocument( aCopyRange, nFlags, bMulti, pDoc, &aMarkData );
+    pDocShell->PostPaint( aRange, PAINT_GRID);
+    pDocShell->PostDataChanged();
+    if (pViewShell)
+        pViewShell->CellContentChanged();
+}
+void __EXPORT ScUndoRefConversion::Undo()
+{
+    BeginUndo();
+    if (pUndoDoc)
+        DoChange(pUndoDoc);
+    ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack();
+    if ( pChangeTrack )
+        pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
+    EndUndo();
+}
+
+void __EXPORT ScUndoRefConversion::Redo()
+{
+    BeginRedo();
+    if (pRedoDoc)
+        DoChange(pRedoDoc);
+    SetChangeTrack();
+    EndRedo();
+}
+
+void __EXPORT ScUndoRefConversion::Repeat(SfxRepeatTarget& rTarget)
+{
+    if (rTarget.ISA(ScTabViewTarget))
+        ((ScTabViewTarget&)rTarget).GetViewShell()->DoRefConversion();
+}
+
+BOOL __EXPORT ScUndoRefConversion::CanRepeat(SfxRepeatTarget& rTarget) const
+{
+    return (rTarget.ISA(ScTabViewTarget));
+}
+//============================================================================
 //	class ScUndoRefreshLink
 //
 //	Link aktualisieren / aendern
diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx
index b62ed23..1531c08 100644
--- a/sc/source/ui/unoobj/cellsuno.cxx
+++ b/sc/source/ui/unoobj/cellsuno.cxx
@@ -5633,7 +5633,15 @@ void SAL_CALL ScCellRangeObj::filter( const uno::Reference<sheet::XSheetFilterDe
 
     ScDocShell* pDocSh = GetDocShell();
     ScFilterDescriptor aImpl(pDocSh);
-    aImpl.setFilterFields( xDescriptor->getFilterFields() );
+    uno::Reference< sheet::XSheetFilterDescriptor2 > xDescriptor2( xDescriptor, uno::UNO_QUERY );
+    if ( xDescriptor2.is() )
+    {
+        aImpl.setFilterFields2( xDescriptor2->getFilterFields2() );
+    }
+    else
+    {
+        aImpl.setFilterFields( xDescriptor->getFilterFields() );
+    }
     //	Rest sind jetzt Properties...
 
     uno::Reference<beans::XPropertySet> xPropSet( xDescriptor, uno::UNO_QUERY );
diff --git a/sc/source/ui/unoobj/datauno.cxx b/sc/source/ui/unoobj/datauno.cxx
index 79614f2..90c6c98 100644
--- a/sc/source/ui/unoobj/datauno.cxx
+++ b/sc/source/ui/unoobj/datauno.cxx
@@ -45,6 +45,8 @@
 #include <com/sun/star/table/TableOrientation.hpp>
 #include <com/sun/star/table/CellRangeAddress.hpp>
 #include <com/sun/star/sheet/DataImportMode.hpp>
+#include <com/sun/star/sheet/FilterOperator2.hpp>
+#include <com/sun/star/sheet/TableFilterField2.hpp>
 
 #include "datauno.hxx"
 #include "dapiuno.hxx"
@@ -1106,7 +1108,7 @@ void ScFilterDescriptorBase::Notify( SfxBroadcaster&, const SfxHint& rHint )
     }
 }
 
-// XSheetFilterDescriptor
+// XSheetFilterDescriptor and XSheetFilterDescriptor2
 
 uno::Sequence<sheet::TableFilterField> SAL_CALL ScFilterDescriptorBase::getFilterFields()
                                                 throw(uno::RuntimeException)
@@ -1177,6 +1179,80 @@ uno::Sequence<sheet::TableFilterField> SAL_CALL ScFilterDescriptorBase::getFilte
     return aSeq;
 }
 
+uno::Sequence<sheet::TableFilterField2> SAL_CALL ScFilterDescriptorBase::getFilterFields2()
+throw(uno::RuntimeException)
+{
+    ScUnoGuard aGuard;
+    ScQueryParam aParam;
+    GetData(aParam);
+
+    SCSIZE nEntries = aParam.GetEntryCount();	// allozierte Eintraege im Param
+    SCSIZE nCount = 0;							// aktive
+    while ( nCount < nEntries &&
+        aParam.GetEntry(nCount).bDoQuery )
+        ++nCount;
+
+    sheet::TableFilterField2 aField;
+    uno::Sequence<sheet::TableFilterField2> aSeq(static_cast<sal_Int32>(nCount));
+    sheet::TableFilterField2* pAry = aSeq.getArray();
+    for (SCSIZE i=0; i<nCount; i++)
+    {
+        const ScQueryEntry& rEntry = aParam.GetEntry(i);
+
+        rtl::OUString aStringValue;
+        if (rEntry.pStr)
+            aStringValue = *rEntry.pStr;
+
+        aField.Connection	 = (rEntry.eConnect == SC_AND) ? sheet::FilterConnection_AND : sheet::FilterConnection_OR;
+        aField.Field		 = rEntry.nField;
+        aField.IsNumeric	 = !rEntry.bQueryByString;
+        aField.StringValue	 = aStringValue;
+        aField.NumericValue	 = rEntry.nVal;
+
+        switch (rEntry.eOp)				// ScQueryOp
+        {
+        case SC_EQUAL:
+            {
+                aField.Operator = sheet::FilterOperator2::EQUAL;
+                if (!rEntry.bQueryByString && *rEntry.pStr == EMPTY_STRING)
+                {
+                    if (rEntry.nVal == SC_EMPTYFIELDS)
+                    {
+                        aField.Operator = sheet::FilterOperator2::EMPTY;
+                        aField.NumericValue = 0;
+                    }
+                    else if (rEntry.nVal == SC_NONEMPTYFIELDS)
+                    {
+                        aField.Operator = sheet::FilterOperator2::NOT_EMPTY;
+                        aField.NumericValue = 0;
+                    }
+                }
+            }
+            break;
+        case SC_LESS:			        aField.Operator = sheet::FilterOperator2::LESS;			        break;
+        case SC_GREATER:		        aField.Operator = sheet::FilterOperator2::GREATER;		        break;
+        case SC_LESS_EQUAL:		        aField.Operator = sheet::FilterOperator2::LESS_EQUAL;	        break;
+        case SC_GREATER_EQUAL:	        aField.Operator = sheet::FilterOperator2::GREATER_EQUAL;        break;
+        case SC_NOT_EQUAL:		        aField.Operator = sheet::FilterOperator2::NOT_EQUAL;	        break;
+        case SC_TOPVAL:			        aField.Operator = sheet::FilterOperator2::TOP_VALUES;	        break;
+        case SC_BOTVAL:			        aField.Operator = sheet::FilterOperator2::BOTTOM_VALUES;        break;
+        case SC_TOPPERC:		        aField.Operator = sheet::FilterOperator2::TOP_PERCENT;	        break;
+        case SC_BOTPERC:		        aField.Operator = sheet::FilterOperator2::BOTTOM_PERCENT;       break;
+        case SC_CONTAINS:               aField.Operator = sheet::FilterOperator2::CONTAINS;             break;
+        case SC_DOES_NOT_CONTAIN:       aField.Operator = sheet::FilterOperator2::DOES_NOT_CONTAIN;     break;
+        case SC_BEGINS_WITH:            aField.Operator = sheet::FilterOperator2::BEGINS_WITH;          break;
+        case SC_DOES_NOT_BEGIN_WITH:    aField.Operator = sheet::FilterOperator2::DOES_NOT_BEGIN_WITH;  break;
+        case SC_ENDS_WITH:              aField.Operator = sheet::FilterOperator2::ENDS_WITH;            break;
+        case SC_DOES_NOT_END_WITH:      aField.Operator = sheet::FilterOperator2::DOES_NOT_END_WITH;    break;
+        default:
+            DBG_ERROR("Falscher Filter-enum");
+            aField.Operator = sheet::FilterOperator2::EMPTY;
+        }
+        pAry[i] = aField;
+    }
+    return aSeq;
+}
+
 void SAL_CALL ScFilterDescriptorBase::setFilterFields(
                 const uno::Sequence<sheet::TableFilterField>& aFilterFields )
                                                 throw(uno::RuntimeException)
@@ -1251,6 +1327,86 @@ void SAL_CALL ScFilterDescriptorBase::setFilterFields(
     PutData(aParam);
 }
 
+void SAL_CALL ScFilterDescriptorBase::setFilterFields2(
+    const uno::Sequence<sheet::TableFilterField2>& aFilterFields )
+    throw(uno::RuntimeException)
+{
+    ScUnoGuard aGuard;
+    ScQueryParam aParam;
+    GetData(aParam);
+
+    SCSIZE nCount = static_cast<SCSIZE>(aFilterFields.getLength());
+    DBG_ASSERT( nCount <= MAXQUERY, "setFilterFields: zu viele" );
+
+    aParam.Resize( nCount );
+
+    const sheet::TableFilterField2* pAry = aFilterFields.getConstArray();
+    SCSIZE i;
+    for (i=0; i<nCount; i++)
+    {
+        ScQueryEntry& rEntry = aParam.GetEntry(i);
+        if (!rEntry.pStr)
+            rEntry.pStr = new String;		// sollte nicht sein (soll immer initialisiert sein)
+
+        rEntry.bDoQuery			= TRUE;
+        rEntry.eConnect			= (pAry[i].Connection == sheet::FilterConnection_AND) ? SC_AND : SC_OR;
+        rEntry.nField			= pAry[i].Field;
+        rEntry.bQueryByString	= !pAry[i].IsNumeric;
+        *rEntry.pStr			= String( pAry[i].StringValue );
+        rEntry.nVal				= pAry[i].NumericValue;
+
+        if (!rEntry.bQueryByString && pDocSh)
+        {
+            pDocSh->GetDocument()->GetFormatTable()->GetInputLineString(rEntry.nVal, 0, *rEntry.pStr);
+        }
+
+        switch (pAry[i].Operator)			// FilterOperator
+        {
+        case sheet::FilterOperator2::EQUAL:			        rEntry.eOp = SC_EQUAL;		        break;
+        case sheet::FilterOperator2::LESS:			        rEntry.eOp = SC_LESS;			    break;
+        case sheet::FilterOperator2::GREATER:			    rEntry.eOp = SC_GREATER;		    break;
+        case sheet::FilterOperator2::LESS_EQUAL:		    rEntry.eOp = SC_LESS_EQUAL;	        break;
+        case sheet::FilterOperator2::GREATER_EQUAL:	        rEntry.eOp = SC_GREATER_EQUAL;      break;
+        case sheet::FilterOperator2::NOT_EQUAL:		        rEntry.eOp = SC_NOT_EQUAL;	        break;
+        case sheet::FilterOperator2::TOP_VALUES:	    	rEntry.eOp = SC_TOPVAL;		        break;
+        case sheet::FilterOperator2::BOTTOM_VALUES:	        rEntry.eOp = SC_BOTVAL;		        break;
+        case sheet::FilterOperator2::TOP_PERCENT:		    rEntry.eOp = SC_TOPPERC;		    break;
+        case sheet::FilterOperator2::BOTTOM_PERCENT:	    rEntry.eOp = SC_BOTPERC;		    break;
+        case sheet::FilterOperator2::CONTAINS:		        rEntry.eOp = SC_CONTAINS;		    break;
+        case sheet::FilterOperator2::DOES_NOT_CONTAIN:		rEntry.eOp = SC_DOES_NOT_CONTAIN;   break;
+        case sheet::FilterOperator2::BEGINS_WITH:			rEntry.eOp = SC_BEGINS_WITH;		break;
+        case sheet::FilterOperator2::DOES_NOT_BEGIN_WITH:	rEntry.eOp = SC_DOES_NOT_BEGIN_WITH;break;
+        case sheet::FilterOperator2::ENDS_WITH:			    rEntry.eOp = SC_ENDS_WITH;		    break;
+        case sheet::FilterOperator2::DOES_NOT_END_WITH:		rEntry.eOp = SC_DOES_NOT_END_WITH;	break;
+        case sheet::FilterOperator2::EMPTY:
+            {
+                rEntry.eOp = SC_EQUAL;
+                rEntry.nVal = SC_EMPTYFIELDS;
+                rEntry.bQueryByString = FALSE;
+                *rEntry.pStr = EMPTY_STRING;
+            }
+            break;
+        case sheet::FilterOperator2::NOT_EMPTY:
+            {
+                rEntry.eOp = SC_EQUAL;
+                rEntry.nVal = SC_NONEMPTYFIELDS;
+                rEntry.bQueryByString = FALSE;
+                *rEntry.pStr = EMPTY_STRING;
+            }
+            break;
+        default:
+            DBG_ERROR("Falscher Query-enum");
+            rEntry.eOp = SC_EQUAL;
+        }
+    }
+
+    SCSIZE nParamCount = aParam.GetEntryCount();	// Param wird nicht unter 8 resized
+    for (i=nCount; i<nParamCount; i++)
+        aParam.GetEntry(i).bDoQuery = FALSE;		// ueberzaehlige Felder zuruecksetzen
+
+    PutData(aParam);
+}
+
 // Rest sind Properties
 
 // XPropertySet
diff --git a/sc/source/ui/vba/vbarange.cxx b/sc/source/ui/vba/vbarange.cxx
index 6b87a9d..832376a 100644
--- a/sc/source/ui/vba/vbarange.cxx
+++ b/sc/source/ui/vba/vbarange.cxx
@@ -77,7 +77,10 @@
 #include <com/sun/star/sheet/XCellRangeMovement.hpp>
 #include <com/sun/star/sheet/XCellRangeData.hpp>
 #include <com/sun/star/sheet/FormulaResult.hpp>
+#include <com/sun/star/sheet/FilterOperator2.hpp>
 #include <com/sun/star/sheet/TableFilterField.hpp>
+#include <com/sun/star/sheet/TableFilterField2.hpp>
+#include <com/sun/star/sheet/XSheetFilterDescriptor2.hpp>
 #include <com/sun/star/sheet/XSheetFilterable.hpp>
 #include <com/sun/star/sheet/FilterConnection.hpp>
 #include <com/sun/star/util/CellProtection.hpp>
@@ -4027,7 +4030,7 @@ void lcl_SetAllQueryForField( ScDocShell* pDocShell, SCCOLROW nField, sal_Int16
 }
 
 // Modifies sCriteria, and nOp depending on the value of sCriteria
-void lcl_setTableFieldsFromCriteria( rtl::OUString& sCriteria1, uno::Reference< beans::XPropertySet >& xDescProps, sheet::TableFilterField& rFilterField )
+void lcl_setTableFieldsFromCriteria( rtl::OUString& sCriteria1, uno::Reference< beans::XPropertySet >& xDescProps, sheet::TableFilterField2& rFilterField )
 {
     // #TODO make this more efficient and cycle through 
     // sCriteria1 character by character to pick up <,<>,=, * etc.
@@ -4047,10 +4050,10 @@ void lcl_setTableFieldsFromCriteria( rtl::OUString& sCriteria1, uno::Reference<
     if ( ( nPos = sCriteria1.indexOf( EQUALS ) ) == 0 )
     {
         if ( sCriteria1.getLength() == EQUALS.getLength() )
-            rFilterField.Operator = sheet::FilterOperator_EMPTY;
+            rFilterField.Operator = sheet::FilterOperator2::EMPTY;
         else
         {
-            rFilterField.Operator = sheet::FilterOperator_EQUAL;
+            rFilterField.Operator = sheet::FilterOperator2::EQUAL;
             sCriteria1 = sCriteria1.copy( EQUALS.getLength() );
             sCriteria1 = VBAToRegexp( sCriteria1 );	
             // UseRegularExpressions 
@@ -4062,10 +4065,10 @@ void lcl_setTableFieldsFromCriteria( rtl::OUString& sCriteria1, uno::Reference<
     else if ( ( nPos = sCriteria1.indexOf( NOTEQUALS ) ) == 0 ) 
     {
         if ( sCriteria1.getLength() == NOTEQUALS.getLength() )
-            rFilterField.Operator = sheet::FilterOperator_NOT_EMPTY;	
+            rFilterField.Operator = sheet::FilterOperator2::NOT_EMPTY;	
         else
         {
-            rFilterField.Operator = sheet::FilterOperator_NOT_EQUAL;
+            rFilterField.Operator = sheet::FilterOperator2::NOT_EQUAL;
             sCriteria1 = sCriteria1.copy( NOTEQUALS.getLength() );
             sCriteria1 = VBAToRegexp( sCriteria1 );	
             // UseRegularExpressions 
@@ -4079,12 +4082,12 @@ void lcl_setTableFieldsFromCriteria( rtl::OUString& sCriteria1, uno::Reference<
         if ( ( nPos = sCriteria1.indexOf( GREATERTHANEQUALS ) ) == 0 )
         {
             sCriteria1 = sCriteria1.copy( GREATERTHANEQUALS.getLength() );
-            rFilterField.Operator = sheet::FilterOperator_GREATER_EQUAL;
+            rFilterField.Operator = sheet::FilterOperator2::GREATER_EQUAL;
         }
         else
         {
             sCriteria1 = sCriteria1.copy( GREATERTHAN.getLength() );
-            rFilterField.Operator = sheet::FilterOperator_GREATER;
+            rFilterField.Operator = sheet::FilterOperator2::GREATER;
         }
 
     }
@@ -4094,17 +4097,17 @@ void lcl_setTableFieldsFromCriteria( rtl::OUString& sCriteria1, uno::Reference<
         if ( ( nPos = sCriteria1.indexOf( LESSTHANEQUALS ) ) == 0 )
         {
             sCriteria1 = sCriteria1.copy( LESSTHANEQUALS.getLength() );
-            rFilterField.Operator = sheet::FilterOperator_LESS_EQUAL;
+            rFilterField.Operator = sheet::FilterOperator2::LESS_EQUAL;
         }
         else
         {
             sCriteria1 = sCriteria1.copy( LESSTHAN.getLength() );
-            rFilterField.Operator = sheet::FilterOperator_LESS;
+            rFilterField.Operator = sheet::FilterOperator2::LESS;
         }
 
     }
     else
-        rFilterField.Operator = sheet::FilterOperator_EQUAL;
+        rFilterField.Operator = sheet::FilterOperator2::EQUAL;
 
     if ( bIsNumeric )
     {
@@ -4213,13 +4216,16 @@ ScVbaRange::AutoFilter( const uno::Any& Field, const uno::Any& Criteria1, const
     bool bAll = false;;
     if ( ( Field >>= nField )  )
     {
-        uno::Sequence< sheet::TableFilterField > sTabFilts;
-        uno::Reference< sheet::XSheetFilterDescriptor > xDesc = xDataBaseRange->getFilterDescriptor();
-        uno::Reference< beans::XPropertySet > xDescProps( xDesc, uno::UNO_QUERY_THROW );
+        uno::Reference< sheet::XSheetFilterDescriptor2 > xDesc(
+                xDataBaseRange->getFilterDescriptor(), uno::UNO_QUERY );
+        if ( xDesc.is() )
+        {
+            uno::Sequence< sheet::TableFilterField2 > sTabFilts;
+            uno::Reference< beans::XPropertySet > xDescProps( xDesc, uno::UNO_QUERY_THROW );
         if ( Criteria1.hasValue() )
         { 
             sTabFilts.realloc( 1 );
-            sTabFilts[0].Operator = sheet::FilterOperator_EQUAL;// sensible default
+            sTabFilts[0].Operator = sheet::FilterOperator2::EQUAL;// sensible default
             if ( !bCritHasNumericValue )
             { 
                 Criteria1 >>= sCriteria1;
@@ -4252,16 +4258,16 @@ ScVbaRange::AutoFilter( const uno::Any& Field, const uno::Any& Criteria1, const
             switch ( nOperator )
             {
                 case excel::XlAutoFilterOperator::xlBottom10Items:
-                    sTabFilts[0].Operator = sheet::FilterOperator_BOTTOM_VALUES;
+                    sTabFilts[0].Operator = sheet::FilterOperator2::BOTTOM_VALUES;
                     break;
                 case excel::XlAutoFilterOperator::xlBottom10Percent:
-                    sTabFilts[0].Operator = sheet::FilterOperator_BOTTOM_PERCENT;
+                    sTabFilts[0].Operator = sheet::FilterOperator2::BOTTOM_PERCENT;
                     break;
                 case excel::XlAutoFilterOperator::xlTop10Items:
-                    sTabFilts[0].Operator = sheet::FilterOperator_TOP_VALUES;
+                    sTabFilts[0].Operator = sheet::FilterOperator2::TOP_VALUES;
                     break;
                 case excel::XlAutoFilterOperator::xlTop10Percent:
-                    sTabFilts[0].Operator = sheet::FilterOperator_TOP_PERCENT;
+                    sTabFilts[0].Operator = sheet::FilterOperator2::TOP_PERCENT;
                     break;
                 case excel::XlAutoFilterOperator::xlOr:
                     nConn = sheet::FilterConnection_OR;
@@ -4300,12 +4306,12 @@ ScVbaRange::AutoFilter( const uno::Any& Field, const uno::Any& Criteria1, const
                 {
                     Criteria2 >>= sTabFilts[1].NumericValue;
                     sTabFilts[1].IsNumeric = sal_True;
-                    sTabFilts[1].Operator = sheet::FilterOperator_EQUAL;
+                    sTabFilts[1].Operator = sheet::FilterOperator2::EQUAL;
                 }
             }
         }
 
-        xDesc->setFilterFields( sTabFilts );
+        xDesc->setFilterFields2( sTabFilts );
         if ( !bAll )
         {
             xDataBaseRange->refresh();
@@ -4313,6 +4319,7 @@ ScVbaRange::AutoFilter( const uno::Any& Field, const uno::Any& Criteria1, const
         else
             // was 0 based now seems to be 1 
             lcl_SetAllQueryForField( pShell, nField, nSheet );
+        }
     }
     else 
     {
@@ -4333,7 +4340,10 @@ ScVbaRange::AutoFilter( const uno::Any& Field, const uno::Any& Criteria1, const
                     lcl_SetAllQueryForField( pShell, rEntry.nField, nSheet );
             }
             // remove exising filters
-            xDataBaseRange->getFilterDescriptor()->setFilterFields( uno::Sequence< sheet::TableFilterField >() );
+            uno::Reference< sheet::XSheetFilterDescriptor2 > xSheetFilterDescriptor(
+                    xDataBaseRange->getFilterDescriptor(), uno::UNO_QUERY );
+            if( xSheetFilterDescriptor.is() )
+                xSheetFilterDescriptor->setFilterFields2( uno::Sequence< sheet::TableFilterField2 >() );
         }
         xDBRangeProps->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("AutoFilter") ), uno::Any(!bHasAuto) );
 
diff --git a/sc/source/ui/view/cellsh1.cxx b/sc/source/ui/view/cellsh1.cxx
index 77b3189..308ca7f 100644
--- a/sc/source/ui/view/cellsh1.cxx
+++ b/sc/source/ui/view/cellsh1.cxx
@@ -1709,32 +1709,7 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq )
             break;
 
         case SID_TOGGLE_REL:
-            {
-                BOOL bOk = FALSE;
-                SCCOL nCol = GetViewData()->GetCurX();
-                SCROW nRow = GetViewData()->GetCurY();
-                SCTAB nTab = GetViewData()->GetTabNo();
-                ScDocument* pDoc = GetViewData()->GetDocument();
-                CellType eType;
-                pDoc->GetCellType( nCol, nRow, nTab, eType );
-                if (eType == CELLTYPE_FORMULA)
-                {
-                    String aOld;
-                    pDoc->GetFormula( nCol, nRow, nTab, aOld );
-                    xub_StrLen nLen = aOld.Len();
-                    ScRefFinder aFinder( aOld, pDoc );
-                    aFinder.ToggleRel( 0, nLen );
-                    if (aFinder.GetFound())
-                    {
-                        String aNew = aFinder.GetText();
-                        pTabViewShell->EnterData( nCol, nRow, nTab, aNew );
-                        pTabViewShell->UpdateInputHandler();
-                        bOk = TRUE;
-                    }
-                }
-                if (!bOk)
-                    pTabViewShell->ErrorMessage(STR_ERR_NOREF);
-            }
+            pTabViewShell->DoRefConversion();
             break;
 
         case SID_DEC_INDENT:
diff --git a/sc/source/ui/view/viewfun4.cxx b/sc/source/ui/view/viewfun4.cxx
index f541e53..62cfd03 100644
--- a/sc/source/ui/view/viewfun4.cxx
+++ b/sc/source/ui/view/viewfun4.cxx
@@ -81,6 +81,9 @@
 #include "impex.hxx"
 #include "editutil.hxx"
 #include "editable.hxx"
+#include "dociter.hxx"
+#include "reffind.hxx"
+#include "compiler.hxx"
 
 using namespace com::sun::star;
 
@@ -187,7 +190,128 @@ void ScViewFunc::PasteRTF( SCCOL nStartCol, SCROW nStartRow,
         ShowAllCursors();
     }
 }
+void ScViewFunc::DoRefConversion( BOOL bRecord )
+{
+    ScDocument* pDoc = GetViewData()->GetDocument();
+    ScMarkData& rMark = GetViewData()->GetMarkData();
+    SCTAB nTabCount = pDoc->GetTableCount();
+    if (bRecord && !pDoc->IsUndoEnabled())
+        bRecord = FALSE;
+
+    ScRange aMarkRange;
+    rMark.MarkToSimple();
+    BOOL bMulti = rMark.IsMultiMarked();
+    if (bMulti)
+        rMark.GetMultiMarkArea( aMarkRange );
+    else if (rMark.IsMarked())
+        rMark.GetMarkArea( aMarkRange );
+    else
+    {
+        aMarkRange = ScRange( GetViewData()->GetCurX(),
+            GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
+    }
+    ScEditableTester aTester( pDoc, aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), 
+                            aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(),rMark );
+    if (!aTester.IsEditable())
+    {
+        ErrorMessage(aTester.GetMessageId());
+        return;
+    }
 
+    ScDocShell* pDocSh = GetViewData()->GetDocShell();
+    BOOL bOk = FALSE;
+
+    ScDocument* pUndoDoc = NULL;
+    if (bRecord)
+    {
+        pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+        SCTAB nTab = aMarkRange.aStart.Tab();
+        pUndoDoc->InitUndo( pDoc, nTab, nTab );
+
+        if ( rMark.GetSelectCount() > 1 )
+        {           
+            for (SCTAB i=0; i<nTabCount; i++)
+                if ( rMark.GetTableSelect(i) && i != nTab )
+                    pUndoDoc->AddUndoTab( i, i );
+        }
+        ScRange aCopyRange = aMarkRange;
+        aCopyRange.aStart.SetTab(0);
+        aCopyRange.aEnd.SetTab(nTabCount-1);
+        pDoc->CopyToDocument( aCopyRange, IDF_ALL, bMulti, pUndoDoc, &rMark );
+    }
+
+    ScRangeListRef xRanges;
+    GetViewData()->GetMultiArea( xRanges );
+    ULONG nCount = xRanges->Count();
+
+    for (SCTAB i=0; i<nTabCount; i++)
+    {
+        if (rMark.GetTableSelect(i))
+        {
+            for (ULONG j=0; j<nCount; j++)
+            {
+                ScRange aRange = *xRanges->GetObject(j);
+                aRange.aStart.SetTab(i);
+                aRange.aEnd.SetTab(i);
+                ScCellIterator aIter( pDoc, aRange );
+                ScBaseCell* pCell = aIter.GetFirst();
+                while ( pCell )
+                {
+                    if (pCell->GetCellType() == CELLTYPE_FORMULA)
+                    {
+                        String aOld;
+                        ((ScFormulaCell*)pCell)->GetFormula(aOld);
+                        xub_StrLen nLen = aOld.Len();
+                        ScRefFinder aFinder( aOld, pDoc );
+                        aFinder.ToggleRel( 0, nLen );
+                        if (aFinder.GetFound())
+                        {
+                            ScAddress aPos = ((ScFormulaCell*)pCell)->aPos;
+                            String aNew = aFinder.GetText(); 
+                            ScCompiler aComp( pDoc, aPos);           
+                            aComp.SetGrammar(pDoc->GetGrammar());
+                            ScTokenArray* pArr = aComp.CompileString( aNew );
+                            ScFormulaCell* pNewCell = new ScFormulaCell( pDoc, aPos,
+                                                        pArr,formula::FormulaGrammar::GRAM_DEFAULT, MM_NONE );
+                            pDoc->PutCell( aPos, pNewCell );
+                            bOk = TRUE;
+                        }
+                    }
+                    pCell = aIter.GetNext();
+                }
+            }
+        }
+    }
+    if (bRecord)
+    {
+        ScDocument* pRedoDoc = new ScDocument( SCDOCMODE_UNDO );
+        SCTAB nTab = aMarkRange.aStart.Tab();
+        pRedoDoc->InitUndo( pDoc, nTab, nTab );
+
+        if ( rMark.GetSelectCount() > 1 )
+        {           
+            for (SCTAB i=0; i<nTabCount; i++)
+                if ( rMark.GetTableSelect(i) && i != nTab )
+                    pRedoDoc->AddUndoTab( i, i );
+        }
+        ScRange aCopyRange = aMarkRange;
+        aCopyRange.aStart.SetTab(0);
+        aCopyRange.aEnd.SetTab(nTabCount-1);
+        pDoc->CopyToDocument( aCopyRange, IDF_ALL, bMulti, pRedoDoc, &rMark );
+
+        pDocSh->GetUndoManager()->AddUndoAction(
+            new ScUndoRefConversion( pDocSh,
+                                    aMarkRange, rMark, pUndoDoc, pRedoDoc, bMulti, IDF_ALL) );
+    }
+
+    pDocSh->PostPaint( aMarkRange, PAINT_GRID );
+    pDocSh->UpdateOle(GetViewData());
+    pDocSh->SetDocumentModified();
+    CellContentChanged();
+
+    if (!bOk)
+        ErrorMessage(STR_ERR_NOREF);
+}
 //	Thesaurus - Undo ok
 void ScViewFunc::DoThesaurus( BOOL bRecord )
 {
@@ -537,11 +661,13 @@ BOOL ScViewFunc::PasteFile( const Point& rPos, const String& rFile, BOOL bLink )
             SfxDispatcher &rDispatcher = GetViewData()->GetDispatcher();
             SfxStringItem aFileNameItem( SID_FILE_NAME, aStrURL );
             SfxStringItem aFilterItem( SID_FILTER_NAME, pFlt->GetName() );
+            // #i69524# add target, as in SfxApplication when the Open dialog is used
+            SfxStringItem aTargetItem( SID_TARGETNAME, String::CreateFromAscii("_default") );
 
             // Asynchron oeffnen, kann naemlich auch aus D&D heraus passieren
             // und das bekommt dem MAC nicht so gut ...
             return BOOL( 0 != rDispatcher.Execute( SID_OPENDOC,
-                                    SFX_CALLMODE_ASYNCHRON, &aFileNameItem, &aFilterItem, 0L) );
+                                    SFX_CALLMODE_ASYNCHRON, &aFileNameItem, &aFilterItem, &aTargetItem, 0L) );
         }
     }
 
diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
index 7ba2130..4f52f31 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -599,6 +599,7 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rS
                     }
                     else
                     {
+                        DELETEZ(pUndoData);
                         ScFormulaCell* pCell = new ScFormulaCell( aCell, *pDoc, aPos );
                         if ( nError )
                         {
@@ -751,12 +752,13 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const EditTextOb
         ScPatternAttr* pCellAttrs = NULL;
         EditTextObject* pNewData = NULL;
         String aString;
+
+        const ScPatternAttr* pOldPattern = pDoc->GetPattern( nCol, nRow, nTab );
+        ScTabEditEngine aEngine( *pOldPattern, pDoc->GetEnginePool() );
+        aEngine.SetText(*pData);
+
         if (bTestSimple)					// Testen, ob einfacher String ohne Attribute
         {
-            const ScPatternAttr* pOldPattern = pDoc->GetPattern( nCol, nRow, nTab );
-            ScTabEditEngine aEngine( *pOldPattern, pDoc->GetEnginePool() );
-            aEngine.SetText(*pData);
-
             ScEditAttrTester aAttrTester( &aEngine );
             bSimple = !aAttrTester.NeedsObject();
             bCommon = aAttrTester.NeedsCellAttr();
@@ -777,11 +779,11 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const EditTextOb
                 pCellAttrs->GetFromEditItemSet( &aAttrTester.GetAttribs() );
                 //!	remove common attributes from EditEngine?
             }
-
-            if (bSimple)
-                aString = aEngine.GetText();
         }
 
+        // #i97726# always get text for "repeat" of undo action
+        aString = ScEditUtil::GetSpaceDelimitedString(aEngine);
+
         //
         // 		Undo
         //
@@ -838,7 +840,7 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const EditTextOb
             {	// wg. ChangeTrack erst jetzt
                 pDocSh->GetUndoManager()->AddUndoAction(
                     new ScUndoEnterData( pDocSh, nCol, nRow, nTab, nPos, pTabs,
-                                        ppOldCells, NULL, NULL, String(),
+                                        ppOldCells, NULL, NULL, aString,
                                         pUndoData ) );
             }
 


More information about the ooo-build-commit mailing list