Date: prev next · Thread: first prev next last
2012 Archives by date, by thread · List index


Hi Markus,

On Thu, Mar 15, 2012 at 04:27, Markus Mohrhard
<markus.mohrhard@googlemail.com> wrote:
Hello Albert,

I have a simple idea that shouldn't be too complex to implement. I
think we can agree that only the sort entries are the difficult part.
I would create a control for an entry an instantiate this one for each
new sort entry. I think we do similar things for several other
dialogs, e.g. SvTabListBox with simple entries or the document
properties dialog with more complex entries.

Great, Let me know if there is anything that I can do to help.

Just two small comments. I think it would be a good idea to group the
three entries in ScSortParam into a own struct so that we only need
one vector. That will make it easier to keep the entries in sync.
And you have a lot of whitespace changes. Can you check your editor
why it replaces so many spaces with tabs. It is quite difficult to
review it otherwise.

Sorry for the messy patch, I didn't check it properly prior to posting
it. I have reworked the patch and also split it up into two.

Now the first patch contains only the internal rework to remove the
limits and converting the data containers from arrays to std:vector.
I've also grouped the three entries in ScSortParam into a own struct
as you suggested, which resulted in quite a number of changes.

Once reviewed this patch can be pushed directly to master since it is
self contained and doesn't change the old
behavior, me thinks.

The second patch is for test purpose only. It basically adds a fourth
sort key when you press the "Add" button.

BTW: I have a Patch that partly fixes fdo#43937, but I guess since it
needs a greater overhaul anyway,  that's of no interest?

Sure it is. If it is simple and safe we can of course use it for 3-5
and until it is fixed in master there too.

Testing my proposed patch some more, I realize it causes more new
problems than it solves. I'll
 have another look at it later.

/Albert
From 67a04d9bd9aa5c298f59cc6e855124da6b9fcddc Mon Sep 17 00:00:00 2001
From: Albert Thuswaldner <albert.thuswaldner@gmail.com>
Date: Tue, 20 Mar 2012 19:38:29 +0100
Subject: [PATCH 1/2] fdo#45747 remove the limitation to 3 sort entries in calc part1

---
 sc/inc/sortparam.hxx                             |   23 +-
 sc/source/core/data/sortparam.cxx                |   98 +++----
 sc/source/core/data/table3.cxx                   |   24 +-
 sc/source/core/tool/dbdata.cxx                   |   14 +-
 sc/source/filter/xml/XMLExportDatabaseRanges.cxx |    8 +-
 sc/source/filter/xml/xmldrani.cxx                |    6 +-
 sc/source/ui/dbgui/tpsort.cxx                    |  347 ++++++++++-----------
 sc/source/ui/docshell/dbdocfun.cxx               |    6 +-
 sc/source/ui/inc/tpsort.hxx                      |   18 +-
 sc/source/ui/src/sortdlg.src                     |    6 +-
 sc/source/ui/unoobj/cellsuno.cxx                 |   16 +-
 sc/source/ui/unoobj/datauno.cxx                  |   46 ++--
 sc/source/ui/vba/vbarange.cxx                    |   18 +-
 sc/source/ui/view/cellsh2.cxx                    |   44 ++--
 sc/source/ui/view/dbfunc3.cxx                    |    2 +-
 15 files changed, 332 insertions(+), 344 deletions(-)

diff --git a/sc/inc/sortparam.hxx b/sc/inc/sortparam.hxx
index f1d4e21..b2de75b 100644
--- a/sc/inc/sortparam.hxx
+++ b/sc/inc/sortparam.hxx
@@ -29,16 +29,27 @@
 #ifndef SC_SORTPARAM_HXX
 #define SC_SORTPARAM_HXX
 
+#define DEFSORT 3
+
+#include <vector>
+
 #include "address.hxx"
 #include <tools/solar.h>
 #include <com/sun/star/lang/Locale.hpp>
 #include "scdllapi.h"
 
-#define MAXSORT 3
-
 struct ScSubTotalParam;
 struct ScQueryParam;
 
+struct SCSortKeyState
+{
+    bool     bDoSort;
+    SCCOLROW nField;
+    bool     bAscending;
+};
+
+typedef ::std::vector<SCSortKeyState> SCSortKeyStateVec;
+
 struct SC_DLLPUBLIC ScSortParam
 {
     SCCOL       nCol1;
@@ -56,13 +67,12 @@ struct SC_DLLPUBLIC ScSortParam
     SCTAB       nDestTab;
     SCCOL       nDestCol;
     SCROW       nDestRow;
-    bool        bDoSort[MAXSORT];
-    SCCOLROW    nField[MAXSORT];
-    bool        bAscending[MAXSORT];
+    SCSortKeyStateVec maKeyState;
     ::com::sun::star::lang::Locale aCollatorLocale;
     ::rtl::OUString aCollatorAlgorithm;
     sal_uInt16  nCompatHeader;
 
+
     ScSortParam();
     ScSortParam( const ScSortParam& r );
     /// SubTotals sort
@@ -73,8 +83,9 @@ struct SC_DLLPUBLIC ScSortParam
     ScSortParam&    operator=  ( const ScSortParam& r );
     bool            operator== ( const ScSortParam& rOther ) const;
     void            Clear       ();
-
     void            MoveToDest();
+
+    inline sal_uInt16 GetSortKeyCount() const { return maKeyState.size(); }
 };
 
 
diff --git a/sc/source/core/data/sortparam.cxx b/sc/source/core/data/sortparam.cxx
index 26e1ac7..704cbc5 100644
--- a/sc/source/core/data/sortparam.cxx
+++ b/sc/source/core/data/sortparam.cxx
@@ -51,15 +51,10 @@ ScSortParam::ScSortParam( const ScSortParam& r ) :
         bNaturalSort(r.bNaturalSort),bUserDef(r.bUserDef),
         bIncludePattern(r.bIncludePattern),bInplace(r.bInplace),
         nDestTab(r.nDestTab),nDestCol(r.nDestCol),nDestRow(r.nDestRow),
+        maKeyState( r.maKeyState ),
         aCollatorLocale( r.aCollatorLocale ), aCollatorAlgorithm( r.aCollatorAlgorithm ),
         nCompatHeader( r.nCompatHeader )
 {
-    for (sal_uInt16 i=0; i<MAXSORT; i++)
-    {
-        bDoSort[i]    = r.bDoSort[i];
-        nField[i]     = r.nField[i];
-        bAscending[i] = r.bAscending[i];
-    }
 }
 
 //------------------------------------------------------------------------
@@ -76,12 +71,8 @@ void ScSortParam::Clear()
     aCollatorLocale = ::com::sun::star::lang::Locale();
     aCollatorAlgorithm = ::rtl::OUString();
 
-    for (sal_uInt16 i=0; i<MAXSORT; i++)
-    {
-        bDoSort[i]    = false;
-        nField[i]     = 0;
-        bAscending[i] = true;
-    }
+    // Initialize to default size
+    maKeyState.assign( DEFSORT, { false, 0, true } );
 }
 
 //------------------------------------------------------------------------
@@ -103,17 +94,11 @@ ScSortParam& ScSortParam::operator=( const ScSortParam& r )
     nDestTab        = r.nDestTab;
     nDestCol        = r.nDestCol;
     nDestRow        = r.nDestRow;
+    maKeyState      = r.maKeyState;
     aCollatorLocale         = r.aCollatorLocale;
     aCollatorAlgorithm      = r.aCollatorAlgorithm;
     nCompatHeader   = r.nCompatHeader;
 
-    for (sal_uInt16 i=0; i<MAXSORT; i++)
-    {
-        bDoSort[i]    = r.bDoSort[i];
-        nField[i]     = r.nField[i];
-        bAscending[i] = r.bAscending[i];
-    }
-
     return *this;
 }
 
@@ -125,10 +110,20 @@ bool ScSortParam::operator==( const ScSortParam& rOther ) const
     // Anzahl der Sorts gleich?
     sal_uInt16 nLast      = 0;
     sal_uInt16 nOtherLast = 0;
-    while ( bDoSort[nLast++] && nLast < MAXSORT ) ;
-    while ( rOther.bDoSort[nOtherLast++] && nOtherLast < MAXSORT ) ;
-    nLast--;
-    nOtherLast--;
+    sal_uInt16 nSortSize = GetSortKeyCount();
+
+    if ( !maKeyState.empty() )
+    {
+        while ( maKeyState[nLast++].bDoSort && nLast < nSortSize ) ;
+        nLast--;
+    }
+
+    if ( !rOther.maKeyState.empty() )
+    {
+        while ( rOther.maKeyState[nOtherLast++].bDoSort && nOtherLast < nSortSize ) ;
+        nOtherLast--;
+    }
+
     if (   (nLast           == nOtherLast)
         && (nCol1           == rOther.nCol1)
         && (nRow1           == rOther.nRow1)
@@ -149,14 +144,17 @@ bool ScSortParam::operator==( const ScSortParam& rOther ) const
         && (aCollatorLocale.Country     == rOther.aCollatorLocale.Country)
         && (aCollatorLocale.Variant     == rOther.aCollatorLocale.Variant)
         && (aCollatorAlgorithm          == rOther.aCollatorAlgorithm)
+        && ( !maKeyState.empty() || !rOther.maKeyState.empty() )
         )
     {
         bEqual = true;
         for ( sal_uInt16 i=0; i<=nLast && bEqual; i++ )
-        {
-            bEqual = (nField[i] == rOther.nField[i]) && (bAscending[i]  == rOther.bAscending[i]);
-        }
+            bEqual = ( maKeyState[i].nField == rOther.maKeyState[i].nField ) &&
+                ( maKeyState[i].bAscending  == rOther.maKeyState[i].bAscending );
     }
+    if ( maKeyState.empty() && rOther.maKeyState.empty() )
+        bEqual = true;
+
     return bEqual;
 }
 
