[Libreoffice-commits] .: 116 commits - chart2/source sc/CppunitTest_sc_ucalc.mk sc/inc sc/Library_sc.mk sc/Package_qa_unit.mk sc/qa sc/source

Kohei Yoshida kohei at kemper.freedesktop.org
Mon May 9 21:41:47 PDT 2011


 chart2/source/controller/dialogs/tp_Scale.cxx |   45 +
 chart2/source/controller/dialogs/tp_Scale.hxx |    2 
 sc/CppunitTest_sc_ucalc.mk                    |   13 
 sc/Library_sc.mk                              |    1 
 sc/Package_qa_unit.mk                         |   44 +
 sc/inc/address.hxx                            |    2 
 sc/inc/dbcolect.hxx                           |    2 
 sc/inc/document.hxx                           |    3 
 sc/inc/dpcachetable.hxx                       |   20 
 sc/inc/dpobject.hxx                           |   80 +
 sc/inc/dpoutput.hxx                           |   10 
 sc/inc/dpsdbtab.hxx                           |    7 
 sc/inc/dpshttab.hxx                           |    4 
 sc/inc/dptabdat.hxx                           |    3 
 sc/inc/dptablecache.hxx                       |   46 -
 sc/inc/rangenam.hxx                           |    3 
 sc/inc/reffind.hxx                            |    5 
 sc/inc/table.hxx                              |    4 
 sc/qa/unit/Makefile                           |   53 +
 sc/qa/unit/ucalc.cxx                          |  627 ++++++++++++--
 sc/source/core/data/conditio.cxx              |   18 
 sc/source/core/data/documen2.cxx              |   50 -
 sc/source/core/data/documen3.cxx              |    8 
 sc/source/core/data/documen4.cxx              |   85 +-
 sc/source/core/data/document.cxx              |    9 
 sc/source/core/data/dpcachetable.cxx          |   72 -
 sc/source/core/data/dpobject.cxx              |  197 ++++
 sc/source/core/data/dpoutput.cxx              |  208 ++++
 sc/source/core/data/dpsdbtab.cxx              |  118 --
 sc/source/core/data/dpshttab.cxx              |   18 
 sc/source/core/data/dptablecache.cxx          |   95 +-
 sc/source/core/data/scdpoutputimpl.cxx        |  184 ----
 sc/source/core/data/scdpoutputimpl.hxx        |   79 -
 sc/source/core/data/table1.cxx                |   54 +
 sc/source/core/data/table2.cxx                |   60 -
 sc/source/core/data/table4.cxx                |  269 +++---
 sc/source/core/inc/interpre.hxx               |    1 
 sc/source/core/tool/compiler.cxx              |    1 
 sc/source/core/tool/dbcolect.cxx              |   29 
 sc/source/core/tool/interpr1.cxx              |   76 +
 sc/source/core/tool/interpr4.cxx              |   92 +-
 sc/source/core/tool/rangenam.cxx              |   17 
 sc/source/core/tool/reffind.cxx               |  196 +++-
 sc/source/filter/excel/excform.cxx            |   19 
 sc/source/filter/excel/excform8.cxx           |   83 +
 sc/source/filter/excel/read.cxx               |    4 
 sc/source/filter/excel/xepivot.cxx            |    2 
 sc/source/filter/excel/xilink.cxx             |  234 ++++-
 sc/source/filter/excel/xipivot.cxx            |   21 
 sc/source/filter/excel/xistyle.cxx            |    4 
 sc/source/filter/inc/excform.hxx              |   11 
 sc/source/filter/inc/xilink.hxx               |   23 
 sc/source/filter/inc/xipivot.hxx              |    1 
 sc/source/filter/inc/xlstring.hxx             |    2 
 sc/source/filter/xml/XMLExportDataPilot.cxx   |   12 
 sc/source/filter/xml/xmlcelli.cxx             |    2 
 sc/source/ui/app/inputwin.cxx                 |   19 
 sc/source/ui/attrdlg/scabstdlg.cxx            |    3 
 sc/source/ui/cctrl/dpcontrol.cxx              |    1 
 sc/source/ui/dbgui/dapidata.cxx               |    2 
 sc/source/ui/dbgui/dpuiglobal.hxx             |    1 
 sc/source/ui/dbgui/fieldwnd.cxx               |    9 
 sc/source/ui/dbgui/pvlaydlg.cxx               |   35 
 sc/source/ui/docshell/docfunc.cxx             |   24 
 sc/source/ui/docshell/docsh5.cxx              |   60 -
 sc/source/ui/docshell/externalrefmgr.cxx      |   76 +
 sc/source/ui/inc/fieldwnd.hxx                 |    1 
 sc/source/ui/inc/output.hxx                   |   21 
 sc/source/ui/inc/pvlaydlg.hxx                 |    2 
 sc/source/ui/inc/undoblk.hxx                  |    4 
 sc/source/ui/src/popup.src                    |    2 
 sc/source/ui/undo/undoblk3.cxx                |   50 -
 sc/source/ui/vba/excelvbahelper.cxx           |   87 ++
 sc/source/ui/vba/excelvbahelper.hxx           |   16 
 sc/source/ui/vba/vbaapplication.cxx           |    3 
 sc/source/ui/vba/vbaworkbook.cxx              |   28 
 sc/source/ui/vba/vbaworkbook.hxx              |    4 
 sc/source/ui/vba/vbaworkbooks.cxx             |   82 -
 sc/source/ui/vba/vbaworksheet.cxx             |  153 ++-
 sc/source/ui/vba/vbaworksheet.hxx             |    5 
 sc/source/ui/vba/vbaworksheets.cxx            |   70 +
 sc/source/ui/vba/vbaworksheets.hxx            |    1 
 sc/source/ui/view/dbfunc3.cxx                 |   42 
 sc/source/ui/view/editsh.cxx                  |    7 
 sc/source/ui/view/output.cxx                  |   10 
 sc/source/ui/view/output2.cxx                 | 1104 ++++++++++++++++++++++----
 sc/source/ui/view/viewfun4.cxx                |    2 
 sc/source/ui/view/viewfunc.cxx                |    9 
 88 files changed, 3878 insertions(+), 1383 deletions(-)

New commits:
commit a9520a694c8a26228ec2e1714b5705ded3d14c28
Merge: 9698b84... b49cc01...
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Mon May 9 23:47:24 2011 -0400

    Merge branch 'libreoffice-3-4'
    
    Conflicts:
    	sc/CppunitTest_sc_ucalc.mk
    	sc/Module_sc.mk
    	sc/qa/unit/ucalc.cxx
    	sc/source/core/tool/dbcolect.cxx
    	sc/source/filter/excel/excimp8.cxx
    	sc/source/filter/inc/excimp8.hxx
    	sc/source/ui/docshell/impex.cxx
    	sc/source/ui/unoobj/datauno.cxx

