1*efeef26fSAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3*efeef26fSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4*efeef26fSAndrew Rist * or more contributor license agreements. See the NOTICE file
5*efeef26fSAndrew Rist * distributed with this work for additional information
6*efeef26fSAndrew Rist * regarding copyright ownership. The ASF licenses this file
7*efeef26fSAndrew Rist * to you under the Apache License, Version 2.0 (the
8*efeef26fSAndrew Rist * "License"); you may not use this file except in compliance
9*efeef26fSAndrew Rist * with the License. You may obtain a copy of the License at
10*efeef26fSAndrew Rist *
11*efeef26fSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12*efeef26fSAndrew Rist *
13*efeef26fSAndrew Rist * Unless required by applicable law or agreed to in writing,
14*efeef26fSAndrew Rist * software distributed under the License is distributed on an
15*efeef26fSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*efeef26fSAndrew Rist * KIND, either express or implied. See the License for the
17*efeef26fSAndrew Rist * specific language governing permissions and limitations
18*efeef26fSAndrew Rist * under the License.
19*efeef26fSAndrew Rist *
20*efeef26fSAndrew Rist *************************************************************/
21*efeef26fSAndrew Rist
22*efeef26fSAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sw.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir #include <hintids.hxx>
28cdf0e10cSrcweir #include <rtl/math.hxx>
29cdf0e10cSrcweir #include <unotools/collatorwrapper.hxx>
30cdf0e10cSrcweir #include <unotools/localedatawrapper.hxx>
31cdf0e10cSrcweir #include <com/sun/star/lang/XMultiServiceFactory.hpp>
32cdf0e10cSrcweir #include <com/sun/star/i18n/CollatorOptions.hpp>
33cdf0e10cSrcweir #include <comphelper/processfactory.hxx>
34cdf0e10cSrcweir #include <editeng/unolingu.hxx>
35cdf0e10cSrcweir #include <docary.hxx>
36cdf0e10cSrcweir #include <fmtanchr.hxx>
37cdf0e10cSrcweir #include <frmfmt.hxx>
38cdf0e10cSrcweir #include <doc.hxx>
39cdf0e10cSrcweir #include <IDocumentUndoRedo.hxx>
40cdf0e10cSrcweir #include <node.hxx>
41cdf0e10cSrcweir #include <pam.hxx>
42cdf0e10cSrcweir #include <ndtxt.hxx>
43cdf0e10cSrcweir #include <swtable.hxx>
44cdf0e10cSrcweir #include <swundo.hxx>
45cdf0e10cSrcweir #include <sortopt.hxx>
46cdf0e10cSrcweir #include <docsort.hxx>
47cdf0e10cSrcweir #include <UndoSort.hxx>
48cdf0e10cSrcweir #include <UndoRedline.hxx>
49cdf0e10cSrcweir #include <hints.hxx>
50cdf0e10cSrcweir #include <tblsel.hxx>
51cdf0e10cSrcweir #include <cellatr.hxx>
52cdf0e10cSrcweir #include <redline.hxx>
53cdf0e10cSrcweir #include <node2lay.hxx>
54cdf0e10cSrcweir #include <unochart.hxx>
55cdf0e10cSrcweir
56cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
57cdf0e10cSrcweir //nur zum debugen
58cdf0e10cSrcweir #include <cellatr.hxx>
59cdf0e10cSrcweir #endif
60cdf0e10cSrcweir
61cdf0e10cSrcweir using namespace ::com::sun::star::lang;
62cdf0e10cSrcweir
63cdf0e10cSrcweir SwSortOptions* SwSortElement::pOptions = 0;
64cdf0e10cSrcweir SwDoc* SwSortElement::pDoc = 0;
65cdf0e10cSrcweir const FlatFndBox* SwSortElement::pBox = 0;
66cdf0e10cSrcweir CollatorWrapper* SwSortElement::pSortCollator = 0;
67cdf0e10cSrcweir Locale* SwSortElement::pLocale = 0;
68cdf0e10cSrcweir String* SwSortElement::pLastAlgorithm = 0;
69cdf0e10cSrcweir LocaleDataWrapper* SwSortElement::pLclData = 0;
70cdf0e10cSrcweir
71cdf0e10cSrcweir SV_IMPL_OP_PTRARR_SORT( SwSortElements, SwSortElementPtr );
72cdf0e10cSrcweir
73cdf0e10cSrcweir
74cdf0e10cSrcweir /*--------------------------------------------------------------------
75cdf0e10cSrcweir Beschreibung: Ein Sortierelement fuers Sort konstruieren
76cdf0e10cSrcweir --------------------------------------------------------------------*/
77cdf0e10cSrcweir
78cdf0e10cSrcweir
Init(SwDoc * pD,const SwSortOptions & rOpt,FlatFndBox * pFltBx)79cdf0e10cSrcweir void SwSortElement::Init( SwDoc* pD, const SwSortOptions& rOpt,
80cdf0e10cSrcweir FlatFndBox* pFltBx )
81cdf0e10cSrcweir {
82cdf0e10cSrcweir ASSERT( !pDoc && !pOptions && !pBox, "wer hat das Finit vergessen?" );
83cdf0e10cSrcweir pDoc = pD;
84cdf0e10cSrcweir pOptions = new SwSortOptions( rOpt );
85cdf0e10cSrcweir pBox = pFltBx;
86cdf0e10cSrcweir
87cdf0e10cSrcweir LanguageType nLang = rOpt.nLanguage;
88cdf0e10cSrcweir switch ( nLang )
89cdf0e10cSrcweir {
90cdf0e10cSrcweir case LANGUAGE_NONE:
91cdf0e10cSrcweir case LANGUAGE_DONTKNOW:
92cdf0e10cSrcweir nLang = (LanguageType)GetAppLanguage();
93cdf0e10cSrcweir break;
94cdf0e10cSrcweir }
95cdf0e10cSrcweir pLocale = new Locale( SvxCreateLocale( nLang ) );
96cdf0e10cSrcweir
97cdf0e10cSrcweir pSortCollator = new CollatorWrapper(
98cdf0e10cSrcweir ::comphelper::getProcessServiceFactory() );
99cdf0e10cSrcweir // pSortCollator->loadCollatorAlgorithm( sAlgorithm, aLocale,
100cdf0e10cSrcweir // rOpt.bIgnoreCase ? SW_COLLATOR_IGNORES : 0 );
101cdf0e10cSrcweir }
102cdf0e10cSrcweir
103cdf0e10cSrcweir
Finit()104cdf0e10cSrcweir void SwSortElement::Finit()
105cdf0e10cSrcweir {
106cdf0e10cSrcweir delete pOptions, pOptions = 0;
107cdf0e10cSrcweir delete pLocale, pLocale = 0;
108cdf0e10cSrcweir delete pLastAlgorithm, pLastAlgorithm = 0;
109cdf0e10cSrcweir delete pSortCollator, pSortCollator = 0;
110cdf0e10cSrcweir delete pLclData, pLclData = 0;
111cdf0e10cSrcweir pDoc = 0;
112cdf0e10cSrcweir pBox = 0;
113cdf0e10cSrcweir }
114cdf0e10cSrcweir
115cdf0e10cSrcweir
~SwSortElement()116cdf0e10cSrcweir SwSortElement::~SwSortElement()
117cdf0e10cSrcweir {
118cdf0e10cSrcweir }
119cdf0e10cSrcweir
120cdf0e10cSrcweir
StrToDouble(const String & rStr) const121cdf0e10cSrcweir double SwSortElement::StrToDouble( const String& rStr ) const
122cdf0e10cSrcweir {
123cdf0e10cSrcweir if( !pLclData )
124cdf0e10cSrcweir pLclData = new LocaleDataWrapper(
125cdf0e10cSrcweir ::comphelper::getProcessServiceFactory(), *pLocale );
126cdf0e10cSrcweir
127cdf0e10cSrcweir rtl_math_ConversionStatus eStatus;
128cdf0e10cSrcweir sal_Int32 nEnd;
129cdf0e10cSrcweir double nRet = ::rtl::math::stringToDouble( rStr,
130cdf0e10cSrcweir pLclData->getNumDecimalSep().GetChar(0),
131cdf0e10cSrcweir pLclData->getNumThousandSep().GetChar(0),
132cdf0e10cSrcweir &eStatus, &nEnd );
133cdf0e10cSrcweir
134cdf0e10cSrcweir if( rtl_math_ConversionStatus_Ok != eStatus || nEnd == 0 )
135cdf0e10cSrcweir nRet = 0.0;
136cdf0e10cSrcweir return nRet;
137cdf0e10cSrcweir }
138cdf0e10cSrcweir
139cdf0e10cSrcweir /*--------------------------------------------------------------------
140cdf0e10cSrcweir Beschreibung: Operatoren zum Vergleichen
141cdf0e10cSrcweir --------------------------------------------------------------------*/
142cdf0e10cSrcweir
143cdf0e10cSrcweir
operator ==(const SwSortElement &)144cdf0e10cSrcweir sal_Bool SwSortElement::operator==(const SwSortElement& )
145cdf0e10cSrcweir {
146cdf0e10cSrcweir return sal_False;
147cdf0e10cSrcweir }
148cdf0e10cSrcweir
149cdf0e10cSrcweir /*--------------------------------------------------------------------
150cdf0e10cSrcweir Beschreibung: Kleiner-Operator fuers sortieren
151cdf0e10cSrcweir --------------------------------------------------------------------*/
152cdf0e10cSrcweir
operator <(const SwSortElement & rCmp)153cdf0e10cSrcweir sal_Bool SwSortElement::operator<(const SwSortElement& rCmp)
154cdf0e10cSrcweir {
155cdf0e10cSrcweir
156cdf0e10cSrcweir // der eigentliche Vergleich
157cdf0e10cSrcweir //
158cdf0e10cSrcweir for(sal_uInt16 nKey = 0; nKey < pOptions->aKeys.Count(); ++nKey)
159cdf0e10cSrcweir {
160cdf0e10cSrcweir const SwSortElement *pOrig, *pCmp;
161cdf0e10cSrcweir
162cdf0e10cSrcweir const SwSortKey* pSrtKey = pOptions->aKeys[ nKey ];
163cdf0e10cSrcweir if( pSrtKey->eSortOrder == SRT_ASCENDING )
164cdf0e10cSrcweir pOrig = this, pCmp = &rCmp;
165cdf0e10cSrcweir else
166cdf0e10cSrcweir pOrig = &rCmp, pCmp = this;
167cdf0e10cSrcweir
168cdf0e10cSrcweir if( pSrtKey->bIsNumeric )
169cdf0e10cSrcweir {
170cdf0e10cSrcweir double n1 = pOrig->GetValue( nKey );
171cdf0e10cSrcweir double n2 = pCmp->GetValue( nKey );
172cdf0e10cSrcweir
173cdf0e10cSrcweir if( n1 == n2 )
174cdf0e10cSrcweir continue;
175cdf0e10cSrcweir
176cdf0e10cSrcweir return n1 < n2;
177cdf0e10cSrcweir }
178cdf0e10cSrcweir else
179cdf0e10cSrcweir {
180cdf0e10cSrcweir if( !pLastAlgorithm || *pLastAlgorithm != pSrtKey->sSortType )
181cdf0e10cSrcweir {
182cdf0e10cSrcweir if( pLastAlgorithm )
183cdf0e10cSrcweir *pLastAlgorithm = pSrtKey->sSortType;
184cdf0e10cSrcweir else
185cdf0e10cSrcweir pLastAlgorithm = new String( pSrtKey->sSortType );
186cdf0e10cSrcweir pSortCollator->loadCollatorAlgorithm( *pLastAlgorithm,
187cdf0e10cSrcweir *pLocale,
188cdf0e10cSrcweir pOptions->bIgnoreCase ? SW_COLLATOR_IGNORES : 0 );
189cdf0e10cSrcweir }
190cdf0e10cSrcweir
191cdf0e10cSrcweir sal_Int32 nCmp = pSortCollator->compareString(
192cdf0e10cSrcweir pOrig->GetKey( nKey ), pCmp->GetKey( nKey ));
193cdf0e10cSrcweir if( 0 == nCmp )
194cdf0e10cSrcweir continue;
195cdf0e10cSrcweir
196cdf0e10cSrcweir return -1 == nCmp;
197cdf0e10cSrcweir }
198cdf0e10cSrcweir }
199cdf0e10cSrcweir return sal_False;
200cdf0e10cSrcweir }
201cdf0e10cSrcweir
GetValue(sal_uInt16 nKey) const202cdf0e10cSrcweir double SwSortElement::GetValue( sal_uInt16 nKey ) const
203cdf0e10cSrcweir {
204cdf0e10cSrcweir return StrToDouble( GetKey( nKey ));
205cdf0e10cSrcweir }
206cdf0e10cSrcweir
207cdf0e10cSrcweir /*--------------------------------------------------------------------
208cdf0e10cSrcweir Beschreibung: SortierElemente fuer Text
209cdf0e10cSrcweir --------------------------------------------------------------------*/
210cdf0e10cSrcweir
211cdf0e10cSrcweir
SwSortTxtElement(const SwNodeIndex & rPos)212cdf0e10cSrcweir SwSortTxtElement::SwSortTxtElement(const SwNodeIndex& rPos)
213cdf0e10cSrcweir : nOrg(rPos.GetIndex()), aPos(rPos)
214cdf0e10cSrcweir {
215cdf0e10cSrcweir }
216cdf0e10cSrcweir
217cdf0e10cSrcweir
~SwSortTxtElement()218cdf0e10cSrcweir SwSortTxtElement::~SwSortTxtElement()
219cdf0e10cSrcweir {
220cdf0e10cSrcweir }
221cdf0e10cSrcweir
222cdf0e10cSrcweir
223cdf0e10cSrcweir /*--------------------------------------------------------------------
224cdf0e10cSrcweir Beschreibung: Key ermitteln
225cdf0e10cSrcweir --------------------------------------------------------------------*/
226cdf0e10cSrcweir
227cdf0e10cSrcweir
GetKey(sal_uInt16 nId) const228cdf0e10cSrcweir String SwSortTxtElement::GetKey(sal_uInt16 nId) const
229cdf0e10cSrcweir {
230cdf0e10cSrcweir SwTxtNode* pTxtNd = aPos.GetNode().GetTxtNode();
231cdf0e10cSrcweir if( !pTxtNd )
232cdf0e10cSrcweir return aEmptyStr;
233cdf0e10cSrcweir
234cdf0e10cSrcweir // fuer TextNodes
235cdf0e10cSrcweir const String& rStr = pTxtNd->GetTxt();
236cdf0e10cSrcweir
237cdf0e10cSrcweir sal_Unicode nDeli = pOptions->cDeli;
238cdf0e10cSrcweir sal_uInt16 nDCount = pOptions->aKeys[nId]->nColumnId, i = 1;
239cdf0e10cSrcweir xub_StrLen nStart = 0;
240cdf0e10cSrcweir
241cdf0e10cSrcweir // Den Delimitter suchen
242cdf0e10cSrcweir while( nStart != STRING_NOTFOUND && i < nDCount)
243cdf0e10cSrcweir if( STRING_NOTFOUND != ( nStart = rStr.Search( nDeli, nStart ) ) )
244cdf0e10cSrcweir {
245cdf0e10cSrcweir nStart++;
246cdf0e10cSrcweir i++;
247cdf0e10cSrcweir }
248cdf0e10cSrcweir
249cdf0e10cSrcweir // naechsten Delimitter gefunden oder Ende des Strings und Kopieren
250cdf0e10cSrcweir xub_StrLen nEnd = rStr.Search( nDeli, nStart+1 );
251cdf0e10cSrcweir return rStr.Copy( nStart, nEnd-nStart );
252cdf0e10cSrcweir }
253cdf0e10cSrcweir
254cdf0e10cSrcweir
255cdf0e10cSrcweir /*--------------------------------------------------------------------
256cdf0e10cSrcweir Beschreibung: Sortier-Elemente fuer Tabellen
257cdf0e10cSrcweir --------------------------------------------------------------------*/
258cdf0e10cSrcweir
SwSortBoxElement(sal_uInt16 nRC)259cdf0e10cSrcweir SwSortBoxElement::SwSortBoxElement( sal_uInt16 nRC )
260cdf0e10cSrcweir : nRow( nRC )
261cdf0e10cSrcweir {
262cdf0e10cSrcweir }
263cdf0e10cSrcweir
264cdf0e10cSrcweir
~SwSortBoxElement()265cdf0e10cSrcweir SwSortBoxElement::~SwSortBoxElement()
266cdf0e10cSrcweir {
267cdf0e10cSrcweir }
268cdf0e10cSrcweir
269cdf0e10cSrcweir /*--------------------------------------------------------------------
270cdf0e10cSrcweir Beschreibung: Schluessel zu einer Zelle ermitteln
271cdf0e10cSrcweir --------------------------------------------------------------------*/
272cdf0e10cSrcweir
273cdf0e10cSrcweir
GetKey(sal_uInt16 nKey) const274cdf0e10cSrcweir String SwSortBoxElement::GetKey(sal_uInt16 nKey) const
275cdf0e10cSrcweir {
276cdf0e10cSrcweir const _FndBox* pFndBox;
277cdf0e10cSrcweir sal_uInt16 nCol = pOptions->aKeys[nKey]->nColumnId-1;
278cdf0e10cSrcweir
279cdf0e10cSrcweir if( SRT_ROWS == pOptions->eDirection )
280cdf0e10cSrcweir pFndBox = pBox->GetBox(nCol, nRow); // Zeilen sortieren
281cdf0e10cSrcweir else
282cdf0e10cSrcweir pFndBox = pBox->GetBox(nRow, nCol); // Spalten sortieren
283cdf0e10cSrcweir
284cdf0e10cSrcweir // Den Text rausfieseln
285cdf0e10cSrcweir String aRetStr;
286cdf0e10cSrcweir if( pFndBox )
287cdf0e10cSrcweir { // StartNode holen und ueberlesen
288cdf0e10cSrcweir const SwTableBox* pMyBox = pFndBox->GetBox();
289cdf0e10cSrcweir ASSERT(pMyBox, "Keine atomare Box");
290cdf0e10cSrcweir
291cdf0e10cSrcweir if( pMyBox->GetSttNd() )
292cdf0e10cSrcweir {
293cdf0e10cSrcweir // ueber alle TextNodes der Box
294cdf0e10cSrcweir const SwNode *pNd = 0, *pEndNd = pMyBox->GetSttNd()->EndOfSectionNode();
295cdf0e10cSrcweir for( sal_uLong nIdx = pMyBox->GetSttIdx() + 1; pNd != pEndNd; ++nIdx )
296cdf0e10cSrcweir if( ( pNd = pDoc->GetNodes()[ nIdx ])->IsTxtNode() )
297cdf0e10cSrcweir aRetStr += ((SwTxtNode*)pNd)->GetTxt();
298cdf0e10cSrcweir }
299cdf0e10cSrcweir }
300cdf0e10cSrcweir return aRetStr;
301cdf0e10cSrcweir }
302cdf0e10cSrcweir
GetValue(sal_uInt16 nKey) const303cdf0e10cSrcweir double SwSortBoxElement::GetValue( sal_uInt16 nKey ) const
304cdf0e10cSrcweir {
305cdf0e10cSrcweir const _FndBox* pFndBox;
306cdf0e10cSrcweir sal_uInt16 nCol = pOptions->aKeys[nKey]->nColumnId-1;
307cdf0e10cSrcweir
308cdf0e10cSrcweir if( SRT_ROWS == pOptions->eDirection )
309cdf0e10cSrcweir pFndBox = pBox->GetBox(nCol, nRow); // Zeilen sortieren
310cdf0e10cSrcweir else
311cdf0e10cSrcweir pFndBox = pBox->GetBox(nRow, nCol); // Spalten sortieren
312cdf0e10cSrcweir
313cdf0e10cSrcweir double nVal;
314cdf0e10cSrcweir if( pFndBox )
315cdf0e10cSrcweir {
316cdf0e10cSrcweir const SwFmt *pFmt = pFndBox->GetBox()->GetFrmFmt();
317cdf0e10cSrcweir if (pFmt->GetTblBoxNumFmt().GetValue() & NUMBERFORMAT_TEXT)
318cdf0e10cSrcweir nVal = SwSortElement::GetValue( nKey );
319cdf0e10cSrcweir else
320cdf0e10cSrcweir nVal = pFmt->GetTblBoxValue().GetValue();
321cdf0e10cSrcweir }
322cdf0e10cSrcweir else
323cdf0e10cSrcweir nVal = 0;
324cdf0e10cSrcweir
325cdf0e10cSrcweir return nVal;
326cdf0e10cSrcweir }
327cdf0e10cSrcweir
328cdf0e10cSrcweir /*--------------------------------------------------------------------
329cdf0e10cSrcweir Beschreibung: Text sortieren im Document
330cdf0e10cSrcweir --------------------------------------------------------------------*/
331cdf0e10cSrcweir
332cdf0e10cSrcweir
SortText(const SwPaM & rPaM,const SwSortOptions & rOpt)333cdf0e10cSrcweir sal_Bool SwDoc::SortText(const SwPaM& rPaM, const SwSortOptions& rOpt)
334cdf0e10cSrcweir {
335cdf0e10cSrcweir // pruefen ob Rahmen im Text
336cdf0e10cSrcweir const SwPosition *pStart = rPaM.Start(), *pEnd = rPaM.End();
337cdf0e10cSrcweir // Index auf den Start der Selektion
338cdf0e10cSrcweir
339cdf0e10cSrcweir for ( sal_uInt16 n = 0; n < GetSpzFrmFmts()->Count(); ++n )
340cdf0e10cSrcweir {
341cdf0e10cSrcweir SwFrmFmt *const pFmt = static_cast<SwFrmFmt*>((*GetSpzFrmFmts())[n]);
342cdf0e10cSrcweir SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
343cdf0e10cSrcweir SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
344cdf0e10cSrcweir
345cdf0e10cSrcweir if (pAPos && (FLY_AT_PARA == pAnchor->GetAnchorId()) &&
346cdf0e10cSrcweir pStart->nNode <= pAPos->nNode && pAPos->nNode <= pEnd->nNode )
347cdf0e10cSrcweir return sal_False;
348cdf0e10cSrcweir }
349cdf0e10cSrcweir
350cdf0e10cSrcweir // pruefe ob nur TextNodes in der Selection liegen
351cdf0e10cSrcweir {
352cdf0e10cSrcweir sal_uLong nStart = pStart->nNode.GetIndex(),
353cdf0e10cSrcweir nEnd = pEnd->nNode.GetIndex();
354cdf0e10cSrcweir while( nStart <= nEnd )
355cdf0e10cSrcweir // Iterieren ueber einen selektierten Bereich
356cdf0e10cSrcweir if( !GetNodes()[ nStart++ ]->IsTxtNode() )
357cdf0e10cSrcweir return sal_False;
358cdf0e10cSrcweir }
359cdf0e10cSrcweir
360cdf0e10cSrcweir bool const bUndo = GetIDocumentUndoRedo().DoesUndo();
361cdf0e10cSrcweir if( bUndo )
362cdf0e10cSrcweir {
363cdf0e10cSrcweir GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
364cdf0e10cSrcweir }
365cdf0e10cSrcweir
366cdf0e10cSrcweir SwPaM* pRedlPam = 0;
367cdf0e10cSrcweir SwUndoRedlineSort* pRedlUndo = 0;
368cdf0e10cSrcweir SwUndoSort* pUndoSort = 0;
369cdf0e10cSrcweir
370cdf0e10cSrcweir if( IsRedlineOn() || (!IsIgnoreRedline() && pRedlineTbl->Count() ))
371cdf0e10cSrcweir {
372cdf0e10cSrcweir pRedlPam = new SwPaM( pStart->nNode, pEnd->nNode, -1, 1 );
373cdf0e10cSrcweir SwCntntNode* pCNd = pRedlPam->GetCntntNode( sal_False );
374cdf0e10cSrcweir if( pCNd )
375cdf0e10cSrcweir pRedlPam->GetMark()->nContent = pCNd->Len();
376cdf0e10cSrcweir
377cdf0e10cSrcweir if( IsRedlineOn() && !IsShowOriginal( GetRedlineMode() ) )
378cdf0e10cSrcweir {
379cdf0e10cSrcweir if( bUndo )
380cdf0e10cSrcweir {
381cdf0e10cSrcweir pRedlUndo = new SwUndoRedlineSort( *pRedlPam,rOpt );
382cdf0e10cSrcweir GetIDocumentUndoRedo().DoUndo(false);
383cdf0e10cSrcweir }
384cdf0e10cSrcweir // erst den Bereich kopieren, dann
385cdf0e10cSrcweir SwNodeIndex aEndIdx( pEnd->nNode, 1 );
386cdf0e10cSrcweir SwNodeRange aRg( pStart->nNode, aEndIdx );
387cdf0e10cSrcweir GetNodes()._Copy( aRg, aEndIdx );
388cdf0e10cSrcweir
389cdf0e10cSrcweir // Bereich neu ist von pEnd->nNode+1 bis aEndIdx
390cdf0e10cSrcweir DeleteRedline( *pRedlPam, true, USHRT_MAX );
391cdf0e10cSrcweir
392cdf0e10cSrcweir pRedlPam->GetMark()->nNode.Assign( pEnd->nNode.GetNode(), 1 );
393cdf0e10cSrcweir pCNd = pRedlPam->GetCntntNode( sal_False );
394cdf0e10cSrcweir pRedlPam->GetMark()->nContent.Assign( pCNd, 0 );
395cdf0e10cSrcweir
396cdf0e10cSrcweir pRedlPam->GetPoint()->nNode.Assign( aEndIdx.GetNode() );
397cdf0e10cSrcweir pCNd = pRedlPam->GetCntntNode( sal_True );
398cdf0e10cSrcweir xub_StrLen nCLen = 0;
399cdf0e10cSrcweir if( !pCNd &&
400cdf0e10cSrcweir 0 != (pCNd = GetNodes()[ aEndIdx.GetIndex()-1 ]->GetCntntNode()))
401cdf0e10cSrcweir {
402cdf0e10cSrcweir nCLen = pCNd->Len();
403cdf0e10cSrcweir pRedlPam->GetPoint()->nNode.Assign( *pCNd );
404cdf0e10cSrcweir }
405cdf0e10cSrcweir pRedlPam->GetPoint()->nContent.Assign( pCNd, nCLen );
406cdf0e10cSrcweir
407cdf0e10cSrcweir if( pRedlUndo )
408cdf0e10cSrcweir pRedlUndo->SetValues( rPaM );
409cdf0e10cSrcweir }
410cdf0e10cSrcweir else
411cdf0e10cSrcweir {
412cdf0e10cSrcweir DeleteRedline( *pRedlPam, true, USHRT_MAX );
413cdf0e10cSrcweir delete pRedlPam, pRedlPam = 0;
414cdf0e10cSrcweir }
415cdf0e10cSrcweir }
416cdf0e10cSrcweir
417cdf0e10cSrcweir SwNodeIndex aStart(pStart->nNode);
418cdf0e10cSrcweir SwSortElement::Init( this, rOpt );
419cdf0e10cSrcweir SwSortElements aSortArr;
420cdf0e10cSrcweir while( aStart <= pEnd->nNode )
421cdf0e10cSrcweir {
422cdf0e10cSrcweir // Iterieren ueber einen selektierten Bereich
423cdf0e10cSrcweir SwSortTxtElement* pSE = new SwSortTxtElement( aStart );
424cdf0e10cSrcweir aSortArr.Insert(pSE);
425cdf0e10cSrcweir aStart++;
426cdf0e10cSrcweir }
427cdf0e10cSrcweir
428cdf0e10cSrcweir // Und jetzt der Akt: Verschieben von Nodes und immer schoen auf UNDO
429cdf0e10cSrcweir // achten
430cdf0e10cSrcweir //
431cdf0e10cSrcweir sal_uLong nBeg = pStart->nNode.GetIndex();
432cdf0e10cSrcweir SwNodeRange aRg( aStart, aStart );
433cdf0e10cSrcweir
434cdf0e10cSrcweir if( bUndo && !pRedlUndo )
435cdf0e10cSrcweir {
436cdf0e10cSrcweir pUndoSort = new SwUndoSort(rPaM, rOpt);
437cdf0e10cSrcweir GetIDocumentUndoRedo().AppendUndo(pUndoSort);
438cdf0e10cSrcweir }
439cdf0e10cSrcweir
440cdf0e10cSrcweir GetIDocumentUndoRedo().DoUndo(false);
441cdf0e10cSrcweir
442cdf0e10cSrcweir for ( sal_uInt16 n = 0; n < aSortArr.Count(); ++n )
443cdf0e10cSrcweir {
444cdf0e10cSrcweir SwSortTxtElement* pBox = (SwSortTxtElement*)aSortArr[n];
445cdf0e10cSrcweir aStart = nBeg + n;
446cdf0e10cSrcweir aRg.aStart = pBox->aPos.GetIndex();
447cdf0e10cSrcweir aRg.aEnd = aRg.aStart.GetIndex() + 1;
448cdf0e10cSrcweir
449cdf0e10cSrcweir // Nodes verschieben
450cdf0e10cSrcweir MoveNodeRange( aRg, aStart,
451cdf0e10cSrcweir IDocumentContentOperations::DOC_MOVEDEFAULT );
452cdf0e10cSrcweir
453cdf0e10cSrcweir // Undo Verschiebungen einpflegen
454cdf0e10cSrcweir if(pUndoSort)
455cdf0e10cSrcweir pUndoSort->Insert(pBox->nOrg, nBeg + n);
456cdf0e10cSrcweir }
457cdf0e10cSrcweir // Alle Elemente aus dem SortArray loeschen
458cdf0e10cSrcweir aSortArr.DeleteAndDestroy(0, aSortArr.Count());
459cdf0e10cSrcweir SwSortElement::Finit();
460cdf0e10cSrcweir
461cdf0e10cSrcweir if( pRedlPam )
462cdf0e10cSrcweir {
463cdf0e10cSrcweir if( pRedlUndo )
464cdf0e10cSrcweir {
465cdf0e10cSrcweir pRedlUndo->SetSaveRange( *pRedlPam );
466cdf0e10cSrcweir // UGLY: temp. enable Undo
467cdf0e10cSrcweir GetIDocumentUndoRedo().DoUndo(true);
468cdf0e10cSrcweir GetIDocumentUndoRedo().AppendUndo( pRedlUndo );
469cdf0e10cSrcweir GetIDocumentUndoRedo().DoUndo(false);
470cdf0e10cSrcweir }
471cdf0e10cSrcweir
472cdf0e10cSrcweir // nBeg is start of sorted range
473cdf0e10cSrcweir SwNodeIndex aSttIdx( GetNodes(), nBeg );
474cdf0e10cSrcweir
475cdf0e10cSrcweir // the copied range is deleted
476cdf0e10cSrcweir SwRedline *const pDeleteRedline(
477cdf0e10cSrcweir new SwRedline( nsRedlineType_t::REDLINE_DELETE, *pRedlPam ));
478cdf0e10cSrcweir
479cdf0e10cSrcweir // pRedlPam points to nodes that may be deleted (hidden) by
480cdf0e10cSrcweir // AppendRedline, so adjust it beforehand to prevent ASSERT
481cdf0e10cSrcweir pRedlPam->GetPoint()->nNode = aSttIdx;
482cdf0e10cSrcweir SwCntntNode* pCNd = aSttIdx.GetNode().GetCntntNode();
483cdf0e10cSrcweir pRedlPam->GetPoint()->nContent.Assign( pCNd, 0 );
484cdf0e10cSrcweir
485cdf0e10cSrcweir AppendRedline(pDeleteRedline, true);
486cdf0e10cSrcweir
487cdf0e10cSrcweir // the sorted range is inserted
488cdf0e10cSrcweir AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, *pRedlPam ), true);
489cdf0e10cSrcweir
490cdf0e10cSrcweir if( pRedlUndo )
491cdf0e10cSrcweir {
492cdf0e10cSrcweir SwNodeIndex aInsEndIdx( pRedlPam->GetMark()->nNode, -1 );
493cdf0e10cSrcweir pRedlPam->GetMark()->nNode = aInsEndIdx;
494cdf0e10cSrcweir SwCntntNode *const pPrevNode =
495cdf0e10cSrcweir pRedlPam->GetMark()->nNode.GetNode().GetCntntNode();
496cdf0e10cSrcweir pRedlPam->GetMark()->nContent.Assign( pPrevNode, pPrevNode->Len() );
497cdf0e10cSrcweir
498cdf0e10cSrcweir pRedlUndo->SetValues( *pRedlPam );
499cdf0e10cSrcweir }
500cdf0e10cSrcweir
501cdf0e10cSrcweir if( pRedlUndo )
502cdf0e10cSrcweir pRedlUndo->SetOffset( aSttIdx );
503cdf0e10cSrcweir
504cdf0e10cSrcweir delete pRedlPam, pRedlPam = 0;
505cdf0e10cSrcweir }
506cdf0e10cSrcweir GetIDocumentUndoRedo().DoUndo( bUndo );
507cdf0e10cSrcweir if( bUndo )
508cdf0e10cSrcweir {
509cdf0e10cSrcweir GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
510cdf0e10cSrcweir }
511cdf0e10cSrcweir
512cdf0e10cSrcweir return sal_True;
513cdf0e10cSrcweir }
514cdf0e10cSrcweir
515cdf0e10cSrcweir /*--------------------------------------------------------------------
516cdf0e10cSrcweir Beschreibung: Tabelle sortieren im Document
517cdf0e10cSrcweir --------------------------------------------------------------------*/
518cdf0e10cSrcweir
SortTbl(const SwSelBoxes & rBoxes,const SwSortOptions & rOpt)519cdf0e10cSrcweir sal_Bool SwDoc::SortTbl(const SwSelBoxes& rBoxes, const SwSortOptions& rOpt)
520cdf0e10cSrcweir {
521cdf0e10cSrcweir // uebers SwDoc fuer Undo !!
522cdf0e10cSrcweir ASSERT( rBoxes.Count(), "keine gueltige Box-Liste" );
523cdf0e10cSrcweir SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
524cdf0e10cSrcweir if( !pTblNd )
525cdf0e10cSrcweir return sal_False;
526cdf0e10cSrcweir
527cdf0e10cSrcweir // Auf gehts sortieren
528cdf0e10cSrcweir // suche alle Boxen / Lines
529cdf0e10cSrcweir _FndBox aFndBox( 0, 0 );
530cdf0e10cSrcweir {
531cdf0e10cSrcweir _FndPara aPara( rBoxes, &aFndBox );
532cdf0e10cSrcweir pTblNd->GetTable().GetTabLines().ForEach( &_FndLineCopyCol, &aPara );;
533cdf0e10cSrcweir }
534cdf0e10cSrcweir
535cdf0e10cSrcweir if(!aFndBox.GetLines().Count())
536cdf0e10cSrcweir return sal_False;
537cdf0e10cSrcweir
538cdf0e10cSrcweir if( !IsIgnoreRedline() && GetRedlineTbl().Count() )
539cdf0e10cSrcweir DeleteRedline( *pTblNd, true, USHRT_MAX );
540cdf0e10cSrcweir
541cdf0e10cSrcweir sal_uInt16 nStart = 0;
542cdf0e10cSrcweir if( pTblNd->GetTable().GetRowsToRepeat() > 0 && rOpt.eDirection == SRT_ROWS )
543cdf0e10cSrcweir {
544cdf0e10cSrcweir // Oberste seleketierte Zeile
545cdf0e10cSrcweir _FndLines& rLines = aFndBox.GetLines();
546cdf0e10cSrcweir
547cdf0e10cSrcweir while( nStart < rLines.Count() )
548cdf0e10cSrcweir {
549cdf0e10cSrcweir // Verschachtelung durch Split Merge beachten,
550cdf0e10cSrcweir // die oberste rausholen
551cdf0e10cSrcweir SwTableLine* pLine = rLines[nStart]->GetLine();
552cdf0e10cSrcweir while ( pLine->GetUpper() )
553cdf0e10cSrcweir pLine = pLine->GetUpper()->GetUpper();
554cdf0e10cSrcweir
555cdf0e10cSrcweir if( pTblNd->GetTable().IsHeadline( *pLine ) )
556cdf0e10cSrcweir nStart++;
557cdf0e10cSrcweir else
558cdf0e10cSrcweir break;
559cdf0e10cSrcweir }
560cdf0e10cSrcweir // Alle selektierten in der HeaderLine ? -> kein Offset
561cdf0e10cSrcweir if( nStart == rLines.Count() )
562cdf0e10cSrcweir nStart = 0;
563cdf0e10cSrcweir }
564cdf0e10cSrcweir
565cdf0e10cSrcweir // umschalten auf relative Formeln
566cdf0e10cSrcweir SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
567cdf0e10cSrcweir aMsgHnt.eFlags = TBL_RELBOXNAME;
568cdf0e10cSrcweir UpdateTblFlds( &aMsgHnt );
569cdf0e10cSrcweir
570cdf0e10cSrcweir // Tabelle als flache Array-Struktur
571cdf0e10cSrcweir FlatFndBox aFlatBox(this, aFndBox);
572cdf0e10cSrcweir
573cdf0e10cSrcweir if(!aFlatBox.IsSymmetric())
574cdf0e10cSrcweir return sal_False;
575cdf0e10cSrcweir
576cdf0e10cSrcweir // MIB 9.7.97: HTML-Layout loeschen
577cdf0e10cSrcweir pTblNd->GetTable().SetHTMLTableLayout( 0 );
578cdf0e10cSrcweir
579cdf0e10cSrcweir // --> FME 2004-11-26 #i37739# A simple 'MakeFrms' after the node sorting
580cdf0e10cSrcweir // does not work if the table is inside a frame and has no prev/next.
581cdf0e10cSrcweir SwNode2Layout aNode2Layout( *pTblNd );
582cdf0e10cSrcweir // <--
583cdf0e10cSrcweir
584cdf0e10cSrcweir // loesche die Frames der Tabelle
585cdf0e10cSrcweir pTblNd->DelFrms();
586cdf0e10cSrcweir // ? TL_CHART2: ?
587cdf0e10cSrcweir
588cdf0e10cSrcweir SwUndoSort* pUndoSort = 0;
589cdf0e10cSrcweir if (GetIDocumentUndoRedo().DoesUndo())
590cdf0e10cSrcweir {
591cdf0e10cSrcweir pUndoSort = new SwUndoSort( rBoxes[0]->GetSttIdx(),
592cdf0e10cSrcweir rBoxes[rBoxes.Count()-1]->GetSttIdx(),
593cdf0e10cSrcweir *pTblNd, rOpt, aFlatBox.HasItemSets() );
594cdf0e10cSrcweir GetIDocumentUndoRedo().AppendUndo(pUndoSort);
595cdf0e10cSrcweir }
596cdf0e10cSrcweir ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
597cdf0e10cSrcweir
598cdf0e10cSrcweir // SchluesselElemente einsortieren
599cdf0e10cSrcweir sal_uInt16 nCount = (rOpt.eDirection == SRT_ROWS) ?
600cdf0e10cSrcweir aFlatBox.GetRows() : aFlatBox.GetCols();
601cdf0e10cSrcweir
602cdf0e10cSrcweir // SortList nach Schluessel sortieren
603cdf0e10cSrcweir SwSortElement::Init( this, rOpt, &aFlatBox );
604cdf0e10cSrcweir SwSortElements aSortList;
605cdf0e10cSrcweir
606cdf0e10cSrcweir // wenn die HeaderLine wiederholt wird und die
607cdf0e10cSrcweir // Zeilen sortiert werden 1.Zeile nicht mitsortieren
608cdf0e10cSrcweir sal_uInt16 i;
609cdf0e10cSrcweir
610cdf0e10cSrcweir for( i = nStart; i < nCount; ++i)
611cdf0e10cSrcweir {
612cdf0e10cSrcweir SwSortBoxElement* pEle = new SwSortBoxElement( i );
613cdf0e10cSrcweir aSortList.Insert(pEle);
614cdf0e10cSrcweir }
615cdf0e10cSrcweir
616cdf0e10cSrcweir // nach Sortierung verschieben
617cdf0e10cSrcweir SwMovedBoxes aMovedList;
618cdf0e10cSrcweir for(i=0; i < aSortList.Count(); ++i)
619cdf0e10cSrcweir {
620cdf0e10cSrcweir SwSortBoxElement* pBox = (SwSortBoxElement*)aSortList[i];
621cdf0e10cSrcweir if(rOpt.eDirection == SRT_ROWS)
622cdf0e10cSrcweir MoveRow(this, aFlatBox, pBox->nRow, i + nStart, aMovedList, pUndoSort);
623cdf0e10cSrcweir else
624cdf0e10cSrcweir MoveCol(this, aFlatBox, pBox->nRow, i + nStart, aMovedList, pUndoSort);
625cdf0e10cSrcweir }
626cdf0e10cSrcweir
627cdf0e10cSrcweir // Restore table frames:
628cdf0e10cSrcweir // --> FME 2004-11-26 #i37739# A simple 'MakeFrms' after the node sorting
629cdf0e10cSrcweir // does not work if the table is inside a frame and has no prev/next.
630cdf0e10cSrcweir const sal_uLong nIdx = pTblNd->GetIndex();
631cdf0e10cSrcweir aNode2Layout.RestoreUpperFrms( GetNodes(), nIdx, nIdx + 1 );
632cdf0e10cSrcweir // <--
633cdf0e10cSrcweir
634cdf0e10cSrcweir // TL_CHART2: need to inform chart of probably changed cell names
635cdf0e10cSrcweir UpdateCharts( pTblNd->GetTable().GetFrmFmt()->GetName() );
636cdf0e10cSrcweir
637cdf0e10cSrcweir // Alle Elemente aus dem SortArray loeschen
638cdf0e10cSrcweir aSortList.DeleteAndDestroy( 0, aSortList.Count() );
639cdf0e10cSrcweir SwSortElement::Finit();
640cdf0e10cSrcweir
641cdf0e10cSrcweir SetModified();
642cdf0e10cSrcweir return sal_True;
643cdf0e10cSrcweir }
644cdf0e10cSrcweir
645cdf0e10cSrcweir /*--------------------------------------------------------------------
646cdf0e10cSrcweir Beschreibung: Zeilenweise verschieben
647cdf0e10cSrcweir --------------------------------------------------------------------*/
648cdf0e10cSrcweir
649cdf0e10cSrcweir
MoveRow(SwDoc * pDoc,const FlatFndBox & rBox,sal_uInt16 nS,sal_uInt16 nT,SwMovedBoxes & rMovedList,SwUndoSort * pUD)650cdf0e10cSrcweir void MoveRow(SwDoc* pDoc, const FlatFndBox& rBox, sal_uInt16 nS, sal_uInt16 nT,
651cdf0e10cSrcweir SwMovedBoxes& rMovedList, SwUndoSort* pUD)
652cdf0e10cSrcweir {
653cdf0e10cSrcweir for( sal_uInt16 i=0; i < rBox.GetCols(); ++i )
654cdf0e10cSrcweir { // Alte Zellen-Pos bestimmen und merken
655cdf0e10cSrcweir const _FndBox* pSource = rBox.GetBox(i, nS);
656cdf0e10cSrcweir
657cdf0e10cSrcweir // neue Zellen-Pos
658cdf0e10cSrcweir const _FndBox* pTarget = rBox.GetBox(i, nT);
659cdf0e10cSrcweir
660cdf0e10cSrcweir const SwTableBox* pT = pTarget->GetBox();
661cdf0e10cSrcweir const SwTableBox* pS = pSource->GetBox();
662cdf0e10cSrcweir
663cdf0e10cSrcweir sal_Bool bMoved = rMovedList.GetPos(pT) != USHRT_MAX;
664cdf0e10cSrcweir
665cdf0e10cSrcweir // und verschieben
666cdf0e10cSrcweir MoveCell(pDoc, pS, pT, bMoved, pUD);
667cdf0e10cSrcweir
668cdf0e10cSrcweir rMovedList.Insert(pS, rMovedList.Count() );
669cdf0e10cSrcweir
670cdf0e10cSrcweir if( pS != pT )
671cdf0e10cSrcweir {
672cdf0e10cSrcweir SwFrmFmt* pTFmt = (SwFrmFmt*)pT->GetFrmFmt();
673cdf0e10cSrcweir const SfxItemSet* pSSet = rBox.GetItemSet( i, nS );
674cdf0e10cSrcweir
675cdf0e10cSrcweir if( pSSet ||
676cdf0e10cSrcweir SFX_ITEM_SET == pTFmt->GetItemState( RES_BOXATR_FORMAT ) ||
677cdf0e10cSrcweir SFX_ITEM_SET == pTFmt->GetItemState( RES_BOXATR_FORMULA ) ||
678cdf0e10cSrcweir SFX_ITEM_SET == pTFmt->GetItemState( RES_BOXATR_VALUE ) )
679cdf0e10cSrcweir {
680cdf0e10cSrcweir pTFmt = ((SwTableBox*)pT)->ClaimFrmFmt();
681cdf0e10cSrcweir pTFmt->LockModify();
682cdf0e10cSrcweir if( pTFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE ) )
683cdf0e10cSrcweir pTFmt->ResetFmtAttr( RES_VERT_ORIENT );
684cdf0e10cSrcweir
685cdf0e10cSrcweir if( pSSet )
686cdf0e10cSrcweir pTFmt->SetFmtAttr( *pSSet );
687cdf0e10cSrcweir pTFmt->UnlockModify();
688cdf0e10cSrcweir }
689cdf0e10cSrcweir }
690cdf0e10cSrcweir }
691cdf0e10cSrcweir }
692cdf0e10cSrcweir
693cdf0e10cSrcweir /*--------------------------------------------------------------------
694cdf0e10cSrcweir Beschreibung: Spaltenweise verschieben
695cdf0e10cSrcweir --------------------------------------------------------------------*/
696cdf0e10cSrcweir
697cdf0e10cSrcweir
MoveCol(SwDoc * pDoc,const FlatFndBox & rBox,sal_uInt16 nS,sal_uInt16 nT,SwMovedBoxes & rMovedList,SwUndoSort * pUD)698cdf0e10cSrcweir void MoveCol(SwDoc* pDoc, const FlatFndBox& rBox, sal_uInt16 nS, sal_uInt16 nT,
699cdf0e10cSrcweir SwMovedBoxes& rMovedList, SwUndoSort* pUD)
700cdf0e10cSrcweir {
701cdf0e10cSrcweir for(sal_uInt16 i=0; i < rBox.GetRows(); ++i)
702cdf0e10cSrcweir { // Alte Zellen-Pos bestimmen und merken
703cdf0e10cSrcweir const _FndBox* pSource = rBox.GetBox(nS, i);
704cdf0e10cSrcweir
705cdf0e10cSrcweir // neue Zellen-Pos
706cdf0e10cSrcweir const _FndBox* pTarget = rBox.GetBox(nT, i);
707cdf0e10cSrcweir
708cdf0e10cSrcweir // und verschieben
709cdf0e10cSrcweir const SwTableBox* pT = pTarget->GetBox();
710cdf0e10cSrcweir const SwTableBox* pS = pSource->GetBox();
711cdf0e10cSrcweir
712cdf0e10cSrcweir // und verschieben
713cdf0e10cSrcweir sal_Bool bMoved = rMovedList.GetPos(pT) != USHRT_MAX;
714cdf0e10cSrcweir MoveCell(pDoc, pS, pT, bMoved, pUD);
715cdf0e10cSrcweir
716cdf0e10cSrcweir rMovedList.Insert(pS, rMovedList.Count() );
717cdf0e10cSrcweir
718cdf0e10cSrcweir if( pS != pT )
719cdf0e10cSrcweir {
720cdf0e10cSrcweir SwFrmFmt* pTFmt = (SwFrmFmt*)pT->GetFrmFmt();
721cdf0e10cSrcweir const SfxItemSet* pSSet = rBox.GetItemSet( nS, i );
722cdf0e10cSrcweir
723cdf0e10cSrcweir if( pSSet ||
724cdf0e10cSrcweir SFX_ITEM_SET == pTFmt->GetItemState( RES_BOXATR_FORMAT ) ||
725cdf0e10cSrcweir SFX_ITEM_SET == pTFmt->GetItemState( RES_BOXATR_FORMULA ) ||
726cdf0e10cSrcweir SFX_ITEM_SET == pTFmt->GetItemState( RES_BOXATR_VALUE ) )
727cdf0e10cSrcweir {
728cdf0e10cSrcweir pTFmt = ((SwTableBox*)pT)->ClaimFrmFmt();
729cdf0e10cSrcweir pTFmt->LockModify();
730cdf0e10cSrcweir if( pTFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE ) )
731cdf0e10cSrcweir pTFmt->ResetFmtAttr( RES_VERT_ORIENT );
732cdf0e10cSrcweir
733cdf0e10cSrcweir if( pSSet )
734cdf0e10cSrcweir pTFmt->SetFmtAttr( *pSSet );
735cdf0e10cSrcweir pTFmt->UnlockModify();
736cdf0e10cSrcweir }
737cdf0e10cSrcweir }
738cdf0e10cSrcweir }
739cdf0e10cSrcweir }
740cdf0e10cSrcweir
741cdf0e10cSrcweir /*--------------------------------------------------------------------
742cdf0e10cSrcweir Beschreibung: Eine einzelne Zelle verschieben
743cdf0e10cSrcweir --------------------------------------------------------------------*/
744cdf0e10cSrcweir
745cdf0e10cSrcweir
MoveCell(SwDoc * pDoc,const SwTableBox * pSource,const SwTableBox * pTar,sal_Bool bMovedBefore,SwUndoSort * pUD)746cdf0e10cSrcweir void MoveCell(SwDoc* pDoc, const SwTableBox* pSource, const SwTableBox* pTar,
747cdf0e10cSrcweir sal_Bool bMovedBefore, SwUndoSort* pUD)
748cdf0e10cSrcweir {
749cdf0e10cSrcweir ASSERT(pSource && pTar,"Fehlende Quelle oder Ziel");
750cdf0e10cSrcweir
751cdf0e10cSrcweir if(pSource == pTar)
752cdf0e10cSrcweir return;
753cdf0e10cSrcweir
754cdf0e10cSrcweir if(pUD)
755cdf0e10cSrcweir pUD->Insert( pSource->GetName(), pTar->GetName() );
756cdf0e10cSrcweir
757cdf0e10cSrcweir // Pam Quelle auf den ersten ContentNode setzen
758cdf0e10cSrcweir SwNodeRange aRg( *pSource->GetSttNd(), 0, *pSource->GetSttNd() );
759cdf0e10cSrcweir SwNode* pNd = pDoc->GetNodes().GoNext( &aRg.aStart );
760cdf0e10cSrcweir
761cdf0e10cSrcweir // wurde die Zelle (Source) nicht verschoben
762cdf0e10cSrcweir // -> einen Leer-Node einfuegen und den Rest verschieben
763cdf0e10cSrcweir // ansonsten steht der Mark auf dem ersten Content-Node
764cdf0e10cSrcweir if( pNd->StartOfSectionNode() == pSource->GetSttNd() )
765cdf0e10cSrcweir pNd = pDoc->GetNodes().MakeTxtNode( aRg.aStart,
766cdf0e10cSrcweir (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() );
767cdf0e10cSrcweir aRg.aEnd = *pNd->EndOfSectionNode();
768cdf0e10cSrcweir
769cdf0e10cSrcweir // Ist das Ziel leer(1 leerer Node vorhanden)
770cdf0e10cSrcweir // -> diesen loeschen und move
771cdf0e10cSrcweir // Ziel
772cdf0e10cSrcweir SwNodeIndex aTar( *pTar->GetSttNd() );
773cdf0e10cSrcweir pNd = pDoc->GetNodes().GoNext( &aTar ); // naechsten ContentNode
774cdf0e10cSrcweir sal_uLong nCount = pNd->EndOfSectionIndex() - pNd->StartOfSectionIndex();
775cdf0e10cSrcweir
776cdf0e10cSrcweir sal_Bool bDelFirst = sal_False;
777cdf0e10cSrcweir if( nCount == 2 )
778cdf0e10cSrcweir {
779cdf0e10cSrcweir ASSERT( pNd->GetCntntNode(), "Kein ContentNode");
780cdf0e10cSrcweir bDelFirst = !pNd->GetCntntNode()->Len() && bMovedBefore;
781cdf0e10cSrcweir }
782cdf0e10cSrcweir
783cdf0e10cSrcweir if(!bDelFirst)
784cdf0e10cSrcweir { // Es besteht schon Inhalt -> alter I n h a l t Section Down
785cdf0e10cSrcweir SwNodeRange aRgTar( aTar.GetNode(), 0, *pNd->EndOfSectionNode() );
786cdf0e10cSrcweir pDoc->GetNodes().SectionDown( &aRgTar );
787cdf0e10cSrcweir }
788cdf0e10cSrcweir
789cdf0e10cSrcweir // Einfuegen der Source
790cdf0e10cSrcweir SwNodeIndex aIns( *pTar->GetSttNd()->EndOfSectionNode() );
791cdf0e10cSrcweir pDoc->MoveNodeRange( aRg, aIns,
792cdf0e10cSrcweir IDocumentContentOperations::DOC_MOVEDEFAULT );
793cdf0e10cSrcweir
794cdf0e10cSrcweir // Falls erster Node leer -> weg damit
795cdf0e10cSrcweir if(bDelFirst)
796cdf0e10cSrcweir pDoc->GetNodes().Delete( aTar, 1 );
797cdf0e10cSrcweir }
798cdf0e10cSrcweir
799cdf0e10cSrcweir /*--------------------------------------------------------------------
800cdf0e10cSrcweir Beschreibung: Zweidimensionales Array aus FndBoxes generieren
801cdf0e10cSrcweir --------------------------------------------------------------------*/
802cdf0e10cSrcweir
803cdf0e10cSrcweir
FlatFndBox(SwDoc * pDocPtr,const _FndBox & rBox)804cdf0e10cSrcweir FlatFndBox::FlatFndBox(SwDoc* pDocPtr, const _FndBox& rBox) :
805cdf0e10cSrcweir pDoc(pDocPtr),
806cdf0e10cSrcweir rBoxRef(rBox),
807cdf0e10cSrcweir pArr(0),
808cdf0e10cSrcweir ppItemSets(0),
809cdf0e10cSrcweir nRow(0),
810cdf0e10cSrcweir nCol(0)
811cdf0e10cSrcweir { // Ist das Array symmetrisch
812cdf0e10cSrcweir if((bSym = CheckLineSymmetry(rBoxRef)) != 0)
813cdf0e10cSrcweir {
814cdf0e10cSrcweir // Spalten/Reihen-Anzahl ermitteln
815cdf0e10cSrcweir nCols = GetColCount(rBoxRef);
816cdf0e10cSrcweir nRows = GetRowCount(rBoxRef);
817cdf0e10cSrcweir
818cdf0e10cSrcweir // lineares Array anlegen
819cdf0e10cSrcweir pArr = new _FndBoxPtr[ nRows * nCols ];
820cdf0e10cSrcweir _FndBox** ppTmp = (_FndBox**)pArr;
821cdf0e10cSrcweir memset( ppTmp, 0, sizeof(_FndBoxPtr) * nRows * nCols );
822cdf0e10cSrcweir
823cdf0e10cSrcweir
824cdf0e10cSrcweir FillFlat( rBoxRef );
825cdf0e10cSrcweir }
826cdf0e10cSrcweir }
827cdf0e10cSrcweir
828cdf0e10cSrcweir
~FlatFndBox()829cdf0e10cSrcweir FlatFndBox::~FlatFndBox()
830cdf0e10cSrcweir {
831cdf0e10cSrcweir _FndBox** ppTmp = (_FndBox**)pArr;
832cdf0e10cSrcweir delete [] ppTmp;
833cdf0e10cSrcweir
834cdf0e10cSrcweir if( ppItemSets )
835cdf0e10cSrcweir delete [] ppItemSets;
836cdf0e10cSrcweir }
837cdf0e10cSrcweir
838cdf0e10cSrcweir /*--------------------------------------------------------------------
839cdf0e10cSrcweir Beschreibung: Alle Lines einer Box muessen gleichviel Boxen haben
840cdf0e10cSrcweir --------------------------------------------------------------------*/
841cdf0e10cSrcweir
842cdf0e10cSrcweir
CheckLineSymmetry(const _FndBox & rBox)843cdf0e10cSrcweir sal_Bool FlatFndBox::CheckLineSymmetry(const _FndBox& rBox)
844cdf0e10cSrcweir {
845cdf0e10cSrcweir const _FndLines &rLines = rBox.GetLines();
846cdf0e10cSrcweir sal_uInt16 nBoxes(0);
847cdf0e10cSrcweir
848cdf0e10cSrcweir // UeberLines iterieren
849cdf0e10cSrcweir for(sal_uInt16 i=0; i < rLines.Count(); ++i)
850cdf0e10cSrcweir { // Die Boxen einer Line
851cdf0e10cSrcweir _FndLine* pLn = rLines[i];
852cdf0e10cSrcweir const _FndBoxes& rBoxes = pLn->GetBoxes();
853cdf0e10cSrcweir
854cdf0e10cSrcweir // Anzahl der Boxen aller Lines ungleich -> keine Symmetrie
855cdf0e10cSrcweir if( i && nBoxes != rBoxes.Count())
856cdf0e10cSrcweir return sal_False;
857cdf0e10cSrcweir
858cdf0e10cSrcweir nBoxes = rBoxes.Count();
859cdf0e10cSrcweir if( !CheckBoxSymmetry( *pLn ) )
860cdf0e10cSrcweir return sal_False;
861cdf0e10cSrcweir }
862cdf0e10cSrcweir return sal_True;
863cdf0e10cSrcweir }
864cdf0e10cSrcweir
865cdf0e10cSrcweir /*--------------------------------------------------------------------
866cdf0e10cSrcweir Beschreibung: Box auf Symmetrie pruefen
867cdf0e10cSrcweir Alle Boxen einer Line muessen gleichviele Lines haben
868cdf0e10cSrcweir --------------------------------------------------------------------*/
869cdf0e10cSrcweir
870cdf0e10cSrcweir
CheckBoxSymmetry(const _FndLine & rLn)871cdf0e10cSrcweir sal_Bool FlatFndBox::CheckBoxSymmetry(const _FndLine& rLn)
872cdf0e10cSrcweir {
873cdf0e10cSrcweir const _FndBoxes &rBoxes = rLn.GetBoxes();
874cdf0e10cSrcweir sal_uInt16 nLines(0);
875cdf0e10cSrcweir
876cdf0e10cSrcweir // Ueber Boxes iterieren
877cdf0e10cSrcweir for(sal_uInt16 i=0; i < rBoxes.Count(); ++i)
878cdf0e10cSrcweir { // Die Boxen einer Line
879cdf0e10cSrcweir _FndBox* pBox = rBoxes[i];
880cdf0e10cSrcweir const _FndLines& rLines = pBox->GetLines();
881cdf0e10cSrcweir
882cdf0e10cSrcweir // Anzahl der Boxen aller Lines ungleich -> keine Symmetrie
883cdf0e10cSrcweir if( i && nLines != rLines.Count() )
884cdf0e10cSrcweir return sal_False;
885cdf0e10cSrcweir
886cdf0e10cSrcweir nLines = rLines.Count();
887cdf0e10cSrcweir if( nLines && !CheckLineSymmetry( *pBox ) )
888cdf0e10cSrcweir return sal_False;
889cdf0e10cSrcweir }
890cdf0e10cSrcweir return sal_True;
891cdf0e10cSrcweir }
892cdf0e10cSrcweir
893cdf0e10cSrcweir /*--------------------------------------------------------------------
894cdf0e10cSrcweir Beschreibung: max Anzahl der Spalten (Boxes)
895cdf0e10cSrcweir --------------------------------------------------------------------*/
896cdf0e10cSrcweir
897cdf0e10cSrcweir
GetColCount(const _FndBox & rBox)898cdf0e10cSrcweir sal_uInt16 FlatFndBox::GetColCount(const _FndBox& rBox)
899cdf0e10cSrcweir {
900cdf0e10cSrcweir const _FndLines& rLines = rBox.GetLines();
901cdf0e10cSrcweir // Ueber Lines iterieren
902cdf0e10cSrcweir if( !rLines.Count() )
903cdf0e10cSrcweir return 1;
904cdf0e10cSrcweir
905cdf0e10cSrcweir sal_uInt16 nSum = 0;
906cdf0e10cSrcweir for( sal_uInt16 i=0; i < rLines.Count(); ++i )
907cdf0e10cSrcweir {
908cdf0e10cSrcweir // Die Boxen einer Line
909cdf0e10cSrcweir sal_uInt16 nCount = 0;
910cdf0e10cSrcweir const _FndBoxes& rBoxes = rLines[i]->GetBoxes();
911cdf0e10cSrcweir for( sal_uInt16 j=0; j < rBoxes.Count(); ++j )
912cdf0e10cSrcweir // Rekursiv wirder ueber die Lines Iterieren
913cdf0e10cSrcweir nCount += rBoxes[j]->GetLines().Count()
914cdf0e10cSrcweir ? GetColCount(*rBoxes[j]) : 1;
915cdf0e10cSrcweir
916cdf0e10cSrcweir if( nSum < nCount )
917cdf0e10cSrcweir nSum = nCount;
918cdf0e10cSrcweir }
919cdf0e10cSrcweir return nSum;
920cdf0e10cSrcweir }
921cdf0e10cSrcweir
922cdf0e10cSrcweir /*--------------------------------------------------------------------
923cdf0e10cSrcweir Beschreibung: max Anzahl der Zeilen (Lines)
924cdf0e10cSrcweir --------------------------------------------------------------------*/
925cdf0e10cSrcweir
926cdf0e10cSrcweir
GetRowCount(const _FndBox & rBox)927cdf0e10cSrcweir sal_uInt16 FlatFndBox::GetRowCount(const _FndBox& rBox)
928cdf0e10cSrcweir {
929cdf0e10cSrcweir const _FndLines& rLines = rBox.GetLines();
930cdf0e10cSrcweir if( !rLines.Count() )
931cdf0e10cSrcweir return 1;
932cdf0e10cSrcweir
933cdf0e10cSrcweir sal_uInt16 nLines = 0;
934cdf0e10cSrcweir for(sal_uInt16 i=0; i < rLines.Count(); ++i)
935cdf0e10cSrcweir { // Die Boxen einer Line
936cdf0e10cSrcweir const _FndBoxes& rBoxes = rLines[i]->GetBoxes();
937cdf0e10cSrcweir sal_uInt16 nLn = 1;
938cdf0e10cSrcweir for(sal_uInt16 j=0; j < rBoxes.Count(); ++j)
939cdf0e10cSrcweir if( rBoxes[j]->GetLines().Count() )
940cdf0e10cSrcweir // Rekursiv ueber die Lines Iterieren
941cdf0e10cSrcweir nLn = Max(GetRowCount(*rBoxes[j]), nLn);
942cdf0e10cSrcweir
943cdf0e10cSrcweir nLines = nLines + nLn;
944cdf0e10cSrcweir }
945cdf0e10cSrcweir return nLines;
946cdf0e10cSrcweir }
947cdf0e10cSrcweir
948cdf0e10cSrcweir /*--------------------------------------------------------------------
949cdf0e10cSrcweir Beschreibung: lineares Array aus atomaren FndBoxes erzeugen
950cdf0e10cSrcweir --------------------------------------------------------------------*/
951cdf0e10cSrcweir
952cdf0e10cSrcweir
FillFlat(const _FndBox & rBox,sal_Bool bLastBox)953cdf0e10cSrcweir void FlatFndBox::FillFlat(const _FndBox& rBox, sal_Bool bLastBox)
954cdf0e10cSrcweir {
955cdf0e10cSrcweir sal_Bool bModRow = sal_False;
956cdf0e10cSrcweir const _FndLines& rLines = rBox.GetLines();
957cdf0e10cSrcweir
958cdf0e10cSrcweir // Ueber Lines iterieren
959cdf0e10cSrcweir sal_uInt16 nOldRow = nRow;
960cdf0e10cSrcweir for( sal_uInt16 i=0; i < rLines.Count(); ++i )
961cdf0e10cSrcweir {
962cdf0e10cSrcweir // Die Boxen einer Line
963cdf0e10cSrcweir const _FndBoxes& rBoxes = rLines[i]->GetBoxes();
964cdf0e10cSrcweir sal_uInt16 nOldCol = nCol;
965cdf0e10cSrcweir for( sal_uInt16 j = 0; j < rBoxes.Count(); ++j )
966cdf0e10cSrcweir {
967cdf0e10cSrcweir // Die Box pruefen ob es eine atomare Box ist
968cdf0e10cSrcweir const _FndBox* pBox = rBoxes[ j ];
969cdf0e10cSrcweir
970cdf0e10cSrcweir if( !pBox->GetLines().Count() )
971cdf0e10cSrcweir {
972cdf0e10cSrcweir // peichern
973cdf0e10cSrcweir sal_uInt16 nOff = nRow * nCols + nCol;
974cdf0e10cSrcweir *(pArr + nOff) = pBox;
975cdf0e10cSrcweir
976cdf0e10cSrcweir // sicher die Formel/Format/Value Werte
977cdf0e10cSrcweir const SwFrmFmt* pFmt = pBox->GetBox()->GetFrmFmt();
978cdf0e10cSrcweir if( SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_FORMAT ) ||
979cdf0e10cSrcweir SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_FORMULA ) ||
980cdf0e10cSrcweir SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_VALUE ) )
981cdf0e10cSrcweir {
982cdf0e10cSrcweir SfxItemSet* pSet = new SfxItemSet( pDoc->GetAttrPool(),
983cdf0e10cSrcweir RES_BOXATR_FORMAT, RES_BOXATR_VALUE,
984cdf0e10cSrcweir RES_VERT_ORIENT, RES_VERT_ORIENT, 0 );
985cdf0e10cSrcweir pSet->Put( pFmt->GetAttrSet() );
986cdf0e10cSrcweir if( !ppItemSets )
987cdf0e10cSrcweir {
988cdf0e10cSrcweir ppItemSets = new SfxItemSet*[ nRows * nCols ];
989cdf0e10cSrcweir memset( ppItemSets, 0, sizeof(SfxItemSet*) * nRows * nCols );
990cdf0e10cSrcweir }
991cdf0e10cSrcweir *(ppItemSets + nOff ) = pSet;
992cdf0e10cSrcweir }
993cdf0e10cSrcweir
994cdf0e10cSrcweir bModRow = sal_True;
995cdf0e10cSrcweir }
996cdf0e10cSrcweir else
997cdf0e10cSrcweir {
998cdf0e10cSrcweir // Rekursiv wieder ueber die Lines einer Box Iterieren
999cdf0e10cSrcweir FillFlat( *pBox, ( j == rBoxes.Count()-1 ) );
1000cdf0e10cSrcweir }
1001cdf0e10cSrcweir nCol++;
1002cdf0e10cSrcweir }
1003cdf0e10cSrcweir if(bModRow)
1004cdf0e10cSrcweir nRow++;
1005cdf0e10cSrcweir nCol = nOldCol;
1006cdf0e10cSrcweir }
1007cdf0e10cSrcweir if(!bLastBox)
1008cdf0e10cSrcweir nRow = nOldRow;
1009cdf0e10cSrcweir }
1010cdf0e10cSrcweir
1011cdf0e10cSrcweir /*--------------------------------------------------------------------
1012cdf0e10cSrcweir Beschreibung: Zugriff auf eine bestimmte Zelle
1013cdf0e10cSrcweir --------------------------------------------------------------------*/
1014cdf0e10cSrcweir
1015cdf0e10cSrcweir
GetBox(sal_uInt16 n_Col,sal_uInt16 n_Row) const1016cdf0e10cSrcweir const _FndBox* FlatFndBox::GetBox(sal_uInt16 n_Col, sal_uInt16 n_Row) const
1017cdf0e10cSrcweir {
1018cdf0e10cSrcweir sal_uInt16 nOff = n_Row * nCols + n_Col;
1019cdf0e10cSrcweir const _FndBox* pTmp = *(pArr + nOff);
1020cdf0e10cSrcweir
1021cdf0e10cSrcweir ASSERT(n_Col < nCols && n_Row < nRows && pTmp, "unzulaessiger Array-Zugriff");
1022cdf0e10cSrcweir return pTmp;
1023cdf0e10cSrcweir }
1024cdf0e10cSrcweir
GetItemSet(sal_uInt16 n_Col,sal_uInt16 n_Row) const1025cdf0e10cSrcweir const SfxItemSet* FlatFndBox::GetItemSet(sal_uInt16 n_Col, sal_uInt16 n_Row) const
1026cdf0e10cSrcweir {
1027cdf0e10cSrcweir ASSERT( !ppItemSets || ( n_Col < nCols && n_Row < nRows), "unzulaessiger Array-Zugriff");
1028cdf0e10cSrcweir
1029cdf0e10cSrcweir return ppItemSets ? *(ppItemSets + (n_Row * nCols + n_Col )) : 0;
1030cdf0e10cSrcweir }
1031cdf0e10cSrcweir
1032cdf0e10cSrcweir
1033