@@ -172,6 +170,7 @@ ScSortParam::ScSortParam( const ScSubTotalParam& rSub, const ScSortParam& rOld )
         nCompatHeader( rOld.nCompatHeader )
 {
     sal_uInt16 nNewCount = 0;
+    sal_uInt16 nSortSize = GetSortKeyCount();
     sal_uInt16 i;
 
     //  zuerst die Gruppen aus den Teilergebnissen
@@ -179,42 +178,34 @@ ScSortParam::ScSortParam( const ScSubTotalParam& rSub, const ScSortParam& 
rOld )
         for (i=0; i<MAXSUBTOTAL; i++)
             if (rSub.bGroupActive[i])
             {
-                if (nNewCount < MAXSORT)
+                if (nNewCount < nSortSize)
                 {
-                    bDoSort[nNewCount]    = true;
-                    nField[nNewCount]     = rSub.nField[i];
-                    bAscending[nNewCount] = rSub.bAscending;
+                    maKeyState[nNewCount] = { true, rSub.nField[i], rSub.bAscending };
                     ++nNewCount;
                 }
             }
 
     //  dann dahinter die alten Einstellungen
-    for (i=0; i<MAXSORT; i++)
-        if (rOld.bDoSort[i])
+    for (i=0; i<nSortSize; i++)
+        if (rOld.maKeyState[i].bDoSort)
         {
-            SCCOLROW nThisField = rOld.nField[i];
+            SCCOLROW nThisField = rOld.maKeyState[i].nField;
             bool bDouble = false;
             for (sal_uInt16 j=0; j<nNewCount; j++)
-                if ( nField[j] == nThisField )
+                if ( maKeyState[j].nField == nThisField )
                     bDouble = true;
             if (!bDouble)               // ein Feld nicht zweimal eintragen
             {
-                if (nNewCount < MAXSORT)
+                if (nNewCount < nSortSize)
                 {
-                    bDoSort[nNewCount]    = true;
-                    nField[nNewCount]     = nThisField;
-                    bAscending[nNewCount] = rOld.bAscending[i];
+                    maKeyState[nNewCount] = { true, nThisField, rOld.maKeyState[i].bAscending };
                     ++nNewCount;
                 }
             }
         }
 
-    for (i=nNewCount; i<MAXSORT; i++)       // Rest loeschen
-    {
-        bDoSort[i]    = false;
-        nField[i]     = 0;
-        bAscending[i] = true;
-    }
+    for (i=nNewCount; i<nSortSize; i++)       // Rest loeschen
+        maKeyState[i] = { false, 0, true };
 }
 
 //------------------------------------------------------------------------
@@ -228,15 +219,10 @@ ScSortParam::ScSortParam( const ScQueryParam& rParam, SCCOL nCol ) :
         bInplace(true),
         nDestTab(0),nDestCol(0),nDestRow(0), nCompatHeader(2)
 {
-    bDoSort[0] = true;
-    nField[0] = nCol;
-    bAscending[0] = true;
-    for (sal_uInt16 i=1; i<MAXSORT; i++)
-    {
-        bDoSort[i]    = false;
-        nField[i]     = 0;
-        bAscending[i] = true;
-    }
+    maKeyState[0] = { true, nCol, true };
+
+    for (sal_uInt16 i=1; i<GetSortKeyCount(); i++)
+        maKeyState[i] = { false, 0, true };
 }
 
 //------------------------------------------------------------------------
@@ -252,11 +238,11 @@ void ScSortParam::MoveToDest()
         nRow1 = sal::static_int_cast<SCROW>( nRow1 + nDifY );
         nCol2 = sal::static_int_cast<SCCOL>( nCol2 + nDifX );
         nRow2 = sal::static_int_cast<SCROW>( nRow2 + nDifY );
-        for (sal_uInt16 i=0; i<MAXSORT; i++)
+        for (sal_uInt16 i=0; i<GetSortKeyCount(); i++)
             if (bByRow)
-                nField[i] += nDifX;
+                maKeyState[i].nField += nDifX;
             else
