diff options
author | Eike Rathke <erack@redhat.com> | 2020-04-08 00:47:09 +0200 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2020-04-08 01:57:45 +0200 |
commit | b1da67699bd05b26ee11460347ca7077d366c2fc (patch) | |
tree | c6f9b96bceac4fabe3748f66e52232684ef0f20d /sc | |
parent | b3363960f97dcb7eaa10dfa708d71198a345924c (diff) |
Resolves: tdf#131442 Sort must not contain matrix formula except 1x1 array
Change-Id: Idc7a9646a70c59fceee0b36426f38a938cf073ce
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/91858
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
Diffstat (limited to 'sc')
-rw-r--r-- | sc/inc/column.hxx | 2 | ||||
-rw-r--r-- | sc/inc/document.hxx | 3 | ||||
-rw-r--r-- | sc/inc/table.hxx | 6 | ||||
-rw-r--r-- | sc/source/core/data/column.cxx | 8 | ||||
-rw-r--r-- | sc/source/core/data/document.cxx | 5 | ||||
-rw-r--r-- | sc/source/core/data/table2.cxx | 30 | ||||
-rw-r--r-- | sc/source/ui/docshell/dbdocfun.cxx | 4 | ||||
-rw-r--r-- | sc/source/ui/docshell/editable.cxx | 12 | ||||
-rw-r--r-- | sc/source/ui/inc/editable.hxx | 9 |
9 files changed, 53 insertions, 26 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 576a88a8f71a..0eb2ad5f1c85 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -234,7 +234,7 @@ public: void FindUsed( SCROW nStartRow, SCROW nEndRow, mdds::flat_segment_tree<SCROW, bool>& rUsed ) const; SCSIZE VisibleCount( SCROW nStartRow, SCROW nEndRow ) const; - sc::MatrixEdge GetBlockMatrixEdges(SCROW nRow1, SCROW nRow2, sc::MatrixEdge nMask ) const; + sc::MatrixEdge GetBlockMatrixEdges(SCROW nRow1, SCROW nRow2, sc::MatrixEdge nMask, bool bNoMatrixAtAll ) const; bool HasSelectionMatrixFragment(const ScMarkData& rMark) const; bool GetFirstVisibleAttr( SCROW& rFirstRow ) const; diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 847a4c42ccee..99c328157347 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -900,7 +900,8 @@ public: bool IsBlockEditable( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, - bool* pOnlyNotBecauseOfMatrix = nullptr ) const; + bool* pOnlyNotBecauseOfMatrix = nullptr, + bool bNoMatrixAtAll = false ) const; bool IsSelectionEditable( const ScMarkData& rMark, bool* pOnlyNotBecauseOfMatrix = nullptr ) const; bool HasSelectedBlockMatrixFragment( SCCOL nStartCol, SCROW nStartRow, diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 8feb233480cf..7de7f24b59c2 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -392,11 +392,13 @@ public: void UnlockTable(); bool IsBlockEditable( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, - SCROW nRow2, bool* pOnlyNotBecauseOfMatrix = nullptr ) const; + SCROW nRow2, bool* pOnlyNotBecauseOfMatrix = nullptr, + bool bNoMatrixAtAll = false ) const; bool IsSelectionEditable( const ScMarkData& rMark, bool* pOnlyNotBecauseOfMatrix = nullptr ) const; - bool HasBlockMatrixFragment( const SCCOL nCol1, SCROW nRow1, const SCCOL nCol2, SCROW nRow2 ) const; + bool HasBlockMatrixFragment( const SCCOL nCol1, SCROW nRow1, const SCCOL nCol2, SCROW nRow2, + bool bNoMatrixAtAll = false ) const; bool HasSelectionMatrixFragment( const ScMarkData& rMark ) const; bool IsBlockEmpty( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, bool bIgnoreNotes ) const; diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx index 7fa1c4c30286..9388e01ee1f0 100644 --- a/sc/source/core/data/column.cxx +++ b/sc/source/core/data/column.cxx @@ -110,7 +110,8 @@ SCROW ScColumn::GetNextUnprotected( SCROW nRow, bool bUp ) const return pAttrArray->GetNextUnprotected(nRow, bUp); } -sc::MatrixEdge ScColumn::GetBlockMatrixEdges( SCROW nRow1, SCROW nRow2, sc::MatrixEdge nMask ) const +sc::MatrixEdge ScColumn::GetBlockMatrixEdges( SCROW nRow1, SCROW nRow2, sc::MatrixEdge nMask, + bool bNoMatrixAtAll ) const { using namespace sc; @@ -163,6 +164,11 @@ sc::MatrixEdge ScColumn::GetBlockMatrixEdges( SCROW nRow1, SCROW nRow2, sc::Matr if (nEdges == MatrixEdge::Nothing) continue; + // A 1x1 matrix array formula is OK even for no matrix at all. + if (bNoMatrixAtAll + && (nEdges != (MatrixEdge::Top | MatrixEdge::Left | MatrixEdge::Bottom | MatrixEdge::Right))) + return MatrixEdge::Inside; // per convention Inside + if (nEdges & MatrixEdge::Top) bOpen = true; // top edge opens, keep on looking else if (!bOpen) diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index 4ecd59225f45..ad292b70b7e2 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -5323,7 +5323,8 @@ void ScDocument::UnlockTable(SCTAB nTab) bool ScDocument::IsBlockEditable( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, - bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const + bool* pOnlyNotBecauseOfMatrix /* = NULL */, + bool bNoMatrixAtAll ) const { // import into read-only document is possible if (!bImportingXML && !mbChangeReadOnlyEnabled && mpShell && mpShell->IsReadOnly()) @@ -5336,7 +5337,7 @@ bool ScDocument::IsBlockEditable( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size())) if (maTabs[nTab]) return maTabs[nTab]->IsBlockEditable( nStartCol, nStartRow, nEndCol, - nEndRow, pOnlyNotBecauseOfMatrix ); + nEndRow, pOnlyNotBecauseOfMatrix, bNoMatrixAtAll ); OSL_FAIL("wrong table number"); if ( pOnlyNotBecauseOfMatrix ) diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index a4391ab7ec05..869d255b2b47 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -2297,7 +2297,8 @@ void ScTable::FindMaxRotCol( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCC } } -bool ScTable::HasBlockMatrixFragment( const SCCOL nCol1, SCROW nRow1, const SCCOL nCol2, SCROW nRow2 ) const +bool ScTable::HasBlockMatrixFragment( const SCCOL nCol1, SCROW nRow1, const SCCOL nCol2, SCROW nRow2, + bool bNoMatrixAtAll ) const { using namespace sc; @@ -2311,28 +2312,38 @@ bool ScTable::HasBlockMatrixFragment( const SCCOL nCol1, SCROW nRow1, const SCCO if ( nCol1 == nMaxCol2 ) { // left and right column const MatrixEdge n = MatrixEdge::Left | MatrixEdge::Right; - nEdges = aCol[nCol1].GetBlockMatrixEdges( nRow1, nRow2, n ); + nEdges = aCol[nCol1].GetBlockMatrixEdges( nRow1, nRow2, n, bNoMatrixAtAll ); if ((nEdges != MatrixEdge::Nothing) && (((nEdges & n)!=n) || (nEdges & (MatrixEdge::Inside|MatrixEdge::Open)))) return true; // left or right edge is missing or open } else { // left column - nEdges = aCol[nCol1].GetBlockMatrixEdges(nRow1, nRow2, MatrixEdge::Left); + nEdges = aCol[nCol1].GetBlockMatrixEdges(nRow1, nRow2, MatrixEdge::Left, bNoMatrixAtAll); if ((nEdges != MatrixEdge::Nothing) && ((!(nEdges & MatrixEdge::Left)) || (nEdges & (MatrixEdge::Inside|MatrixEdge::Open)))) return true; // left edge missing or open // right column - nEdges = aCol[nMaxCol2].GetBlockMatrixEdges(nRow1, nRow2, MatrixEdge::Right); + nEdges = aCol[nMaxCol2].GetBlockMatrixEdges(nRow1, nRow2, MatrixEdge::Right, bNoMatrixAtAll); if ((nEdges != MatrixEdge::Nothing) && ((!(nEdges & MatrixEdge::Right)) || (nEdges & (MatrixEdge::Inside|MatrixEdge::Open)))) return true; // right edge is missing or open } - if ( nRow1 == nRow2 ) + if (bNoMatrixAtAll) + { + for (SCCOL i=nCol1; i<=nMaxCol2; i++) + { + nEdges = aCol[i].GetBlockMatrixEdges( nRow1, nRow2, MatrixEdge::Nothing, bNoMatrixAtAll); + if (nEdges != MatrixEdge::Nothing + && (nEdges != (MatrixEdge::Top | MatrixEdge::Left | MatrixEdge::Bottom | MatrixEdge::Right))) + return true; + } + } + else if ( nRow1 == nRow2 ) { // Row on top and on bottom bool bOpen = false; const MatrixEdge n = MatrixEdge::Bottom | MatrixEdge::Top; for ( SCCOL i=nCol1; i<=nMaxCol2; i++) { - nEdges = aCol[i].GetBlockMatrixEdges( nRow1, nRow1, n ); + nEdges = aCol[i].GetBlockMatrixEdges( nRow1, nRow1, n, bNoMatrixAtAll ); if (nEdges != MatrixEdge::Nothing) { if ( (nEdges & n) != n ) @@ -2360,7 +2371,7 @@ bool ScTable::HasBlockMatrixFragment( const SCCOL nCol1, SCROW nRow1, const SCCO bool bOpen = false; for ( SCCOL i=nCol1; i<=nMaxCol2; i++) { - nEdges = aCol[i].GetBlockMatrixEdges( nR, nR, n ); + nEdges = aCol[i].GetBlockMatrixEdges( nR, nR, n, bNoMatrixAtAll ); if ( nEdges != MatrixEdge::Nothing) { // in top row no top edge respectively @@ -2399,7 +2410,8 @@ bool ScTable::HasSelectionMatrixFragment( const ScMarkData& rMark ) const } bool ScTable::IsBlockEditable( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, - SCROW nRow2, bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const + SCROW nRow2, bool* pOnlyNotBecauseOfMatrix /* = NULL */, + bool bNoMatrixAtAll ) const { if ( !ValidColRow( nCol2, nRow2 ) ) { @@ -2467,7 +2479,7 @@ bool ScTable::IsBlockEditable( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, } if ( bIsEditable ) { - if ( HasBlockMatrixFragment( nCol1, nRow1, nCol2, nRow2 ) ) + if (HasBlockMatrixFragment( nCol1, nRow1, nCol2, nRow2, bNoMatrixAtAll)) { bIsEditable = false; if ( pOnlyNotBecauseOfMatrix ) diff --git a/sc/source/ui/docshell/dbdocfun.cxx b/sc/source/ui/docshell/dbdocfun.cxx index e57020b93de3..352c77f619e9 100644 --- a/sc/source/ui/docshell/dbdocfun.cxx +++ b/sc/source/ui/docshell/dbdocfun.cxx @@ -512,8 +512,8 @@ bool ScDBDocFunc::Sort( SCTAB nTab, const ScSortParam& rSortParam, else nStartingColToEdit++; } - ScEditableTester aTester( &rDoc, nTab, nStartingColToEdit,nStartingRowToEdit, - aLocalParam.nCol2,aLocalParam.nRow2 ); + ScEditableTester aTester( &rDoc, nTab, nStartingColToEdit, nStartingRowToEdit, + aLocalParam.nCol2, aLocalParam.nRow2, true /*bNoMatrixAtAll*/ ); if (!aTester.IsEditable()) { if (!bApi) diff --git a/sc/source/ui/docshell/editable.cxx b/sc/source/ui/docshell/editable.cxx index 8d461a0806b7..ec9f071b9096 100644 --- a/sc/source/ui/docshell/editable.cxx +++ b/sc/source/ui/docshell/editable.cxx @@ -29,11 +29,11 @@ ScEditableTester::ScEditableTester() : } ScEditableTester::ScEditableTester( const ScDocument* pDoc, SCTAB nTab, - SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow ) : + SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, bool bNoMatrixAtAll ) : mbIsEditable(true), mbOnlyMatrix(true) { - TestBlock( pDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow ); + TestBlock( pDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow, bNoMatrixAtAll ); } ScEditableTester::ScEditableTester( const ScDocument* pDoc, @@ -80,12 +80,12 @@ ScEditableTester::ScEditableTester( } void ScEditableTester::TestBlock( const ScDocument* pDoc, SCTAB nTab, - SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow ) + SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, bool bNoMatrixAtAll ) { if (mbIsEditable || mbOnlyMatrix) { bool bThisMatrix; - if ( !pDoc->IsBlockEditable( nTab, nStartCol, nStartRow, nEndCol, nEndRow, &bThisMatrix ) ) + if (!pDoc->IsBlockEditable( nTab, nStartCol, nStartRow, nEndCol, nEndRow, &bThisMatrix, bNoMatrixAtAll)) { mbIsEditable = false; if ( !bThisMatrix ) @@ -104,7 +104,7 @@ void ScEditableTester::TestSelectedBlock( const ScDocument* pDoc, if (rTab >= nTabCount) break; - TestBlock( pDoc, rTab, nStartCol, nStartRow, nEndCol, nEndRow ); + TestBlock( pDoc, rTab, nStartCol, nStartRow, nEndCol, nEndRow, false ); } } @@ -117,7 +117,7 @@ void ScEditableTester::TestRange( const ScDocument* pDoc, const ScRange& rRange SCROW nEndRow = rRange.aEnd.Row(); SCTAB nEndTab = rRange.aEnd.Tab(); for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) - TestBlock( pDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow ); + TestBlock( pDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow, false ); } void ScEditableTester::TestSelection( const ScDocument* pDoc, const ScMarkData& rMark ) diff --git a/sc/source/ui/inc/editable.hxx b/sc/source/ui/inc/editable.hxx index 05eaa985d04c..97d28ede388f 100644 --- a/sc/source/ui/inc/editable.hxx +++ b/sc/source/ui/inc/editable.hxx @@ -41,8 +41,12 @@ public: ScEditableTester(); // calls TestBlock + /** @param bNoMatrixAtAll + TRUE if there must not be any matrix, not even entirely + containted; for example in sorting. */ ScEditableTester( const ScDocument* pDoc, SCTAB nTab, - SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow ); + SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, + bool bNoMatrixAtAll = false ); // calls TestSelectedBlock ScEditableTester( const ScDocument* pDoc, @@ -65,7 +69,8 @@ public: // Several calls to the Test... methods check if *all* of the ranges // are editable. For several independent checks, Reset() has to be used. void TestBlock( const ScDocument* pDoc, SCTAB nTab, - SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow ); + SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, + bool bNoMatrixAtAll = false ); void TestSelectedBlock( const ScDocument* pDoc, SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, const ScMarkData& rMark ); |