diff --cc sc/qa/unit/ucalc.cxx
index 242a092,7a6d46e..a27b591
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@@ -823,41 -921,261 +937,261 @@@ void Test::testDataPilot(
  
      pDPObj->Output(aOutRange.aStart);
      aOutRange = pDPObj->GetOutRange();
-     const ScAddress& s = aOutRange.aStart;
-     const ScAddress& e = aOutRange.aEnd;
-     printer.resize(e.Row() - s.Row() + 1, e.Col() - s.Col() + 1);
-     SCROW nOutRowSize = SAL_N_ELEMENTS(aOutputCheck);
-     SCCOL nOutColSize = SAL_N_ELEMENTS(aOutputCheck[0]);
-     CPPUNIT_ASSERT_MESSAGE("Row size of the table output is not as expected.",
-                            nOutRowSize == (e.Row()-s.Row()+1));
-     CPPUNIT_ASSERT_MESSAGE("Column size of the table output is not as expected.",
-                            nOutColSize == (e.Col()-s.Col()+1));
-     for (SCROW nRow = 0; nRow < nOutRowSize; ++nRow)
      {
-         for (SCCOL nCol = 0; nCol < nOutColSize; ++nCol)
+         // Expected output table content.  0 = empty cell
+         const char* aOutputCheck[][5] = {
+             { "Sum - Score", "Group", 0, 0, 0 },
+             { "Name", "A", "B", "C", "Total Result" },
+             { "Andy", "30", 0, 0, "30" },
+             { "Bruce", "20", 0, 0, "20" },
+             { "Charlie", 0, "45", 0, "45" },
+             { "David", 0, "12", 0, "12" },
+             { "Edward", 0, 0, "8", "8" },
+             { "Frank", 0, 0, "15", "15" },
+             { "Total Result", "50", "57", "23", "130" }
+         };
+ 
+         bSuccess = checkDPTableOutput<5>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output");
+         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
+     }
+ 
+     // Update the cell values.
+     double aData2[] = { 100, 200, 300, 400, 500, 600 };
+     for (size_t i = 0; i < SAL_N_ELEMENTS(aData2); ++i)
+     {
+         SCROW nRow = i + 1;
+         m_pDoc->SetValue(2, nRow, 0, aData2[i]);
+     }
+ 
+     printer.resize(nRow2 - nRow1 + 1, nCol2 - nCol1 + 1);
+     for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
+     {
+         for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
          {
              String aVal;
-             m_pDoc->GetString(nCol + s.Col(), nRow + s.Row(), s.Tab(), aVal);
+             m_pDoc->GetString(nCol, nRow, 0, aVal);
+             printer.set(nRow, nCol, aVal);
+         }
+     }
+     printer.print("Data sheet content (modified)");
+     printer.clear();
+ 
+     // Now, create a copy of the datapilot object for the updated table, but
+     // don't clear the cache which should force the copy to use the old data
+     // from the cache.
+     ScDPObject* pDPObj2 = new ScDPObject(*pDPObj);
+     pDPs->FreeTable(pDPObj);
+     pDPs->InsertNewTable(pDPObj2);
+ 
+     aOutRange = pDPObj2->GetOutRange();
+     pDPObj2->ClearSource();
+     pDPObj2->Output(aOutRange.aStart);
+     {
+         // Expected output table content.  0 = empty cell
+         const char* aOutputCheck[][5] = {
+             { "Sum - Score", "Group", 0, 0, 0 },
+             { "Name", "A", "B", "C", "Total Result" },
+             { "Andy", "30", 0, 0, "30" },
+             { "Bruce", "20", 0, 0, "20" },
+             { "Charlie", 0, "45", 0, "45" },
+             { "David", 0, "12", 0, "12" },
+             { "Edward", 0, 0, "8", "8" },
+             { "Frank", 0, 0, "15", "15" },
+             { "Total Result", "50", "57", "23", "130" }
+         };
+ 
+         bSuccess = checkDPTableOutput<5>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output (from old cache)");
+         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
+     }
+ 
+     // This time clear the cache to refresh the data from the source range.
+     CPPUNIT_ASSERT_MESSAGE("This datapilot should be based on sheet data.", pDPObj2->IsSheetData());
+     ScDPCollection::SheetCaches& rCaches = pDPs->GetSheetCaches();
+     const ScSheetSourceDesc* pDesc = pDPObj2->GetSheetDesc();
+     rCaches.removeCache(pDesc->GetSourceRange());
+     pDPObj2->ClearSource();
+     pDPObj2->Output(aOutRange.aStart);
+ 
+     {
+         // Expected output table content.  0 = empty cell
+         const char* aOutputCheck[][5] = {
+             { "Sum - Score", "Group", 0, 0, 0 },
+             { "Name", "A", "B", "C", "Total Result" },
+             { "Andy", "100", 0, 0, "100" },
+             { "Bruce", "200", 0, 0, "200" },
+             { "Charlie", 0, "300", 0, "300" },
+             { "David", 0, "400", 0, "400" },
+             { "Edward", 0, 0, "500", "500" },
+             { "Frank", 0, 0, "600", "600" },
+             { "Total Result", "300", "700", "1100", "2100" }
+         };
+ 
+         bSuccess = checkDPTableOutput<5>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output (refreshed)");
+         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
+     }
+ 
+     pDPs->FreeTable(pDPObj2);
 -    CPPUNIT_ASSERT_MESSAGE("There shouldn't be any data pilot table stored with the document.", 
++    CPPUNIT_ASSERT_MESSAGE("There shouldn't be any data pilot table stored with the document.",
+                            pDPs->GetCount() == 0);
+ 
+     m_pDoc->DeleteTab(1);
+     m_pDoc->DeleteTab(0);
+ }
+ 
+ void Test::testDataPilotFilters()
+ {
+     m_pDoc->InsertTab(0, OUString(RTL_CONSTASCII_USTRINGPARAM("Data")));
+     m_pDoc->InsertTab(1, OUString(RTL_CONSTASCII_USTRINGPARAM("Table")));
+ 
+     // Dimension definition
+     DPFieldDef aFields[] = {
+         { "Name",   sheet::DataPilotFieldOrientation_HIDDEN },
+         { "Group1", sheet::DataPilotFieldOrientation_HIDDEN },
+         { "Group2", sheet::DataPilotFieldOrientation_PAGE },
+         { "Val1",   sheet::DataPilotFieldOrientation_DATA },
+         { "Val2",   sheet::DataPilotFieldOrientation_DATA }
+     };
+ 
+     // Raw data
+     const char* aData[][5] = {
+         { "A", "1", "A", "1", "10" },
+         { "B", "1", "A", "1", "10" },
+         { "C", "1", "B", "1", "10" },
+         { "D", "1", "B", "1", "10" },
+         { "E", "2", "A", "1", "10" },
+         { "F", "2", "A", "1", "10" },
+         { "G", "2", "B", "1", "10" },
+         { "H", "2", "B", "1", "10" }
+     };
+ 
+     size_t nFieldCount = SAL_N_ELEMENTS(aFields);
+     size_t nDataCount = SAL_N_ELEMENTS(aData);
+ 
+     // Insert field names in row 0.
+     for (size_t i = 0; i < nFieldCount; ++i)
+         m_pDoc->SetString(static_cast<SCCOL>(i), 0, 0, OUString(aFields[i].pName, strlen(aFields[i].pName), RTL_TEXTENCODING_UTF8));
+ 
+     // Insert data into row 1 and downward.
+     for (size_t i = 0; i < nDataCount; ++i)
+     {
+         SCROW nRow = static_cast<SCROW>(i) + 1;
+         for (size_t j = 0; j < nFieldCount; ++j)
+         {
+             SCCOL nCol = static_cast<SCCOL>(j);
+             m_pDoc->SetString(
+                 nCol, nRow, 0, OUString(aData[i][j], strlen(aData[i][j]), RTL_TEXTENCODING_UTF8));
+         }
+     }
+ 
+     SCROW nRow1 = 0, nRow2 = 0;
+     SCCOL nCol1 = 0, nCol2 = 0;
+     m_pDoc->GetDataArea(0, nCol1, nRow1, nCol2, nRow2, true, false);
+     CPPUNIT_ASSERT_MESSAGE("Data is expected to start from (col=0,row=0).", nCol1 == 0 && nRow1 == 0);
+     CPPUNIT_ASSERT_MESSAGE("Unexpected data range.",
+                            nCol2 == static_cast<SCCOL>(nFieldCount - 1) && nRow2 == static_cast<SCROW>(nDataCount));
+ 
+     SheetPrinter printer(nRow2 - nRow1 + 1, nCol2 - nCol1 + 1);
+     for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
+     {
+         for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+         {
+             String aVal;
+             m_pDoc->GetString(nCol, nRow, 0, aVal);
              printer.set(nRow, nCol, aVal);
-             const char* p = aOutputCheck[nRow][nCol];
-             if (p)
-             {
-                 OUString aCheckVal = OUString::createFromAscii(p);
-                 bool bEqual = aCheckVal.equals(aVal);
-                 if (!bEqual)
-                 {
-                     cerr << "Expected: " << aCheckVal << "  Actual: " << aVal << endl;
- //                    CPPUNIT_ASSERT_MESSAGE("Unexpected cell content.", false);
-                 }
-             }
-             else
-                 CPPUNIT_ASSERT_MESSAGE("Empty cell expected.", aVal.Len() == 0);
          }
      }
-     printer.print("DataPilot table output");
+     printer.print("Data sheet content");
      printer.clear();
  
-     // Now, delete the datapilot object.
+     ScDPObject* pDPObj = createDPFromRange(
+         m_pDoc, ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0), aFields, nFieldCount, true);
+ 
+     ScDPCollection* pDPs = m_pDoc->GetDPCollection();
+     bool bSuccess = pDPs->InsertNewTable(pDPObj);
+     CPPUNIT_ASSERT_MESSAGE("failed to insert a new datapilot object into document", bSuccess);
+     CPPUNIT_ASSERT_MESSAGE("there should be only one data pilot table.",
+                            pDPs->GetCount() == 1);
+     pDPObj->SetName(pDPs->CreateNewName());
+ 
+     bool bOverFlow = false;
+     ScRange aOutRange = pDPObj->GetNewOutputRange(bOverFlow);
+     CPPUNIT_ASSERT_MESSAGE("Table overflow!?", !bOverFlow);
+ 
+     pDPObj->Output(aOutRange.aStart);
+     aOutRange = pDPObj->GetOutRange();
+     {
+         // Expected output table content.  0 = empty cell
+         const char* aOutputCheck[][2] = {
+             { "Filter", 0 },
+             { "Group2", "- all -" },
+             { 0, 0 },
+             { "Data", 0 },
+             { "Sum - Val1", "8" },
+             { "Sum - Val2", "80" },
+             { "Total Sum - Val1", "8" },
+             { "Total Sum - Val2", "80" }
+         };
+ 
+         bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output (unfiltered)");
+         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
+     }
+ 
+     // Set current page of 'Group2' to 'A'.
+     ScDPSaveData aSaveData(*pDPObj->GetSaveData());
+     ScDPSaveDimension* pDim = aSaveData.GetDimensionByName(
+         OUString(RTL_CONSTASCII_USTRINGPARAM("Group2")));
+     CPPUNIT_ASSERT_MESSAGE("Dimension not found", pDim);
+     OUString aPage(RTL_CONSTASCII_USTRINGPARAM("A"));
+     pDim->SetCurrentPage(&aPage);
+     pDPObj->SetSaveData(aSaveData);
+     pDPObj->Output(aOutRange.aStart);
+     aOutRange = pDPObj->GetOutRange();
+     {
+         // Expected output table content.  0 = empty cell
+         const char* aOutputCheck[][2] = {
+             { "Filter", 0 },
+             { "Group2", "A" },
+             { 0, 0 },
+             { "Data", 0 },
+             { "Sum - Val1", "4" },
+             { "Sum - Val2", "40" },
+             { "Total Sum - Val1", "4" },
+             { "Total Sum - Val2", "40" }
+         };
+ 
+         bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output (filtered by page)");
+         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
+     }
+ 
+     // Set query filter.
+     ScSheetSourceDesc aDesc(*pDPObj->GetSheetDesc());
+     ScQueryParam aQueryParam(aDesc.GetQueryParam());
+     CPPUNIT_ASSERT_MESSAGE("There should be at least one query entry.", aQueryParam.GetEntryCount() > 0);
+     ScQueryEntry& rEntry = aQueryParam.GetEntry(0);
+     rEntry.bDoQuery = true;
+     rEntry.nField = 1;  // Group1
+     rEntry.nVal = 1;
+     aDesc.SetQueryParam(aQueryParam);
+     pDPObj->SetSheetDesc(aDesc);
+     pDPObj->Output(aOutRange.aStart);
+     aOutRange = pDPObj->GetOutRange();
+     {
+         // Expected output table content.  0 = empty cell
+         const char* aOutputCheck[][2] = {
+             { "Filter", 0 },
+             { "Group2", "A" },
+             { 0, 0 },
+             { "Data", 0 },
+             { "Sum - Val1", "2" },
+             { "Sum - Val2", "20" },
+             { "Total Sum - Val1", "2" },
+             { "Total Sum - Val2", "20" }
+         };
+ 
+         bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output (filtered by query)");
+         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
+     }
+ 
      pDPs->FreeTable(pDPObj);
      CPPUNIT_ASSERT_MESSAGE("There shouldn't be any data pilot table stored with the document.",
                             pDPs->GetCount() == 0);
diff --cc sc/source/core/tool/dbcolect.cxx
index 2a707eb,635ab5a..dc53395
--- a/sc/source/core/tool/dbcolect.cxx
+++ b/sc/source/core/tool/dbcolect.cxx
@@@ -821,6 -825,27 +825,27 @@@ ScDBData* ScDBCollection::GetDBAtArea(S
      return NULL;	
  }
  
+ ScDBData* ScDBCollection::GetFilterDBAtTable(SCTAB nTab) const
+ {
+     ScDBData* pDataEmpty = NULL;
+     if (pItems)
+     {
+         for (sal_uInt16 i = 0; i < nCount; i++)
+         {
+             ScDBData* pDBTemp = (ScDBData*)pItems[i];
+             if ( pDBTemp->GetTable() == nTab )
 -            {                
 -                sal_Bool bFilter = pDBTemp->HasAutoFilter() || pDBTemp->HasQueryParam();              
 -              
 -                if ( bFilter )                 
++            {
++                sal_Bool bFilter = pDBTemp->HasAutoFilter() || pDBTemp->HasQueryParam();
++
++                if ( bFilter )
+                     return pDBTemp;
+             }
+         }
+     }
+ 
+     return pDataEmpty;
+ }
+ 
  sal_Bool ScDBCollection::SearchName( const String& rName, sal_uInt16& rIndex ) const
  {
      if (rtl::OUString(rName)==rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(STR_DB_LOCAL_NONAME)))
commit b49cc01b9556a434c3c690df3bb6ddad5e0a7802
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Mon May 9 22:54:59 2011 -0400

    fdo#36933: Fixed array comparison with external references.

diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index ce59c16..7caee75 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -316,6 +316,7 @@ void PopExternalSingleRef(ScExternalRefCache::TokenRef& rToken, ScExternalRefCac
 void PopExternalDoubleRef(sal_uInt16& rFileId, String& rTabName, ScComplexRefData& rRef);
 void PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArray);
 void PopExternalDoubleRef(ScMatrixRef& rMat);
+void GetExternalDoubleRef(sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& aData, ScExternalRefCache::TokenArrayRef& rArray);
 sal_Bool PopDoubleRefOrSingleRef( ScAddress& rAdr );
 void PopDoubleRefPushMatrix();
 // If MatrixFormula: convert formula::svDoubleRef to svMatrix, create JumpMatrix.
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 8beb6f1..1999bff 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -810,6 +810,38 @@ double ScInterpreter::Compare()
                 }
             }
             break;
+            case svExternalSingleRef:
+            {
+                ScMatrixRef pMat = GetMatrix();
+                if (!pMat)
+                {
+                    SetError( errIllegalParameter);
+                    break;
+                }
+
+                SCSIZE nC, nR;
+                pMat->GetDimensions(nC, nR);
+                if (!nC || !nR)
+                {
+                    SetError( errIllegalParameter);
+                    break;
+                }
+                if (pMat->IsEmpty(0, 0))
+                    aComp.bEmpty[i] = true;
+                else if (pMat->IsString(0, 0))
+                {
+                    *aComp.pVal[i] = pMat->GetString(0, 0);
+                    aComp.bVal[i] = false;
+                }
+                else
+                {
+                    aComp.nVal[i] = pMat->GetDouble(0, 0);
+                    aComp.bVal[i] = true;
+                }
+            }
+            break;
+            case svExternalDoubleRef:
+                // TODO: Find out how to handle this...
             default:
                 SetError( errIllegalParameter);
             break;
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 551a1c2..bfe5b6b 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -1519,6 +1519,28 @@ void ScInterpreter::PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArr
     if (nGlobalError)
         return;
 
+    GetExternalDoubleRef(nFileId, aTabName, aData, rArray);
+    if (nGlobalError)
+        return;
+}
+
+void ScInterpreter::PopExternalDoubleRef(ScMatrixRef& rMat)
+{
+    ScExternalRefCache::TokenArrayRef pArray;
+    PopExternalDoubleRef(pArray);
+    if (nGlobalError)
+        return;
+
+    // For now, we only support single range data for external
+    // references, which means the array should only contain a
+    // single matrix token.
+    ScToken* p = static_cast<ScToken*>(pArray->First());
+    rMat = p->GetMatrix();
+}
+
+void ScInterpreter::GetExternalDoubleRef(
+    sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& rData, ScExternalRefCache::TokenArrayRef& rArray)
+{
     ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager();
     const String* pFile = pRefMgr->getExternalFileName(nFileId);
     if (!pFile)
@@ -1526,18 +1548,19 @@ void ScInterpreter::PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArr
         SetError(errNoName);
         return;
     }
-    if (aData.Ref1.IsTabRel() || aData.Ref2.IsTabRel())
+    if (rData.Ref1.IsTabRel() || rData.Ref2.IsTabRel())
     {
         OSL_FAIL("ScCompiler::GetToken: external double reference must have an absolute table reference!");
         SetError(errNoRef);
         return;
     }
 
+    ScComplexRefData aData(rData);
     aData.CalcAbsIfRel(aPos);
     ScRange aRange(aData.Ref1.nCol, aData.Ref1.nRow, aData.Ref1.nTab,
                    aData.Ref2.nCol, aData.Ref2.nRow, aData.Ref2.nTab);
     ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(
-        nFileId, aTabName, aRange, &aPos);
+        nFileId, rTabName, aRange, &aPos);
 
     if (!pArray)
     {
@@ -1562,20 +1585,6 @@ void ScInterpreter::PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArr
     rArray = pArray;
 }
 
-void ScInterpreter::PopExternalDoubleRef(ScMatrixRef& rMat)
-{
-    ScExternalRefCache::TokenArrayRef pArray;
-    PopExternalDoubleRef(pArray);
-    if (nGlobalError)
-        return;
-
-    // For now, we only support single range data for external
-    // references, which means the array should only contain a
-    // single matrix token.
-    ScToken* p = static_cast<ScToken*>(pArray->First());
-    rMat = p->GetMatrix();
-}
-
 sal_Bool ScInterpreter::PopDoubleRefOrSingleRef( ScAddress& rAdr )
 {
     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopDoubleRefOrSingleRef" );
@@ -1643,6 +1652,7 @@ bool ScInterpreter::ConvertMatrixParameters()
                 case svDouble:
                 case svString:
                 case svSingleRef:
+                case svExternalSingleRef:
                 case svMissing:
                 case svError:
                 case svEmptyCell:
@@ -1700,6 +1710,35 @@ bool ScInterpreter::ConvertMatrixParameters()
                     }
                 }
                 break;
