1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: attarray.cxx,v $
10 * $Revision: 1.25.32.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 //------------------------------------------------------------------------
38 #include "scitems.hxx"
39 #include <svx/algitem.hxx>
40 #include <svx/boxitem.hxx>
41 #include <svx/bolnitem.hxx>
42 #include <svx/frmdiritem.hxx>
43 #include <svx/shaditem.hxx>
44 #include <svx/editobj.hxx>
45 #include <svtools/poolcach.hxx>
46 #include <svx/fontitem.hxx>
47 #include <vcl/fontcvt.hxx>
49 #include "attarray.hxx"
51 #include "document.hxx"
52 #include "docpool.hxx"
53 #include "patattr.hxx"
54 #include "stlsheet.hxx"
55 #include "stlpool.hxx"
56 #include "markarr.hxx"
57 #include "rechead.hxx"
58 #include "globstr.hrc"
60 #include "segmenttree.hxx"
63 #define DBGOUTPUT(s) \
64 DBG_ERROR( String("Invalidate ") + String(s) + String(": ") \
65 + String(nCol) + String('/') + String(aAdrStart.Row()) + String('/') + String(nTab) \
67 + String(nCol) + String('/') + String(aAdrEnd.Row()) + String('/') + String(nTab) \
70 // STATIC DATA -----------------------------------------------------------
73 //------------------------------------------------------------------------
75 ScAttrArray::ScAttrArray( SCCOL nNewCol
, SCTAB nNewTab
, ScDocument
* pDoc
) :
81 pData
= new ScAttrEntry
[1];
84 pData
[0].nRow
= MAXROW
;
85 pData
[0].pPattern
= pDocument
->GetDefPattern(); // ohne Put !!!
89 //------------------------------------------------------------------------
91 ScAttrArray::~ScAttrArray()
99 ScDocumentPool
* pDocPool
= pDocument
->GetPool();
100 for (SCSIZE i
=0; i
<nCount
; i
++)
101 pDocPool
->Remove(*pData
[i
].pPattern
);
107 //------------------------------------------------------------------------
109 void ScAttrArray::TestData() const
116 for (nPos
=0; nPos
<nCount
; nPos
++)
119 if (pData
[nPos
].pPattern
== pData
[nPos
-1].pPattern
|| pData
[nPos
].nRow
<= pData
[nPos
-1].nRow
)
121 if (pData
[nPos
].pPattern
->Which() != ATTR_PATTERN
)
124 if ( nPos
&& pData
[nPos
-1].nRow
!= MAXROW
)
129 ByteString aMsg
= ByteString::CreateFromInt32(nErr
);
130 aMsg
+= " errors in attribute array, column ";
131 aMsg
+= ByteString::CreateFromInt32(nCol
);
132 DBG_ERROR( aMsg
.GetBuffer() );
137 //------------------------------------------------------------------------
139 void ScAttrArray::Reset( const ScPatternAttr
* pPattern
, BOOL bAlloc
)
143 ScDocumentPool
* pDocPool
= pDocument
->GetPool();
144 const ScPatternAttr
* pOldPattern
;
145 ScAddress
aAdrStart( nCol
, 0, nTab
);
146 ScAddress
aAdrEnd ( nCol
, 0, nTab
);
148 for (SCSIZE i
=0; i
<nCount
; i
++)
150 // ueberpruefen, ob Attributierung die Textbreite der Zelle aendert
151 pOldPattern
= pData
[i
].pPattern
;
152 BOOL bNumFormatChanged
;
153 if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged
,
154 pPattern
->GetItemSet(), pOldPattern
->GetItemSet() ) )
156 aAdrStart
.SetRow( i
? pData
[i
-1].nRow
+1 : 0 );
157 aAdrEnd
.SetRow( pData
[i
].nRow
);
158 pDocument
->InvalidateTextWidth( &aAdrStart
, &aAdrEnd
, bNumFormatChanged
);
159 #ifdef DBG_INVALIDATE
163 // bedingtes Format gesetzt oder geloescht?
164 if ( &pPattern
->GetItem(ATTR_CONDITIONAL
) != &pOldPattern
->GetItem(ATTR_CONDITIONAL
) )
166 pDocument
->ConditionalChanged( ((const SfxUInt32Item
&)
167 pOldPattern
->GetItem(ATTR_CONDITIONAL
)).GetValue() );
168 pDocument
->ConditionalChanged( ((const SfxUInt32Item
&)
169 pPattern
->GetItem(ATTR_CONDITIONAL
)).GetValue() );
171 pDocPool
->Remove(*pOldPattern
);
175 if (pDocument
->IsStreamValid(nTab
))
176 pDocument
->SetStreamValid(nTab
, FALSE
);
181 pData
= new ScAttrEntry
[1];
184 ScPatternAttr
* pNewPattern
= (ScPatternAttr
*) &pDocPool
->Put(*pPattern
);
185 pData
[0].nRow
= MAXROW
;
186 pData
[0].pPattern
= pNewPattern
;
192 pData
= NULL
; // muss sofort wieder belegt werden !
198 BOOL
ScAttrArray::Concat(SCSIZE nPos
)
201 if (pData
&& (nPos
< nCount
))
205 if (pData
[nPos
- 1].pPattern
== pData
[nPos
].pPattern
)
207 pData
[nPos
- 1].nRow
= pData
[nPos
].nRow
;
208 pDocument
->GetPool()->Remove(*pData
[nPos
].pPattern
);
209 memmove(&pData
[nPos
], &pData
[nPos
+ 1], (nCount
- nPos
- 1) * sizeof(ScAttrEntry
));
210 pData
[nCount
- 1].pPattern
= NULL
;
211 pData
[nCount
- 1].nRow
= 0;
217 if (nPos
+ 1 < nCount
)
219 if (pData
[nPos
+ 1].pPattern
== pData
[nPos
].pPattern
)
221 pData
[nPos
].nRow
= pData
[nPos
+ 1].nRow
;
222 pDocument
->GetPool()->Remove(*pData
[nPos
].pPattern
);
223 memmove(&pData
[nPos
+ 1], &pData
[nPos
+ 2], (nCount
- nPos
- 2) * sizeof(ScAttrEntry
));
224 pData
[nCount
- 1].pPattern
= NULL
;
225 pData
[nCount
- 1].nRow
= 0;
234 //------------------------------------------------------------------------
236 BOOL
ScAttrArray::Search( SCROW nRow
, SCSIZE
& nIndex
) const
239 long nHi
= static_cast<long>(nCount
) - 1;
243 BOOL bFound
= (nCount
== 1);
246 while ( !bFound
&& nLo
<= nHi
)
250 nStartRow
= (long) pData
[i
- 1].nRow
;
253 nEndRow
= (long) pData
[i
].nRow
;
254 if (nEndRow
< (long) nRow
)
257 if (nStartRow
>= (long) nRow
)
274 const ScPatternAttr
* ScAttrArray::GetPattern( SCROW nRow
) const
277 if (Search( nRow
, i
))
278 return pData
[i
].pPattern
;
284 const ScPatternAttr
* ScAttrArray::GetPatternRange( SCROW
& rStartRow
,
285 SCROW
& rEndRow
, SCROW nRow
) const
288 if ( Search( nRow
, nIndex
) )
291 rStartRow
= pData
[nIndex
-1].nRow
+ 1;
294 rEndRow
= pData
[nIndex
].nRow
;
295 return pData
[nIndex
].pPattern
;
300 //------------------------------------------------------------------------
302 void ScAttrArray::SetPattern( SCROW nRow
, const ScPatternAttr
* pPattern
, BOOL bPutToPool
)
304 SetPatternArea( nRow
, nRow
, pPattern
, bPutToPool
);
307 void ScAttrArray::RemoveCellCharAttribs( SCROW nStartRow
, SCROW nEndRow
,
308 const ScPatternAttr
* pPattern
, ScEditDataArray
* pDataArray
)
310 for (SCROW nRow
= nStartRow
; nRow
<= nEndRow
; ++nRow
)
313 pDocument
->GetCell(nCol
, nRow
, nTab
, pCell
);
314 if (pCell
&& pCell
->GetCellType() == CELLTYPE_EDIT
)
316 EditTextObject
* pOldData
= NULL
;
317 ScEditCell
* pEditCell
= static_cast<ScEditCell
*>(pCell
);
319 pOldData
= pEditCell
->GetData()->Clone();
320 pEditCell
->RemoveCharAttribs(*pPattern
);
323 EditTextObject
* pNewData
= pEditCell
->GetData()->Clone();
324 pDataArray
->AddItem(nTab
, nCol
, nRow
, pOldData
, pNewData
);
330 void ScAttrArray::SetPatternArea(SCROW nStartRow
, SCROW nEndRow
, const ScPatternAttr
*pPattern
,
331 BOOL bPutToPool
, ScEditDataArray
* pDataArray
)
333 if (ValidRow(nStartRow
) && ValidRow(nEndRow
))
336 pPattern
= (const ScPatternAttr
*) &pDocument
->GetPool()->Put(*pPattern
);
338 if ((nStartRow
== 0) && (nEndRow
== MAXROW
))
342 SCSIZE nNeeded
= nCount
+ 2;
343 if ( nLimit
< nNeeded
)
345 nLimit
+= SC_ATTRARRAY_DELTA
;
346 if ( nLimit
< nNeeded
)
348 ScAttrEntry
* pNewData
= new ScAttrEntry
[nLimit
];
349 memcpy( pNewData
, pData
, nCount
*sizeof(ScAttrEntry
) );
354 ScAddress
aAdrStart( nCol
, 0, nTab
);
355 ScAddress
aAdrEnd ( nCol
, 0, nTab
);
357 SCSIZE ni
= 0; // number of entries in beginning
358 SCSIZE nx
= 0; // track position
359 SCROW ns
= 0; // start row of track position
364 Search( nStartRow
, nIndex
);
370 ns
= pData
[ni
-1].nRow
+1;
374 // ueberpruefen, ob Attributierung die Textbreite der Zelle aendert
375 // oder bedingte Formate neu gesetzt oder geloescht werden
376 while ( ns
<= nEndRow
)
378 const SfxItemSet
& rNewSet
= pPattern
->GetItemSet();
379 const SfxItemSet
& rOldSet
= pData
[nx
].pPattern
->GetItemSet();
381 BOOL bNumFormatChanged
;
382 if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged
,
385 aAdrStart
.SetRow( Max(nStartRow
,ns
) );
386 aAdrEnd
.SetRow( Min(nEndRow
,pData
[nx
].nRow
) );
387 pDocument
->InvalidateTextWidth( &aAdrStart
, &aAdrEnd
, bNumFormatChanged
);
388 #ifdef DBG_INVALIDATE
389 DBGOUTPUT("SetPatternArea");
392 if ( &rNewSet
.Get(ATTR_CONDITIONAL
) != &rOldSet
.Get(ATTR_CONDITIONAL
) )
394 pDocument
->ConditionalChanged( ((const SfxUInt32Item
&)
395 rOldSet
.Get(ATTR_CONDITIONAL
)).GetValue() );
396 pDocument
->ConditionalChanged( ((const SfxUInt32Item
&)
397 rNewSet
.Get(ATTR_CONDITIONAL
)).GetValue() );
399 ns
= pData
[nx
].nRow
+ 1;
403 // continue modifying data array
405 SCSIZE nInsert
; // insert position (MAXROWCOUNT := no insert)
406 BOOL bCombined
= FALSE
;
410 nInsert
= MAXROWCOUNT
;
411 if ( pData
[ni
].pPattern
!= pPattern
)
413 if ( ni
== 0 || (pData
[ni
-1].nRow
< nStartRow
- 1) )
414 { // may be a split or a simple insert or just a shrink,
415 // row adjustment is done further down
416 if ( pData
[ni
].nRow
> nEndRow
)
421 else if ( ni
> 0 && pData
[ni
-1].nRow
== nStartRow
- 1 )
424 if ( ni
> 0 && pData
[ni
-1].pPattern
== pPattern
)
426 pData
[ni
-1].nRow
= nEndRow
;
427 nInsert
= MAXROWCOUNT
;
434 SCSIZE nj
= ni
; // stop position of range to replace
435 while ( nj
< nCount
&& pData
[nj
].nRow
<= nEndRow
)
439 if ( nj
< nCount
&& pData
[nj
].pPattern
== pPattern
)
443 if ( pData
[ni
-1].pPattern
== pPattern
)
444 { // adjacent entries
445 pData
[ni
-1].nRow
= pData
[nj
].nRow
;
448 else if ( ni
== nInsert
)
449 pData
[ni
-1].nRow
= nStartRow
- 1; // shrink
451 nInsert
= MAXROWCOUNT
;
454 else if ( ni
> 0 && ni
== nInsert
)
455 pData
[ni
-1].nRow
= nStartRow
- 1; // shrink
457 ScDocumentPool
* pDocPool
= pDocument
->GetPool();
459 { // duplicate splitted entry in pool
460 pDocPool
->Put( *pData
[ni
-1].pPattern
);
463 { // remove middle entries
464 for ( SCSIZE nk
=ni
; nk
<nj
; nk
++)
465 { // remove entries from pool
466 pDocPool
->Remove( *pData
[nk
].pPattern
);
469 { // replace one entry
470 pData
[ni
].nRow
= nEndRow
;
471 pData
[ni
].pPattern
= pPattern
;
473 nInsert
= MAXROWCOUNT
;
477 memmove( pData
+ ni
, pData
+ nj
, (nCount
- nj
) * sizeof(ScAttrEntry
) );
482 if ( nInsert
< sal::static_int_cast
<SCSIZE
>(MAXROWCOUNT
) )
483 { // insert or append new entry
484 if ( nInsert
<= nCount
)
487 memmove( pData
+ nInsert
+ 1, pData
+ nInsert
,
488 (nCount
- nInsert
) * sizeof(ScAttrEntry
) );
491 memmove( pData
+ nInsert
+ 2, pData
+ nInsert
,
492 (nCount
- nInsert
) * sizeof(ScAttrEntry
) );
493 pData
[nInsert
+1] = pData
[nInsert
-1];
498 pData
[nInsert
-1].nRow
= nStartRow
- 1;
499 pData
[nInsert
].nRow
= nEndRow
;
500 pData
[nInsert
].pPattern
= pPattern
;
502 // Remove character attributes from these cells if the pattern
503 // is applied during normal session. We don't want to do this
504 // while importing document.
505 if (!pDocument
->IsLoadingMedium())
506 RemoveCellCharAttribs(nStartRow
, nEndRow
, pPattern
,pDataArray
);
511 if (pDocument
->IsStreamValid(nTab
))
512 pDocument
->SetStreamValid(nTab
, FALSE
);
515 // InfoBox(0, String(nCount) + String(" Eintraege") ).Execute();
523 void ScAttrArray::ApplyStyleArea( SCROW nStartRow
, SCROW nEndRow
, ScStyleSheet
* pStyle
)
525 if (ValidRow(nStartRow
) && ValidRow(nEndRow
))
529 if (!Search( nStartRow
, nPos
))
531 DBG_ERROR("Search-Fehler");
535 ScAddress
aAdrStart( nCol
, 0, nTab
);
536 ScAddress
aAdrEnd ( nCol
, 0, nTab
);
540 const ScPatternAttr
* pOldPattern
= pData
[nPos
].pPattern
;
541 ScPatternAttr
* pNewPattern
= new ScPatternAttr(*pOldPattern
);
542 pNewPattern
->SetStyleSheet(pStyle
);
544 SCROW nY2
= pData
[nPos
].nRow
;
545 nStart
= pData
[nPos
].nRow
+ 1;
547 if ( *pNewPattern
== *pOldPattern
)
549 // keep the original pattern (might be default)
550 // pNewPattern is deleted below
553 else if ( nY1
< nStartRow
|| nY2
> nEndRow
)
555 if (nY1
< nStartRow
) nY1
=nStartRow
;
556 if (nY2
> nEndRow
) nY2
=nEndRow
;
557 SetPatternArea( nY1
, nY2
, pNewPattern
, TRUE
);
558 Search( nStart
, nPos
);
562 // ueberpruefen, ob Attributierung die Textbreite der Zelle aendert
563 // bedingte Formate in Vorlagen gibt es (noch) nicht
565 const SfxItemSet
& rNewSet
= pNewPattern
->GetItemSet();
566 const SfxItemSet
& rOldSet
= pOldPattern
->GetItemSet();
568 BOOL bNumFormatChanged
;
569 if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged
,
572 aAdrStart
.SetRow( nPos
? pData
[nPos
-1].nRow
+1 : 0 );
573 aAdrEnd
.SetRow( pData
[nPos
].nRow
);
574 pDocument
->InvalidateTextWidth( &aAdrStart
, &aAdrEnd
, bNumFormatChanged
);
575 #ifdef DBG_INVALIDATE
576 DBGOUTPUT("ApplyStyleArea");
580 pDocument
->GetPool()->Remove(*pData
[nPos
].pPattern
);
581 pData
[nPos
].pPattern
= (const ScPatternAttr
*)
582 &pDocument
->GetPool()->Put(*pNewPattern
);
584 Search(nStart
, nPos
);
590 while ((nStart
<= nEndRow
) && (nPos
< nCount
));
592 if (pDocument
->IsStreamValid(nTab
))
593 pDocument
->SetStreamValid(nTab
, FALSE
);
602 // const wird weggecastet, weil es sonst
603 // zu ineffizient/kompliziert wird!
604 #define SET_LINECOLOR(dest,c) \
607 ((SvxBorderLine*)(dest))->SetColor((c)); \
610 #define SET_LINE(dest,src) \
613 SvxBorderLine* pCast = (SvxBorderLine*)(dest); \
614 pCast->SetOutWidth((src)->GetOutWidth()); \
615 pCast->SetInWidth ((src)->GetInWidth()); \
616 pCast->SetDistance((src)->GetDistance()); \
619 void ScAttrArray::ApplyLineStyleArea( SCROW nStartRow
, SCROW nEndRow
,
620 const SvxBorderLine
* pLine
, BOOL bColorOnly
)
622 if ( bColorOnly
&& !pLine
)
625 if (ValidRow(nStartRow
) && ValidRow(nEndRow
))
629 if (!Search( nStartRow
, nPos
))
631 DBG_ERROR("Search-Fehler");
637 const ScPatternAttr
* pOldPattern
= pData
[nPos
].pPattern
;
638 const SfxItemSet
& rOldSet
= pOldPattern
->GetItemSet();
639 const SfxPoolItem
* pBoxItem
= 0;
640 SfxItemState eState
= rOldSet
.GetItemState( ATTR_BORDER
, TRUE
, &pBoxItem
);
641 const SfxPoolItem
* pTLBRItem
= 0;
642 SfxItemState eTLBRState
= rOldSet
.GetItemState( ATTR_BORDER_TLBR
, TRUE
, &pTLBRItem
);
643 const SfxPoolItem
* pBLTRItem
= 0;
644 SfxItemState eBLTRState
= rOldSet
.GetItemState( ATTR_BORDER_BLTR
, TRUE
, &pBLTRItem
);
646 if ( (SFX_ITEM_SET
== eState
) || (SFX_ITEM_SET
== eTLBRState
) || (SFX_ITEM_SET
== eBLTRState
) )
648 ScPatternAttr
* pNewPattern
= new ScPatternAttr(*pOldPattern
);
649 SfxItemSet
& rNewSet
= pNewPattern
->GetItemSet();
651 SCROW nY2
= pData
[nPos
].nRow
;
653 SvxBoxItem
* pNewBoxItem
= pBoxItem
? (SvxBoxItem
*)pBoxItem
->Clone() : 0;
654 SvxLineItem
* pNewTLBRItem
= pTLBRItem
? (SvxLineItem
*)pTLBRItem
->Clone() : 0;
655 SvxLineItem
* pNewBLTRItem
= pBLTRItem
? (SvxLineItem
*)pBLTRItem
->Clone() : 0;
657 // Linienattribute holen und mit Parametern aktualisieren
663 if ( pNewBoxItem
->GetTop() ) pNewBoxItem
->SetLine( NULL
, BOX_LINE_TOP
);
664 if ( pNewBoxItem
->GetBottom() ) pNewBoxItem
->SetLine( NULL
, BOX_LINE_BOTTOM
);
665 if ( pNewBoxItem
->GetLeft() ) pNewBoxItem
->SetLine( NULL
, BOX_LINE_LEFT
);
666 if ( pNewBoxItem
->GetRight() ) pNewBoxItem
->SetLine( NULL
, BOX_LINE_RIGHT
);
668 if( pNewTLBRItem
&& pNewTLBRItem
->GetLine() )
669 pNewTLBRItem
->SetLine( 0 );
670 if( pNewBLTRItem
&& pNewBLTRItem
->GetLine() )
671 pNewBLTRItem
->SetLine( 0 );
677 Color
aColor( pLine
->GetColor() );
680 SET_LINECOLOR( pNewBoxItem
->GetTop(), aColor
);
681 SET_LINECOLOR( pNewBoxItem
->GetBottom(), aColor
);
682 SET_LINECOLOR( pNewBoxItem
->GetLeft(), aColor
);
683 SET_LINECOLOR( pNewBoxItem
->GetRight(), aColor
);
686 SET_LINECOLOR( pNewTLBRItem
->GetLine(), aColor
);
688 SET_LINECOLOR( pNewBLTRItem
->GetLine(), aColor
);
694 SET_LINE( pNewBoxItem
->GetTop(), pLine
);
695 SET_LINE( pNewBoxItem
->GetBottom(), pLine
);
696 SET_LINE( pNewBoxItem
->GetLeft(), pLine
);
697 SET_LINE( pNewBoxItem
->GetRight(), pLine
);
700 SET_LINE( pNewTLBRItem
->GetLine(), pLine
);
702 SET_LINE( pNewBLTRItem
->GetLine(), pLine
);
705 if( pNewBoxItem
) rNewSet
.Put( *pNewBoxItem
);
706 if( pNewTLBRItem
) rNewSet
.Put( *pNewTLBRItem
);
707 if( pNewBLTRItem
) rNewSet
.Put( *pNewBLTRItem
);
709 nStart
= pData
[nPos
].nRow
+ 1;
711 if ( nY1
< nStartRow
|| nY2
> nEndRow
)
713 if (nY1
< nStartRow
) nY1
=nStartRow
;
714 if (nY2
> nEndRow
) nY2
=nEndRow
;
715 SetPatternArea( nY1
, nY2
, pNewPattern
, TRUE
);
716 Search( nStart
, nPos
);
720 //! aus Pool loeschen?
721 pDocument
->GetPool()->Remove(*pData
[nPos
].pPattern
);
722 pData
[nPos
].pPattern
= (const ScPatternAttr
*)
723 &pDocument
->GetPool()->Put(*pNewPattern
);
726 Search(nStart
, nPos
);
737 nStart
= pData
[nPos
].nRow
+ 1;
741 while ((nStart
<= nEndRow
) && (nPos
< nCount
));
749 void ScAttrArray::ApplyCacheArea( SCROW nStartRow
, SCROW nEndRow
, SfxItemPoolCache
* pCache
, ScEditDataArray
* pDataArray
)
755 if (ValidRow(nStartRow
) && ValidRow(nEndRow
))
759 if (!Search( nStartRow
, nPos
))
761 DBG_ERROR("Search-Fehler");
765 ScAddress
aAdrStart( nCol
, 0, nTab
);
766 ScAddress
aAdrEnd ( nCol
, 0, nTab
);
770 const ScPatternAttr
* pOldPattern
= pData
[nPos
].pPattern
;
771 const ScPatternAttr
* pNewPattern
= (const ScPatternAttr
*) &pCache
->ApplyTo( *pOldPattern
, TRUE
);
772 ScDocumentPool::CheckRef( *pOldPattern
);
773 ScDocumentPool::CheckRef( *pNewPattern
);
774 if (pNewPattern
!= pOldPattern
)
777 SCROW nY2
= pData
[nPos
].nRow
;
778 nStart
= pData
[nPos
].nRow
+ 1;
780 if ( nY1
< nStartRow
|| nY2
> nEndRow
)
782 if (nY1
< nStartRow
) nY1
=nStartRow
;
783 if (nY2
> nEndRow
) nY2
=nEndRow
;
784 SetPatternArea( nY1
, nY2
, pNewPattern
, false, pDataArray
);
785 Search( nStart
, nPos
);
789 // ueberpruefen, ob Attributierung die Textbreite der Zelle aendert
791 const SfxItemSet
& rNewSet
= pNewPattern
->GetItemSet();
792 const SfxItemSet
& rOldSet
= pOldPattern
->GetItemSet();
794 BOOL bNumFormatChanged
;
795 if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged
,
798 aAdrStart
.SetRow( nPos
? pData
[nPos
-1].nRow
+1 : 0 );
799 aAdrEnd
.SetRow( pData
[nPos
].nRow
);
800 pDocument
->InvalidateTextWidth( &aAdrStart
, &aAdrEnd
, bNumFormatChanged
);
801 #ifdef DBG_INVALIDATE
802 DBGOUTPUT("ApplyCacheArea");
806 // bedingte Formate neu gesetzt oder geloescht ?
808 if ( &rNewSet
.Get(ATTR_CONDITIONAL
) != &rOldSet
.Get(ATTR_CONDITIONAL
) )
810 pDocument
->ConditionalChanged( ((const SfxUInt32Item
&)
811 rOldSet
.Get(ATTR_CONDITIONAL
)).GetValue() );
812 pDocument
->ConditionalChanged( ((const SfxUInt32Item
&)
813 rNewSet
.Get(ATTR_CONDITIONAL
)).GetValue() );
816 pDocument
->GetPool()->Remove(*pData
[nPos
].pPattern
);
817 pData
[nPos
].pPattern
= pNewPattern
;
819 Search(nStart
, nPos
);
826 //!!!!!!!!!!!!!!!!!! mit diesem Remove gibt es Abstuerze (Calc1 Import)
827 //! pDocument->GetPool()->Remove(*pNewPattern);
828 nStart
= pData
[nPos
].nRow
+ 1;
832 while (nStart
<= nEndRow
);
834 if (pDocument
->IsStreamValid(nTab
))
835 pDocument
->SetStreamValid(nTab
, FALSE
);
844 void lcl_MergeDeep( SfxItemSet
& rMergeSet
, const SfxItemSet
& rSource
)
846 const SfxPoolItem
* pNewItem
;
847 const SfxPoolItem
* pOldItem
;
848 for (USHORT nId
=ATTR_PATTERN_START
; nId
<=ATTR_PATTERN_END
; nId
++)
850 // pMergeSet hat keinen Parent
851 SfxItemState eOldState
= rMergeSet
.GetItemState( nId
, FALSE
, &pOldItem
);
853 if ( eOldState
== SFX_ITEM_DEFAULT
) // Default
855 SfxItemState eNewState
= rSource
.GetItemState( nId
, TRUE
, &pNewItem
);
856 if ( eNewState
== SFX_ITEM_SET
)
858 if ( *pNewItem
!= rMergeSet
.GetPool()->GetDefaultItem(nId
) )
859 rMergeSet
.InvalidateItem( nId
);
862 else if ( eOldState
== SFX_ITEM_SET
) // Item gesetzt
864 SfxItemState eNewState
= rSource
.GetItemState( nId
, TRUE
, &pNewItem
);
865 if ( eNewState
== SFX_ITEM_SET
)
867 if ( pNewItem
!= pOldItem
) // beide gepuhlt
868 rMergeSet
.InvalidateItem( nId
);
872 if ( *pOldItem
!= rSource
.GetPool()->GetDefaultItem(nId
) )
873 rMergeSet
.InvalidateItem( nId
);
876 // Dontcare bleibt Dontcare
881 void ScAttrArray::MergePatternArea( SCROW nStartRow
, SCROW nEndRow
,
882 ScMergePatternState
& rState
, BOOL bDeep
) const
884 if (ValidRow(nStartRow
) && ValidRow(nEndRow
))
888 if (!Search( nStartRow
, nPos
))
890 DBG_ERROR("Search-Fehler");
896 // gleiche Patterns muessen nicht mehrfach angesehen werden
898 const ScPatternAttr
* pPattern
= pData
[nPos
].pPattern
;
899 if ( pPattern
!= rState
.pOld1
&& pPattern
!= rState
.pOld2
)
901 const SfxItemSet
& rThisSet
= pPattern
->GetItemSet();
904 // (*ppSet)->MergeValues( rThisSet, FALSE );
905 // geht nicht, weil die Vorlagen nicht beruecksichtigt werden
908 lcl_MergeDeep( *rState
.pItemSet
, rThisSet
);
910 rState
.pItemSet
->MergeValues( rThisSet
, FALSE
);
914 // erstes Pattern - in Set ohne Parent kopieren
915 rState
.pItemSet
= new SfxItemSet( *rThisSet
.GetPool(), rThisSet
.GetRanges() );
916 rState
.pItemSet
->Set( rThisSet
, bDeep
);
919 rState
.pOld2
= rState
.pOld1
;
920 rState
.pOld1
= pPattern
;
923 nStart
= pData
[nPos
].nRow
+ 1;
926 while (nStart
<= nEndRow
);
932 // Umrandung zusammenbauen
934 BOOL
lcl_TestAttr( const SvxBorderLine
* pOldLine
, const SvxBorderLine
* pNewLine
,
935 BYTE
& rModified
, const SvxBorderLine
*& rpNew
)
937 if (rModified
== SC_LINE_DONTCARE
)
938 return FALSE
; // weiter geht's nicht
940 if (rModified
== SC_LINE_EMPTY
)
942 rModified
= SC_LINE_SET
;
944 return TRUE
; // zum ersten mal gesetzt
947 if (pOldLine
== pNewLine
)
953 if (pOldLine
&& pNewLine
)
954 if (*pOldLine
== *pNewLine
)
960 rModified
= SC_LINE_DONTCARE
;
962 return TRUE
; // andere Linie -> dontcare
966 void lcl_MergeToFrame( SvxBoxItem
* pLineOuter
, SvxBoxInfoItem
* pLineInner
,
967 ScLineFlags
& rFlags
, const ScPatternAttr
* pPattern
,
968 BOOL bLeft
, SCCOL nDistRight
, BOOL bTop
, SCROW nDistBottom
)
970 // rechten/unteren Rahmen setzen, wenn Zelle bis zum Ende zusammengefasst:
971 const ScMergeAttr
& rMerge
= (const ScMergeAttr
&)pPattern
->GetItem(ATTR_MERGE
);
972 if ( rMerge
.GetColMerge() == nDistRight
+ 1 )
974 if ( rMerge
.GetRowMerge() == nDistBottom
+ 1 )
977 const SvxBoxItem
* pCellFrame
= (SvxBoxItem
*) &pPattern
->GetItemSet().Get( ATTR_BORDER
);
978 const SvxBorderLine
* pLeftAttr
= pCellFrame
->GetLeft();
979 const SvxBorderLine
* pRightAttr
= pCellFrame
->GetRight();
980 const SvxBorderLine
* pTopAttr
= pCellFrame
->GetTop();
981 const SvxBorderLine
* pBottomAttr
= pCellFrame
->GetBottom();
982 const SvxBorderLine
* pNew
;
986 if (lcl_TestAttr( pLineOuter
->GetTop(), pTopAttr
, rFlags
.nTop
, pNew
))
987 pLineOuter
->SetLine( pNew
, BOX_LINE_TOP
);
991 if (lcl_TestAttr( pLineInner
->GetHori(), pTopAttr
, rFlags
.nHori
, pNew
))
992 pLineInner
->SetLine( pNew
, BOXINFO_LINE_HORI
);
995 if (nDistBottom
== 0)
997 if (lcl_TestAttr( pLineOuter
->GetBottom(), pBottomAttr
, rFlags
.nBottom
, pNew
))
998 pLineOuter
->SetLine( pNew
, BOX_LINE_BOTTOM
);
1002 if (lcl_TestAttr( pLineInner
->GetHori(), pBottomAttr
, rFlags
.nHori
, pNew
))
1003 pLineInner
->SetLine( pNew
, BOXINFO_LINE_HORI
);
1008 if (lcl_TestAttr( pLineOuter
->GetLeft(), pLeftAttr
, rFlags
.nLeft
, pNew
))
1009 pLineOuter
->SetLine( pNew
, BOX_LINE_LEFT
);
1013 if (lcl_TestAttr( pLineInner
->GetVert(), pLeftAttr
, rFlags
.nVert
, pNew
))
1014 pLineInner
->SetLine( pNew
, BOXINFO_LINE_VERT
);
1017 if (nDistRight
== 0)
1019 if (lcl_TestAttr( pLineOuter
->GetRight(), pRightAttr
, rFlags
.nRight
, pNew
))
1020 pLineOuter
->SetLine( pNew
, BOX_LINE_RIGHT
);
1024 if (lcl_TestAttr( pLineInner
->GetVert(), pRightAttr
, rFlags
.nVert
, pNew
))
1025 pLineInner
->SetLine( pNew
, BOXINFO_LINE_VERT
);
1030 void ScAttrArray::MergeBlockFrame( SvxBoxItem
* pLineOuter
, SvxBoxInfoItem
* pLineInner
,
1031 ScLineFlags
& rFlags
,
1032 SCROW nStartRow
, SCROW nEndRow
, BOOL bLeft
, SCCOL nDistRight
) const
1034 const ScPatternAttr
* pPattern
;
1036 if (nStartRow
== nEndRow
)
1038 pPattern
= GetPattern( nStartRow
);
1039 lcl_MergeToFrame( pLineOuter
, pLineInner
, rFlags
, pPattern
, bLeft
, nDistRight
, TRUE
, 0 );
1043 pPattern
= GetPattern( nStartRow
);
1044 lcl_MergeToFrame( pLineOuter
, pLineInner
, rFlags
, pPattern
, bLeft
, nDistRight
, TRUE
,
1045 nEndRow
-nStartRow
);
1049 Search( nStartRow
+1, nStartIndex
);
1050 Search( nEndRow
-1, nEndIndex
);
1051 for (SCSIZE i
=nStartIndex
; i
<=nEndIndex
; i
++)
1053 pPattern
= (ScPatternAttr
*) pData
[i
].pPattern
;
1054 lcl_MergeToFrame( pLineOuter
, pLineInner
, rFlags
, pPattern
, bLeft
, nDistRight
, FALSE
,
1055 nEndRow
- Min( pData
[i
].nRow
, (SCROW
)(nEndRow
-1) ) );
1056 // nDistBottom hier immer > 0
1059 pPattern
= GetPattern( nEndRow
);
1060 lcl_MergeToFrame( pLineOuter
, pLineInner
, rFlags
, pPattern
, bLeft
, nDistRight
, FALSE
, 0 );
1068 // ApplyFrame - auf einen Eintrag im Array
1071 BOOL
ScAttrArray::ApplyFrame( const SvxBoxItem
* pBoxItem
,
1072 const SvxBoxInfoItem
* pBoxInfoItem
,
1073 SCROW nStartRow
, SCROW nEndRow
,
1074 BOOL bLeft
, SCCOL nDistRight
, BOOL bTop
, SCROW nDistBottom
)
1076 DBG_ASSERT( pBoxItem
&& pBoxInfoItem
, "Linienattribute fehlen!" );
1078 const ScPatternAttr
* pPattern
= GetPattern( nStartRow
);
1079 const SvxBoxItem
* pOldFrame
= (const SvxBoxItem
*)
1080 &pPattern
->GetItemSet().Get( ATTR_BORDER
);
1082 // rechten/unteren Rahmen setzen, wenn Zelle bis zum Ende zusammengefasst:
1083 const ScMergeAttr
& rMerge
= (const ScMergeAttr
&)pPattern
->GetItem(ATTR_MERGE
);
1084 if ( rMerge
.GetColMerge() == nDistRight
+ 1 )
1086 if ( rMerge
.GetRowMerge() == nDistBottom
+ 1 )
1089 SvxBoxItem
aNewFrame( *pOldFrame
);
1091 if ( bLeft
? pBoxInfoItem
->IsValid(VALID_LEFT
) : pBoxInfoItem
->IsValid(VALID_VERT
) )
1092 aNewFrame
.SetLine( bLeft
? pBoxItem
->GetLeft() : pBoxInfoItem
->GetVert(),
1094 if ( (nDistRight
==0) ? pBoxInfoItem
->IsValid(VALID_RIGHT
) : pBoxInfoItem
->IsValid(VALID_VERT
) )
1095 aNewFrame
.SetLine( (nDistRight
==0) ? pBoxItem
->GetRight() : pBoxInfoItem
->GetVert(),
1097 if ( bTop
? pBoxInfoItem
->IsValid(VALID_TOP
) : pBoxInfoItem
->IsValid(VALID_HORI
) )
1098 aNewFrame
.SetLine( bTop
? pBoxItem
->GetTop() : pBoxInfoItem
->GetHori(),
1100 if ( (nDistBottom
==0) ? pBoxInfoItem
->IsValid(VALID_BOTTOM
) : pBoxInfoItem
->IsValid(VALID_HORI
) )
1101 aNewFrame
.SetLine( (nDistBottom
==0) ? pBoxItem
->GetBottom() : pBoxInfoItem
->GetHori(),
1104 if (aNewFrame
== *pOldFrame
)
1111 SfxItemPoolCache
aCache( pDocument
->GetPool(), &aNewFrame
);
1112 ApplyCacheArea( nStartRow
, nEndRow
, &aCache
);
1114 /* ScPatternAttr* pNewPattern = (ScPatternAttr*) pPattern->Clone();
1115 pNewPattern->GetItemSet().Put( aNewFrame );
1116 SetPatternArea( nStartRow, nEndRow, pNewPattern, TRUE );
1123 void ScAttrArray::ApplyBlockFrame( const SvxBoxItem
* pLineOuter
, const SvxBoxInfoItem
* pLineInner
,
1124 SCROW nStartRow
, SCROW nEndRow
, BOOL bLeft
, SCCOL nDistRight
)
1126 if (nStartRow
== nEndRow
)
1127 ApplyFrame( pLineOuter
, pLineInner
, nStartRow
, nEndRow
, bLeft
, nDistRight
, TRUE
, 0 );
1130 ApplyFrame( pLineOuter
, pLineInner
, nStartRow
, nStartRow
, bLeft
, nDistRight
,
1131 TRUE
, nEndRow
-nStartRow
);
1133 if ( nEndRow
> nStartRow
+1 ) // innerer Teil vorhanden?
1137 Search( nStartRow
+1, nStartIndex
);
1138 Search( nEndRow
-1, nEndIndex
);
1139 SCROW nTmpStart
= nStartRow
+1;
1141 for (SCSIZE i
=nStartIndex
; i
<=nEndIndex
;)
1143 nTmpEnd
= Min( (SCROW
)(nEndRow
-1), (SCROW
)(pData
[i
].nRow
) );
1144 BOOL bChanged
= ApplyFrame( pLineOuter
, pLineInner
, nTmpStart
, nTmpEnd
,
1145 bLeft
, nDistRight
, FALSE
, nEndRow
-nTmpEnd
);
1146 nTmpStart
= nTmpEnd
+1;
1149 Search(nTmpStart
, i
);
1150 Search(nEndRow
-1, nEndIndex
);
1157 ApplyFrame( pLineOuter
, pLineInner
, nEndRow
, nEndRow
, bLeft
, nDistRight
, FALSE
, 0 );
1162 long lcl_LineSize( const SvxBorderLine
& rLine
)
1164 // nur eine Linie -> halbe Breite, min. 20
1165 // doppelte Linie -> halber Abstand + eine Linie (je min. 20)
1168 USHORT nWidth
= Max( rLine
.GetOutWidth(), rLine
.GetInWidth() );
1169 USHORT nDist
= rLine
.GetDistance();
1172 DBG_ASSERT( rLine
.GetOutWidth() && rLine
.GetInWidth(),
1173 "Linie hat Abstand, aber nur eine Breite ???" );
1175 // nTotal += ( nDist > 40 ) ? ( nDist / 2 ) : 20;
1176 nTotal
+= ( nDist
> 20 ) ? nDist
: 20;
1177 nTotal
+= ( nWidth
> 20 ) ? nWidth
: 20;
1180 // nTotal += ( nWidth > 40 ) ? ( nWidth / 2 ) : 20;
1181 nTotal
+= ( nWidth
> 20 ) ? nWidth
: 20;
1183 //! auch halbieren ???
1189 BOOL
ScAttrArray::HasLines( SCROW nRow1
, SCROW nRow2
, Rectangle
& rSizes
,
1190 BOOL bLeft
, BOOL bRight
) const
1194 Search( nRow1
, nStartIndex
);
1195 Search( nRow2
, nEndIndex
);
1196 BOOL bFound
= FALSE
;
1198 const SvxBoxItem
* pItem
= 0;
1199 const SvxBorderLine
* pLine
= 0;
1204 pItem
= (const SvxBoxItem
*) &pData
[nStartIndex
].pPattern
->GetItem(ATTR_BORDER
);
1205 pLine
= pItem
->GetTop();
1208 nCmp
= lcl_LineSize(*pLine
);
1209 if ( nCmp
> rSizes
.Top() )
1210 rSizes
.Top() = nCmp
;
1216 if ( nEndIndex
!= nStartIndex
)
1217 pItem
= (const SvxBoxItem
*) &pData
[nEndIndex
].pPattern
->GetItem(ATTR_BORDER
);
1218 pLine
= pItem
->GetBottom();
1221 nCmp
= lcl_LineSize(*pLine
);
1222 if ( nCmp
> rSizes
.Bottom() )
1223 rSizes
.Bottom() = nCmp
;
1227 if ( bLeft
|| bRight
)
1228 for ( SCSIZE i
=nStartIndex
; i
<=nEndIndex
; i
++)
1230 pItem
= (const SvxBoxItem
*) &pData
[i
].pPattern
->GetItem(ATTR_BORDER
);
1236 pLine
= pItem
->GetLeft();
1239 nCmp
= lcl_LineSize(*pLine
);
1240 if ( nCmp
> rSizes
.Left() )
1241 rSizes
.Left() = nCmp
;
1250 pLine
= pItem
->GetRight();
1253 nCmp
= lcl_LineSize(*pLine
);
1254 if ( nCmp
> rSizes
.Right() )
1255 rSizes
.Right() = nCmp
;
1264 // Testen, ob Bereich bestimmtes Attribut enthaelt
1266 BOOL
ScAttrArray::HasAttrib( SCROW nRow1
, SCROW nRow2
, USHORT nMask
) const
1270 Search( nRow1
, nStartIndex
);
1271 Search( nRow2
, nEndIndex
);
1272 BOOL bFound
= FALSE
;
1274 for (SCSIZE i
=nStartIndex
; i
<=nEndIndex
&& !bFound
; i
++)
1276 const ScPatternAttr
* pPattern
= pData
[i
].pPattern
;
1277 if ( nMask
& HASATTR_MERGED
)
1279 const ScMergeAttr
* pMerge
=
1280 (const ScMergeAttr
*) &pPattern
->GetItem( ATTR_MERGE
);
1281 if ( pMerge
->GetColMerge() > 1 || pMerge
->GetRowMerge() > 1 )
1284 if ( nMask
& ( HASATTR_OVERLAPPED
| HASATTR_NOTOVERLAPPED
| HASATTR_AUTOFILTER
) )
1286 const ScMergeFlagAttr
* pMergeFlag
=
1287 (const ScMergeFlagAttr
*) &pPattern
->GetItem( ATTR_MERGE_FLAG
);
1288 if ( (nMask
& HASATTR_OVERLAPPED
) && pMergeFlag
->IsOverlapped() )
1290 if ( (nMask
& HASATTR_NOTOVERLAPPED
) && !pMergeFlag
->IsOverlapped() )
1292 if ( (nMask
& HASATTR_AUTOFILTER
) && pMergeFlag
->HasAutoFilter() )
1295 if ( nMask
& HASATTR_LINES
)
1297 const SvxBoxItem
* pBox
=
1298 (const SvxBoxItem
*) &pPattern
->GetItem( ATTR_BORDER
);
1299 if ( pBox
->GetLeft() || pBox
->GetRight() || pBox
->GetTop() || pBox
->GetBottom() )
1302 if ( nMask
& HASATTR_SHADOW
)
1304 const SvxShadowItem
* pShadow
=
1305 (const SvxShadowItem
*) &pPattern
->GetItem( ATTR_SHADOW
);
1306 if ( pShadow
->GetLocation() != SVX_SHADOW_NONE
)
1309 if ( nMask
& HASATTR_CONDITIONAL
)
1311 const SfxUInt32Item
* pConditional
=
1312 (const SfxUInt32Item
*) &pPattern
->GetItem( ATTR_CONDITIONAL
);
1313 if ( pConditional
->GetValue() != 0 )
1316 if ( nMask
& HASATTR_PROTECTED
)
1318 const ScProtectionAttr
* pProtect
=
1319 (const ScProtectionAttr
*) &pPattern
->GetItem( ATTR_PROTECTION
);
1320 if ( pProtect
->GetProtection() || pProtect
->GetHideCell() )
1323 if ( nMask
& HASATTR_ROTATE
)
1325 const SfxInt32Item
* pRotate
=
1326 (const SfxInt32Item
*) &pPattern
->GetItem( ATTR_ROTATE_VALUE
);
1327 // 90 or 270 degrees is former SvxOrientationItem - only look for other values
1328 // (see ScPatternAttr::GetCellOrientation)
1329 INT32 nAngle
= pRotate
->GetValue();
1330 if ( nAngle
!= 0 && nAngle
!= 9000 && nAngle
!= 27000 )
1333 if ( nMask
& HASATTR_NEEDHEIGHT
)
1335 if (pPattern
->GetCellOrientation() != SVX_ORIENTATION_STANDARD
)
1337 else if (((const SfxBoolItem
&)pPattern
->GetItem( ATTR_LINEBREAK
)).GetValue())
1339 else if ((SvxCellHorJustify
)((const SvxHorJustifyItem
&)pPattern
->
1340 GetItem( ATTR_HOR_JUSTIFY
)).GetValue() == SVX_HOR_JUSTIFY_BLOCK
)
1342 else if (((const SfxUInt32Item
&)pPattern
->GetItem( ATTR_CONDITIONAL
)).GetValue())
1344 else if (((const SfxInt32Item
&)pPattern
->GetItem( ATTR_ROTATE_VALUE
)).GetValue())
1347 if ( nMask
& ( HASATTR_SHADOW_RIGHT
| HASATTR_SHADOW_DOWN
) )
1349 const SvxShadowItem
* pShadow
=
1350 (const SvxShadowItem
*) &pPattern
->GetItem( ATTR_SHADOW
);
1351 SvxShadowLocation eLoc
= pShadow
->GetLocation();
1352 if ( nMask
& HASATTR_SHADOW_RIGHT
)
1353 if ( eLoc
== SVX_SHADOW_TOPRIGHT
|| eLoc
== SVX_SHADOW_BOTTOMRIGHT
)
1355 if ( nMask
& HASATTR_SHADOW_DOWN
)
1356 if ( eLoc
== SVX_SHADOW_BOTTOMLEFT
|| eLoc
== SVX_SHADOW_BOTTOMRIGHT
)
1359 if ( nMask
& HASATTR_RTL
)
1361 const SvxFrameDirectionItem
& rDirection
=
1362 (const SvxFrameDirectionItem
&) pPattern
->GetItem( ATTR_WRITINGDIR
);
1363 if ( rDirection
.GetValue() == FRMDIR_HORI_RIGHT_TOP
)
1366 if ( nMask
& HASATTR_RIGHTORCENTER
)
1368 // called only if the sheet is LTR, so physical=logical alignment can be assumed
1369 SvxCellHorJustify eHorJust
= (SvxCellHorJustify
)
1370 ((const SvxHorJustifyItem
&) pPattern
->GetItem( ATTR_HOR_JUSTIFY
)).GetValue();
1371 if ( eHorJust
== SVX_HOR_JUSTIFY_RIGHT
|| eHorJust
== SVX_HOR_JUSTIFY_CENTER
)
1379 // Bereich um evtl. enthaltene Zusammenfassungen erweitern
1380 // und evtl. MergeFlag anpassen (bRefresh)
1382 BOOL
ScAttrArray::ExtendMerge( SCCOL nThisCol
, SCROW nStartRow
, SCROW nEndRow
,
1383 SCCOL
& rPaintCol
, SCROW
& rPaintRow
,
1384 BOOL bRefresh
, BOOL bAttrs
)
1386 const ScPatternAttr
* pPattern
;
1387 const ScMergeAttr
* pItem
;
1390 Search( nStartRow
, nStartIndex
);
1391 Search( nEndRow
, nEndIndex
);
1392 BOOL bFound
= FALSE
;
1394 for (SCSIZE i
=nStartIndex
; i
<=nEndIndex
; i
++)
1396 pPattern
= pData
[i
].pPattern
;
1397 pItem
= (const ScMergeAttr
*) &pPattern
->GetItem( ATTR_MERGE
);
1398 SCsCOL nCountX
= pItem
->GetColMerge();
1399 SCsROW nCountY
= pItem
->GetRowMerge();
1400 if (nCountX
>1 || nCountY
>1)
1402 SCROW nThisRow
= (i
>0) ? pData
[i
-1].nRow
+1 : 0;
1403 SCCOL nMergeEndCol
= nThisCol
+ nCountX
- 1;
1404 SCROW nMergeEndRow
= nThisRow
+ nCountY
- 1;
1405 if (nMergeEndCol
> rPaintCol
&& nMergeEndCol
<= MAXCOL
)
1406 rPaintCol
= nMergeEndCol
;
1407 if (nMergeEndRow
> rPaintRow
&& nMergeEndRow
<= MAXROW
)
1408 rPaintRow
= nMergeEndRow
;
1413 const SvxShadowItem
* pShadow
=
1414 (const SvxShadowItem
*) &pPattern
->GetItem( ATTR_SHADOW
);
1415 SvxShadowLocation eLoc
= pShadow
->GetLocation();
1416 if ( eLoc
== SVX_SHADOW_TOPRIGHT
|| eLoc
== SVX_SHADOW_BOTTOMRIGHT
)
1417 if ( nMergeEndCol
+1 > rPaintCol
&& nMergeEndCol
< MAXCOL
)
1418 rPaintCol
= nMergeEndCol
+1;
1419 if ( eLoc
== SVX_SHADOW_BOTTOMLEFT
|| eLoc
== SVX_SHADOW_BOTTOMRIGHT
)
1420 if ( nMergeEndRow
+1 > rPaintRow
&& nMergeEndRow
< MAXROW
)
1421 rPaintRow
= nMergeEndRow
+1;
1426 if ( nMergeEndCol
> nThisCol
)
1427 pDocument
->ApplyFlagsTab( nThisCol
+1, nThisRow
, nMergeEndCol
, pData
[i
].nRow
,
1429 if ( nMergeEndRow
> nThisRow
)
1430 pDocument
->ApplyFlagsTab( nThisCol
, nThisRow
+1, nThisCol
, nMergeEndRow
,
1432 if ( nMergeEndCol
> nThisCol
&& nMergeEndRow
> nThisRow
)
1433 pDocument
->ApplyFlagsTab( nThisCol
+1, nThisRow
+1, nMergeEndCol
, nMergeEndRow
,
1434 nTab
, SC_MF_HOR
| SC_MF_VER
);
1436 Search( nThisRow
, i
); // Daten wurden veraendert
1437 Search( nStartRow
, nStartIndex
);
1438 Search( nEndRow
, nEndIndex
);
1447 BOOL
ScAttrArray::RemoveAreaMerge(SCROW nStartRow
, SCROW nEndRow
)
1449 BOOL bFound
= FALSE
;
1450 const ScPatternAttr
* pPattern
;
1451 const ScMergeAttr
* pItem
;
1454 Search( nStartRow
, nIndex
);
1455 SCROW nThisStart
= (nIndex
>0) ? pData
[nIndex
-1].nRow
+1 : 0;
1456 if (nThisStart
< nStartRow
)
1457 nThisStart
= nStartRow
;
1459 while ( nThisStart
<= nEndRow
)
1461 SCROW nThisEnd
= pData
[nIndex
].nRow
;
1462 if (nThisEnd
> nEndRow
)
1465 pPattern
= pData
[nIndex
].pPattern
;
1466 pItem
= (const ScMergeAttr
*) &pPattern
->GetItem( ATTR_MERGE
);
1467 SCsCOL nCountX
= pItem
->GetColMerge();
1468 SCsROW nCountY
= pItem
->GetRowMerge();
1469 if (nCountX
>1 || nCountY
>1)
1471 const ScMergeAttr
* pAttr
= (const ScMergeAttr
*)
1472 &pDocument
->GetPool()->GetDefaultItem( ATTR_MERGE
);
1473 const ScMergeFlagAttr
* pFlagAttr
= (const ScMergeFlagAttr
*)
1474 &pDocument
->GetPool()->GetDefaultItem( ATTR_MERGE_FLAG
);
1476 DBG_ASSERT( nCountY
==1 || nThisStart
==nThisEnd
, "was'n hier los?" );
1478 SCCOL nThisCol
= nCol
;
1479 SCCOL nMergeEndCol
= nThisCol
+ nCountX
- 1;
1480 SCROW nMergeEndRow
= nThisEnd
+ nCountY
- 1;
1482 //! ApplyAttr fuer Bereiche !!!
1484 for (SCROW nThisRow
= nThisStart
; nThisRow
<= nThisEnd
; nThisRow
++)
1485 pDocument
->ApplyAttr( nThisCol
, nThisRow
, nTab
, *pAttr
);
1487 ScPatternAttr
* pNewPattern
= new ScPatternAttr( pDocument
->GetPool() );
1488 SfxItemSet
* pSet
= &pNewPattern
->GetItemSet();
1489 pSet
->Put( *pFlagAttr
);
1490 pDocument
->ApplyPatternAreaTab( nThisCol
, nThisStart
, nMergeEndCol
, nMergeEndRow
,
1491 nTab
, *pNewPattern
);
1494 Search( nThisEnd
, nIndex
); // Daten wurden veraendert !!!
1498 if ( nIndex
< nCount
)
1499 nThisStart
= pData
[nIndex
-1].nRow
+1;
1501 nThisStart
= MAXROW
+1; // Ende
1507 // Bereich loeschen, aber Merge-Flags stehenlassen
1509 void ScAttrArray::DeleteAreaSafe(SCROW nStartRow
, SCROW nEndRow
)
1511 SetPatternAreaSafe( nStartRow
, nEndRow
, pDocument
->GetDefPattern(), TRUE
);
1515 void ScAttrArray::SetPatternAreaSafe( SCROW nStartRow
, SCROW nEndRow
,
1516 const ScPatternAttr
* pWantedPattern
, BOOL bDefault
)
1518 const ScPatternAttr
* pOldPattern
;
1519 const ScMergeFlagAttr
* pItem
;
1524 BOOL bFirstUse
= TRUE
;
1526 Search( nStartRow
, nIndex
);
1527 nThisRow
= (nIndex
>0) ? pData
[nIndex
-1].nRow
+1 : 0;
1528 while ( nThisRow
<= nEndRow
)
1530 pOldPattern
= pData
[nIndex
].pPattern
;
1531 if (pOldPattern
!= pWantedPattern
) //! else-Zweig ?
1533 if (nThisRow
< nStartRow
) nThisRow
= nStartRow
;
1534 nRow
= pData
[nIndex
].nRow
;
1535 SCROW nAttrRow
= Min( (SCROW
)nRow
, (SCROW
)nEndRow
);
1536 pItem
= (const ScMergeFlagAttr
*) &pOldPattern
->GetItem( ATTR_MERGE_FLAG
);
1538 if (pItem
->IsOverlapped() || pItem
->HasAutoFilter())
1540 // #108045# default-constructing a ScPatternAttr for DeleteArea doesn't work
1541 // because it would have no cell style information.
1542 // Instead, the document's GetDefPattern is copied. Since it is passed as
1543 // pWantedPattern, no special treatment of default is needed here anymore.
1544 ScPatternAttr
* pNewPattern
= new ScPatternAttr( *pWantedPattern
);
1545 SfxItemSet
* pSet
= &pNewPattern
->GetItemSet();
1546 pSet
->Put( *pItem
);
1547 SetPatternArea( nThisRow
, nAttrRow
, pNewPattern
, TRUE
);
1557 pDocument
->GetPool()->Put( *pWantedPattern
); // im Pool ist es schon!
1559 SetPatternArea( nThisRow
, nAttrRow
, pWantedPattern
);
1562 Search( nThisRow
, nIndex
); // Daten wurden veraendert !!!
1566 nThisRow
= pData
[nIndex
-1].nRow
+1;
1571 BOOL
ScAttrArray::ApplyFlags( SCROW nStartRow
, SCROW nEndRow
, INT16 nFlags
)
1573 const ScPatternAttr
* pOldPattern
;
1579 BOOL bChanged
= FALSE
;
1581 Search( nStartRow
, nIndex
);
1582 nThisRow
= (nIndex
>0) ? pData
[nIndex
-1].nRow
+1 : 0;
1583 if (nThisRow
< nStartRow
) nThisRow
= nStartRow
;
1585 while ( nThisRow
<= nEndRow
)
1587 pOldPattern
= pData
[nIndex
].pPattern
;
1588 nOldValue
= ((const ScMergeFlagAttr
*) &pOldPattern
->GetItem( ATTR_MERGE_FLAG
))->GetValue();
1589 if ( (nOldValue
| nFlags
) != nOldValue
)
1591 nRow
= pData
[nIndex
].nRow
;
1592 SCROW nAttrRow
= Min( (SCROW
)nRow
, (SCROW
)nEndRow
);
1593 ScPatternAttr
aNewPattern(*pOldPattern
);
1594 aNewPattern
.GetItemSet().Put( ScMergeFlagAttr( nOldValue
| nFlags
) );
1595 SetPatternArea( nThisRow
, nAttrRow
, &aNewPattern
, TRUE
);
1596 Search( nThisRow
, nIndex
); // Daten wurden veraendert !!!
1601 nThisRow
= pData
[nIndex
-1].nRow
+1;
1608 BOOL
ScAttrArray::RemoveFlags( SCROW nStartRow
, SCROW nEndRow
, INT16 nFlags
)
1610 const ScPatternAttr
* pOldPattern
;
1616 BOOL bChanged
= FALSE
;
1618 Search( nStartRow
, nIndex
);
1619 nThisRow
= (nIndex
>0) ? pData
[nIndex
-1].nRow
+1 : 0;
1620 if (nThisRow
< nStartRow
) nThisRow
= nStartRow
;
1622 while ( nThisRow
<= nEndRow
)
1624 pOldPattern
= pData
[nIndex
].pPattern
;
1625 nOldValue
= ((const ScMergeFlagAttr
*) &pOldPattern
->GetItem( ATTR_MERGE_FLAG
))->GetValue();
1626 if ( (nOldValue
& ~nFlags
) != nOldValue
)
1628 nRow
= pData
[nIndex
].nRow
;
1629 SCROW nAttrRow
= Min( (SCROW
)nRow
, (SCROW
)nEndRow
);
1630 ScPatternAttr
aNewPattern(*pOldPattern
);
1631 aNewPattern
.GetItemSet().Put( ScMergeFlagAttr( nOldValue
& ~nFlags
) );
1632 SetPatternArea( nThisRow
, nAttrRow
, &aNewPattern
, TRUE
);
1633 Search( nThisRow
, nIndex
); // Daten wurden veraendert !!!
1638 nThisRow
= pData
[nIndex
-1].nRow
+1;
1645 void ScAttrArray::ClearItems( SCROW nStartRow
, SCROW nEndRow
, const USHORT
* pWhich
)
1647 const ScPatternAttr
* pOldPattern
;
1653 Search( nStartRow
, nIndex
);
1654 nThisRow
= (nIndex
>0) ? pData
[nIndex
-1].nRow
+1 : 0;
1655 if (nThisRow
< nStartRow
) nThisRow
= nStartRow
;
1657 while ( nThisRow
<= nEndRow
)
1659 pOldPattern
= pData
[nIndex
].pPattern
;
1660 if ( pOldPattern
->HasItemsSet( pWhich
) )
1662 ScPatternAttr
aNewPattern(*pOldPattern
);
1663 aNewPattern
.ClearItems( pWhich
);
1665 nRow
= pData
[nIndex
].nRow
;
1666 SCROW nAttrRow
= Min( (SCROW
)nRow
, (SCROW
)nEndRow
);
1667 SetPatternArea( nThisRow
, nAttrRow
, &aNewPattern
, TRUE
);
1668 Search( nThisRow
, nIndex
); // Daten wurden veraendert !!!
1672 nThisRow
= pData
[nIndex
-1].nRow
+1;
1677 void ScAttrArray::ChangeIndent( SCROW nStartRow
, SCROW nEndRow
, BOOL bIncrement
)
1680 Search( nStartRow
, nIndex
);
1681 SCROW nThisStart
= (nIndex
>0) ? pData
[nIndex
-1].nRow
+1 : 0;
1682 if (nThisStart
< nStartRow
) nThisStart
= nStartRow
;
1684 while ( nThisStart
<= nEndRow
)
1686 const ScPatternAttr
* pOldPattern
= pData
[nIndex
].pPattern
;
1687 const SfxItemSet
& rOldSet
= pOldPattern
->GetItemSet();
1688 const SfxPoolItem
* pItem
;
1690 BOOL bNeedJust
= ( rOldSet
.GetItemState( ATTR_HOR_JUSTIFY
, FALSE
, &pItem
) != SFX_ITEM_SET
1691 || ((const SvxHorJustifyItem
*)pItem
)->GetValue() != SVX_HOR_JUSTIFY_LEFT
);
1692 USHORT nOldValue
= ((const SfxUInt16Item
&)rOldSet
.Get( ATTR_INDENT
)).GetValue();
1693 USHORT nNewValue
= nOldValue
;
1696 if ( nNewValue
< SC_MAX_INDENT
)
1698 nNewValue
+= SC_INDENT_STEP
;
1699 if ( nNewValue
> SC_MAX_INDENT
) nNewValue
= SC_MAX_INDENT
;
1704 if ( nNewValue
> 0 )
1706 if ( nNewValue
> SC_INDENT_STEP
)
1707 nNewValue
-= SC_INDENT_STEP
;
1713 if ( bNeedJust
|| nNewValue
!= nOldValue
)
1715 SCROW nThisEnd
= pData
[nIndex
].nRow
;
1716 SCROW nAttrRow
= Min( nThisEnd
, nEndRow
);
1717 ScPatternAttr
aNewPattern(*pOldPattern
);
1718 aNewPattern
.GetItemSet().Put( SfxUInt16Item( ATTR_INDENT
, nNewValue
) );
1720 aNewPattern
.GetItemSet().Put(
1721 SvxHorJustifyItem( SVX_HOR_JUSTIFY_LEFT
, ATTR_HOR_JUSTIFY
) );
1722 SetPatternArea( nThisStart
, nAttrRow
, &aNewPattern
, TRUE
);
1724 nThisStart
= nThisEnd
+ 1;
1725 Search( nThisStart
, nIndex
); // Daten wurden veraendert !!!
1729 nThisStart
= pData
[nIndex
].nRow
+ 1; // weiterzaehlen...
1736 SCsROW
ScAttrArray::GetNextUnprotected( SCsROW nRow
, BOOL bUp
) const
1742 Search(nRow
, nIndex
);
1743 while (((const ScProtectionAttr
&)pData
[nIndex
].pPattern
->
1744 GetItem(ATTR_PROTECTION
)).GetProtection())
1749 return -1; // nichts gefunden
1751 nRet
= pData
[nIndex
].nRow
;
1755 nRet
= pData
[nIndex
].nRow
+1;
1758 return MAXROW
+1; // nichts gefunden
1765 void ScAttrArray::FindStyleSheet( const SfxStyleSheetBase
* pStyleSheet
, ScFlatBoolRowSegments
& rUsedRows
, bool bReset
)
1769 while (nPos
< nCount
)
1771 SCROW nEnd
= pData
[nPos
].nRow
;
1772 if (pData
[nPos
].pPattern
->GetStyleSheet() == pStyleSheet
)
1774 // for (SCROW nRow = nStart; nRow <= nEnd; nRow++)
1775 // pUsed[nRow] = TRUE;
1777 rUsedRows
.setTrue(nStart
, nEnd
);
1781 ScPatternAttr
* pNewPattern
= new ScPatternAttr(*pData
[nPos
].pPattern
);
1782 pDocument
->GetPool()->Remove(*pData
[nPos
].pPattern
);
1783 pNewPattern
->SetStyleSheet( (ScStyleSheet
*)
1784 pDocument
->GetStyleSheetPool()->
1785 Find( ScGlobal::GetRscString(STR_STYLENAME_STANDARD
),
1786 SFX_STYLE_FAMILY_PARA
,
1787 SFXSTYLEBIT_AUTO
| SCSTYLEBIT_STANDARD
) );
1788 pData
[nPos
].pPattern
= (const ScPatternAttr
*)
1789 &pDocument
->GetPool()->Put(*pNewPattern
);
1794 Search(nStart
, nPos
);
1795 --nPos
; // wegen ++ am Ende
1805 BOOL
ScAttrArray::IsStyleSheetUsed( const ScStyleSheet
& rStyle
,
1806 BOOL bGatherAllStyles
) const
1808 BOOL bIsUsed
= FALSE
;
1811 while ( nPos
< nCount
)
1813 const ScStyleSheet
* pStyle
= pData
[nPos
].pPattern
->GetStyleSheet();
1816 pStyle
->SetUsage( ScStyleSheet::USED
);
1817 if ( pStyle
== &rStyle
)
1819 if ( !bGatherAllStyles
)
1831 BOOL
ScAttrArray::IsEmpty() const
1835 if ( pData
[0].pPattern
!= pDocument
->GetDefPattern() )
1845 //UNUSED2008-05 SCROW ScAttrArray::GetFirstEntryPos() const
1847 //UNUSED2008-05 DBG_ASSERT( nCount, "nCount = 0" );
1849 //UNUSED2008-05 if ( pData[0].pPattern != pDocument->GetDefPattern() )
1850 //UNUSED2008-05 return 0;
1851 //UNUSED2008-05 else
1853 //UNUSED2008-05 if (nCount==1)
1854 //UNUSED2008-05 return 0; // leer
1855 //UNUSED2008-05 else
1856 //UNUSED2008-05 return pData[0].nRow + 1;
1861 //UNUSED2008-05 SCROW ScAttrArray::GetLastEntryPos( BOOL bIncludeBottom ) const
1863 //UNUSED2008-05 DBG_ASSERT( nCount, "nCount == 0" );
1865 //UNUSED2008-05 if (bIncludeBottom)
1866 //UNUSED2008-05 bIncludeBottom = ( pData[nCount-1].pPattern != pDocument->GetDefPattern() );
1868 //UNUSED2008-05 if (bIncludeBottom)
1869 //UNUSED2008-05 return MAXROW;
1870 //UNUSED2008-05 else
1872 //UNUSED2008-05 if (nCount<=1)
1873 //UNUSED2008-05 return 0; // leer
1874 //UNUSED2008-05 else
1875 //UNUSED2008-05 return pData[nCount-2].nRow;
1880 BOOL
ScAttrArray::GetFirstVisibleAttr( SCROW
& rFirstRow
) const
1882 DBG_ASSERT( nCount
, "nCount == 0" );
1884 BOOL bFound
= FALSE
;
1887 // Skip first entry if more than 1 row.
1888 // Entries at the end are not skipped, GetFirstVisibleAttr may be larger than GetLastVisibleAttr.
1890 SCSIZE nVisStart
= 1;
1891 while ( nVisStart
< nCount
&& pData
[nVisStart
].pPattern
->IsVisibleEqual(*pData
[nVisStart
-1].pPattern
) )
1893 if ( nVisStart
>= nCount
|| pData
[nVisStart
-1].nRow
> 0 ) // more than 1 row?
1896 while ( nStart
< nCount
&& !bFound
)
1898 if ( pData
[nStart
].pPattern
->IsVisible() )
1900 rFirstRow
= nStart
? ( pData
[nStart
-1].nRow
+ 1 ) : 0;
1910 // size (rows) of a range of attributes after cell content where the search is stopped
1911 // (more than a default page size, 2*42 because it's as good as any number)
1913 const SCROW SC_VISATTR_STOP
= 84;
1915 BOOL
ScAttrArray::GetLastVisibleAttr( SCROW
& rLastRow
, SCROW nLastData
) const
1917 // #i30830# changed behavior:
1918 // ignore all attributes starting with the first run of SC_VISATTR_STOP equal rows
1919 // below the last content cell
1921 if ( nLastData
== MAXROW
)
1923 rLastRow
= MAXROW
; // can't look for attributes below MAXROW
1927 BOOL bFound
= FALSE
;
1929 // loop backwards from the end instead of using Search, assuming that
1930 // there usually aren't many attributes below the last cell
1932 SCSIZE nPos
= nCount
;
1933 while ( nPos
> 0 && pData
[nPos
-1].nRow
> nLastData
)
1935 SCSIZE nEndPos
= nPos
- 1;
1936 SCSIZE nStartPos
= nEndPos
; // find range of visually equal formats
1937 while ( nStartPos
> 0 &&
1938 pData
[nStartPos
-1].nRow
> nLastData
&&
1939 pData
[nStartPos
-1].pPattern
->IsVisibleEqual(*pData
[nStartPos
].pPattern
) )
1942 SCROW nAttrStartRow
= ( nStartPos
> 0 ) ? ( pData
[nStartPos
-1].nRow
+ 1 ) : 0;
1943 if ( nAttrStartRow
<= nLastData
)
1944 nAttrStartRow
= nLastData
+ 1;
1945 SCROW nAttrSize
= pData
[nEndPos
].nRow
+ 1 - nAttrStartRow
;
1946 if ( nAttrSize
>= SC_VISATTR_STOP
)
1948 bFound
= FALSE
; // ignore this range and below
1950 else if ( !bFound
&& pData
[nEndPos
].pPattern
->IsVisible() )
1952 rLastRow
= pData
[nEndPos
].nRow
;
1956 nPos
= nStartPos
; // look further from the top of the range
1963 BOOL
ScAttrArray::HasVisibleAttrIn( SCROW nStartRow
, SCROW nEndRow
) const
1966 Search( nStartRow
, nIndex
);
1967 SCROW nThisStart
= nStartRow
;
1968 BOOL bFound
= FALSE
;
1969 while ( nIndex
< nCount
&& nThisStart
<= nEndRow
&& !bFound
)
1971 if ( pData
[nIndex
].pPattern
->IsVisible() )
1974 nThisStart
= pData
[nIndex
].nRow
+ 1;
1982 BOOL
ScAttrArray::IsVisibleEqual( const ScAttrArray
& rOther
,
1983 SCROW nStartRow
, SCROW nEndRow
) const
1986 SCSIZE nThisPos
= 0;
1987 SCSIZE nOtherPos
= 0;
1988 if ( nStartRow
> 0 )
1990 Search( nStartRow
, nThisPos
);
1991 rOther
.Search( nStartRow
, nOtherPos
);
1994 while ( nThisPos
<nCount
&& nOtherPos
<rOther
.nCount
&& bEqual
)
1996 SCROW nThisRow
= pData
[nThisPos
].nRow
;
1997 SCROW nOtherRow
= rOther
.pData
[nOtherPos
].nRow
;
1998 const ScPatternAttr
* pThisPattern
= pData
[nThisPos
].pPattern
;
1999 const ScPatternAttr
* pOtherPattern
= rOther
.pData
[nOtherPos
].pPattern
;
2000 bEqual
= ( pThisPattern
== pOtherPattern
||
2001 pThisPattern
->IsVisibleEqual(*pOtherPattern
) );
2003 if ( nThisRow
>= nOtherRow
)
2005 if ( nOtherRow
>= nEndRow
) break;
2008 if ( nThisRow
<= nOtherRow
)
2010 if ( nThisRow
>= nEndRow
) break;
2019 BOOL
ScAttrArray::IsAllEqual( const ScAttrArray
& rOther
, SCROW nStartRow
, SCROW nEndRow
) const
2021 //! mit IsVisibleEqual zusammenfassen?
2024 SCSIZE nThisPos
= 0;
2025 SCSIZE nOtherPos
= 0;
2026 if ( nStartRow
> 0 )
2028 Search( nStartRow
, nThisPos
);
2029 rOther
.Search( nStartRow
, nOtherPos
);
2032 while ( nThisPos
<nCount
&& nOtherPos
<rOther
.nCount
&& bEqual
)
2034 SCROW nThisRow
= pData
[nThisPos
].nRow
;
2035 SCROW nOtherRow
= rOther
.pData
[nOtherPos
].nRow
;
2036 const ScPatternAttr
* pThisPattern
= pData
[nThisPos
].pPattern
;
2037 const ScPatternAttr
* pOtherPattern
= rOther
.pData
[nOtherPos
].pPattern
;
2038 bEqual
= ( pThisPattern
== pOtherPattern
);
2040 if ( nThisRow
>= nOtherRow
)
2042 if ( nOtherRow
>= nEndRow
) break;
2045 if ( nThisRow
<= nOtherRow
)
2047 if ( nThisRow
>= nEndRow
) break;
2056 BOOL
ScAttrArray::TestInsertCol( SCROW nStartRow
, SCROW nEndRow
) const
2058 // horizontal zusammengefasste duerfen nicht herausgeschoben werden
2059 // (ob die ganze Zusammenfassung betroffen ist, ist hier nicht zu erkennen)
2065 if ( nStartRow
> 0 )
2066 Search( nStartRow
, nIndex
);
2068 for ( ; nIndex
< nCount
; nIndex
++ )
2070 if ( ((const ScMergeFlagAttr
&)pData
[nIndex
].pPattern
->
2071 GetItem(ATTR_MERGE_FLAG
)).IsHorOverlapped() )
2073 bTest
= FALSE
; // darf nicht herausgeschoben werden
2076 if ( pData
[nIndex
].nRow
>= nEndRow
) // Ende des Bereichs
2084 BOOL
ScAttrArray::TestInsertRow( SCSIZE nSize
) const
2086 // wenn die erste herausgeschobene Zeile vertikal ueberlappt ist,
2087 // wuerde eine kaputte Zusammenfassung uebrigbleiben
2091 // MAXROW + 1 - nSize = erste herausgeschobene Zeile
2093 SCSIZE nFirstLost
= nCount
-1;
2094 while ( nFirstLost
&& pData
[nFirstLost
-1].nRow
>= sal::static_int_cast
<SCROW
>(MAXROW
+ 1 - nSize
) )
2097 if ( ((const ScMergeFlagAttr
&)pData
[nFirstLost
].pPattern
->
2098 GetItem(ATTR_MERGE_FLAG
)).IsVerOverlapped() )
2106 void ScAttrArray::InsertRow( SCROW nStartRow
, SCSIZE nSize
)
2111 SCROW nSearch
= nStartRow
> 0 ? nStartRow
- 1 : 0; // Vorgaenger erweitern
2113 Search( nSearch
, nIndex
);
2115 // ein gesetztes ScMergeAttr darf nicht ausgedehnt werden
2116 // (darum hinterher wieder loeschen)
2118 BOOL bDoMerge
= ((const ScMergeAttr
&) pData
[nIndex
].pPattern
->GetItem(ATTR_MERGE
)).IsMerged();
2122 for (i
= nIndex
; i
< nCount
-1; i
++)
2124 SCROW nNew
= pData
[i
].nRow
+ nSize
;
2125 if ( nNew
>= MAXROW
) // Ende erreicht ?
2129 nRemove
= i
+1; // folgende loeschen
2131 pData
[i
].nRow
= nNew
;
2134 // muessen Eintraege am Ende geloescht werden?
2136 if (nRemove
&& nRemove
< nCount
)
2137 DeleteRange( nRemove
, nCount
-1 );
2139 if (bDoMerge
) // ausgedehntes ScMergeAttr wieder reparieren
2141 //! ApplyAttr fuer Bereiche !!!
2143 const SfxPoolItem
& rDef
= pDocument
->GetPool()->GetDefaultItem( ATTR_MERGE
);
2144 for (SCSIZE nAdd
=0; nAdd
<nSize
; nAdd
++)
2145 pDocument
->ApplyAttr( nCol
, nStartRow
+nAdd
, nTab
, rDef
);
2147 // im eingefuegten Bereich ist nichts zusammengefasst
2150 // Don't duplicate the merge flags in the inserted row.
2151 RemoveFlags( nStartRow
, nStartRow
+nSize
-1, SC_MF_ALL
);
2155 void ScAttrArray::DeleteRow( SCROW nStartRow
, SCSIZE nSize
)
2160 SCSIZE nStartIndex
= 0;
2161 SCSIZE nEndIndex
= 0;
2164 for ( i
= 0; i
< nCount
-1; i
++)
2165 if (pData
[i
].nRow
>= nStartRow
&& pData
[i
].nRow
<= sal::static_int_cast
<SCROW
>(nStartRow
+nSize
-1))
2180 nStart
= pData
[nStartIndex
-1].nRow
+ 1;
2182 if (nStart
< nStartRow
)
2184 pData
[nStartIndex
].nRow
= nStartRow
- 1;
2187 if (nEndIndex
>= nStartIndex
)
2189 DeleteRange( nStartIndex
, nEndIndex
);
2190 if (nStartIndex
> 0)
2191 if ( pData
[nStartIndex
-1].pPattern
== pData
[nStartIndex
].pPattern
)
2192 DeleteRange( nStartIndex
-1, nStartIndex
-1 );
2195 for (i
= 0; i
< nCount
-1; i
++)
2196 if (pData
[i
].nRow
>= nStartRow
)
2197 pData
[i
].nRow
-= nSize
;
2199 // unten nicht Default-Pattern nachschieben, um Druckbereiche erkennen zu koennen
2200 // stattdessen nur Merge-Flags loeschen
2202 RemoveFlags( MAXROW
-nSize
+1, MAXROW
, SC_MF_HOR
| SC_MF_VER
| SC_MF_AUTO
);
2207 void ScAttrArray::DeleteRange( SCSIZE nStartIndex
, SCSIZE nEndIndex
)
2209 ScDocumentPool
* pDocPool
= pDocument
->GetPool();
2210 for (SCSIZE i
= nStartIndex
; i
<= nEndIndex
; i
++)
2211 pDocPool
->Remove(*pData
[i
].pPattern
);
2213 memmove( &pData
[nStartIndex
], &pData
[nEndIndex
+ 1], (nCount
- nEndIndex
- 1) * sizeof(ScAttrEntry
) );
2214 nCount
-= nEndIndex
-nStartIndex
+1;
2218 void ScAttrArray::DeleteArea(SCROW nStartRow
, SCROW nEndRow
)
2220 RemoveAreaMerge( nStartRow
, nEndRow
); // von zusammengefassten auch die Flags loeschen
2222 if ( !HasAttrib( nStartRow
, nEndRow
, HASATTR_OVERLAPPED
| HASATTR_AUTOFILTER
) )
2223 SetPatternArea( nStartRow
, nEndRow
, pDocument
->GetDefPattern() );
2225 DeleteAreaSafe( nStartRow
, nEndRow
); // Merge-Flags stehenlassen
2229 void ScAttrArray::DeleteHardAttr(SCROW nStartRow
, SCROW nEndRow
)
2231 const ScPatternAttr
* pDefPattern
= pDocument
->GetDefPattern();
2232 const ScPatternAttr
* pOldPattern
;
2238 Search( nStartRow
, nIndex
);
2239 nThisRow
= (nIndex
>0) ? pData
[nIndex
-1].nRow
+1 : 0;
2240 if (nThisRow
< nStartRow
) nThisRow
= nStartRow
;
2242 while ( nThisRow
<= nEndRow
)
2244 pOldPattern
= pData
[nIndex
].pPattern
;
2246 if ( pOldPattern
->GetItemSet().Count() ) // harte Attribute ?
2248 nRow
= pData
[nIndex
].nRow
;
2249 SCROW nAttrRow
= Min( (SCROW
)nRow
, (SCROW
)nEndRow
);
2251 ScPatternAttr
aNewPattern(*pOldPattern
);
2252 SfxItemSet
& rSet
= aNewPattern
.GetItemSet();
2253 for (USHORT nId
= ATTR_PATTERN_START
; nId
<= ATTR_PATTERN_END
; nId
++)
2254 if (nId
!= ATTR_MERGE
&& nId
!= ATTR_MERGE_FLAG
)
2255 rSet
.ClearItem(nId
);
2257 if ( aNewPattern
== *pDefPattern
)
2258 SetPatternArea( nThisRow
, nAttrRow
, pDefPattern
, FALSE
);
2260 SetPatternArea( nThisRow
, nAttrRow
, &aNewPattern
, TRUE
);
2262 Search( nThisRow
, nIndex
); // Daten wurden veraendert !!!
2266 nThisRow
= pData
[nIndex
-1].nRow
+1;
2270 // Verschieben innerhalb eines Dokuments
2272 void ScAttrArray::MoveTo(SCROW nStartRow
, SCROW nEndRow
, ScAttrArray
& rAttrArray
)
2274 SCROW nStart
= nStartRow
;
2275 for (SCSIZE i
= 0; i
< nCount
; i
++)
2277 if ((pData
[i
].nRow
>= nStartRow
) && ((i
==0) ? TRUE
: pData
[i
-1].nRow
< nEndRow
))
2279 // Kopieren (bPutToPool=TRUE)
2280 rAttrArray
.SetPatternArea( nStart
, Min( (SCROW
)pData
[i
].nRow
, (SCROW
)nEndRow
),
2281 pData
[i
].pPattern
, TRUE
);
2283 nStart
= Max( (SCROW
)nStart
, (SCROW
)(pData
[i
].nRow
+ 1) );
2285 DeleteArea(nStartRow
, nEndRow
);
2289 // Kopieren zwischen Dokumenten (Clipboard)
2291 void ScAttrArray::CopyArea( SCROW nStartRow
, SCROW nEndRow
, long nDy
, ScAttrArray
& rAttrArray
,
2294 nStartRow
-= nDy
; // Source
2297 SCROW nDestStart
= Max((long)((long)nStartRow
+ nDy
), (long) 0);
2298 SCROW nDestEnd
= Min((long)((long)nEndRow
+ nDy
), (long) MAXROW
);
2300 ScDocumentPool
* pSourceDocPool
= pDocument
->GetPool();
2301 ScDocumentPool
* pDestDocPool
= rAttrArray
.pDocument
->GetPool();
2302 BOOL bSamePool
= (pSourceDocPool
==pDestDocPool
);
2304 for (SCSIZE i
= 0; (i
< nCount
) && (nDestStart
<= nDestEnd
); i
++)
2306 if (pData
[i
].nRow
>= nStartRow
)
2308 const ScPatternAttr
* pOldPattern
= pData
[i
].pPattern
;
2309 const ScPatternAttr
* pNewPattern
;
2311 if (IsDefaultItem( pOldPattern
))
2313 // am Default muss nichts veraendert werden
2315 pNewPattern
= (const ScPatternAttr
*)
2316 &pDestDocPool
->GetDefaultItem( ATTR_PATTERN
);
2318 else if ( nStripFlags
)
2320 ScPatternAttr
* pTmpPattern
= new ScPatternAttr( *pOldPattern
);
2321 INT16 nNewFlags
= 0;
2322 if ( nStripFlags
!= SC_MF_ALL
)
2323 nNewFlags
= ((const ScMergeFlagAttr
&)pTmpPattern
->GetItem(ATTR_MERGE_FLAG
)).
2324 GetValue() & ~nStripFlags
;
2327 pTmpPattern
->GetItemSet().Put( ScMergeFlagAttr( nNewFlags
) );
2329 pTmpPattern
->GetItemSet().ClearItem( ATTR_MERGE_FLAG
);
2332 pNewPattern
= (ScPatternAttr
*) &pDestDocPool
->Put(*pTmpPattern
);
2334 pNewPattern
= pTmpPattern
->PutInPool( rAttrArray
.pDocument
, pDocument
);
2340 pNewPattern
= (ScPatternAttr
*) &pDestDocPool
->Put(*pOldPattern
);
2342 pNewPattern
= pOldPattern
->PutInPool( rAttrArray
.pDocument
, pDocument
);
2345 rAttrArray
.SetPatternArea(nDestStart
,
2346 Min((SCROW
)(pData
[i
].nRow
+ nDy
), nDestEnd
), pNewPattern
);
2349 // when pasting from clipboard and skipping filtered rows, the adjusted end position
2351 nDestStart
= Max((long)nDestStart
, (long)(pData
[i
].nRow
+ nDy
+ 1));
2355 // Flags stehenlassen
2356 //! mit CopyArea zusammenfassen !!!
2358 void ScAttrArray::CopyAreaSafe( SCROW nStartRow
, SCROW nEndRow
, long nDy
, ScAttrArray
& rAttrArray
)
2360 nStartRow
-= nDy
; // Source
2363 SCROW nDestStart
= Max((long)((long)nStartRow
+ nDy
), (long) 0);
2364 SCROW nDestEnd
= Min((long)((long)nEndRow
+ nDy
), (long) MAXROW
);
2366 if ( !rAttrArray
.HasAttrib( nDestStart
, nDestEnd
, HASATTR_OVERLAPPED
) )
2368 CopyArea( nStartRow
+nDy
, nEndRow
+nDy
, nDy
, rAttrArray
);
2372 ScDocumentPool
* pSourceDocPool
= pDocument
->GetPool();
2373 ScDocumentPool
* pDestDocPool
= rAttrArray
.pDocument
->GetPool();
2374 BOOL bSamePool
= (pSourceDocPool
==pDestDocPool
);
2376 for (SCSIZE i
= 0; (i
< nCount
) && (nDestStart
<= nDestEnd
); i
++)
2378 if (pData
[i
].nRow
>= nStartRow
)
2380 const ScPatternAttr
* pOldPattern
= pData
[i
].pPattern
;
2381 const ScPatternAttr
* pNewPattern
;
2384 pNewPattern
= (ScPatternAttr
*) &pDestDocPool
->Put(*pOldPattern
);
2386 pNewPattern
= pOldPattern
->PutInPool( rAttrArray
.pDocument
, pDocument
);
2388 rAttrArray
.SetPatternAreaSafe(nDestStart
,
2389 Min((SCROW
)(pData
[i
].nRow
+ nDy
), nDestEnd
), pNewPattern
, FALSE
);
2392 // when pasting from clipboard and skipping filtered rows, the adjusted end position
2394 nDestStart
= Max((long)nDestStart
, (long)(pData
[i
].nRow
+ nDy
+ 1));
2399 SCsROW
ScAttrArray::SearchStyle( SCsROW nRow
, const ScStyleSheet
* pSearchStyle
,
2400 BOOL bUp
, ScMarkArray
* pMarkArray
)
2402 BOOL bFound
= FALSE
;
2406 nRow
= pMarkArray
->GetNextMarked( nRow
, bUp
);
2407 if (!VALIDROW(nRow
))
2412 Search(nRow
, nIndex
);
2413 const ScPatternAttr
* pPattern
= pData
[nIndex
].pPattern
;
2415 while (nIndex
< nCount
&& !bFound
)
2417 if (pPattern
->GetStyleSheet() == pSearchStyle
)
2421 nRow
= pMarkArray
->GetNextMarked( nRow
, bUp
);
2422 SCROW nStart
= nIndex
? pData
[nIndex
-1].nRow
+1 : 0;
2423 if (nRow
>= nStart
&& nRow
<= pData
[nIndex
].nRow
)
2442 nRow
= pData
[nIndex
].nRow
;
2443 pPattern
= pData
[nIndex
].pPattern
;
2448 nRow
= pData
[nIndex
].nRow
+1;
2451 pPattern
= pData
[nIndex
].pPattern
;
2456 DBG_ASSERT( bFound
|| !ValidRow(nRow
), "interner Fehler in ScAttrArray::SearchStyle" );
2462 BOOL
ScAttrArray::SearchStyleRange( SCsROW
& rRow
, SCsROW
& rEndRow
,
2463 const ScStyleSheet
* pSearchStyle
, BOOL bUp
, ScMarkArray
* pMarkArray
)
2465 SCsROW nStartRow
= SearchStyle( rRow
, pSearchStyle
, bUp
, pMarkArray
);
2466 if (VALIDROW(nStartRow
))
2469 Search(nStartRow
,nIndex
);
2475 rEndRow
= pData
[nIndex
-1].nRow
+ 1;
2480 SCROW nMarkEnd
= pMarkArray
->GetMarkEnd( nStartRow
, TRUE
);
2481 if (nMarkEnd
>rEndRow
)
2487 rEndRow
= pData
[nIndex
].nRow
;
2490 SCROW nMarkEnd
= pMarkArray
->GetMarkEnd( nStartRow
, FALSE
);
2491 if (nMarkEnd
<rEndRow
)
2502 //------------------------------------------------------------------------
2504 // Laden / Speichern
2509 void ScAttrArray::Save( SvStream
& /* rStream */ ) const
2511 #if SC_ROWLIMIT_STREAM_ACCESS
2512 #error address types changed!
2513 ScWriteHeader
aHdr( rStream
, 8 );
2515 ScDocumentPool
* pDocPool
= pDocument
->GetPool();
2517 USHORT nSaveCount
= nCount
;
2518 SCROW nSaveMaxRow
= pDocument
->GetSrcMaxRow();
2519 if ( nSaveMaxRow
!= MAXROW
)
2521 if ( nSaveCount
> 1 && pData
[nSaveCount
-2].nRow
>= nSaveMaxRow
)
2523 pDocument
->SetLostData(); // Warnung ausgeben
2526 while ( nSaveCount
> 1 && pData
[nSaveCount
-2].nRow
>= nSaveMaxRow
);
2530 rStream
<< nSaveCount
;
2532 const SfxPoolItem
* pItem
;
2533 for (SCSIZE i
=0; i
<nSaveCount
; i
++)
2535 rStream
<< Min( pData
[i
].nRow
, nSaveMaxRow
);
2537 const ScPatternAttr
* pPattern
= pData
[i
].pPattern
;
2538 pDocPool
->StoreSurrogate( rStream
, pPattern
);
2540 // FALSE, weil ATTR_CONDITIONAL (noch) nicht in Vorlagen:
2541 if (pPattern
->GetItemSet().GetItemState(ATTR_CONDITIONAL
,FALSE
,&pItem
) == SFX_ITEM_SET
)
2542 pDocument
->SetConditionalUsed( ((const SfxUInt32Item
*)pItem
)->GetValue() );
2544 if (pPattern
->GetItemSet().GetItemState(ATTR_VALIDDATA
,FALSE
,&pItem
) == SFX_ITEM_SET
)
2545 pDocument
->SetValidationUsed( ((const SfxUInt32Item
*)pItem
)->GetValue() );
2547 #endif // SC_ROWLIMIT_STREAM_ACCESS
2551 void ScAttrArray::Load( SvStream
& /* rStream */ )
2553 #if SC_ROWLIMIT_STREAM_ACCESS
2554 #error address types changed!
2555 ScDocumentPool
* pDocPool
= pDocument
->GetPool();
2557 ScReadHeader
aHdr( rStream
);
2560 rStream
>> nNewCount
;
2561 if ( nNewCount
> MAXROW
+1 ) // wuerde das Array zu gross?
2563 pDocument
->SetLostData();
2564 rStream
.SetError( SVSTREAM_FILEFORMAT_ERROR
);
2568 Reset( pDocument
->GetDefPattern(), FALSE
); // loeschen
2569 pData
= new ScAttrEntry
[nNewCount
]; // neu anlegen
2570 for (SCSIZE i
=0; i
<nNewCount
; i
++)
2572 rStream
>> pData
[i
].nRow
;
2574 USHORT nWhich
= ATTR_PATTERN
;
2575 const ScPatternAttr
* pNewPattern
= (const ScPatternAttr
*)
2576 pDocPool
->LoadSurrogate( rStream
, nWhich
, ATTR_PATTERN
);
2579 // da is was schiefgelaufen
2580 DBG_ERROR("ScAttrArray::Load: Surrogat nicht im Pool");
2581 pNewPattern
= pDocument
->GetDefPattern();
2583 ScDocumentPool::CheckRef( *pNewPattern
);
2584 pData
[i
].pPattern
= pNewPattern
;
2586 // LoadSurrogate erhoeht auch die Ref
2588 nCount
= nLimit
= nNewCount
;
2590 if ( nCount
> 1 && pData
[nCount
-2].nRow
>= MAXROW
) // faengt ein Attribut hinter MAXROW an?
2592 pDocument
->SetLostData();
2593 rStream
.SetError( SVSTREAM_FILEFORMAT_ERROR
);
2597 if ( pDocument
->GetSrcMaxRow() != MAXROW
) // Ende anpassen?
2599 // Ende immer auf MAXROW umsetzen (nur auf 32 Bit)
2601 DBG_ASSERT( pData
[nCount
-1].nRow
== pDocument
->GetSrcMaxRow(), "Attribut-Ende ?!?" );
2602 pData
[nCount
-1].nRow
= MAXROW
;
2604 #endif // SC_ROWLIMIT_STREAM_ACCESS
2609 //UNUSED2008-05 void ScAttrArray::ConvertFontsAfterLoad()
2611 //UNUSED2008-05 ScFontToSubsFontConverter_AutoPtr xFontConverter;
2612 //UNUSED2008-05 const ULONG nFlags = FONTTOSUBSFONT_IMPORT | FONTTOSUBSFONT_ONLYOLDSOSYMBOLFONTS;
2613 //UNUSED2008-05 SCSIZE nIndex = 0;
2614 //UNUSED2008-05 SCROW nThisRow = 0;
2616 //UNUSED2008-05 while ( nThisRow <= MAXROW )
2618 //UNUSED2008-05 const ScPatternAttr* pOldPattern = pData[nIndex].pPattern;
2619 //UNUSED2008-05 const SfxPoolItem* pItem;
2620 //UNUSED2008-05 if( pOldPattern->GetItemSet().GetItemState( ATTR_FONT, FALSE, &pItem ) == SFX_ITEM_SET )
2622 //UNUSED2008-05 const SvxFontItem* pFontItem = (const SvxFontItem*) pItem;
2623 //UNUSED2008-05 const String& rOldName = pFontItem->GetFamilyName();
2624 //UNUSED2008-05 xFontConverter = CreateFontToSubsFontConverter( rOldName, nFlags );
2625 //UNUSED2008-05 if ( xFontConverter )
2627 //UNUSED2008-05 String aNewName( GetFontToSubsFontName( xFontConverter ) );
2628 //UNUSED2008-05 if ( aNewName != rOldName )
2630 //UNUSED2008-05 SCROW nAttrRow = pData[nIndex].nRow;
2631 //UNUSED2008-05 SvxFontItem aNewItem( pFontItem->GetFamily(), aNewName,
2632 //UNUSED2008-05 pFontItem->GetStyleName(), pFontItem->GetPitch(),
2633 //UNUSED2008-05 RTL_TEXTENCODING_DONTKNOW, ATTR_FONT );
2634 //UNUSED2008-05 ScPatternAttr aNewPattern( *pOldPattern );
2635 //UNUSED2008-05 aNewPattern.GetItemSet().Put( aNewItem );
2636 //UNUSED2008-05 SetPatternArea( nThisRow, nAttrRow, &aNewPattern, TRUE );
2637 //UNUSED2008-05 Search( nThisRow, nIndex ); //! data changed
2641 //UNUSED2008-05 ++nIndex;
2642 //UNUSED2008-05 nThisRow = pData[nIndex-1].nRow+1;