[Libreoffice-commits] .: Branch 'libreoffice-3-3' - 7 commits - sc/inc sc/source

Kohei Yoshida kohei at kemper.freedesktop.org
Fri Jan 7 14:07:58 PST 2011


 sc/inc/document.hxx                      |   22 ++++++-
 sc/inc/drwlayer.hxx                      |    2 
 sc/inc/table.hxx                         |   16 ++++-
 sc/source/core/data/document.cxx         |    7 +-
 sc/source/core/data/drwlayer.cxx         |    6 +-
 sc/source/core/data/table1.cxx           |   38 ++++++++----
 sc/source/core/data/table2.cxx           |   93 +++++++++++++++++++++++++------
 sc/source/core/data/table3.cxx           |   74 +++++++++++++++++++++++-
 sc/source/filter/xml/xmlrowi.cxx         |   17 ++++-
 sc/source/ui/docshell/externalrefmgr.cxx |    7 +-
 sc/source/ui/view/dbfunc.cxx             |    5 +
 sc/source/ui/view/tabvwshe.cxx           |    4 +
 12 files changed, 236 insertions(+), 55 deletions(-)

New commits:
commit 0fe55349b05fae496a86a3fa958d184f0453916c
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Fri Jan 7 17:03:44 2011 -0500

    This is also part of the merge.

diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index d92c2a8..55974e2 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -1645,7 +1645,6 @@ SCSIZE ScTable::Query(ScQueryParam& rParamOrg, BOOL bKeepSub)
                             aParam.nDestCol, aParam.nDestRow, aParam.nDestTab );
     }
 
-    InitializeNoteCaptions();
     if (aParam.bInplace)
         IncRecalcLevel();       // #i116164# once for all entries
 
@@ -1786,7 +1785,7 @@ SCSIZE ScTable::Query(ScQueryParam& rParamOrg, BOOL bKeepSub)
         DecRecalcLevel();
 
     delete[] pSpecial;
-    SetDrawPageSize();
+
     return nCount;
 }
 
commit c64adfe893eea2d86c46a07ec9c3f99a7b465734
Merge: c8a34b0... 1509a04...
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Fri Jan 7 15:44:10 2011 -0500

    Merge commit 'ooo/OOO330_m19' into libreoffice-3-3
    
    Conflicts:
    	sc/source/core/data/table2.cxx
    	sc/source/core/data/table3.cxx

diff --cc sc/inc/document.hxx
index 3dc346c,ae323f6..07cabf9
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@@ -930,13 -918,29 +930,29 @@@ public
      USHORT			GetErrCode( const ScAddress& ) const;
  
                      /** Shrink a range to only include data area.
+ 
                          This is not the actually used area within the 
                          selection, but the bounds of the sheet's data area 
-                         instead. */
+                         instead.
+ 
 -                        @returns TRUE if the area passed intersected the data 
 -                                 area, FALSE if not, in which case the values 
 -                                 obtained may be out of bounds, not in order or 
 -                                 unmodified. TRUE does not mean that there 
++                        @returns TRUE if the area passed intersected the data
++                                 area, FALSE if not, in which case the values
++                                 obtained may be out of bounds, not in order or
++                                 unmodified. TRUE does not mean that there
+                                  actually is any data within the selection.
+                      */
      bool            ShrinkToDataArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow ) const;
  
-                     /** Shrink a range to only include used data area. */
-     bool            ShrinkToUsedDataArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const;
+                     /** Shrink a range to only include used data area.
 -                        
++
+                         @param o_bShrunk
+                                Out parameter, TRUE if area was shrunk, FALSE if not.
+ 
+                         @returns TRUE if there is any data, FALSE if not.
+                      */
+     bool            ShrinkToUsedDataArea( bool& o_bShrunk,
+                                           SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow,
+                                           SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const;
  
      void            GetDataArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow,
                                   SCCOL& rEndCol, SCROW& rEndRow, BOOL bIncludeOld, bool bOnlyDown ) const;
diff --cc sc/inc/table.hxx
index 8edec9f,c184680..66a64c7
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@@ -86,12 -84,19 +86,23 @@@ class CollatorWrapper
  class ScFlatUInt16RowSegments;
  class ScFlatBoolRowSegments;
  class ScFlatBoolColSegments;
 +struct ScSetStringParam;
 +struct ScColWidthParam;
 +struct ScColWidthParam;
  
 +typedef std::hash_map< ::rtl::OUString, rtl::OUString, ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > NameToNameMap;
  