+                case svExternalDoubleRef:
+                {
+                    ScParameterClassification::Type eType =
+                        ScParameterClassification::GetParameterType( pCur, nParams - i);
+                    if (eType == ScParameterClassification::Array)
+                    {
+                        sal_uInt16 nFileId = p->GetIndex();
+                        const String& rTabName = p->GetString();
+                        const ScComplexRefData& rRef = static_cast<ScToken*>(p)->GetDoubleRef();
+                        ScExternalRefCache::TokenArrayRef pArray;
+                        GetExternalDoubleRef(nFileId, rTabName, rRef, pArray);
+                        if (nGlobalError)
+                            break;
+
+                        ScToken* pTemp = static_cast<ScToken*>(pArray->First());
+                        if (!pTemp)
+                            break;
+
+                        ScMatrixRef pMat = pTemp->GetMatrix();
+                        if (pMat)
+                        {
+                            ScToken* pNew = new ScMatrixToken( pMat);
+                            pNew->IncRef();
+                            pStack[ sp - i ] = pNew;
+                            p->DecRef();    // p may be dead now!
+                        }
+                    }
+                }
+                break;
                 case svRefList:
                 {
                     ScParameterClassification::Type eType =
commit d0b1966c59ae094ebb17a13f9903dbd32db9fb40
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Thu May 5 17:59:58 2011 +0200

    use sheet local db data in ScVbaRange::Autofilter
    
    Signed-off-by: Kohei Yoshida <kyoshida at novell.com>

diff --git a/sc/inc/unonames.hxx b/sc/inc/unonames.hxx
index fb557be..f826e36 100644
--- a/sc/inc/unonames.hxx
+++ b/sc/inc/unonames.hxx
@@ -48,6 +48,7 @@
 #define SC_UNO_EXTERNALDOCLINKS     "ExternalDocLinks"
 #define SC_UNO_COLLABELRNG			"ColumnLabelRanges"
 #define SC_UNO_DATABASERNG			"DatabaseRanges"
+#define SC_UNO_UNNAMEDDBRNG         "UnnamedDatabaseRanges"
 #define SC_UNO_NAMEDRANGES			"NamedRanges"
 #define SC_UNO_ROWLABELRNG			"RowLabelRanges"
 #define SC_UNO_SHEETLINKS			"SheetLinks"
diff --git a/sc/source/ui/docshell/dbdocfun.cxx b/sc/source/ui/docshell/dbdocfun.cxx
index 2173320..245de3b 100644
--- a/sc/source/ui/docshell/dbdocfun.cxx
+++ b/sc/source/ui/docshell/dbdocfun.cxx
@@ -255,7 +255,7 @@ sal_Bool ScDBDocFunc::ModifyDBData( const ScDBData& rNewData, sal_Bool /* bApi *
 
 // -----------------------------------------------------------------
 
-sal_Bool ScDBDocFunc::RepeatDB( const String& rDBName, sal_Bool bRecord, sal_Bool bApi )
+sal_Bool ScDBDocFunc::RepeatDB( const String& rDBName, sal_Bool bRecord, sal_Bool bApi, bool bIsUnnamed, SCTAB aTab )
 {
     //!	auch fuer ScDBFunc::RepeatDB benutzen!
 
@@ -263,12 +263,21 @@ sal_Bool ScDBDocFunc::RepeatDB( const String& rDBName, sal_Bool bRecord, sal_Boo
     ScDocument* pDoc = rDocShell.GetDocument();
     if (bRecord && !pDoc->IsUndoEnabled())
         bRecord = false;
-    ScDBCollection*	pColl = pDoc->GetDBCollection();
-    sal_uInt16 nIndex;
-    if ( pColl && pColl->SearchName( rDBName, nIndex ) )
+    ScDBData* pDBData = NULL;
+    if (bIsUnnamed)
     {
-        ScDBData* pDBData = (*pColl)[nIndex];
+        pDBData = pDoc->GetAnonymousDBData( aTab );
+    }
+    else
+    {
+        sal_uInt16 nIndex;
+        ScDBCollection*	pColl = pDoc->GetDBCollection();
+        if ( pColl && pColl->SearchName( rDBName, nIndex ) )
+            pDBData = (*pColl)[nIndex];
+    }
 
+    if ( pDBData )
+    {
         ScQueryParam aQueryParam;
         pDBData->GetQueryParam( aQueryParam );
         sal_Bool bQuery = aQueryParam.GetEntry(0).bDoQuery;
diff --git a/sc/source/ui/inc/dbdocfun.hxx b/sc/source/ui/inc/dbdocfun.hxx
index bf61081..3598662 100644
--- a/sc/source/ui/inc/dbdocfun.hxx
+++ b/sc/source/ui/inc/dbdocfun.hxx
@@ -114,7 +114,7 @@ public:
     sal_Bool			RenameDBRange( const String& rOld, const String& rNew, sal_Bool bApi );
     sal_Bool			ModifyDBData( const ScDBData& rNewData, sal_Bool bApi );	// Name unveraendert
 
-    sal_Bool			RepeatDB( const String& rDBName, sal_Bool bRecord, sal_Bool bApi );
+    sal_Bool			RepeatDB( const String& rDBName, sal_Bool bRecord, sal_Bool bApi, bool bIsUnnamed=false, SCTAB aTab = 0);
 
     sal_Bool			DataPilotUpdate( ScDPObject* pOldObj, const ScDPObject* pNewObj,
                                         sal_Bool bRecord, sal_Bool bApi, sal_Bool bAllowMove = false );
diff --git a/sc/source/ui/unoobj/datauno.cxx b/sc/source/ui/unoobj/datauno.cxx
index 2e021c0..860db1b 100644
--- a/sc/source/ui/unoobj/datauno.cxx
+++ b/sc/source/ui/unoobj/datauno.cxx
@@ -1908,7 +1908,7 @@ void SAL_CALL ScDatabaseRangeObj::refresh() throw(uno::RuntimeException)
 
         // interne Operationen (sort, query, subtotal) nur, wenn kein Fehler
         if (bContinue)
-            aFunc.RepeatDB( pData->GetName(), sal_True, sal_True );
+            aFunc.RepeatDB( pData->GetName(), true, true, bIsUnnamed, aTab );
     }
 }
 
diff --git a/sc/source/ui/unoobj/docuno.cxx b/sc/source/ui/unoobj/docuno.cxx
index f0e964b..9f4abf5 100644
--- a/sc/source/ui/unoobj/docuno.cxx
+++ b/sc/source/ui/unoobj/docuno.cxx
@@ -56,6 +56,7 @@
 #include <com/sun/star/util/Date.hpp>
 #include <com/sun/star/sheet/XNamedRanges.hpp>
 #include <com/sun/star/sheet/XLabelRanges.hpp>
+#include <com/sun/star/sheet/XUnnamedDatabaseRanges.hpp>
 #include <com/sun/star/i18n/XForbiddenCharacters.hpp>
 #include <com/sun/star/script/XLibraryContainer.hpp>
 #include <com/sun/star/lang/XInitialization.hpp>
@@ -1780,6 +1781,10 @@ uno::Any SAL_CALL ScModelObj::getPropertyValue( const rtl::OUString& aPropertyNa
         {
             aRet <<= uno::Reference<sheet::XDatabaseRanges>(new ScDatabaseRangesObj( pDocShell ));
         }
+        else if ( aString.EqualsAscii( SC_UNO_UNNAMEDDBRNG ) )
+        {
+            aRet <<= uno::Reference<sheet::XUnnamedDatabaseRanges>(new ScUnnamedDatabaseRangesObj(pDocShell));
+        }
         else if ( aString.EqualsAscii( SC_UNO_COLLABELRNG ) )
         {
             aRet <<= uno::Reference<sheet::XLabelRanges>(new ScLabelRangesObj( pDocShell, sal_True ));
diff --git a/sc/source/ui/vba/excelvbahelper.cxx b/sc/source/ui/vba/excelvbahelper.cxx
index d98f1ac..cbf30eb 100644
--- a/sc/source/ui/vba/excelvbahelper.cxx
+++ b/sc/source/ui/vba/excelvbahelper.cxx
@@ -66,36 +66,33 @@ GetDataBaseRanges( ScDocShell* pShell ) throw ( uno::RuntimeException )
     return xDBRanges;
 }
 
+uno::Reference< sheet::XUnnamedDatabaseRanges >
+GetUnnamedDataBaseRanges( ScDocShell* pShell ) throw ( uno::RuntimeException )
+{
+    uno::Reference< frame::XModel > xModel;
+    if ( pShell )
+        xModel.set( pShell->GetModel(), uno::UNO_QUERY_THROW );
+    uno::Reference< beans::XPropertySet > xModelProps( xModel, uno::UNO_QUERY_THROW );
+    uno::Reference< sheet::XUnnamedDatabaseRanges > xUnnamedDBRanges( xModelProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("UnnamedDatabaseRanges") ) ), uno::UNO_QUERY_THROW );
+    return xUnnamedDBRanges;
+}
+
 // returns the XDatabaseRange for the autofilter on sheet (nSheet)
 // also populates sName with the name of range
 uno::Reference< sheet::XDatabaseRange >
-GetAutoFiltRange( ScDocShell* pShell, sal_Int16 nSheet, rtl::OUString& sName ) throw ( uno::RuntimeException )
+GetAutoFiltRange( ScDocShell* pShell, sal_Int16 nSheet ) throw ( uno::RuntimeException )
 {
-    uno::Reference< container::XIndexAccess > xIndexAccess( GetDataBaseRanges( pShell ), uno::UNO_QUERY_THROW );
+    uno::Reference< sheet::XUnnamedDatabaseRanges > xUnnamedDBRanges( GetUnnamedDataBaseRanges( pShell ), uno::UNO_QUERY_THROW );
     uno::Reference< sheet::XDatabaseRange > xDataBaseRange;
-    table::CellRangeAddress dbAddress;
-    for ( sal_Int32 index=0; index < xIndexAccess->getCount(); ++index )
+    if (xUnnamedDBRanges->hasByTable( nSheet ) )
     {
-        uno::Reference< sheet::XDatabaseRange > xDBRange( xIndexAccess->getByIndex( index ), uno::UNO_QUERY_THROW );
-        uno::Reference< container::XNamed > xNamed( xDBRange, uno::UNO_QUERY_THROW );
-        // autofilters work weirdly with openoffice, unnamed is the default
-        // named range which is used to create an autofilter, but
-        // its also possible that another name could be used
-        //     this also causes problems when an autofilter is created on
-        //     another sheet
-        // ( but.. you can use any named range )
-        dbAddress = xDBRange->getDataArea();
-        if ( dbAddress.Sheet == nSheet )
+        uno::Reference< sheet::XDatabaseRange > xDBRange( xUnnamedDBRanges->getByTable( nSheet ) , uno::UNO_QUERY_THROW );
+        sal_Bool bHasAuto = false;
+        uno::Reference< beans::XPropertySet > xProps( xDBRange, uno::UNO_QUERY_THROW );
+        xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("AutoFilter") ) ) >>= bHasAuto;
+        if ( bHasAuto )
         {
-            sal_Bool bHasAuto = false;
-            uno::Reference< beans::XPropertySet > xProps( xDBRange, uno::UNO_QUERY_THROW );
-            xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("AutoFilter") ) ) >>= bHasAuto;
-            if ( bHasAuto )
-            {
-                sName = xNamed->getName();
-                xDataBaseRange=xDBRange;
-                break;
-            }
+            xDataBaseRange=xDBRange;
         }
     }
     return xDataBaseRange;
diff --git a/sc/source/ui/vba/excelvbahelper.hxx b/sc/source/ui/vba/excelvbahelper.hxx
index bf8ae56..eebeaff 100644
--- a/sc/source/ui/vba/excelvbahelper.hxx
+++ b/sc/source/ui/vba/excelvbahelper.hxx
@@ -32,6 +32,7 @@
 #include "docsh.hxx"
 #include <com/sun/star/sheet/XDatabaseRanges.hpp>
 #include <com/sun/star/sheet/XDatabaseRange.hpp>
+#include <com/sun/star/sheet/XUnnamedDatabaseRanges.hpp>
 #include <com/sun/star/table/XCellRange.hpp>
 #include <com/sun/star/sheet/XSheetCellRangeContainer.hpp>
 #include <com/sun/star/sheet/XSpreadsheet.hpp>
@@ -65,8 +66,9 @@ formula::FormulaGrammar::Grammar GetFormulaGrammar( ScDocument* pDoc, const ScAd
 void CompileExcelFormulaToODF( ScDocument* pDoc, const String& rOldFormula, String& rNewFormula );
 void CompileODFFormulaToExcel( ScDocument* pDoc, const String& rOldFormula, String& rNewFormula, const formula::FormulaGrammar::Grammar eGrammar );
 css::uno::Reference< css::sheet::XDatabaseRanges > GetDataBaseRanges( ScDocShell* pShell ) throw ( css::uno::RuntimeException );
+css::uno::Reference< css::sheet::XUnnamedDatabaseRanges > GetUnnamedDataBaseRanges( ScDocShell* pShell ) throw ( css::uno::RuntimeException );
 
-css::uno::Reference< css::sheet::XDatabaseRange > GetAutoFiltRange( ScDocShell* pShell, sal_Int16 nSheet, rtl::OUString& sName ) throw ( css::uno::RuntimeException );
+css::uno::Reference< css::sheet::XDatabaseRange > GetAutoFiltRange( ScDocShell* pShell, sal_Int16 nSheet ) throw ( css::uno::RuntimeException );
 css::uno::Reference< ooo::vba::XHelperInterface > getUnoSheetModuleObj( const css::uno::Reference< css::sheet::XSpreadsheet >& xSheet ) throw ( css::uno::RuntimeException );
 css::uno::Reference< ooo::vba::XHelperInterface > getUnoSheetModuleObj( const css::uno::Reference< css::sheet::XSheetCellRangeContainer >& xRanges ) throw ( css::uno::RuntimeException );
 css::uno::Reference< ooo::vba::XHelperInterface > getUnoSheetModuleObj( const css::uno::Reference< css::table::XCellRange >& xRange ) throw ( css::uno::RuntimeException );
diff --git a/sc/source/ui/vba/vbarange.cxx b/sc/source/ui/vba/vbarange.cxx
index 1895c78..1689b13 100644
--- a/sc/source/ui/vba/vbarange.cxx
+++ b/sc/source/ui/vba/vbarange.cxx
@@ -39,6 +39,7 @@
 #include <com/sun/star/script/vba/XVBAEventProcessor.hpp>
 #include <com/sun/star/sheet/XDatabaseRange.hpp>
 #include <com/sun/star/sheet/XDatabaseRanges.hpp>
+#include <com/sun/star/sheet/XUnnamedDatabaseRanges.hpp>
 #include <com/sun/star/sheet/XGoalSeek.hpp>
 #include <com/sun/star/sheet/XSheetOperation.hpp>
 #include <com/sun/star/sheet/CellFlags.hpp>
@@ -4334,20 +4335,10 @@ ScVbaRange::ApplicationRange( const uno::Reference< uno::XComponentContext >& xC
 // Helper functions for AutoFilter
 ScDBData* lcl_GetDBData_Impl( ScDocShell* pDocShell, sal_Int16 nSheet )
 {
-    rtl::OUString sName;
-    excel::GetAutoFiltRange( pDocShell, nSheet, sName );
-    OSL_TRACE("lcl_GetDBData_Impl got autofilter range %s for sheet %d",
-        rtl::OUStringToOString( sName, RTL_TEXTENCODING_UTF8 ).getStr() , nSheet );
     ScDBData* pRet = NULL;
     if (pDocShell)
     {
-        ScDBCollection* pNames = pDocShell->GetDocument()->GetDBCollection();
-        if (pNames)
-        {
-            sal_uInt16 nPos = 0;
-            if (pNames->SearchName( sName , nPos ))
-                pRet = (*pNames)[nPos];
-        }
+        pRet = pDocShell->GetDocument()->GetAnonymousDBData(nSheet);
     }
     return pRet;
 }
@@ -4501,8 +4492,7 @@ ScVbaRange::AutoFilter( const uno::Any& Field, const uno::Any& Criteria1, const
     sal_Int16 nSheet = thisAddress.Sheet;
     ScDocShell* pShell = getScDocShell();
     sal_Bool bHasAuto = false;
-    rtl::OUString sAutofiltRangeName;
-    uno::Reference< sheet::XDatabaseRange > xDataBaseRange = excel::GetAutoFiltRange( pShell, nSheet, sAutofiltRangeName );
+    uno::Reference< sheet::XDatabaseRange > xDataBaseRange = excel::GetAutoFiltRange( pShell, nSheet );
     if ( xDataBaseRange.is() )
         bHasAuto = true;
 
@@ -4549,16 +4539,13 @@ ScVbaRange::AutoFilter( const uno::Any& Field, const uno::Any& Criteria1, const
             }
         }
 
-        uno::Reference< sheet::XDatabaseRanges > xDBRanges = excel::GetDataBaseRanges( pShell );
+        uno::Reference< sheet::XUnnamedDatabaseRanges > xDBRanges = excel::GetUnnamedDataBaseRanges( pShell );
         if ( xDBRanges.is() )
         {
-            rtl::OUString sGenName( RTL_CONSTASCII_USTRINGPARAM("VBA_Autofilter_") );
-            sGenName += rtl::OUString::valueOf( static_cast< sal_Int32 >( nSheet ) );
-            OSL_TRACE("Going to add new autofilter range.. name %s",
-                rtl::OUStringToOString( sGenName, RTL_TEXTENCODING_UTF8 ).getStr() , nSheet );
-            if ( !xDBRanges->hasByName( sGenName ) )
-                xDBRanges->addNewByName(  sGenName, autoFiltAddress );
-            xDataBaseRange.set( xDBRanges->getByName(  sGenName ), uno::UNO_QUERY_THROW );
+            OSL_TRACE("Going to add new autofilter range.. sheet %i", nSheet );
+            if ( !xDBRanges->hasByTable( nSheet ) )
+                xDBRanges->setByTable( autoFiltAddress );
+            xDataBaseRange.set( xDBRanges->getByTable(nSheet ), uno::UNO_QUERY_THROW );
         }
         if ( !xDataBaseRange.is() )
             throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Failed to find the autofilter placeholder range" ) ), uno::Reference< uno::XInterface >() );
commit b433b34c2cc5877d658b6970b67702d400f83482
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Thu May 5 14:25:42 2011 +0200

    check for less equal, not greater equal
    
    Signed-off-by: Kohei Yoshida <kyoshida at novell.com>

diff --git a/sc/source/ui/unoobj/datauno.cxx b/sc/source/ui/unoobj/datauno.cxx
index 9a4f5a0..2e021c0 100644
--- a/sc/source/ui/unoobj/datauno.cxx
+++ b/sc/source/ui/unoobj/datauno.cxx
@@ -2406,7 +2406,7 @@ void ScUnnamedDatabaseRangesObj::setByTable( const table::CellRangeAddress& aRan
     bool bDone = false;
     if (pDocShell)
     {
-        if ( pDocShell->GetDocument()->GetTableCount() >= aRange.Sheet )
+        if ( pDocShell->GetDocument()->GetTableCount() <= aRange.Sheet )
             throw lang::IndexOutOfBoundsException();
 
         ScDBDocFunc aFunc(*pDocShell);
@@ -2427,7 +2427,7 @@ uno::Any ScUnnamedDatabaseRangesObj::getByTable( const sal_Int32 nTab )
     SolarMutexGuard aGuard;
     if (pDocShell)
     {
-        if ( pDocShell->GetDocument()->GetTableCount() >= nTab )
+        if ( pDocShell->GetDocument()->GetTableCount() <= nTab )
             throw lang::IndexOutOfBoundsException();
         uno::Reference<sheet::XDatabaseRange> xRange( new ScDatabaseRangeObj(pDocShell, (SCTAB) nTab) );
         if (xRange.is())
@@ -2446,7 +2446,7 @@ sal_Bool ScUnnamedDatabaseRangesObj::hasByTable( sal_Int32 nTab )
     SolarMutexGuard aGuard;
     if (pDocShell)
     {
-         if (pDocShell->GetDocument()->GetTableCount() >= nTab)
+         if (pDocShell->GetDocument()->GetTableCount() <= nTab)
             throw lang::IndexOutOfBoundsException();
         if (pDocShell->GetDocument()->GetAnonymousDBData((SCTAB) nTab))
             return true;
commit 9bb51147c10238a3b618593a48cb795132fd70cf
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Wed May 4 20:12:41 2011 +0200

    add implementation for new uno interface XUnnamedDatabaseRange
    
    Signed-off-by: Kohei Yoshida <kyoshida at novell.com>

diff --git a/sc/inc/datauno.hxx b/sc/inc/datauno.hxx
index 429ca3a..7d43e4f 100644
--- a/sc/inc/datauno.hxx
+++ b/sc/inc/datauno.hxx
@@ -40,6 +40,7 @@
 #include <com/sun/star/sheet/XConsolidationDescriptor.hpp>
 #include <com/sun/star/sheet/XDatabaseRanges.hpp>
 #include <com/sun/star/sheet/XDatabaseRange.hpp>
+#include <com/sun/star/sheet/XUnnamedDatabaseRanges.hpp>
 #include <com/sun/star/sheet/XSubTotalDescriptor.hpp>
 #include <com/sun/star/sheet/XSubTotalField.hpp>
 #include <com/sun/star/lang/XServiceInfo.hpp>
@@ -501,6 +502,8 @@ private:
     String					aName;
     SfxItemPropertySet		aPropSet;
     XDBRefreshListenerArr_Impl aRefreshListeners;
+    bool                    bIsUnnamed;
+    SCTAB                   aTab;
 
 private:
     ScDBData*				GetDBData_Impl() const;
@@ -508,6 +511,7 @@ private:
 
 public:
                             ScDatabaseRangeObj(ScDocShell* pDocSh, const String& rNm);
+                            ScDatabaseRangeObj(ScDocShell* pDocSh, const SCTAB nTab);
     virtual					~ScDatabaseRangeObj();
 
     virtual void			Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
@@ -662,6 +666,32 @@ public:
                                 throw(::com::sun::star::uno::RuntimeException);
 };
 
+class ScUnnamedDatabaseRangesObj : public cppu::WeakImplHelper1<
+                                com::sun::star::sheet::XUnnamedDatabaseRanges>,
+                            public SfxListener
+{
+private:
+    ScDocShell*				pDocShell;
+
+public:
+                            ScUnnamedDatabaseRangesObj(ScDocShell* pDocSh);
+    virtual					~ScUnnamedDatabaseRangesObj();
+
+    virtual void			Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
+
+                            // XUnnamedDatabaseRanges
+    virtual void SAL_CALL setByTable( const ::com::sun::star::table::CellRangeAddress& aRange )
+                                throw(::com::sun::star::uno::RuntimeException,
+                                      ::com::sun::star::lang::IndexOutOfBoundsException );
+    virtual com::sun::star::uno::Any SAL_CALL getByTable( const sal_Int32 nTab )
+                                throw(::com::sun::star::uno::RuntimeException,
+                                ::com::sun::star::lang::IndexOutOfBoundsException,
+                                ::com::sun::star::container::NoSuchElementException );
+    virtual sal_Bool SAL_CALL hasByTable( sal_Int32 nTab )
+                                throw (::com::sun::star::uno::RuntimeException,
+                                ::com::sun::star::lang::IndexOutOfBoundsException);
+};
+
 
 
 #endif
diff --git a/sc/source/ui/unoobj/datauno.cxx b/sc/source/ui/unoobj/datauno.cxx
index edc7fea..9a4f5a0 100644
--- a/sc/source/ui/unoobj/datauno.cxx
+++ b/sc/source/ui/unoobj/datauno.cxx
@@ -57,6 +57,7 @@
 #include "docsh.hxx"
 #include "dbdocfun.hxx"
 #include "unonames.hxx"
+#include "globalnames.hxx"
 #include "globstr.hrc"
 #include "convuno.hxx"
 #include "hints.hxx"
@@ -1607,7 +1608,18 @@ void ScDataPilotFilterDescriptor::PutData( const ScQueryParam& rParam )
 ScDatabaseRangeObj::ScDatabaseRangeObj(ScDocShell* pDocSh, const String& rNm) :
     pDocShell( pDocSh ),
     aName( rNm ),
-    aPropSet( lcl_GetDBRangePropertyMap() )
+    aPropSet( lcl_GetDBRangePropertyMap() ),
+    bIsUnnamed(false)
+{
+    pDocShell->GetDocument()->AddUnoObject(*this);
+}
+
+ScDatabaseRangeObj::ScDatabaseRangeObj(ScDocShell* pDocSh, const SCTAB nTab) :
+    pDocShell( pDocSh ),
+    aName(RTL_CONSTASCII_USTRINGPARAM(STR_DB_LOCAL_NONAME)),
+    aPropSet( lcl_GetDBRangePropertyMap() ),
+    bIsUnnamed(true),
+    aTab( nTab )
 {
     pDocShell->GetDocument()->AddUnoObject(*this);
 }
@@ -1641,12 +1653,19 @@ ScDBData* ScDatabaseRangeObj::GetDBData_Impl() const
     ScDBData* pRet = NULL;
     if (pDocShell)
     {
-        ScDBCollection* pNames = pDocShell->GetDocument()->GetDBCollection();
-        if (pNames)
+        if (bIsUnnamed)
         {
-            sal_uInt16 nPos = 0;
-            if (pNames->SearchName( aName, nPos ))
-                pRet = (*pNames)[nPos];
+            pRet = pDocShell->GetDocument()->GetAnonymousDBData(aTab);
+        }
+        else
+        {
+            ScDBCollection* pNames = pDocShell->GetDocument()->GetDBCollection();
+            if (pNames)
+            {
+                sal_uInt16 nPos = 0;
+                if (pNames->SearchName( aName, nPos ))
+                    pRet = (*pNames)[nPos];
+            }
         }
     }
     return pRet;
@@ -2079,7 +2098,7 @@ uno::Any SAL_CALL ScDatabaseRangeObj::getPropertyValue( const rtl::OUString& aPr
         {
             //	all database ranges except "unnamed" are user defined
             ScUnoHelpFunctions::SetBoolInAny( aRet,
-                        ( pData->GetName() != ScGlobal::GetRscString(STR_DB_NONAME) ) );
+                        ( pData->GetName() != String(RTL_CONSTASCII_USTRINGPARAM(STR_DB_LOCAL_NONAME))  ) );
         }
         else if ( aString.EqualsAscii( SC_UNO_LINKDISPBIT ) )
         {
@@ -2354,8 +2373,90 @@ sal_Bool SAL_CALL ScDatabaseRangesObj::hasByName( const rtl::OUString& aName )
 
 //------------------------------------------------------------------------
 
+ScUnnamedDatabaseRangesObj::ScUnnamedDatabaseRangesObj(ScDocShell* pDocSh) :
+    pDocShell( pDocSh )
+{
+    pDocShell->GetDocument()->AddUnoObject(*this);
+}
+
+ScUnnamedDatabaseRangesObj::~ScUnnamedDatabaseRangesObj()
+{
+    if (pDocShell)
+        pDocShell->GetDocument()->RemoveUnoObject(*this);
+}
+
+void ScUnnamedDatabaseRangesObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
+{
+    //	Referenz-Update interessiert hier nicht
+
+    if ( rHint.ISA( SfxSimpleHint ) &&
+            ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
+    {
+        pDocShell = NULL;		// ungueltig geworden
+    }
+}
+
+// XUnnamedDatabaseRanges
+
+void ScUnnamedDatabaseRangesObj::setByTable( const table::CellRangeAddress& aRange )
+                                throw( uno::RuntimeException,
+                                        lang::IndexOutOfBoundsException )
+{
+    SolarMutexGuard aGuard;
+    bool bDone = false;
+    if (pDocShell)
+    {
+        if ( pDocShell->GetDocument()->GetTableCount() >= aRange.Sheet )
+            throw lang::IndexOutOfBoundsException();
 
+        ScDBDocFunc aFunc(*pDocShell);
+        String aString(RTL_CONSTASCII_USTRINGPARAM(STR_DB_LOCAL_NONAME));
+        ScRange aUnnamedRange( (SCCOL)aRange.StartColumn, (SCROW)aRange.StartRow, aRange.Sheet,
+                            (SCCOL)aRange.EndColumn,   (SCROW)aRange.EndRow,   aRange.Sheet );
+        bDone = aFunc.AddDBRange( aString, aUnnamedRange, sal_True );
+    }
+    if (!bDone)
+        throw uno::RuntimeException();		// no other exceptions specified
+}
 
+uno::Any ScUnnamedDatabaseRangesObj::getByTable( const sal_Int32 nTab )
+                                throw(uno::RuntimeException,
+                                    lang::IndexOutOfBoundsException,
+                                    container::NoSuchElementException)
+{
+    SolarMutexGuard aGuard;
+    if (pDocShell)
+    {
+        if ( pDocShell->GetDocument()->GetTableCount() >= nTab )
+            throw lang::IndexOutOfBoundsException();
+        uno::Reference<sheet::XDatabaseRange> xRange( new ScDatabaseRangeObj(pDocShell, (SCTAB) nTab) );
+        if (xRange.is())
+            return uno::makeAny(xRange);
+        else
+            throw container::NoSuchElementException();
+    }
+    else
+        throw uno::RuntimeException();
+}
+
+sal_Bool ScUnnamedDatabaseRangesObj::hasByTable( sal_Int32 nTab )
+                                    throw (uno::RuntimeException,
+                                        lang::IndexOutOfBoundsException)
+{
+    SolarMutexGuard aGuard;
+    if (pDocShell)
+    {
+         if (pDocShell->GetDocument()->GetTableCount() >= nTab)
+            throw lang::IndexOutOfBoundsException();
+        if (pDocShell->GetDocument()->GetAnonymousDBData((SCTAB) nTab))
+            return true;
+        return false;
+    }
+    else
+        return false;
+}
+
+//------------------------------------------------------------------------
 
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit a5bca90ef7e50f97ffb8610feab9ea00156ce5a5
Author: Thorsten Behrens <tbehrens at novell.com>
Date:   Fri May 6 18:43:35 2011 +0200

    Force calc unit test to use en-US locale and strings

diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index 58cacbc..7a6d46e 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -49,6 +49,8 @@
 #include <cppuhelper/bootstrap.hxx>
 #include <comphelper/processfactory.hxx>
 #include <comphelper/oslfile2streamwrap.hxx>
+#include <i18npool/mslangid.hxx>
+#include <unotools/syslocaleoptions.hxx>
 
 #include <vcl/svapp.hxx>
 #include "scdll.hxx"
@@ -304,28 +306,6 @@ Test::Test()
     //of retaining references to the root ServiceFactory as its passed around
     comphelper::setProcessServiceFactory(xSM);
 
-#if 0
-    // TODO: attempt to explicitly set UI locale to en-US, to get the unit
-    // test to work under non-English build environment.  But this causes
-    // runtime exception....
-    uno::Reference<lang::XMultiServiceFactory> theConfigProvider =
-        uno::Reference<lang::XMultiServiceFactory> (
-            xSM->createInstance(
-                OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationProvider"))), uno::UNO_QUERY_THROW);
-
-    uno::Sequence<uno::Any> theArgs(1);
-    OUString aLocalePath(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.Linguistic/General"));
-    theArgs[0] <<= aLocalePath;
-    uno::Reference<beans::XPropertySet> xProp(
-        theConfigProvider->createInstanceWithArguments(
-            OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationUpdateAccess")), theArgs), uno::UNO_QUERY_THROW);
-
-    OUString aLang(RTL_CONSTASCII_USTRINGPARAM("en-US"));
-    uno::Any aAny;
-    aAny <<= aLang;
-    xProp->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("UILocale")), aAny);
-#endif
-
     // initialise UCB-Broker
     uno::Sequence<uno::Any> aUcbInitSequence(2);
     aUcbInitSequence[0] <<= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Local"));
@@ -339,8 +319,19 @@ Test::Test()
         rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ucb.FileContentProvider"))), uno::UNO_QUERY);
     xUcb->registerContentProvider(xFileProvider, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("file")), sal_True);
 
-    InitVCL(xSM);
+    // force locale (and resource files loaded) to en-US
+    const LanguageType eLang=LANGUAGE_ENGLISH_US;
 
+    rtl::OUString aLang, aCountry;
+    MsLangId::convertLanguageToIsoNames(eLang, aLang, aCountry);
+    lang::Locale aLocale(aLang, aCountry, rtl::OUString());
+    ResMgr::SetDefaultLocale( aLocale );
+
+    SvtSysLocaleOptions aLocalOptions;
+    aLocalOptions.SetUILocaleConfigString(
+        MsLangId::convertLanguageToIsoString( eLang ) );
+
+    InitVCL(xSM);
     ScDLL::Init();
 
     oslProcessError err = osl_getProcessWorkingDir(&m_aPWDURL.pData);
commit 3f39523ac9284c55c0e9c380750bd5dce213ed19
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Fri May 6 22:34:11 2011 -0400

    fdo#36789: Set all dynamic controls invisible upon instantiation.
    
    Some of the dialog code depends on the controls being hidden unless
    explicitly set visible.  Unfortunately that's not really guaranteed
    so we need to make that logic explicit.

diff --git a/chart2/source/controller/dialogs/tp_Scale.cxx b/chart2/source/controller/dialogs/tp_Scale.cxx
index 6e020c6..93ab4a1 100644
--- a/chart2/source/controller/dialogs/tp_Scale.cxx
+++ b/chart2/source/controller/dialogs/tp_Scale.cxx
@@ -183,6 +183,8 @@ ScaleTabPage::ScaleTabPage(Window* pWindow,const SfxItemSet& rInAttrs) :
     aFmtFldMax.SetModifyHdl(LINK(this, ScaleTabPage, FmtFieldModifiedHdl));
     aFmtFldStepMain.SetModifyHdl(LINK(this, ScaleTabPage, FmtFieldModifiedHdl));
     aFmtFldOrigin.SetModifyHdl(LINK(this, ScaleTabPage, FmtFieldModifiedHdl));
+
+    HideAllControls();
 }
 
 IMPL_LINK( ScaleTabPage, FmtFieldModifiedHdl, FormattedField*, pFmtFied )
@@ -784,6 +786,49 @@ bool ScaleTabPage::ShowWarning( sal_uInt16 nResIdMessage, Control* pControl /* =
     return true;
 }
 
+void ScaleTabPage::HideAllControls()
+{
+    // We need to set these controls invisible when the class is instantiated
+    // since some code in EnableControls() depends on that logic. The real
+    // visibility of these controls depend on axis data type, and are
+    // set in EnableControls().
+
+    m_aTxt_AxisType.Hide();
+    m_aLB_AxisType.Hide();
+
+    aCbxLogarithm.Hide();
+    aTxtMin.Hide();
+    aFmtFldMin.Hide();
+    aCbxAutoMin.Hide();
+    aTxtMax.Hide();
+    aFmtFldMax.Hide();
+    aCbxAutoMax.Hide();
+    aTxtMain.Hide();
+    aFmtFldStepMain.Hide();
+    aCbxAutoStepMain.Hide();
+    aTxtHelp.Hide();
+    aTxtHelpCount.Hide();
+    aMtStepHelp.Hide();
+    aCbxAutoStepHelp.Hide();
+
+    aTxtOrigin.Hide();
+    aFmtFldOrigin.Hide();
+    aCbxAutoOrigin.Hide();
+
+    aTxtHelpCount.Hide();
+    aTxtHelp.Hide();
+
+    m_aTxt_TimeResolution.Hide();
+    m_aLB_TimeResolution.Hide();
+    m_aCbx_AutoTimeResolution.Hide();
+
+    aFmtFldStepMain.Hide();
+    m_aMt_MainDateStep.Hide();
+
+    m_aLB_MainTimeUnit.Hide();
+    m_aLB_HelpTimeUnit.Hide();
+}
+
 //.............................................................................
 } //namespace chart
 //.............................................................................
diff --git a/chart2/source/controller/dialogs/tp_Scale.hxx b/chart2/source/controller/dialogs/tp_Scale.hxx
index f99377b..a6a5ab8 100644
--- a/chart2/source/controller/dialogs/tp_Scale.hxx
+++ b/chart2/source/controller/dialogs/tp_Scale.hxx
@@ -138,6 +138,8 @@ private:
         @return false, if nResIdMessage was 0, true otherwise
      */
     bool ShowWarning( sal_uInt16 nResIdMessage, Control* pControl = NULL );
+
+    void HideAllControls();
 };
 
 //.............................................................................
commit 09ad3b0ffd21936f4eb8bf380ff0f55512c47480
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Fri May 6 15:35:19 2011 -0400

    Explicitly specify less function object for map, to get it to build with MSVC.

diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx
index 5769303..510f308 100644
--- a/sc/inc/dpobject.hxx
+++ b/sc/inc/dpobject.hxx
@@ -297,6 +297,11 @@ public:
         ::rtl::OUString maDBName;
         ::rtl::OUString maCommand;
         DBType(sal_Int32 nSdbType, const ::rtl::OUString& rDBName, const ::rtl::OUString& rCommand);
+
+        struct less : public ::std::binary_function<DBType, DBType, bool>
+        {
+            bool operator() (const DBType& left, const DBType& right) const;
+        };
     };
 
     /**
@@ -304,7 +309,7 @@ public:
      */
     class DBCaches
     {
-        typedef ::boost::ptr_map<DBType, ScDPCache> CachesType;
+        typedef ::boost::ptr_map<DBType, ScDPCache, DBType::less> CachesType;
         CachesType maCaches;
         ScDocument* mpDoc;
     public:
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index 0ab6d32..58cacbc 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -798,7 +798,7 @@ ScDPObject* createDPFromRange(
     {
         OUString aDimName(aFields[i].pName, strlen(aFields[i].pName), RTL_TEXTENCODING_UTF8);
         ScDPSaveDimension* pDim = aSaveData.GetDimensionByName(aDimName);
-        pDim->SetOrientation(aFields[i].eOrient);
+        pDim->SetOrientation(static_cast<sal_uInt16>(aFields[i].eOrient));
         pDim->SetUsedHierarchy(0);
         pDim->SetShowEmpty(true);
 
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
index 401ef3b..85f02e2 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -2445,6 +2445,11 @@ void ScDPCollection::NameCaches::removeCache(const OUString& rName)
 ScDPCollection::DBType::DBType(sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand) :
     mnSdbType(nSdbType), maDBName(rDBName), maCommand(rCommand) {}
 
+bool ScDPCollection::DBType::less::operator() (const DBType& left, const DBType& right) const
+{
+    return left < right;
+}
+
 ScDPCollection::DBCaches::DBCaches(ScDocument* pDoc) : mpDoc(pDoc) {}
 
 const ScDPCache* ScDPCollection::DBCaches::getCache(sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand)
commit 67d7f2e028566c39cf296fae5ef91d4fe0d3c26d
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Fri May 6 01:50:02 2011 -0400

    Remove range names with external references regardless of cells.
    
    Sometimes range names may contain external references but no sheet
    cells reference that range names.  Even then, breaking the link
    should remove those range names.

diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx
index d1cc636..1bfdc8b 100644
--- a/sc/source/ui/docshell/externalrefmgr.cxx
+++ b/sc/source/ui/docshell/externalrefmgr.cxx
@@ -2442,23 +2442,22 @@ void ScExternalRefManager::breakLink(sal_uInt16 nFileId)
         // the original container.
         RefCellSet aSet = itrRefs->second;
         for_each(aSet.begin(), aSet.end(), ConvertFormulaToStatic(mpDoc));
+        maRefCells.erase(nFileId);
+    }
+
+    // Remove all named ranges that reference this document.
 
-        // Remove all named ranges that reference this document.
+    // Global named ranges.
+    ScRangeName* pRanges = mpDoc->GetRangeName();
+    if (pRanges)
+        removeRangeNamesBySrcDoc(*pRanges, nFileId);
 
-        // Global named ranges.
-        ScRangeName* pRanges = mpDoc->GetRangeName();
+    // Sheet-local named ranges.
+    for (SCTAB i = 0, n = mpDoc->GetTableCount(); i < n; ++i)
+    {
+        pRanges = mpDoc->GetRangeName(i);
         if (pRanges)
             removeRangeNamesBySrcDoc(*pRanges, nFileId);
-
-        // Sheet-local named ranges.
-        for (SCTAB i = 0, n = mpDoc->GetTableCount(); i < n; ++i)
-        {
-            pRanges = mpDoc->GetRangeName(i);
-            if (pRanges)
-                removeRangeNamesBySrcDoc(*pRanges, nFileId);
-        }
-
-        maRefCells.erase(nFileId);
     }
 
     lcl_removeByFileId(nFileId, maDocShells);
commit 3d28f8b19427588df949d613791350f5e17baab0
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Fri May 6 01:12:37 2011 -0400

    Wrong approach. You can't use remove_if with set.
    
    std::remove_if is only for sequence containers, not for associative
    containers.  Sure enough, using that caused crash on closing the
    document.  This fixes it.

diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx
index 59365c1..d1cc636 100644
--- a/sc/source/ui/docshell/externalrefmgr.cxx
+++ b/sc/source/ui/docshell/externalrefmgr.cxx
@@ -203,34 +203,55 @@ private:
 };
 
 /**
- * Predicate used to determine whether a named range contains an external
- * reference to a particular document.
+ * Check whether a named range contains an external reference to a
+ * particular document.
  */
-class RangeNameWithExtRef : unary_function<ScRangeData, bool>
+bool hasRefsToSrcDoc(ScRangeData& rData, sal_uInt16 nFileId)
 {
-    sal_uInt16 mnFileId;
-public:
-    RangeNameWithExtRef(sal_uInt16 nFileId) : mnFileId(nFileId) {}
-    bool operator() (ScRangeData& rData) const
+    ScTokenArray* pArray = rData.GetCode();
+    if (!pArray)
+        return false;
+
+    pArray->Reset();
+    ScToken* p = static_cast<ScToken*>(pArray->GetNextReference());
+    for (; p; p = static_cast<ScToken*>(pArray->GetNextReference()))
     {
-        ScTokenArray* pArray = rData.GetCode();
-        if (!pArray)
-            return false;
+        if (!p->IsExternalRef())
+            continue;
 
-        pArray->Reset();
-        ScToken* p = static_cast<ScToken*>(pArray->GetNextReference());
-        for (; p; p = static_cast<ScToken*>(pArray->GetNextReference()))
-        {
-            if (!p->IsExternalRef())
-                continue;
+        if (p->GetIndex() == nFileId)
+            return true;
+    }
+    return false;
+}
 
-            if (p->GetIndex() == mnFileId)
-                return true;
-        }
-        return false;
+class EraseRangeByIterator : unary_function<ScRangeName::iterator, void>
+{
+    ScRangeName& mrRanges;
+public:
+    EraseRangeByIterator(ScRangeName& rRanges) : mrRanges(rRanges) {}
+    void operator() (const ScRangeName::iterator& itr)
+    {
+        mrRanges.erase(itr);
     }
 };
 
+/**
+ * Remove all named ranges that contain references to specified source
+ * document.
+ */
+void removeRangeNamesBySrcDoc(ScRangeName& rRanges, sal_uInt16 nFileId)
+{
+    ScRangeName::iterator itr = rRanges.begin(), itrEnd = rRanges.end();
+    vector<ScRangeName::iterator> v;
+    for (; itr != itrEnd; ++itr)
+    {
+        if (hasRefsToSrcDoc(*itr, nFileId))
+            v.push_back(itr);
+    }
+    for_each(v.begin(), v.end(), EraseRangeByIterator(rRanges));
+}
+
 }
 
 // ============================================================================
@@ -2427,14 +2448,14 @@ void ScExternalRefManager::breakLink(sal_uInt16 nFileId)
         // Global named ranges.
         ScRangeName* pRanges = mpDoc->GetRangeName();
         if (pRanges)
-            remove_if(pRanges->begin(), pRanges->end(), RangeNameWithExtRef(nFileId));
+            removeRangeNamesBySrcDoc(*pRanges, nFileId);
 
         // Sheet-local named ranges.
         for (SCTAB i = 0, n = mpDoc->GetTableCount(); i < n; ++i)
         {
             pRanges = mpDoc->GetRangeName(i);
             if (pRanges)
-                remove_if(pRanges->begin(), pRanges->end(), RangeNameWithExtRef(nFileId));
+                removeRangeNamesBySrcDoc(*pRanges, nFileId);
         }
 
         maRefCells.erase(nFileId);
commit c719ed67aa45701c771134cabf51c37dc7d0ec9d
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Fri May 6 00:07:35 2011 -0400

    fdo#34930: Remove range names with external references when breaking link.
    
    When breaking a link in Edit -> Links, cells containing references to
    that link get staticized i.e. their formulas replaced with static
    values.  This also applies to cells containing range names that point
    to external document.  We should remove such range names when the link
    gets broken, or else reloading the document would re-introduce the link
    on file load again, and the link would never go away (without manually
    removing those range names).

diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx
index fc12cf1..59365c1 100644
--- a/sc/source/ui/docshell/externalrefmgr.cxx
+++ b/sc/source/ui/docshell/externalrefmgr.cxx
@@ -74,6 +74,7 @@ using ::rtl::OUString;
 using ::std::vector;
 using ::std::find;
 using ::std::find_if;
+using ::std::remove_if;
 using ::std::distance;
 using ::std::pair;
 using ::std::list;
@@ -85,7 +86,7 @@ using namespace formula;
 
 namespace {
 
-class TabNameSearchPredicate : public unary_function<bool, ScExternalRefCache::TableName>
+class TabNameSearchPredicate : public unary_function<ScExternalRefCache::TableName, bool>
 {
 public:
     explicit TabNameSearchPredicate(const String& rSearchName) :
@@ -201,6 +202,35 @@ private:
     ScDocument* mpDoc;
 };
 
+/**
+ * Predicate used to determine whether a named range contains an external
+ * reference to a particular document.
+ */
+class RangeNameWithExtRef : unary_function<ScRangeData, bool>
+{
+    sal_uInt16 mnFileId;
+public:
+    RangeNameWithExtRef(sal_uInt16 nFileId) : mnFileId(nFileId) {}
+    bool operator() (ScRangeData& rData) const
+    {
+        ScTokenArray* pArray = rData.GetCode();
+        if (!pArray)
+            return false;
+
+        pArray->Reset();
+        ScToken* p = static_cast<ScToken*>(pArray->GetNextReference());
+        for (; p; p = static_cast<ScToken*>(pArray->GetNextReference()))
+        {
+            if (!p->IsExternalRef())
+                continue;
+
+            if (p->GetIndex() == mnFileId)
+                return true;
+        }
+        return false;
+    }
+};
+
 }
 
 // ============================================================================