-                nField[i] += nDifY;
+                maKeyState[i].nField += nDifY;
 
         bInplace = true;
     }
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index d740a30..3310956 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -270,14 +270,14 @@ public:
 ScSortInfoArray* ScTable::CreateSortInfoArray( SCCOLROW nInd1, SCCOLROW nInd2 )
 {
     sal_uInt16 nUsedSorts = 1;
-    while ( nUsedSorts < nMaxSorts && aSortParam.bDoSort[nUsedSorts] )
+    while ( nUsedSorts < nMaxSorts && aSortParam.maKeyState[nUsedSorts].bDoSort )
         nUsedSorts++;
     ScSortInfoArray* pArray = new ScSortInfoArray( nUsedSorts, nInd1, nInd2 );
     if ( aSortParam.bByRow )
     {
         for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
         {
-            SCCOL nCol = static_cast<SCCOL>(aSortParam.nField[nSort]);
+            SCCOL nCol = static_cast<SCCOL>(aSortParam.maKeyState[nSort].nField);
             ScColumn* pCol = &aCol[nCol];
             for ( SCROW nRow = nInd1; nRow <= nInd2; nRow++ )
             {
@@ -292,7 +292,7 @@ ScSortInfoArray* ScTable::CreateSortInfoArray( SCCOLROW nInd1, SCCOLROW nInd2 )
     {
         for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
         {
-            SCROW nRow = aSortParam.nField[nSort];
+            SCROW nRow = aSortParam.maKeyState[nSort].nField;
             for ( SCCOL nCol = static_cast<SCCOL>(nInd1);
                     nCol <= static_cast<SCCOL>(nInd2); nCol++ )
             {
@@ -473,7 +473,7 @@ short ScTable::CompareCell( sal_uInt16 nSort,
                 else if (nVal1 > nVal2)
                     nRes = 1;
             }
-            if ( !aSortParam.bAscending[nSort] )
+            if ( !aSortParam.maKeyState[nSort].bAscending )
                 nRes = -nRes;
         }
         else
@@ -499,12 +499,12 @@ short ScTable::Compare( ScSortInfoArray* pArray, SCCOLROW nIndex1, SCCOLROW 
nInd
         ScSortInfo* pInfo2 = pArray->Get( nSort, nIndex2 );
         if ( aSortParam.bByRow )
             nRes = CompareCell( nSort,
-                pInfo1->pCell, static_cast<SCCOL>(aSortParam.nField[nSort]), pInfo1->nOrg,
-                pInfo2->pCell, static_cast<SCCOL>(aSortParam.nField[nSort]), pInfo2->nOrg );
+                pInfo1->pCell, static_cast<SCCOL>(aSortParam.maKeyState[nSort].nField), 
pInfo1->nOrg,
+                pInfo2->pCell, static_cast<SCCOL>(aSortParam.maKeyState[nSort].nField), 
pInfo2->nOrg );
         else
             nRes = CompareCell( nSort,
-                pInfo1->pCell, static_cast<SCCOL>(pInfo1->nOrg), aSortParam.nField[nSort],
-                pInfo2->pCell, static_cast<SCCOL>(pInfo2->nOrg), aSortParam.nField[nSort] );
+                pInfo1->pCell, static_cast<SCCOL>(pInfo1->nOrg), 
aSortParam.maKeyState[nSort].nField,
+                pInfo2->pCell, static_cast<SCCOL>(pInfo2->nOrg), 
aSortParam.maKeyState[nSort].nField );
     } while ( nRes == 0 && ++nSort < pArray->GetUsedSorts() );
     if( nRes == 0 )
     {
@@ -684,22 +684,22 @@ short ScTable::Compare(SCCOLROW nIndex1, SCCOLROW nIndex2)
     {
         do
         {
-            SCCOL nCol = static_cast<SCCOL>(aSortParam.nField[nSort]);
+            SCCOL nCol = static_cast<SCCOL>(aSortParam.maKeyState[nSort].nField);
             ScBaseCell* pCell1 = aCol[nCol].GetCell( nIndex1 );
             ScBaseCell* pCell2 = aCol[nCol].GetCell( nIndex2 );
             nRes = CompareCell( nSort, pCell1, nCol, nIndex1, pCell2, nCol, nIndex2 );
-        } while ( nRes == 0 && ++nSort < nMaxSorts && aSortParam.bDoSort[nSort] );
+        } while ( nRes == 0 && ++nSort < nMaxSorts && aSortParam.maKeyState[nSort].bDoSort );
     }
     else
     {
         do
         {
-            SCROW nRow = aSortParam.nField[nSort];
+            SCROW nRow = aSortParam.maKeyState[nSort].nField;
             ScBaseCell* pCell1 = aCol[nIndex1].GetCell( nRow );
             ScBaseCell* pCell2 = aCol[nIndex2].GetCell( nRow );
             nRes = CompareCell( nSort, pCell1, static_cast<SCCOL>(nIndex1),
                     nRow, pCell2, static_cast<SCCOL>(nIndex2), nRow );
-        } while ( nRes == 0 && ++nSort < nMaxSorts && aSortParam.bDoSort[nSort] );
+        } while ( nRes == 0 && ++nSort < nMaxSorts && aSortParam.maKeyState[nSort].bDoSort );
     }
     return nRes;
 }
diff --git a/sc/source/core/tool/dbdata.cxx b/sc/source/core/tool/dbdata.cxx
index c612d32..4c14735 100644
--- a/sc/source/core/tool/dbdata.cxx
+++ b/sc/source/core/tool/dbdata.cxx
@@ -246,7 +246,7 @@ ScDBData::~ScDBData()
             aBuf.append(ScGlobal::GetRscString(STR_OPERATION_FILTER));
     }
 
-    if (mpSortParam->bDoSort[0])
+    if (mpSortParam->maKeyState[0].bDoSort)
     {
         if (aBuf.getLength())
             aBuf.appendAscii(RTL_CONSTASCII_STRINGPARAM(", "));
@@ -299,13 +299,13 @@ void ScDBData::MoveTo(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, 
SCROW n
     long nSortDif = bByRow ? nDifX : nDifY;
     long nSortEnd = bByRow ? static_cast<long>(nCol2) : static_cast<long>(nRow2);
 
-    for (i=0; i<MAXSORT; i++)
+    for (i=0; i<mpSortParam->GetSortKeyCount(); i++)
     {
-        mpSortParam->nField[i] += nSortDif;
-        if (mpSortParam->nField[i] > nSortEnd)
+        mpSortParam->maKeyState[i].nField += nSortDif;
+        if (mpSortParam->maKeyState[i].nField > nSortEnd)
         {
-            mpSortParam->nField[i] = 0;
-            mpSortParam->bDoSort[i] = false;
+            mpSortParam->maKeyState[i].nField = 0;
+            mpSortParam->maKeyState[i].bDoSort = false;
         }
     }
 
@@ -460,7 +460,7 @@ bool ScDBData::HasQueryParam() const
 
 bool ScDBData::HasSortParam() const
 {
-    return mpSortParam && mpSortParam->bDoSort[0];
+    return mpSortParam && mpSortParam->maKeyState[0].bDoSort;
 }
 
 bool ScDBData::HasSubTotalParam() const
diff --git a/sc/source/filter/xml/XMLExportDatabaseRanges.cxx 
b/sc/source/filter/xml/XMLExportDatabaseRanges.cxx
index 8aab8b5..551c035 100644
--- a/sc/source/filter/xml/XMLExportDatabaseRanges.cxx
+++ b/sc/source/filter/xml/XMLExportDatabaseRanges.cxx
@@ -317,9 +317,9 @@ private:
 
         // Count sort items first.
         size_t nSortCount = 0;
-        for (; nSortCount < MAXSORT; ++nSortCount)
+        for (; nSortCount < aParam.GetSortKeyCount(); ++nSortCount)
         {
-            if (!aParam.bDoSort[nSortCount])
+            if (!aParam.maKeyState[nSortCount].bDoSort)
                 break;
         }
 
@@ -359,10 +359,10 @@ private:
         for (size_t i = 0; i < nSortCount; ++i)
         {
             // Convert field value from absolute to relative.
-            SCCOLROW nField = aParam.nField[i] - nFieldStart;
+            SCCOLROW nField = aParam.maKeyState[i].nField - nFieldStart;
             mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FIELD_NUMBER, 
OUString::valueOf(nField));
 
-            if (!aParam.bAscending[i])
+            if (!aParam.maKeyState[i].bAscending)
                 mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ORDER, XML_DESCENDING);
 
             if (aParam.bUserDef)
diff --git a/sc/source/filter/xml/xmldrani.cxx b/sc/source/filter/xml/xmldrani.cxx
index 37c4471..c622255 100644
--- a/sc/source/filter/xml/xmldrani.cxx
+++ b/sc/source/filter/xml/xmldrani.cxx
@@ -370,11 +370,11 @@ ScDBData* ScXMLDatabaseRangeContext::ConvertToDBData(const OUString& rName)
         ScSortDescriptor::FillSortParam(aParam, aSortSequence);
 
         SCCOLROW nStartPos = aParam.bByRow ? maRange.aStart.Col() : maRange.aStart.Row();
-        for (size_t i = 0; i < MAXSORT; ++i)
+        for (size_t i = 0; i < aParam.GetSortKeyCount(); ++i)
         {
-            if (!aParam.bDoSort[i])
+            if (!aParam.maKeyState[i].bDoSort)
                 break;
-            aParam.nField[i] += nStartPos;
+            aParam.maKeyState[i].nField += nStartPos;
         }
 
         pData->SetSortParam(aParam);
diff --git a/sc/source/ui/dbgui/tpsort.cxx b/sc/source/ui/dbgui/tpsort.cxx
index f2cc430..4d6832a 100644
--- a/sc/source/ui/dbgui/tpsort.cxx
+++ b/sc/source/ui/dbgui/tpsort.cxx
@@ -114,7 +114,10 @@ ScTabPageSortFields::ScTabPageSortFields( Window*           pParent,
         rSortData       ( ((const ScSortItem&)
                            rArgSet.Get( nWhichSort )).
                                 GetSortData() ),
+        newSortData     ( rSortData ),
         nFieldCount     ( 0 ),
+        nSortKeyCount   ( DEFSORT ),
+        nCurrentOffset  ( 0 ),
         bHasHeader      ( false ),
         bSortByRows     ( false )
 {
@@ -128,7 +131,6 @@ ScTabPageSortFields::ScTabPageSortFields( Window*           pParent,
 ScTabPageSortFields::~ScTabPageSortFields()
 {
 }
-
 // -----------------------------------------------------------------------
 
 void ScTabPageSortFields::Init()
@@ -140,7 +142,19 @@ void ScTabPageSortFields::Init()
 
     OSL_ENSURE( pViewData, "ViewData not found!" );
 
-    nFieldArr[0] = 0;
+    // Create local copy of ScParam
+    newSortData = rSortData;
+
+    if (pDlg)
+    {
+        const SfxItemSet* pExample = pDlg->GetExampleSet();
+        const SfxPoolItem* pItem;
+        if ( pExample && pExample->GetItemState( nWhichSort, sal_True, &pItem ) == SFX_ITEM_SET )
+            newSortData = ((const ScSortItem*)pItem)->GetSortData();
+    }
+
+    // Connect handlers and widgets
+    nFieldArr.push_back( 0 );
     nFirstCol = 0;
     nFirstRow = 0;
 
@@ -151,18 +165,10 @@ void ScTabPageSortFields::Init()
     aLbSort2.Clear();
     aLbSort3.Clear();
 
-    aSortLbArr[0]       = &aLbSort1;
-    aSortLbArr[1]       = &aLbSort2;
-    aSortLbArr[2]       = &aLbSort3;
-    aDirBtnArr[0][0]    = &aBtnUp1;
-    aDirBtnArr[0][1]    = &aBtnDown1;
-    aDirBtnArr[1][0]    = &aBtnUp2;
-    aDirBtnArr[1][1]    = &aBtnDown2;
-    aDirBtnArr[2][0]    = &aBtnUp3;
-    aDirBtnArr[2][1]    = &aBtnDown3;
-    aFlArr[0]           = &aFlSort1;
-    aFlArr[1]           = &aFlSort2;
-    aFlArr[2]           = &aFlSort3;
+    aLbSortArr = { &aLbSort1,  &aLbSort2,  &aLbSort3 };
+    aBtnUp     = { &aBtnUp1,   &aBtnUp2,   &aBtnUp3 };
+    aBtnDown   = { &aBtnDown1, &aBtnDown2, &aBtnDown3 };
+    aFlArr     = { &aFlSort1,  &aFlSort2,  &aFlSort3 };
 }
 
 // -----------------------------------------------------------------------
@@ -177,61 +183,63 @@ SfxTabPage* ScTabPageSortFields::Create( Window*    pParent,
 
 void ScTabPageSortFields::Reset( const SfxItemSet& /* rArgSet */ )
 {
-    bSortByRows = rSortData.bByRow;
-    bHasHeader  = rSortData.bHasHeader;
+    bSortByRows = newSortData.bByRow;
+    bHasHeader  = newSortData.bHasHeader;
 
     if ( aLbSort1.GetEntryCount() == 0 )
-        FillFieldLists();
+        FillFieldLists(0);
 
     // ListBox selection:
-
-    if ( rSortData.bDoSort[0] )
+    if ( newSortData.maKeyState[0].bDoSort )
     {
-        for ( sal_uInt16 i=0; i<3; i++ )
+        for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
         {
-            if ( rSortData.bDoSort[i] )
+            if ( newSortData.maKeyState[i].bDoSort )
             {
-                aSortLbArr[i]->SelectEntryPos(
-                     GetFieldSelPos( rSortData.nField[i] ) );
+                aLbSortArr[i]->SelectEntryPos( GetFieldSelPos(
+                                    newSortData.maKeyState[i].nField ) );
 
-                (rSortData.bAscending[i])
-                    ? aDirBtnArr[i][0]->Check()     // Up
-                    : aDirBtnArr[i][1]->Check();    // Down
+                (newSortData.maKeyState[i].bAscending)
+                    ? aBtnUp[i]->Check()
+                    : aBtnDown[i]->Check();
             }
             else
             {
-                aSortLbArr[i]->SelectEntryPos( 0 ); // Select none
-                aDirBtnArr[i][0]->Check();          // Up
+                aLbSortArr[i]->SelectEntryPos( 0 ); // Select none
+                aBtnUp[i]->Check();
             }
         }
 
-        EnableField( 1 );
-        EnableField( 2 );
-        EnableField( 3 );
-        if ( aLbSort1.GetSelectEntryPos() == 0 )
-            DisableField( 2 );
-        if ( aLbSort2.GetSelectEntryPos() == 0 )
-            DisableField( 3 );
+        // Enable or disable field depending on preceding Listbox selection
+        EnableField( 0 );
+        for ( sal_uInt16 i=1; i<nSortKeyCount; i++ )
+            if ( aLbSortArr[i - 1] -> GetSelectEntryPos() == 0 )
+                DisableField( i );
+            else
+                EnableField( i );
     }
     else
     {
         SCCOL  nCol = pViewData->GetCurX();
 
-        if( nCol < rSortData.nCol1 )
-            nCol = rSortData.nCol1;
-        else if( nCol > rSortData.nCol2 )
-            nCol = rSortData.nCol2;
-
-        sal_uInt16  nSort1Pos = nCol - rSortData.nCol1+1;
-        aLbSort1.SelectEntryPos( nSort1Pos );
-        aLbSort2.SelectEntryPos( 0 );
-        aLbSort3.SelectEntryPos( 0 );
-        aBtnUp1.Check();
-        aBtnUp2.Check();
-        aBtnUp3.Check();
+        if( nCol < newSortData.nCol1 )
+            nCol = newSortData.nCol1;
+        else if( nCol > newSortData.nCol2 )
+            nCol = newSortData.nCol2;
+
+        sal_uInt16  nSort1Pos = nCol - newSortData.nCol1+1;
+
+        aLbSortArr[0] -> SelectEntryPos( nSort1Pos );
+        for ( sal_uInt16 i=1; i<nSortKeyCount; i++ )
+            aLbSortArr[i] -> SelectEntryPos( 0 );
+
+        for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
+            aBtnUp[i] -> Check();
+
+        EnableField ( 0 );
         EnableField ( 1 );
-        EnableField ( 2 );
-        DisableField( 3 );
+        for ( sal_uInt16 i=2; i<nSortKeyCount; i++ )
+            DisableField( i );
     }
 
     if ( pDlg )
@@ -245,65 +253,48 @@ void ScTabPageSortFields::Reset( const SfxItemSet& /* rArgSet */ )
 
 sal_Bool ScTabPageSortFields::FillItemSet( SfxItemSet& rArgSet )
 {
-    ScSortParam theSortData = rSortData;
-    if (pDlg)
-    {
-        const SfxItemSet* pExample = pDlg->GetExampleSet();
-        const SfxPoolItem* pItem;
-        if ( pExample && pExample->GetItemState( nWhichSort, sal_True, &pItem ) == SFX_ITEM_SET )
-            theSortData = ((const ScSortItem*)pItem)->GetSortData();
-    }
-
-    sal_uInt16  nSort1Pos = aLbSort1.GetSelectEntryPos();
-    sal_uInt16  nSort2Pos = aLbSort2.GetSelectEntryPos();
-    sal_uInt16  nSort3Pos = aLbSort3.GetSelectEntryPos();
+    std::vector<sal_uInt16>  nSortPos;
 
-    OSL_ENSURE(    (nSort1Pos <= SC_MAXFIELDS)
-                && (nSort2Pos <= SC_MAXFIELDS)
-                && (nSort3Pos <= SC_MAXFIELDS),
-                "Array range error!" );
+    for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
+    {
+        nSortPos.push_back( aLbSortArr[i] -> GetSelectEntryPos() );
 
-    if ( nSort1Pos == LISTBOX_ENTRY_NOTFOUND ) nSort1Pos = 0;
-    if ( nSort2Pos == LISTBOX_ENTRY_NOTFOUND ) nSort2Pos = 0;
-    if ( nSort3Pos == LISTBOX_ENTRY_NOTFOUND ) nSort3Pos = 0;
+        if ( nSortPos[i] == LISTBOX_ENTRY_NOTFOUND ) nSortPos[i] = 0;
+    }
 
-    if ( nSort1Pos > 0 )
+    if ( nSortPos[0] > 0 )
     {
-        theSortData.bDoSort[0] = (nSort1Pos > 0);
-        theSortData.bDoSort[1] = (nSort2Pos > 0);
-        theSortData.bDoSort[2] = (nSort3Pos > 0);
+        for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
+            newSortData.maKeyState[i].bDoSort = (nSortPos[i] > 0);
 
         // If the "OK" was selected on the Options page while the sort
         // direction was changed, then the first field (i.e. nFieldArr[0])
         // of the respective direction is chosen as the sorting criterion:
         if ( bSortByRows != pDlg->GetByRows() )
         {
-            theSortData.nField[0] =
-            theSortData.nField[1] =
-            theSortData.nField[2] = ( bSortByRows ?
-                    static_cast<SCCOLROW>(nFirstRow) :
-                    static_cast<SCCOLROW>(nFirstCol) );
+            for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
+                newSortData.maKeyState[i].nField = ( bSortByRows ?
+                                                     static_cast<SCCOLROW>(nFirstRow) :
+                                                     static_cast<SCCOLROW>(nFirstCol) );
         }
         else
-        {
-            theSortData.nField[0] = nFieldArr[nSort1Pos];
-            theSortData.nField[1] = nFieldArr[nSort2Pos];
-            theSortData.nField[2] = nFieldArr[nSort3Pos];
-        }
+       {
+           for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
+               newSortData.maKeyState[i].nField = nFieldArr[nSortPos[i]];
+       }
+
+        for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
+            newSortData.maKeyState[i].bAscending = aBtnUp[i] -> IsChecked();
 
-        theSortData.bAscending[0] = aBtnUp1.IsChecked();
-        theSortData.bAscending[1] = aBtnUp2.IsChecked();
-        theSortData.bAscending[2] = aBtnUp3.IsChecked();
         // bHasHeader is in ScTabPageSortOptions::FillItemSet, where it belongs
     }
     else
     {
-        theSortData.bDoSort[0] =
-        theSortData.bDoSort[1] =
-        theSortData.bDoSort[2] = false;
+        for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
+            newSortData.maKeyState[i].bDoSort = false;
     }
 
-    rArgSet.Put( ScSortItem( SCITEM_SORTDATA, NULL, &theSortData ) );
+    rArgSet.Put( ScSortItem( SCITEM_SORTDATA, NULL, &newSortData ) );
 
     return sal_True;
 }
@@ -315,19 +306,19 @@ void ScTabPageSortFields::ActivatePage()
 {
     if ( pDlg )
     {
-        if (   bHasHeader  != pDlg->GetHeaders()
-            || bSortByRows != pDlg->GetByRows()   )
+        if ( bHasHeader  != pDlg->GetHeaders()
+             || bSortByRows != pDlg->GetByRows() )
         {
-            sal_uInt16  nCurSel1 = aLbSort1.GetSelectEntryPos();
-            sal_uInt16  nCurSel2 = aLbSort2.GetSelectEntryPos();
-            sal_uInt16  nCurSel3 = aLbSort3.GetSelectEntryPos();
+            std::vector<sal_uInt16> nCurSel;
+            for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
+                nCurSel.push_back( aLbSortArr[i] -> GetSelectEntryPos() );
 
             bHasHeader  = pDlg->GetHeaders();
             bSortByRows = pDlg->GetByRows();
-            FillFieldLists();
-            aLbSort1.SelectEntryPos( nCurSel1 );
-            aLbSort2.SelectEntryPos( nCurSel2 );
-            aLbSort3.SelectEntryPos( nCurSel3 );
+            FillFieldLists(0);
+
+            for ( sal_uInt16 i=0; i<nSortKeyCount; i++ )
+                aLbSortArr[i] -> SelectEntryPos( nCurSel[i] );
         }
     }
 }
@@ -355,14 +346,12 @@ int ScTabPageSortFields::DeactivatePage( SfxItemSet* pSetP )
 
 void ScTabPageSortFields::DisableField( sal_uInt16 nField )
 {
-    nField--;
-
-    if ( nField<=2 )
+    if ( nField<nSortKeyCount )
     {
-        aSortLbArr[nField]   ->Disable();
-        aDirBtnArr[nField][0]->Disable();
-        aDirBtnArr[nField][1]->Disable();
-        aFlArr[nField]       ->Disable();
+        aLbSortArr[nField]   -> Disable();
+        aBtnUp[nField]       -> Disable();
+        aBtnDown[nField]     -> Disable();
+        aFlArr[nField]       -> Disable();
     }
 }
 
@@ -370,20 +359,18 @@ void ScTabPageSortFields::DisableField( sal_uInt16 nField )
 
 void ScTabPageSortFields::EnableField( sal_uInt16 nField )
 {
-    nField--;
-
-    if ( nField<=2 )
+    if ( nField<nSortKeyCount )
     {
-        aSortLbArr[nField]   ->Enable();
-        aDirBtnArr[nField][0]->Enable();
-        aDirBtnArr[nField][1]->Enable();
-        aFlArr[nField]       ->Enable();
+        aLbSortArr[nField]   -> Enable();
+        aBtnUp[nField]       -> Enable();
+        aBtnDown[nField]     -> Enable();
+        aFlArr[nField]       -> Enable();
     }
 }
 
 // -----------------------------------------------------------------------
 
-void ScTabPageSortFields::FillFieldLists()
+void ScTabPageSortFields::FillFieldLists( sal_uInt16 nStartField )
 {
     if ( pViewData )
     {
@@ -391,12 +378,11 @@ void ScTabPageSortFields::FillFieldLists()
 
         if ( pDoc )
         {
-            aLbSort1.Clear();
-            aLbSort2.Clear();
-            aLbSort3.Clear();
-            aLbSort1.InsertEntry( aStrUndefined, 0 );
-            aLbSort2.InsertEntry( aStrUndefined, 0 );
-            aLbSort3.InsertEntry( aStrUndefined, 0 );
+            for ( sal_uInt16 i=nStartField; i<nSortKeyCount; i++ )
+            {
+                aLbSortArr[i] -> Clear();
+                aLbSortArr[i] -> InsertEntry( aStrUndefined, 0 );
+            }
 
             SCCOL   nFirstSortCol   = rSortData.nCol1;
             SCROW   nFirstSortRow   = rSortData.nRow1;
@@ -418,10 +404,11 @@ void ScTabPageSortFields::FillFieldLists()
                         aFieldName += ' ';
                         aFieldName += ScColToAlpha( col );
                     }
-                    nFieldArr[i] = col;
-                    aLbSort1.InsertEntry( aFieldName, i );
-                    aLbSort2.InsertEntry( aFieldName, i );
-                    aLbSort3.InsertEntry( aFieldName, i );
+                    nFieldArr.push_back( col );
+
+                    for ( sal_uInt16 j=nStartField; j<nSortKeyCount; j++ )
+                        aLbSortArr[j] -> InsertEntry( aFieldName, i );
+
                     i++;
                 }
             }
@@ -440,10 +427,11 @@ void ScTabPageSortFields::FillFieldLists()
                         aFieldName += ' ';
                         aFieldName += String::CreateFromInt32( row+1 );
                     }
-                    nFieldArr[i] = row;
-                    aLbSort1.InsertEntry( aFieldName, i );
-                    aLbSort2.InsertEntry( aFieldName, i );
-                    aLbSort3.InsertEntry( aFieldName, i );
+                    nFieldArr.push_back( row );
+
+                    for ( sal_uInt16 j=nStartField; j<nSortKeyCount; j++ )
+                        aLbSortArr[j] -> InsertEntry( aFieldName, i );
+
                     i++;
                 }
             }
@@ -478,38 +466,30 @@ sal_uInt16 ScTabPageSortFields::GetFieldSelPos( SCCOLROW nField )
 IMPL_LINK( ScTabPageSortFields, SelectHdl, ListBox *, pLb )
 {
     String aSelEntry = pLb->GetSelectEntry();
+    sal_uInt16  nPos   = 0;
 
-    if ( pLb == &aLbSort1 )
-    {
-        if ( aSelEntry == aStrUndefined )
-        {
-            aLbSort2.SelectEntryPos( 0 );
-            aLbSort3.SelectEntryPos( 0 );
-
-            if ( aFlSort2.IsEnabled() )
-                DisableField( 2 );
+    // Find selected listbox
+    while ( pLb != aLbSortArr[nPos] )
+        ++nPos;
 
-            if ( aFlSort3.IsEnabled() )
-                DisableField( 3 );
-        }
-        else
-        {
-            if ( !aFlSort2.IsEnabled() )
-                EnableField( 2 );
-        }
-    }
-    else if ( pLb == &aLbSort2 )
+    // If not selecting the last Listbox modify the succeeding ones
+    ++nPos;
+    if ( nPos < nSortKeyCount )
     {
         if ( aSelEntry == aStrUndefined )
         {
-            aLbSort3.SelectEntryPos( 0 );
-            if ( aFlSort3.IsEnabled() )
-                DisableField( 3 );
+            for ( sal_uInt16 i=nPos; i<nSortKeyCount; i++ )
+            {
+                aLbSortArr[i] -> SelectEntryPos( 0 );
+
+                if ( aFlArr[i] -> IsEnabled() )
+                    DisableField( i );
+            }
         }
         else
         {
-            if ( !aFlSort3.IsEnabled() )
-                EnableField( 3 );
+            if ( !aFlArr[nPos] -> IsEnabled() )
+                EnableField( nPos );
         }
     }
     return 0;
@@ -550,6 +530,7 @@ ScTabPageSortOptions::ScTabPageSortOptions( Window*             pParent,
         nWhichSort      ( rArgSet.GetPool()->GetWhich( SID_SORT ) ),
         rSortData       ( ((const ScSortItem&)
                           rArgSet.Get( nWhichSort )).GetSortData() ),
+        newSortData     ( rSortData ),
         pViewData       ( NULL ),
         pDoc            ( NULL ),
         pDlg            ( (ScSortDlg*)(GetParent() ? GetParent()->GetParent() : 0 ) ),
@@ -606,12 +587,23 @@ void ScTabPageSortOptions::Init()
 
     OSL_ENSURE( pViewData, "ViewData not found! :-/" );
 
+    // Create local copy of ScParam
+    newSortData = rSortData;
+
+    if (pDlg)
+    {
+        const SfxItemSet* pExample = pDlg->GetExampleSet();
+        const SfxPoolItem* pItem;
+        if ( pExample && pExample->GetItemState( nWhichSort, sal_True, &pItem ) == SFX_ITEM_SET )
+            newSortData = ((const ScSortItem*)pItem)->GetSortData();
+    }
+
     if ( pViewData && pDoc )
     {
         String          theArea;
         ScDBCollection* pDBColl     = pDoc->GetDBCollection();
         String          theDbArea;
-        const SCTAB nCurTab     = pViewData->GetTabNo();
+        const SCTAB     nCurTab     = pViewData->GetTabNo();
         String          theDbName   = 
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(STR_DB_LOCAL_NONAME));
         const formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention();
 
@@ -636,17 +628,17 @@ void ScTabPageSortOptions::Init()
 
         // Check whether the field that is passed on is a database field:
 
-        ScAddress aScAddress( rSortData.nCol1, rSortData.nRow1, nCurTab );
+        ScAddress aScAddress( newSortData.nCol1, newSortData.nRow1, nCurTab );
         ScRange( aScAddress,
-                 ScAddress( rSortData.nCol2, rSortData.nRow2, nCurTab )
+                 ScAddress( newSortData.nCol2, newSortData.nRow2, nCurTab )
                ).Format( theArea, SCR_ABS, pDoc, eConv );
 
         if ( pDBColl )
         {
             ScDBData* pDBData
                     = pDBColl->GetDBAtArea( nCurTab,
-                                            rSortData.nCol1, rSortData.nRow1,
-                                            rSortData.nCol2, rSortData.nRow2 );
+                                            newSortData.nCol1, newSortData.nRow1,
+                                            newSortData.nCol2, newSortData.nRow2 );
             if ( pDBData )
             {
                 theDbName = pDBData->GetName();
@@ -752,46 +744,37 @@ void ScTabPageSortOptions::Reset( const SfxItemSet& /* rArgSet */ )
 
 sal_Bool ScTabPageSortOptions::FillItemSet( SfxItemSet& rArgSet )
 {
-    ScSortParam theSortData = rSortData;
-    if (pDlg)
-    {
-        const SfxItemSet* pExample = pDlg->GetExampleSet();
-        const SfxPoolItem* pItem;
-        if ( pExample && pExample->GetItemState( nWhichSort, sal_True, &pItem ) == SFX_ITEM_SET )
-            theSortData = ((const ScSortItem*)pItem)->GetSortData();
-    }
-
-    theSortData.bByRow          = aBtnTopDown.IsChecked();
-    theSortData.bHasHeader      = aBtnHeader.IsChecked();
-    theSortData.bCaseSens       = aBtnCase.IsChecked();
-    theSortData.bNaturalSort    = aBtnNaturalSort.IsChecked();
-    theSortData.bIncludePattern = aBtnFormats.IsChecked();
-    theSortData.bInplace        = !aBtnCopyResult.IsChecked();
-    theSortData.nDestCol        = theOutPos.Col();
-    theSortData.nDestRow        = theOutPos.Row();
-    theSortData.nDestTab        = theOutPos.Tab();
-    theSortData.bUserDef        = aBtnSortUser.IsChecked();
-    theSortData.nUserIndex      = (aBtnSortUser.IsChecked())
-                                    ? aLbSortUser.GetSelectEntryPos()
-                                    : 0;
+    newSortData.bByRow          = aBtnTopDown.IsChecked();
+    newSortData.bHasHeader      = aBtnHeader.IsChecked();
+    newSortData.bCaseSens       = aBtnCase.IsChecked();
+    newSortData.bNaturalSort    = aBtnNaturalSort.IsChecked();
+    newSortData.bIncludePattern = aBtnFormats.IsChecked();
+    newSortData.bInplace        = !aBtnCopyResult.IsChecked();
+    newSortData.nDestCol        = theOutPos.Col();
+    newSortData.nDestRow        = theOutPos.Row();
+    newSortData.nDestTab        = theOutPos.Tab();
+    newSortData.bUserDef        = aBtnSortUser.IsChecked();
+    newSortData.nUserIndex      = (aBtnSortUser.IsChecked())
+                                   ? aLbSortUser.GetSelectEntryPos()
+                                   : 0;
 
     // get locale
     LanguageType eLang = aLbLanguage.GetSelectLanguage();
-    theSortData.aCollatorLocale = MsLangId::convertLanguageToLocale( eLang, false );
+    newSortData.aCollatorLocale = MsLangId::convertLanguageToLocale( eLang, false );
 
     // get algorithm
     String sAlg;
     if ( eLang != LANGUAGE_SYSTEM )
     {
         uno::Sequence<rtl::OUString> aAlgos = pColWrap->listCollatorAlgorithms(
-                theSortData.aCollatorLocale );
+                newSortData.aCollatorLocale );
         sal_uInt16 nSel = aLbAlgorithm.GetSelectEntryPos();
         if ( nSel < aAlgos.getLength() )
             sAlg = aAlgos[nSel];
     }
-    theSortData.aCollatorAlgorithm = sAlg;
+    newSortData.aCollatorAlgorithm = sAlg;
 
-    rArgSet.Put( ScSortItem( SCITEM_SORTDATA, &theSortData ) );
+    rArgSet.Put( ScSortItem( SCITEM_SORTDATA, &newSortData ) );
 
     return sal_True;
 }
diff --git a/sc/source/ui/docshell/dbdocfun.cxx b/sc/source/ui/docshell/dbdocfun.cxx
index c1464b1..7f43ba7 100644
--- a/sc/source/ui/docshell/dbdocfun.cxx
+++ b/sc/source/ui/docshell/dbdocfun.cxx
@@ -282,7 +282,7 @@ bool ScDBDocFunc::RepeatDB( const ::rtl::OUString& rDBName, bool bRecord, bool b
 
         ScSortParam aSortParam;
         pDBData->GetSortParam( aSortParam );
-        sal_Bool bSort = aSortParam.bDoSort[0];
+        sal_Bool bSort = aSortParam.maKeyState[0].bDoSort;
 
         ScSubTotalParam aSubTotalParam;
         pDBData->GetSubTotalParam( aSubTotalParam );
@@ -585,7 +585,7 @@ sal_Bool ScDBDocFunc::Sort( SCTAB nTab, const ScSortParam& rSortParam,
     }
 
     // don't call ScDocument::Sort with an empty SortParam (may be empty here if bCopy is set)
-    if ( aLocalParam.bDoSort[0] )
+    if ( aLocalParam.maKeyState[0].bDoSort )
         pDoc->Sort( nTab, aLocalParam, bRepeatQuery );
 
     sal_Bool bSave = sal_True;
@@ -593,7 +593,7 @@ sal_Bool ScDBDocFunc::Sort( SCTAB nTab, const ScSortParam& rSortParam,
     {
         ScSortParam aOldSortParam;
         pDBData->GetSortParam( aOldSortParam );
-        if ( aOldSortParam.bDoSort[0] && aOldSortParam.bInplace )   // Inplace-Sortierung gemerkt?
+        if ( aOldSortParam.maKeyState[0].bDoSort && aOldSortParam.bInplace )   // 
Inplace-Sortierung gemerkt?
         {
             bSave = false;
             aOldSortParam.nDestCol = rSortParam.nDestCol;
diff --git a/sc/source/ui/inc/tpsort.hxx b/sc/source/ui/inc/tpsort.hxx
index 8b87726..684fe3e 100644
--- a/sc/source/ui/inc/tpsort.hxx
+++ b/sc/source/ui/inc/tpsort.hxx
@@ -29,6 +29,7 @@
 #ifndef SC_TPSORT_HXX
 #define SC_TPSORT_HXX
 
+#include <vector>
 
 #include <sfx2/tabdlg.hxx>
 #include <vcl/edit.hxx>
@@ -40,6 +41,7 @@
 
 #include "global.hxx"
 #include "address.hxx"
+#include "sortparam.hxx"
 
 //------------------------------------------------------------------------
 
@@ -97,23 +99,28 @@ private:
     ScSortDlg*          pDlg;
     ScViewData*         pViewData;
     const ScSortParam&  rSortData;
-    SCCOLROW            nFieldArr[SC_MAXFIELDS];
+    ScSortParam         newSortData;
+    std::vector<SCCOLROW>  nFieldArr;
     sal_uInt16          nFieldCount;
+    sal_uInt16          nSortKeyCount;
+    sal_uInt16          nCurrentOffset;
+
     SCCOL               nFirstCol;
     SCROW               nFirstRow;
     sal_Bool            bHasHeader;
     sal_Bool            bSortByRows;
 
-    ListBox*            aSortLbArr[3];
-    RadioButton*        aDirBtnArr[3][2];
-    FixedLine*          aFlArr[3];
+    std::vector<ListBox*>      aLbSortArr;
+    std::vector<RadioButton*>  aBtnUp;
+    std::vector<RadioButton*>  aBtnDown;
+    std::vector<FixedLine*>    aFlArr;
 
 #ifdef _TPSORT_CXX
 private:
     void    Init            ();
     void    DisableField    ( sal_uInt16 nField );
     void    EnableField     ( sal_uInt16 nField );
-    void    FillFieldLists  ();
+    void    FillFieldLists  ( sal_uInt16 nStartField );
     sal_uInt16  GetFieldSelPos  ( SCCOLROW nField );
 
     // Handler ------------------------
@@ -181,6 +188,7 @@ private:
 
     const sal_uInt16    nWhichSort;
     const ScSortParam&  rSortData;
+    ScSortParam         newSortData;
     ScViewData*         pViewData;
     ScDocument*         pDoc;
     ScSortDlg*          pDlg;
diff --git a/sc/source/ui/src/sortdlg.src b/sc/source/ui/src/sortdlg.src
index a4296f4..466ab7a 100644
--- a/sc/source/ui/src/sortdlg.src
+++ b/sc/source/ui/src/sortdlg.src
@@ -61,7 +61,7 @@ TabPage RID_SCPAGE_SORT_FIELDS
     {
         Pos = MAP_APPFONT ( 6 , 3 ) ;
         Size = MAP_APPFONT ( 248 , 8 ) ;
-        Text [ en-US ] = "Sort ~by" ;
+        Text [ en-US ] = "Sort ~key 1" ;
     };
     ListBox LB_SORT2
     {
@@ -92,7 +92,7 @@ TabPage RID_SCPAGE_SORT_FIELDS
     {
         Pos = MAP_APPFONT ( 6 , 44 ) ;
         Size = MAP_APPFONT ( 248 , 8 ) ;
-        Text [ en-US ] = "Then b~y" ;
+        Text [ en-US ] = "Sort ~key 2" ;
     };
     ListBox LB_SORT3
     {
@@ -123,7 +123,7 @@ TabPage RID_SCPAGE_SORT_FIELDS
     {
         Pos = MAP_APPFONT ( 6 , 85 ) ;
         Size = MAP_APPFONT ( 248 , 8 ) ;
-        Text [ en-US ] = "T~hen by" ;
+        Text [ en-US ] = "Sort ~key 3" ;
     };
 };
 
diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx
index c82e56a..750822c 100644
--- a/sc/source/ui/unoobj/cellsuno.cxx
+++ b/sc/source/ui/unoobj/cellsuno.cxx
@@ -5625,9 +5625,9 @@ uno::Sequence<beans::PropertyValue> SAL_CALL 
ScCellRangeObj::createSortDescripto
             SCCOLROW nFieldStart = aParam.bByRow ?
                 static_cast<SCCOLROW>(aDBRange.aStart.Col()) :
                 static_cast<SCCOLROW>(aDBRange.aStart.Row());
-            for (sal_uInt16 i=0; i<MAXSORT; i++)
-                if ( aParam.bDoSort[i] && aParam.nField[i] >= nFieldStart )
-                    aParam.nField[i] -= nFieldStart;
+            for (sal_uInt16 i=0; i<aParam.GetSortKeyCount(); i++)
+                if ( aParam.maKeyState[i].bDoSort && aParam.maKeyState[i].nField >= nFieldStart )
+                    aParam.maKeyState[i].nField -= nFieldStart;
         }
     }
 
@@ -5653,9 +5653,9 @@ void SAL_CALL ScCellRangeObj::sort( const 
uno::Sequence<beans::PropertyValue>& a
             SCCOLROW nOldStart = aParam.bByRow ?
                 static_cast<SCCOLROW>(aRange.aStart.Col()) :
                 static_cast<SCCOLROW>(aRange.aStart.Row());
-            for (i=0; i<MAXSORT; i++)
-                if ( aParam.bDoSort[i] && aParam.nField[i] >= nOldStart )
-                    aParam.nField[i] -= nOldStart;
+            for (i=0; i<aParam.GetSortKeyCount(); i++)
+                if ( aParam.maKeyState[i].bDoSort && aParam.maKeyState[i].nField >= nOldStart )
+                    aParam.maKeyState[i].nField -= nOldStart;
         }
 
         ScSortDescriptor::FillSortParam( aParam, aDescriptor );
@@ -5665,8 +5665,8 @@ void SAL_CALL ScCellRangeObj::sort( const 
uno::Sequence<beans::PropertyValue>& a
         SCCOLROW nFieldStart = aParam.bByRow ?
             static_cast<SCCOLROW>(aRange.aStart.Col()) :
             static_cast<SCCOLROW>(aRange.aStart.Row());
-        for (i=0; i<MAXSORT; i++)
-            aParam.nField[i] += nFieldStart;
+        for (i=0; i<aParam.GetSortKeyCount(); i++)
+            aParam.maKeyState[i].nField += nFieldStart;
 
         SCTAB nTab = aRange.aStart.Tab();
         aParam.nCol1 = aRange.aStart.Col();
diff --git a/sc/source/ui/unoobj/datauno.cxx b/sc/source/ui/unoobj/datauno.cxx
index 125ac54..b5c5285 100644
--- a/sc/source/ui/unoobj/datauno.cxx
+++ b/sc/source/ui/unoobj/datauno.cxx
@@ -334,7 +334,7 @@ void ScSortDescriptor::FillProperties( uno::Sequence<beans::PropertyValue>& rSeq
     aOutPos.Row    = rParam.nDestRow;
 
     sal_uInt16 nSortCount = 0;
-    while ( nSortCount < MAXSORT && rParam.bDoSort[nSortCount] )
+    while ( nSortCount < rParam.GetSortKeyCount() && rParam.maKeyState[nSortCount].bDoSort )
         ++nSortCount;
 
     uno::Sequence<table::TableSortField> aFields(nSortCount);
@@ -343,8 +343,8 @@ void ScSortDescriptor::FillProperties( uno::Sequence<beans::PropertyValue>& rSeq
         table::TableSortField* pFieldArray = aFields.getArray();
         for (sal_uInt16 i=0; i<nSortCount; i++)
         {
-            pFieldArray[i].Field         = rParam.nField[i];
-            pFieldArray[i].IsAscending   = rParam.bAscending[i];
+            pFieldArray[i].Field         = rParam.maKeyState[i].nField;
+            pFieldArray[i].IsAscending   = rParam.maKeyState[i].bAscending;
             pFieldArray[i].FieldType     = table::TableSortFieldType_AUTOMATIC;     // immer 
Automatic
             pFieldArray[i].IsCaseSensitive = rParam.bCaseSens;
             pFieldArray[i].CollatorLocale = rParam.aCollatorLocale;
@@ -361,7 +361,7 @@ void ScSortDescriptor::FillProperties( uno::Sequence<beans::PropertyValue>& rSeq
     ScUnoHelpFunctions::SetBoolInAny( pArray[1].Value, rParam.bHasHeader );
 
     pArray[2].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_MAXFLD ));
-    pArray[2].Value <<= (sal_Int32) MAXSORT;
+    pArray[2].Value <<= (sal_Int32) rParam.GetSortKeyCount();
 
     pArray[3].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_SORTFLD ));
     pArray[3].Value <<= aFields;
@@ -386,6 +386,8 @@ void ScSortDescriptor::FillSortParam( ScSortParam& rParam, const uno::Sequence<b
 {
     const beans::PropertyValue* pPropArray = rSeq.getConstArray();
     long nPropCount = rSeq.getLength();
+    sal_Int16 nSortSize = rParam.GetSortKeyCount();
+
     for (long nProp = 0; nProp < nPropCount; nProp++)
     {
         const beans::PropertyValue& rProp = pPropArray[nProp];
@@ -407,7 +409,7 @@ void ScSortDescriptor::FillSortParam( ScSortParam& rParam, const uno::Sequence<b
         else if (aPropName.EqualsAscii( SC_UNONAME_MAXFLD ))
         {
             sal_Int32 nVal;
-            if ( (rProp.Value >>= nVal) && nVal > MAXSORT )
+            if ( (rProp.Value >>= nVal) && nVal > nSortSize )
             {
                 //! specify exceptions
                 //! throw lang::IllegalArgumentException();
@@ -421,37 +423,37 @@ void ScSortDescriptor::FillSortParam( ScSortParam& rParam, const 
uno::Sequence<b
             {
                 sal_Int32 nCount = aSeq.getLength();
                 sal_Int32 i;
-                if ( nCount > MAXSORT )
+                if ( nCount > (sal_Int32) rParam.GetSortKeyCount() )
                 {
                     OSL_FAIL("Zu viele Sortierfelder");
-                    nCount = MAXSORT;
+                    nCount = nSortSize;
                 }
                 const util::SortField* pFieldArray = aSeq.getConstArray();
                 for (i=0; i<nCount; i++)
                 {
-                    rParam.nField[i]     = (SCCOLROW)pFieldArray[i].Field;
-                    rParam.bAscending[i] = pFieldArray[i].SortAscending;
+                    rParam.maKeyState[i].nField     = (SCCOLROW)pFieldArray[i].Field;
+                    rParam.maKeyState[i].bAscending = pFieldArray[i].SortAscending;
 
                     // FieldType wird ignoriert
-                    rParam.bDoSort[i] = sal_True;
+                    rParam.maKeyState[i].bDoSort = sal_True;
                 }
-                for (i=nCount; i<MAXSORT; i++)
-                    rParam.bDoSort[i] = false;
+                for (i=nCount; i<nSortSize; i++)
+                    rParam.maKeyState[i].bDoSort = false;
             }
             else if ( rProp.Value >>= aNewSeq )
             {
                 sal_Int32 nCount = aNewSeq.getLength();
                 sal_Int32 i;
-                if ( nCount > MAXSORT )
+                if ( nCount > nSortSize )
                 {
                     OSL_FAIL("Zu viele Sortierfelder");
-                    nCount = MAXSORT;
+                    nCount = nSortSize;
                 }
                 const table::TableSortField* pFieldArray = aNewSeq.getConstArray();
                 for (i=0; i<nCount; i++)
                 {
-                    rParam.nField[i]     = (SCCOLROW)pFieldArray[i].Field;
-                    rParam.bAscending[i] = pFieldArray[i].IsAscending;
+                    rParam.maKeyState[i].nField     = (SCCOLROW)pFieldArray[i].Field;
+                    rParam.maKeyState[i].bAscending = pFieldArray[i].IsAscending;
 
                     // only one is possible, sometime we should make it possible to have different 
for every entry
                     rParam.bCaseSens = pFieldArray[i].IsCaseSensitive;
@@ -459,10 +461,10 @@ void ScSortDescriptor::FillSortParam( ScSortParam& rParam, const 
uno::Sequence<b
                     rParam.aCollatorAlgorithm = pFieldArray[i].CollatorAlgorithm;
 
                     // FieldType wird ignoriert
-                    rParam.bDoSort[i] = sal_True;
+                    rParam.maKeyState[i].bDoSort = sal_True;
                 }
-                for (i=nCount; i<MAXSORT; i++)
-                    rParam.bDoSort[i] = false;
+                for (i=nCount; i<nSortSize; i++)
+                    rParam.maKeyState[i].bDoSort = false;
             }
         }
         else if (aPropName.EqualsAscii( SC_UNONAME_ISCASE ))
@@ -1818,9 +1820,9 @@ uno::Sequence<beans::PropertyValue> SAL_CALL 
ScDatabaseRangeObj::getSortDescript
         ScRange aDBRange;
         pData->GetArea(aDBRange);
         SCCOLROW nFieldStart = aParam.bByRow ? static_cast<SCCOLROW>(aDBRange.aStart.Col()) : 
static_cast<SCCOLROW>(aDBRange.aStart.Row());
-        for (sal_uInt16 i=0; i<MAXSORT; i++)
-            if ( aParam.bDoSort[i] && aParam.nField[i] >= nFieldStart )
-                aParam.nField[i] -= nFieldStart;
+        for (sal_uInt16 i=0; i<aParam.GetSortKeyCount(); i++)
+            if ( aParam.maKeyState[i].bDoSort && aParam.maKeyState[i].nField >= nFieldStart )
+                aParam.maKeyState[i].nField -= nFieldStart;
     }
 
     uno::Sequence<beans::PropertyValue> aSeq( ScSortDescriptor::GetPropertyCount() );
diff --git a/sc/source/ui/vba/vbarange.cxx b/sc/source/ui/vba/vbarange.cxx
index 23a7492..0a9af87 100644
--- a/sc/source/ui/vba/vbarange.cxx
+++ b/sc/source/ui/vba/vbarange.cxx
@@ -3540,9 +3540,9 @@ ScVbaRange::Sort( const uno::Any& Key1, const uno::Any& Order1, const 
uno::Any&
 
     // set up defaults
 
-    sal_Int16 nOrder1 = aSortParam.bAscending[0] ? excel::XlSortOrder::xlAscending : 
excel::XlSortOrder::xlDescending;
-    sal_Int16 nOrder2 = aSortParam.bAscending[1] ? excel::XlSortOrder::xlAscending : 
excel::XlSortOrder::xlDescending;
-    sal_Int16 nOrder3 = aSortParam.bAscending[2] ? excel::XlSortOrder::xlAscending : 
excel::XlSortOrder::xlDescending;
+    sal_Int16 nOrder1 = aSortParam.maKeyState[1].bAscending ? excel::XlSortOrder::xlAscending : 
excel::XlSortOrder::xlDescending;
+    sal_Int16 nOrder2 = aSortParam.maKeyState[2].bAscending ? excel::XlSortOrder::xlAscending : 
excel::XlSortOrder::xlDescending;
+    sal_Int16 nOrder3 = aSortParam.maKeyState[3].bAscending ? excel::XlSortOrder::xlAscending : 
excel::XlSortOrder::xlDescending;
 
     sal_Int16 nCustom = aSortParam.nUserIndex;
     sal_Int16 nSortMethod = excel::XlSortMethod::xlPinYin;
@@ -3621,26 +3621,26 @@ ScVbaRange::Sort( const uno::Any& Key1, const uno::Any& Order1, const 
uno::Any&
     {
         nOrder1 = ::comphelper::getINT16(Order1);
         if (  nOrder1 == excel::XlSortOrder::xlAscending )
-            aSortParam.bAscending[0]  = true;
+            aSortParam.maKeyState[0].bAscending  = true;
         else
-            aSortParam.bAscending[0]  = false;
+            aSortParam.maKeyState[0].bAscending  = false;
 
     }
     if ( Order2.hasValue() )
     {
         nOrder2 = ::comphelper::getINT16(Order2);
         if ( nOrder2 == excel::XlSortOrder::xlAscending )
-            aSortParam.bAscending[1]  = true;
+            aSortParam.maKeyState[1].bAscending  = true;
         else
-            aSortParam.bAscending[1]  = false;
+            aSortParam.maKeyState[1].bAscending  = false;
     }
     if ( Order3.hasValue() )
     {
         nOrder3 = ::comphelper::getINT16(Order3);
         if ( nOrder3 == excel::XlSortOrder::xlAscending )
-            aSortParam.bAscending[2]  = true;
+            aSortParam.maKeyState[2].bAscending  = true;
         else
-            aSortParam.bAscending[2]  = false;
+            aSortParam.maKeyState[2].bAscending  = false;
     }
 
     uno::Reference< table::XCellRange > xKey1;
diff --git a/sc/source/ui/view/cellsh2.cxx b/sc/source/ui/view/cellsh2.cxx
index 77121b7..bf1b3db 100644
--- a/sc/source/ui/view/cellsh2.cxx
+++ b/sc/source/ui/view/cellsh2.cxx
@@ -376,12 +376,10 @@ void ScCellShell::ExecuteDB( SfxRequest& rReq )
                     aSortParam.bNaturalSort     = false;
                     aSortParam.bIncludePattern  = true;
                     aSortParam.bInplace         = true;
-                    aSortParam.bDoSort[0]       = true;
-                    aSortParam.nField[0]        = nCol;
-                    aSortParam.bAscending[0]    = (nSlotId == SID_SORT_ASCENDING);
+                    aSortParam.maKeyState[0]    = { true, nCol, nSlotId == SID_SORT_ASCENDING };
 
-                    for ( sal_uInt16 i=1; i<MAXSORT; i++ )
-                        aSortParam.bDoSort[i] = false;
+                    for ( sal_uInt16 i=1; i<aSortParam.GetSortKeyCount(); i++ )
+                        aSortParam.maKeyState[i].bDoSort = false;
 
                     aArgSet.Put( ScSortItem( SCITEM_SORTDATA, GetViewData(), &aSortParam ) );
 
@@ -440,24 +438,24 @@ void ScCellShell::ExecuteDB( SfxRequest& rReq )
                         SCCOLROW nField0 = 0;
                         if ( pArgs->GetItemState( FN_PARAM_1, sal_True, &pItem ) == SFX_ITEM_SET )
                             nField0 = ((const SfxInt32Item*)pItem)->GetValue();
-                        aSortParam.bDoSort[0] = ( nField0 != 0 );
-                        aSortParam.nField[0] = nField0 > 0 ? (nField0-1) : 0;
+                        aSortParam.maKeyState[0].bDoSort = ( nField0 != 0 );
+                        aSortParam.maKeyState[0].nField = nField0 > 0 ? (nField0-1) : 0;
                         if ( pArgs->GetItemState( FN_PARAM_2, sal_True, &pItem ) == SFX_ITEM_SET )
-                            aSortParam.bAscending[0] = ((const SfxBoolItem*)pItem)->GetValue();
+                            aSortParam.maKeyState[0].bAscending = ((const 
SfxBoolItem*)pItem)->GetValue();
                         SCCOLROW nField1 = 0;
                         if ( pArgs->GetItemState( FN_PARAM_3, sal_True, &pItem ) == SFX_ITEM_SET )
                             nField1 = ((const SfxInt32Item*)pItem)->GetValue();
-                        aSortParam.bDoSort[1] = ( nField1 != 0 );
-                        aSortParam.nField[1] = nField1 > 0 ? (nField1-1) : 0;
+                        aSortParam.maKeyState[1].bDoSort = ( nField1 != 0 );
+                        aSortParam.maKeyState[1].nField = nField1 > 0 ? (nField1-1) : 0;
                         if ( pArgs->GetItemState( FN_PARAM_4, sal_True, &pItem ) == SFX_ITEM_SET )
-                            aSortParam.bAscending[1] = ((const SfxBoolItem*)pItem)->GetValue();
+                            aSortParam.maKeyState[1].bAscending = ((const 
SfxBoolItem*)pItem)->GetValue();
                         SCCOLROW nField2 = 0;
                         if ( pArgs->GetItemState( FN_PARAM_5, sal_True, &pItem ) == SFX_ITEM_SET )
                             nField2 = ((const SfxInt32Item*)pItem)->GetValue();
-                        aSortParam.bDoSort[2] = ( nField2 != 0 );
-                        aSortParam.nField[2] = nField2 > 0 ? (nField2-1) : 0;
+                        aSortParam.maKeyState[2].bDoSort = ( nField2 != 0 );
+                        aSortParam.maKeyState[2].nField = nField2 > 0 ? (nField2-1) : 0;
                         if ( pArgs->GetItemState( FN_PARAM_6, sal_True, &pItem ) == SFX_ITEM_SET )
-                            aSortParam.bAscending[2] = ((const SfxBoolItem*)pItem)->GetValue();
+                            aSortParam.maKeyState[2].bAscending = ((const 
SfxBoolItem*)pItem)->GetValue();
 
                         // subtotal when needed new
                         pTabViewShell->UISort( aSortParam );
@@ -516,26 +514,26 @@ void ScCellShell::ExecuteDB( SfxRequest& rReq )
                                     rOutParam.bIncludePattern ) );
                                 sal_uInt16 nUser = rOutParam.bUserDef ? ( rOutParam.nUserIndex + 1 
) : 0;
                                 rReq.AppendItem( SfxUInt16Item( SID_SORT_USERDEF, nUser ) );
-                                if ( rOutParam.bDoSort[0] )
+                                if ( rOutParam.maKeyState[0].bDoSort )
                                 {
                                     rReq.AppendItem( SfxInt32Item( FN_PARAM_1,
-                                        rOutParam.nField[0] + 1 ) );
+                                        rOutParam.maKeyState[0].nField + 1 ) );
                                     rReq.AppendItem( SfxBoolItem( FN_PARAM_2,
-                                        rOutParam.bAscending[0] ) );
+                                        rOutParam.maKeyState[0].bAscending ) );
                                 }
-                                if ( rOutParam.bDoSort[1] )
+                                if ( rOutParam.maKeyState[1].bDoSort )
                                 {
                                     rReq.AppendItem( SfxInt32Item( FN_PARAM_3,
-                                        rOutParam.nField[1] + 1 ) );
+                                        rOutParam.maKeyState[1].nField + 1 ) );
                                     rReq.AppendItem( SfxBoolItem( FN_PARAM_4,
-                                        rOutParam.bAscending[1] ) );
+                                        rOutParam.maKeyState[1].bAscending ) );
                                 }
-                                if ( rOutParam.bDoSort[2] )
+                                if ( rOutParam.maKeyState[2].bDoSort )
                                 {
                                     rReq.AppendItem( SfxInt32Item( FN_PARAM_5,
-                                        rOutParam.nField[2] + 1 ) );
+                                        rOutParam.maKeyState[2].nField + 1 ) );
                                     rReq.AppendItem( SfxBoolItem( FN_PARAM_6,
-                                        rOutParam.bAscending[2] ) );
+                                        rOutParam.maKeyState[2].bAscending ) );
                                 }
                             }
 
diff --git a/sc/source/ui/view/dbfunc3.cxx b/sc/source/ui/view/dbfunc3.cxx
index f6eb887..aa15898 100644
--- a/sc/source/ui/view/dbfunc3.cxx
+++ b/sc/source/ui/view/dbfunc3.cxx
@@ -2158,7 +2158,7 @@ void ScDBFunc::RepeatDB( sal_Bool bRecord )
 
     ScSortParam aSortParam;
     pDBData->GetSortParam( aSortParam );
-    sal_Bool bSort = aSortParam.bDoSort[0];
+    sal_Bool bSort = aSortParam.maKeyState[0].bDoSort;
 
     ScSubTotalParam aSubTotalParam;
     pDBData->GetSubTotalParam( aSubTotalParam );
-- 
1.7.3.4

From 41dc7ddaa24efcacfaae73b153a5146bd5859a11 Mon Sep 17 00:00:00 2001
From: Albert Thuswaldner <albert.thuswaldner@gmail.com>
Date: Tue, 20 Mar 2012 20:09:52 +0100
Subject: [PATCH 2/2] fdo#45747 temporary patch adding 4th sort key

---
 sc/source/ui/dbgui/tpsort.cxx |   74 ++++++++++++++++++++++++++++++++++++++++-
 sc/source/ui/inc/sortdlg.hrc  |    7 ++++
 sc/source/ui/inc/tpsort.hxx   |   12 ++++++-
 sc/source/ui/src/sortdlg.src  |   40 ++++++++++++++++++++++
 4 files changed, 131 insertions(+), 2 deletions(-)

diff --git a/sc/source/ui/dbgui/tpsort.cxx b/sc/source/ui/dbgui/tpsort.cxx
index 4d6832a..ffcde6f 100644
--- a/sc/source/ui/dbgui/tpsort.cxx
+++ b/sc/source/ui/dbgui/tpsort.cxx
@@ -103,6 +103,13 @@ ScTabPageSortFields::ScTabPageSortFields( Window*           pParent,
         aLbSort3        ( this, ScResId( LB_SORT3  ) ),
         aBtnUp3         ( this, ScResId( BTN_UP3   ) ),
         aBtnDown3       ( this, ScResId( BTN_DOWN3 ) ),
+        //
+        aBtnAdd         ( this, ScResId( BTN_ADD   ) ),
+        //
+        aFlSort4        ( this, ScResId( FL_SORT4  ) ),
+        aLbSort4        ( this, ScResId( LB_SORT4  ) ),
+        aBtnUp4         ( this, ScResId( BTN_UP4   ) ),
+        aBtnDown4       ( this, ScResId( BTN_DOWN4 ) ),
 
         aStrUndefined   ( ScResId( SCSTR_UNDEFINED ) ),
         aStrColumn      ( ScResId( SCSTR_COLUMN ) ),
@@ -158,6 +165,8 @@ void ScTabPageSortFields::Init()
     nFirstCol = 0;
     nFirstRow = 0;
 
+    aBtnAdd.SetClickHdl( LINK( this, ScTabPageSortFields, BtnHdl ) );
+
     aLbSort1.SetSelectHdl( LINK( this, ScTabPageSortFields, SelectHdl ) );
     aLbSort2.SetSelectHdl( LINK( this, ScTabPageSortFields, SelectHdl ) );
     aLbSort3.SetSelectHdl( LINK( this, ScTabPageSortFields, SelectHdl ) );
@@ -169,6 +178,12 @@ void ScTabPageSortFields::Init()
     aBtnUp     = { &aBtnUp1,   &aBtnUp2,   &aBtnUp3 };
     aBtnDown   = { &aBtnDown1, &aBtnDown2, &aBtnDown3 };
     aFlArr     = { &aFlSort1,  &aFlSort2,  &aFlSort3 };
+
+    // Hide Sort key 4 widgets
+    aFlSort4.Hide();
+    aLbSort4.Hide();
+    aBtnUp4.Hide();
+    aBtnDown4.Hide();
 }
 
 // -----------------------------------------------------------------------
@@ -181,6 +196,51 @@ SfxTabPage* ScTabPageSortFields::Create( Window*    pParent,
 
 // -----------------------------------------------------------------------
 
+void ScTabPageSortFields::AddSortKey()
+{
+    sal_uInt16 nSortKeyIndex = nSortKeyCount;
+
+    // Extend local SortParam copy
+    const SCSortKeyState atempKeyState = { false, 0, true };
+    newSortData.maKeyState.push_back( atempKeyState );
+
+    // Show Sort key 4 widgets
+    aFlSort4.Show();
+    aLbSort4.Show();
+    aBtnUp4.Show();
+    aBtnDown4.Show();
+
+    // Connect handlers and widgets
+    aLbSort4.SetSelectHdl( LINK( this, ScTabPageSortFields, SelectHdl ) );
+    aLbSort4.Clear();
+
+    aLbSortArr.push_back( &aLbSort4 );
+
+    aBtnUp.push_back( &aBtnUp4 );
+    aBtnDown.push_back( &aBtnDown4 );
+
+    aFlArr.push_back( &aFlSort4 );
+
+    ++nSortKeyCount;
+
+    // Populate listbox
+    FillFieldLists(nSortKeyIndex);
+
+    // Set Status
+    aBtnUp[nSortKeyIndex]->Check();
+    aLbSortArr[nSortKeyIndex]->SelectEntryPos( 0 );
+    DisableField( nSortKeyIndex );
+
+    // Move Add button
+    Point aBtnAddPos = aBtnAdd.GetPosPixel();
+    aBtnAddPos.Y() += aBtnAdd.GetSizePixel().Height();
+    aBtnAdd.SetPosPixel( Point( aBtnAddPos.X(), aBtnAddPos.Y() + SC_KEY_OFFSET ) );
+    Point aBtnAddPos2 = aBtnAdd.GetPosPixel();
+}
+
+
+// -----------------------------------------------------------------------
+
 void ScTabPageSortFields::Reset( const SfxItemSet& /* rArgSet */ )
 {
     bSortByRows = newSortData.bByRow;
@@ -460,7 +520,7 @@ sal_uInt16 ScTabPageSortFields::GetFieldSelPos( SCCOLROW nField )
 }
 
 // -----------------------------------------------------------------------
-// Handler:
+// Handlers:
 //---------
 
 IMPL_LINK( ScTabPageSortFields, SelectHdl, ListBox *, pLb )
@@ -495,6 +555,18 @@ IMPL_LINK( ScTabPageSortFields, SelectHdl, ListBox *, pLb )
     return 0;
 }
 
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ScTabPageSortFields, BtnHdl, PushButton*, pBtn )
+{
+    if ( pBtn == &aBtnAdd )
+    {
+        if ( nSortKeyCount == 3 )
+            AddSortKey();
+    }
+    return( 0L );
+}
+
 //========================================================================
 // Sort option Tab Page:
 //========================================================================
diff --git a/sc/source/ui/inc/sortdlg.hrc b/sc/source/ui/inc/sortdlg.hrc
index f583dd3d..dcc38e0 100644
--- a/sc/source/ui/inc/sortdlg.hrc
+++ b/sc/source/ui/inc/sortdlg.hrc
@@ -51,6 +51,13 @@
 #define BTN_DOWN2           11
 #define BTN_DOWN3           12
 
+#define BTN_ADD             13
+
+#define FL_SORT4            14
+#define LB_SORT4            15
+#define BTN_UP4             16
+#define BTN_DOWN4           17
+
 // TP_SORT_OPTIONS:
 #define FL_DIRECTION        1
 #define LB_SORT_USER        2
diff --git a/sc/source/ui/inc/tpsort.hxx b/sc/source/ui/inc/tpsort.hxx
index 684fe3e..94af453 100644
--- a/sc/source/ui/inc/tpsort.hxx
+++ b/sc/source/ui/inc/tpsort.hxx
@@ -47,6 +47,7 @@
 
 // +1 because one field is reserved for the "- undefined -" entry
 #define SC_MAXFIELDS    MAXCOLCOUNT+1
+#define SC_KEY_OFFSET   41L
 
 class ScViewData;
 class ScSortDlg;
@@ -91,6 +92,13 @@ private:
     RadioButton     aBtnUp3;
     RadioButton     aBtnDown3;
 
+    PushButton     aBtnAdd;
+
+    FixedLine       aFlSort4;
+    ListBox         aLbSort4;
+    RadioButton     aBtnUp4;
+    RadioButton     aBtnDown4;
+
     String          aStrUndefined;
     String          aStrColumn;
     String          aStrRow;
@@ -118,13 +126,15 @@ private:
 #ifdef _TPSORT_CXX
 private:
     void    Init            ();
+    void    AddSortKey      ();
     void    DisableField    ( sal_uInt16 nField );
     void    EnableField     ( sal_uInt16 nField );
     void    FillFieldLists  ( sal_uInt16 nStartField );
     sal_uInt16  GetFieldSelPos  ( SCCOLROW nField );
 
-    // Handler ------------------------
+    // Handlers ------------------------
     DECL_LINK( SelectHdl, ListBox * );
+    DECL_LINK( BtnHdl, PushButton* );
 #endif
 };
 