+ struct ScShowRowsEntry
+ {
+     SCROW   mnRow1;
+     SCROW   mnRow2;
+     bool    mbShow;
+ 
+     ScShowRowsEntry( SCROW nR1, SCROW nR2, bool bS ) :
+         mnRow1(nR1), mnRow2(nR2), mbShow(bS) {}
+ };
+ 
+ 
  class ScTable
  {
  private:
diff --cc sc/source/core/data/document.cxx
index 2a66a64,8e3bb7a..eb4af87
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@@ -712,11 -702,14 +712,14 @@@ bool ScDocument::ShrinkToUsedDataArea( 
          SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const
  {
      if (!ValidTab(nTab) || !pTab[nTab])
+     {
+         o_bShrunk = false;
          return false;
-     return pTab[nTab]->ShrinkToUsedDataArea( rStartCol, rStartRow, rEndCol, rEndRow, bColumnsOnly);
+     }
+     return pTab[nTab]->ShrinkToUsedDataArea( o_bShrunk, rStartCol, rStartRow, rEndCol, rEndRow, bColumnsOnly);
  }
  
 -//	zusammenhaengender Bereich
 +// connected area
  
  void ScDocument::GetDataArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow,
                                SCCOL& rEndCol, SCROW& rEndRow, BOOL bIncludeOld, bool bOnlyDown ) const
diff --cc sc/source/core/data/table2.cxx
index 7413c70,cb07bda..752208f
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@@ -2615,9 -2645,11 +2635,10 @@@ void ScTable::DBShowRow(SCROW nRow, boo
  }
  
  
- void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
+ void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, bool bShow, bool bSetFlags)
  {
+     // #i116164# IncRecalcLevel/DecRecalcLevel is in ScTable::Query
      SCROW nStartRow = nRow1;
 -    InitializeNoteCaptions();
      while (nStartRow <= nRow2)
      {
          SCROW nEndRow = -1;
diff --cc sc/source/core/data/table3.cxx
index c02939c,542d3a6..d92c2a8
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@@ -1643,8 -1491,15 +1645,16 @@@ SCSIZE ScTable::Query(ScQueryParam& rPa
                              aParam.nDestCol, aParam.nDestRow, aParam.nDestTab );
      }
  
 +    InitializeNoteCaptions();
-     for (SCROW j=aParam.nRow1 + nHeader; j<=nEndRow; j++)
+     if (aParam.bInplace)
+         IncRecalcLevel();       // #i116164# once for all entries
+ 
+     // #i116164# If there are no drawing objects within the area, call SetRowHidden/SetRowFiltered for all rows at the end
+     std::vector<ScShowRowsEntry> aEntries;
+     ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
+     bool bHasObjects = pDrawLayer && pDrawLayer->HasObjectsInRows( nTab, aParam.nRow1 + nHeader, aParam.nRow2, false );
+ 
+     for (SCROW j=aParam.nRow1 + nHeader; j<=aParam.nRow2; j++)
      {
          BOOL bResult;									// Filterergebnis
          BOOL bValid = ValidQuery(j, aParam, pSpecial);
@@@ -1718,10 -1577,61 +1732,61 @@@
      }
  
      if (aParam.bInplace && bStarted)
-         DBShowRows(nOldStart,nOldEnd, bOldResult);
+     {
+         DBShowRows(nOldStart,nOldEnd, bOldResult, bHasObjects);
+         if (!bHasObjects)
+             aEntries.push_back(ScShowRowsEntry(nOldStart, nOldEnd, bOldResult));
+     }
+ 
+     // #i116164# execute the collected SetRowHidden/SetRowFiltered calls
+     if (!bHasObjects)
+     {
+         std::vector<ScShowRowsEntry>::const_iterator aEnd = aEntries.end();
+         std::vector<ScShowRowsEntry>::const_iterator aIter = aEntries.begin();
+         if ( aIter != aEnd )
+         {
+             // do only one HeightChanged call with the final difference in heights
+             long nOldHeight = 0;
+             if ( pDrawLayer )
+                 nOldHeight = static_cast<long>(GetRowHeight(aParam.nRow1 + nHeader, aParam.nRow2));
+ 
+             // clear the range first instead of many changes in the middle of the filled array
+             SetRowHidden(aParam.nRow1 + nHeader, aParam.nRow2, false);
+             SetRowFiltered(aParam.nRow1 + nHeader, aParam.nRow2, false);
+ 
+             // insert from back, in case the filter range is large
+             mpHiddenRows->setInsertFromBack(true);
+             mpFilteredRows->setInsertFromBack(true);
+ 
+             while (aIter != aEnd)
+             {
+                 if (!aIter->mbShow)
+                 {
+                     SCROW nStartRow = aIter->mnRow1;
+                     SCROW nEndRow = aIter->mnRow2;
+                     SetRowHidden(nStartRow, nEndRow, true);
+                     SetRowFiltered(nStartRow, nEndRow, true);
+                 }
+                 ++aIter;
+             }
+ 
+             mpHiddenRows->setInsertFromBack(false);
+             mpFilteredRows->setInsertFromBack(false);
+ 
+             if ( pDrawLayer )
+             {
+                 // if there are no objects in the filtered range, a single HeightChanged call is enough
+                 long nNewHeight = static_cast<long>(GetRowHeight(aParam.nRow1 + nHeader, aParam.nRow2));
+                 pDrawLayer->HeightChanged( nTab, aParam.nRow1 + nHeader, nNewHeight - nOldHeight );
+             }
+         }
+     }
+ 
+     if (aParam.bInplace)
+         DecRecalcLevel();
  
      delete[] pSpecial;
 -
 +    SetDrawPageSize();
      return nCount;
  }
  