@@ -2391,6 +2421,22 @@ void ScExternalRefManager::breakLink(sal_uInt16 nFileId)
         // the original container.
         RefCellSet aSet = itrRefs->second;
         for_each(aSet.begin(), aSet.end(), ConvertFormulaToStatic(mpDoc));
+
+        // Remove all named ranges that reference this document.
+
+        // Global named ranges.
+        ScRangeName* pRanges = mpDoc->GetRangeName();
+        if (pRanges)
+            remove_if(pRanges->begin(), pRanges->end(), RangeNameWithExtRef(nFileId));
+
+        // Sheet-local named ranges.
+        for (SCTAB i = 0, n = mpDoc->GetTableCount(); i < n; ++i)
+        {
+            pRanges = mpDoc->GetRangeName(i);
+            if (pRanges)
+                remove_if(pRanges->begin(), pRanges->end(), RangeNameWithExtRef(nFileId));
+        }
+
         maRefCells.erase(nFileId);
     }
 
commit e892251cac6d6b8830dcf61361348561b99c67f3
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Thu May 5 22:46:39 2011 -0400

    Properly cache external reference values in named ranges.
    
    Values of the external references used only in named ranges were
    not cached properly.  This commit fixes it.

diff --git a/sc/source/core/data/documen4.cxx b/sc/source/core/data/documen4.cxx
index a5ecb95..85dc636 100644
--- a/sc/source/core/data/documen4.cxx
+++ b/sc/source/core/data/documen4.cxx
@@ -296,42 +296,71 @@ void ScDocument::InsertTableOp(const ScTabOpParam& rParam,      // Mehrfachopera
                     pTab[i]->PutCell( j, k, aRefCell.CloneWithoutNote( *this, ScAddress( j, k, i ), SC_CLONECELL_STARTLISTENING ) );
 }
 
+namespace {
+
+bool setCacheTableReferenced(ScToken& rToken, ScExternalRefManager& rRefMgr)
+{
+    switch (rToken.GetType())
+    {
+        case svExternalSingleRef:
+            return rRefMgr.setCacheTableReferenced(
+                rToken.GetIndex(), rToken.GetString(), 1);
+        case svExternalDoubleRef:
+        {
+            const ScComplexRefData& rRef = rToken.GetDoubleRef();
+            size_t nSheets = rRef.Ref2.nTab - rRef.Ref1.nTab + 1;
+            return rRefMgr.setCacheTableReferenced(
+                    rToken.GetIndex(), rToken.GetString(), nSheets);
+        }
+        case svExternalName:
+            /* TODO: external names aren't supported yet, but would
+             * have to be marked as well, if so. Mechanism would be
+             * different. */
+            DBG_ERRORFILE("ScDocument::MarkUsedExternalReferences: implement the svExternalName case!");
+        default:
+            ;
+    }
+    return false;
+}
+
+}
+
 bool ScDocument::MarkUsedExternalReferences( ScTokenArray & rArr )
 {
+    if (!rArr.GetLen())
+        return false;
+
+    ScExternalRefManager* pRefMgr = NULL;
+    rArr.Reset();
+    ScToken* t = NULL;
     bool bAllMarked = false;
-    if (rArr.GetLen())
+    while (!bAllMarked && (t = static_cast<ScToken*>(rArr.GetNextReferenceOrName())) != NULL)
     {
-        ScExternalRefManager* pRefMgr = NULL;
-        rArr.Reset();
-        ScToken* t;
-        while (!bAllMarked && (t = static_cast<ScToken*>(rArr.GetNextReferenceOrName())) != NULL)
+        if (t->IsExternalRef())
+        {
+            if (!pRefMgr)
+                pRefMgr = GetExternalRefManager();
+
+            bAllMarked = setCacheTableReferenced(*t, *pRefMgr);
+        }
+        else if (t->GetType() == svIndex)
         {
-            if (t->IsExternalRef())
+            // this is a named range.  Check if the range contains an external
+            // reference.
+            ScRangeData* pRangeData = GetRangeName()->findByIndex(t->GetIndex());
+            if (!pRangeData)
+                continue;
+
+            ScTokenArray* pArray = pRangeData->GetCode();
+            for (t = static_cast<ScToken*>(pArray->First()); t; t = static_cast<ScToken*>(pArray->Next()))
             {
+                if (!t->IsExternalRef())
+                    continue;
+
                 if (!pRefMgr)
                     pRefMgr = GetExternalRefManager();
-                switch (t->GetType())
-                {
-                    case svExternalSingleRef:
-                        bAllMarked = pRefMgr->setCacheTableReferenced( 
-                                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 
-                         * have to be marked as well, if so. Mechanism would be 
-                         * different. */
-                        DBG_ERRORFILE("ScDocument::MarkUsedExternalReferences: implement the svExternalName case!");
-                        break;
-                    default: break;
-                }
+
+                bAllMarked = setCacheTableReferenced(*t, *pRefMgr);
             }
         }
     }
commit 12400a5fe4204f9aed4ac7e3525a64ff357c862f
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Thu May 5 17:24:31 2011 -0400

    Get external references to work with MAX and MIN.

diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 3a7ad46..8beb6f1 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -2908,8 +2908,10 @@ void ScInterpreter::ScMin( sal_Bool bTextAsZero )
             }
             break;
             case svMatrix :
+            case svExternalSingleRef:
+            case svExternalDoubleRef:
             {
-                ScMatrixRef pMat = PopMatrix();
+                ScMatrixRef pMat = GetMatrix();
                 if (pMat)
                 {
                     SCSIZE nC, nR;
@@ -3029,8 +3031,10 @@ void ScInterpreter::ScMax( sal_Bool bTextAsZero )
             }
             break;
             case svMatrix :
+            case svExternalSingleRef:
+            case svExternalDoubleRef:
             {
-                ScMatrixRef pMat = PopMatrix();
+                ScMatrixRef pMat = GetMatrix();
                 if (pMat)
                 {
                     nFuncFmtType = NUMBERFORMAT_NUMBER;
commit e22027a42f3f7cb3ad33e407c4c1230038d73a03
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Thu May 5 10:58:02 2011 -0400

    Let's not use const_iterator here, as MSVC complains about it.

diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 0760e54..67d94bc 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -158,12 +158,12 @@ void ScTable::InsertRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE
         if (!maRowManualBreaks.empty())
         {
             // Copy all breaks up to nStartRow (non-inclusive).
-            ::std::set<SCROW>::const_iterator itr1 = maRowManualBreaks.lower_bound(nStartRow);
+            ::std::set<SCROW>::iterator itr1 = maRowManualBreaks.lower_bound(nStartRow);
             ::std::set<SCROW> aNewBreaks(maRowManualBreaks.begin(), itr1);
 
             // Copy all breaks from nStartRow (inclusive) to the last element,
             // but add nSize to each value.
-            ::std::set<SCROW>::const_iterator itr2 = maRowManualBreaks.end();
+            ::std::set<SCROW>::iterator itr2 = maRowManualBreaks.end();
             for (; itr1 != itr2; ++itr1)
                 aNewBreaks.insert(static_cast<SCROW>(*itr1 + nSize));
 
commit c66d1b9fcc2244b4fd8940f17ebf4e772f09c84e
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Thu May 5 00:23:25 2011 -0400

    fdo#36406: Let's not use invalidated iterators.
    
    std::set::erase(iterator) call invalidates the iterator of the erased
    element.  We better not use it after the erase() call.  Since the number
    of manual breaks should not be high enough to cause a performance
    bottleneck under normal usage, a safer linear copy should just be fine.
    
    Now, I'm not sure if this indeed is the cause of the erroneous amount
    of manual breaks in the test document, but I didn't see any other likely
    spot.

diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index ce5c7e6..0760e54 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -157,18 +157,17 @@ void ScTable::InsertRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE
 
         if (!maRowManualBreaks.empty())
         {
-            std::set<SCROW>::reverse_iterator rit = maRowManualBreaks.rbegin();
-            while (rit != maRowManualBreaks.rend())
-            {
-                SCROW nRow = *rit;
-                if (nRow < nStartRow)
-                    break;  // while
-                else
-                {
-                    maRowManualBreaks.erase( (++rit).base());
-                    maRowManualBreaks.insert( static_cast<SCROW>( nRow + nSize));
-                }
-            }
+            // Copy all breaks up to nStartRow (non-inclusive).
+            ::std::set<SCROW>::const_iterator itr1 = maRowManualBreaks.lower_bound(nStartRow);
+            ::std::set<SCROW> aNewBreaks(maRowManualBreaks.begin(), itr1);
+
+            // Copy all breaks from nStartRow (inclusive) to the last element,
+            // but add nSize to each value.
+            ::std::set<SCROW>::const_iterator itr2 = maRowManualBreaks.end();
+            for (; itr1 != itr2; ++itr1)
+                aNewBreaks.insert(static_cast<SCROW>(*itr1 + nSize));
+
+            maRowManualBreaks.swap(aNewBreaks);
         }
     }
 
@@ -208,14 +207,21 @@ void ScTable::DeleteRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE
 
         if (!maRowManualBreaks.empty())
         {
-            std::set<SCROW>::iterator it = maRowManualBreaks.upper_bound( static_cast<SCROW>( nStartRow + nSize - 1));
-            maRowManualBreaks.erase( maRowManualBreaks.lower_bound( nStartRow), it);
-            while (it != maRowManualBreaks.end())
-            {
-                SCROW nRow = *it;
-                maRowManualBreaks.erase( it++);
-                maRowManualBreaks.insert( static_cast<SCROW>( nRow - nSize));
-            }
+            // Erase all manual breaks between nStartRow and nStartRow + nSize - 1 (inclusive).
+            std::set<SCROW>::iterator itr1 = maRowManualBreaks.lower_bound(nStartRow);
+            std::set<SCROW>::iterator itr2 = maRowManualBreaks.upper_bound(static_cast<SCROW>(nStartRow + nSize - 1));
+            maRowManualBreaks.erase(itr1, itr2);
+
+            // Copy all breaks from the 1st element up to nStartRow to the new container.
+            itr1 = maRowManualBreaks.lower_bound(nStartRow);
+            ::std::set<SCROW> aNewBreaks(maRowManualBreaks.begin(), itr1);
+
+            // Copy all breaks from nStartRow to the last element, but subtract each value by nSize.
+            itr2 = maRowManualBreaks.end();
+            for (; itr1 != itr2; ++itr1)
+                aNewBreaks.insert(static_cast<SCROW>(*itr1 - nSize));
+
+            maRowManualBreaks.swap(aNewBreaks);
         }
     }
 
commit 1100b09b45af0d9a4d8afd76791326232d35b3f2
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Wed May 4 22:05:51 2011 -0400

    Added unit test for PRODUCT cell function with inline array.
    
    3.3.2 didn't calculate this correctly.

diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index dd86f8b..0ab6d32 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -224,7 +224,7 @@ public:
 
     void testCollator();
     void testInput();
-    void testSUM();
+    void testCellFunctions();
     void testVolatileFunc();
     void testFuncParam();
     void testNamedRange();
@@ -264,7 +264,7 @@ public:
     CPPUNIT_TEST_SUITE(Test);
     CPPUNIT_TEST(testCollator);
     CPPUNIT_TEST(testInput);
-    CPPUNIT_TEST(testSUM);
+    CPPUNIT_TEST(testCellFunctions);
     CPPUNIT_TEST(testVolatileFunc);
     CPPUNIT_TEST(testFuncParam);
     CPPUNIT_TEST(testNamedRange);
@@ -398,11 +398,13 @@ void Test::testInput()
     m_pDoc->DeleteTab(0);
 }
 
-void Test::testSUM()
+void Test::testCellFunctions()
 {
     rtl::OUString aTabName(RTL_CONSTASCII_USTRINGPARAM("foo"));
     CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
                             m_pDoc->InsertTab (0, aTabName));
+
+    // SUM
     double val = 1;
     m_pDoc->SetValue (0, 0, 0, val);
     m_pDoc->SetValue (0, 1, 0, val);
@@ -412,6 +414,23 @@ void Test::testSUM()
     m_pDoc->GetValue (0, 2, 0, result);
     CPPUNIT_ASSERT_MESSAGE ("calculation failed", result == 2.0);
 
+    // PRODUCT
+    val = 1;
+    m_pDoc->SetValue(0, 0, 0, val);
+    val = 2;
+    m_pDoc->SetValue(0, 1, 0, val);
+    val = 3;
+    m_pDoc->SetValue(0, 2, 0, val);
+    m_pDoc->SetString(0, 3, 0, OUString(RTL_CONSTASCII_USTRINGPARAM("=PRODUCT(A1:A3)")));
+    m_pDoc->CalcAll();
+    m_pDoc->GetValue(0, 3, 0, result);
+    CPPUNIT_ASSERT_MESSAGE("Calculation of PRODUCT failed", result == 6.0);
+
+    m_pDoc->SetString(0, 4, 0, OUString(RTL_CONSTASCII_USTRINGPARAM("=PRODUCT({1;2;3})")));
+    m_pDoc->CalcAll();
+    m_pDoc->GetValue(0, 4, 0, result);
+    CPPUNIT_ASSERT_MESSAGE("Calculation of PRODUCT with inline array failed", result == 6.0);
+
     m_pDoc->DeleteTab(0);
 }
 
commit e43736eda4df49bd1c592ba1c7a7c26bcc6a2083
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Wed May 4 19:37:28 2011 -0400

    fdo#36848: Typing a named range in the position window should jump.

diff --git a/sc/source/ui/app/inputwin.cxx b/sc/source/ui/app/inputwin.cxx
index 4e88c19..3907c6d 100644
--- a/sc/source/ui/app/inputwin.cxx
+++ b/sc/source/ui/app/inputwin.cxx
@@ -1533,7 +1533,7 @@ ScNameInputType lcl_GetInputType( const String& rText )
         sal_Int32 nNumeric;
 
         if ( aRange.Parse( rText, pDoc, eConv ) & SCA_VALID )
-            eRet = SC_NAME_INPUT_NAMEDRANGE;
+            eRet = SC_NAME_INPUT_RANGE;
         else if ( aAddress.Parse( rText, pDoc, eConv ) & SCA_VALID )
             eRet = SC_NAME_INPUT_CELL;
         else if ( aRangeUtil.MakeRangeFromName( rText, pDoc, nTab, aRange, RUTL_NAMES, eConv ) )
@@ -1697,11 +1697,14 @@ void ScPosWnd::DoEnter()
                 else
                 {
                     // for all selection types, excecute the SID_CURRENTCELL slot.
-                    // Note that SID_CURRENTCELL always expects address to be
-                    // in Calc A1 format.  Convert the text.
-                    ScRange aRange;
-                    aRange.ParseAny(aText, pDoc, pDoc->GetAddressConvention());
-                    aRange.Format(aText, SCR_ABS_3D, pDoc, ::formula::FormulaGrammar::CONV_OOO);
+                    if (eType == SC_NAME_INPUT_CELL || eType == SC_NAME_INPUT_RANGE)
+                    {
+                        // Note that SID_CURRENTCELL always expects address to
+                        // be in Calc A1 format.  Convert the text.
+                        ScRange aRange;
+                        aRange.ParseAny(aText, pDoc, pDoc->GetAddressConvention());
+                        aRange.Format(aText, SCR_ABS_3D, pDoc, ::formula::FormulaGrammar::CONV_OOO);
+                    }
 
                     SfxStringItem aPosItem( SID_CURRENTCELL, aText );
                     SfxBoolItem aUnmarkItem( FN_PARAM_1, sal_True );        // remove existing selection
commit 8fdf19844c061923424835054b66c2d3380662a9
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Wed May 4 18:47:36 2011 -0400

    Properly close the document shell when erased from the manager.
    
    Because the document shell object was erased without properly having
    its shell closed, it failed to update the values when the link was
    updated, especially when the source document was open.  Closing it
    properly when its object is erased should fix it.

diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx
index f9de3e8..fc12cf1 100644
--- a/sc/source/ui/docshell/externalrefmgr.cxx
+++ b/sc/source/ui/docshell/externalrefmgr.cxx
@@ -2358,9 +2358,14 @@ void lcl_removeByFileId(sal_uInt16 nFileId, MapContainer& rMap)
 {
     typename MapContainer::iterator itr = rMap.find(nFileId);
     if (itr != rMap.end())
+    {
+        // Close this document shell.
+        itr->second.maShell->DoClose();
         rMap.erase(itr);
+    }
 }
 
+
 void ScExternalRefManager::refreshNames(sal_uInt16 nFileId)
 {
     maRefCache.clearCache(nFileId);
@@ -2528,6 +2533,9 @@ void ScExternalRefManager::purgeStaleSrcDocument(sal_Int32 nTimeOut)
         sal_Int32 nSinceLastAccess = (Time() - itr->second.maLastAccess).GetTime();
         if (nSinceLastAccess < nTimeOut)
             aNewDocShells.insert(*itr);
+        else
+            // Timed out.  Let's close this.
+            itr->second.maShell->DoClose();
     }
     maDocShells.swap(aNewDocShells);
 
commit 71a67be19f95758035a8214126f5f008f1647c05
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Wed May 4 16:27:16 2011 -0400

    fdo#33137: Fixed external references with COUNTIF.

diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index a3a7850..3a7ad46 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -4603,7 +4603,9 @@ void ScInterpreter::ScCountIf()
                 }
             }
             break;
-            case svMatrix :
+            case svMatrix:
+            case svExternalSingleRef:
+            case svExternalDoubleRef:
             {
                 ScMatValType nType = GetDoubleOrStringFromMatrix( fVal,
                         rString);
@@ -4648,23 +4650,25 @@ void ScInterpreter::ScCountIf()
                     nTab2 = nTab1;
                     break;
                 case svMatrix:
+                case svExternalSingleRef:
+                case svExternalDoubleRef:
+                {
+                    pQueryMatrix = GetMatrix();
+                    if (!pQueryMatrix)
                     {
-                        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;
+                        PushIllegalParameter();
+                        return;
                     }
-                    break;
+                    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 ;
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 1c7ecdd..551a1c2 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -2350,13 +2350,9 @@ ScMatValType ScInterpreter::GetDoubleOrStringFromMatrix( double& rDouble,
 
     ScMatrixRef pMat;
     StackVar eType = GetStackType();
-    if (eType == svExternalDoubleRef)
+    if (eType == svExternalDoubleRef || eType == svExternalSingleRef || eType == svMatrix)
     {
-        PopExternalDoubleRef(pMat);
-    }
-    else if (eType == svMatrix)
-    {
-        pMat = PopMatrix();
+        pMat = GetMatrix();
     }
     else
     {
commit 6cae0836410f5e72ecfeb934aa886353417e6d38
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Wed May 4 15:29:53 2011 -0400

    fdo#36849: Assume that the range list member may be NULL.

diff --git a/sc/source/core/data/conditio.cxx b/sc/source/core/data/conditio.cxx
index 6f9fda7..642c39b 100644
--- a/sc/source/core/data/conditio.cxx
+++ b/sc/source/core/data/conditio.cxx
@@ -1270,7 +1270,8 @@ ScConditionalFormat::ScConditionalFormat(const ScConditionalFormat& r) :
     pAreas( NULL ),
     nKey( r.nKey ),
     ppEntries( NULL ),
-    nEntryCount( r.nEntryCount )
+    nEntryCount( r.nEntryCount ),
+    pRanges( NULL )
 {
     if (nEntryCount)
     {
@@ -1281,7 +1282,8 @@ ScConditionalFormat::ScConditionalFormat(const ScConditionalFormat& r) :
             ppEntries[i]->SetParent(this);
         }
     }
-    pRanges = new ScRangeList( *r.pRanges );
+    if (r.pRanges)
+        pRanges = new ScRangeList( *r.pRanges );
 }
 
 ScConditionalFormat* ScConditionalFormat::Clone(ScDocument* pNewDoc) const
@@ -1320,10 +1322,16 @@ sal_Bool ScConditionalFormat::EqualEntries( const ScConditionalFormat& r ) const
         if ( ! (*ppEntries[i] == *r.ppEntries[i]) )
             return false;
 
-    if( *pRanges != *r.pRanges )
-        return false;
+    if (pRanges)
+    {
+        if (r.pRanges)
+            return *pRanges == *r.pRanges;
+        else
+            return false;
+    }
 
-    return true;
+    // pRanges is NULL, which means r.pRanges must be NULL.
+    return r.pRanges.Is() == false;
 }
 
 void ScConditionalFormat::AddRangeInfo( const ScRangeListRef& rRanges )
diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
index e575ef3..85f7b06 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -97,10 +97,13 @@ static void lcl_PostRepaintCondFormat( const ScConditionalFormat *pCondFmt, ScDo
 {
     if( pCondFmt )
     {
-        const ScRangeListRef& aRanges = pCondFmt->GetRangeInfo();
-        size_t nCount = aRanges->size();
+        const ScRangeListRef& xRanges = pCondFmt->GetRangeInfo();
+        if (!xRanges)
+            return;
+
+        size_t nCount = xRanges->size();
         for( size_t n = 0 ; n < nCount; n++ )
-            pDocSh->PostPaint( *((*aRanges)[n]), PAINT_ALL );
+            pDocSh->PostPaint( *((*xRanges)[n]), PAINT_ALL );
     }
 }
 
commit d9c7edd51d7858fae466853dc57eec66c740399e
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Tue May 3 22:20:42 2011 -0400

    fdo#36051: Eliminated the hang due to removal of autofill undo object.
    
    An artifact of the old code, which appears to do nothing meaningful
    today was performing an incredibly slow operation upon destruction of
    the autofill undo object.  Removed it, and also removed several other
    methods and data members that were used only in that removed code.

diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 820dd2c..4c7202b 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -1487,7 +1487,6 @@ public:
     VirtualDevice*	GetVirtualDevice_100th_mm();
     SC_DLLPUBLIC OutputDevice*	GetRefDevice();	// WYSIWYG: Printer, otherwise VirtualDevice...
 
-    void 			EraseNonUsedSharedNames(sal_uInt16 nLevel);
     sal_Bool			GetNextSpellingCell(SCCOL& nCol, SCROW& nRow, SCTAB nTab,
                                         sal_Bool bInSel, const ScMarkData& rMark) const;
 
diff --git a/sc/inc/rangenam.hxx b/sc/inc/rangenam.hxx
index e06f208..21cf333 100644
--- a/sc/inc/rangenam.hxx
+++ b/sc/inc/rangenam.hxx
@@ -181,7 +181,6 @@ class ScRangeName
 private:
     typedef ::boost::ptr_set<ScRangeData> DataType;
     DataType maData;
-    sal_uInt16  mnSharedMaxIndex;
 
 public:
     /// Map that manages stored ScRangeName instances.
@@ -208,8 +207,6 @@ public:
     void UpdateTabRef(SCTAB nTable, sal_uInt16 nFlag, SCTAB nNewTable = 0);
     void UpdateTranspose(const ScRange& rSource, const ScAddress& rDest);
     void UpdateGrow(const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY);
-    sal_uInt16 GetSharedMaxIndex();
-    void SetSharedMaxIndex(sal_uInt16 nInd);
 
     SC_DLLPUBLIC const_iterator begin() const;
     SC_DLLPUBLIC const_iterator end() const;
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 27c925b..36bd138 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -173,7 +173,6 @@ private:
     ScSortParam		aSortParam;
     CollatorWrapper*	pSortCollator;
     sal_Bool			bGlobalKeepQuery;
-    sal_Bool			bSharedNameInserted;
 
     ScRangeVec      aPrintRanges;
     bool            bPrintEntireSheet;
diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx
index 5c4957d..80b0c12 100644
--- a/sc/source/core/data/documen2.cxx
+++ b/sc/source/core/data/documen2.cxx
@@ -1130,53 +1130,6 @@ void ScDocument::SetError( SCCOL nCol, SCROW nRow, SCTAB nTab, const sal_uInt16
             pTab[nTab]->SetError( nCol, nRow, nError );
 }
 
-namespace {
-
-bool eraseUnusedSharedName(ScRangeName* pRangeName, ScTable* pTab[], sal_uInt16 nLevel)
-{
-    if (!pRangeName)
-        return false;
-
-    ScRangeName::iterator itr = pRangeName->begin(), itrEnd = pRangeName->end();
-    for (; itr != itrEnd; ++itr)
-    {
-        if (!itr->HasType(RT_SHARED))
-            continue;
-
-        String aName;
-        itr->GetName(aName);
-        aName.Erase(0, 6);						// !!! vgl. Table4, FillFormula !!
-        sal_uInt16 nInd = static_cast<sal_uInt16>(aName.ToInt32());
-        if (nInd > nLevel)
-            continue;
-
-        sal_uInt16 nIndex = itr->GetIndex();
-
-        bool bInUse = false;
-        for (SCTAB j = 0; !bInUse && (j <= MAXTAB); ++j)
-        {
-            if (pTab[j])
-                bInUse = pTab[j]->IsRangeNameInUse(0, 0, MAXCOL-1, MAXROW-1, nIndex);
-        }
-        if (!bInUse)
-        {
-            pRangeName->erase(itr);
-            return true;
-        }
-    }
-    return false;
-}
-
-}
-
-void ScDocument::EraseNonUsedSharedNames(sal_uInt16 nLevel)
-{
-    if (!pRangeName)
-        return;
-    while (eraseUnusedSharedName(pRangeName, pTab, nLevel))
-        ;
-}
-
 //	----------------------------------------------------------------------------
 
 void ScDocument::SetConsolidateDlgData( const ScConsolidateParam* pData )
diff --git a/sc/source/core/data/table4.cxx b/sc/source/core/data/table4.cxx
index 4d0c5d1..4c2e15b 100644
--- a/sc/source/core/data/table4.cxx
+++ b/sc/source/core/data/table4.cxx
@@ -1576,17 +1576,11 @@ void ScTable::Fill( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
     ScProgress aProgress( pDocument->GetDocumentShell(),
                             ScGlobal::GetRscString(STR_FILL_SERIES_PROGRESS), nProgCount );
 
-    bSharedNameInserted = false;
-
     if (eFillCmd == FILL_AUTO)
         FillAuto(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir, aProgress);
     else
         FillSeries(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir,
                     eFillCmd, eFillDateCmd, nStepValue, nMaxValue, 0, sal_True, aProgress);
-
-    if (bSharedNameInserted)						// Wurde Shared-Name eingefuegt?
-        pDocument->GetRangeName()->SetSharedMaxIndex(
-            pDocument->GetRangeName()->GetSharedMaxIndex()+1);	// dann hochzaehlen
 }
 
 
diff --git a/sc/source/core/tool/rangenam.cxx b/sc/source/core/tool/rangenam.cxx
index 01e2fbd..94d6797 100644
--- a/sc/source/core/tool/rangenam.cxx
+++ b/sc/source/core/tool/rangenam.cxx
@@ -729,11 +729,10 @@ void ScRangeName::copyLocalNames(const TabNameMap& rNames, TabNameCopyMap& rCopy
     }
 }
 
-ScRangeName::ScRangeName() :
-    mnSharedMaxIndex(0) {}
+ScRangeName::ScRangeName() {}
 
 ScRangeName::ScRangeName(const ScRangeName& r) :
-    maData(r.maData), mnSharedMaxIndex(r.mnSharedMaxIndex) {}
+    maData(r.maData) {}
 
 const ScRangeData* ScRangeName::findByRange(const ScRange& rRange) const
 {
@@ -806,16 +805,6 @@ void ScRangeName::UpdateGrow(const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY)
         itr->UpdateGrow(rArea, nGrowX, nGrowY);
 }
 
-sal_uInt16 ScRangeName::GetSharedMaxIndex()
-{
-    return mnSharedMaxIndex;
-}
-
-void ScRangeName::SetSharedMaxIndex(sal_uInt16 nInd)
-{
-    mnSharedMaxIndex = nInd;
-}
-
 ScRangeName::const_iterator ScRangeName::begin() const
 {
     return maData.begin();
@@ -886,7 +875,7 @@ void ScRangeName::clear()
 
 bool ScRangeName::operator== (const ScRangeName& r) const
 {
-    return maData == r.maData && mnSharedMaxIndex == r.mnSharedMaxIndex;
+    return maData == r.maData;
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx
index 30551cf..a0e5355 100644
--- a/sc/source/ui/docshell/docfunc.cxx
+++ b/sc/source/ui/docshell/docfunc.cxx
@@ -4023,8 +4023,7 @@ sal_Bool ScDocFunc::FillSimple( const ScRange& rRange, const ScMarkData* pTabMar
         {
             rDocShell.GetUndoManager()->AddUndoAction(
                 new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
-                                    eDir, FILL_SIMPLE, FILL_DAY, MAXDOUBLE, 1.0, 1e307,
-                                    pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) );
+                                    eDir, FILL_SIMPLE, FILL_DAY, MAXDOUBLE, 1.0, 1e307) );
         }
 
         rDocShell.PostPaintGridAll();
@@ -4143,8 +4142,7 @@ sal_Bool ScDocFunc::FillSeries( const ScRange& rRange, const ScMarkData* pTabMar
         {
             rDocShell.GetUndoManager()->AddUndoAction(
                 new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
-                                    eDir, eCmd, eDateCmd, fStart, fStep, fMax,
-                                    pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) );
+                                    eDir, eCmd, eDateCmd, fStart, fStep, fMax) );
         }
 
         bSuccess = sal_True;
