diff options
Diffstat (limited to 'sc/source/core/tool/rangelst.cxx')
-rw-r--r-- | sc/source/core/tool/rangelst.cxx | 923 |
1 files changed, 923 insertions, 0 deletions
diff --git a/sc/source/core/tool/rangelst.cxx b/sc/source/core/tool/rangelst.cxx new file mode 100644 index 000000000000..7395da73d33e --- /dev/null +++ b/sc/source/core/tool/rangelst.cxx @@ -0,0 +1,923 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + +//------------------------------------------------------------------------ + +#define SC_RANGELST_CXX //fuer ICC + +#include <tools/debug.hxx> +#include <stdlib.h> // qsort +#include <unotools/collatorwrapper.hxx> + +#include "rangelst.hxx" +#include "document.hxx" +#include "refupdat.hxx" +#include "rechead.hxx" +#include "compiler.hxx" + +using ::std::vector; +using ::std::advance; +using ::std::find_if; +using ::std::for_each; +using ::formula::FormulaGrammar; + +namespace { + +template<typename T> +class FindEnclosingRange : public ::std::unary_function<bool, ScRange*> +{ +public: + FindEnclosingRange(const T& rTest) : mrTest(rTest) {} + FindEnclosingRange(const FindEnclosingRange& r) : mrTest(r.mrTest) {} + bool operator() (const ScRange* pRange) const + { + return pRange->In(mrTest); + } +private: + const T& mrTest; +}; + +template<typename T> +class FindIntersectingRange : public ::std::unary_function<bool, ScRange*> +{ +public: + FindIntersectingRange(const T& rTest) : mrTest(rTest) {} + FindIntersectingRange(const FindIntersectingRange& r) : mrTest(r.mrTest) {} + bool operator() (const ScRange* pRange) const + { + return pRange->Intersects(mrTest); + } +private: + const T& mrTest; +}; + +class AppendToList : public ::std::unary_function<void, const ScRange*> +{ +public: + AppendToList(vector<ScRange*>& rRanges) : mrRanges(rRanges) {} + AppendToList(const AppendToList& r) : mrRanges(r.mrRanges) {} + void operator() (const ScRange* p) + { + mrRanges.push_back(new ScRange(*p)); + } +private: + vector<ScRange*>& mrRanges; +}; + +template<typename T> +struct DeleteObject : public ::std::unary_function<void, T*> +{ + void operator() (T* p) + { + delete p; + } +}; + +class CountCells : public ::std::unary_function<void, const ScRange*> +{ +public: + CountCells() : mnCellCount(0) {} + CountCells(const CountCells& r) : mnCellCount(r.mnCellCount) {} + + void operator() (const ScRange* p) + { + mnCellCount += + size_t(p->aEnd.Col() - p->aStart.Col() + 1) + * size_t(p->aEnd.Row() - p->aStart.Row() + 1) + * size_t(p->aEnd.Tab() - p->aStart.Tab() + 1); + } + + size_t getCellCount() const { return mnCellCount; } + +private: + size_t mnCellCount; +}; + +class FormatString : public ::std::unary_function<void, const ScRange*> +{ +public: + FormatString(String& rStr, sal_uInt16 nFlags, ScDocument* pDoc, FormulaGrammar::AddressConvention eConv, sal_Unicode cDelim) : + mrStr(rStr), + mnFlags(nFlags), + mpDoc(pDoc), + meConv(eConv), + mcDelim(cDelim), + mbFirst(true) {} + + FormatString(const FormatString& r) : + mrStr(r.mrStr), + mnFlags(r.mnFlags), + mpDoc(r.mpDoc), + meConv(r.meConv), + mcDelim(r.mcDelim), + mbFirst(r.mbFirst) {} + + void operator() (const ScRange* p) + { + String aStr; + p->Format(aStr, mnFlags, mpDoc, meConv); + if (mbFirst) + mbFirst = false; + else + mrStr += mcDelim; + mrStr += aStr; + } +private: + String& mrStr; + sal_uInt16 mnFlags; + ScDocument* mpDoc; + FormulaGrammar::AddressConvention meConv; + sal_Unicode mcDelim; + bool mbFirst; +}; + +} + +// === ScRangeList ==================================================== + +ScRangeList::~ScRangeList() +{ + RemoveAll(); +} + +sal_uInt16 ScRangeList::Parse( const String& rStr, ScDocument* pDoc, sal_uInt16 nMask, + formula::FormulaGrammar::AddressConvention eConv, + sal_Unicode cDelimiter ) +{ + if ( rStr.Len() ) + { + if (!cDelimiter) + cDelimiter = ScCompiler::GetNativeSymbol(ocSep).GetChar(0); + + nMask |= SCA_VALID; // falls das jemand vergessen sollte + sal_uInt16 nResult = (sal_uInt16)~0; // alle Bits setzen + ScRange aRange; + String aOne; + SCTAB nTab = 0; + if ( pDoc ) + { + //! erste markierte Tabelle gibts nicht mehr am Dokument + //! -> uebergeben? oder spaeter an den Ranges setzen + } + else + nTab = 0; + sal_uInt16 nTCount = rStr.GetTokenCount( cDelimiter ); + for ( sal_uInt16 i=0; i<nTCount; i++ ) + { + aOne = rStr.GetToken( i, cDelimiter ); + aRange.aStart.SetTab( nTab ); // Default Tab wenn nicht angegeben + sal_uInt16 nRes = aRange.ParseAny( aOne, pDoc, eConv ); + sal_uInt16 nEndRangeBits = SCA_VALID_COL2 | SCA_VALID_ROW2 | SCA_VALID_TAB2; + sal_uInt16 nTmp1 = ( nRes & SCA_BITS ); + sal_uInt16 nTmp2 = ( nRes & nEndRangeBits ); + // If we have a valid single range with + // any of the address bits we are interested in + // set - set the equiv end range bits + if ( (nRes & SCA_VALID ) && nTmp1 && ( nTmp2 != nEndRangeBits ) ) + nRes |= ( nTmp1 << 4 ); + + if ( (nRes & nMask) == nMask ) + Append( aRange ); + nResult &= nRes; // alle gemeinsamen Bits bleiben erhalten + } + return nResult; // SCA_VALID gesetzt wenn alle ok + } + else + return 0; +} + + +void ScRangeList::Format( String& rStr, sal_uInt16 nFlags, ScDocument* pDoc, + formula::FormulaGrammar::AddressConvention eConv, + sal_Unicode cDelimiter ) const +{ + rStr.Erase(); + + if (!cDelimiter) + cDelimiter = ScCompiler::GetNativeSymbol(ocSep).GetChar(0); + + FormatString func(rStr, nFlags, pDoc, eConv, cDelimiter); + for_each(maRanges.begin(), maRanges.end(), func); +} + + +void ScRangeList::Join( const ScRange& r, bool bIsInList ) +{ + if ( maRanges.empty() ) + { + Append( r ); + return ; + } + SCCOL nCol1 = r.aStart.Col(); + SCROW nRow1 = r.aStart.Row(); + SCTAB nTab1 = r.aStart.Tab(); + SCCOL nCol2 = r.aEnd.Col(); + SCROW nRow2 = r.aEnd.Row(); + SCTAB nTab2 = r.aEnd.Tab(); + + ScRange* pOver = (ScRange*) &r; // fies aber wahr wenn bInList + size_t nOldPos = 0; + if ( bIsInList ) + { + // Find the current position of this range. + for ( size_t i = 0, nRanges = maRanges.size(); i < nRanges; ++i ) + { + if ( maRanges[i] == pOver ) + { + nOldPos = i; + break; + } + } + } + bool bJoinedInput = false; + + for ( size_t i = 0, nRanges = maRanges.size(); i < nRanges && pOver; ++i ) + { + ScRange* p = maRanges[i]; + if ( p == pOver ) + continue; // derselbe, weiter mit dem naechsten + bool bJoined = false; + if ( p->In( r ) ) + { // Range r in Range p enthalten oder identisch + if ( bIsInList ) + bJoined = true; // weg mit Range r + else + { // das war's dann + bJoinedInput = true; // nicht anhaengen + break; // for + } + } + else if ( r.In( *p ) ) + { // Range p in Range r enthalten, r zum neuen Range machen + *p = r; + bJoined = true; + } + if ( !bJoined && p->aStart.Tab() == nTab1 && p->aEnd.Tab() == nTab2 ) + { // 2D + if ( p->aStart.Col() == nCol1 && p->aEnd.Col() == nCol2 ) + { + if ( p->aStart.Row() == nRow2+1 ) + { // oben + p->aStart.SetRow( nRow1 ); + bJoined = true; + } + else if ( p->aEnd.Row() == nRow1-1 ) + { // unten + p->aEnd.SetRow( nRow2 ); + bJoined = true; + } + } + else if ( p->aStart.Row() == nRow1 && p->aEnd.Row() == nRow2 ) + { + if ( p->aStart.Col() == nCol2+1 ) + { // links + p->aStart.SetCol( nCol1 ); + bJoined = true; + } + else if ( p->aEnd.Col() == nCol1-1 ) + { // rechts + p->aEnd.SetCol( nCol2 ); + bJoined = true; + } + } + } + if ( bJoined ) + { + if ( bIsInList ) + { // innerhalb der Liste Range loeschen + Remove(nOldPos); + delete pOver; + pOver = NULL; + if ( nOldPos ) + nOldPos--; // Seek richtig aufsetzen + } + bJoinedInput = true; + Join( *p, true ); // rekursiv! + } + } + if ( !bIsInList && !bJoinedInput ) + Append( r ); +} + + +bool ScRangeList::operator==( const ScRangeList& r ) const +{ + if ( this == &r ) + return true; + + if (maRanges.size() != r.maRanges.size()) + return false; + + vector<ScRange*>::const_iterator itr1 = maRanges.begin(), itrEnd = maRanges.end(); + vector<ScRange*>::const_iterator itr2 = r.maRanges.begin(); + for (; itr1 != itrEnd; ++itr1, ++itr2) + { + const ScRange* p1 = *itr1; + const ScRange* p2 = *itr2; + if (*p1 != *p2) + return false; + } + return true; +} + +bool ScRangeList::operator!=( const ScRangeList& r ) const +{ + return !operator==( r ); +} + +bool ScRangeList::UpdateReference( + UpdateRefMode eUpdateRefMode, + ScDocument* pDoc, + const ScRange& rWhere, + SCsCOL nDx, + SCsROW nDy, + SCsTAB nDz +) +{ + if (maRanges.empty()) + // No ranges to update. Bail out. + return false; + + bool bChanged = false; + SCCOL nCol1; + SCROW nRow1; + SCTAB nTab1; + SCCOL nCol2; + SCROW nRow2; + SCTAB nTab2; + rWhere.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); + + vector<ScRange*>::iterator itr = maRanges.begin(), itrEnd = maRanges.end(); + for (; itr != itrEnd; ++itr) + { + ScRange* pR = *itr; + SCCOL theCol1; + SCROW theRow1; + SCTAB theTab1; + SCCOL theCol2; + SCROW theRow2; + SCTAB theTab2; + pR->GetVars( theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 ); + if ( ScRefUpdate::Update( pDoc, eUpdateRefMode, + nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, + nDx, nDy, nDz, + theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 ) + != UR_NOTHING ) + { + bChanged = true; + pR->aStart.Set( theCol1, theRow1, theTab1 ); + pR->aEnd.Set( theCol2, theRow2, theTab2 ); + } + } + return bChanged; +} + +const ScRange* ScRangeList::Find( const ScAddress& rAdr ) const +{ + vector<ScRange*>::const_iterator itr = find_if( + maRanges.begin(), maRanges.end(), FindEnclosingRange<ScAddress>(rAdr)); + return itr == maRanges.end() ? NULL : *itr; +} + +ScRange* ScRangeList::Find( const ScAddress& rAdr ) +{ + vector<ScRange*>::iterator itr = find_if( + maRanges.begin(), maRanges.end(), FindEnclosingRange<ScAddress>(rAdr)); + return itr == maRanges.end() ? NULL : *itr; +} + +ScRangeList::ScRangeList( const ScRangeList& rList ) : + SvRefBase() +{ + maRanges.reserve(rList.maRanges.size()); + for_each(rList.maRanges.begin(), rList.maRanges.end(), AppendToList(maRanges)); +} + +ScRangeList& ScRangeList::operator=(const ScRangeList& rList) +{ + RemoveAll(); + maRanges.reserve(rList.maRanges.size()); + for_each(rList.maRanges.begin(), rList.maRanges.end(), AppendToList(maRanges)); + return *this; +} + +bool ScRangeList::Intersects( const ScRange& rRange ) const +{ + vector<ScRange*>::const_iterator itrEnd = maRanges.end(); + vector<ScRange*>::const_iterator itr = + find_if(maRanges.begin(), itrEnd, FindIntersectingRange<ScRange>(rRange)); + return itr != itrEnd; +} + +bool ScRangeList::In( const ScRange& rRange ) const +{ + vector<ScRange*>::const_iterator itrEnd = maRanges.end(); + vector<ScRange*>::const_iterator itr = + find_if(maRanges.begin(), itrEnd, FindEnclosingRange<ScRange>(rRange)); + return itr != itrEnd; +} + + +size_t ScRangeList::GetCellCount() const +{ + CountCells func; + return for_each(maRanges.begin(), maRanges.end(), func).getCellCount(); +} + +ScRange* ScRangeList::Remove(size_t nPos) +{ + if (maRanges.size() <= nPos) + // Out-of-bound condition. Bail out. + return NULL; + + vector<ScRange*>::iterator itr = maRanges.begin(); + advance(itr, nPos); + ScRange* p = *itr; + maRanges.erase(itr); + return p; +} + +void ScRangeList::RemoveAll() +{ + for_each(maRanges.begin(), maRanges.end(), DeleteObject<ScRange>()); + maRanges.clear(); +} + +bool ScRangeList::empty() const +{ + return maRanges.empty(); +} + +size_t ScRangeList::size() const +{ + return maRanges.size(); +} + +ScRange* ScRangeList::operator [](size_t idx) +{ + return maRanges[idx]; +} + +const ScRange* ScRangeList::operator [](size_t idx) const +{ + return maRanges[idx]; +} + +ScRange* ScRangeList::front() +{ + return maRanges.front(); +} + +const ScRange* ScRangeList::front() const +{ + return maRanges.front(); +} + +ScRange* ScRangeList::back() +{ + return maRanges.back(); +} + +const ScRange* ScRangeList::back() const +{ + return maRanges.back(); +} + +void ScRangeList::push_back(ScRange* p) +{ + maRanges.push_back(p); +} + +// === ScRangePairList ======================================================== + +ScRangePairList::~ScRangePairList() +{ + for_each( maPairs.begin(), maPairs.end(), DeleteObject<ScRangePair>() ); + maPairs.clear(); +} + +//----------------------------------------------------------------------------- +ScRangePair* ScRangePairList::Remove(size_t nPos) +{ + if (maPairs.size() <= nPos) + // Out-of-bound condition. Bail out. + return NULL; + + vector<ScRangePair*>::iterator itr = maPairs.begin(); + advance(itr, nPos); + ScRangePair* p = *itr; + maPairs.erase(itr); + return p; +} + +//----------------------------------------------------------------------------- +ScRangePair* ScRangePairList::Remove( ScRangePair* Adr) +{ + ScRangePair* p = NULL; + + if (Adr == NULL) return NULL; + + for ( vector<ScRangePair*>::iterator itr = maPairs.begin(); itr < maPairs.end(); ++itr ) + { + if ( Adr == (p = *itr) ) + { + maPairs.erase( itr ); + break; + } + } + return p; +} + +bool ScRangePairList::operator==( const ScRangePairList& r ) const +{ + if ( this == &r ) + return true; // identische Referenz + if ( maPairs.size() != r.size() ) + return false; + for ( size_t nIdx = 0, nCnt = maPairs.size(); nIdx < nCnt; ++nIdx ) + { + if ( *maPairs[ nIdx ] != *r[ nIdx ] ) + return false; // auch andere Reihenfolge ist ungleich + } + return true; +} + +ScRangePair* ScRangePairList::operator [](size_t idx) +{ + return maPairs[idx]; +} + +const ScRangePair* ScRangePairList::operator [](size_t idx) const +{ + return maPairs[idx]; +} + +size_t ScRangePairList::size() const +{ + return maPairs.size(); +} + +bool ScRangePairList::UpdateReference( UpdateRefMode eUpdateRefMode, + ScDocument* pDoc, const ScRange& rWhere, + SCsCOL nDx, SCsROW nDy, SCsTAB nDz ) +{ + bool bChanged = false; + if ( !maPairs.empty() ) + { + SCCOL nCol1; + SCROW nRow1; + SCTAB nTab1; + SCCOL nCol2; + SCROW nRow2; + SCTAB nTab2; + rWhere.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); + for ( size_t i = 0, nPairs = maPairs.size(); i < nPairs; ++i ) + { + ScRangePair* pR = maPairs[ i ]; + for ( sal_uInt16 j=0; j<2; j++ ) + { + ScRange& rRange = pR->GetRange(j); + SCCOL theCol1; + SCROW theRow1; + SCTAB theTab1; + SCCOL theCol2; + SCROW theRow2; + SCTAB theTab2; + rRange.GetVars( theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 ); + if ( ScRefUpdate::Update( pDoc, eUpdateRefMode, + nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, + nDx, nDy, nDz, + theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 ) + != UR_NOTHING ) + { + bChanged = true; + rRange.aStart.Set( theCol1, theRow1, theTab1 ); + rRange.aEnd.Set( theCol2, theRow2, theTab2 ); + } + } + } + } + return bChanged; +} + +//----------------------------------------------------------------------------- +// Delete entries that have the labels (first range) on nTab +void ScRangePairList::DeleteOnTab( SCTAB nTab ) +{ + size_t nListCount = maPairs.size(); + size_t nPos = 0; + while ( nPos < nListCount ) + { + ScRangePair* pR = maPairs[ nPos ]; + ScRange aRange = pR->GetRange(0); + if ( aRange.aStart.Tab() == nTab && aRange.aEnd.Tab() == nTab ) + { + Remove( nPos ); + delete pR; + nListCount = maPairs.size(); + } + else + ++nPos; + } +} + +//----------------------------------------------------------------------------- +ScRangePair* ScRangePairList::Find( const ScAddress& rAdr ) const +{ + for ( size_t j = 0, nListCount = maPairs.size(); j < nListCount; j++ ) + { + ScRangePair* pR = maPairs[ j ]; + if ( pR->GetRange(0).In( rAdr ) ) + return pR; + } + return NULL; +} + +//----------------------------------------------------------------------------- +ScRangePair* ScRangePairList::Find( const ScRange& rRange ) const +{ + for ( size_t j = 0, nListCount = maPairs.size(); j < nListCount; j++ ) + { + ScRangePair* pR = maPairs[ j ]; + if ( pR->GetRange(0) == rRange ) + return pR; + } + return NULL; +} + + +//----------------------------------------------------------------------------- +ScRangePairList* ScRangePairList::Clone() const +{ + ScRangePairList* pNew = new ScRangePairList; + for ( size_t j = 0, nListCount = maPairs.size(); j < nListCount; j++ ) + { + pNew->Append( *maPairs[ j ] ); + } + return pNew; +} + +//----------------------------------------------------------------------------- +struct ScRangePairNameSort +{ + ScRangePair* pPair; + ScDocument* pDoc; +}; + +//----------------------------------------------------------------------------- +extern "C" int +#ifdef WNT +__cdecl +#endif +ScRangePairList_QsortNameCompare( const void* p1, const void* p2 ) +{ + const ScRangePairNameSort* ps1 = (const ScRangePairNameSort*)p1; + const ScRangePairNameSort* ps2 = (const ScRangePairNameSort*)p2; + const ScAddress& rStartPos1 = ps1->pPair->GetRange(0).aStart; + const ScAddress& rStartPos2 = ps2->pPair->GetRange(0).aStart; + String aStr1, aStr2; + sal_Int32 nComp; + if ( rStartPos1.Tab() == rStartPos2.Tab() ) + nComp = COMPARE_EQUAL; + else + { + ps1->pDoc->GetName( rStartPos1.Tab(), aStr1 ); + ps2->pDoc->GetName( rStartPos2.Tab(), aStr2 ); + nComp = ScGlobal::GetCollator()->compareString( aStr1, aStr2 ); + } + switch ( nComp ) + { + case COMPARE_LESS: + return -1; + //break; + case COMPARE_GREATER: + return 1; + //break; + default: + // gleiche Tabs + if ( rStartPos1.Col() < rStartPos2.Col() ) + return -1; + if ( rStartPos1.Col() > rStartPos2.Col() ) + return 1; + // gleiche Cols + if ( rStartPos1.Row() < rStartPos2.Row() ) + return -1; + if ( rStartPos1.Row() > rStartPos2.Row() ) + return 1; + // erste Ecke gleich, zweite Ecke + { + const ScAddress& rEndPos1 = ps1->pPair->GetRange(0).aEnd; + const ScAddress& rEndPos2 = ps2->pPair->GetRange(0).aEnd; + if ( rEndPos1.Tab() == rEndPos2.Tab() ) + nComp = COMPARE_EQUAL; + else + { + ps1->pDoc->GetName( rEndPos1.Tab(), aStr1 ); + ps2->pDoc->GetName( rEndPos2.Tab(), aStr2 ); + nComp = ScGlobal::GetCollator()->compareString( aStr1, aStr2 ); + } + switch ( nComp ) + { + case COMPARE_LESS: + return -1; + //break; + case COMPARE_GREATER: + return 1; + //break; + default: + // gleiche Tabs + if ( rEndPos1.Col() < rEndPos2.Col() ) + return -1; + if ( rEndPos1.Col() > rEndPos2.Col() ) + return 1; + // gleiche Cols + if ( rEndPos1.Row() < rEndPos2.Row() ) + return -1; + if ( rEndPos1.Row() > rEndPos2.Row() ) + return 1; + return 0; + } + } + return 0; + } + return 0; // just in case +} + +//----------------------------------------------------------------------------- +void ScRangePairList::Join( const ScRangePair& r, bool bIsInList ) +{ + if ( maPairs.empty() ) + { + Append( r ); + return ; + } + const ScRange& r1 = r.GetRange(0); + const ScRange& r2 = r.GetRange(1); + SCCOL nCol1 = r1.aStart.Col(); + SCROW nRow1 = r1.aStart.Row(); + SCTAB nTab1 = r1.aStart.Tab(); + SCCOL nCol2 = r1.aEnd.Col(); + SCROW nRow2 = r1.aEnd.Row(); + SCTAB nTab2 = r1.aEnd.Tab(); + ScRangePair* pOver = (ScRangePair*) &r; // fies aber wahr wenn bInList + size_t nOldPos = 0; + if ( bIsInList ) + { + // Find the current position of this range. + for ( size_t i = 0, nPairs = maPairs.size(); i < nPairs; ++i ) + { + if ( maPairs[i] == pOver ) + { + nOldPos = i; + break; + } + } + } + bool bJoinedInput = false; + + for ( size_t i = 0, nPairs = maPairs.size(); i < nPairs && pOver; ++i ) + { + ScRangePair* p = maPairs[ i ]; + if ( p == pOver ) + continue; // derselbe, weiter mit dem naechsten + bool bJoined = false; + ScRange& rp1 = p->GetRange(0); + ScRange& rp2 = p->GetRange(1); + if ( rp2 == r2 ) + { // nur wenn Range2 gleich ist + if ( rp1.In( r1 ) ) + { // RangePair r in RangePair p enthalten oder identisch + if ( bIsInList ) + bJoined = true; // weg mit RangePair r + else + { // das war's dann + bJoinedInput = true; // nicht anhaengen + break; // for + } + } + else if ( r1.In( rp1 ) ) + { // RangePair p in RangePair r enthalten, r zum neuen RangePair machen + *p = r; + bJoined = true; + } + } + if ( !bJoined && rp1.aStart.Tab() == nTab1 && rp1.aEnd.Tab() == nTab2 + && rp2.aStart.Tab() == r2.aStart.Tab() + && rp2.aEnd.Tab() == r2.aEnd.Tab() ) + { // 2D, Range2 muss genauso nebeneinander liegen wie Range1 + if ( rp1.aStart.Col() == nCol1 && rp1.aEnd.Col() == nCol2 + && rp2.aStart.Col() == r2.aStart.Col() + && rp2.aEnd.Col() == r2.aEnd.Col() ) + { + if ( rp1.aStart.Row() == nRow2+1 + && rp2.aStart.Row() == r2.aEnd.Row()+1 ) + { // oben + rp1.aStart.SetRow( nRow1 ); + rp2.aStart.SetRow( r2.aStart.Row() ); + bJoined = true; + } + else if ( rp1.aEnd.Row() == nRow1-1 + && rp2.aEnd.Row() == r2.aStart.Row()-1 ) + { // unten + rp1.aEnd.SetRow( nRow2 ); + rp2.aEnd.SetRow( r2.aEnd.Row() ); + bJoined = true; + } + } + else if ( rp1.aStart.Row() == nRow1 && rp1.aEnd.Row() == nRow2 + && rp2.aStart.Row() == r2.aStart.Row() + && rp2.aEnd.Row() == r2.aEnd.Row() ) + { + if ( rp1.aStart.Col() == nCol2+1 + && rp2.aStart.Col() == r2.aEnd.Col()+1 ) + { // links + rp1.aStart.SetCol( nCol1 ); + rp2.aStart.SetCol( r2.aStart.Col() ); + bJoined = true; + } + else if ( rp1.aEnd.Col() == nCol1-1 + && rp2.aEnd.Col() == r2.aEnd.Col()-1 ) + { // rechts + rp1.aEnd.SetCol( nCol2 ); + rp2.aEnd.SetCol( r2.aEnd.Col() ); + bJoined = true; + } + } + } + if ( bJoined ) + { + if ( bIsInList ) + { // innerhalb der Liste RangePair loeschen + Remove( nOldPos ); + delete pOver; + pOver = NULL; + if ( nOldPos ) + nOldPos--; // Seek richtig aufsetzen + } + bJoinedInput = true; + Join( *p, true ); // rekursiv! + } + } + if ( !bIsInList && !bJoinedInput ) + Append( r ); +} + +//----------------------------------------------------------------------------- +ScRangePair** ScRangePairList::CreateNameSortedArray( size_t& nListCount, + ScDocument* pDoc ) const +{ + nListCount = maPairs.size(); + DBG_ASSERT( nListCount * sizeof(ScRangePairNameSort) <= (size_t)~0x1F, + "ScRangePairList::CreateNameSortedArray nListCount * sizeof(ScRangePairNameSort) > (size_t)~0x1F" ); + ScRangePairNameSort* pSortArray = (ScRangePairNameSort*) + new sal_uInt8 [ nListCount * sizeof(ScRangePairNameSort) ]; + sal_uLong j; + for ( j=0; j < nListCount; j++ ) + { + pSortArray[j].pPair = maPairs[ j ]; + pSortArray[j].pDoc = pDoc; + } +#if !(defined(ICC ) && defined(OS2)) + qsort( (void*)pSortArray, nListCount, sizeof(ScRangePairNameSort), &ScRangePairList_QsortNameCompare ); +#else + qsort( (void*)pSortArray, nListCount, sizeof(ScRangePairNameSort), ICCQsortRPairCompare ); +#endif + // ScRangePair Pointer aufruecken + ScRangePair** ppSortArray = (ScRangePair**)pSortArray; + for ( j=0; j < nListCount; j++ ) + { + ppSortArray[j] = pSortArray[j].pPair; + } + return ppSortArray; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |