Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <boost/ptr_container/ptr_set.hpp>
30 : :
31 : : #include <hintids.hxx>
32 : : #include <rtl/math.hxx>
33 : : #include <unotools/collatorwrapper.hxx>
34 : : #include <unotools/localedatawrapper.hxx>
35 : : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
36 : : #include <com/sun/star/i18n/CollatorOptions.hpp>
37 : : #include <comphelper/processfactory.hxx>
38 : : #include <editeng/unolingu.hxx>
39 : : #include <docary.hxx>
40 : : #include <fmtanchr.hxx>
41 : : #include <frmfmt.hxx>
42 : : #include <doc.hxx>
43 : : #include <IDocumentUndoRedo.hxx>
44 : : #include <node.hxx>
45 : : #include <pam.hxx>
46 : : #include <ndtxt.hxx>
47 : : #include <swtable.hxx>
48 : : #include <swundo.hxx>
49 : : #include <sortopt.hxx>
50 : : #include <docsort.hxx>
51 : : #include <UndoSort.hxx>
52 : : #include <UndoRedline.hxx>
53 : : #include <hints.hxx>
54 : : #include <tblsel.hxx>
55 : : #include <cellatr.hxx>
56 : : #include <redline.hxx>
57 : : #include <node2lay.hxx>
58 : : #include <unochart.hxx>
59 : :
60 : : using namespace ::com::sun::star::lang;
61 : : using namespace ::com::sun::star;
62 : :
63 : : SwSortOptions* SwSortElement::pOptions = 0;
64 : : SwDoc* SwSortElement::pDoc = 0;
65 : : const FlatFndBox* SwSortElement::pBox = 0;
66 : : CollatorWrapper* SwSortElement::pSortCollator = 0;
67 : : lang::Locale* SwSortElement::pLocale = 0;
68 : : String* SwSortElement::pLastAlgorithm = 0;
69 : : LocaleDataWrapper* SwSortElement::pLclData = 0;
70 : :
71 : : // List of all sorted elements
72 : : typedef SwSortElement* SwSortElementPtr;
73 : :
74 : : typedef ::boost::ptr_multiset<SwSortTxtElement> SwSortTxtElements;
75 : : typedef ::boost::ptr_multiset<SwSortBoxElement> SwSortBoxElements;
76 : :
77 : : /*--------------------------------------------------------------------
78 : : Description: Construct a SortElement for the Sort
79 : : --------------------------------------------------------------------*/
80 : 16 : void SwSortElement::Init( SwDoc* pD, const SwSortOptions& rOpt,
81 : : FlatFndBox* pFltBx )
82 : : {
83 : : OSL_ENSURE( !pDoc && !pOptions && !pBox, "Who forgot to call Finit?" );
84 : 16 : pDoc = pD;
85 [ + - ]: 16 : pOptions = new SwSortOptions( rOpt );
86 : 16 : pBox = pFltBx;
87 : :
88 : 16 : LanguageType nLang = rOpt.nLanguage;
89 [ - + ]: 16 : switch ( nLang )
90 : : {
91 : : case LANGUAGE_NONE:
92 : : case LANGUAGE_DONTKNOW:
93 : 0 : nLang = (LanguageType)GetAppLanguage();
94 : 0 : break;
95 : : }
96 [ + - ]: 16 : pLocale = new lang::Locale( SvxCreateLocale( nLang ) );
97 : :
98 : : pSortCollator = new CollatorWrapper(
99 [ + - ][ + - ]: 16 : ::comphelper::getProcessServiceFactory() );
100 : 16 : }
101 : :
102 : 16 : void SwSortElement::Finit()
103 : : {
104 [ + - ]: 16 : delete pOptions, pOptions = 0;
105 [ + - ]: 16 : delete pLocale, pLocale = 0;
106 [ + + ]: 16 : delete pLastAlgorithm, pLastAlgorithm = 0;
107 [ + - ]: 16 : delete pSortCollator, pSortCollator = 0;
108 [ + + ]: 16 : delete pLclData, pLclData = 0;
109 : 16 : pDoc = 0;
110 : 16 : pBox = 0;
111 : 16 : }
112 : :
113 : 104 : SwSortElement::~SwSortElement()
114 : : {
115 [ - + ]: 104 : }
116 : :
117 : 428 : double SwSortElement::StrToDouble( const String& rStr ) const
118 : : {
119 [ + + ]: 428 : if( !pLclData )
120 : : pLclData = new LocaleDataWrapper(
121 [ + - ][ + - ]: 8 : ::comphelper::getProcessServiceFactory(), *pLocale );
[ + - ]
122 : :
123 : : rtl_math_ConversionStatus eStatus;
124 : : sal_Int32 nEnd;
125 : : double nRet = ::rtl::math::stringToDouble( rStr,
126 [ + - ]: 428 : pLclData->getNumDecimalSep()[0],
127 [ + - ]: 428 : pLclData->getNumThousandSep()[0],
128 [ + - ]: 428 : &eStatus, &nEnd );
129 : :
130 [ + + ][ + - ]: 428 : if( rtl_math_ConversionStatus_Ok != eStatus || nEnd == 0 )
131 : 362 : nRet = 0.0;
132 : 428 : return nRet;
133 : : }
134 : :
135 : 384 : int SwSortElement::keycompare(const SwSortElement& rCmp, sal_uInt16 nKey) const
136 : : {
137 : 384 : int nCmp = 0;
138 : : // The actual comparison
139 : : const SwSortElement *pOrig, *pCmp;
140 : :
141 : 384 : const SwSortKey* pSrtKey = pOptions->aKeys[ nKey ];
142 [ + + ]: 384 : if( pSrtKey->eSortOrder == SRT_ASCENDING )
143 : 188 : pOrig = this, pCmp = &rCmp;
144 : : else
145 : 196 : pOrig = &rCmp, pCmp = this;
146 : :
147 [ + + ]: 384 : if( pSrtKey->bIsNumeric )
148 : : {
149 : 246 : double n1 = pOrig->GetValue( nKey );
150 : 246 : double n2 = pCmp->GetValue( nKey );
151 : :
152 [ + + ]: 246 : nCmp = n1 < n2 ? -1 : n1 == n2 ? 0 : 1;
153 : : }
154 : : else
155 : : {
156 [ + + ][ - + ]: 138 : if( !pLastAlgorithm || *pLastAlgorithm != pSrtKey->sSortType )
[ + + ]
157 : : {
158 [ - + ]: 8 : if( pLastAlgorithm )
159 : 0 : *pLastAlgorithm = pSrtKey->sSortType;
160 : : else
161 [ + - ]: 8 : pLastAlgorithm = new String( pSrtKey->sSortType );
162 : : pSortCollator->loadCollatorAlgorithm( *pLastAlgorithm,
163 : : *pLocale,
164 [ + - ][ + - ]: 8 : pOptions->bIgnoreCase ? SW_COLLATOR_IGNORES : 0 );
165 : : }
166 : :
167 : : nCmp = pSortCollator->compareString(
168 [ + - ][ + - ]: 138 : pOrig->GetKey( nKey ), pCmp->GetKey( nKey ));
[ + - ][ + - ]
[ + - ]
169 : : }
170 : 384 : return nCmp;
171 : : }
172 : :
173 : : /*--------------------------------------------------------------------
174 : : Description: Comparison operators
175 : : --------------------------------------------------------------------*/
176 : 0 : sal_Bool SwSortElement::operator==(const SwSortElement& ) const
177 : : {
178 : 0 : return sal_False;
179 : : }
180 : :
181 : : /*--------------------------------------------------------------------
182 : : Description: Less-than operator for sorting
183 : : --------------------------------------------------------------------*/
184 : 280 : sal_Bool SwSortElement::operator<(const SwSortElement& rCmp) const
185 : : {
186 : : // The actual comparison
187 [ + + ]: 436 : for(sal_uInt16 nKey = 0; nKey < pOptions->aKeys.size(); ++nKey)
188 : : {
189 : 384 : int nCmp = keycompare(rCmp, nKey);
190 : :
191 [ + + ]: 384 : if (nCmp == 0)
192 : 156 : continue;
193 : :
194 : 228 : return nCmp < 0;
195 : : }
196 : :
197 : 280 : return sal_False;
198 : : }
199 : :
200 : 428 : double SwSortElement::GetValue( sal_uInt16 nKey ) const
201 : : {
202 [ + - ]: 428 : return StrToDouble( GetKey( nKey ));
203 : : }
204 : :
205 : : /*--------------------------------------------------------------------
206 : : Description: SortingElement for Text
207 : : --------------------------------------------------------------------*/
208 : 56 : SwSortTxtElement::SwSortTxtElement(const SwNodeIndex& rPos)
209 [ + - ]: 56 : : nOrg(rPos.GetIndex()), aPos(rPos)
210 : : {
211 : 56 : }
212 : :
213 [ + - ]: 56 : SwSortTxtElement::~SwSortTxtElement()
214 : : {
215 [ - + ]: 112 : }
216 : :
217 : : /*--------------------------------------------------------------------
218 : : Description: Get Key
219 : : --------------------------------------------------------------------*/
220 : 440 : String SwSortTxtElement::GetKey(sal_uInt16 nId) const
221 : : {
222 : 440 : SwTxtNode* pTxtNd = aPos.GetNode().GetTxtNode();
223 [ - + ]: 440 : if( !pTxtNd )
224 : 0 : return aEmptyStr;
225 : :
226 : : // for TextNodes
227 : 440 : const String& rStr = pTxtNd->GetTxt();
228 : :
229 : 440 : sal_Unicode nDeli = pOptions->cDeli;
230 : 440 : sal_uInt16 nDCount = pOptions->aKeys[nId]->nColumnId, i = 1;
231 : 440 : xub_StrLen nStart = 0;
232 : :
233 : : // Find the delimiter
234 [ + - ][ - + ]: 440 : while( nStart != STRING_NOTFOUND && i < nDCount)
[ - + ]
235 [ # # ]: 0 : if( STRING_NOTFOUND != ( nStart = rStr.Search( nDeli, nStart ) ) )
236 : : {
237 : 0 : nStart++;
238 : 0 : i++;
239 : : }
240 : :
241 : : // Found next delimiter or end of String
242 : : // and copy
243 : 440 : xub_StrLen nEnd = rStr.Search( nDeli, nStart+1 );
244 : 440 : return rStr.Copy( nStart, nEnd-nStart );
245 : : }
246 : :
247 : : /*--------------------------------------------------------------------
248 : : Description: SortingElement for Tables
249 : : --------------------------------------------------------------------*/
250 : 48 : SwSortBoxElement::SwSortBoxElement( sal_uInt16 nRC )
251 : 48 : : nRow( nRC )
252 : : {
253 : 48 : }
254 : :
255 : 48 : SwSortBoxElement::~SwSortBoxElement()
256 : : {
257 [ - + ]: 96 : }
258 : :
259 : : /*--------------------------------------------------------------------
260 : : Description: Get Key for a cell
261 : : --------------------------------------------------------------------*/
262 : 264 : String SwSortBoxElement::GetKey(sal_uInt16 nKey) const
263 : : {
264 : : const _FndBox* pFndBox;
265 : 264 : sal_uInt16 nCol = pOptions->aKeys[nKey]->nColumnId-1;
266 : :
267 [ + - ]: 264 : if( SRT_ROWS == pOptions->eDirection )
268 : 264 : pFndBox = pBox->GetBox(nCol, nRow); // Sort rows
269 : : else
270 : 0 : pFndBox = pBox->GetBox(nRow, nCol); // Sort columns
271 : :
272 : : // Extract the Text
273 : 264 : String aRetStr;
274 [ + - ]: 264 : if( pFndBox )
275 : : { // Get StartNode and skip it
276 : 264 : const SwTableBox* pMyBox = pFndBox->GetBox();
277 : : OSL_ENSURE(pMyBox, "No atomic Box");
278 : :
279 [ + - ]: 264 : if( pMyBox->GetSttNd() )
280 : : {
281 : : // Iterate over all the Box's TextNodes
282 : 264 : const SwNode *pNd = 0, *pEndNd = pMyBox->GetSttNd()->EndOfSectionNode();
283 [ + + ][ + - ]: 792 : for( sal_uLong nIdx = pMyBox->GetSttIdx() + 1; pNd != pEndNd; ++nIdx )
284 [ + - ][ + - ]: 528 : if( ( pNd = pDoc->GetNodes()[ nIdx ])->IsTxtNode() )
[ + + ]
285 [ + - ][ + - ]: 264 : aRetStr += ((SwTxtNode*)pNd)->GetTxt();
286 : : }
287 : : }
288 : 264 : return aRetStr;
289 : : }
290 : :
291 : 208 : double SwSortBoxElement::GetValue( sal_uInt16 nKey ) const
292 : : {
293 : : const _FndBox* pFndBox;
294 : 208 : sal_uInt16 nCol = pOptions->aKeys[nKey]->nColumnId-1;
295 : :
296 [ + - ]: 208 : if( SRT_ROWS == pOptions->eDirection )
297 : 208 : pFndBox = pBox->GetBox(nCol, nRow); // Sort rows
298 : : else
299 : 0 : pFndBox = pBox->GetBox(nRow, nCol); // Sort columns
300 : :
301 : :
302 : : double nVal;
303 [ + - ]: 208 : if( pFndBox )
304 : : {
305 : 208 : const SwFmt *pFmt = pFndBox->GetBox()->GetFrmFmt();
306 [ + + ]: 208 : if (pFmt->GetTblBoxNumFmt().GetValue() & NUMBERFORMAT_TEXT)
307 : 144 : nVal = SwSortElement::GetValue( nKey );
308 : : else
309 : 64 : nVal = pFmt->GetTblBoxValue().GetValue();
310 : : }
311 : : else
312 : 0 : nVal = 0;
313 : :
314 : 208 : return nVal;
315 : : }
316 : :
317 : : /*--------------------------------------------------------------------
318 : : Description: Sort Text in the Document
319 : : --------------------------------------------------------------------*/
320 : 8 : sal_Bool SwDoc::SortText(const SwPaM& rPaM, const SwSortOptions& rOpt)
321 : : {
322 : : // Check if Frame is in the Text
323 [ + - ][ + - ]: 8 : const SwPosition *pStart = rPaM.Start(), *pEnd = rPaM.End();
324 : :
325 : : // Set index to the Selection's start
326 [ - + ]: 8 : for ( sal_uInt16 n = 0; n < GetSpzFrmFmts()->size(); ++n )
327 : : {
328 : 0 : SwFrmFmt *const pFmt = static_cast<SwFrmFmt*>((*GetSpzFrmFmts())[n]);
329 [ # # ]: 0 : SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
330 [ # # ]: 0 : SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
331 : :
332 [ # # ][ # # : 0 : if (pAPos && (FLY_AT_PARA == pAnchor->GetAnchorId()) &&
# # # # ]
[ # # ]
333 : 0 : pStart->nNode <= pAPos->nNode && pAPos->nNode <= pEnd->nNode )
334 : 0 : return sal_False;
335 : : }
336 : :
337 : : // Check if only TextNodes are within the Selection
338 : : {
339 : 8 : sal_uLong nStart = pStart->nNode.GetIndex(),
340 : 8 : nEnd = pEnd->nNode.GetIndex();
341 [ + + ]: 64 : while( nStart <= nEnd )
342 : : // Iterate over a selected Area
343 [ + - ][ + - ]: 56 : if( !GetNodes()[ nStart++ ]->IsTxtNode() )
[ - + ]
344 : 0 : return sal_False;
345 : : }
346 : :
347 [ + - ][ + - ]: 8 : bool const bUndo = GetIDocumentUndoRedo().DoesUndo();
348 [ + - ]: 8 : if( bUndo )
349 : : {
350 [ + - ][ + - ]: 8 : GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
351 : : }
352 : :
353 : 8 : SwPaM* pRedlPam = 0;
354 : 8 : SwUndoRedlineSort* pRedlUndo = 0;
355 : 8 : SwUndoSort* pUndoSort = 0;
356 : :
357 [ + - ][ + - ]: 8 : if( IsRedlineOn() || (!IsIgnoreRedline() && !pRedlineTbl->empty() ))
[ + - ][ + - ]
[ - + ][ - + ]
358 : : {
359 [ # # ][ # # ]: 0 : pRedlPam = new SwPaM( pStart->nNode, pEnd->nNode, -1, 1 );
360 : 0 : SwCntntNode* pCNd = pRedlPam->GetCntntNode( sal_False );
361 [ # # ]: 0 : if( pCNd )
362 [ # # ][ # # ]: 0 : pRedlPam->GetMark()->nContent = pCNd->Len();
363 : :
364 [ # # ][ # # ]: 0 : if( IsRedlineOn() && !IsShowOriginal( GetRedlineMode() ) )
[ # # ][ # # ]
[ # # ]
365 : : {
366 [ # # ]: 0 : if( bUndo )
367 : : {
368 [ # # ][ # # ]: 0 : pRedlUndo = new SwUndoRedlineSort( *pRedlPam,rOpt );
369 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().DoUndo(false);
370 : : }
371 : : // First copy the area
372 [ # # ]: 0 : SwNodeIndex aEndIdx( pEnd->nNode, 1 );
373 [ # # ]: 0 : SwNodeRange aRg( pStart->nNode, aEndIdx );
374 [ # # ][ # # ]: 0 : GetNodes()._Copy( aRg, aEndIdx );
375 : :
376 : : // Area is new from pEnd->nNode+1 to aEndIdx
377 [ # # ]: 0 : DeleteRedline( *pRedlPam, true, USHRT_MAX );
378 : :
379 [ # # ]: 0 : pRedlPam->GetMark()->nNode.Assign( pEnd->nNode.GetNode(), 1 );
380 : 0 : pCNd = pRedlPam->GetCntntNode( sal_False );
381 [ # # ][ # # ]: 0 : pRedlPam->GetMark()->nContent.Assign( pCNd, 0 );
382 : :
383 [ # # ]: 0 : pRedlPam->GetPoint()->nNode.Assign( aEndIdx.GetNode() );
384 : 0 : pCNd = pRedlPam->GetCntntNode( sal_True );
385 : 0 : xub_StrLen nCLen = 0;
386 [ # # ][ # # ]: 0 : if( !pCNd &&
[ # # ]
387 [ # # ][ # # ]: 0 : 0 != (pCNd = GetNodes()[ aEndIdx.GetIndex()-1 ]->GetCntntNode()))
388 : : {
389 [ # # ]: 0 : nCLen = pCNd->Len();
390 [ # # ]: 0 : pRedlPam->GetPoint()->nNode.Assign( *pCNd );
391 : : }
392 [ # # ][ # # ]: 0 : pRedlPam->GetPoint()->nContent.Assign( pCNd, nCLen );
393 : :
394 [ # # ]: 0 : if( pRedlUndo )
395 [ # # ][ # # ]: 0 : pRedlUndo->SetValues( rPaM );
[ # # ]
396 : : }
397 : : else
398 : : {
399 [ # # ]: 0 : DeleteRedline( *pRedlPam, true, USHRT_MAX );
400 [ # # ][ # # ]: 0 : delete pRedlPam, pRedlPam = 0;
401 : : }
402 : : }
403 : :
404 [ + - ]: 8 : SwNodeIndex aStart(pStart->nNode);
405 [ + - ]: 8 : SwSortElement::Init( this, rOpt );
406 [ + - ]: 8 : SwSortTxtElements aSortSet;
407 [ + + ]: 64 : while( aStart <= pEnd->nNode )
408 : : {
409 : : // Iterate over a selected Area
410 [ + - ][ + - ]: 56 : SwSortTxtElement* pSE = new SwSortTxtElement( aStart );
411 [ + - ]: 56 : aSortSet.insert(pSE);
412 [ + - ]: 56 : aStart++;
413 : : }
414 : :
415 : : // Now comes the tricky part: Move Nodes (and always keep Undo in mind)
416 : 8 : sal_uLong nBeg = pStart->nNode.GetIndex();
417 [ + - ]: 8 : SwNodeRange aRg( aStart, aStart );
418 : :
419 [ + - ][ + - ]: 8 : if( bUndo && !pRedlUndo )
420 : : {
421 [ + - ][ + - ]: 8 : pUndoSort = new SwUndoSort(rPaM, rOpt);
422 [ + - ][ + - ]: 8 : GetIDocumentUndoRedo().AppendUndo(pUndoSort);
423 : : }
424 : :
425 [ + - ][ + - ]: 8 : GetIDocumentUndoRedo().DoUndo(false);
426 : :
427 : 8 : size_t n = 0;
428 [ + - ][ + - ]: 128 : for (SwSortTxtElements::const_iterator it = aSortSet.begin();
[ + - ][ + - ]
[ + + ]
429 [ + - ]: 64 : it != aSortSet.end(); ++it, ++n)
430 : : {
431 [ + - ]: 56 : aStart = nBeg + n;
432 [ + - ][ + - ]: 56 : aRg.aStart = it->aPos.GetIndex();
433 [ + - ]: 56 : aRg.aEnd = aRg.aStart.GetIndex() + 1;
434 : :
435 : : // Move Nodes
436 : : MoveNodeRange( aRg, aStart,
437 [ + - ]: 56 : IDocumentContentOperations::DOC_MOVEDEFAULT );
438 : :
439 : : // Insert Move in Undo
440 [ + - ]: 56 : if(pUndoSort)
441 : : {
442 [ + - ][ + - ]: 56 : pUndoSort->Insert(it->nOrg, nBeg + n);
443 : : }
444 : : }
445 : : // Delete all elements from the SortArray
446 [ + - ]: 8 : aSortSet.clear();
447 [ + - ]: 8 : SwSortElement::Finit();
448 : :
449 [ - + ]: 8 : if( pRedlPam )
450 : : {
451 [ # # ]: 0 : if( pRedlUndo )
452 : : {
453 [ # # ]: 0 : pRedlUndo->SetSaveRange( *pRedlPam );
454 : : // UGLY: temp. enable Undo
455 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().DoUndo(true);
456 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().AppendUndo( pRedlUndo );
457 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().DoUndo(false);
458 : : }
459 : :
460 : : // nBeg is start of sorted range
461 [ # # ][ # # ]: 0 : SwNodeIndex aSttIdx( GetNodes(), nBeg );
462 : :
463 : : // the copied range is deleted
464 : : SwRedline *const pDeleteRedline(
465 [ # # ][ # # ]: 0 : new SwRedline( nsRedlineType_t::REDLINE_DELETE, *pRedlPam ));
466 : :
467 : : // pRedlPam points to nodes that may be deleted (hidden) by
468 : : // AppendRedline, so adjust it beforehand to prevent ASSERT
469 [ # # ]: 0 : pRedlPam->GetPoint()->nNode = aSttIdx;
470 : 0 : SwCntntNode* pCNd = aSttIdx.GetNode().GetCntntNode();
471 [ # # ][ # # ]: 0 : pRedlPam->GetPoint()->nContent.Assign( pCNd, 0 );
472 : :
473 [ # # ]: 0 : AppendRedline(pDeleteRedline, true);
474 : :
475 : : // the sorted range is inserted
476 [ # # ][ # # ]: 0 : AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, *pRedlPam ), true);
[ # # ]
477 : :
478 [ # # ]: 0 : if( pRedlUndo )
479 : : {
480 [ # # ]: 0 : SwNodeIndex aInsEndIdx( pRedlPam->GetMark()->nNode, -1 );
481 [ # # ]: 0 : pRedlPam->GetMark()->nNode = aInsEndIdx;
482 : : SwCntntNode *const pPrevNode =
483 : 0 : pRedlPam->GetMark()->nNode.GetNode().GetCntntNode();
484 [ # # ][ # # ]: 0 : pRedlPam->GetMark()->nContent.Assign( pPrevNode, pPrevNode->Len() );
[ # # ]
485 : :
486 [ # # ][ # # ]: 0 : pRedlUndo->SetValues( *pRedlPam );
487 : : }
488 : :
489 [ # # ]: 0 : if( pRedlUndo )
490 [ # # ]: 0 : pRedlUndo->SetOffset( aSttIdx );
491 : :
492 [ # # ][ # # ]: 0 : delete pRedlPam, pRedlPam = 0;
[ # # ]
493 : : }
494 [ + - ][ + - ]: 8 : GetIDocumentUndoRedo().DoUndo( bUndo );
495 [ + - ]: 8 : if( bUndo )
496 : : {
497 [ + - ][ + - ]: 8 : GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
498 : : }
499 : :
500 [ + - ][ + - ]: 8 : return sal_True;
[ + - ]
501 : : }
502 : :
503 : : /*--------------------------------------------------------------------
504 : : Description: Sort Table in the Document
505 : : --------------------------------------------------------------------*/
506 : 8 : sal_Bool SwDoc::SortTbl(const SwSelBoxes& rBoxes, const SwSortOptions& rOpt)
507 : : {
508 : : // Via SwDoc for Undo!
509 : : OSL_ENSURE( !rBoxes.empty(), "no valid Box list" );
510 [ + - ][ + - ]: 8 : SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
511 [ - + ]: 8 : if( !pTblNd )
512 : 0 : return sal_False;
513 : :
514 : : // We begin sorting
515 : : // Find all Boxes/Lines
516 [ + - ]: 8 : _FndBox aFndBox( 0, 0 );
517 : : {
518 : 8 : _FndPara aPara( rBoxes, &aFndBox );
519 [ + - ]: 8 : ForEach_FndLineCopyCol( pTblNd->GetTable().GetTabLines(), &aPara );
520 : : }
521 : :
522 [ - + ]: 8 : if(aFndBox.GetLines().empty())
523 : 0 : return sal_False;
524 : :
525 [ + - ][ + - ]: 8 : if( !IsIgnoreRedline() && !GetRedlineTbl().empty() )
[ + - ][ - + ]
[ - + ]
526 [ # # ]: 0 : DeleteRedline( *pTblNd, true, USHRT_MAX );
527 : :
528 : 8 : sal_uInt16 nStart = 0;
529 [ + - ][ - + ]: 8 : if( pTblNd->GetTable().GetRowsToRepeat() > 0 && rOpt.eDirection == SRT_ROWS )
[ # # ][ - + ]
530 : : {
531 : : // Uppermost selected Cell
532 : 0 : _FndLines& rLines = aFndBox.GetLines();
533 : :
534 [ # # ]: 0 : while( nStart < rLines.size() )
535 : : {
536 : : // Respect Split Merge nesting,
537 : : // extract the upper most
538 [ # # ]: 0 : SwTableLine* pLine = rLines[nStart].GetLine();
539 [ # # ]: 0 : while ( pLine->GetUpper() )
540 : 0 : pLine = pLine->GetUpper()->GetUpper();
541 : :
542 [ # # ][ # # ]: 0 : if( pTblNd->GetTable().IsHeadline( *pLine ) )
543 : 0 : nStart++;
544 : : else
545 : 0 : break;
546 : : }
547 : : // Are all selected in the HeaderLine? -> no Offset
548 [ # # ]: 0 : if( nStart == rLines.size() )
549 : 0 : nStart = 0;
550 : : }
551 : :
552 : : // Switch to relative Formulas
553 [ + - ]: 8 : SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
554 : 8 : aMsgHnt.eFlags = TBL_RELBOXNAME;
555 [ + - ]: 8 : UpdateTblFlds( &aMsgHnt );
556 : :
557 : : // Table as a flat array structure
558 [ + - ]: 8 : FlatFndBox aFlatBox(this, aFndBox);
559 : :
560 [ - + ]: 8 : if(!aFlatBox.IsSymmetric())
561 : 0 : return sal_False;
562 : :
563 : : // Delete HTML layout
564 [ + - ]: 8 : pTblNd->GetTable().SetHTMLTableLayout( 0 );
565 : :
566 : : // #i37739# A simple 'MakeFrms' after the node sorting
567 : : // does not work if the table is inside a frame and has no prev/next.
568 [ + - ]: 8 : SwNode2Layout aNode2Layout( *pTblNd );
569 : :
570 : : // Delete the Table's Frames
571 [ + - ]: 8 : pTblNd->DelFrms();
572 : : // ? TL_CHART2: ?
573 : :
574 : 8 : SwUndoSort* pUndoSort = 0;
575 [ + - ][ + - ]: 8 : if (GetIDocumentUndoRedo().DoesUndo())
[ + - ]
576 : : {
577 [ + - ]: 8 : pUndoSort = new SwUndoSort( rBoxes[0]->GetSttIdx(),
578 [ + - ]: 8 : rBoxes.back()->GetSttIdx(),
579 [ + - ][ + - ]: 16 : *pTblNd, rOpt, aFlatBox.HasItemSets() );
[ + - ][ + - ]
580 [ + - ][ + - ]: 8 : GetIDocumentUndoRedo().AppendUndo(pUndoSort);
581 : : }
582 [ + - ][ + - ]: 8 : ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
583 : :
584 : : // Insert KeyElements
585 : : sal_uInt16 nCount = (rOpt.eDirection == SRT_ROWS) ?
586 [ + - ]: 8 : aFlatBox.GetRows() : aFlatBox.GetCols();
587 : :
588 : : // Sort SortList by Key
589 [ + - ]: 8 : SwSortElement::Init( this, rOpt, &aFlatBox );
590 [ + - ]: 8 : SwSortBoxElements aSortList;
591 : :
592 : : // When sorting, do not include the first row if the HeaderLine is repeated
593 : : sal_uInt16 i;
594 : :
595 [ + + ]: 56 : for( i = nStart; i < nCount; ++i)
596 : : {
597 [ + - ]: 48 : SwSortBoxElement* pEle = new SwSortBoxElement( i );
598 [ + - ]: 48 : aSortList.insert(pEle);
599 : : }
600 : :
601 : : // Move after Sorting
602 [ + - ]: 8 : SwMovedBoxes aMovedList;
603 : 8 : i = 0;
604 [ + - ][ + - ]: 112 : for (SwSortBoxElements::const_iterator it = aSortList.begin();
[ + - ][ + - ]
[ + + ]
605 [ + - ]: 56 : it != aSortList.end(); ++i, ++it)
606 : : {
607 [ + - ]: 48 : if(rOpt.eDirection == SRT_ROWS)
608 : : {
609 [ + - ][ + - ]: 48 : MoveRow(this, aFlatBox, it->nRow, i+nStart, aMovedList, pUndoSort);
610 : : }
611 : : else
612 : : {
613 [ # # ][ # # ]: 0 : MoveCol(this, aFlatBox, it->nRow, i+nStart, aMovedList, pUndoSort);
614 : : }
615 : : }
616 : :
617 : : // Restore table frames:
618 : : // #i37739# A simple 'MakeFrms' after the node sorting
619 : : // does not work if the table is inside a frame and has no prev/next.
620 : 8 : const sal_uLong nIdx = pTblNd->GetIndex();
621 [ + - ][ + - ]: 8 : aNode2Layout.RestoreUpperFrms( GetNodes(), nIdx, nIdx + 1 );
622 : :
623 : : // TL_CHART2: need to inform chart of probably changed cell names
624 [ + - ]: 8 : UpdateCharts( pTblNd->GetTable().GetFrmFmt()->GetName() );
625 : :
626 : : // Delete all Elements in the SortArray
627 [ + - ]: 8 : aSortList.clear();
628 [ + - ]: 8 : SwSortElement::Finit();
629 : :
630 [ + - ]: 8 : SetModified();
631 [ + - ][ + - ]: 8 : return sal_True;
[ + - ][ + - ]
[ + - ]
632 : : }
633 : :
634 : : /*--------------------------------------------------------------------
635 : : Description: Move a row
636 : : --------------------------------------------------------------------*/
637 : 48 : void MoveRow(SwDoc* pDoc, const FlatFndBox& rBox, sal_uInt16 nS, sal_uInt16 nT,
638 : : SwMovedBoxes& rMovedList, SwUndoSort* pUD)
639 : : {
640 [ + + ]: 144 : for( sal_uInt16 i=0; i < rBox.GetCols(); ++i )
641 : : { // Get old cell position and remember it
642 : 96 : const _FndBox* pSource = rBox.GetBox(i, nS);
643 : :
644 : : // new cell position
645 : 96 : const _FndBox* pTarget = rBox.GetBox(i, nT);
646 : :
647 : 96 : const SwTableBox* pT = pTarget->GetBox();
648 : 96 : const SwTableBox* pS = pSource->GetBox();
649 : :
650 [ + - ]: 96 : sal_Bool bMoved = rMovedList.GetPos(pT) != USHRT_MAX;
651 : :
652 : : // and move it
653 [ + - ]: 96 : MoveCell(pDoc, pS, pT, bMoved, pUD);
654 : :
655 [ + - ]: 96 : rMovedList.push_back(pS);
656 : :
657 [ + + ]: 96 : if( pS != pT )
658 : : {
659 : 76 : SwFrmFmt* pTFmt = (SwFrmFmt*)pT->GetFrmFmt();
660 : 76 : const SfxItemSet* pSSet = rBox.GetItemSet( i, nS );
661 : :
662 [ + - ][ + - ]: 190 : if( pSSet ||
[ - + ][ + + ]
[ + + ]
663 [ + - ]: 38 : SFX_ITEM_SET == pTFmt->GetItemState( RES_BOXATR_FORMAT ) ||
664 [ + - ]: 38 : SFX_ITEM_SET == pTFmt->GetItemState( RES_BOXATR_FORMULA ) ||
665 [ + - ]: 38 : SFX_ITEM_SET == pTFmt->GetItemState( RES_BOXATR_VALUE ) )
666 : : {
667 [ + - ]: 38 : pTFmt = ((SwTableBox*)pT)->ClaimFrmFmt();
668 : 38 : pTFmt->LockModify();
669 [ + - ][ + - ]: 38 : if( pTFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE ) )
670 [ + - ]: 38 : pTFmt->ResetFmtAttr( RES_VERT_ORIENT );
671 : :
672 [ + - ]: 38 : if( pSSet )
673 [ + - ]: 38 : pTFmt->SetFmtAttr( *pSSet );
674 : 38 : pTFmt->UnlockModify();
675 : : }
676 : : }
677 : : }
678 : 48 : }
679 : :
680 : : /*--------------------------------------------------------------------
681 : : Description: Move a column
682 : : --------------------------------------------------------------------*/
683 : 0 : void MoveCol(SwDoc* pDoc, const FlatFndBox& rBox, sal_uInt16 nS, sal_uInt16 nT,
684 : : SwMovedBoxes& rMovedList, SwUndoSort* pUD)
685 : : {
686 [ # # ]: 0 : for(sal_uInt16 i=0; i < rBox.GetRows(); ++i)
687 : : { // Get old cell position and remember it
688 : 0 : const _FndBox* pSource = rBox.GetBox(nS, i);
689 : :
690 : : // new cell position
691 : 0 : const _FndBox* pTarget = rBox.GetBox(nT, i);
692 : :
693 : : // and move it
694 : 0 : const SwTableBox* pT = pTarget->GetBox();
695 : 0 : const SwTableBox* pS = pSource->GetBox();
696 : :
697 : : // and move it
698 [ # # ]: 0 : sal_Bool bMoved = rMovedList.GetPos(pT) != USHRT_MAX;
699 [ # # ]: 0 : MoveCell(pDoc, pS, pT, bMoved, pUD);
700 : :
701 [ # # ]: 0 : rMovedList.push_back(pS);
702 : :
703 [ # # ]: 0 : if( pS != pT )
704 : : {
705 : 0 : SwFrmFmt* pTFmt = (SwFrmFmt*)pT->GetFrmFmt();
706 : 0 : const SfxItemSet* pSSet = rBox.GetItemSet( nS, i );
707 : :
708 [ # # ][ # # ]: 0 : if( pSSet ||
[ # # ][ # # ]
[ # # ]
709 [ # # ]: 0 : SFX_ITEM_SET == pTFmt->GetItemState( RES_BOXATR_FORMAT ) ||
710 [ # # ]: 0 : SFX_ITEM_SET == pTFmt->GetItemState( RES_BOXATR_FORMULA ) ||
711 [ # # ]: 0 : SFX_ITEM_SET == pTFmt->GetItemState( RES_BOXATR_VALUE ) )
712 : : {
713 [ # # ]: 0 : pTFmt = ((SwTableBox*)pT)->ClaimFrmFmt();
714 : 0 : pTFmt->LockModify();
715 [ # # ][ # # ]: 0 : if( pTFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE ) )
716 [ # # ]: 0 : pTFmt->ResetFmtAttr( RES_VERT_ORIENT );
717 : :
718 [ # # ]: 0 : if( pSSet )
719 [ # # ]: 0 : pTFmt->SetFmtAttr( *pSSet );
720 : 0 : pTFmt->UnlockModify();
721 : : }
722 : : }
723 : : }
724 : 0 : }
725 : :
726 : : /*--------------------------------------------------------------------
727 : : Description: Move a single Cell
728 : : --------------------------------------------------------------------*/
729 : 96 : void MoveCell(SwDoc* pDoc, const SwTableBox* pSource, const SwTableBox* pTar,
730 : : sal_Bool bMovedBefore, SwUndoSort* pUD)
731 : : {
732 : : OSL_ENSURE(pSource && pTar,"Source or target missing");
733 : :
734 [ + + ]: 96 : if(pSource == pTar)
735 : 96 : return;
736 : :
737 [ + - ]: 76 : if(pUD)
738 [ + - ][ + - ]: 76 : pUD->Insert( pSource->GetName(), pTar->GetName() );
[ + - ][ + - ]
[ + - ]
739 : :
740 : : // Set Pam source to the first ContentNode
741 [ + - ]: 76 : SwNodeRange aRg( *pSource->GetSttNd(), 0, *pSource->GetSttNd() );
742 [ + - ][ + - ]: 76 : SwNode* pNd = pDoc->GetNodes().GoNext( &aRg.aStart );
[ + - ]
743 : :
744 : : // If the Cell (Source) wasn't moved
745 : : // -> insert an empty Node and move the rest or the Mark
746 : : // points to the first ContentNode
747 [ + + ]: 76 : if( pNd->StartOfSectionNode() == pSource->GetSttNd() )
748 [ + - ]: 40 : pNd = pDoc->GetNodes().MakeTxtNode( aRg.aStart,
749 [ + - ][ + - ]: 80 : (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() );
750 [ + - ]: 76 : aRg.aEnd = *pNd->EndOfSectionNode();
751 : :
752 : : // If the Target is empty (there is one empty Node)
753 : : // -> delete it and move the Target
754 [ + - ]: 76 : SwNodeIndex aTar( *pTar->GetSttNd() );
755 [ + - ][ + - ]: 76 : pNd = pDoc->GetNodes().GoNext( &aTar ); // next ContentNode
[ + - ]
756 : 76 : sal_uLong nCount = pNd->EndOfSectionIndex() - pNd->StartOfSectionIndex();
757 : :
758 : 76 : sal_Bool bDelFirst = sal_False;
759 [ + - ]: 76 : if( nCount == 2 )
760 : : {
761 : : OSL_ENSURE( pNd->GetCntntNode(), "No ContentNode");
762 [ + - ][ + + ]: 76 : bDelFirst = !pNd->GetCntntNode()->Len() && bMovedBefore;
[ + + ]
763 : : }
764 : :
765 [ + + ]: 76 : if(!bDelFirst)
766 : : { // We already have Content -> old Content Section Down
767 [ + - ]: 36 : SwNodeRange aRgTar( aTar.GetNode(), 0, *pNd->EndOfSectionNode() );
768 [ + - ][ + - ]: 36 : pDoc->GetNodes().SectionDown( &aRgTar );
[ + - ]
769 : : }
770 : :
771 : : // Insert the Source
772 [ + - ]: 76 : SwNodeIndex aIns( *pTar->GetSttNd()->EndOfSectionNode() );
773 : : pDoc->MoveNodeRange( aRg, aIns,
774 [ + - ]: 76 : IDocumentContentOperations::DOC_MOVEDEFAULT );
775 : :
776 : : // If first Node is empty -> delete it
777 [ + + ]: 76 : if(bDelFirst)
778 [ + - ][ + - ]: 96 : pDoc->GetNodes().Delete( aTar, 1 );
[ + - ][ + - ]
[ + - ]
779 : : }
780 : :
781 : : /*--------------------------------------------------------------------
782 : : Description: Generate two-dimensional array of FndBoxes
783 : : --------------------------------------------------------------------*/
784 : 8 : FlatFndBox::FlatFndBox(SwDoc* pDocPtr, const _FndBox& rBox) :
785 : : pDoc(pDocPtr),
786 : : rBoxRef(rBox),
787 : : pArr(0),
788 : : ppItemSets(0),
789 : : nRow(0),
790 : 8 : nCol(0)
791 : : { // If the array is symmetric
792 [ + - ]: 8 : if((bSym = CheckLineSymmetry(rBoxRef)) != 0)
793 : : {
794 : : // Determine column/row count
795 : 8 : nCols = GetColCount(rBoxRef);
796 : 8 : nRows = GetRowCount(rBoxRef);
797 : :
798 : : // Create linear array
799 : 8 : pArr = new const _FndBox*[ nRows * nCols ];
800 : 8 : _FndBox** ppTmp = (_FndBox**)pArr;
801 : 8 : memset( ppTmp, 0, sizeof(const _FndBox*) * nRows * nCols );
802 : :
803 : :
804 : 8 : FillFlat( rBoxRef );
805 : : }
806 : 8 : }
807 : :
808 : 8 : FlatFndBox::~FlatFndBox()
809 : : {
810 : 8 : _FndBox** ppTmp = (_FndBox**)pArr;
811 [ + - ]: 8 : delete [] ppTmp;
812 : :
813 [ + - ]: 8 : if( ppItemSets )
814 [ + - ]: 8 : delete [] ppItemSets;
815 : 8 : }
816 : :
817 : : /*--------------------------------------------------------------------
818 : : Description: All Lines of a Box need to have as many Boxes
819 : : --------------------------------------------------------------------*/
820 : 8 : sal_Bool FlatFndBox::CheckLineSymmetry(const _FndBox& rBox)
821 : : {
822 : 8 : const _FndLines &rLines = rBox.GetLines();
823 : 8 : sal_uInt16 nBoxes(0);
824 : :
825 : : // Iterate over Lines
826 [ + + ]: 56 : for(sal_uInt16 i=0; i < rLines.size(); ++i)
827 : : { // A List's Box
828 : 48 : const _FndLine* pLn = &rLines[i];
829 : 48 : const _FndBoxes& rBoxes = pLn->GetBoxes();
830 : :
831 : : // Amount of Boxes of all Lines is uneven -> no symmetry
832 [ - + ][ - + ]: 48 : if( i && nBoxes != rBoxes.size())
[ + + ]
833 : 0 : return sal_False;
834 : :
835 : 48 : nBoxes = rBoxes.size();
836 [ - + ]: 48 : if( !CheckBoxSymmetry( *pLn ) )
837 : 0 : return sal_False;
838 : : }
839 : 8 : return sal_True;
840 : : }
841 : :
842 : : /*--------------------------------------------------------------------
843 : : Description: Check Box for symmetry
844 : : All Boxes of a Line need to have as many Lines
845 : : --------------------------------------------------------------------*/
846 : 48 : sal_Bool FlatFndBox::CheckBoxSymmetry(const _FndLine& rLn)
847 : : {
848 : 48 : const _FndBoxes &rBoxes = rLn.GetBoxes();
849 : 48 : sal_uInt16 nLines(0);
850 : :
851 : : // Iterate over Boxes
852 [ + + ]: 144 : for(sal_uInt16 i=0; i < rBoxes.size(); ++i)
853 : : { // The Boxes of a Line
854 : 96 : _FndBox const*const pBox = &rBoxes[i];
855 : 96 : const _FndLines& rLines = pBox->GetLines();
856 : :
857 : : // Amount of Boxes of all Lines is uneven -> no symmetry
858 [ - + ][ - + ]: 96 : if( i && nLines != rLines.size() )
[ + + ]
859 : 0 : return sal_False;
860 : :
861 : 96 : nLines = rLines.size();
862 [ # # ][ - + ]: 96 : if( nLines && !CheckLineSymmetry( *pBox ) )
[ - + ]
863 : 0 : return sal_False;
864 : : }
865 : 48 : return sal_True;
866 : : }
867 : :
868 : : /*--------------------------------------------------------------------
869 : : Description: Maximum count of Columns (Boxes)
870 : : --------------------------------------------------------------------*/
871 : 8 : sal_uInt16 FlatFndBox::GetColCount(const _FndBox& rBox)
872 : : {
873 : 8 : const _FndLines& rLines = rBox.GetLines();
874 : : // Iterate over Lines
875 [ - + ]: 8 : if( rLines.empty() )
876 : 0 : return 1;
877 : :
878 : 8 : sal_uInt16 nSum = 0;
879 [ + + ]: 56 : for( sal_uInt16 i=0; i < rLines.size(); ++i )
880 : : {
881 : : // The Boxes of a Line
882 : 48 : sal_uInt16 nCount = 0;
883 : 48 : const _FndBoxes& rBoxes = rLines[i].GetBoxes();
884 [ + + ]: 144 : for( sal_uInt16 j=0; j < rBoxes.size(); ++j )
885 : : // Iterate recursively over the Lines
886 : 96 : nCount += (rBoxes[j].GetLines().size())
887 [ - + ]: 96 : ? GetColCount(rBoxes[j]) : 1;
888 : :
889 [ + + ]: 48 : if( nSum < nCount )
890 : 8 : nSum = nCount;
891 : : }
892 : 8 : return nSum;
893 : : }
894 : :
895 : : /*--------------------------------------------------------------------
896 : : Description: Maximum count of Rows (Lines)
897 : : --------------------------------------------------------------------*/
898 : 8 : sal_uInt16 FlatFndBox::GetRowCount(const _FndBox& rBox)
899 : : {
900 : 8 : const _FndLines& rLines = rBox.GetLines();
901 [ - + ]: 8 : if( rLines.empty() )
902 : 0 : return 1;
903 : :
904 : 8 : sal_uInt16 nLines = 0;
905 [ + + ]: 56 : for(sal_uInt16 i=0; i < rLines.size(); ++i)
906 : : { // The Boxes of a Line
907 : 48 : const _FndBoxes& rBoxes = rLines[i].GetBoxes();
908 : 48 : sal_uInt16 nLn = 1;
909 [ + + ]: 144 : for(sal_uInt16 j=0; j < rBoxes.size(); ++j)
910 [ - + ]: 96 : if (rBoxes[j].GetLines().size())
911 : : // Iterate recursively over the Lines
912 : 0 : nLn = Max(GetRowCount(rBoxes[j]), nLn);
913 : :
914 : 48 : nLines = nLines + nLn;
915 : : }
916 : 8 : return nLines;
917 : : }
918 : :
919 : : /*--------------------------------------------------------------------
920 : : Description: Create a linear array of atmoic FndBoxes
921 : : --------------------------------------------------------------------*/
922 : 8 : void FlatFndBox::FillFlat(const _FndBox& rBox, sal_Bool bLastBox)
923 : : {
924 : 8 : sal_Bool bModRow = sal_False;
925 : 8 : const _FndLines& rLines = rBox.GetLines();
926 : :
927 : : // Iterate over Lines
928 : 8 : sal_uInt16 nOldRow = nRow;
929 [ + + ]: 56 : for( sal_uInt16 i=0; i < rLines.size(); ++i )
930 : : {
931 : : // The Boxes of a Line
932 : 48 : const _FndBoxes& rBoxes = rLines[i].GetBoxes();
933 : 48 : sal_uInt16 nOldCol = nCol;
934 [ + + ]: 144 : for( sal_uInt16 j = 0; j < rBoxes.size(); ++j )
935 : : {
936 : : // Check the Box if it's an atomic one
937 : 96 : const _FndBox *const pBox = &rBoxes[j];
938 : :
939 [ + - ]: 96 : if( !pBox->GetLines().size() )
940 : : {
941 : : // save it
942 : 96 : sal_uInt16 nOff = nRow * nCols + nCol;
943 : 96 : *(pArr + nOff) = pBox;
944 : :
945 : : // Save the Formula/Format/Value values
946 : 96 : const SwFrmFmt* pFmt = pBox->GetBox()->GetFrmFmt();
947 [ + + ][ + + : 192 : if( SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_FORMAT ) ||
+ - - + ]
948 : 48 : SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_FORMULA ) ||
949 : 48 : SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_VALUE ) )
950 : : {
951 : 48 : SfxItemSet* pSet = new SfxItemSet( pDoc->GetAttrPool(),
952 : : RES_BOXATR_FORMAT, RES_BOXATR_VALUE,
953 [ + - ]: 48 : RES_VERT_ORIENT, RES_VERT_ORIENT, 0 );
954 : 48 : pSet->Put( pFmt->GetAttrSet() );
955 [ + + ]: 48 : if( !ppItemSets )
956 : : {
957 : 8 : ppItemSets = new SfxItemSet*[ nRows * nCols ];
958 : 8 : memset( ppItemSets, 0, sizeof(SfxItemSet*) * nRows * nCols );
959 : : }
960 : 48 : *(ppItemSets + nOff ) = pSet;
961 : : }
962 : :
963 : 96 : bModRow = sal_True;
964 : : }
965 : : else
966 : : {
967 : : // Iterate recursively over the Lines of a Box
968 : 0 : FillFlat( *pBox, ( j == rBoxes.size()-1 ) );
969 : : }
970 : 96 : nCol++;
971 : : }
972 [ + - ]: 48 : if(bModRow)
973 : 48 : nRow++;
974 : 48 : nCol = nOldCol;
975 : : }
976 [ + - ]: 8 : if(!bLastBox)
977 : 8 : nRow = nOldRow;
978 : 8 : }
979 : :
980 : : /*--------------------------------------------------------------------
981 : : Description: Access a specific Cell
982 : : --------------------------------------------------------------------*/
983 : 664 : const _FndBox* FlatFndBox::GetBox(sal_uInt16 n_Col, sal_uInt16 n_Row) const
984 : : {
985 : 664 : sal_uInt16 nOff = n_Row * nCols + n_Col;
986 : 664 : const _FndBox* pTmp = *(pArr + nOff);
987 : :
988 : : OSL_ENSURE(n_Col < nCols && n_Row < nRows && pTmp, "invalid array access");
989 : 664 : return pTmp;
990 : : }
991 : :
992 : 76 : const SfxItemSet* FlatFndBox::GetItemSet(sal_uInt16 n_Col, sal_uInt16 n_Row) const
993 : : {
994 : : OSL_ENSURE( !ppItemSets || ( n_Col < nCols && n_Row < nRows), "invalid array access");
995 : :
996 [ + - ]: 76 : return ppItemSets ? *(ppItemSets + (n_Row * nCols + n_Col )) : 0;
997 : : }
998 : :
999 : 96 : sal_uInt16 SwMovedBoxes::GetPos(const SwTableBox* pTableBox) const
1000 : : {
1001 [ + - ]: 96 : const_iterator it = std::find(begin(), end(), pTableBox);
1002 [ + - ][ + + ]: 96 : return it == end() ? USHRT_MAX : it - begin();
[ + - ][ + + ]
[ # # ]
1003 : : }
1004 : :
1005 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|