commit 1509a04294f7134ebdda348d969af25354f90e23
Merge: a09c206... 2e78560...
Author: Kurt Zenker <kz at openoffice.org>
Date:   Thu Jan 6 16:49:55 2011 +0100

    CWS-TOOLING: integrate CWS calc64

commit a09c206998f92f799ba408aeae8263ac1159b683
Merge: b6ea51b... 8839ada...
Author: Kurt Zenker <kz at openoffice.org>
Date:   Thu Jan 6 14:53:34 2011 +0100

    CWS-TOOLING: integrate CWS ooo33gsl13

commit 2e7856016590b7c2ac910eaabd5cf860ba135520
Author: Niklas Nebel <nn at openoffice.org>
Date:   Wed Jan 5 11:52:05 2011 +0100

    calc64: remove a warning

diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 3f9db7f..75cb5d5 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -2717,7 +2717,6 @@ void ScTable::ShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
         BOOL bChanged = ( bWasVis != bShow );
         if ( bChanged && bHasObjects )
         {
-            ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
             if (pDrawLayer)
             {
                 long nHeight = static_cast<long>(mpRowHeights->getSumValue(nStartRow, nEndRow));
commit 0c2ccbd2fe129b2c7adf368a8a1fb855bf22fc02
Author: Niklas Nebel <nn at openoffice.org>
Date:   Wed Jan 5 11:30:14 2011 +0100

    calc64: #i116164# performance of filters with many filtered ranges

diff --git a/sc/inc/drwlayer.hxx b/sc/inc/drwlayer.hxx
index 0d76cfa..5900113 100644
--- a/sc/inc/drwlayer.hxx
+++ b/sc/inc/drwlayer.hxx
@@ -159,7 +159,7 @@ public:
     void			WidthChanged( SCTAB nTab, SCCOL nCol, long nDifTwips );
     void			HeightChanged( SCTAB nTab, SCROW nRow, long nDifTwips );
 
-    BOOL			HasObjectsInRows( SCTAB nTab, SCROW nStartRow, SCROW nEndRow );
+    BOOL            HasObjectsInRows( SCTAB nTab, SCROW nStartRow, SCROW nEndRow, bool bIncludeNotes = true );
 
     void			DeleteObjectsInArea( SCTAB nTab, SCCOL nCol1,SCROW nRow1,
                                             SCCOL nCol2,SCROW nRow2 );
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index a40dfaf..1895600 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -86,6 +86,17 @@ class ScFlatBoolRowSegments;
 class ScFlatBoolColSegments;
 
 
+struct ScShowRowsEntry
+{
+    SCROW   mnRow1;
+    SCROW   mnRow2;
+    bool    mbShow;
+
+    ScShowRowsEntry( SCROW nR1, SCROW nR2, bool bS ) :
+        mnRow1(nR1), mnRow2(nR2), mbShow(bS) {}
+};
+
+
 class ScTable
 {
 private:
@@ -657,7 +668,7 @@ public:
     void		DBShowRow(SCROW nRow, bool bShow);
 
     void		ShowRows(SCROW nRow1, SCROW nRow2, bool bShow);
-    void		DBShowRows(SCROW nRow1, SCROW nRow2, bool bShow);
+    void        DBShowRows(SCROW nRow1, SCROW nRow2, bool bShow, bool bSetFlags);   // if bSetFlags=false, no SetRowHidden/SetRowFiltered
 
     void		SetColFlags( SCCOL nCol, BYTE nNewFlags );
     void		SetRowFlags( SCROW nRow, BYTE nNewFlags );
diff --git a/sc/source/core/data/drwlayer.cxx b/sc/source/core/data/drwlayer.cxx
index 2718824..c4d7211 100644
--- a/sc/source/core/data/drwlayer.cxx
+++ b/sc/source/core/data/drwlayer.cxx
@@ -1137,7 +1137,7 @@ void ScDrawLayer::HeightChanged( SCTAB nTab, SCROW nRow, long nDifTwips )
     MoveAreaTwips( nTab, aRect, Point( 0,nDifTwips ), aTopLeft );
 }
 
-BOOL ScDrawLayer::HasObjectsInRows( SCTAB nTab, SCROW nStartRow, SCROW nEndRow )
+BOOL ScDrawLayer::HasObjectsInRows( SCTAB nTab, SCROW nStartRow, SCROW nEndRow, bool bIncludeNotes )
 {
     DBG_ASSERT( pDoc, "ScDrawLayer::HasObjectsInRows without document" );
     if ( !pDoc )
@@ -1178,7 +1178,9 @@ BOOL ScDrawLayer::HasObjectsInRows( SCTAB nTab, SCROW nStartRow, SCROW nEndRow )
     while ( pObject && !bFound )
     {
         aObjRect = pObject->GetSnapRect();	//! GetLogicRect ?
-        if (aTestRect.IsInside(aObjRect.TopLeft()) || aTestRect.IsInside(aObjRect.BottomLeft()))
+        // #i116164# note captions are handled separately, don't have to be included for each single row height change
+        if ( (aTestRect.IsInside(aObjRect.TopLeft()) || aTestRect.IsInside(aObjRect.BottomLeft())) &&
+             (bIncludeNotes || !IsNoteCaption(pObject)) )
             bFound = TRUE;
 
         pObject = aIter.Next();
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 765f831..3f9db7f 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -774,6 +774,9 @@ void ScTable::CopyToTable(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
                     pDestTab->pRowFlags->CopyFrom(*pRowFlags, nRow1, nRow2);
 
                     // Hidden flags.
+                    // #i116164# Collect information first, then apply the changes,
+                    // so RowHidden doesn't rebuild the tree for each row range.
+                    std::vector<ScShowRowsEntry> aEntries;
                     for (SCROW i = nRow1; i <= nRow2; ++i)
                     {
                         SCROW nThisLastRow, nDestLastRow;
@@ -786,7 +789,8 @@ void ScTable::CopyToTable(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
                             // the last row shouldn't exceed the upper bound the caller specified.
                             nLastRow = nRow2;
     
-                        pDestTab->SetRowHidden(i, nLastRow, bThisHidden);
+                        //pDestTab->SetRowHidden(i, nLastRow, bThisHidden);
+                        aEntries.push_back(ScShowRowsEntry(i, nLastRow, bThisHidden));
 
                         bool bThisHiddenChange = (bThisHidden != bDestHidden);
                         if (bThisHiddenChange && pCharts)
@@ -801,7 +805,20 @@ void ScTable::CopyToTable(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
                         // Jump to the last row of the identical flag segment.
                         i = nLastRow;
                     }
-                
+
+                    std::vector<ScShowRowsEntry>::const_iterator aEnd = aEntries.end();
+                    std::vector<ScShowRowsEntry>::const_iterator aIter = aEntries.begin();
+                    if ( aIter != aEnd )
+                    {
+                        pDestTab->mpHiddenRows->setInsertFromBack(true);    // important for undo document
+                        while (aIter != aEnd)
+                        {
+                            pDestTab->SetRowHidden(aIter->mnRow1, aIter->mnRow2, !aIter->mbShow);
+                            ++aIter;
+                        }
+                        pDestTab->mpHiddenRows->setInsertFromBack(false);
+                    }
+
                     // Filtered flags.
                     for (SCROW i = nRow1; i <= nRow2; ++i)
                     {
@@ -2625,10 +2642,10 @@ void ScTable::DBShowRow(SCROW nRow, bool bShow)
 }
 
 
-void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
+void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, bool bShow, bool bSetFlags)
 {
+    // #i116164# IncRecalcLevel/DecRecalcLevel is in ScTable::Query
     SCROW nStartRow = nRow1;
-    IncRecalcLevel();
     InitializeNoteCaptions();
     while (nStartRow <= nRow2)
     {
@@ -2638,7 +2655,7 @@ void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
             nEndRow = nRow2;
 
         BOOL bChanged = ( bWasVis != bShow );
-        if ( bChanged )
+        if ( bChanged && bSetFlags )
         {
             ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
             if (pDrawLayer)
@@ -2651,8 +2668,13 @@ void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
             }
         }
 
-        SetRowHidden(nStartRow, nEndRow, !bShow);
-        SetRowFiltered(nStartRow, nEndRow, !bShow);
+        // #i116164# Directly modify the flags only if there are drawing objects within the area.
+        // Otherwise, all modifications are made together in ScTable::Query, so the tree isn't constantly rebuilt.
+        if ( bSetFlags )
+        {
+            SetRowHidden(nStartRow, nEndRow, !bShow);
+            SetRowFiltered(nStartRow, nEndRow, !bShow);
+        }
 
         if ( bChanged )
         {
@@ -2669,8 +2691,6 @@ void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
     //	to be done here.
     if (pOutlineTable)
         UpdateOutlineRow( nRow1, nRow2, bShow );
-
-    DecRecalcLevel();
 }
 
 
@@ -2679,6 +2699,14 @@ void ScTable::ShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
     SCROW nStartRow = nRow1;
     IncRecalcLevel();
     InitializeNoteCaptions();
+
+    // #i116164# if there are no drawing objects within the row range, a single HeightChanged call is enough
+    ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
+    bool bHasObjects = pDrawLayer && pDrawLayer->HasObjectsInRows( nTab, nRow1, nRow2, false );
+    long nOldHeight = 0;
+    if ( pDrawLayer && !bHasObjects )
+        nOldHeight = static_cast<long>(GetRowHeight(nRow1, nRow2));
+
     while (nStartRow <= nRow2)
     {
         SCROW nEndRow = -1;
@@ -2687,7 +2715,7 @@ void ScTable::ShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
             nEndRow = nRow2;
 
         BOOL bChanged = ( bWasVis != bShow );
-        if ( bChanged )
+        if ( bChanged && bHasObjects )
         {
             ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
             if (pDrawLayer)
@@ -2700,9 +2728,14 @@ void ScTable::ShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
             }
         }
 
-        SetRowHidden(nStartRow, nEndRow, !bShow);
-        if (bShow)
-            SetRowFiltered(nStartRow, nEndRow, false);
+        // #i116164# Directly modify the flags only if there are drawing objects within the area.
+        // Otherwise, all rows are modified together after the loop, so the tree isn't constantly rebuilt.
+        if ( bHasObjects )
+        {
+            SetRowHidden(nStartRow, nEndRow, !bShow);
+            if (bShow)
+                SetRowFiltered(nStartRow, nEndRow, false);
+        }
 
         if ( bChanged )
         {
@@ -2715,6 +2748,25 @@ void ScTable::ShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
 
         nStartRow = nEndRow + 1;
     }
+
+    if ( !bHasObjects )
+    {
+        // #i116164# set the flags for the whole range at once
+        SetRowHidden(nRow1, nRow2, !bShow);
+        if (bShow)
+            SetRowFiltered(nRow1, nRow2, false);
+
+        if ( pDrawLayer )
+        {
+            // if there are no objects in the range, a single HeightChanged call is enough
+            long nNewHeight = 0;
+            if ( bShow )
+                nNewHeight = static_cast<long>(GetRowHeight(nRow1, nRow2));
+            if ( nNewHeight != nOldHeight )
+                pDrawLayer->HeightChanged( nTab, nRow1, nNewHeight - nOldHeight );
+        }
+    }
+
     DecRecalcLevel();
 }
 
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index d3f025b..542d3a6 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -59,6 +59,8 @@
 #include "cellform.hxx"
 #include "postit.hxx"
 #include "queryparam.hxx"
+#include "segmenttree.hxx"
+#include "drwlayer.hxx"
 
 #include <vector>
 
@@ -1489,6 +1491,14 @@ SCSIZE ScTable::Query(ScQueryParam& rParamOrg, BOOL bKeepSub)
                             aParam.nDestCol, aParam.nDestRow, aParam.nDestTab );
     }
 
+    if (aParam.bInplace)
+        IncRecalcLevel();       // #i116164# once for all entries
+
+    // #i116164# If there are no drawing objects within the area, call SetRowHidden/SetRowFiltered for all rows at the end
+    std::vector<ScShowRowsEntry> aEntries;
+    ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
+    bool bHasObjects = pDrawLayer && pDrawLayer->HasObjectsInRows( nTab, aParam.nRow1 + nHeader, aParam.nRow2, false );
+
     for (SCROW j=aParam.nRow1 + nHeader; j<=aParam.nRow2; j++)
     {
         BOOL bResult;									// Filterergebnis
@@ -1544,7 +1554,11 @@ SCSIZE ScTable::Query(ScQueryParam& rParamOrg, BOOL bKeepSub)
             else
             {
                 if (bStarted)
-                    DBShowRows(nOldStart,nOldEnd, bOldResult);
+                {
+                    DBShowRows(nOldStart,nOldEnd, bOldResult, bHasObjects);
+                    if (!bHasObjects)
+                        aEntries.push_back(ScShowRowsEntry(nOldStart, nOldEnd, bOldResult));
+                }
                 nOldStart = nOldEnd = j;
                 bOldResult = bResult;
             }
@@ -1563,7 +1577,58 @@ SCSIZE ScTable::Query(ScQueryParam& rParamOrg, BOOL bKeepSub)
     }
 
     if (aParam.bInplace && bStarted)
-        DBShowRows(nOldStart,nOldEnd, bOldResult);
+    {
+        DBShowRows(nOldStart,nOldEnd, bOldResult, bHasObjects);
+        if (!bHasObjects)
+            aEntries.push_back(ScShowRowsEntry(nOldStart, nOldEnd, bOldResult));
+    }
+
+    // #i116164# execute the collected SetRowHidden/SetRowFiltered calls
+    if (!bHasObjects)
+    {
+        std::vector<ScShowRowsEntry>::const_iterator aEnd = aEntries.end();
+        std::vector<ScShowRowsEntry>::const_iterator aIter = aEntries.begin();
+        if ( aIter != aEnd )
+        {
+            // do only one HeightChanged call with the final difference in heights
+            long nOldHeight = 0;
+            if ( pDrawLayer )
+                nOldHeight = static_cast<long>(GetRowHeight(aParam.nRow1 + nHeader, aParam.nRow2));
+
+            // clear the range first instead of many changes in the middle of the filled array
+            SetRowHidden(aParam.nRow1 + nHeader, aParam.nRow2, false);
+            SetRowFiltered(aParam.nRow1 + nHeader, aParam.nRow2, false);
+
+            // insert from back, in case the filter range is large
+            mpHiddenRows->setInsertFromBack(true);
+            mpFilteredRows->setInsertFromBack(true);
+
+            while (aIter != aEnd)
+            {
+                if (!aIter->mbShow)
+                {
+                    SCROW nStartRow = aIter->mnRow1;
+                    SCROW nEndRow = aIter->mnRow2;
+                    SetRowHidden(nStartRow, nEndRow, true);
+                    SetRowFiltered(nStartRow, nEndRow, true);
+                }
+                ++aIter;
+            }
+
+            mpHiddenRows->setInsertFromBack(false);
+            mpFilteredRows->setInsertFromBack(false);
+
+            if ( pDrawLayer )
+            {
+                // if there are no objects in the filtered range, a single HeightChanged call is enough
+                long nNewHeight = static_cast<long>(GetRowHeight(aParam.nRow1 + nHeader, aParam.nRow2));
+                pDrawLayer->HeightChanged( nTab, aParam.nRow1 + nHeader, nNewHeight - nOldHeight );
+            }
+        }
+    }
+
+    if (aParam.bInplace)
+        DecRecalcLevel();
 
     delete[] pSpecial;
 
diff --git a/sc/source/filter/xml/xmlrowi.cxx b/sc/source/filter/xml/xmlrowi.cxx
index d99e9f6..4bd614f 100644
--- a/sc/source/filter/xml/xmlrowi.cxx
+++ b/sc/source/filter/xml/xmlrowi.cxx
@@ -171,6 +171,7 @@ void ScXMLTableRowContext::EndElement()
     sal_Int32 nSheet = rXMLImport.GetTables().GetCurrentSheet();
     sal_Int32 nCurrentRow(rXMLImport.GetTables().GetCurrentRow());
     uno::Reference<sheet::XSpreadsheet> xSheet(rXMLImport.GetTables().GetCurrentXSheet());
+    ScDocument* pDoc = rXMLImport.GetDocument();
     if(xSheet.is())
     {
         sal_Int32 nFirstRow(nCurrentRow - nRepeatedRows + 1);
@@ -218,10 +219,18 @@ void ScXMLTableRowContext::EndElement()
                         bVisible = sal_False;
                         bFiltered = sal_True;
                     }
-                    if (!bVisible)
-                        xRowProperties->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_ISVISIBLE)), uno::makeAny(bVisible));
-                    if (bFiltered)
-                        xRowProperties->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_ISFILTERED)), uno::makeAny(bFiltered));
+
+                    // #i116164# call SetRowHidden/SetRowFiltered directly, so the tree doesn't have to be rebuilt
+                    // to compare with existing hidden flags.
+                    if (!bVisible && pDoc)
+                        pDoc->SetRowHidden((SCROW)nFirstRow, (SCROW)nCurrentRow, (SCTAB)nSheet, true);
+                    if (bFiltered && pDoc)
+                        pDoc->SetRowFiltered((SCROW)nFirstRow, (SCROW)nCurrentRow, (SCTAB)nSheet, true);
+
+                    //if (!bVisible)
+                    //    xRowProperties->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_ISVISIBLE)), uno::makeAny(bVisible));
+                    //if (bFiltered)
+                    //    xRowProperties->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_ISFILTERED)), uno::makeAny(bFiltered));
                 }
             }
         }
commit 8839ada2ba12033f1c7d7ab23f59353e036dbbb2
Author: Eike Rathke [er] <eike.rathke at oracle.com>
Date:   Sat Dec 11 16:08:03 2010 +0100

    ooo33gsl13: #i115906# obtain correct data range for external references
    * Apparently ScTable::GetFirstDataPos() never worked as intended and selected
      the first non-empty row of the first non-empty column instead of also taking
      following columns into account where non-empty rows may be on top of that.
    * Caller of ScDocument::ShrinkToDataArea() must check the return value, if
      false there is no data in the area passed and the values obtained may be out
      of bounds, not in order or unmodified.
    * In ScExternalRefMgr a call of ScDocument::ShrinkToUsedDataArea() was
      intended instead of ScDocument::ShrinkToDataArea(). For this changed the
      return of ShrinkToUsedDataArea() to flag if there is any data and added an
      out parameter to flag if the area was shrunk.
    * Sanitized arguments and slightly optimized ScTable::ShrinkToUsedDataArea()
      to not have to check for >0 and <MAX on each iteration.
    (transplanted from 31b53a2ec7e32f9560464f8a3b9f6c3e07b29083)

diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 82ddefb..ae323f6 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -918,13 +918,29 @@ public:
     USHORT			GetErrCode( const ScAddress& ) const;
 
                     /** Shrink a range to only include data area.
+
                         This is not the actually used area within the 
                         selection, but the bounds of the sheet's data area 
-                        instead. */
+                        instead.
+
+                        @returns TRUE if the area passed intersected the data 
+                                 area, FALSE if not, in which case the values 
+                                 obtained may be out of bounds, not in order or 
+                                 unmodified. TRUE does not mean that there 
+                                 actually is any data within the selection.
+                     */
     bool            ShrinkToDataArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow ) const;
 
-                    /** Shrink a range to only include used data area. */
-    bool            ShrinkToUsedDataArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const;
+                    /** Shrink a range to only include used data area.
+                        
+                        @param o_bShrunk
+                               Out parameter, TRUE if area was shrunk, FALSE if not.
+
+                        @returns TRUE if there is any data, FALSE if not.
+                     */
+    bool            ShrinkToUsedDataArea( bool& o_bShrunk,
+                                          SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow,
+                                          SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const;
 
     void            GetDataArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow,
                                  SCCOL& rEndCol, SCROW& rEndRow, BOOL bIncludeOld, bool bOnlyDown ) const;
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index a40dfaf..c5c0911 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -417,7 +417,8 @@ public:
     void        GetDataArea( SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow,
                              BOOL bIncludeOld, bool bOnlyDown ) const;
 
-    bool		ShrinkToUsedDataArea( SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const;
+    bool        ShrinkToUsedDataArea( bool& o_bShrunk, SCCOL& rStartCol, SCROW& rStartRow,
+                                      SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const;
 
     SCSIZE	    GetEmptyLinesInBlock( SCCOL nStartCol, SCROW nStartRow,
                                         SCCOL nEndCol, SCROW nEndRow, ScDirection eDir );
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index b7ecc94..8e3bb7a 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -698,12 +698,15 @@ bool ScDocument::ShrinkToDataArea(SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow
     return true;  // success!
 }
 
-bool ScDocument::ShrinkToUsedDataArea( SCTAB nTab, SCCOL& rStartCol,
+bool ScDocument::ShrinkToUsedDataArea( bool& o_bShrunk, SCTAB nTab, SCCOL& rStartCol,
         SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const
 {
     if (!ValidTab(nTab) || !pTab[nTab])
+    {
+        o_bShrunk = false;
         return false;
-    return pTab[nTab]->ShrinkToUsedDataArea( rStartCol, rStartRow, rEndCol, rEndRow, bColumnsOnly);
+    }
+    return pTab[nTab]->ShrinkToUsedDataArea( o_bShrunk, rStartCol, rStartRow, rEndCol, rEndRow, bColumnsOnly);
 }
 
 //	zusammenhaengender Bereich
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index b6788eb..98cf23c 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -740,18 +740,28 @@ void ScTable::GetDataArea( SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, S
 }
 
 
-bool ScTable::ShrinkToUsedDataArea( SCCOL& rStartCol, SCROW& rStartRow,
+bool ScTable::ShrinkToUsedDataArea( bool& o_bShrunk, SCCOL& rStartCol, SCROW& rStartRow,
         SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const
 {
-    bool bRet = false;
-    bool bChanged;
+    o_bShrunk = false;
+
+    PutInOrder( rStartCol, rEndCol);
+    PutInOrder( rStartRow, rEndRow);
+    if (rStartCol < 0)
+        rStartCol = 0, o_bShrunk = true;
+    if (rStartRow < 0)
+        rStartRow = 0, o_bShrunk = true;
+    if (rEndCol > MAXCOL)
+        rEndCol = MAXCOL, o_bShrunk = true;
+    if (rEndRow > MAXROW)
+        rEndRow = MAXROW, o_bShrunk = true;
 
+    bool bChanged;
     do
     {
         bChanged = false;
 
-        bool bCont = true;
-        while (rEndCol > 0 && bCont && rStartCol < rEndCol)
+        while (rStartCol < rEndCol)
         {
             if (aCol[rEndCol].IsEmptyBlock( rStartRow, rEndRow))
             {
@@ -759,11 +769,10 @@ bool ScTable::ShrinkToUsedDataArea( SCCOL& rStartCol, SCROW& rStartRow,
                 bChanged = true;
             }
             else
-                bCont = false;
+                break;  // while
         }
 
-        bCont = true;
-        while (rStartCol < MAXCOL && bCont && rStartCol < rEndCol)
+        while (rStartCol < rEndCol)
         {
             if (aCol[rStartCol].IsEmptyBlock( rStartRow, rEndRow))
             {
@@ -771,12 +780,12 @@ bool ScTable::ShrinkToUsedDataArea( SCCOL& rStartCol, SCROW& rStartRow,
                 bChanged = true;
             }
             else
-                bCont = false;
+                break;  // while
         }
 
         if (!bColumnsOnly)
         {
-            if (rStartRow < MAXROW && rStartRow < rEndRow)
+            if (rStartRow < rEndRow)
             {
                 bool bFound = false;
                 for (SCCOL i=rStartCol; i<=rEndCol && !bFound; i++)
@@ -789,7 +798,7 @@ bool ScTable::ShrinkToUsedDataArea( SCCOL& rStartCol, SCROW& rStartRow,
                 }
             }
 
-            if (rEndRow > 0 && rStartRow < rEndRow)
+            if (rStartRow < rEndRow)
             {
                 bool bFound = false;
                 for (SCCOL i=rStartCol; i<=rEndCol && !bFound; i++)
@@ -804,9 +813,12 @@ bool ScTable::ShrinkToUsedDataArea( SCCOL& rStartCol, SCROW& rStartRow,
         }
 
         if (bChanged)
-            bRet = true;
+            o_bShrunk = true;
     } while( bChanged );
-    return bRet;
+
+    return rStartCol != rEndCol || (bColumnsOnly ? 
+            !aCol[rStartCol].IsEmptyBlock( rStartRow, rEndRow) :
+            (rStartRow != rEndRow || aCol[rStartCol].HasDataAt( rStartRow)));
 }
 
 
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 765f831..b527a73 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -1135,10 +1135,16 @@ ScBaseCell* ScTable::GetCell( SCCOL nCol, SCROW nRow ) const
 void ScTable::GetFirstDataPos(SCCOL& rCol, SCROW& rRow) const
 {
     rCol = 0;
-    rRow = 0;
+    rRow = MAXROW+1;
     while (aCol[rCol].IsEmptyData() && rCol < MAXCOL)
         ++rCol;
-    rRow = aCol[rCol].GetFirstDataPos();
+    SCCOL nCol = rCol;
+    while (nCol <= MAXCOL && rRow > 0)
+    {
+        if (!aCol[nCol].IsEmptyData())
+            rRow = ::std::min( rRow, aCol[nCol].GetFirstDataPos());
+        ++nCol;
+    }
 }
 
 void ScTable::GetLastDataPos(SCCOL& rCol, SCROW& rRow) const
@@ -1148,11 +1154,8 @@ void ScTable::GetLastDataPos(SCCOL& rCol, SCROW& rRow) const
     while (aCol[rCol].IsEmptyData() && (rCol > 0))
         rCol--;
     SCCOL nCol = rCol;
-    while ((SCsCOL)nCol >= 0)
-    {
-        rRow = Max(rRow, aCol[nCol].GetLastDataPos());
-        nCol--;
-    }
+    while (nCol >= 0 && rRow < MAXROW)
+        rRow = ::std::max( rRow, aCol[nCol--].GetLastDataPos());
 }
 
 
diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx
index 269c3d5..3941fac 100644
--- a/sc/source/ui/docshell/externalrefmgr.cxx
+++ b/sc/source/ui/docshell/externalrefmgr.cxx
@@ -1392,7 +1392,8 @@ static ScTokenArray* lcl_convertToTokenArray(ScDocument* pSrcDoc, ScRange& rRang
         // Only loop within the data area.
         SCCOL nDataCol1 = nCol1, nDataCol2 = nCol2;
         SCROW nDataRow1 = nRow1, nDataRow2 = nRow2;
-        if (!pSrcDoc->ShrinkToDataArea(nTab, nDataCol1, nDataRow1, nDataCol2, nDataRow2))
+        bool bShrunk;
+        if (!pSrcDoc->ShrinkToUsedDataArea( bShrunk, nTab, nDataCol1, nDataRow1, nDataCol2, nDataRow2, false))
             // no data within specified range.
             continue;
 
@@ -1708,8 +1709,8 @@ ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefToken(
 
     SCCOL nDataCol1 = 0, nDataCol2 = MAXCOL;
     SCROW nDataRow1 = 0, nDataRow2 = MAXROW;
-    pSrcDoc->ShrinkToDataArea(nTab, nDataCol1, nDataRow1, nDataCol2, nDataRow2);
-    if (rCell.Col() < nDataCol1 || nDataCol2 < rCell.Col() || rCell.Row() < nDataRow1 || nDataRow2 < rCell.Row())
+    bool bData = pSrcDoc->ShrinkToDataArea(nTab, nDataCol1, nDataRow1, nDataCol2, nDataRow2);
+    if (!bData || rCell.Col() < nDataCol1 || nDataCol2 < rCell.Col() || rCell.Row() < nDataRow1 || nDataRow2 < rCell.Row())
     {
         // requested cell is outside the data area.  Don't even bother caching
         // this data, but add it to the cached range to prevent accessing the
diff --git a/sc/source/ui/view/dbfunc.cxx b/sc/source/ui/view/dbfunc.cxx
index 308df11..2c29989 100644
--- a/sc/source/ui/view/dbfunc.cxx
+++ b/sc/source/ui/view/dbfunc.cxx
@@ -159,7 +159,10 @@ ScDBData* ScDBFunc::GetDBData( BOOL bMark, ScGetDBMode eMode, ScGetDBSelection e
                     ScDocument* pDoc = pDocSh->GetDocument();
                     SCCOL nCol1 = aRange.aStart.Col(), nCol2 = aRange.aEnd.Col();
                     SCROW nRow1 = aRange.aStart.Row(), nRow2 = aRange.aEnd.Row();
-                    if (pDoc->ShrinkToUsedDataArea( aRange.aStart.Tab(), nCol1, nRow1, nCol2, nRow2, bShrinkColumnsOnly))
+                    bool bShrunk;
+                    pDoc->ShrinkToUsedDataArea( bShrunk, aRange.aStart.Tab(), 
+                            nCol1, nRow1, nCol2, nRow2, bShrinkColumnsOnly);
+                    if (bShrunk)
                     {
                         aRange.aStart.SetCol(nCol1);
                         aRange.aEnd.SetCol(nCol2);
diff --git a/sc/source/ui/view/tabvwshe.cxx b/sc/source/ui/view/tabvwshe.cxx
index 7d0fec8..3314b4e 100644
--- a/sc/source/ui/view/tabvwshe.cxx
+++ b/sc/source/ui/view/tabvwshe.cxx
@@ -97,7 +97,9 @@ String __EXPORT ScTabViewShell::GetSelectionText( BOOL bWholeWord )
                 SCROW nRow1, nRow2;
                 SCTAB nTab1, nTab2;
                 aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
-                if (pDoc->ShrinkToUsedDataArea( nTab1, nCol1, nRow1, nCol2, nRow2, false))
+                bool bShrunk;
+                pDoc->ShrinkToUsedDataArea( bShrunk, nTab1, nCol1, nRow1, nCol2, nRow2, false);
+                if (bShrunk)
                 {
                     aRange.aStart.SetCol( nCol1 );
                     aRange.aStart.SetRow( nRow1 );


More information about the Libreoffice-commits mailing list