diff --git a/sc/source/ui/src/sortdlg.src b/sc/source/ui/src/sortdlg.src
index 466ab7a..0c798d3 100644
--- a/sc/source/ui/src/sortdlg.src
+++ b/sc/source/ui/src/sortdlg.src
@@ -125,6 +125,46 @@ TabPage RID_SCPAGE_SORT_FIELDS
         Size = MAP_APPFONT ( 248 , 8 ) ;
         Text [ en-US ] = "Sort ~key 3" ;
     };
+    PushButton BTN_ADD
+    {
+        Pos = MAP_APPFONT (  12 ,126 ) ;
+        Size = MAP_APPFONT ( 50 , 14 ) ;
+        TabStop = TRUE ;
+        Text [ en-US ] = "~Add" ;
+    };
+
+// temoprary fourth button
+    ListBox LB_SORT4
+    {
+        HelpID = "sc:ListBox:RID_SCPAGE_SORT_FIELDS:LB_SORT4";
+        Border = TRUE ;
+        Pos = MAP_APPFONT ( 12 , 142 ) ;
+        Size = MAP_APPFONT ( 154 , 90 ) ;
+        TabStop = TRUE ;
+        DropDown = TRUE ;
+    };
+    RadioButton BTN_UP4
+    {
+        HelpID = "sc:RadioButton:RID_SCPAGE_SORT_FIELDS:BTN_UP4";
+        Pos = MAP_APPFONT ( 172 , 137 ) ;
+        Size = MAP_APPFONT ( 79 , 10 ) ;
+        Text [ en-US ] = "As~cending" ;
+        TabStop = TRUE ;
+    };
+    RadioButton BTN_DOWN4
+    {
+        HelpID = "sc:RadioButton:RID_SCPAGE_SORT_FIELDS:BTN_DOWN4";
+        Pos = MAP_APPFONT ( 172 , 151 ) ;
+        Size = MAP_APPFONT ( 79 , 10 ) ;
+        Text [ en-US ] = "Desce~nding" ;
+        TabStop = TRUE ;
+    };
+    FixedLine FL_SORT4
+    {
+        Pos = MAP_APPFONT ( 6 , 126 ) ;
+        Size = MAP_APPFONT ( 243 , 8 ) ;
+        Text [ en-US ] = "Sort ~key 4" ;
+    };
 };
 
 TabPage RID_SCPAGE_SORT_OPTIONS
-- 
1.7.3.4


Context


Privacy Policy | Impressum (Legal Info) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Creative Commons Attribution-Share Alike 3.0 License. This does not include the source code of LibreOffice, which is licensed under the Mozilla Public License (MPLv2). "LibreOffice" and "The Document Foundation" are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy.