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 "scitems.hxx"
30 : : #include <svx/algitem.hxx>
31 : : #include <editeng/boxitem.hxx>
32 : : #include <editeng/bolnitem.hxx>
33 : : #include <editeng/frmdiritem.hxx>
34 : : #include <editeng/shaditem.hxx>
35 : : #include <editeng/editobj.hxx>
36 : : #include <editeng/justifyitem.hxx>
37 : : #include <svl/poolcach.hxx>
38 : : #include <editeng/fontitem.hxx>
39 : : #include <unotools/fontcvt.hxx>
40 : :
41 : : #include "attarray.hxx"
42 : : #include "global.hxx"
43 : : #include "document.hxx"
44 : : #include "docpool.hxx"
45 : : #include "patattr.hxx"
46 : : #include "stlsheet.hxx"
47 : : #include "stlpool.hxx"
48 : : #include "markarr.hxx"
49 : : #include "rechead.hxx"
50 : : #include "globstr.hrc"
51 : : #include "segmenttree.hxx"
52 : : #include "cell.hxx"
53 : : #include <rtl/strbuf.hxx>
54 : :
55 : : // STATIC DATA -----------------------------------------------------------
56 : :
57 : : //------------------------------------------------------------------------
58 : : using ::editeng::SvxBorderLine;
59 : :
60 : 1982464 : ScAttrArray::ScAttrArray( SCCOL nNewCol, SCTAB nNewTab, ScDocument* pDoc ) :
61 : : nCol( nNewCol ),
62 : : nTab( nNewTab ),
63 : 1982464 : pDocument( pDoc )
64 : : {
65 : 1982464 : nCount = nLimit = 1;
66 : 1982464 : pData = new ScAttrEntry[1];
67 [ + - ]: 1982464 : if (pData)
68 : : {
69 : 1982464 : pData[0].nRow = MAXROW;
70 : 1982464 : pData[0].pPattern = pDocument->GetDefPattern(); // no put
71 : : }
72 : 1982464 : }
73 : :
74 : : //------------------------------------------------------------------------
75 : :
76 : 1787904 : ScAttrArray::~ScAttrArray()
77 : : {
78 : : #if OSL_DEBUG_LEVEL > 1
79 : : TestData();
80 : : #endif
81 : :
82 [ + - ]: 1787904 : if (pData)
83 : : {
84 : 1787904 : ScDocumentPool* pDocPool = pDocument->GetPool();
85 [ + + ]: 3587934 : for (SCSIZE i=0; i<nCount; i++)
86 : 1800030 : pDocPool->Remove(*pData[i].pPattern);
87 : :
88 [ + - ]: 1787904 : delete[] pData;
89 : : }
90 : 1787904 : }
91 : :
92 : : //------------------------------------------------------------------------
93 : : #if OSL_DEBUG_LEVEL > 1
94 : : void ScAttrArray::TestData() const
95 : : {
96 : :
97 : : sal_uInt16 nErr = 0;
98 : : if (pData)
99 : : {
100 : : SCSIZE nPos;
101 : : for (nPos=0; nPos<nCount; nPos++)
102 : : {
103 : : if (nPos > 0)
104 : : if (pData[nPos].pPattern == pData[nPos-1].pPattern || pData[nPos].nRow <= pData[nPos-1].nRow)
105 : : ++nErr;
106 : : if (pData[nPos].pPattern->Which() != ATTR_PATTERN)
107 : : ++nErr;
108 : : }
109 : : if ( nPos && pData[nPos-1].nRow != MAXROW )
110 : : ++nErr;
111 : : }
112 : : if (nErr)
113 : : {
114 : : rtl::OStringBuffer aMsg;
115 : : aMsg.append(static_cast<sal_Int32>(nErr));
116 : : aMsg.append(RTL_CONSTASCII_STRINGPARAM(
117 : : " errors in attribute array, column "));
118 : : aMsg.append(static_cast<sal_Int32>(nCol));
119 : : OSL_FAIL(aMsg.getStr());
120 : : }
121 : : }
122 : : #endif
123 : :
124 : : //------------------------------------------------------------------------
125 : :
126 : 42925 : void ScAttrArray::Reset( const ScPatternAttr* pPattern, bool bAlloc )
127 : : {
128 [ + - ]: 42925 : if (pData)
129 : : {
130 [ + - ]: 42925 : ScDocumentPool* pDocPool = pDocument->GetPool();
131 : : const ScPatternAttr* pOldPattern;
132 : 42925 : ScAddress aAdrStart( nCol, 0, nTab );
133 : 42925 : ScAddress aAdrEnd ( nCol, 0, nTab );
134 : :
135 [ + + ]: 85850 : for (SCSIZE i=0; i<nCount; i++)
136 : : {
137 : : // ensure that attributing changes text width of cell
138 : 42925 : pOldPattern = pData[i].pPattern;
139 : : bool bNumFormatChanged;
140 [ - + ]: 42925 : if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
141 [ + - ]: 42925 : pPattern->GetItemSet(), pOldPattern->GetItemSet() ) )
142 : : {
143 [ # # ]: 0 : aAdrStart.SetRow( i ? pData[i-1].nRow+1 : 0 );
144 : 0 : aAdrEnd .SetRow( pData[i].nRow );
145 [ # # ]: 0 : pDocument->InvalidateTextWidth( &aAdrStart, &aAdrEnd, bNumFormatChanged );
146 : : }
147 [ + - ]: 42925 : pDocPool->Remove(*pOldPattern);
148 : : }
149 [ + - ]: 42925 : delete[] pData;
150 : :
151 [ + - ][ - + ]: 42925 : if (pDocument->IsStreamValid(nTab))
152 [ # # ]: 0 : pDocument->SetStreamValid(nTab, false);
153 : :
154 [ + - ]: 42925 : if (bAlloc)
155 : : {
156 : 42925 : nCount = nLimit = 1;
157 [ + - ]: 42925 : pData = new ScAttrEntry[1];
158 [ + - ]: 42925 : if (pData)
159 : : {
160 [ + - ]: 42925 : ScPatternAttr* pNewPattern = (ScPatternAttr*) &pDocPool->Put(*pPattern);
161 : 42925 : pData[0].nRow = MAXROW;
162 : 42925 : pData[0].pPattern = pNewPattern;
163 : : }
164 : : }
165 : : else
166 : : {
167 : 0 : nCount = nLimit = 0;
168 : 42925 : pData = NULL; // should be immediately occupied again
169 : : }
170 : : }
171 : 42925 : }
172 : :
173 : :
174 : 49535 : bool ScAttrArray::Concat(SCSIZE nPos)
175 : : {
176 : 49535 : bool bRet = false;
177 [ + - ][ + - ]: 49535 : if (pData && (nPos < nCount))
178 : : {
179 [ + + ]: 49535 : if (nPos > 0)
180 : : {
181 [ - + ]: 167 : if (pData[nPos - 1].pPattern == pData[nPos].pPattern)
182 : : {
183 : 0 : pData[nPos - 1].nRow = pData[nPos].nRow;
184 : 0 : pDocument->GetPool()->Remove(*pData[nPos].pPattern);
185 : 0 : memmove(&pData[nPos], &pData[nPos + 1], (nCount - nPos - 1) * sizeof(ScAttrEntry));
186 : 0 : pData[nCount - 1].pPattern = NULL;
187 : 0 : pData[nCount - 1].nRow = 0;
188 : 0 : nCount--;
189 : 0 : nPos--;
190 : 0 : bRet = true;
191 : : }
192 : : }
193 [ + + ]: 49535 : if (nPos + 1 < nCount)
194 : : {
195 [ - + ]: 1913 : if (pData[nPos + 1].pPattern == pData[nPos].pPattern)
196 : : {
197 : 0 : pData[nPos].nRow = pData[nPos + 1].nRow;
198 : 0 : pDocument->GetPool()->Remove(*pData[nPos].pPattern);
199 : 0 : memmove(&pData[nPos + 1], &pData[nPos + 2], (nCount - nPos - 2) * sizeof(ScAttrEntry));
200 : 0 : pData[nCount - 1].pPattern = NULL;
201 : 0 : pData[nCount - 1].nRow = 0;
202 : 0 : nCount--;
203 : 0 : bRet = true;
204 : : }
205 : : }
206 : : }
207 : 49535 : return bRet;
208 : : }
209 : :
210 : : //------------------------------------------------------------------------
211 : :
212 : 16905770 : bool ScAttrArray::Search( SCROW nRow, SCSIZE& nIndex ) const
213 : : {
214 : 16905770 : long nHi = static_cast<long>(nCount) - 1;
215 : 16905770 : long i = 0;
216 : 16905770 : bool bFound = (nCount == 1);
217 [ + - ]: 16905770 : if (pData)
218 : : {
219 : 16905770 : long nLo = 0;
220 : 16905770 : long nStartRow = 0;
221 : 16905770 : long nEndRow = 0;
222 [ + + ][ + + ]: 17097551 : while ( !bFound && nLo <= nHi )
[ + + ]
223 : : {
224 : 191781 : i = (nLo + nHi) / 2;
225 [ + + ]: 191781 : if (i > 0)
226 : 153788 : nStartRow = (long) pData[i - 1].nRow;
227 : : else
228 : 37993 : nStartRow = -1;
229 : 191781 : nEndRow = (long) pData[i].nRow;
230 [ + + ]: 191781 : if (nEndRow < (long) nRow)
231 : 65454 : nLo = ++i;
232 : : else
233 [ + + ]: 126327 : if (nStartRow >= (long) nRow)
234 : 34812 : nHi = --i;
235 : : else
236 : 91515 : bFound = true;
237 : : }
238 : : }
239 : : else
240 : 0 : bFound = false;
241 : :
242 [ + + ]: 16905770 : if (bFound)
243 : 16903206 : nIndex=(SCSIZE)i;
244 : : else
245 : 2564 : nIndex=0;
246 : 16905770 : return bFound;
247 : : }
248 : :
249 : :
250 : 88851 : const ScPatternAttr* ScAttrArray::GetPattern( SCROW nRow ) const
251 : : {
252 : : SCSIZE i;
253 [ + - ]: 88851 : if (Search( nRow, i ))
254 : 88851 : return pData[i].pPattern;
255 : : else
256 : 88851 : return NULL;
257 : : }
258 : :
259 : :
260 : 0 : const ScPatternAttr* ScAttrArray::GetPatternRange( SCROW& rStartRow,
261 : : SCROW& rEndRow, SCROW nRow ) const
262 : : {
263 : : SCSIZE nIndex;
264 [ # # ]: 0 : if ( Search( nRow, nIndex ) )
265 : : {
266 [ # # ]: 0 : if ( nIndex > 0 )
267 : 0 : rStartRow = pData[nIndex-1].nRow + 1;
268 : : else
269 : 0 : rStartRow = 0;
270 : 0 : rEndRow = pData[nIndex].nRow;
271 : 0 : return pData[nIndex].pPattern;
272 : : }
273 : 0 : return NULL;
274 : : }
275 : :
276 : : //------------------------------------------------------------------------
277 : :
278 : 1140 : void ScAttrArray::SetPattern( SCROW nRow, const ScPatternAttr* pPattern, bool bPutToPool )
279 : : {
280 : 1140 : SetPatternArea( nRow, nRow, pPattern, bPutToPool );
281 : 1140 : }
282 : :
283 : 0 : void ScAttrArray::RemoveCellCharAttribs( SCROW nStartRow, SCROW nEndRow,
284 : : const ScPatternAttr* pPattern, ScEditDataArray* pDataArray )
285 : : {
286 [ # # ]: 0 : for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow)
287 : : {
288 : : ScBaseCell* pCell;
289 [ # # ]: 0 : pDocument->GetCell(nCol, nRow, nTab, pCell);
290 [ # # ][ # # ]: 0 : if (pCell && pCell->GetCellType() == CELLTYPE_EDIT)
[ # # ]
291 : : {
292 : 0 : EditTextObject* pOldData = NULL;
293 : 0 : ScEditCell* pEditCell = static_cast<ScEditCell*>(pCell);
294 [ # # ]: 0 : if (pDataArray)
295 [ # # ]: 0 : pOldData = pEditCell->GetData()->Clone();
296 [ # # ]: 0 : pEditCell->RemoveCharAttribs(*pPattern);
297 [ # # ]: 0 : if (pDataArray)
298 : : {
299 [ # # ]: 0 : EditTextObject* pNewData = pEditCell->GetData()->Clone();
300 [ # # ]: 0 : pDataArray->AddItem(nTab, nCol, nRow, pOldData, pNewData);
301 : : }
302 : : }
303 : : }
304 : 0 : }
305 : :
306 : 82311 : void ScAttrArray::SetPatternArea(SCROW nStartRow, SCROW nEndRow, const ScPatternAttr *pPattern,
307 : : bool bPutToPool, ScEditDataArray* pDataArray )
308 : : {
309 [ + - ][ + - ]: 82311 : if (ValidRow(nStartRow) && ValidRow(nEndRow))
[ + - ]
310 : : {
311 [ + + ]: 82311 : if (bPutToPool)
312 : 12106 : pPattern = (const ScPatternAttr*) &pDocument->GetPool()->Put(*pPattern);
313 : :
314 [ + + ][ + + ]: 82311 : if ((nStartRow == 0) && (nEndRow == MAXROW))
315 : 42925 : Reset(pPattern);
316 : : else
317 : : {
318 : 39386 : SCSIZE nNeeded = nCount + 2;
319 [ + + ]: 39386 : if ( nLimit < nNeeded )
320 : : {
321 : 18864 : nLimit += SC_ATTRARRAY_DELTA;
322 [ - + ]: 18864 : if ( nLimit < nNeeded )
323 : 0 : nLimit = nNeeded;
324 [ + - ]: 18864 : ScAttrEntry* pNewData = new ScAttrEntry[nLimit];
325 : 18864 : memcpy( pNewData, pData, nCount*sizeof(ScAttrEntry) );
326 [ + - ]: 18864 : delete[] pData;
327 : 18864 : pData = pNewData;
328 : : }
329 : :
330 : 39386 : ScAddress aAdrStart( nCol, 0, nTab );
331 : 39386 : ScAddress aAdrEnd ( nCol, 0, nTab );
332 : :
333 : 39386 : SCSIZE ni = 0; // number of entries in beginning
334 : 39386 : SCSIZE nx = 0; // track position
335 : 39386 : SCROW ns = 0; // start row of track position
336 [ + + ]: 39386 : if ( nStartRow > 0 )
337 : : {
338 : : // skip beginning
339 : : SCSIZE nIndex;
340 : 26832 : Search( nStartRow, nIndex );
341 : 26832 : ni = nIndex;
342 : :
343 [ + + ]: 26832 : if ( ni > 0 )
344 : : {
345 : 15967 : nx = ni;
346 : 26832 : ns = pData[ni-1].nRow+1;
347 : : }
348 : : }
349 : :
350 : : // ensure that attributing changes text width of cell
351 : : // otherwise, conditional formats need to be reset or deleted
352 [ + + ]: 80869 : while ( ns <= nEndRow )
353 : : {
354 : 41483 : const SfxItemSet& rNewSet = pPattern->GetItemSet();
355 : 41483 : const SfxItemSet& rOldSet = pData[nx].pPattern->GetItemSet();
356 : :
357 : : bool bNumFormatChanged;
358 [ + + ]: 41483 : if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
359 [ + - ]: 41483 : rNewSet, rOldSet ) )
360 : : {
361 : 4791 : aAdrStart.SetRow( Max(nStartRow,ns) );
362 : 4791 : aAdrEnd .SetRow( Min(nEndRow,pData[nx].nRow) );
363 [ + - ]: 4791 : pDocument->InvalidateTextWidth( &aAdrStart, &aAdrEnd, bNumFormatChanged );
364 : : }
365 : 41483 : ns = pData[nx].nRow + 1;
366 : 41483 : nx++;
367 : : }
368 : :
369 : : // continue modifying data array
370 : :
371 : : SCSIZE nInsert; // insert position (MAXROWCOUNT := no insert)
372 : 39386 : bool bCombined = false;
373 : 39386 : bool bSplit = false;
374 [ + + ]: 39386 : if ( nStartRow > 0 )
375 : : {
376 : 26832 : nInsert = MAXROWCOUNT;
377 [ + + ]: 26832 : if ( pData[ni].pPattern != pPattern )
378 : : {
379 [ + + ][ + + ]: 17764 : if ( ni == 0 || (pData[ni-1].nRow < nStartRow - 1) )
380 : : { // may be a split or a simple insert or just a shrink,
381 : : // row adjustment is done further down
382 [ + + ]: 3161 : if ( pData[ni].nRow > nEndRow )
383 : 1993 : bSplit = true;
384 : 3161 : ni++;
385 : 3161 : nInsert = ni;
386 : : }
387 [ + - ][ + - ]: 14603 : else if ( ni > 0 && pData[ni-1].nRow == nStartRow - 1 )
388 : 17764 : nInsert = ni;
389 : : }
390 [ + + ][ + + ]: 26832 : if ( ni > 0 && pData[ni-1].pPattern == pPattern )
391 : : { // combine
392 : 1668 : pData[ni-1].nRow = nEndRow;
393 : 1668 : nInsert = MAXROWCOUNT;
394 : 1668 : bCombined = true;
395 : : }
396 : : }
397 : : else
398 : 12554 : nInsert = 0;
399 : :
400 : 39386 : SCSIZE nj = ni; // stop position of range to replace
401 [ + + ][ + + ]: 52827 : while ( nj < nCount && pData[nj].nRow <= nEndRow )
[ + + ]
402 : 13441 : nj++;
403 [ + + ]: 39386 : if ( !bSplit )
404 : : {
405 [ + + ][ + + ]: 37393 : if ( nj < nCount && pData[nj].pPattern == pPattern )
406 : : { // combine
407 [ + + ]: 16588 : if ( ni > 0 )
408 : : {
409 [ + + ]: 333 : if ( pData[ni-1].pPattern == pPattern )
410 : : { // adjacent entries
411 : 231 : pData[ni-1].nRow = pData[nj].nRow;
412 : 231 : nj++;
413 : : }
414 [ + + ]: 102 : else if ( ni == nInsert )
415 : 18 : pData[ni-1].nRow = nStartRow - 1; // shrink
416 : : }
417 : 16588 : nInsert = MAXROWCOUNT;
418 : 16588 : bCombined = true;
419 : : }
420 [ + + ][ + + ]: 20805 : else if ( ni > 0 && ni == nInsert )
421 : 37393 : pData[ni-1].nRow = nStartRow - 1; // shrink
422 : : }
423 [ + - ]: 39386 : ScDocumentPool* pDocPool = pDocument->GetPool();
424 [ + + ]: 39386 : if ( bSplit )
425 : : { // duplicate splitted entry in pool
426 [ + - ]: 1993 : pDocPool->Put( *pData[ni-1].pPattern );
427 : : }
428 [ + + ]: 39386 : if ( ni < nj )
429 : : { // remove middle entries
430 [ + + ]: 25044 : for ( SCSIZE nk=ni; nk<nj; nk++)
431 : : { // remove entries from pool
432 [ + - ]: 13672 : pDocPool->Remove( *pData[nk].pPattern );
433 : : }
434 [ + + ]: 11372 : if ( !bCombined )
435 : : { // replace one entry
436 : 10592 : pData[ni].nRow = nEndRow;
437 : 10592 : pData[ni].pPattern = pPattern;
438 : 10592 : ni++;
439 : 10592 : nInsert = MAXROWCOUNT;
440 : : }
441 [ + + ]: 11372 : if ( ni < nj )
442 : : { // remove entries
443 : 784 : memmove( pData + ni, pData + nj, (nCount - nj) * sizeof(ScAttrEntry) );
444 : 784 : nCount -= nj - ni;
445 : : }
446 : : }
447 : :
448 [ + + ]: 39386 : if ( nInsert < sal::static_int_cast<SCSIZE>(MAXROWCOUNT) )
449 : : { // insert or append new entry
450 [ + - ]: 10769 : if ( nInsert <= nCount )
451 : : {
452 [ + + ]: 10769 : if ( !bSplit )
453 : 8776 : memmove( pData + nInsert + 1, pData + nInsert,
454 : 8776 : (nCount - nInsert) * sizeof(ScAttrEntry) );
455 : : else
456 : : {
457 : 1993 : memmove( pData + nInsert + 2, pData + nInsert,
458 : 3986 : (nCount - nInsert) * sizeof(ScAttrEntry) );
459 : 1993 : pData[nInsert+1] = pData[nInsert-1];
460 : 1993 : nCount++;
461 : : }
462 : : }
463 [ + + ]: 10769 : if ( nInsert )
464 : 8269 : pData[nInsert-1].nRow = nStartRow - 1;
465 : 10769 : pData[nInsert].nRow = nEndRow;
466 : 10769 : pData[nInsert].pPattern = pPattern;
467 : :
468 : : // Remove character attributes from these cells if the pattern
469 : : // is applied during normal session.
470 [ - + ]: 10769 : if (pDataArray)
471 [ # # ]: 0 : RemoveCellCharAttribs(nStartRow, nEndRow, pPattern, pDataArray);
472 : :
473 : 10769 : nCount++;
474 : : }
475 : :
476 [ + - ][ + + ]: 39386 : if (pDocument->IsStreamValid(nTab))
477 [ + - ]: 82311 : pDocument->SetStreamValid(nTab, false);
478 : : }
479 : : }
480 : :
481 : : #if OSL_DEBUG_LEVEL > 1
482 : : TestData();
483 : : #endif
484 : 82311 : }
485 : :
486 : :
487 : 7013 : void ScAttrArray::ApplyStyleArea( SCROW nStartRow, SCROW nEndRow, ScStyleSheet* pStyle )
488 : : {
489 [ + - ][ + - ]: 7013 : if (ValidRow(nStartRow) && ValidRow(nEndRow))
[ + - ]
490 : : {
491 : : SCSIZE nPos;
492 : 7013 : SCROW nStart=0;
493 [ + - ]: 7013 : if (!Search( nStartRow, nPos ))
494 : : {
495 : : OSL_FAIL("Search Failure");
496 : 7013 : return;
497 : : }
498 : :
499 : 7013 : ScAddress aAdrStart( nCol, 0, nTab );
500 : 7013 : ScAddress aAdrEnd ( nCol, 0, nTab );
501 : :
502 [ + + ][ + - ]: 7281 : do
[ + + ]
503 : : {
504 : 7281 : const ScPatternAttr* pOldPattern = pData[nPos].pPattern;
505 [ + - ][ + - ]: 7281 : ScPatternAttr* pNewPattern = new ScPatternAttr(*pOldPattern);
506 [ + - ]: 7281 : pNewPattern->SetStyleSheet(pStyle);
507 : 7281 : SCROW nY1 = nStart;
508 : 7281 : SCROW nY2 = pData[nPos].nRow;
509 : 7281 : nStart = pData[nPos].nRow + 1;
510 : :
511 [ + - ][ + + ]: 7281 : if ( *pNewPattern == *pOldPattern )
512 : : {
513 : : // keep the original pattern (might be default)
514 : : // pNewPattern is deleted below
515 : 4078 : nPos++;
516 : : }
517 [ + + ][ + + ]: 3203 : else if ( nY1 < nStartRow || nY2 > nEndRow )
518 : : {
519 [ + + ]: 3010 : if (nY1 < nStartRow) nY1=nStartRow;
520 [ + + ]: 3010 : if (nY2 > nEndRow) nY2=nEndRow;
521 [ + - ]: 3010 : SetPatternArea( nY1, nY2, pNewPattern, true );
522 : 3010 : Search( nStart, nPos );
523 : : }
524 : : else
525 : : {
526 : : // ensure attributing changes text width of cell; otherwise
527 : : // there aren't (yet) template format changes
528 : 193 : const SfxItemSet& rNewSet = pNewPattern->GetItemSet();
529 : 193 : const SfxItemSet& rOldSet = pOldPattern->GetItemSet();
530 : :
531 : : bool bNumFormatChanged;
532 [ + + ]: 193 : if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
533 [ + - ]: 193 : rNewSet, rOldSet ) )
534 : : {
535 [ + - ]: 7 : aAdrStart.SetRow( nPos ? pData[nPos-1].nRow+1 : 0 );
536 : 7 : aAdrEnd .SetRow( pData[nPos].nRow );
537 [ + - ]: 7 : pDocument->InvalidateTextWidth( &aAdrStart, &aAdrEnd, bNumFormatChanged );
538 : : }
539 : :
540 [ + - ][ + - ]: 193 : pDocument->GetPool()->Remove(*pData[nPos].pPattern);
541 : 193 : pData[nPos].pPattern = (const ScPatternAttr*)
542 [ + - ][ + - ]: 193 : &pDocument->GetPool()->Put(*pNewPattern);
543 [ + - ][ - + ]: 193 : if (Concat(nPos))
544 : 0 : Search(nStart, nPos);
545 : : else
546 : 193 : nPos++;
547 : : }
548 [ + - ][ + - ]: 7281 : delete pNewPattern;
549 : : }
550 : : while ((nStart <= nEndRow) && (nPos < nCount));
551 : :
552 [ + - ][ - + ]: 7013 : if (pDocument->IsStreamValid(nTab))
553 [ # # ]: 7013 : pDocument->SetStreamValid(nTab, false);
554 : : }
555 : :
556 : : #if OSL_DEBUG_LEVEL > 1
557 : : TestData();
558 : : #endif
559 : : }
560 : :
561 : :
562 : : // const cast, otherwise it will be too inefficient/complicated
563 : : #define SET_LINECOLOR(dest,c) \
564 : : if ((dest)) \
565 : : { \
566 : : ((SvxBorderLine*)(dest))->SetColor((c)); \
567 : : }
568 : :
569 : : #define SET_LINE(dest,src) \
570 : : if ((dest)) \
571 : : { \
572 : : SvxBorderLine* pCast = (SvxBorderLine*)(dest); \
573 : : pCast->SetBorderLineStyle( (src)->GetBorderLineStyle() ); \
574 : : pCast->SetWidth( (src)->GetWidth( ) ); \
575 : : }
576 : :
577 : 0 : void ScAttrArray::ApplyLineStyleArea( SCROW nStartRow, SCROW nEndRow,
578 : : const SvxBorderLine* pLine, bool bColorOnly )
579 : : {
580 [ # # ][ # # ]: 0 : if ( bColorOnly && !pLine )
581 : 0 : return;
582 : :
583 [ # # ][ # # ]: 0 : if (ValidRow(nStartRow) && ValidRow(nEndRow))
[ # # ]
584 : : {
585 : : SCSIZE nPos;
586 : 0 : SCROW nStart=0;
587 [ # # ]: 0 : if (!Search( nStartRow, nPos ))
588 : : {
589 : : OSL_FAIL("Search failure");
590 : : return;
591 : : }
592 : :
593 [ # # ][ # # ]: 0 : do
[ # # ]
594 : : {
595 : 0 : const ScPatternAttr* pOldPattern = pData[nPos].pPattern;
596 : 0 : const SfxItemSet& rOldSet = pOldPattern->GetItemSet();
597 : 0 : const SfxPoolItem* pBoxItem = 0;
598 [ # # ]: 0 : SfxItemState eState = rOldSet.GetItemState( ATTR_BORDER, true, &pBoxItem );
599 : 0 : const SfxPoolItem* pTLBRItem = 0;
600 [ # # ]: 0 : SfxItemState eTLBRState = rOldSet.GetItemState( ATTR_BORDER_TLBR, true, &pTLBRItem );
601 : 0 : const SfxPoolItem* pBLTRItem = 0;
602 [ # # ]: 0 : SfxItemState eBLTRState = rOldSet.GetItemState( ATTR_BORDER_BLTR, true, &pBLTRItem );
603 : :
604 [ # # ][ # # ]: 0 : if ( (SFX_ITEM_SET == eState) || (SFX_ITEM_SET == eTLBRState) || (SFX_ITEM_SET == eBLTRState) )
[ # # ]
605 : : {
606 [ # # ][ # # ]: 0 : ScPatternAttr* pNewPattern = new ScPatternAttr(*pOldPattern);
607 : 0 : SfxItemSet& rNewSet = pNewPattern->GetItemSet();
608 : 0 : SCROW nY1 = nStart;
609 : 0 : SCROW nY2 = pData[nPos].nRow;
610 : :
611 [ # # ][ # # ]: 0 : SvxBoxItem* pNewBoxItem = pBoxItem ? (SvxBoxItem*)pBoxItem->Clone() : 0;
612 [ # # ][ # # ]: 0 : SvxLineItem* pNewTLBRItem = pTLBRItem ? (SvxLineItem*)pTLBRItem->Clone() : 0;
613 [ # # ][ # # ]: 0 : SvxLineItem* pNewBLTRItem = pBLTRItem ? (SvxLineItem*)pBLTRItem->Clone() : 0;
614 : :
615 : : // fetch line and update attributes with parameters
616 : :
617 [ # # ]: 0 : if ( !pLine )
618 : : {
619 [ # # ]: 0 : if( pNewBoxItem )
620 : : {
621 [ # # ][ # # ]: 0 : if ( pNewBoxItem->GetTop() ) pNewBoxItem->SetLine( NULL, BOX_LINE_TOP );
622 [ # # ][ # # ]: 0 : if ( pNewBoxItem->GetBottom() ) pNewBoxItem->SetLine( NULL, BOX_LINE_BOTTOM );
623 [ # # ][ # # ]: 0 : if ( pNewBoxItem->GetLeft() ) pNewBoxItem->SetLine( NULL, BOX_LINE_LEFT );
624 [ # # ][ # # ]: 0 : if ( pNewBoxItem->GetRight() ) pNewBoxItem->SetLine( NULL, BOX_LINE_RIGHT );
625 : : }
626 [ # # ][ # # ]: 0 : if( pNewTLBRItem && pNewTLBRItem->GetLine() )
[ # # ]
627 [ # # ]: 0 : pNewTLBRItem->SetLine( 0 );
628 [ # # ][ # # ]: 0 : if( pNewBLTRItem && pNewBLTRItem->GetLine() )
[ # # ]
629 [ # # ]: 0 : pNewBLTRItem->SetLine( 0 );
630 : : }
631 : : else
632 : : {
633 [ # # ]: 0 : if ( bColorOnly )
634 : : {
635 : 0 : Color aColor( pLine->GetColor() );
636 [ # # ]: 0 : if( pNewBoxItem )
637 : : {
638 [ # # ]: 0 : SET_LINECOLOR( pNewBoxItem->GetTop(), aColor );
639 [ # # ]: 0 : SET_LINECOLOR( pNewBoxItem->GetBottom(), aColor );
640 [ # # ]: 0 : SET_LINECOLOR( pNewBoxItem->GetLeft(), aColor );
641 [ # # ]: 0 : SET_LINECOLOR( pNewBoxItem->GetRight(), aColor );
642 : : }
643 [ # # ]: 0 : if( pNewTLBRItem )
644 [ # # ]: 0 : SET_LINECOLOR( pNewTLBRItem->GetLine(), aColor );
645 [ # # ]: 0 : if( pNewBLTRItem )
646 [ # # ]: 0 : SET_LINECOLOR( pNewBLTRItem->GetLine(), aColor );
647 : : }
648 : : else
649 : : {
650 [ # # ]: 0 : if( pNewBoxItem )
651 : : {
652 [ # # ][ # # ]: 0 : SET_LINE( pNewBoxItem->GetTop(), pLine );
653 [ # # ][ # # ]: 0 : SET_LINE( pNewBoxItem->GetBottom(), pLine );
654 [ # # ][ # # ]: 0 : SET_LINE( pNewBoxItem->GetLeft(), pLine );
655 [ # # ][ # # ]: 0 : SET_LINE( pNewBoxItem->GetRight(), pLine );
656 : : }
657 [ # # ]: 0 : if( pNewTLBRItem )
658 [ # # ][ # # ]: 0 : SET_LINE( pNewTLBRItem->GetLine(), pLine );
659 [ # # ]: 0 : if( pNewBLTRItem )
660 [ # # ][ # # ]: 0 : SET_LINE( pNewBLTRItem->GetLine(), pLine );
661 : : }
662 : : }
663 [ # # ][ # # ]: 0 : if( pNewBoxItem ) rNewSet.Put( *pNewBoxItem );
664 [ # # ][ # # ]: 0 : if( pNewTLBRItem ) rNewSet.Put( *pNewTLBRItem );
665 [ # # ][ # # ]: 0 : if( pNewBLTRItem ) rNewSet.Put( *pNewBLTRItem );
666 : :
667 : 0 : nStart = pData[nPos].nRow + 1;
668 : :
669 [ # # ][ # # ]: 0 : if ( nY1 < nStartRow || nY2 > nEndRow )
670 : : {
671 [ # # ]: 0 : if (nY1 < nStartRow) nY1=nStartRow;
672 [ # # ]: 0 : if (nY2 > nEndRow) nY2=nEndRow;
673 [ # # ]: 0 : SetPatternArea( nY1, nY2, pNewPattern, true );
674 : 0 : Search( nStart, nPos );
675 : : }
676 : : else
677 : : {
678 : : // remove from pool ?
679 [ # # ][ # # ]: 0 : pDocument->GetPool()->Remove(*pData[nPos].pPattern);
680 : 0 : pData[nPos].pPattern = (const ScPatternAttr*)
681 [ # # ][ # # ]: 0 : &pDocument->GetPool()->Put(*pNewPattern);
682 : :
683 [ # # ][ # # ]: 0 : if (Concat(nPos))
684 : 0 : Search(nStart, nPos);
685 : : else
686 : 0 : nPos++;
687 : : }
688 [ # # ][ # # ]: 0 : delete pNewBoxItem;
689 [ # # ][ # # ]: 0 : delete pNewTLBRItem;
690 [ # # ][ # # ]: 0 : delete pNewBLTRItem;
691 [ # # ][ # # ]: 0 : delete pNewPattern;
692 : : }
693 : : else
694 : : {
695 : 0 : nStart = pData[nPos].nRow + 1;
696 : 0 : nPos++;
697 : : }
698 : : }
699 : : while ((nStart <= nEndRow) && (nPos < nCount));
700 : : }
701 : : }
702 : :
703 : : #undef SET_LINECOLOR
704 : : #undef SET_LINE
705 : :
706 : :
707 : 54867 : void ScAttrArray::ApplyCacheArea( SCROW nStartRow, SCROW nEndRow, SfxItemPoolCache* pCache, ScEditDataArray* pDataArray )
708 : : {
709 : : #if OSL_DEBUG_LEVEL > 1
710 : : TestData();
711 : : #endif
712 : :
713 [ + - ][ + - ]: 54867 : if (ValidRow(nStartRow) && ValidRow(nEndRow))
[ + - ]
714 : : {
715 : : SCSIZE nPos;
716 : 54867 : SCROW nStart=0;
717 [ + - ]: 54867 : if (!Search( nStartRow, nPos ))
718 : : {
719 : : OSL_FAIL("Search Failure");
720 : 54867 : return;
721 : : }
722 : :
723 : 54867 : ScAddress aAdrStart( nCol, 0, nTab );
724 : 54867 : ScAddress aAdrEnd ( nCol, 0, nTab );
725 : :
726 [ + + ]: 54921 : do
727 : : {
728 : 54921 : const ScPatternAttr* pOldPattern = pData[nPos].pPattern;
729 [ + - ]: 54921 : const ScPatternAttr* pNewPattern = (const ScPatternAttr*) &pCache->ApplyTo( *pOldPattern, true );
730 [ + - ]: 54921 : ScDocumentPool::CheckRef( *pOldPattern );
731 [ + - ]: 54921 : ScDocumentPool::CheckRef( *pNewPattern );
732 [ + + ]: 54921 : if (pNewPattern != pOldPattern)
733 : : {
734 : 54464 : SCROW nY1 = nStart;
735 : 54464 : SCROW nY2 = pData[nPos].nRow;
736 : 54464 : nStart = pData[nPos].nRow + 1;
737 : :
738 [ + + ][ + + ]: 54464 : if ( nY1 < nStartRow || nY2 > nEndRow )
739 : : {
740 [ + + ]: 5122 : if (nY1 < nStartRow) nY1=nStartRow;
741 [ + + ]: 5122 : if (nY2 > nEndRow) nY2=nEndRow;
742 [ + - ]: 5122 : SetPatternArea( nY1, nY2, pNewPattern, false, pDataArray );
743 : 5122 : Search( nStart, nPos );
744 : : }
745 : : else
746 : : {
747 : : // ensure attributing changes text-width of cell
748 : :
749 : 49342 : const SfxItemSet& rNewSet = pNewPattern->GetItemSet();
750 : 49342 : const SfxItemSet& rOldSet = pOldPattern->GetItemSet();
751 : :
752 : : bool bNumFormatChanged;
753 [ + + ]: 49342 : if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
754 [ + - ]: 49342 : rNewSet, rOldSet ) )
755 : : {
756 [ + + ]: 1022 : aAdrStart.SetRow( nPos ? pData[nPos-1].nRow+1 : 0 );
757 : 1022 : aAdrEnd .SetRow( pData[nPos].nRow );
758 [ + - ]: 1022 : pDocument->InvalidateTextWidth( &aAdrStart, &aAdrEnd, bNumFormatChanged );
759 : : }
760 : :
761 [ + - ][ + - ]: 49342 : pDocument->GetPool()->Remove(*pData[nPos].pPattern);
762 : 49342 : pData[nPos].pPattern = pNewPattern;
763 [ + - ][ - + ]: 49342 : if (Concat(nPos))
764 : 0 : Search(nStart, nPos);
765 : : else
766 : 54464 : ++nPos;
767 : : }
768 : : }
769 : : else
770 : : {
771 : 457 : nStart = pData[nPos].nRow + 1;
772 : 457 : ++nPos;
773 : : }
774 : : }
775 : : while (nStart <= nEndRow);
776 : :
777 [ + - ][ - + ]: 54867 : if (pDocument->IsStreamValid(nTab))
778 [ # # ]: 54867 : pDocument->SetStreamValid(nTab, false);
779 : : }
780 : :
781 : : #if OSL_DEBUG_LEVEL > 1
782 : : TestData();
783 : : #endif
784 : : }
785 : :
786 : 24940 : bool ScAttrArray::SetAttrEntries(ScAttrEntry* pNewData, SCSIZE nSize)
787 : : {
788 [ + - ]: 24940 : if (pData)
789 : : {
790 : 24940 : ScDocumentPool* pDocPool = pDocument->GetPool();
791 [ + + ]: 49880 : for (SCSIZE i=0; i<nCount; i++)
792 : 24940 : pDocPool->Remove(*pData[i].pPattern);
793 : :
794 [ + - ]: 24940 : delete[] pData;
795 : : }
796 : :
797 : 24940 : pData = pNewData;
798 : 24940 : nCount = nLimit = nSize;
799 : 24940 : return true;
800 : : }
801 : :
802 : 46 : void lcl_MergeDeep( SfxItemSet& rMergeSet, const SfxItemSet& rSource )
803 : : {
804 : : const SfxPoolItem* pNewItem;
805 : : const SfxPoolItem* pOldItem;
806 [ + + ]: 2622 : for (sal_uInt16 nId=ATTR_PATTERN_START; nId<=ATTR_PATTERN_END; nId++)
807 : : {
808 : : // pMergeSet has no parent
809 [ + - ]: 2576 : SfxItemState eOldState = rMergeSet.GetItemState( nId, false, &pOldItem );
810 : :
811 [ + + ]: 2576 : if ( eOldState == SFX_ITEM_DEFAULT )
812 : : {
813 [ + - ]: 2282 : SfxItemState eNewState = rSource.GetItemState( nId, true, &pNewItem );
814 [ + + ]: 2282 : if ( eNewState == SFX_ITEM_SET )
815 : : {
816 [ + - ][ + - ]: 46 : if ( *pNewItem != rMergeSet.GetPool()->GetDefaultItem(nId) )
[ + + ]
817 [ + - ]: 2 : rMergeSet.InvalidateItem( nId );
818 : : }
819 : : }
820 [ + - ]: 294 : else if ( eOldState == SFX_ITEM_SET ) // Item gesetzt
821 : : {
822 [ + - ]: 294 : SfxItemState eNewState = rSource.GetItemState( nId, true, &pNewItem );
823 [ + - ]: 294 : if ( eNewState == SFX_ITEM_SET )
824 : : {
825 [ - + ]: 294 : if ( pNewItem != pOldItem ) // beide gepuhlt
826 [ # # ]: 0 : rMergeSet.InvalidateItem( nId );
827 : : }
828 : : else // Default
829 : : {
830 [ # # ][ # # ]: 0 : if ( *pOldItem != rSource.GetPool()->GetDefaultItem(nId) )
[ # # ]
831 [ # # ]: 0 : rMergeSet.InvalidateItem( nId );
832 : : }
833 : : }
834 : : // Dontcare remains Dontcare
835 : : }
836 : 46 : }
837 : :
838 : :
839 : 67318 : void ScAttrArray::MergePatternArea( SCROW nStartRow, SCROW nEndRow,
840 : : ScMergePatternState& rState, bool bDeep ) const
841 : : {
842 [ + - ][ + - ]: 67318 : if (ValidRow(nStartRow) && ValidRow(nEndRow))
[ + - ]
843 : : {
844 : : SCSIZE nPos;
845 : 67318 : SCROW nStart=0;
846 [ + - ]: 67318 : if (!Search( nStartRow, nPos ))
847 : : {
848 : : OSL_FAIL("Search failure");
849 : 67318 : return;
850 : : }
851 : :
852 [ + + ]: 67396 : do
853 : : {
854 : : // similar patterns must not be repeated
855 : :
856 : 67396 : const ScPatternAttr* pPattern = pData[nPos].pPattern;
857 [ + + ][ + + ]: 67396 : if ( pPattern != rState.pOld1 && pPattern != rState.pOld2 )
858 : : {
859 : 7349 : const SfxItemSet& rThisSet = pPattern->GetItemSet();
860 [ + + ]: 7349 : if (rState.pItemSet)
861 : : {
862 [ + - ]: 46 : if (bDeep)
863 [ + - ]: 46 : lcl_MergeDeep( *rState.pItemSet, rThisSet );
864 : : else
865 [ # # ]: 0 : rState.pItemSet->MergeValues( rThisSet, false );
866 : : }
867 : : else
868 : : {
869 : : // first pattern - copied from parent
870 [ + - ][ + - ]: 7303 : rState.pItemSet = new SfxItemSet( *rThisSet.GetPool(), rThisSet.GetRanges() );
871 [ + - ]: 7303 : rState.pItemSet->Set( rThisSet, bDeep );
872 : : }
873 : :
874 : 7349 : rState.pOld2 = rState.pOld1;
875 : 7349 : rState.pOld1 = pPattern;
876 : : }
877 : :
878 : 67396 : nStart = pData[nPos].nRow + 1;
879 : 67396 : ++nPos;
880 : : }
881 : : while (nStart <= nEndRow);
882 : : }
883 : : }
884 : :
885 : :
886 : :
887 : : // assemble border
888 : :
889 : 1784 : bool lcl_TestAttr( const SvxBorderLine* pOldLine, const SvxBorderLine* pNewLine,
890 : : sal_uInt8& rModified, const SvxBorderLine*& rpNew )
891 : : {
892 [ - + ]: 1784 : if (rModified == SC_LINE_DONTCARE)
893 : 0 : return false; // don't go again
894 : :
895 [ + + ]: 1784 : if (rModified == SC_LINE_EMPTY)
896 : : {
897 : 272 : rModified = SC_LINE_SET;
898 : 272 : rpNew = pNewLine;
899 : 272 : return true; // initial value
900 : : }
901 : :
902 [ + - ]: 1512 : if (pOldLine == pNewLine)
903 : : {
904 : 1512 : rpNew = pOldLine;
905 : 1512 : return false;
906 : : }
907 : :
908 [ # # ][ # # ]: 0 : if (pOldLine && pNewLine)
909 [ # # ]: 0 : if (*pOldLine == *pNewLine)
910 : : {
911 : 0 : rpNew = pOldLine;
912 : 0 : return false;
913 : : }
914 : :
915 : 0 : rModified = SC_LINE_DONTCARE;
916 : 0 : rpNew = NULL;
917 : 1784 : return true; // another line -> don't care
918 : : }
919 : :
920 : :
921 : 446 : void lcl_MergeToFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner,
922 : : ScLineFlags& rFlags, const ScPatternAttr* pPattern,
923 : : bool bLeft, SCCOL nDistRight, bool bTop, SCROW nDistBottom )
924 : : {
925 : : // right/bottom border set when connected together
926 [ + - ]: 446 : const ScMergeAttr& rMerge = (const ScMergeAttr&)pPattern->GetItem(ATTR_MERGE);
927 [ - + ]: 446 : if ( rMerge.GetColMerge() == nDistRight + 1 )
928 : 0 : nDistRight = 0;
929 [ - + ]: 446 : if ( rMerge.GetRowMerge() == nDistBottom + 1 )
930 : 0 : nDistBottom = 0;
931 : :
932 [ + - ]: 446 : const SvxBoxItem* pCellFrame = (SvxBoxItem*) &pPattern->GetItemSet().Get( ATTR_BORDER );
933 : 446 : const SvxBorderLine* pLeftAttr = pCellFrame->GetLeft();
934 : 446 : const SvxBorderLine* pRightAttr = pCellFrame->GetRight();
935 : 446 : const SvxBorderLine* pTopAttr = pCellFrame->GetTop();
936 : 446 : const SvxBorderLine* pBottomAttr = pCellFrame->GetBottom();
937 : : const SvxBorderLine* pNew;
938 : :
939 [ + + ]: 446 : if (bTop)
940 : : {
941 [ + - ][ + + ]: 158 : if (lcl_TestAttr( pLineOuter->GetTop(), pTopAttr, rFlags.nTop, pNew ))
942 [ + - ]: 50 : pLineOuter->SetLine( pNew, BOX_LINE_TOP );
943 : : }
944 : : else
945 : : {
946 [ + - ][ - + ]: 288 : if (lcl_TestAttr( pLineInner->GetHori(), pTopAttr, rFlags.nHori, pNew ))
947 [ # # ]: 0 : pLineInner->SetLine( pNew, BOXINFO_LINE_HORI );
948 : : }
949 : :
950 [ + + ]: 446 : if (nDistBottom == 0)
951 : : {
952 [ + - ][ + + ]: 158 : if (lcl_TestAttr( pLineOuter->GetBottom(), pBottomAttr, rFlags.nBottom, pNew ))
953 [ + - ]: 50 : pLineOuter->SetLine( pNew, BOX_LINE_BOTTOM );
954 : : }
955 : : else
956 : : {
957 [ + - ][ + + ]: 288 : if (lcl_TestAttr( pLineInner->GetHori(), pBottomAttr, rFlags.nHori, pNew ))
958 [ + - ]: 36 : pLineInner->SetLine( pNew, BOXINFO_LINE_HORI );
959 : : }
960 : :
961 [ + + ]: 446 : if (bLeft)
962 : : {
963 [ + - ][ + + ]: 122 : if (lcl_TestAttr( pLineOuter->GetLeft(), pLeftAttr, rFlags.nLeft, pNew ))
964 [ + - ]: 50 : pLineOuter->SetLine( pNew, BOX_LINE_LEFT );
965 : : }
966 : : else
967 : : {
968 [ + - ][ - + ]: 324 : if (lcl_TestAttr( pLineInner->GetVert(), pLeftAttr, rFlags.nVert, pNew ))
969 [ # # ]: 0 : pLineInner->SetLine( pNew, BOXINFO_LINE_VERT );
970 : : }
971 : :
972 [ + + ]: 446 : if (nDistRight == 0)
973 : : {
974 [ + - ][ + + ]: 122 : if (lcl_TestAttr( pLineOuter->GetRight(), pRightAttr, rFlags.nRight, pNew ))
975 [ + - ]: 50 : pLineOuter->SetLine( pNew, BOX_LINE_RIGHT );
976 : : }
977 : : else
978 : : {
979 [ + - ][ + + ]: 324 : if (lcl_TestAttr( pLineInner->GetVert(), pRightAttr, rFlags.nVert, pNew ))
980 [ + - ]: 36 : pLineInner->SetLine( pNew, BOXINFO_LINE_VERT );
981 : : }
982 : 446 : }
983 : :
984 : :
985 : 158 : void ScAttrArray::MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner,
986 : : ScLineFlags& rFlags,
987 : : SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight ) const
988 : : {
989 : : const ScPatternAttr* pPattern;
990 : :
991 [ + + ]: 158 : if (nStartRow == nEndRow)
992 : : {
993 : 14 : pPattern = GetPattern( nStartRow );
994 : 14 : lcl_MergeToFrame( pLineOuter, pLineInner, rFlags, pPattern, bLeft, nDistRight, true, 0 );
995 : : }
996 : : else
997 : : {
998 : 144 : pPattern = GetPattern( nStartRow );
999 : : lcl_MergeToFrame( pLineOuter, pLineInner, rFlags, pPattern, bLeft, nDistRight, true,
1000 [ + - ]: 144 : nEndRow-nStartRow );
1001 : :
1002 : : SCSIZE nStartIndex;
1003 : : SCSIZE nEndIndex;
1004 : 144 : Search( nStartRow+1, nStartIndex );
1005 : 144 : Search( nEndRow-1, nEndIndex );
1006 [ + + ]: 288 : for (SCSIZE i=nStartIndex; i<=nEndIndex; i++)
1007 : : {
1008 : 144 : pPattern = (ScPatternAttr*) pData[i].pPattern;
1009 : : lcl_MergeToFrame( pLineOuter, pLineInner, rFlags, pPattern, bLeft, nDistRight, false,
1010 [ + - ]: 144 : nEndRow - Min( pData[i].nRow, (SCROW)(nEndRow-1) ) );
1011 : : // nDistBottom here always > 0
1012 : : }
1013 : :
1014 : 144 : pPattern = GetPattern( nEndRow );
1015 [ + - ]: 144 : lcl_MergeToFrame( pLineOuter, pLineInner, rFlags, pPattern, bLeft, nDistRight, false, 0 );
1016 : : }
1017 : 158 : }
1018 : :
1019 : : //
1020 : : // apply border
1021 : : //
1022 : :
1023 : : // ApplyFrame - on an entry into the array
1024 : :
1025 : 5202 : bool ScAttrArray::ApplyFrame( const SvxBoxItem* pBoxItem,
1026 : : const SvxBoxInfoItem* pBoxInfoItem,
1027 : : SCROW nStartRow, SCROW nEndRow,
1028 : : bool bLeft, SCCOL nDistRight, bool bTop, SCROW nDistBottom )
1029 : : {
1030 : : OSL_ENSURE( pBoxItem && pBoxInfoItem, "Linienattribute fehlen!" );
1031 : :
1032 : 5202 : const ScPatternAttr* pPattern = GetPattern( nStartRow );
1033 : : const SvxBoxItem* pOldFrame = (const SvxBoxItem*)
1034 [ + - ]: 5202 : &pPattern->GetItemSet().Get( ATTR_BORDER );
1035 : :
1036 : : // right/bottom border set when connected together
1037 [ + - ]: 5202 : const ScMergeAttr& rMerge = (const ScMergeAttr&)pPattern->GetItem(ATTR_MERGE);
1038 [ - + ]: 5202 : if ( rMerge.GetColMerge() == nDistRight + 1 )
1039 : 0 : nDistRight = 0;
1040 [ - + ]: 5202 : if ( rMerge.GetRowMerge() == nDistBottom + 1 )
1041 : 0 : nDistBottom = 0;
1042 : :
1043 [ + - ]: 5202 : SvxBoxItem aNewFrame( *pOldFrame );
1044 : :
1045 [ + + ][ + + ]: 5202 : if ( bLeft ? pBoxInfoItem->IsValid(VALID_LEFT) : pBoxInfoItem->IsValid(VALID_VERT) )
1046 : : aNewFrame.SetLine( bLeft ? pBoxItem->GetLeft() : pBoxInfoItem->GetVert(),
1047 [ + - ][ + - ]: 2574 : BOX_LINE_LEFT );
1048 [ + + ][ + + ]: 5202 : if ( (nDistRight==0) ? pBoxInfoItem->IsValid(VALID_RIGHT) : pBoxInfoItem->IsValid(VALID_VERT) )
1049 : : aNewFrame.SetLine( (nDistRight==0) ? pBoxItem->GetRight() : pBoxInfoItem->GetVert(),
1050 [ + - ][ + - ]: 2577 : BOX_LINE_RIGHT );
1051 [ + + ][ + + ]: 5202 : if ( bTop ? pBoxInfoItem->IsValid(VALID_TOP) : pBoxInfoItem->IsValid(VALID_HORI) )
1052 : : aNewFrame.SetLine( bTop ? pBoxItem->GetTop() : pBoxInfoItem->GetHori(),
1053 [ + + ][ + - ]: 3180 : BOX_LINE_TOP );
1054 [ + + ][ + + ]: 5202 : if ( (nDistBottom==0) ? pBoxInfoItem->IsValid(VALID_BOTTOM) : pBoxInfoItem->IsValid(VALID_HORI) )
1055 : : aNewFrame.SetLine( (nDistBottom==0) ? pBoxItem->GetBottom() : pBoxInfoItem->GetHori(),
1056 [ + + ][ + - ]: 3180 : BOX_LINE_BOTTOM );
1057 : :
1058 [ + - ][ + + ]: 5202 : if (aNewFrame == *pOldFrame)
1059 : : {
1060 : : // nothing to do
1061 : 1110 : return false;
1062 : : }
1063 : : else
1064 : : {
1065 [ + - ][ + - ]: 4092 : SfxItemPoolCache aCache( pDocument->GetPool(), &aNewFrame );
1066 [ + - ]: 4092 : ApplyCacheArea( nStartRow, nEndRow, &aCache );
1067 : :
1068 [ + - ]: 4092 : return true;
1069 [ + - ]: 5202 : }
1070 : : }
1071 : :
1072 : :
1073 : 3130 : void ScAttrArray::ApplyBlockFrame( const SvxBoxItem* pLineOuter, const SvxBoxInfoItem* pLineInner,
1074 : : SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight )
1075 : : {
1076 [ + + ]: 3130 : if (nStartRow == nEndRow)
1077 : 1863 : ApplyFrame( pLineOuter, pLineInner, nStartRow, nEndRow, bLeft, nDistRight, true, 0 );
1078 : : else
1079 : : {
1080 : : ApplyFrame( pLineOuter, pLineInner, nStartRow, nStartRow, bLeft, nDistRight,
1081 : 1267 : true, nEndRow-nStartRow );
1082 : :
1083 [ + + ]: 1267 : if ( nEndRow > nStartRow+1 ) // inner part available?
1084 : : {
1085 : : SCSIZE nStartIndex;
1086 : : SCSIZE nEndIndex;
1087 : 682 : Search( nStartRow+1, nStartIndex );
1088 : 682 : Search( nEndRow-1, nEndIndex );
1089 : 682 : SCROW nTmpStart = nStartRow+1;
1090 : : SCROW nTmpEnd;
1091 [ + + ]: 1487 : for (SCSIZE i=nStartIndex; i<=nEndIndex;)
1092 : : {
1093 : 805 : nTmpEnd = Min( (SCROW)(nEndRow-1), (SCROW)(pData[i].nRow) );
1094 : : bool bChanged = ApplyFrame( pLineOuter, pLineInner, nTmpStart, nTmpEnd,
1095 [ + - ]: 805 : bLeft, nDistRight, false, nEndRow-nTmpEnd );
1096 : 805 : nTmpStart = nTmpEnd+1;
1097 [ + + ]: 805 : if (bChanged)
1098 : : {
1099 : 405 : Search(nTmpStart, i);
1100 : 405 : Search(nEndRow-1, nEndIndex);
1101 : : }
1102 : : else
1103 : 400 : i++;
1104 : : }
1105 : : }
1106 : :
1107 : 1267 : ApplyFrame( pLineOuter, pLineInner, nEndRow, nEndRow, bLeft, nDistRight, false, 0 );
1108 : : }
1109 : 3130 : }
1110 : :
1111 : :
1112 : 0 : long lcl_LineSize( const SvxBorderLine& rLine )
1113 : : {
1114 : : // only one line -> half width, min. 20
1115 : : // double line -> half line spacing + (per min. 20)
1116 : :
1117 : 0 : long nTotal = 0;
1118 : 0 : sal_uInt16 nWidth = Max( rLine.GetOutWidth(), rLine.GetInWidth() );
1119 : 0 : sal_uInt16 nDist = rLine.GetDistance();
1120 [ # # ]: 0 : if (nDist)
1121 : : {
1122 : : OSL_ENSURE( rLine.GetOutWidth() && rLine.GetInWidth(),
1123 : : "Line has a distance, but only a width?" );
1124 : :
1125 [ # # ]: 0 : nTotal += ( nDist > 20 ) ? nDist : 20;
1126 [ # # ]: 0 : nTotal += ( nWidth > 20 ) ? nWidth : 20;
1127 : : }
1128 [ # # ]: 0 : else if (nWidth)
1129 [ # # ]: 0 : nTotal += ( nWidth > 20 ) ? nWidth : 20;
1130 : :
1131 : : // also halved ?
1132 : :
1133 : 0 : return nTotal;
1134 : : }
1135 : :
1136 : : // Test if field contains specific attribute
1137 : :
1138 : 8074579 : bool ScAttrArray::HasAttrib( SCROW nRow1, SCROW nRow2, sal_uInt16 nMask ) const
1139 : : {
1140 : : SCSIZE nStartIndex;
1141 : : SCSIZE nEndIndex;
1142 : 8074579 : Search( nRow1, nStartIndex );
1143 : 8074579 : Search( nRow2, nEndIndex );
1144 : 8074579 : bool bFound = false;
1145 : :
1146 [ + + ][ + + ]: 16163964 : for (SCSIZE i=nStartIndex; i<=nEndIndex && !bFound; i++)
[ + + ]
1147 : : {
1148 : 8089385 : const ScPatternAttr* pPattern = pData[i].pPattern;
1149 [ + + ]: 8089385 : if ( nMask & HASATTR_MERGED )
1150 : : {
1151 : : const ScMergeAttr* pMerge =
1152 [ + - ]: 5537 : (const ScMergeAttr*) &pPattern->GetItem( ATTR_MERGE );
1153 [ + + ][ - + ]: 5537 : if ( pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1 )
[ + + ]
1154 : 13 : bFound = true;
1155 : : }
1156 [ + + ]: 8089385 : if ( nMask & ( HASATTR_OVERLAPPED | HASATTR_NOTOVERLAPPED | HASATTR_AUTOFILTER ) )
1157 : : {
1158 : : const ScMergeFlagAttr* pMergeFlag =
1159 [ + - ]: 15892 : (const ScMergeFlagAttr*) &pPattern->GetItem( ATTR_MERGE_FLAG );
1160 [ + - ][ + + ]: 15892 : if ( (nMask & HASATTR_OVERLAPPED) && pMergeFlag->IsOverlapped() )
[ + + ]
1161 : 3 : bFound = true;
1162 [ - + ][ # # ]: 15892 : if ( (nMask & HASATTR_NOTOVERLAPPED) && !pMergeFlag->IsOverlapped() )
[ - + ]
1163 : 0 : bFound = true;
1164 [ + + ][ + + ]: 15892 : if ( (nMask & HASATTR_AUTOFILTER) && pMergeFlag->HasAutoFilter() )
[ + + ]
1165 : 26 : bFound = true;
1166 : : }
1167 [ + + ]: 8089385 : if ( nMask & HASATTR_LINES )
1168 : : {
1169 : : const SvxBoxItem* pBox =
1170 [ + - ]: 104709 : (const SvxBoxItem*) &pPattern->GetItem( ATTR_BORDER );
1171 [ + + ][ + - ]: 104709 : if ( pBox->GetLeft() || pBox->GetRight() || pBox->GetTop() || pBox->GetBottom() )
[ + - ][ - + ]
[ + + ]
1172 : 3 : bFound = true;
1173 : : }
1174 [ + + ]: 8089385 : if ( nMask & HASATTR_SHADOW )
1175 : : {
1176 : : const SvxShadowItem* pShadow =
1177 [ + - ]: 104403 : (const SvxShadowItem*) &pPattern->GetItem( ATTR_SHADOW );
1178 [ - + ]: 104403 : if ( pShadow->GetLocation() != SVX_SHADOW_NONE )
1179 : 0 : bFound = true;
1180 : : }
1181 [ + + ]: 8089385 : if ( nMask & HASATTR_CONDITIONAL )
1182 : : {
1183 : : const SfxUInt32Item* pConditional =
1184 [ + - ]: 4863712 : (const SfxUInt32Item*) &pPattern->GetItem( ATTR_CONDITIONAL );
1185 [ + + ]: 4863712 : if ( pConditional->GetValue() != 0 )
1186 : 903 : bFound = true;
1187 : : }
1188 [ + + ]: 8089385 : if ( nMask & HASATTR_PROTECTED )
1189 : : {
1190 : : const ScProtectionAttr* pProtect =
1191 [ + - ]: 20 : (const ScProtectionAttr*) &pPattern->GetItem( ATTR_PROTECTION );
1192 [ - + ][ # # ]: 20 : if ( pProtect->GetProtection() || pProtect->GetHideCell() )
[ + - ]
1193 : 20 : bFound = true;
1194 : : }
1195 [ + + ]: 8089385 : if ( nMask & HASATTR_ROTATE )
1196 : : {
1197 : : const SfxInt32Item* pRotate =
1198 [ + - ]: 73356 : (const SfxInt32Item*) &pPattern->GetItem( ATTR_ROTATE_VALUE );
1199 : : // 90 or 270 degrees is former SvxOrientationItem - only look for other values
1200 : : // (see ScPatternAttr::GetCellOrientation)
1201 : 73356 : sal_Int32 nAngle = pRotate->GetValue();
1202 [ + - ][ + + ]: 73356 : if ( nAngle != 0 && nAngle != 9000 && nAngle != 27000 )
[ + + ]
1203 : 545 : bFound = true;
1204 : : }
1205 [ + + ]: 8089385 : if ( nMask & HASATTR_NEEDHEIGHT )
1206 : : {
1207 [ + - ][ - + ]: 2531 : if (pPattern->GetCellOrientation() != SVX_ORIENTATION_STANDARD)
1208 : 0 : bFound = true;
1209 [ + - ][ - + ]: 2531 : else if (((const SfxBoolItem&)pPattern->GetItem( ATTR_LINEBREAK )).GetValue())
1210 : 0 : bFound = true;
1211 [ - + ]: 2531 : else if ((SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern->
1212 [ + - ]: 2531 : GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_BLOCK)
1213 : 0 : bFound = true;
1214 [ + - ][ - + ]: 2531 : else if (((const SfxUInt32Item&)pPattern->GetItem( ATTR_CONDITIONAL )).GetValue())
1215 : 0 : bFound = true;
1216 [ + - ][ - + ]: 2531 : else if (((const SfxInt32Item&)pPattern->GetItem( ATTR_ROTATE_VALUE )).GetValue())
1217 : 0 : bFound = true;
1218 : : }
1219 [ + + ]: 8089385 : if ( nMask & ( HASATTR_SHADOW_RIGHT | HASATTR_SHADOW_DOWN ) )
1220 : : {
1221 : : const SvxShadowItem* pShadow =
1222 [ + - ]: 1704 : (const SvxShadowItem*) &pPattern->GetItem( ATTR_SHADOW );
1223 : 1704 : SvxShadowLocation eLoc = pShadow->GetLocation();
1224 [ + + ]: 1704 : if ( nMask & HASATTR_SHADOW_RIGHT )
1225 [ + - ][ - + ]: 240 : if ( eLoc == SVX_SHADOW_TOPRIGHT || eLoc == SVX_SHADOW_BOTTOMRIGHT )
1226 : 0 : bFound = true;
1227 [ + + ]: 1704 : if ( nMask & HASATTR_SHADOW_DOWN )
1228 [ + - ][ - + ]: 1464 : if ( eLoc == SVX_SHADOW_BOTTOMLEFT || eLoc == SVX_SHADOW_BOTTOMRIGHT )
1229 : 0 : bFound = true;
1230 : : }
1231 [ - + ]: 8089385 : if ( nMask & HASATTR_RTL )
1232 : : {
1233 : : const SvxFrameDirectionItem& rDirection =
1234 [ # # ]: 0 : (const SvxFrameDirectionItem&) pPattern->GetItem( ATTR_WRITINGDIR );
1235 [ # # ]: 0 : if ( rDirection.GetValue() == FRMDIR_HORI_RIGHT_TOP )
1236 : 0 : bFound = true;
1237 : : }
1238 [ + + ]: 8089385 : if ( nMask & HASATTR_RIGHTORCENTER )
1239 : : {
1240 : : // called only if the sheet is LTR, so physical=logical alignment can be assumed
1241 : : SvxCellHorJustify eHorJust = (SvxCellHorJustify)
1242 [ + - ]: 3204952 : ((const SvxHorJustifyItem&) pPattern->GetItem( ATTR_HOR_JUSTIFY )).GetValue();
1243 [ + + ][ + + ]: 3204952 : if ( eHorJust == SVX_HOR_JUSTIFY_RIGHT || eHorJust == SVX_HOR_JUSTIFY_CENTER )
1244 : 202 : bFound = true;
1245 : : }
1246 : : }
1247 : :
1248 : 8074579 : return bFound;
1249 : : }
1250 : :
1251 : : // Area around any given summaries expand and adapt any MergeFlag (bRefresh)
1252 : 9873 : bool ScAttrArray::ExtendMerge( SCCOL nThisCol, SCROW nStartRow, SCROW nEndRow,
1253 : : SCCOL& rPaintCol, SCROW& rPaintRow,
1254 : : bool bRefresh )
1255 : : {
1256 : : const ScPatternAttr* pPattern;
1257 : : const ScMergeAttr* pItem;
1258 : : SCSIZE nStartIndex;
1259 : : SCSIZE nEndIndex;
1260 : 9873 : Search( nStartRow, nStartIndex );
1261 : 9873 : Search( nEndRow, nEndIndex );
1262 : 9873 : bool bFound = false;
1263 : :
1264 [ + + ]: 20398 : for (SCSIZE i=nStartIndex; i<=nEndIndex; i++)
1265 : : {
1266 : 10525 : pPattern = pData[i].pPattern;
1267 [ + - ]: 10525 : pItem = (const ScMergeAttr*) &pPattern->GetItem( ATTR_MERGE );
1268 : 10525 : SCsCOL nCountX = pItem->GetColMerge();
1269 : 10525 : SCsROW nCountY = pItem->GetRowMerge();
1270 [ - + ][ + + ]: 10525 : if (nCountX>1 || nCountY>1)
1271 : : {
1272 [ + + ]: 39 : SCROW nThisRow = (i>0) ? pData[i-1].nRow+1 : 0;
1273 : 39 : SCCOL nMergeEndCol = nThisCol + nCountX - 1;
1274 : 39 : SCROW nMergeEndRow = nThisRow + nCountY - 1;
1275 [ + + ][ + - ]: 39 : if (nMergeEndCol > rPaintCol && nMergeEndCol <= MAXCOL)
1276 : 30 : rPaintCol = nMergeEndCol;
1277 [ + + ][ + - ]: 39 : if (nMergeEndRow > rPaintRow && nMergeEndRow <= MAXROW)
1278 : 32 : rPaintRow = nMergeEndRow;
1279 : 39 : bFound = true;
1280 : :
1281 [ + + ]: 39 : if (bRefresh)
1282 : : {
1283 [ + - ]: 3 : if ( nMergeEndCol > nThisCol )
1284 : 3 : pDocument->ApplyFlagsTab( nThisCol+1, nThisRow, nMergeEndCol, pData[i].nRow,
1285 [ + - ]: 3 : nTab, SC_MF_HOR );
1286 [ + - ]: 3 : if ( nMergeEndRow > nThisRow )
1287 : : pDocument->ApplyFlagsTab( nThisCol, nThisRow+1, nThisCol, nMergeEndRow,
1288 [ + - ]: 3 : nTab, SC_MF_VER );
1289 [ + - ][ + - ]: 3 : if ( nMergeEndCol > nThisCol && nMergeEndRow > nThisRow )
1290 : : pDocument->ApplyFlagsTab( nThisCol+1, nThisRow+1, nMergeEndCol, nMergeEndRow,
1291 [ + - ]: 3 : nTab, SC_MF_HOR | SC_MF_VER );
1292 : :
1293 : 3 : Search( nThisRow, i ); // Data changed
1294 : 3 : Search( nStartRow, nStartIndex );
1295 : 3 : Search( nEndRow, nEndIndex );
1296 : : }
1297 : : }
1298 : : }
1299 : :
1300 : 9873 : return bFound;
1301 : : }
1302 : :
1303 : :
1304 : 8399 : bool ScAttrArray::RemoveAreaMerge(SCROW nStartRow, SCROW nEndRow)
1305 : : {
1306 : 8399 : bool bFound = false;
1307 : : const ScPatternAttr* pPattern;
1308 : : const ScMergeAttr* pItem;
1309 : : SCSIZE nIndex;
1310 : :
1311 : 8399 : Search( nStartRow, nIndex );
1312 [ + + ]: 8399 : SCROW nThisStart = (nIndex>0) ? pData[nIndex-1].nRow+1 : 0;
1313 [ + + ]: 8399 : if (nThisStart < nStartRow)
1314 : 344 : nThisStart = nStartRow;
1315 : :
1316 [ + + ]: 19082 : while ( nThisStart <= nEndRow )
1317 : : {
1318 : 10683 : SCROW nThisEnd = pData[nIndex].nRow;
1319 [ + + ]: 10683 : if (nThisEnd > nEndRow)
1320 : 4860 : nThisEnd = nEndRow;
1321 : :
1322 : 10683 : pPattern = pData[nIndex].pPattern;
1323 [ + - ]: 10683 : pItem = (const ScMergeAttr*) &pPattern->GetItem( ATTR_MERGE );
1324 : 10683 : SCsCOL nCountX = pItem->GetColMerge();
1325 : 10683 : SCsROW nCountY = pItem->GetRowMerge();
1326 [ - + ][ + - ]: 10683 : if (nCountX>1 || nCountY>1)
1327 : : {
1328 : : const ScMergeAttr* pAttr = (const ScMergeAttr*)
1329 [ # # ][ # # ]: 0 : &pDocument->GetPool()->GetDefaultItem( ATTR_MERGE );
1330 : : const ScMergeFlagAttr* pFlagAttr = (const ScMergeFlagAttr*)
1331 [ # # ][ # # ]: 0 : &pDocument->GetPool()->GetDefaultItem( ATTR_MERGE_FLAG );
1332 : :
1333 : : OSL_ENSURE( nCountY==1 || nThisStart==nThisEnd, "What's up?" );
1334 : :
1335 : 0 : SCCOL nThisCol = nCol;
1336 : 0 : SCCOL nMergeEndCol = nThisCol + nCountX - 1;
1337 : 0 : SCROW nMergeEndRow = nThisEnd + nCountY - 1;
1338 : :
1339 : : // ApplyAttr for areas
1340 : :
1341 [ # # ]: 0 : for (SCROW nThisRow = nThisStart; nThisRow <= nThisEnd; nThisRow++)
1342 [ # # ]: 0 : pDocument->ApplyAttr( nThisCol, nThisRow, nTab, *pAttr );
1343 : :
1344 [ # # ][ # # ]: 0 : ScPatternAttr* pNewPattern = new ScPatternAttr( pDocument->GetPool() );
[ # # ]
1345 : 0 : SfxItemSet* pSet = &pNewPattern->GetItemSet();
1346 [ # # ]: 0 : pSet->Put( *pFlagAttr );
1347 : : pDocument->ApplyPatternAreaTab( nThisCol, nThisStart, nMergeEndCol, nMergeEndRow,
1348 [ # # ]: 0 : nTab, *pNewPattern );
1349 [ # # ][ # # ]: 0 : delete pNewPattern;
1350 : :
1351 : 0 : Search( nThisEnd, nIndex ); // data changed
1352 : : }
1353 : :
1354 : 10683 : ++nIndex;
1355 [ + + ]: 10683 : if ( nIndex < nCount )
1356 : 2753 : nThisStart = pData[nIndex-1].nRow+1;
1357 : : else
1358 : 7930 : nThisStart = MAXROW+1; // End
1359 : : }
1360 : :
1361 : 8399 : return bFound;
1362 : : }
1363 : :
1364 : : // Remove field, but leave MergeFlags
1365 : :
1366 : 26 : void ScAttrArray::DeleteAreaSafe(SCROW nStartRow, SCROW nEndRow)
1367 : : {
1368 : 26 : SetPatternAreaSafe( nStartRow, nEndRow, pDocument->GetDefPattern(), true );
1369 : 26 : }
1370 : :
1371 : :
1372 : 26 : void ScAttrArray::SetPatternAreaSafe( SCROW nStartRow, SCROW nEndRow,
1373 : : const ScPatternAttr* pWantedPattern, bool bDefault )
1374 : : {
1375 : : const ScPatternAttr* pOldPattern;
1376 : : const ScMergeFlagAttr* pItem;
1377 : :
1378 : : SCSIZE nIndex;
1379 : : SCROW nRow;
1380 : : SCROW nThisRow;
1381 : 26 : bool bFirstUse = true;
1382 : :
1383 : 26 : Search( nStartRow, nIndex );
1384 [ + + ]: 26 : nThisRow = (nIndex>0) ? pData[nIndex-1].nRow+1 : 0;
1385 [ + + ]: 242 : while ( nThisRow <= nEndRow )
1386 : : {
1387 : 216 : pOldPattern = pData[nIndex].pPattern;
1388 [ + - ]: 216 : if (pOldPattern != pWantedPattern) //! else-Zweig ?
1389 : : {
1390 [ - + ]: 216 : if (nThisRow < nStartRow) nThisRow = nStartRow;
1391 : 216 : nRow = pData[nIndex].nRow;
1392 : 216 : SCROW nAttrRow = Min( (SCROW)nRow, (SCROW)nEndRow );
1393 [ + - ]: 216 : pItem = (const ScMergeFlagAttr*) &pOldPattern->GetItem( ATTR_MERGE_FLAG );
1394 : :
1395 [ + - ][ + + ]: 216 : if (pItem->IsOverlapped() || pItem->HasAutoFilter())
[ + + ]
1396 : : {
1397 : : // default-constructing a ScPatternAttr for DeleteArea doesn't work
1398 : : // because it would have no cell style information.
1399 : : // Instead, the document's GetDefPattern is copied. Since it is passed as
1400 : : // pWantedPattern, no special treatment of default is needed here anymore.
1401 [ + - ][ + - ]: 26 : ScPatternAttr* pNewPattern = new ScPatternAttr( *pWantedPattern );
1402 : 26 : SfxItemSet* pSet = &pNewPattern->GetItemSet();
1403 [ + - ]: 26 : pSet->Put( *pItem );
1404 [ + - ]: 26 : SetPatternArea( nThisRow, nAttrRow, pNewPattern, true );
1405 [ + - ][ + - ]: 26 : delete pNewPattern;
1406 : : }
1407 : : else
1408 : : {
1409 [ - + ]: 190 : if ( !bDefault )
1410 : : {
1411 [ # # ]: 0 : if (bFirstUse)
1412 : 0 : bFirstUse = false;
1413 : : else
1414 : : // it's in the pool
1415 [ # # ][ # # ]: 0 : pDocument->GetPool()->Put( *pWantedPattern );
1416 : : }
1417 [ + - ]: 190 : SetPatternArea( nThisRow, nAttrRow, pWantedPattern );
1418 : : }
1419 : :
1420 : 216 : Search( nThisRow, nIndex ); // data changed
1421 : : }
1422 : :
1423 : 216 : ++nIndex;
1424 : 216 : nThisRow = pData[nIndex-1].nRow+1;
1425 : : }
1426 : 26 : }
1427 : :
1428 : :
1429 : 1422 : bool ScAttrArray::ApplyFlags( SCROW nStartRow, SCROW nEndRow, sal_Int16 nFlags )
1430 : : {
1431 : : const ScPatternAttr* pOldPattern;
1432 : :
1433 : : sal_Int16 nOldValue;
1434 : : SCSIZE nIndex;
1435 : : SCROW nRow;
1436 : : SCROW nThisRow;
1437 : 1422 : bool bChanged = false;
1438 : :
1439 : 1422 : Search( nStartRow, nIndex );
1440 [ + + ]: 1422 : nThisRow = (nIndex>0) ? pData[nIndex-1].nRow+1 : 0;
1441 [ + + ]: 1422 : if (nThisRow < nStartRow) nThisRow = nStartRow;
1442 : :
1443 [ + + ]: 6457 : while ( nThisRow <= nEndRow )
1444 : : {
1445 : 5035 : pOldPattern = pData[nIndex].pPattern;
1446 [ + - ]: 5035 : nOldValue = ((const ScMergeFlagAttr*) &pOldPattern->GetItem( ATTR_MERGE_FLAG ))->GetValue();
1447 [ + + ]: 5035 : if ( (nOldValue | nFlags) != nOldValue )
1448 : : {
1449 : 4933 : nRow = pData[nIndex].nRow;
1450 : 4933 : SCROW nAttrRow = Min( (SCROW)nRow, (SCROW)nEndRow );
1451 [ + - ]: 4933 : ScPatternAttr aNewPattern(*pOldPattern);
1452 [ + - ][ + - ]: 4933 : aNewPattern.GetItemSet().Put( ScMergeFlagAttr( nOldValue | nFlags ) );
[ + - ]
1453 [ + - ]: 4933 : SetPatternArea( nThisRow, nAttrRow, &aNewPattern, true );
1454 : 4933 : Search( nThisRow, nIndex ); // data changed
1455 [ + - ]: 4933 : bChanged = true;
1456 : : }
1457 : :
1458 : 5035 : ++nIndex;
1459 : 5035 : nThisRow = pData[nIndex-1].nRow+1;
1460 : : }
1461 : :
1462 : 1422 : return bChanged;
1463 : : }
1464 : :
1465 : :
1466 : 41094 : bool ScAttrArray::RemoveFlags( SCROW nStartRow, SCROW nEndRow, sal_Int16 nFlags )
1467 : : {
1468 : : const ScPatternAttr* pOldPattern;
1469 : :
1470 : : sal_Int16 nOldValue;
1471 : : SCSIZE nIndex;
1472 : : SCROW nRow;
1473 : : SCROW nThisRow;
1474 : 41094 : bool bChanged = false;
1475 : :
1476 : 41094 : Search( nStartRow, nIndex );
1477 [ + + ]: 41094 : nThisRow = (nIndex>0) ? pData[nIndex-1].nRow+1 : 0;
1478 [ + + ]: 41094 : if (nThisRow < nStartRow) nThisRow = nStartRow;
1479 : :
1480 [ + + ]: 82949 : while ( nThisRow <= nEndRow )
1481 : : {
1482 : 41855 : pOldPattern = pData[nIndex].pPattern;
1483 [ + - ]: 41855 : nOldValue = ((const ScMergeFlagAttr*) &pOldPattern->GetItem( ATTR_MERGE_FLAG ))->GetValue();
1484 [ + + ]: 41855 : if ( (nOldValue & ~nFlags) != nOldValue )
1485 : : {
1486 : 788 : nRow = pData[nIndex].nRow;
1487 : 788 : SCROW nAttrRow = Min( (SCROW)nRow, (SCROW)nEndRow );
1488 [ + - ]: 788 : ScPatternAttr aNewPattern(*pOldPattern);
1489 [ + - ][ + - ]: 788 : aNewPattern.GetItemSet().Put( ScMergeFlagAttr( nOldValue & ~nFlags ) );
[ + - ]
1490 [ + - ]: 788 : SetPatternArea( nThisRow, nAttrRow, &aNewPattern, true );
1491 : 788 : Search( nThisRow, nIndex ); // data changed
1492 [ + - ]: 788 : bChanged = true;
1493 : : }
1494 : :
1495 : 41855 : ++nIndex;
1496 : 41855 : nThisRow = pData[nIndex-1].nRow+1;
1497 : : }
1498 : :
1499 : 41094 : return bChanged;
1500 : : }
1501 : :
1502 : :
1503 : 4 : void ScAttrArray::ClearItems( SCROW nStartRow, SCROW nEndRow, const sal_uInt16* pWhich )
1504 : : {
1505 : : const ScPatternAttr* pOldPattern;
1506 : :
1507 : : SCSIZE nIndex;
1508 : : SCROW nRow;
1509 : : SCROW nThisRow;
1510 : :
1511 : 4 : Search( nStartRow, nIndex );
1512 [ - + ]: 4 : nThisRow = (nIndex>0) ? pData[nIndex-1].nRow+1 : 0;
1513 [ - + ]: 4 : if (nThisRow < nStartRow) nThisRow = nStartRow;
1514 : :
1515 [ + + ]: 8 : while ( nThisRow <= nEndRow )
1516 : : {
1517 : 4 : pOldPattern = pData[nIndex].pPattern;
1518 [ + - ][ - + ]: 4 : if ( pOldPattern->HasItemsSet( pWhich ) )
1519 : : {
1520 [ # # ]: 0 : ScPatternAttr aNewPattern(*pOldPattern);
1521 [ # # ]: 0 : aNewPattern.ClearItems( pWhich );
1522 : :
1523 : 0 : nRow = pData[nIndex].nRow;
1524 : 0 : SCROW nAttrRow = Min( (SCROW)nRow, (SCROW)nEndRow );
1525 [ # # ]: 0 : SetPatternArea( nThisRow, nAttrRow, &aNewPattern, true );
1526 [ # # ]: 0 : Search( nThisRow, nIndex ); // data changed
1527 : : }
1528 : :
1529 : 4 : ++nIndex;
1530 : 4 : nThisRow = pData[nIndex-1].nRow+1;
1531 : : }
1532 : 4 : }
1533 : :
1534 : :
1535 : 34 : void ScAttrArray::ChangeIndent( SCROW nStartRow, SCROW nEndRow, bool bIncrement )
1536 : : {
1537 : : SCSIZE nIndex;
1538 : 34 : Search( nStartRow, nIndex );
1539 [ + + ]: 34 : SCROW nThisStart = (nIndex>0) ? pData[nIndex-1].nRow+1 : 0;
1540 [ + + ]: 34 : if (nThisStart < nStartRow) nThisStart = nStartRow;
1541 : :
1542 [ + + ]: 68 : while ( nThisStart <= nEndRow )
1543 : : {
1544 : 34 : const ScPatternAttr* pOldPattern = pData[nIndex].pPattern;
1545 : 34 : const SfxItemSet& rOldSet = pOldPattern->GetItemSet();
1546 : : const SfxPoolItem* pItem;
1547 : :
1548 [ + - ]: 34 : bool bNeedJust = ( rOldSet.GetItemState( ATTR_HOR_JUSTIFY, false, &pItem ) != SFX_ITEM_SET
1549 [ + + ][ - + ]: 34 : || ((const SvxHorJustifyItem*)pItem)->GetValue() != SVX_HOR_JUSTIFY_LEFT );
1550 [ + - ]: 34 : sal_uInt16 nOldValue = ((const SfxUInt16Item&)rOldSet.Get( ATTR_INDENT )).GetValue();
1551 : 34 : sal_uInt16 nNewValue = nOldValue;
1552 [ + + ]: 34 : if ( bIncrement )
1553 : : {
1554 [ + - ]: 17 : if ( nNewValue < SC_MAX_INDENT )
1555 : : {
1556 : 17 : nNewValue += SC_INDENT_STEP;
1557 [ - + ]: 17 : if ( nNewValue > SC_MAX_INDENT ) nNewValue = SC_MAX_INDENT;
1558 : : }
1559 : : }
1560 : : else
1561 : : {
1562 [ + - ]: 17 : if ( nNewValue > 0 )
1563 : : {
1564 [ - + ]: 17 : if ( nNewValue > SC_INDENT_STEP )
1565 : 0 : nNewValue -= SC_INDENT_STEP;
1566 : : else
1567 : 17 : nNewValue = 0;
1568 : : }
1569 : : }
1570 : :
1571 [ + + ][ + - ]: 34 : if ( bNeedJust || nNewValue != nOldValue )
1572 : : {
1573 : 34 : SCROW nThisEnd = pData[nIndex].nRow;
1574 : 34 : SCROW nAttrRow = Min( nThisEnd, nEndRow );
1575 [ + - ]: 34 : ScPatternAttr aNewPattern(*pOldPattern);
1576 [ + - ][ + - ]: 34 : aNewPattern.GetItemSet().Put( SfxUInt16Item( ATTR_INDENT, nNewValue ) );
[ + - ]
1577 [ + + ]: 34 : if ( bNeedJust )
1578 : 17 : aNewPattern.GetItemSet().Put(
1579 [ + - + - ]: 34 : SvxHorJustifyItem( SVX_HOR_JUSTIFY_LEFT, ATTR_HOR_JUSTIFY ) );
[ + - ]
1580 [ + - ]: 34 : SetPatternArea( nThisStart, nAttrRow, &aNewPattern, true );
1581 : :
1582 : 34 : nThisStart = nThisEnd + 1;
1583 [ + - ]: 34 : Search( nThisStart, nIndex ); // data changed
1584 : : }
1585 : : else
1586 : : {
1587 : 0 : nThisStart = pData[nIndex].nRow + 1;
1588 : 34 : ++nIndex;
1589 : : }
1590 : : }
1591 : 34 : }
1592 : :
1593 : :
1594 : 0 : SCsROW ScAttrArray::GetNextUnprotected( SCsROW nRow, bool bUp ) const
1595 : : {
1596 : 0 : long nRet = nRow;
1597 [ # # ]: 0 : if (VALIDROW(nRow))
1598 : : {
1599 : : SCSIZE nIndex;
1600 : 0 : Search(nRow, nIndex);
1601 [ # # ]: 0 : while (((const ScProtectionAttr&)pData[nIndex].pPattern->
1602 [ # # ]: 0 : GetItem(ATTR_PROTECTION)).GetProtection())
1603 : : {
1604 [ # # ]: 0 : if (bUp)
1605 : : {
1606 [ # # ]: 0 : if (nIndex==0)
1607 : 0 : return -1; // not found
1608 : 0 : --nIndex;
1609 : 0 : nRet = pData[nIndex].nRow;
1610 : : }
1611 : : else
1612 : : {
1613 : 0 : nRet = pData[nIndex].nRow+1;
1614 : 0 : ++nIndex;
1615 [ # # ]: 0 : if (nIndex>=nCount)
1616 : 0 : return MAXROW+1; // not found
1617 : : }
1618 : : }
1619 : : }
1620 : 0 : return nRet;
1621 : : }
1622 : :
1623 : 5344256 : void ScAttrArray::FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, ScFlatBoolRowSegments& rUsedRows, bool bReset )
1624 : : {
1625 : 5344256 : SCROW nStart = 0;
1626 : 5344256 : SCSIZE nPos = 0;
1627 [ + + ]: 10688512 : while (nPos < nCount)
1628 : : {
1629 : 5344256 : SCROW nEnd = pData[nPos].nRow;
1630 [ + + ]: 5344256 : if (pData[nPos].pPattern->GetStyleSheet() == pStyleSheet)
1631 : : {
1632 [ + - ]: 3256320 : rUsedRows.setTrue(nStart, nEnd);
1633 : :
1634 [ - + ]: 3256320 : if (bReset)
1635 : : {
1636 [ # # ][ # # ]: 0 : ScPatternAttr* pNewPattern = new ScPatternAttr(*pData[nPos].pPattern);
1637 [ # # ][ # # ]: 0 : pDocument->GetPool()->Remove(*pData[nPos].pPattern);
1638 : : pNewPattern->SetStyleSheet( (ScStyleSheet*)
1639 [ # # ]: 0 : pDocument->GetStyleSheetPool()->
1640 [ # # ]: 0 : Find( ScGlobal::GetRscString(STR_STYLENAME_STANDARD),
1641 : : SFX_STYLE_FAMILY_PARA,
1642 [ # # ][ # # ]: 0 : SFXSTYLEBIT_AUTO | SCSTYLEBIT_STANDARD ) );
1643 : 0 : pData[nPos].pPattern = (const ScPatternAttr*)
1644 [ # # ][ # # ]: 0 : &pDocument->GetPool()->Put(*pNewPattern);
1645 [ # # ][ # # ]: 0 : delete pNewPattern;
1646 : :
1647 [ # # ][ # # ]: 0 : if (Concat(nPos))
1648 : : {
1649 : 0 : Search(nStart, nPos);
1650 : 0 : --nPos; // because ++ at end
1651 : : }
1652 : : }
1653 : : }
1654 : 5344256 : nStart = nEnd + 1;
1655 : 5344256 : ++nPos;
1656 : : }
1657 : 5344256 : }
1658 : :
1659 : :
1660 : 0 : bool ScAttrArray::IsStyleSheetUsed( const ScStyleSheet& rStyle,
1661 : : bool bGatherAllStyles ) const
1662 : : {
1663 : 0 : bool bIsUsed = false;
1664 : 0 : SCSIZE nPos = 0;
1665 : :
1666 [ # # ]: 0 : while ( nPos < nCount )
1667 : : {
1668 : 0 : const ScStyleSheet* pStyle = pData[nPos].pPattern->GetStyleSheet();
1669 [ # # ]: 0 : if ( pStyle )
1670 : : {
1671 : 0 : pStyle->SetUsage( ScStyleSheet::USED );
1672 [ # # ]: 0 : if ( pStyle == &rStyle )
1673 : : {
1674 [ # # ]: 0 : if ( !bGatherAllStyles )
1675 : 0 : return true;
1676 : 0 : bIsUsed = true;
1677 : : }
1678 : : }
1679 : 0 : nPos++;
1680 : : }
1681 : :
1682 : 0 : return bIsUsed;
1683 : : }
1684 : :
1685 : :
1686 : 7 : bool ScAttrArray::IsEmpty() const
1687 : : {
1688 [ + - ]: 7 : if (nCount == 1)
1689 : : {
1690 [ - + ]: 7 : if ( pData[0].pPattern != pDocument->GetDefPattern() )
1691 : 0 : return false;
1692 : : else
1693 : 7 : return true;
1694 : : }
1695 : : else
1696 : 7 : return false;
1697 : : }
1698 : :
1699 : :
1700 : 893952 : bool ScAttrArray::GetFirstVisibleAttr( SCROW& rFirstRow ) const
1701 : : {
1702 : : OSL_ENSURE( nCount, "nCount == 0" );
1703 : :
1704 : 893952 : bool bFound = false;
1705 : 893952 : SCSIZE nStart = 0;
1706 : :
1707 : : // Skip first entry if more than 1 row.
1708 : : // Entries at the end are not skipped, GetFirstVisibleAttr may be larger than GetLastVisibleAttr.
1709 : :
1710 : 893952 : SCSIZE nVisStart = 1;
1711 [ + + ][ + + ]: 894156 : while ( nVisStart < nCount && pData[nVisStart].pPattern->IsVisibleEqual(*pData[nVisStart-1].pPattern) )
[ + + ]
1712 : 204 : ++nVisStart;
1713 [ + + ][ + + ]: 893952 : if ( nVisStart >= nCount || pData[nVisStart-1].nRow > 0 ) // more than 1 row?
1714 : 893946 : nStart = nVisStart;
1715 : :
1716 [ + + ][ + + ]: 894048 : while ( nStart < nCount && !bFound )
[ + + ]
1717 : : {
1718 [ + + ]: 96 : if ( pData[nStart].pPattern->IsVisible() )
1719 : : {
1720 [ + - ]: 90 : rFirstRow = nStart ? ( pData[nStart-1].nRow + 1 ) : 0;
1721 : 90 : bFound = true;
1722 : : }
1723 : : else
1724 : 6 : ++nStart;
1725 : : }
1726 : :
1727 : 893952 : return bFound;
1728 : : }
1729 : :
1730 : : // size (rows) of a range of attributes after cell content where the search is stopped
1731 : : // (more than a default page size, 2*42 because it's as good as any number)
1732 : :
1733 : : const SCROW SC_VISATTR_STOP = 84;
1734 : :
1735 : 1333980 : bool ScAttrArray::GetLastVisibleAttr( SCROW& rLastRow, SCROW nLastData, bool bFullFormattedArea ) const
1736 : : {
1737 : : OSL_ENSURE( nCount, "nCount == 0" );
1738 : :
1739 : : // #i30830# changed behavior:
1740 : : // ignore all attributes starting with the first run of SC_VISATTR_STOP equal rows
1741 : : // below the last content cell
1742 : :
1743 [ - + ]: 1333980 : if ( nLastData == MAXROW )
1744 : : {
1745 : 0 : rLastRow = MAXROW; // can't look for attributes below MAXROW
1746 : 0 : return true;
1747 : : }
1748 : :
1749 : : // Quick check: last data row in or immediately preceding a run that is the
1750 : : // last attribution down to the end, e.g. default style or column style.
1751 : 1333980 : SCSIZE nPos = nCount - 1;
1752 [ + + ]: 1333980 : SCROW nStartRow = (nPos ? pData[nPos-1].nRow + 1 : 0);
1753 [ + + ]: 1333980 : if (nStartRow <= nLastData + 1)
1754 : : {
1755 [ - + ][ # # ]: 1333920 : if (bFullFormattedArea && pData[nPos].pPattern->IsVisible())
[ # # ][ - + ]
1756 : : {
1757 : 0 : rLastRow = pData[nPos].nRow;
1758 : 0 : return true;
1759 : : }
1760 : : else
1761 : : {
1762 : : // Ignore here a few rows if data happens to end within
1763 : : // SC_VISATTR_STOP rows before MAXROW.
1764 : 1333920 : rLastRow = nLastData;
1765 : 1333920 : return false;
1766 : : }
1767 : : }
1768 : :
1769 : : // Find a run below last data row.
1770 : 60 : bool bFound = false;
1771 : 60 : Search( nLastData, nPos );
1772 [ + - ]: 140 : while ( nPos < nCount )
1773 : : {
1774 : : // find range of visually equal formats
1775 : 140 : SCSIZE nEndPos = nPos;
1776 [ + + ][ + + ]: 312 : while ( nEndPos < nCount-1 &&
[ + + ]
1777 [ + - ]: 126 : pData[nEndPos].pPattern->IsVisibleEqual( *pData[nEndPos+1].pPattern))
1778 : 46 : ++nEndPos;
1779 [ + + ]: 140 : SCROW nAttrStartRow = ( nPos > 0 ) ? ( pData[nPos-1].nRow + 1 ) : 0;
1780 [ + + ]: 140 : if ( nAttrStartRow <= nLastData )
1781 : 60 : nAttrStartRow = nLastData + 1;
1782 : 140 : SCROW nAttrSize = pData[nEndPos].nRow + 1 - nAttrStartRow;
1783 [ + + ][ + - ]: 140 : if ( nAttrSize >= SC_VISATTR_STOP && !bFullFormattedArea )
1784 : 60 : break; // while, ignore this range and below
1785 [ + - ][ + - ]: 80 : else if ( pData[nEndPos].pPattern->IsVisible() )
1786 : : {
1787 : 80 : rLastRow = pData[nEndPos].nRow;
1788 : 80 : bFound = true;
1789 : : }
1790 : 80 : nPos = nEndPos + 1;
1791 : : }
1792 : :
1793 : 1333980 : return bFound;
1794 : : }
1795 : :
1796 : :
1797 : 0 : bool ScAttrArray::HasVisibleAttrIn( SCROW nStartRow, SCROW nEndRow ) const
1798 : : {
1799 : : SCSIZE nIndex;
1800 : 0 : Search( nStartRow, nIndex );
1801 : 0 : SCROW nThisStart = nStartRow;
1802 : 0 : bool bFound = false;
1803 [ # # ][ # # ]: 0 : while ( nIndex < nCount && nThisStart <= nEndRow && !bFound )
[ # # ][ # # ]
1804 : : {
1805 [ # # ][ # # ]: 0 : if ( pData[nIndex].pPattern->IsVisible() )
1806 : 0 : bFound = true;
1807 : :
1808 : 0 : nThisStart = pData[nIndex].nRow + 1;
1809 : 0 : ++nIndex;
1810 : : }
1811 : :
1812 : 0 : return bFound;
1813 : : }
1814 : :
1815 : :
1816 : 12 : bool ScAttrArray::IsVisibleEqual( const ScAttrArray& rOther,
1817 : : SCROW nStartRow, SCROW nEndRow ) const
1818 : : {
1819 : 12 : bool bEqual = true;
1820 : 12 : SCSIZE nThisPos = 0;
1821 : 12 : SCSIZE nOtherPos = 0;
1822 [ - + ]: 12 : if ( nStartRow > 0 )
1823 : : {
1824 : 0 : Search( nStartRow, nThisPos );
1825 : 0 : rOther.Search( nStartRow, nOtherPos );
1826 : : }
1827 : :
1828 [ + - ][ + - ]: 48 : while ( nThisPos<nCount && nOtherPos<rOther.nCount && bEqual )
[ + + ][ + + ]
1829 : : {
1830 : 36 : SCROW nThisRow = pData[nThisPos].nRow;
1831 : 36 : SCROW nOtherRow = rOther.pData[nOtherPos].nRow;
1832 : 36 : const ScPatternAttr* pThisPattern = pData[nThisPos].pPattern;
1833 : 36 : const ScPatternAttr* pOtherPattern = rOther.pData[nOtherPos].pPattern;
1834 : : bEqual = ( pThisPattern == pOtherPattern ||
1835 [ + + ][ + - ]: 36 : pThisPattern->IsVisibleEqual(*pOtherPattern) );
[ + + ]
1836 : :
1837 [ + + ]: 36 : if ( nThisRow >= nOtherRow )
1838 : : {
1839 [ - + ]: 30 : if ( nOtherRow >= nEndRow ) break;
1840 : 30 : ++nOtherPos;
1841 : : }
1842 [ + - ]: 36 : if ( nThisRow <= nOtherRow )
1843 : : {
1844 [ - + ]: 36 : if ( nThisRow >= nEndRow ) break;
1845 : 36 : ++nThisPos;
1846 : : }
1847 : : }
1848 : :
1849 : 12 : return bEqual;
1850 : : }
1851 : :
1852 : :
1853 : 14340 : bool ScAttrArray::IsAllEqual( const ScAttrArray& rOther, SCROW nStartRow, SCROW nEndRow ) const
1854 : : {
1855 : : // summarised with IsVisibleEqual
1856 : :
1857 : 14340 : bool bEqual = true;
1858 : 14340 : SCSIZE nThisPos = 0;
1859 : 14340 : SCSIZE nOtherPos = 0;
1860 [ - + ]: 14340 : if ( nStartRow > 0 )
1861 : : {
1862 : 0 : Search( nStartRow, nThisPos );
1863 : 0 : rOther.Search( nStartRow, nOtherPos );
1864 : : }
1865 : :
1866 [ + - ][ + - ]: 14350 : while ( nThisPos<nCount && nOtherPos<rOther.nCount && bEqual )
[ + + ][ + + ]
1867 : : {
1868 : 14342 : SCROW nThisRow = pData[nThisPos].nRow;
1869 : 14342 : SCROW nOtherRow = rOther.pData[nOtherPos].nRow;
1870 : 14342 : const ScPatternAttr* pThisPattern = pData[nThisPos].pPattern;
1871 : 14342 : const ScPatternAttr* pOtherPattern = rOther.pData[nOtherPos].pPattern;
1872 : 14342 : bEqual = ( pThisPattern == pOtherPattern );
1873 : :
1874 [ + + ]: 14342 : if ( nThisRow >= nOtherRow )
1875 : : {
1876 [ + + ]: 14334 : if ( nOtherRow >= nEndRow ) break;
1877 : 2 : ++nOtherPos;
1878 : : }
1879 [ + - ]: 10 : if ( nThisRow <= nOtherRow )
1880 : : {
1881 [ - + ]: 10 : if ( nThisRow >= nEndRow ) break;
1882 : 10 : ++nThisPos;
1883 : : }
1884 : : }
1885 : :
1886 : 14340 : return bEqual;
1887 : : }
1888 : :
1889 : :
1890 : 0 : bool ScAttrArray::TestInsertCol( SCROW nStartRow, SCROW nEndRow) const
1891 : : {
1892 : : // Horizontal aggregate are not allowed to be moved out; if whole summary,
1893 : : // here is not recognized
1894 : :
1895 : 0 : bool bTest = true;
1896 [ # # ]: 0 : if (!IsEmpty())
1897 : : {
1898 : 0 : SCSIZE nIndex = 0;
1899 [ # # ]: 0 : if ( nStartRow > 0 )
1900 : 0 : Search( nStartRow, nIndex );
1901 : :
1902 [ # # ]: 0 : for ( ; nIndex < nCount; nIndex++ )
1903 : : {
1904 [ # # ]: 0 : if ( ((const ScMergeFlagAttr&)pData[nIndex].pPattern->
1905 [ # # ]: 0 : GetItem(ATTR_MERGE_FLAG)).IsHorOverlapped() )
1906 : : {
1907 : 0 : bTest = false; // may not be pushed out
1908 : 0 : break;
1909 : : }
1910 [ # # ]: 0 : if ( pData[nIndex].nRow >= nEndRow ) // end of range
1911 : 0 : break;
1912 : : }
1913 : : }
1914 : 0 : return bTest;
1915 : : }
1916 : :
1917 : :
1918 : 18735 : bool ScAttrArray::TestInsertRow( SCSIZE nSize ) const
1919 : : {
1920 : : // if 1st row pushed out is vertically overlapped, summary would be broken
1921 : :
1922 [ + - ]: 18735 : if (pData)
1923 : : {
1924 : : // MAXROW + 1 - nSize = 1st row pushed out
1925 : :
1926 : 18735 : SCSIZE nFirstLost = nCount-1;
1927 [ + + ][ - + ]: 18735 : while ( nFirstLost && pData[nFirstLost-1].nRow >= sal::static_int_cast<SCROW>(MAXROW + 1 - nSize) )
[ - + ]
1928 : 0 : --nFirstLost;
1929 : :
1930 [ - + ]: 18735 : if ( ((const ScMergeFlagAttr&)pData[nFirstLost].pPattern->
1931 : 18735 : GetItem(ATTR_MERGE_FLAG)).IsVerOverlapped() )
1932 : 0 : return false;
1933 : : }
1934 : :
1935 : 18735 : return true;
1936 : : }
1937 : :
1938 : :
1939 : 18735 : void ScAttrArray::InsertRow( SCROW nStartRow, SCSIZE nSize )
1940 : : {
1941 [ + - ]: 18735 : if (!pData)
1942 : 18735 : return;
1943 : :
1944 [ + + ]: 18735 : SCROW nSearch = nStartRow > 0 ? nStartRow - 1 : 0; // expand predecessor
1945 : : SCSIZE nIndex;
1946 : 18735 : Search( nSearch, nIndex );
1947 : :
1948 : : // set ScMergeAttr may not be extended (so behind delete again)
1949 : :
1950 [ + - ]: 18735 : bool bDoMerge = ((const ScMergeAttr&) pData[nIndex].pPattern->GetItem(ATTR_MERGE)).IsMerged();
1951 : :
1952 : 18735 : SCSIZE nRemove = 0;
1953 : : SCSIZE i;
1954 [ + + ]: 18749 : for (i = nIndex; i < nCount-1; i++)
1955 : : {
1956 : 14 : SCROW nNew = pData[i].nRow + nSize;
1957 [ - + ]: 14 : if ( nNew >= MAXROW ) // at end?
1958 : : {
1959 : 0 : nNew = MAXROW;
1960 [ # # ]: 0 : if (!nRemove)
1961 : 0 : nRemove = i+1; // remove the following?
1962 : : }
1963 : 14 : pData[i].nRow = nNew;
1964 : : }
1965 : :
1966 : : // Remove entries at end ?
1967 : :
1968 [ - + ][ # # ]: 18735 : if (nRemove && nRemove < nCount)
1969 [ # # ]: 0 : DeleteRange( nRemove, nCount-1 );
1970 : :
1971 [ - + ]: 18735 : if (bDoMerge) // extensively repair (again) ScMergeAttr
1972 : : {
1973 : : // ApplyAttr for areas
1974 : :
1975 [ # # ][ # # ]: 0 : const SfxPoolItem& rDef = pDocument->GetPool()->GetDefaultItem( ATTR_MERGE );
1976 [ # # ]: 0 : for (SCSIZE nAdd=0; nAdd<nSize; nAdd++)
1977 [ # # ]: 0 : pDocument->ApplyAttr( nCol, nStartRow+nAdd, nTab, rDef );
1978 : :
1979 : : // reply inserts in this area not summarized
1980 : : }
1981 : :
1982 : : // Don't duplicate the merge flags in the inserted row.
1983 : : // #i108488# SC_MF_SCENARIO has to be allowed.
1984 [ + - ]: 18735 : RemoveFlags( nStartRow, nStartRow+nSize-1, SC_MF_HOR | SC_MF_VER | SC_MF_AUTO | SC_MF_BUTTON );
1985 : : }
1986 : :
1987 : :
1988 : 10240 : void ScAttrArray::DeleteRow( SCROW nStartRow, SCSIZE nSize )
1989 : : {
1990 [ + - ]: 10240 : if (pData)
1991 : : {
1992 : 10240 : bool bFirst=true;
1993 : 10240 : SCSIZE nStartIndex = 0;
1994 : 10240 : SCSIZE nEndIndex = 0;
1995 : : SCSIZE i;
1996 : :
1997 [ + + ]: 10248 : for ( i = 0; i < nCount-1; i++)
1998 [ + + ][ + + ]: 8 : if (pData[i].nRow >= nStartRow && pData[i].nRow <= sal::static_int_cast<SCROW>(nStartRow+nSize-1))
[ + + ]
1999 : : {
2000 [ + - ]: 2 : if (bFirst)
2001 : : {
2002 : 2 : nStartIndex = i;
2003 : 2 : bFirst = false;
2004 : : }
2005 : 2 : nEndIndex = i;
2006 : : }
2007 [ + + ]: 10240 : if (!bFirst)
2008 : : {
2009 : : SCROW nStart;
2010 [ - + ]: 2 : if (nStartIndex==0)
2011 : 0 : nStart = 0;
2012 : : else
2013 : 2 : nStart = pData[nStartIndex-1].nRow + 1;
2014 : :
2015 [ - + ]: 2 : if (nStart < nStartRow)
2016 : : {
2017 : 0 : pData[nStartIndex].nRow = nStartRow - 1;
2018 : 0 : ++nStartIndex;
2019 : : }
2020 [ + - ]: 2 : if (nEndIndex >= nStartIndex)
2021 : : {
2022 : 2 : DeleteRange( nStartIndex, nEndIndex );
2023 [ + - ]: 2 : if (nStartIndex > 0)
2024 [ + - ]: 2 : if ( pData[nStartIndex-1].pPattern == pData[nStartIndex].pPattern )
2025 : 2 : DeleteRange( nStartIndex-1, nStartIndex-1 );
2026 : : }
2027 : : }
2028 [ + + ]: 10244 : for (i = 0; i < nCount-1; i++)
2029 [ + + ]: 4 : if (pData[i].nRow >= nStartRow)
2030 : 3 : pData[i].nRow -= nSize;
2031 : :
2032 : : // Below does not follow the pattern to detect pressure ranges;
2033 : : // instead, only remove merge flags.
2034 : 10240 : RemoveFlags( MAXROW-nSize+1, MAXROW, SC_MF_HOR | SC_MF_VER | SC_MF_AUTO );
2035 : : }
2036 : 10240 : }
2037 : :
2038 : :
2039 : 4 : void ScAttrArray::DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex )
2040 : : {
2041 : 4 : ScDocumentPool* pDocPool = pDocument->GetPool();
2042 [ + + ]: 8 : for (SCSIZE i = nStartIndex; i <= nEndIndex; i++)
2043 : 4 : pDocPool->Remove(*pData[i].pPattern);
2044 : :
2045 : 4 : memmove( &pData[nStartIndex], &pData[nEndIndex + 1], (nCount - nEndIndex - 1) * sizeof(ScAttrEntry) );
2046 : 4 : nCount -= nEndIndex-nStartIndex+1;
2047 : 4 : }
2048 : :
2049 : :
2050 : 8399 : void ScAttrArray::DeleteArea(SCROW nStartRow, SCROW nEndRow)
2051 : : {
2052 : 8399 : RemoveAreaMerge( nStartRow, nEndRow ); // remove from combined flags
2053 : :
2054 [ + + ]: 8399 : if ( !HasAttrib( nStartRow, nEndRow, HASATTR_OVERLAPPED | HASATTR_AUTOFILTER) )
2055 : 8373 : SetPatternArea( nStartRow, nEndRow, pDocument->GetDefPattern() );
2056 : : else
2057 : 26 : DeleteAreaSafe( nStartRow, nEndRow ); // leave merge flags
2058 : 8399 : }
2059 : :
2060 : :
2061 : 2 : void ScAttrArray::DeleteHardAttr(SCROW nStartRow, SCROW nEndRow)
2062 : : {
2063 [ + - ]: 2 : const ScPatternAttr* pDefPattern = pDocument->GetDefPattern();
2064 : : const ScPatternAttr* pOldPattern;
2065 : :
2066 : : SCSIZE nIndex;
2067 : : SCROW nRow;
2068 : : SCROW nThisRow;
2069 : :
2070 : 2 : Search( nStartRow, nIndex );
2071 [ + - ]: 2 : nThisRow = (nIndex>0) ? pData[nIndex-1].nRow+1 : 0;
2072 [ - + ]: 2 : if (nThisRow < nStartRow) nThisRow = nStartRow;
2073 : :
2074 [ + + ]: 4 : while ( nThisRow <= nEndRow )
2075 : : {
2076 : 2 : pOldPattern = pData[nIndex].pPattern;
2077 : :
2078 [ + - ]: 2 : if ( pOldPattern->GetItemSet().Count() ) // hard attributes ?
2079 : : {
2080 : 2 : nRow = pData[nIndex].nRow;
2081 : 2 : SCROW nAttrRow = Min( (SCROW)nRow, (SCROW)nEndRow );
2082 : :
2083 [ + - ]: 2 : ScPatternAttr aNewPattern(*pOldPattern);
2084 : 2 : SfxItemSet& rSet = aNewPattern.GetItemSet();
2085 [ + + ]: 114 : for (sal_uInt16 nId = ATTR_PATTERN_START; nId <= ATTR_PATTERN_END; nId++)
2086 [ + + ][ + + ]: 112 : if (nId != ATTR_MERGE && nId != ATTR_MERGE_FLAG)
2087 [ + - ]: 108 : rSet.ClearItem(nId);
2088 : :
2089 [ + - ][ + - ]: 2 : if ( aNewPattern == *pDefPattern )
2090 [ + - ]: 2 : SetPatternArea( nThisRow, nAttrRow, pDefPattern, false );
2091 : : else
2092 [ # # ]: 0 : SetPatternArea( nThisRow, nAttrRow, &aNewPattern, true );
2093 : :
2094 [ + - ]: 2 : Search( nThisRow, nIndex ); // data changed
2095 : : }
2096 : :
2097 : 2 : ++nIndex;
2098 : 2 : nThisRow = pData[nIndex-1].nRow+1;
2099 : : }
2100 : 2 : }
2101 : :
2102 : :
2103 : : // move within a document
2104 : :
2105 : 3066 : void ScAttrArray::MoveTo(SCROW nStartRow, SCROW nEndRow, ScAttrArray& rAttrArray)
2106 : : {
2107 : 3066 : SCROW nStart = nStartRow;
2108 [ + + ]: 6132 : for (SCSIZE i = 0; i < nCount; i++)
2109 : : {
2110 [ + - ][ - + ]: 3066 : if ((pData[i].nRow >= nStartRow) && ((i==0) ? true : pData[i-1].nRow < nEndRow))
[ # # ]
2111 : : {
2112 : : // copy (bPutToPool=TRUE)
2113 : 3066 : rAttrArray.SetPatternArea( nStart, Min( (SCROW)pData[i].nRow, (SCROW)nEndRow ),
2114 : 3066 : pData[i].pPattern, true );
2115 : : }
2116 : 3066 : nStart = Max( (SCROW)nStart, (SCROW)(pData[i].nRow + 1) );
2117 : : }
2118 : 3066 : DeleteArea(nStartRow, nEndRow);
2119 : 3066 : }
2120 : :
2121 : :
2122 : : // copy between documents (Clipboard)
2123 : :
2124 : 52444 : void ScAttrArray::CopyArea( SCROW nStartRow, SCROW nEndRow, long nDy, ScAttrArray& rAttrArray,
2125 : : sal_Int16 nStripFlags )
2126 : : {
2127 : 52444 : nStartRow -= nDy; // Source
2128 : 52444 : nEndRow -= nDy;
2129 : :
2130 : 52444 : SCROW nDestStart = Max((long)((long)nStartRow + nDy), (long) 0);
2131 : 52444 : SCROW nDestEnd = Min((long)((long)nEndRow + nDy), (long) MAXROW);
2132 : :
2133 : 52444 : ScDocumentPool* pSourceDocPool = pDocument->GetPool();
2134 : 52444 : ScDocumentPool* pDestDocPool = rAttrArray.pDocument->GetPool();
2135 : 52444 : bool bSamePool = (pSourceDocPool==pDestDocPool);
2136 : :
2137 [ + + ][ + + ]: 108740 : for (SCSIZE i = 0; (i < nCount) && (nDestStart <= nDestEnd); i++)
[ + + ]
2138 : : {
2139 [ + + ]: 56296 : if (pData[i].nRow >= nStartRow)
2140 : : {
2141 : 55590 : const ScPatternAttr* pOldPattern = pData[i].pPattern;
2142 : : const ScPatternAttr* pNewPattern;
2143 : :
2144 [ + + ]: 55590 : if (IsDefaultItem( pOldPattern ))
2145 : : {
2146 : : // default: nothing changed
2147 : :
2148 : : pNewPattern = (const ScPatternAttr*)
2149 : 49946 : &pDestDocPool->GetDefaultItem( ATTR_PATTERN );
2150 : : }
2151 [ - + ]: 5644 : else if ( nStripFlags )
2152 : : {
2153 [ # # ]: 0 : ScPatternAttr* pTmpPattern = new ScPatternAttr( *pOldPattern );
2154 : 0 : sal_Int16 nNewFlags = 0;
2155 [ # # ]: 0 : if ( nStripFlags != SC_MF_ALL )
2156 : 0 : nNewFlags = ((const ScMergeFlagAttr&)pTmpPattern->GetItem(ATTR_MERGE_FLAG)).
2157 : 0 : GetValue() & ~nStripFlags;
2158 : :
2159 [ # # ]: 0 : if ( nNewFlags )
2160 [ # # ]: 0 : pTmpPattern->GetItemSet().Put( ScMergeFlagAttr( nNewFlags ) );
2161 : : else
2162 : 0 : pTmpPattern->GetItemSet().ClearItem( ATTR_MERGE_FLAG );
2163 : :
2164 [ # # ]: 0 : if (bSamePool)
2165 : 0 : pNewPattern = (ScPatternAttr*) &pDestDocPool->Put(*pTmpPattern);
2166 : : else
2167 : 0 : pNewPattern = pTmpPattern->PutInPool( rAttrArray.pDocument, pDocument );
2168 [ # # ]: 0 : delete pTmpPattern;
2169 : : }
2170 : : else
2171 : : {
2172 [ + + ]: 5644 : if (bSamePool)
2173 : 5630 : pNewPattern = (ScPatternAttr*) &pDestDocPool->Put(*pOldPattern);
2174 : : else
2175 : 14 : pNewPattern = pOldPattern->PutInPool( rAttrArray.pDocument, pDocument );
2176 : : }
2177 : :
2178 : : rAttrArray.SetPatternArea(nDestStart,
2179 : 55590 : Min((SCROW)(pData[i].nRow + nDy), nDestEnd), pNewPattern);
2180 : : }
2181 : :
2182 : : // when pasting from clipboard and skipping filtered rows, the adjusted
2183 : : // end position can be negative
2184 : 56296 : nDestStart = Max((long)nDestStart, (long)(pData[i].nRow + nDy + 1));
2185 : : }
2186 : 52444 : }
2187 : :
2188 : :
2189 : : // leave flags
2190 : : // summarized with CopyArea
2191 : :
2192 : 95 : void ScAttrArray::CopyAreaSafe( SCROW nStartRow, SCROW nEndRow, long nDy, ScAttrArray& rAttrArray )
2193 : : {
2194 : 95 : nStartRow -= nDy; // Source
2195 : 95 : nEndRow -= nDy;
2196 : :
2197 : 95 : SCROW nDestStart = Max((long)((long)nStartRow + nDy), (long) 0);
2198 : 95 : SCROW nDestEnd = Min((long)((long)nEndRow + nDy), (long) MAXROW);
2199 : :
2200 [ + - ]: 95 : if ( !rAttrArray.HasAttrib( nDestStart, nDestEnd, HASATTR_OVERLAPPED ) )
2201 : : {
2202 : 95 : CopyArea( nStartRow+nDy, nEndRow+nDy, nDy, rAttrArray );
2203 : 95 : return;
2204 : : }
2205 : :
2206 : 0 : ScDocumentPool* pSourceDocPool = pDocument->GetPool();
2207 : 0 : ScDocumentPool* pDestDocPool = rAttrArray.pDocument->GetPool();
2208 : 0 : bool bSamePool = (pSourceDocPool==pDestDocPool);
2209 : :
2210 [ # # ][ # # ]: 0 : for (SCSIZE i = 0; (i < nCount) && (nDestStart <= nDestEnd); i++)
[ # # ]
2211 : : {
2212 [ # # ]: 0 : if (pData[i].nRow >= nStartRow)
2213 : : {
2214 : 0 : const ScPatternAttr* pOldPattern = pData[i].pPattern;
2215 : : const ScPatternAttr* pNewPattern;
2216 : :
2217 [ # # ]: 0 : if (bSamePool)
2218 : 0 : pNewPattern = (ScPatternAttr*) &pDestDocPool->Put(*pOldPattern);
2219 : : else
2220 : 0 : pNewPattern = pOldPattern->PutInPool( rAttrArray.pDocument, pDocument );
2221 : :
2222 : : rAttrArray.SetPatternAreaSafe(nDestStart,
2223 : 0 : Min((SCROW)(pData[i].nRow + nDy), nDestEnd), pNewPattern, false);
2224 : : }
2225 : :
2226 : : // when pasting from clipboard and skipping filtered rows, the adjusted
2227 : : // end position can be negative
2228 : 0 : nDestStart = Max((long)nDestStart, (long)(pData[i].nRow + nDy + 1));
2229 : : }
2230 : : }
2231 : :
2232 : :
2233 : 0 : SCsROW ScAttrArray::SearchStyle( SCsROW nRow, const ScStyleSheet* pSearchStyle,
2234 : : bool bUp, ScMarkArray* pMarkArray )
2235 : : {
2236 : 0 : bool bFound = false;
2237 : :
2238 [ # # ]: 0 : if (pMarkArray)
2239 : : {
2240 [ # # ]: 0 : nRow = pMarkArray->GetNextMarked( nRow, bUp );
2241 [ # # ]: 0 : if (!VALIDROW(nRow))
2242 : 0 : return nRow;
2243 : : }
2244 : :
2245 : : SCSIZE nIndex;
2246 : 0 : Search(nRow, nIndex);
2247 : 0 : const ScPatternAttr* pPattern = pData[nIndex].pPattern;
2248 : :
2249 [ # # ][ # # ]: 0 : while (nIndex < nCount && !bFound)
[ # # ]
2250 : : {
2251 [ # # ]: 0 : if (pPattern->GetStyleSheet() == pSearchStyle)
2252 : : {
2253 [ # # ]: 0 : if (pMarkArray)
2254 : : {
2255 [ # # ]: 0 : nRow = pMarkArray->GetNextMarked( nRow, bUp );
2256 [ # # ]: 0 : SCROW nStart = nIndex ? pData[nIndex-1].nRow+1 : 0;
2257 [ # # ][ # # ]: 0 : if (nRow >= nStart && nRow <= pData[nIndex].nRow)
2258 : 0 : bFound = true;
2259 : : }
2260 : : else
2261 : 0 : bFound = true;
2262 : : }
2263 : :
2264 [ # # ]: 0 : if (!bFound)
2265 : : {
2266 [ # # ]: 0 : if (bUp)
2267 : : {
2268 [ # # ]: 0 : if (nIndex==0)
2269 : : {
2270 : 0 : nIndex = nCount;
2271 : 0 : nRow = -1;
2272 : : }
2273 : : else
2274 : : {
2275 : 0 : --nIndex;
2276 : 0 : nRow = pData[nIndex].nRow;
2277 : 0 : pPattern = pData[nIndex].pPattern;
2278 : : }
2279 : : }
2280 : : else
2281 : : {
2282 : 0 : nRow = pData[nIndex].nRow+1;
2283 : 0 : ++nIndex;
2284 [ # # ]: 0 : if (nIndex<nCount)
2285 : 0 : pPattern = pData[nIndex].pPattern;
2286 : : }
2287 : : }
2288 : : }
2289 : :
2290 : : OSL_ENSURE( bFound || !ValidRow(nRow), "Internal failure in in ScAttrArray::SearchStyle" );
2291 : :
2292 : 0 : return nRow;
2293 : : }
2294 : :
2295 : :
2296 : 0 : bool ScAttrArray::SearchStyleRange( SCsROW& rRow, SCsROW& rEndRow,
2297 : : const ScStyleSheet* pSearchStyle, bool bUp, ScMarkArray* pMarkArray )
2298 : : {
2299 : 0 : SCsROW nStartRow = SearchStyle( rRow, pSearchStyle, bUp, pMarkArray );
2300 [ # # ]: 0 : if (VALIDROW(nStartRow))
2301 : : {
2302 : : SCSIZE nIndex;
2303 : 0 : Search(nStartRow,nIndex);
2304 : :
2305 : 0 : rRow = nStartRow;
2306 [ # # ]: 0 : if (bUp)
2307 : : {
2308 [ # # ]: 0 : if (nIndex>0)
2309 : 0 : rEndRow = pData[nIndex-1].nRow + 1;
2310 : : else
2311 : 0 : rEndRow = 0;
2312 [ # # ]: 0 : if (pMarkArray)
2313 : : {
2314 [ # # ]: 0 : SCROW nMarkEnd = pMarkArray->GetMarkEnd( nStartRow, true );
2315 [ # # ]: 0 : if (nMarkEnd>rEndRow)
2316 : 0 : rEndRow = nMarkEnd;
2317 : : }
2318 : : }
2319 : : else
2320 : : {
2321 : 0 : rEndRow = pData[nIndex].nRow;
2322 [ # # ]: 0 : if (pMarkArray)
2323 : : {
2324 [ # # ]: 0 : SCROW nMarkEnd = pMarkArray->GetMarkEnd( nStartRow, false );
2325 [ # # ]: 0 : if (nMarkEnd<rEndRow)
2326 : 0 : rEndRow = nMarkEnd;
2327 : : }
2328 : : }
2329 : :
2330 : 0 : return true;
2331 : : }
2332 : : else
2333 : 0 : return false;
2334 : : }
2335 : :
2336 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|