@@ -4271,8 +4269,7 @@ sal_Bool ScDocFunc::FillAuto( ScRange& rRange, const ScMarkData* pTabMark, FillD
     {
         rDocShell.GetUndoManager()->AddUndoAction(
             new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
-                                eDir, eCmd, eDateCmd, MAXDOUBLE, fStep, fMax,
-                                pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) );
+                                eDir, eCmd, eDateCmd, MAXDOUBLE, fStep, fMax) );
     }
 
     rDocShell.PostPaintGridAll();
diff --git a/sc/source/ui/inc/undoblk.hxx b/sc/source/ui/inc/undoblk.hxx
index d1e484d..42293d4 100644
--- a/sc/source/ui/inc/undoblk.hxx
+++ b/sc/source/ui/inc/undoblk.hxx
@@ -421,8 +421,7 @@ public:
                                     ScDocument* pNewUndoDoc, const ScMarkData& rMark,
                                     FillDir eNewFillDir,
                                     FillCmd eNewFillCmd, FillDateCmd eNewFillDateCmd,
-                                    double fNewStartValue, double fNewStepValue, double fNewMaxValue,
-                                    sal_uInt16 nMaxShIndex );
+                                    double fNewStartValue, double fNewStepValue, double fNewMaxValue );
     virtual 		~ScUndoAutoFill();
 
     virtual void	Undo();
@@ -444,7 +443,6 @@ private:
     double			fMaxValue;
     sal_uLong			nStartChangeAction;
     sal_uLong			nEndChangeAction;
-    sal_uInt16			nMaxSharedIndex;
 
     void			SetChangeTrack();
 };
diff --git a/sc/source/ui/undo/undoblk3.cxx b/sc/source/ui/undo/undoblk3.cxx
index b8cfabe..33caf97 100644
--- a/sc/source/ui/undo/undoblk3.cxx
+++ b/sc/source/ui/undo/undoblk3.cxx
@@ -602,8 +602,7 @@ ScUndoAutoFill::ScUndoAutoFill( ScDocShell* pNewDocShell,
                 const ScRange& rRange, const ScRange& rSourceArea,
                 ScDocument* pNewUndoDoc, const ScMarkData& rMark,
                 FillDir eNewFillDir, FillCmd eNewFillCmd, FillDateCmd eNewFillDateCmd,
-                double fNewStartValue, double fNewStepValue, double fNewMaxValue,
-                sal_uInt16 nMaxShIndex )
+                double fNewStartValue, double fNewStepValue, double fNewMaxValue )
         //
     :	ScBlockUndo( pNewDocShell, rRange, SC_UNDO_AUTOHEIGHT ),
         //
@@ -615,8 +614,7 @@ ScUndoAutoFill::ScUndoAutoFill( ScDocShell* pNewDocShell,
         eFillDateCmd	( eNewFillDateCmd ),
         fStartValue		( fNewStartValue ),
         fStepValue		( fNewStepValue ),
-        fMaxValue		( fNewMaxValue ),
-        nMaxSharedIndex	( nMaxShIndex)
+        fMaxValue		( fNewMaxValue )
 {
     SetChangeTrack();
 }
@@ -626,7 +624,6 @@ ScUndoAutoFill::ScUndoAutoFill( ScDocShell* pNewDocShell,
 
 ScUndoAutoFill::~ScUndoAutoFill()
 {
-    pDocShell->GetDocument()->EraseNonUsedSharedNames(nMaxSharedIndex);
     delete pUndoDoc;
 }
 
@@ -649,26 +646,6 @@ void ScUndoAutoFill::SetChangeTrack()
         nStartChangeAction = nEndChangeAction = 0;
 }
 
-namespace {
-
-bool eraseNameContaining(ScRangeName& rNames, const rtl::OUString& rCriteria)
-{
-    ScRangeName::iterator itr = rNames.begin(), itrEnd = rNames.end();
-    for (; itr != itrEnd; ++itr)
-    {
-        rtl::OUString aRName = itr->GetName();
-        if (aRName.indexOf(rCriteria) >= 0)
-        {
-            // Criteria found.  Erase this.
-            rNames.erase(itr);
-            return true;
-        }
-    }
-    return false;
-}
-
-}
-
 void ScUndoAutoFill::Undo()
 {
     BeginUndo();
@@ -698,29 +675,6 @@ void ScUndoAutoFill::Undo()
     if (pViewShell)
         pViewShell->CellContentChanged();
 
-// Shared-Names loeschen
-// Falls Undo ins Dokument gespeichert
-// => automatisches Loeschen am Ende
-// umarbeiten!!
-
-    String aName = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("___SC_"));
-    aName += String::CreateFromInt32(nMaxSharedIndex);
-    aName += '_';
-    ScRangeName* pRangeName = pDoc->GetRangeName();
-    bool bHasFound = false;
-    // Remove all range names that contain ___SC_...
-    while (true)
-    {
-        bool bErased = eraseNameContaining(*pRangeName, aName);
-        if (bErased)
-            bHasFound = true;
-        else
-            break;
-    }
-
-    if (bHasFound)
-        pRangeName->SetSharedMaxIndex(pRangeName->GetSharedMaxIndex()-1);
-
     ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
     if ( pChangeTrack )
         pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
commit 89024286750f1df62b0a687860eb08567e76422d
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Tue May 3 17:22:28 2011 -0400

    Simplify the code a bit.

diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 6370b66..3e86a75 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -5427,16 +5427,8 @@ void ScDocument::EnableUndo( bool bVal )
     // enabled, or else re-enabling it may not actually re-enable undo unless
     // the lock count becomes zero.
 
-    if (bVal)
-    {
-        if (!GetUndoManager()->IsUndoEnabled())
-            GetUndoManager()->EnableUndo(true);
-    }
-    else
-    {
-        if (GetUndoManager()->IsUndoEnabled())
-            GetUndoManager()->EnableUndo(false);
-    }
+    if (bVal != GetUndoManager()->IsUndoEnabled())
+        GetUndoManager()->EnableUndo(bVal);
 
     mbUndoEnabled = bVal;
 }
commit ae86fba1c98b16e0d98258d35265fd3ab50af710
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Tue May 3 17:16:41 2011 -0400

    fdo#36721: Fixed a crash on datapilot while editing the source range.

diff --git a/sc/source/ui/dbgui/pvlaydlg.cxx b/sc/source/ui/dbgui/pvlaydlg.cxx
index 0ff9928..6616595 100644
--- a/sc/source/ui/dbgui/pvlaydlg.cxx
+++ b/sc/source/ui/dbgui/pvlaydlg.cxx
@@ -1450,11 +1450,24 @@ void ScDPLayoutDlg::UpdateSrcRange()
     switch (eSrcType)
     {
         case SRC_REF:
+        {
             // data source is a range reference.
             if (inSheet.GetSourceRange() == aNewRange)
                 // new range is identical to the current range.  Nothing to do.
                 return;
             inSheet.SetSourceRange(aNewRange);
+            sal_uLong nError = inSheet.CheckSourceRange();
+            if (nError)
+            {
+                // The error number corresponds with string ID for the error
+                // message.  In the future we should display the error message
+                // somewhere in the dialog to let the user know of the reason
+                // for error.
+                aEdInPos.SetRefValid(false);
+                aBtnOk.Disable();
+                return;
+            }
+        }
         break;
         case SRC_NAME:
             // data source is a range name.
commit 2abc42e0734b2a95e80243bb27de8eaafc90d290
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Tue May 3 16:25:39 2011 -0400

    Invalidate page breaks on print range changes.

diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index a333603..551ecbf 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -1696,6 +1696,8 @@ void ScTable::SetRepeatColRange( const ScRange* pNew )
 
     if (IsStreamValid())
         SetStreamValid(false);
+
+    InvalidatePageBreaks();
 }
 
 void ScTable::SetRepeatRowRange( const ScRange* pNew )
@@ -1704,6 +1706,8 @@ void ScTable::SetRepeatRowRange( const ScRange* pNew )
 
     if (IsStreamValid())
         SetStreamValid(false);
+
+    InvalidatePageBreaks();
 }
 
 void ScTable::ClearPrintRanges()
@@ -1713,6 +1717,8 @@ void ScTable::ClearPrintRanges()
 
     if (IsStreamValid())
         SetStreamValid(false);
+
+    InvalidatePageBreaks();
 }
 
 void ScTable::AddPrintRange( const ScRange& rNew )
@@ -1723,6 +1729,8 @@ void ScTable::AddPrintRange( const ScRange& rNew )
 
     if (IsStreamValid())
         SetStreamValid(false);
+
+    InvalidatePageBreaks();
 }
 
 
commit d53ec5342f018f7c766e47bf67aefebd3fe76d6a
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Tue May 3 16:05:44 2011 -0400

    fdo#36746: Prevent crash during sort.
    
    This was indirectly caused by the change in SfxUndoManager, to keep
    track of lock count to allow nested enabling / disabling of undo
    operations.  Because of this, it's very important to not enable /
    disable unless it's currently disabled / enabled, respectively.

diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index bb881a0..6370b66 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -5422,7 +5422,22 @@ void ScDocument::SetSubTotalCellsDirty(const ScRange& rDirtyRange)
 
 void ScDocument::EnableUndo( bool bVal )
 {
-    GetUndoManager()->EnableUndo(bVal);
+    // The undo manager increases lock count every time undo is disabled.
+    // Because of this, we shouldn't disable undo unless it's currently
+    // enabled, or else re-enabling it may not actually re-enable undo unless
+    // the lock count becomes zero.
+
+    if (bVal)
+    {
+        if (!GetUndoManager()->IsUndoEnabled())
+            GetUndoManager()->EnableUndo(true);
+    }
+    else
+    {

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list