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
);
178 pData
= new ScAttrEntry
[1];
181 ScPatternAttr
* pNewPattern
= (ScPatternAttr
*) &pDocPool
->Put(*pPattern
);
182 pData
[0].nRow
= MAXROW
;
183 pData
[0].pPattern
= pNewPattern
;
189 pData
= NULL
; // muss sofort wieder belegt werden !
195 BOOL
ScAttrArray::Concat(SCSIZE nPos
)
198 if (pData
&& (nPos
< nCount
))
202 if (pData
[nPos
- 1].pPattern
== pData
[nPos
].pPattern
)
204 pData
[nPos
- 1].nRow
= pData
[nPos
].nRow
;
205 pDocument
->GetPool()->Remove(*pData
[nPos
].pPattern
);
206 memmove(&pData
[nPos
], &pData
[nPos
+ 1], (nCount
- nPos
- 1) * sizeof(ScAttrEntry
));
207 pData
[nCount
- 1].pPattern
= NULL
;
208 pData
[nCount
- 1].nRow
= 0;
214 if (nPos
+ 1 < nCount
)
216 if (pData
[nPos
+ 1].pPattern
== pData
[nPos
].pPattern
)
218 pData
[nPos
].nRow
= pData
[nPos
+ 1].nRow
;
219 pDocument
->GetPool()->Remove(*pData
[nPos
].pPattern
);
220 memmove(&pData
[nPos
+ 1], &pData
[nPos
+ 2], (nCount
- nPos
- 2) * sizeof(ScAttrEntry
));
221 pData
[nCount
- 1].pPattern
= NULL
;
222 pData
[nCount
- 1].nRow
= 0;
231 //------------------------------------------------------------------------
233 BOOL
ScAttrArray::Search( SCROW nRow
, SCSIZE
& nIndex
) const
236 long nHi
= static_cast<long>(nCount
) - 1;
240 BOOL bFound
= (nCount
== 1);
243 while ( !bFound
&& nLo
<= nHi
)
247 nStartRow
= (long) pData
[i
- 1].nRow
;
250 nEndRow
= (long) pData
[i
].nRow
;
251 if (nEndRow
< (long) nRow
)
254 if (nStartRow
>= (long) nRow
)
271 const ScPatternAttr
* ScAttrArray::GetPattern( SCROW nRow
) const
274 if (Search( nRow
, i
))
275 return pData
[i
].pPattern
;
281 const ScPatternAttr
* ScAttrArray::GetPatternRange( SCROW
& rStartRow
,
282 SCROW
& rEndRow
, SCROW nRow
) const
285 if ( Search( nRow
, nIndex
) )
288 rStartRow
= pData
[nIndex
-1].nRow
+ 1;
291 rEndRow
= pData
[nIndex
].nRow
;
292 return pData
[nIndex
].pPattern
;
297 //------------------------------------------------------------------------
299 void ScAttrArray::SetPattern( SCROW nRow
, const ScPatternAttr
* pPattern
, BOOL bPutToPool
)
301 SetPatternArea( nRow
, nRow
, pPattern
, bPutToPool
);
304 void ScAttrArray::RemoveCellCharAttribs( SCROW nStartRow
, SCROW nEndRow
,
305 const ScPatternAttr
* pPattern
, ScEditDataArray
* pDataArray
)
307 for (SCROW nRow
= nStartRow
; nRow
<= nEndRow
; ++nRow
)
310 pDocument
->GetCell(nCol
, nRow
, nTab
, pCell
);
311 if (pCell
&& pCell
->GetCellType() == CELLTYPE_EDIT
)
313 EditTextObject
* pOldData
= NULL
;
314 ScEditCell
* pEditCell
= static_cast<ScEditCell
*>(pCell
);
316 pOldData
= pEditCell
->GetData()->Clone();
317 pEditCell
->RemoveCharAttribs(*pPattern
);
320 EditTextObject
* pNewData
= pEditCell
->GetData()->Clone();
321 pDataArray
->AddItem(nTab
, nCol
, nRow
, pOldData
, pNewData
);
327 void ScAttrArray::SetPatternArea(SCROW nStartRow
, SCROW nEndRow
, const ScPatternAttr
*pPattern
,
328 BOOL bPutToPool
, ScEditDataArray
* pDataArray
)
330 if (ValidRow(nStartRow
) && ValidRow(nEndRow
))
333 pPattern
= (const ScPatternAttr
*) &pDocument
->GetPool()->Put(*pPattern
);
335 if ((nStartRow
== 0) && (nEndRow
== MAXROW
))
339 SCSIZE nNeeded
= nCount
+ 2;
340 if ( nLimit
< nNeeded
)
342 nLimit
+= SC_ATTRARRAY_DELTA
;
343 if ( nLimit
< nNeeded
)
345 ScAttrEntry
* pNewData
= new ScAttrEntry
[nLimit
];
346 memcpy( pNewData
, pData
, nCount
*sizeof(ScAttrEntry
) );
351 ScAddress
aAdrStart( nCol
, 0, nTab
);
352 ScAddress
aAdrEnd ( nCol
, 0, nTab
);
354 SCSIZE ni
= 0; // number of entries in beginning
355 SCSIZE nx
= 0; // track position
356 SCROW ns
= 0; // start row of track position
361 Search( nStartRow
, nIndex
);
367 ns
= pData
[ni
-1].nRow
+1;
371 // ueberpruefen, ob Attributierung die Textbreite der Zelle aendert
372 // oder bedingte Formate neu gesetzt oder geloescht werden
373 while ( ns
<= nEndRow
)
375 const SfxItemSet
& rNewSet
= pPattern
->GetItemSet();
376 const SfxItemSet
& rOldSet
= pData
[nx
].pPattern
->GetItemSet();
378 BOOL bNumFormatChanged
;
379 if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged
,
382 aAdrStart
.SetRow( Max(nStartRow
,ns
) );
383 aAdrEnd
.SetRow( Min(nEndRow
,pData
[nx
].nRow
) );
384 pDocument
->InvalidateTextWidth( &aAdrStart
, &aAdrEnd
, bNumFormatChanged
);
385 #ifdef DBG_INVALIDATE
386 DBGOUTPUT("SetPatternArea");
389 if ( &rNewSet
.Get(ATTR_CONDITIONAL
) != &rOldSet
.Get(ATTR_CONDITIONAL
) )
391 pDocument
->ConditionalChanged( ((const SfxUInt32Item
&)
392 rOldSet
.Get(ATTR_CONDITIONAL
)).GetValue() );
393 pDocument
->ConditionalChanged( ((const SfxUInt32Item
&)
394 rNewSet
.Get(ATTR_CONDITIONAL
)).GetValue() );
396 ns
= pData
[nx
].nRow
+ 1;
400 // continue modifying data array
402 SCSIZE nInsert
; // insert position (MAXROWCOUNT := no insert)
403 BOOL bCombined
= FALSE
;
407 nInsert
= MAXROWCOUNT
;
408 if ( pData
[ni
].pPattern
!= pPattern
)
410 if ( ni
== 0 || (pData
[ni
-1].nRow
< nStartRow
- 1) )
411 { // may be a split or a simple insert or just a shrink,
412 // row adjustment is done further down
413 if ( pData
[ni
].nRow
> nEndRow
)
418 else if ( ni
> 0 && pData
[ni
-1].nRow
== nStartRow
- 1 )
421 if ( ni
> 0 && pData
[ni
-1].pPattern
== pPattern
)
423 pData
[ni
-1].nRow
= nEndRow
;
424 nInsert
= MAXROWCOUNT
;
431 SCSIZE nj
= ni
; // stop position of range to replace
432 while ( nj
< nCount
&& pData
[nj
].nRow
<= nEndRow
)
436 if ( nj
< nCount
&& pData
[nj
].pPattern
== pPattern
)
440 if ( pData
[ni
-1].pPattern
== pPattern
)
441 { // adjacent entries
442 pData
[ni
-1].nRow
= pData
[nj
].nRow
;
445 else if ( ni
== nInsert
)
446 pData
[ni
-1].nRow
= nStartRow
- 1; // shrink
448 nInsert
= MAXROWCOUNT
;
451 else if ( ni
> 0 && ni
== nInsert
)
452 pData
[ni
-1].nRow
= nStartRow
- 1; // shrink
454 ScDocumentPool
* pDocPool
= pDocument
->GetPool();
456 { // duplicate splitted entry in pool
457 pDocPool
->Put( *pData
[ni
-1].pPattern
);
460 { // remove middle entries
461 for ( SCSIZE nk
=ni
; nk
<nj
; nk
++)
462 { // remove entries from pool
463 pDocPool
->Remove( *pData
[nk
].pPattern
);
466 { // replace one entry
467 pData
[ni
].nRow
= nEndRow
;
468 pData
[ni
].pPattern
= pPattern
;
470 nInsert
= MAXROWCOUNT
;
474 memmove( pData
+ ni
, pData
+ nj
, (nCount
- nj
) * sizeof(ScAttrEntry
) );
479 if ( nInsert
< sal::static_int_cast
<SCSIZE
>(MAXROWCOUNT
) )
480 { // insert or append new entry
481 if ( nInsert
<= nCount
)
484 memmove( pData
+ nInsert
+ 1, pData
+ nInsert
,
485 (nCount
- nInsert
) * sizeof(ScAttrEntry
) );
488 memmove( pData
+ nInsert
+ 2, pData
+ nInsert
,
489 (nCount
- nInsert
) * sizeof(ScAttrEntry
) );
490 pData
[nInsert
+1] = pData
[nInsert
-1];
495 pData
[nInsert
-1].nRow
= nStartRow
- 1;
496 pData
[nInsert
].nRow
= nEndRow
;
497 pData
[nInsert
].pPattern
= pPattern
;
499 // Remove character attributes from these cells if the pattern
500 // is applied during normal session. We don't want to do this
501 // while importing document.
502 if (!pDocument
->IsLoadingMedium())
503 RemoveCellCharAttribs(nStartRow
, nEndRow
, pPattern
,pDataArray
);
509 // InfoBox(0, String(nCount) + String(" Eintraege") ).Execute();
517 void ScAttrArray::ApplyStyleArea( SCROW nStartRow
, SCROW nEndRow
, ScStyleSheet
* pStyle
)
519 if (ValidRow(nStartRow
) && ValidRow(nEndRow
))
523 if (!Search( nStartRow
, nPos
))
525 DBG_ERROR("Search-Fehler");
529 ScAddress
aAdrStart( nCol
, 0, nTab
);
530 ScAddress
aAdrEnd ( nCol
, 0, nTab
);
534 const ScPatternAttr
* pOldPattern
= pData
[nPos
].pPattern
;
535 ScPatternAttr
* pNewPattern
= new ScPatternAttr(*pOldPattern
);
536 pNewPattern
->SetStyleSheet(pStyle
);
538 SCROW nY2
= pData
[nPos
].nRow
;
539 nStart
= pData
[nPos
].nRow
+ 1;
541 if ( *pNewPattern
== *pOldPattern
)
543 // keep the original pattern (might be default)
544 // pNewPattern is deleted below
547 else if ( nY1
< nStartRow
|| nY2
> nEndRow
)
549 if (nY1
< nStartRow
) nY1
=nStartRow
;
550 if (nY2
> nEndRow
) nY2
=nEndRow
;
551 SetPatternArea( nY1
, nY2
, pNewPattern
, TRUE
);
552 Search( nStart
, nPos
);
556 // ueberpruefen, ob Attributierung die Textbreite der Zelle aendert
557 // bedingte Formate in Vorlagen gibt es (noch) nicht
559 const SfxItemSet
& rNewSet
= pNewPattern
->GetItemSet();
560 const SfxItemSet
& rOldSet
= pOldPattern
->GetItemSet();
562 BOOL bNumFormatChanged
;
563 if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged
,
566 aAdrStart
.SetRow( nPos
? pData
[nPos
-1].nRow
+1 : 0 );
567 aAdrEnd
.SetRow( pData
[nPos
].nRow
);
568 pDocument
->InvalidateTextWidth( &aAdrStart
, &aAdrEnd
, bNumFormatChanged
);
569 #ifdef DBG_INVALIDATE
570 DBGOUTPUT("ApplyStyleArea");
574 pDocument
->GetPool()->Remove(*pData
[nPos
].pPattern
);
575 pData
[nPos
].pPattern
= (const ScPatternAttr
*)
576 &pDocument
->GetPool()->Put(*pNewPattern
);
578 Search(nStart
, nPos
);
584 while ((nStart
<= nEndRow
) && (nPos
< nCount
));
593 // const wird weggecastet, weil es sonst
594 // zu ineffizient/kompliziert wird!
595 #define SET_LINECOLOR(dest,c) \
598 ((SvxBorderLine*)(dest))->SetColor((c)); \
601 #define SET_LINE(dest,src) \
604 SvxBorderLine* pCast = (SvxBorderLine*)(dest); \
605 pCast->SetOutWidth((src)->GetOutWidth()); \
606 pCast->SetInWidth ((src)->GetInWidth()); \
607 pCast->SetDistance((src)->GetDistance()); \
610 void ScAttrArray::ApplyLineStyleArea( SCROW nStartRow
, SCROW nEndRow
,
611 const SvxBorderLine
* pLine
, BOOL bColorOnly
)
613 if ( bColorOnly
&& !pLine
)
616 if (ValidRow(nStartRow
) && ValidRow(nEndRow
))
620 if (!Search( nStartRow
, nPos
))
622 DBG_ERROR("Search-Fehler");
628 const ScPatternAttr
* pOldPattern
= pData
[nPos
].pPattern
;
629 const SfxItemSet
& rOldSet
= pOldPattern
->GetItemSet();
630 const SfxPoolItem
* pBoxItem
= 0;
631 SfxItemState eState
= rOldSet
.GetItemState( ATTR_BORDER
, TRUE
, &pBoxItem
);
632 const SfxPoolItem
* pTLBRItem
= 0;
633 SfxItemState eTLBRState
= rOldSet
.GetItemState( ATTR_BORDER_TLBR
, TRUE
, &pTLBRItem
);
634 const SfxPoolItem
* pBLTRItem
= 0;
635 SfxItemState eBLTRState
= rOldSet
.GetItemState( ATTR_BORDER_BLTR
, TRUE
, &pBLTRItem
);
637 if ( (SFX_ITEM_SET
== eState
) || (SFX_ITEM_SET
== eTLBRState
) || (SFX_ITEM_SET
== eBLTRState
) )
639 ScPatternAttr
* pNewPattern
= new ScPatternAttr(*pOldPattern
);
640 SfxItemSet
& rNewSet
= pNewPattern
->GetItemSet();
642 SCROW nY2
= pData
[nPos
].nRow
;
644 SvxBoxItem
* pNewBoxItem
= pBoxItem
? (SvxBoxItem
*)pBoxItem
->Clone() : 0;
645 SvxLineItem
* pNewTLBRItem
= pTLBRItem
? (SvxLineItem
*)pTLBRItem
->Clone() : 0;
646 SvxLineItem
* pNewBLTRItem
= pBLTRItem
? (SvxLineItem
*)pBLTRItem
->Clone() : 0;
648 // Linienattribute holen und mit Parametern aktualisieren
654 if ( pNewBoxItem
->GetTop() ) pNewBoxItem
->SetLine( NULL
, BOX_LINE_TOP
);
655 if ( pNewBoxItem
->GetBottom() ) pNewBoxItem
->SetLine( NULL
, BOX_LINE_BOTTOM
);
656 if ( pNewBoxItem
->GetLeft() ) pNewBoxItem
->SetLine( NULL
, BOX_LINE_LEFT
);
657 if ( pNewBoxItem
->GetRight() ) pNewBoxItem
->SetLine( NULL
, BOX_LINE_RIGHT
);
659 if( pNewTLBRItem
&& pNewTLBRItem
->GetLine() )
660 pNewTLBRItem
->SetLine( 0 );
661 if( pNewBLTRItem
&& pNewBLTRItem
->GetLine() )
662 pNewBLTRItem
->SetLine( 0 );
668 Color
aColor( pLine
->GetColor() );
671 SET_LINECOLOR( pNewBoxItem
->GetTop(), aColor
);
672 SET_LINECOLOR( pNewBoxItem
->GetBottom(), aColor
);
673 SET_LINECOLOR( pNewBoxItem
->GetLeft(), aColor
);
674 SET_LINECOLOR( pNewBoxItem
->GetRight(), aColor
);
677 SET_LINECOLOR( pNewTLBRItem
->GetLine(), aColor
);
679 SET_LINECOLOR( pNewBLTRItem
->GetLine(), aColor
);
685 SET_LINE( pNewBoxItem
->GetTop(), pLine
);
686 SET_LINE( pNewBoxItem
->GetBottom(), pLine
);
687 SET_LINE( pNewBoxItem
->GetLeft(), pLine
);
688 SET_LINE( pNewBoxItem
->GetRight(), pLine
);
691 SET_LINE( pNewTLBRItem
->GetLine(), pLine
);
693 SET_LINE( pNewBLTRItem
->GetLine(), pLine
);
696 if( pNewBoxItem
) rNewSet
.Put( *pNewBoxItem
);
697 if( pNewTLBRItem
) rNewSet
.Put( *pNewTLBRItem
);
698 if( pNewBLTRItem
) rNewSet
.Put( *pNewBLTRItem
);
700 nStart
= pData
[nPos
].nRow
+ 1;
702 if ( nY1
< nStartRow
|| nY2
> nEndRow
)
704 if (nY1
< nStartRow
) nY1
=nStartRow
;
705 if (nY2
> nEndRow
) nY2
=nEndRow
;
706 SetPatternArea( nY1
, nY2
, pNewPattern
, TRUE
);
707 Search( nStart
, nPos
);
711 //! aus Pool loeschen?
712 pDocument
->GetPool()->Remove(*pData
[nPos
].pPattern
);
713 pData
[nPos
].pPattern
= (const ScPatternAttr
*)
714 &pDocument
->GetPool()->Put(*pNewPattern
);
717 Search(nStart
, nPos
);
728 nStart
= pData
[nPos
].nRow
+ 1;
732 while ((nStart
<= nEndRow
) && (nPos
< nCount
));
740 void ScAttrArray::ApplyCacheArea( SCROW nStartRow
, SCROW nEndRow
, SfxItemPoolCache
* pCache
, ScEditDataArray
* pDataArray
)
746 if (ValidRow(nStartRow
) && ValidRow(nEndRow
))
750 if (!Search( nStartRow
, nPos
))
752 DBG_ERROR("Search-Fehler");
756 ScAddress
aAdrStart( nCol
, 0, nTab
);
757 ScAddress
aAdrEnd ( nCol
, 0, nTab
);
761 const ScPatternAttr
* pOldPattern
= pData
[nPos
].pPattern
;
762 const ScPatternAttr
* pNewPattern
= (const ScPatternAttr
*) &pCache
->ApplyTo( *pOldPattern
, TRUE
);
763 ScDocumentPool::CheckRef( *pOldPattern
);
764 ScDocumentPool::CheckRef( *pNewPattern
);
765 if (pNewPattern
!= pOldPattern
)
768 SCROW nY2
= pData
[nPos
].nRow
;
769 nStart
= pData
[nPos
].nRow
+ 1;
771 if ( nY1
< nStartRow
|| nY2
> nEndRow
)
773 if (nY1
< nStartRow
) nY1
=nStartRow
;
774 if (nY2
> nEndRow
) nY2
=nEndRow
;
775 SetPatternArea( nY1
, nY2
, pNewPattern
, false, pDataArray
);
776 Search( nStart
, nPos
);
780 // ueberpruefen, ob Attributierung die Textbreite der Zelle aendert
782 const SfxItemSet
& rNewSet
= pNewPattern
->GetItemSet();
783 const SfxItemSet
& rOldSet
= pOldPattern
->GetItemSet();
785 BOOL bNumFormatChanged
;
786 if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged
,
789 aAdrStart
.SetRow( nPos
? pData
[nPos
-1].nRow
+1 : 0 );
790 aAdrEnd
.SetRow( pData
[nPos
].nRow
);
791 pDocument
->InvalidateTextWidth( &aAdrStart
, &aAdrEnd
, bNumFormatChanged
);
792 #ifdef DBG_INVALIDATE
793 DBGOUTPUT("ApplyCacheArea");
797 // bedingte Formate neu gesetzt oder geloescht ?
799 if ( &rNewSet
.Get(ATTR_CONDITIONAL
) != &rOldSet
.Get(ATTR_CONDITIONAL
) )
801 pDocument
->ConditionalChanged( ((const SfxUInt32Item
&)
802 rOldSet
.Get(ATTR_CONDITIONAL
)).GetValue() );
803 pDocument
->ConditionalChanged( ((const SfxUInt32Item
&)
804 rNewSet
.Get(ATTR_CONDITIONAL
)).GetValue() );
807 pDocument
->GetPool()->Remove(*pData
[nPos
].pPattern
);
808 pData
[nPos
].pPattern
= pNewPattern
;
810 Search(nStart
, nPos
);
817 //!!!!!!!!!!!!!!!!!! mit diesem Remove gibt es Abstuerze (Calc1 Import)
818 //! pDocument->GetPool()->Remove(*pNewPattern);
819 nStart
= pData
[nPos
].nRow
+ 1;
823 while (nStart
<= nEndRow
);
832 void lcl_MergeDeep( SfxItemSet
& rMergeSet
, const SfxItemSet
& rSource
)
834 const SfxPoolItem
* pNewItem
;
835 const SfxPoolItem
* pOldItem
;
836 for (USHORT nId
=ATTR_PATTERN_START
; nId
<=ATTR_PATTERN_END
; nId
++)
838 // pMergeSet hat keinen Parent
839 SfxItemState eOldState
= rMergeSet
.GetItemState( nId
, FALSE
, &pOldItem
);
841 if ( eOldState
== SFX_ITEM_DEFAULT
) // Default
843 SfxItemState eNewState
= rSource
.GetItemState( nId
, TRUE
, &pNewItem
);
844 if ( eNewState
== SFX_ITEM_SET
)
846 if ( *pNewItem
!= rMergeSet
.GetPool()->GetDefaultItem(nId
) )
847 rMergeSet
.InvalidateItem( nId
);
850 else if ( eOldState
== SFX_ITEM_SET
) // Item gesetzt
852 SfxItemState eNewState
= rSource
.GetItemState( nId
, TRUE
, &pNewItem
);
853 if ( eNewState
== SFX_ITEM_SET
)
855 if ( pNewItem
!= pOldItem
) // beide gepuhlt
856 rMergeSet
.InvalidateItem( nId
);
860 if ( *pOldItem
!= rSource
.GetPool()->GetDefaultItem(nId
) )
861 rMergeSet
.InvalidateItem( nId
);
864 // Dontcare bleibt Dontcare
869 void ScAttrArray::MergePatternArea( SCROW nStartRow
, SCROW nEndRow
,
870 ScMergePatternState
& rState
, BOOL bDeep
) const
872 if (ValidRow(nStartRow
) && ValidRow(nEndRow
))
876 if (!Search( nStartRow
, nPos
))
878 DBG_ERROR("Search-Fehler");
884 // gleiche Patterns muessen nicht mehrfach angesehen werden
886 const ScPatternAttr
* pPattern
= pData
[nPos
].pPattern
;
887 if ( pPattern
!= rState
.pOld1
&& pPattern
!= rState
.pOld2
)
889 const SfxItemSet
& rThisSet
= pPattern
->GetItemSet();
892 // (*ppSet)->MergeValues( rThisSet, FALSE );
893 // geht nicht, weil die Vorlagen nicht beruecksichtigt werden
896 lcl_MergeDeep( *rState
.pItemSet
, rThisSet
);
898 rState
.pItemSet
->MergeValues( rThisSet
, FALSE
);
902 // erstes Pattern - in Set ohne Parent kopieren
903 rState
.pItemSet
= new SfxItemSet( *rThisSet
.GetPool(), rThisSet
.GetRanges() );
904 rState
.pItemSet
->Set( rThisSet
, bDeep
);
907 rState
.pOld2
= rState
.pOld1
;
908 rState
.pOld1
= pPattern
;
911 nStart
= pData
[nPos
].nRow
+ 1;
914 while (nStart
<= nEndRow
);
920 // Umrandung zusammenbauen
922 BOOL
lcl_TestAttr( const SvxBorderLine
* pOldLine
, const SvxBorderLine
* pNewLine
,
923 BYTE
& rModified
, const SvxBorderLine
*& rpNew
)
925 if (rModified
== SC_LINE_DONTCARE
)
926 return FALSE
; // weiter geht's nicht
928 if (rModified
== SC_LINE_EMPTY
)
930 rModified
= SC_LINE_SET
;
932 return TRUE
; // zum ersten mal gesetzt
935 if (pOldLine
== pNewLine
)
941 if (pOldLine
&& pNewLine
)
942 if (*pOldLine
== *pNewLine
)
948 rModified
= SC_LINE_DONTCARE
;
950 return TRUE
; // andere Linie -> dontcare
954 void lcl_MergeToFrame( SvxBoxItem
* pLineOuter
, SvxBoxInfoItem
* pLineInner
,
955 ScLineFlags
& rFlags
, const ScPatternAttr
* pPattern
,
956 BOOL bLeft
, SCCOL nDistRight
, BOOL bTop
, SCROW nDistBottom
)
958 // rechten/unteren Rahmen setzen, wenn Zelle bis zum Ende zusammengefasst:
959 const ScMergeAttr
& rMerge
= (const ScMergeAttr
&)pPattern
->GetItem(ATTR_MERGE
);
960 if ( rMerge
.GetColMerge() == nDistRight
+ 1 )
962 if ( rMerge
.GetRowMerge() == nDistBottom
+ 1 )
965 const SvxBoxItem
* pCellFrame
= (SvxBoxItem
*) &pPattern
->GetItemSet().Get( ATTR_BORDER
);
966 const SvxBorderLine
* pLeftAttr
= pCellFrame
->GetLeft();
967 const SvxBorderLine
* pRightAttr
= pCellFrame
->GetRight();
968 const SvxBorderLine
* pTopAttr
= pCellFrame
->GetTop();
969 const SvxBorderLine
* pBottomAttr
= pCellFrame
->GetBottom();
970 const SvxBorderLine
* pNew
;
974 if (lcl_TestAttr( pLineOuter
->GetTop(), pTopAttr
, rFlags
.nTop
, pNew
))
975 pLineOuter
->SetLine( pNew
, BOX_LINE_TOP
);
979 if (lcl_TestAttr( pLineInner
->GetHori(), pTopAttr
, rFlags
.nHori
, pNew
))
980 pLineInner
->SetLine( pNew
, BOXINFO_LINE_HORI
);
983 if (nDistBottom
== 0)
985 if (lcl_TestAttr( pLineOuter
->GetBottom(), pBottomAttr
, rFlags
.nBottom
, pNew
))
986 pLineOuter
->SetLine( pNew
, BOX_LINE_BOTTOM
);
990 if (lcl_TestAttr( pLineInner
->GetHori(), pBottomAttr
, rFlags
.nHori
, pNew
))
991 pLineInner
->SetLine( pNew
, BOXINFO_LINE_HORI
);
996 if (lcl_TestAttr( pLineOuter
->GetLeft(), pLeftAttr
, rFlags
.nLeft
, pNew
))
997 pLineOuter
->SetLine( pNew
, BOX_LINE_LEFT
);
1001 if (lcl_TestAttr( pLineInner
->GetVert(), pLeftAttr
, rFlags
.nVert
, pNew
))
1002 pLineInner
->SetLine( pNew
, BOXINFO_LINE_VERT
);
1005 if (nDistRight
== 0)
1007 if (lcl_TestAttr( pLineOuter
->GetRight(), pRightAttr
, rFlags
.nRight
, pNew
))
1008 pLineOuter
->SetLine( pNew
, BOX_LINE_RIGHT
);
1012 if (lcl_TestAttr( pLineInner
->GetVert(), pRightAttr
, rFlags
.nVert
, pNew
))
1013 pLineInner
->SetLine( pNew
, BOXINFO_LINE_VERT
);
1018 void ScAttrArray::MergeBlockFrame( SvxBoxItem
* pLineOuter
, SvxBoxInfoItem
* pLineInner
,
1019 ScLineFlags
& rFlags
,
1020 SCROW nStartRow
, SCROW nEndRow
, BOOL bLeft
, SCCOL nDistRight
) const
1022 const ScPatternAttr
* pPattern
;
1024 if (nStartRow
== nEndRow
)
1026 pPattern
= GetPattern( nStartRow
);
1027 lcl_MergeToFrame( pLineOuter
, pLineInner
, rFlags
, pPattern
, bLeft
, nDistRight
, TRUE
, 0 );
1031 pPattern
= GetPattern( nStartRow
);
1032 lcl_MergeToFrame( pLineOuter
, pLineInner
, rFlags
, pPattern
, bLeft
, nDistRight
, TRUE
,
1033 nEndRow
-nStartRow
);
1037 Search( nStartRow
+1, nStartIndex
);
1038 Search( nEndRow
-1, nEndIndex
);
1039 for (SCSIZE i
=nStartIndex
; i
<=nEndIndex
; i
++)
1041 pPattern
= (ScPatternAttr
*) pData
[i
].pPattern
;
1042 lcl_MergeToFrame( pLineOuter
, pLineInner
, rFlags
, pPattern
, bLeft
, nDistRight
, FALSE
,
1043 nEndRow
- Min( pData
[i
].nRow
, (SCROW
)(nEndRow
-1) ) );
1044 // nDistBottom hier immer > 0
1047 pPattern
= GetPattern( nEndRow
);
1048 lcl_MergeToFrame( pLineOuter
, pLineInner
, rFlags
, pPattern
, bLeft
, nDistRight
, FALSE
, 0 );
1056 // ApplyFrame - auf einen Eintrag im Array
1059 BOOL
ScAttrArray::ApplyFrame( const SvxBoxItem
* pBoxItem
,
1060 const SvxBoxInfoItem
* pBoxInfoItem
,
1061 SCROW nStartRow
, SCROW nEndRow
,
1062 BOOL bLeft
, SCCOL nDistRight
, BOOL bTop
, SCROW nDistBottom
)
1064 DBG_ASSERT( pBoxItem
&& pBoxInfoItem
, "Linienattribute fehlen!" );
1066 const ScPatternAttr
* pPattern
= GetPattern( nStartRow
);
1067 const SvxBoxItem
* pOldFrame
= (const SvxBoxItem
*)
1068 &pPattern
->GetItemSet().Get( ATTR_BORDER
);
1070 // rechten/unteren Rahmen setzen, wenn Zelle bis zum Ende zusammengefasst:
1071 const ScMergeAttr
& rMerge
= (const ScMergeAttr
&)pPattern
->GetItem(ATTR_MERGE
);
1072 if ( rMerge
.GetColMerge() == nDistRight
+ 1 )
1074 if ( rMerge
.GetRowMerge() == nDistBottom
+ 1 )
1077 SvxBoxItem
aNewFrame( *pOldFrame
);
1079 if ( bLeft
? pBoxInfoItem
->IsValid(VALID_LEFT
) : pBoxInfoItem
->IsValid(VALID_VERT
) )
1080 aNewFrame
.SetLine( bLeft
? pBoxItem
->GetLeft() : pBoxInfoItem
->GetVert(),
1082 if ( (nDistRight
==0) ? pBoxInfoItem
->IsValid(VALID_RIGHT
) : pBoxInfoItem
->IsValid(VALID_VERT
) )
1083 aNewFrame
.SetLine( (nDistRight
==0) ? pBoxItem
->GetRight() : pBoxInfoItem
->GetVert(),
1085 if ( bTop
? pBoxInfoItem
->IsValid(VALID_TOP
) : pBoxInfoItem
->IsValid(VALID_HORI
) )
1086 aNewFrame
.SetLine( bTop
? pBoxItem
->GetTop() : pBoxInfoItem
->GetHori(),
1088 if ( (nDistBottom
==0) ? pBoxInfoItem
->IsValid(VALID_BOTTOM
) : pBoxInfoItem
->IsValid(VALID_HORI
) )
1089 aNewFrame
.SetLine( (nDistBottom
==0) ? pBoxItem
->GetBottom() : pBoxInfoItem
->GetHori(),
1092 if (aNewFrame
== *pOldFrame
)
1099 SfxItemPoolCache
aCache( pDocument
->GetPool(), &aNewFrame
);
1100 ApplyCacheArea( nStartRow
, nEndRow
, &aCache
);
1102 /* ScPatternAttr* pNewPattern = (ScPatternAttr*) pPattern->Clone();
1103 pNewPattern->GetItemSet().Put( aNewFrame );
1104 SetPatternArea( nStartRow, nEndRow, pNewPattern, TRUE );
1111 void ScAttrArray::ApplyBlockFrame( const SvxBoxItem
* pLineOuter
, const SvxBoxInfoItem
* pLineInner
,
1112 SCROW nStartRow
, SCROW nEndRow
, BOOL bLeft
, SCCOL nDistRight
)
1114 if (nStartRow
== nEndRow
)
1115 ApplyFrame( pLineOuter
, pLineInner
, nStartRow
, nEndRow
, bLeft
, nDistRight
, TRUE
, 0 );
1118 ApplyFrame( pLineOuter
, pLineInner
, nStartRow
, nStartRow
, bLeft
, nDistRight
,
1119 TRUE
, nEndRow
-nStartRow
);
1121 if ( nEndRow
> nStartRow
+1 ) // innerer Teil vorhanden?
1125 Search( nStartRow
+1, nStartIndex
);
1126 Search( nEndRow
-1, nEndIndex
);
1127 SCROW nTmpStart
= nStartRow
+1;
1129 for (SCSIZE i
=nStartIndex
; i
<=nEndIndex
;)
1131 nTmpEnd
= Min( (SCROW
)(nEndRow
-1), (SCROW
)(pData
[i
].nRow
) );
1132 BOOL bChanged
= ApplyFrame( pLineOuter
, pLineInner
, nTmpStart
, nTmpEnd
,
1133 bLeft
, nDistRight
, FALSE
, nEndRow
-nTmpEnd
);
1134 nTmpStart
= nTmpEnd
+1;
1137 Search(nTmpStart
, i
);
1138 Search(nEndRow
-1, nEndIndex
);
1145 ApplyFrame( pLineOuter
, pLineInner
, nEndRow
, nEndRow
, bLeft
, nDistRight
, FALSE
, 0 );
1150 long lcl_LineSize( const SvxBorderLine
& rLine
)
1152 // nur eine Linie -> halbe Breite, min. 20
1153 // doppelte Linie -> halber Abstand + eine Linie (je min. 20)
1156 USHORT nWidth
= Max( rLine
.GetOutWidth(), rLine
.GetInWidth() );
1157 USHORT nDist
= rLine
.GetDistance();
1160 DBG_ASSERT( rLine
.GetOutWidth() && rLine
.GetInWidth(),
1161 "Linie hat Abstand, aber nur eine Breite ???" );
1163 // nTotal += ( nDist > 40 ) ? ( nDist / 2 ) : 20;
1164 nTotal
+= ( nDist
> 20 ) ? nDist
: 20;
1165 nTotal
+= ( nWidth
> 20 ) ? nWidth
: 20;
1168 // nTotal += ( nWidth > 40 ) ? ( nWidth / 2 ) : 20;
1169 nTotal
+= ( nWidth
> 20 ) ? nWidth
: 20;
1171 //! auch halbieren ???
1177 BOOL
ScAttrArray::HasLines( SCROW nRow1
, SCROW nRow2
, Rectangle
& rSizes
,
1178 BOOL bLeft
, BOOL bRight
) const
1182 Search( nRow1
, nStartIndex
);
1183 Search( nRow2
, nEndIndex
);
1184 BOOL bFound
= FALSE
;
1186 const SvxBoxItem
* pItem
= 0;
1187 const SvxBorderLine
* pLine
= 0;
1192 pItem
= (const SvxBoxItem
*) &pData
[nStartIndex
].pPattern
->GetItem(ATTR_BORDER
);
1193 pLine
= pItem
->GetTop();
1196 nCmp
= lcl_LineSize(*pLine
);
1197 if ( nCmp
> rSizes
.Top() )
1198 rSizes
.Top() = nCmp
;
1204 if ( nEndIndex
!= nStartIndex
)
1205 pItem
= (const SvxBoxItem
*) &pData
[nEndIndex
].pPattern
->GetItem(ATTR_BORDER
);
1206 pLine
= pItem
->GetBottom();
1209 nCmp
= lcl_LineSize(*pLine
);
1210 if ( nCmp
> rSizes
.Bottom() )
1211 rSizes
.Bottom() = nCmp
;
1215 if ( bLeft
|| bRight
)
1216 for ( SCSIZE i
=nStartIndex
; i
<=nEndIndex
; i
++)
1218 pItem
= (const SvxBoxItem
*) &pData
[i
].pPattern
->GetItem(ATTR_BORDER
);
1224 pLine
= pItem
->GetLeft();
1227 nCmp
= lcl_LineSize(*pLine
);
1228 if ( nCmp
> rSizes
.Left() )
1229 rSizes
.Left() = nCmp
;
1238 pLine
= pItem
->GetRight();
1241 nCmp
= lcl_LineSize(*pLine
);
1242 if ( nCmp
> rSizes
.Right() )
1243 rSizes
.Right() = nCmp
;
1252 // Testen, ob Bereich bestimmtes Attribut enthaelt
1254 BOOL
ScAttrArray::HasAttrib( SCROW nRow1
, SCROW nRow2
, USHORT nMask
) const
1258 Search( nRow1
, nStartIndex
);
1259 Search( nRow2
, nEndIndex
);
1260 BOOL bFound
= FALSE
;
1262 for (SCSIZE i
=nStartIndex
; i
<=nEndIndex
&& !bFound
; i
++)
1264 const ScPatternAttr
* pPattern
= pData
[i
].pPattern
;
1265 if ( nMask
& HASATTR_MERGED
)
1267 const ScMergeAttr
* pMerge
=
1268 (const ScMergeAttr
*) &pPattern
->GetItem( ATTR_MERGE
);
1269 if ( pMerge
->GetColMerge() > 1 || pMerge
->GetRowMerge() > 1 )
1272 if ( nMask
& ( HASATTR_OVERLAPPED
| HASATTR_NOTOVERLAPPED
| HASATTR_AUTOFILTER
) )
1274 const ScMergeFlagAttr
* pMergeFlag
=
1275 (const ScMergeFlagAttr
*) &pPattern
->GetItem( ATTR_MERGE_FLAG
);
1276 if ( (nMask
& HASATTR_OVERLAPPED
) && pMergeFlag
->IsOverlapped() )
1278 if ( (nMask
& HASATTR_NOTOVERLAPPED
) && !pMergeFlag
->IsOverlapped() )
1280 if ( (nMask
& HASATTR_AUTOFILTER
) && pMergeFlag
->HasAutoFilter() )
1283 if ( nMask
& HASATTR_LINES
)
1285 const SvxBoxItem
* pBox
=
1286 (const SvxBoxItem
*) &pPattern
->GetItem( ATTR_BORDER
);
1287 if ( pBox
->GetLeft() || pBox
->GetRight() || pBox
->GetTop() || pBox
->GetBottom() )
1290 if ( nMask
& HASATTR_SHADOW
)
1292 const SvxShadowItem
* pShadow
=
1293 (const SvxShadowItem
*) &pPattern
->GetItem( ATTR_SHADOW
);
1294 if ( pShadow
->GetLocation() != SVX_SHADOW_NONE
)
1297 if ( nMask
& HASATTR_CONDITIONAL
)
1299 const SfxUInt32Item
* pConditional
=
1300 (const SfxUInt32Item
*) &pPattern
->GetItem( ATTR_CONDITIONAL
);
1301 if ( pConditional
->GetValue() != 0 )
1304 if ( nMask
& HASATTR_PROTECTED
)
1306 const ScProtectionAttr
* pProtect
=
1307 (const ScProtectionAttr
*) &pPattern
->GetItem( ATTR_PROTECTION
);
1308 if ( pProtect
->GetProtection() || pProtect
->GetHideCell() )
1311 if ( nMask
& HASATTR_ROTATE
)
1313 const SfxInt32Item
* pRotate
=
1314 (const SfxInt32Item
*) &pPattern
->GetItem( ATTR_ROTATE_VALUE
);
1315 // 90 or 270 degrees is former SvxOrientationItem - only look for other values
1316 // (see ScPatternAttr::GetCellOrientation)
1317 INT32 nAngle
= pRotate
->GetValue();
1318 if ( nAngle
!= 0 && nAngle
!= 9000 && nAngle
!= 27000 )
1321 if ( nMask
& HASATTR_NEEDHEIGHT
)
1323 if (pPattern
->GetCellOrientation() != SVX_ORIENTATION_STANDARD
)
1325 else if (((const SfxBoolItem
&)pPattern
->GetItem( ATTR_LINEBREAK
)).GetValue())
1327 else if ((SvxCellHorJustify
)((const SvxHorJustifyItem
&)pPattern
->
1328 GetItem( ATTR_HOR_JUSTIFY
)).GetValue() == SVX_HOR_JUSTIFY_BLOCK
)
1330 else if (((const SfxUInt32Item
&)pPattern
->GetItem( ATTR_CONDITIONAL
)).GetValue())
1332 else if (((const SfxInt32Item
&)pPattern
->GetItem( ATTR_ROTATE_VALUE
)).GetValue())
1335 if ( nMask
& ( HASATTR_SHADOW_RIGHT
| HASATTR_SHADOW_DOWN
) )
1337 const SvxShadowItem
* pShadow
=
1338 (const SvxShadowItem
*) &pPattern
->GetItem( ATTR_SHADOW
);
1339 SvxShadowLocation eLoc
= pShadow
->GetLocation();
1340 if ( nMask
& HASATTR_SHADOW_RIGHT
)
1341 if ( eLoc
== SVX_SHADOW_TOPRIGHT
|| eLoc
== SVX_SHADOW_BOTTOMRIGHT
)
1343 if ( nMask
& HASATTR_SHADOW_DOWN
)
1344 if ( eLoc
== SVX_SHADOW_BOTTOMLEFT
|| eLoc
== SVX_SHADOW_BOTTOMRIGHT
)
1347 if ( nMask
& HASATTR_RTL
)
1349 const SvxFrameDirectionItem
& rDirection
=
1350 (const SvxFrameDirectionItem
&) pPattern
->GetItem( ATTR_WRITINGDIR
);
1351 if ( rDirection
.GetValue() == FRMDIR_HORI_RIGHT_TOP
)
1354 if ( nMask
& HASATTR_RIGHTORCENTER
)
1356 // called only if the sheet is LTR, so physical=logical alignment can be assumed
1357 SvxCellHorJustify eHorJust
= (SvxCellHorJustify
)
1358 ((const SvxHorJustifyItem
&) pPattern
->GetItem( ATTR_HOR_JUSTIFY
)).GetValue();
1359 if ( eHorJust
== SVX_HOR_JUSTIFY_RIGHT
|| eHorJust
== SVX_HOR_JUSTIFY_CENTER
)
1367 // Bereich um evtl. enthaltene Zusammenfassungen erweitern
1368 // und evtl. MergeFlag anpassen (bRefresh)
1370 BOOL
ScAttrArray::ExtendMerge( SCCOL nThisCol
, SCROW nStartRow
, SCROW nEndRow
,
1371 SCCOL
& rPaintCol
, SCROW
& rPaintRow
,
1372 BOOL bRefresh
, BOOL bAttrs
)
1374 const ScPatternAttr
* pPattern
;
1375 const ScMergeAttr
* pItem
;
1378 Search( nStartRow
, nStartIndex
);
1379 Search( nEndRow
, nEndIndex
);
1380 BOOL bFound
= FALSE
;
1382 for (SCSIZE i
=nStartIndex
; i
<=nEndIndex
; i
++)
1384 pPattern
= pData
[i
].pPattern
;
1385 pItem
= (const ScMergeAttr
*) &pPattern
->GetItem( ATTR_MERGE
);
1386 SCsCOL nCountX
= pItem
->GetColMerge();
1387 SCsROW nCountY
= pItem
->GetRowMerge();
1388 if (nCountX
>1 || nCountY
>1)
1390 SCROW nThisRow
= (i
>0) ? pData
[i
-1].nRow
+1 : 0;
1391 SCCOL nMergeEndCol
= nThisCol
+ nCountX
- 1;
1392 SCROW nMergeEndRow
= nThisRow
+ nCountY
- 1;
1393 if (nMergeEndCol
> rPaintCol
&& nMergeEndCol
<= MAXCOL
)
1394 rPaintCol
= nMergeEndCol
;
1395 if (nMergeEndRow
> rPaintRow
&& nMergeEndRow
<= MAXROW
)
1396 rPaintRow
= nMergeEndRow
;
1401 const SvxShadowItem
* pShadow
=
1402 (const SvxShadowItem
*) &pPattern
->GetItem( ATTR_SHADOW
);
1403 SvxShadowLocation eLoc
= pShadow
->GetLocation();
1404 if ( eLoc
== SVX_SHADOW_TOPRIGHT
|| eLoc
== SVX_SHADOW_BOTTOMRIGHT
)
1405 if ( nMergeEndCol
+1 > rPaintCol
&& nMergeEndCol
< MAXCOL
)
1406 rPaintCol
= nMergeEndCol
+1;
1407 if ( eLoc
== SVX_SHADOW_BOTTOMLEFT
|| eLoc
== SVX_SHADOW_BOTTOMRIGHT
)
1408 if ( nMergeEndRow
+1 > rPaintRow
&& nMergeEndRow
< MAXROW
)
1409 rPaintRow
= nMergeEndRow
+1;
1414 if ( nMergeEndCol
> nThisCol
)
1415 pDocument
->ApplyFlagsTab( nThisCol
+1, nThisRow
, nMergeEndCol
, pData
[i
].nRow
,
1417 if ( nMergeEndRow
> nThisRow
)
1418 pDocument
->ApplyFlagsTab( nThisCol
, nThisRow
+1, nThisCol
, nMergeEndRow
,
1420 if ( nMergeEndCol
> nThisCol
&& nMergeEndRow
> nThisRow
)
1421 pDocument
->ApplyFlagsTab( nThisCol
+1, nThisRow
+1, nMergeEndCol
, nMergeEndRow
,
1422 nTab
, SC_MF_HOR
| SC_MF_VER
);
1424 Search( nThisRow
, i
); // Daten wurden veraendert
1425 Search( nStartRow
, nStartIndex
);
1426 Search( nEndRow
, nEndIndex
);
1435 BOOL
ScAttrArray::RemoveAreaMerge(SCROW nStartRow
, SCROW nEndRow
)
1437 BOOL bFound
= FALSE
;
1438 const ScPatternAttr
* pPattern
;
1439 const ScMergeAttr
* pItem
;
1442 Search( nStartRow
, nIndex
);
1443 SCROW nThisStart
= (nIndex
>0) ? pData
[nIndex
-1].nRow
+1 : 0;
1444 if (nThisStart
< nStartRow
)
1445 nThisStart
= nStartRow
;
1447 while ( nThisStart
<= nEndRow
)
1449 SCROW nThisEnd
= pData
[nIndex
].nRow
;
1450 if (nThisEnd
> nEndRow
)
1453 pPattern
= pData
[nIndex
].pPattern
;
1454 pItem
= (const ScMergeAttr
*) &pPattern
->GetItem( ATTR_MERGE
);
1455 SCsCOL nCountX
= pItem
->GetColMerge();
1456 SCsROW nCountY
= pItem
->GetRowMerge();
1457 if (nCountX
>1 || nCountY
>1)
1459 const ScMergeAttr
* pAttr
= (const ScMergeAttr
*)
1460 &pDocument
->GetPool()->GetDefaultItem( ATTR_MERGE
);
1461 const ScMergeFlagAttr
* pFlagAttr
= (const ScMergeFlagAttr
*)
1462 &pDocument
->GetPool()->GetDefaultItem( ATTR_MERGE_FLAG
);
1464 DBG_ASSERT( nCountY
==1 || nThisStart
==nThisEnd
, "was'n hier los?" );
1466 SCCOL nThisCol
= nCol
;
1467 SCCOL nMergeEndCol
= nThisCol
+ nCountX
- 1;
1468 SCROW nMergeEndRow
= nThisEnd
+ nCountY
- 1;
1470 //! ApplyAttr fuer Bereiche !!!
1472 for (SCROW nThisRow
= nThisStart
; nThisRow
<= nThisEnd
; nThisRow
++)
1473 pDocument
->ApplyAttr( nThisCol
, nThisRow
, nTab
, *pAttr
);
1475 ScPatternAttr
* pNewPattern
= new ScPatternAttr( pDocument
->GetPool() );
1476 SfxItemSet
* pSet
= &pNewPattern
->GetItemSet();
1477 pSet
->Put( *pFlagAttr
);
1478 pDocument
->ApplyPatternAreaTab( nThisCol
, nThisStart
, nMergeEndCol
, nMergeEndRow
,
1479 nTab
, *pNewPattern
);
1482 Search( nThisEnd
, nIndex
); // Daten wurden veraendert !!!
1486 if ( nIndex
< nCount
)
1487 nThisStart
= pData
[nIndex
-1].nRow
+1;
1489 nThisStart
= MAXROW
+1; // Ende
1495 // Bereich loeschen, aber Merge-Flags stehenlassen
1497 void ScAttrArray::DeleteAreaSafe(SCROW nStartRow
, SCROW nEndRow
)
1499 SetPatternAreaSafe( nStartRow
, nEndRow
, pDocument
->GetDefPattern(), TRUE
);
1503 void ScAttrArray::SetPatternAreaSafe( SCROW nStartRow
, SCROW nEndRow
,
1504 const ScPatternAttr
* pWantedPattern
, BOOL bDefault
)
1506 const ScPatternAttr
* pOldPattern
;
1507 const ScMergeFlagAttr
* pItem
;
1512 BOOL bFirstUse
= TRUE
;
1514 Search( nStartRow
, nIndex
);
1515 nThisRow
= (nIndex
>0) ? pData
[nIndex
-1].nRow
+1 : 0;
1516 while ( nThisRow
<= nEndRow
)
1518 pOldPattern
= pData
[nIndex
].pPattern
;
1519 if (pOldPattern
!= pWantedPattern
) //! else-Zweig ?
1521 if (nThisRow
< nStartRow
) nThisRow
= nStartRow
;
1522 nRow
= pData
[nIndex
].nRow
;
1523 SCROW nAttrRow
= Min( (SCROW
)nRow
, (SCROW
)nEndRow
);
1524 pItem
= (const ScMergeFlagAttr
*) &pOldPattern
->GetItem( ATTR_MERGE_FLAG
);
1526 if (pItem
->IsOverlapped() || pItem
->HasAutoFilter())
1528 // #108045# default-constructing a ScPatternAttr for DeleteArea doesn't work
1529 // because it would have no cell style information.
1530 // Instead, the document's GetDefPattern is copied. Since it is passed as
1531 // pWantedPattern, no special treatment of default is needed here anymore.
1532 ScPatternAttr
* pNewPattern
= new ScPatternAttr( *pWantedPattern
);
1533 SfxItemSet
* pSet
= &pNewPattern
->GetItemSet();
1534 pSet
->Put( *pItem
);
1535 SetPatternArea( nThisRow
, nAttrRow
, pNewPattern
, TRUE
);
1545 pDocument
->GetPool()->Put( *pWantedPattern
); // im Pool ist es schon!
1547 SetPatternArea( nThisRow
, nAttrRow
, pWantedPattern
);
1550 Search( nThisRow
, nIndex
); // Daten wurden veraendert !!!
1554 nThisRow
= pData
[nIndex
-1].nRow
+1;
1559 BOOL
ScAttrArray::ApplyFlags( SCROW nStartRow
, SCROW nEndRow
, INT16 nFlags
)
1561 const ScPatternAttr
* pOldPattern
;
1567 BOOL bChanged
= FALSE
;
1569 Search( nStartRow
, nIndex
);
1570 nThisRow
= (nIndex
>0) ? pData
[nIndex
-1].nRow
+1 : 0;
1571 if (nThisRow
< nStartRow
) nThisRow
= nStartRow
;
1573 while ( nThisRow
<= nEndRow
)
1575 pOldPattern
= pData
[nIndex
].pPattern
;
1576 nOldValue
= ((const ScMergeFlagAttr
*) &pOldPattern
->GetItem( ATTR_MERGE_FLAG
))->GetValue();
1577 if ( (nOldValue
| nFlags
) != nOldValue
)
1579 nRow
= pData
[nIndex
].nRow
;
1580 SCROW nAttrRow
= Min( (SCROW
)nRow
, (SCROW
)nEndRow
);
1581 ScPatternAttr
aNewPattern(*pOldPattern
);
1582 aNewPattern
.GetItemSet().Put( ScMergeFlagAttr( nOldValue
| nFlags
) );
1583 SetPatternArea( nThisRow
, nAttrRow
, &aNewPattern
, TRUE
);
1584 Search( nThisRow
, nIndex
); // Daten wurden veraendert !!!
1589 nThisRow
= pData
[nIndex
-1].nRow
+1;
1596 BOOL
ScAttrArray::RemoveFlags( SCROW nStartRow
, SCROW nEndRow
, INT16 nFlags
)
1598 const ScPatternAttr
* pOldPattern
;
1604 BOOL bChanged
= FALSE
;
1606 Search( nStartRow
, nIndex
);
1607 nThisRow
= (nIndex
>0) ? pData
[nIndex
-1].nRow
+1 : 0;
1608 if (nThisRow
< nStartRow
) nThisRow
= nStartRow
;
1610 while ( nThisRow
<= nEndRow
)
1612 pOldPattern
= pData
[nIndex
].pPattern
;
1613 nOldValue
= ((const ScMergeFlagAttr
*) &pOldPattern
->GetItem( ATTR_MERGE_FLAG
))->GetValue();
1614 if ( (nOldValue
& ~nFlags
) != nOldValue
)
1616 nRow
= pData
[nIndex
].nRow
;
1617 SCROW nAttrRow
= Min( (SCROW
)nRow
, (SCROW
)nEndRow
);
1618 ScPatternAttr
aNewPattern(*pOldPattern
);
1619 aNewPattern
.GetItemSet().Put( ScMergeFlagAttr( nOldValue
& ~nFlags
) );
1620 SetPatternArea( nThisRow
, nAttrRow
, &aNewPattern
, TRUE
);
1621 Search( nThisRow
, nIndex
); // Daten wurden veraendert !!!
1626 nThisRow
= pData
[nIndex
-1].nRow
+1;
1633 void ScAttrArray::ClearItems( SCROW nStartRow
, SCROW nEndRow
, const USHORT
* pWhich
)
1635 const ScPatternAttr
* pOldPattern
;
1641 Search( nStartRow
, nIndex
);
1642 nThisRow
= (nIndex
>0) ? pData
[nIndex
-1].nRow
+1 : 0;
1643 if (nThisRow
< nStartRow
) nThisRow
= nStartRow
;
1645 while ( nThisRow
<= nEndRow
)
1647 pOldPattern
= pData
[nIndex
].pPattern
;
1648 if ( pOldPattern
->HasItemsSet( pWhich
) )
1650 ScPatternAttr
aNewPattern(*pOldPattern
);
1651 aNewPattern
.ClearItems( pWhich
);
1653 nRow
= pData
[nIndex
].nRow
;
1654 SCROW nAttrRow
= Min( (SCROW
)nRow
, (SCROW
)nEndRow
);
1655 SetPatternArea( nThisRow
, nAttrRow
, &aNewPattern
, TRUE
);
1656 Search( nThisRow
, nIndex
); // Daten wurden veraendert !!!
1660 nThisRow
= pData
[nIndex
-1].nRow
+1;
1665 void ScAttrArray::ChangeIndent( SCROW nStartRow
, SCROW nEndRow
, BOOL bIncrement
)
1668 Search( nStartRow
, nIndex
);
1669 SCROW nThisStart
= (nIndex
>0) ? pData
[nIndex
-1].nRow
+1 : 0;
1670 if (nThisStart
< nStartRow
) nThisStart
= nStartRow
;
1672 while ( nThisStart
<= nEndRow
)
1674 const ScPatternAttr
* pOldPattern
= pData
[nIndex
].pPattern
;
1675 const SfxItemSet
& rOldSet
= pOldPattern
->GetItemSet();
1676 const SfxPoolItem
* pItem
;
1678 BOOL bNeedJust
= ( rOldSet
.GetItemState( ATTR_HOR_JUSTIFY
, FALSE
, &pItem
) != SFX_ITEM_SET
1679 || ((const SvxHorJustifyItem
*)pItem
)->GetValue() != SVX_HOR_JUSTIFY_LEFT
);
1680 USHORT nOldValue
= ((const SfxUInt16Item
&)rOldSet
.Get( ATTR_INDENT
)).GetValue();
1681 USHORT nNewValue
= nOldValue
;
1684 if ( nNewValue
< SC_MAX_INDENT
)
1686 nNewValue
+= SC_INDENT_STEP
;
1687 if ( nNewValue
> SC_MAX_INDENT
) nNewValue
= SC_MAX_INDENT
;
1692 if ( nNewValue
> 0 )
1694 if ( nNewValue
> SC_INDENT_STEP
)
1695 nNewValue
-= SC_INDENT_STEP
;
1701 if ( bNeedJust
|| nNewValue
!= nOldValue
)
1703 SCROW nThisEnd
= pData
[nIndex
].nRow
;
1704 SCROW nAttrRow
= Min( nThisEnd
, nEndRow
);
1705 ScPatternAttr
aNewPattern(*pOldPattern
);
1706 aNewPattern
.GetItemSet().Put( SfxUInt16Item( ATTR_INDENT
, nNewValue
) );
1708 aNewPattern
.GetItemSet().Put(
1709 SvxHorJustifyItem( SVX_HOR_JUSTIFY_LEFT
, ATTR_HOR_JUSTIFY
) );
1710 SetPatternArea( nThisStart
, nAttrRow
, &aNewPattern
, TRUE
);
1712 nThisStart
= nThisEnd
+ 1;
1713 Search( nThisStart
, nIndex
); // Daten wurden veraendert !!!
1717 nThisStart
= pData
[nIndex
].nRow
+ 1; // weiterzaehlen...
1724 SCsROW
ScAttrArray::GetNextUnprotected( SCsROW nRow
, BOOL bUp
) const
1730 Search(nRow
, nIndex
);
1731 while (((const ScProtectionAttr
&)pData
[nIndex
].pPattern
->
1732 GetItem(ATTR_PROTECTION
)).GetProtection())
1737 return -1; // nichts gefunden
1739 nRet
= pData
[nIndex
].nRow
;
1743 nRet
= pData
[nIndex
].nRow
+1;
1746 return MAXROW
+1; // nichts gefunden
1753 void ScAttrArray::FindStyleSheet( const SfxStyleSheetBase
* pStyleSheet
, ScFlatBoolRowSegments
& rUsedRows
, bool bReset
)
1757 while (nPos
< nCount
)
1759 SCROW nEnd
= pData
[nPos
].nRow
;
1760 if (pData
[nPos
].pPattern
->GetStyleSheet() == pStyleSheet
)
1762 // for (SCROW nRow = nStart; nRow <= nEnd; nRow++)
1763 // pUsed[nRow] = TRUE;
1765 rUsedRows
.setTrue(nStart
, nEnd
);
1769 ScPatternAttr
* pNewPattern
= new ScPatternAttr(*pData
[nPos
].pPattern
);
1770 pDocument
->GetPool()->Remove(*pData
[nPos
].pPattern
);
1771 pNewPattern
->SetStyleSheet( (ScStyleSheet
*)
1772 pDocument
->GetStyleSheetPool()->
1773 Find( ScGlobal::GetRscString(STR_STYLENAME_STANDARD
),
1774 SFX_STYLE_FAMILY_PARA
,
1775 SFXSTYLEBIT_AUTO
| SCSTYLEBIT_STANDARD
) );
1776 pData
[nPos
].pPattern
= (const ScPatternAttr
*)
1777 &pDocument
->GetPool()->Put(*pNewPattern
);
1782 Search(nStart
, nPos
);
1783 --nPos
; // wegen ++ am Ende
1793 BOOL
ScAttrArray::IsStyleSheetUsed( const ScStyleSheet
& rStyle
,
1794 BOOL bGatherAllStyles
) const
1796 BOOL bIsUsed
= FALSE
;
1799 while ( nPos
< nCount
)
1801 const ScStyleSheet
* pStyle
= pData
[nPos
].pPattern
->GetStyleSheet();
1804 pStyle
->SetUsage( ScStyleSheet::USED
);
1805 if ( pStyle
== &rStyle
)
1807 if ( !bGatherAllStyles
)
1819 BOOL
ScAttrArray::IsEmpty() const
1823 if ( pData
[0].pPattern
!= pDocument
->GetDefPattern() )
1833 //UNUSED2008-05 SCROW ScAttrArray::GetFirstEntryPos() const
1835 //UNUSED2008-05 DBG_ASSERT( nCount, "nCount = 0" );
1837 //UNUSED2008-05 if ( pData[0].pPattern != pDocument->GetDefPattern() )
1838 //UNUSED2008-05 return 0;
1839 //UNUSED2008-05 else
1841 //UNUSED2008-05 if (nCount==1)
1842 //UNUSED2008-05 return 0; // leer
1843 //UNUSED2008-05 else
1844 //UNUSED2008-05 return pData[0].nRow + 1;
1849 //UNUSED2008-05 SCROW ScAttrArray::GetLastEntryPos( BOOL bIncludeBottom ) const
1851 //UNUSED2008-05 DBG_ASSERT( nCount, "nCount == 0" );
1853 //UNUSED2008-05 if (bIncludeBottom)
1854 //UNUSED2008-05 bIncludeBottom = ( pData[nCount-1].pPattern != pDocument->GetDefPattern() );
1856 //UNUSED2008-05 if (bIncludeBottom)
1857 //UNUSED2008-05 return MAXROW;
1858 //UNUSED2008-05 else
1860 //UNUSED2008-05 if (nCount<=1)
1861 //UNUSED2008-05 return 0; // leer
1862 //UNUSED2008-05 else
1863 //UNUSED2008-05 return pData[nCount-2].nRow;
1868 BOOL
ScAttrArray::GetFirstVisibleAttr( SCROW
& rFirstRow
) const
1870 DBG_ASSERT( nCount
, "nCount == 0" );
1872 BOOL bFound
= FALSE
;
1875 // Skip first entry if more than 1 row.
1876 // Entries at the end are not skipped, GetFirstVisibleAttr may be larger than GetLastVisibleAttr.
1878 SCSIZE nVisStart
= 1;
1879 while ( nVisStart
< nCount
&& pData
[nVisStart
].pPattern
->IsVisibleEqual(*pData
[nVisStart
-1].pPattern
) )
1881 if ( nVisStart
>= nCount
|| pData
[nVisStart
-1].nRow
> 0 ) // more than 1 row?
1884 while ( nStart
< nCount
&& !bFound
)
1886 if ( pData
[nStart
].pPattern
->IsVisible() )
1888 rFirstRow
= nStart
? ( pData
[nStart
-1].nRow
+ 1 ) : 0;
1898 // size (rows) of a range of attributes after cell content where the search is stopped
1899 // (more than a default page size, 2*42 because it's as good as any number)
1901 const SCROW SC_VISATTR_STOP
= 84;
1903 BOOL
ScAttrArray::GetLastVisibleAttr( SCROW
& rLastRow
, SCROW nLastData
) const
1905 // #i30830# changed behavior:
1906 // ignore all attributes starting with the first run of SC_VISATTR_STOP equal rows
1907 // below the last content cell
1909 if ( nLastData
== MAXROW
)
1911 rLastRow
= MAXROW
; // can't look for attributes below MAXROW
1915 BOOL bFound
= FALSE
;
1917 // loop backwards from the end instead of using Search, assuming that
1918 // there usually aren't many attributes below the last cell
1920 SCSIZE nPos
= nCount
;
1921 while ( nPos
> 0 && pData
[nPos
-1].nRow
> nLastData
)
1923 SCSIZE nEndPos
= nPos
- 1;
1924 SCSIZE nStartPos
= nEndPos
; // find range of visually equal formats
1925 while ( nStartPos
> 0 &&
1926 pData
[nStartPos
-1].nRow
> nLastData
&&
1927 pData
[nStartPos
-1].pPattern
->IsVisibleEqual(*pData
[nStartPos
].pPattern
) )
1930 SCROW nAttrStartRow
= ( nStartPos
> 0 ) ? ( pData
[nStartPos
-1].nRow
+ 1 ) : 0;
1931 if ( nAttrStartRow
<= nLastData
)
1932 nAttrStartRow
= nLastData
+ 1;
1933 SCROW nAttrSize
= pData
[nEndPos
].nRow
+ 1 - nAttrStartRow
;
1934 if ( nAttrSize
>= SC_VISATTR_STOP
)
1936 bFound
= FALSE
; // ignore this range and below
1938 else if ( !bFound
&& pData
[nEndPos
].pPattern
->IsVisible() )
1940 rLastRow
= pData
[nEndPos
].nRow
;
1944 nPos
= nStartPos
; // look further from the top of the range
1951 BOOL
ScAttrArray::HasVisibleAttrIn( SCROW nStartRow
, SCROW nEndRow
) const
1954 Search( nStartRow
, nIndex
);
1955 SCROW nThisStart
= nStartRow
;
1956 BOOL bFound
= FALSE
;
1957 while ( nIndex
< nCount
&& nThisStart
<= nEndRow
&& !bFound
)
1959 if ( pData
[nIndex
].pPattern
->IsVisible() )
1962 nThisStart
= pData
[nIndex
].nRow
+ 1;
1970 BOOL
ScAttrArray::IsVisibleEqual( const ScAttrArray
& rOther
,
1971 SCROW nStartRow
, SCROW nEndRow
) const
1974 SCSIZE nThisPos
= 0;
1975 SCSIZE nOtherPos
= 0;
1976 if ( nStartRow
> 0 )
1978 Search( nStartRow
, nThisPos
);
1979 rOther
.Search( nStartRow
, nOtherPos
);
1982 while ( nThisPos
<nCount
&& nOtherPos
<rOther
.nCount
&& bEqual
)
1984 SCROW nThisRow
= pData
[nThisPos
].nRow
;
1985 SCROW nOtherRow
= rOther
.pData
[nOtherPos
].nRow
;
1986 const ScPatternAttr
* pThisPattern
= pData
[nThisPos
].pPattern
;
1987 const ScPatternAttr
* pOtherPattern
= rOther
.pData
[nOtherPos
].pPattern
;
1988 bEqual
= ( pThisPattern
== pOtherPattern
||
1989 pThisPattern
->IsVisibleEqual(*pOtherPattern
) );
1991 if ( nThisRow
>= nOtherRow
)
1993 if ( nOtherRow
>= nEndRow
) break;
1996 if ( nThisRow
<= nOtherRow
)
1998 if ( nThisRow
>= nEndRow
) break;
2007 BOOL
ScAttrArray::IsAllEqual( const ScAttrArray
& rOther
, SCROW nStartRow
, SCROW nEndRow
) const
2009 //! mit IsVisibleEqual zusammenfassen?
2012 SCSIZE nThisPos
= 0;
2013 SCSIZE nOtherPos
= 0;
2014 if ( nStartRow
> 0 )
2016 Search( nStartRow
, nThisPos
);
2017 rOther
.Search( nStartRow
, nOtherPos
);
2020 while ( nThisPos
<nCount
&& nOtherPos
<rOther
.nCount
&& bEqual
)
2022 SCROW nThisRow
= pData
[nThisPos
].nRow
;
2023 SCROW nOtherRow
= rOther
.pData
[nOtherPos
].nRow
;
2024 const ScPatternAttr
* pThisPattern
= pData
[nThisPos
].pPattern
;
2025 const ScPatternAttr
* pOtherPattern
= rOther
.pData
[nOtherPos
].pPattern
;
2026 bEqual
= ( pThisPattern
== pOtherPattern
);
2028 if ( nThisRow
>= nOtherRow
)
2030 if ( nOtherRow
>= nEndRow
) break;
2033 if ( nThisRow
<= nOtherRow
)
2035 if ( nThisRow
>= nEndRow
) break;
2044 BOOL
ScAttrArray::TestInsertCol( SCROW nStartRow
, SCROW nEndRow
) const
2046 // horizontal zusammengefasste duerfen nicht herausgeschoben werden
2047 // (ob die ganze Zusammenfassung betroffen ist, ist hier nicht zu erkennen)
2053 if ( nStartRow
> 0 )
2054 Search( nStartRow
, nIndex
);
2056 for ( ; nIndex
< nCount
; nIndex
++ )
2058 if ( ((const ScMergeFlagAttr
&)pData
[nIndex
].pPattern
->
2059 GetItem(ATTR_MERGE_FLAG
)).IsHorOverlapped() )
2061 bTest
= FALSE
; // darf nicht herausgeschoben werden
2064 if ( pData
[nIndex
].nRow
>= nEndRow
) // Ende des Bereichs
2072 BOOL
ScAttrArray::TestInsertRow( SCSIZE nSize
) const
2074 // wenn die erste herausgeschobene Zeile vertikal ueberlappt ist,
2075 // wuerde eine kaputte Zusammenfassung uebrigbleiben
2079 // MAXROW + 1 - nSize = erste herausgeschobene Zeile
2081 SCSIZE nFirstLost
= nCount
-1;
2082 while ( nFirstLost
&& pData
[nFirstLost
-1].nRow
>= sal::static_int_cast
<SCROW
>(MAXROW
+ 1 - nSize
) )
2085 if ( ((const ScMergeFlagAttr
&)pData
[nFirstLost
].pPattern
->
2086 GetItem(ATTR_MERGE_FLAG
)).IsVerOverlapped() )
2094 void ScAttrArray::InsertRow( SCROW nStartRow
, SCSIZE nSize
)
2099 SCROW nSearch
= nStartRow
> 0 ? nStartRow
- 1 : 0; // Vorgaenger erweitern
2101 Search( nSearch
, nIndex
);
2103 // ein gesetztes ScMergeAttr darf nicht ausgedehnt werden
2104 // (darum hinterher wieder loeschen)
2106 BOOL bDoMerge
= ((const ScMergeAttr
&) pData
[nIndex
].pPattern
->GetItem(ATTR_MERGE
)).IsMerged();
2110 for (i
= nIndex
; i
< nCount
-1; i
++)
2112 SCROW nNew
= pData
[i
].nRow
+ nSize
;
2113 if ( nNew
>= MAXROW
) // Ende erreicht ?
2117 nRemove
= i
+1; // folgende loeschen
2119 pData
[i
].nRow
= nNew
;
2122 // muessen Eintraege am Ende geloescht werden?
2124 if (nRemove
&& nRemove
< nCount
)
2125 DeleteRange( nRemove
, nCount
-1 );
2127 if (bDoMerge
) // ausgedehntes ScMergeAttr wieder reparieren
2129 //! ApplyAttr fuer Bereiche !!!
2131 const SfxPoolItem
& rDef
= pDocument
->GetPool()->GetDefaultItem( ATTR_MERGE
);
2132 for (SCSIZE nAdd
=0; nAdd
<nSize
; nAdd
++)
2133 pDocument
->ApplyAttr( nCol
, nStartRow
+nAdd
, nTab
, rDef
);
2135 // im eingefuegten Bereich ist nichts zusammengefasst
2138 // Don't duplicate the merge flags in the inserted row.
2139 RemoveFlags( nStartRow
, nStartRow
+nSize
-1, SC_MF_ALL
);
2143 void ScAttrArray::DeleteRow( SCROW nStartRow
, SCSIZE nSize
)
2148 SCSIZE nStartIndex
= 0;
2149 SCSIZE nEndIndex
= 0;
2152 for ( i
= 0; i
< nCount
-1; i
++)
2153 if (pData
[i
].nRow
>= nStartRow
&& pData
[i
].nRow
<= sal::static_int_cast
<SCROW
>(nStartRow
+nSize
-1))
2168 nStart
= pData
[nStartIndex
-1].nRow
+ 1;
2170 if (nStart
< nStartRow
)
2172 pData
[nStartIndex
].nRow
= nStartRow
- 1;
2175 if (nEndIndex
>= nStartIndex
)
2177 DeleteRange( nStartIndex
, nEndIndex
);
2178 if (nStartIndex
> 0)
2179 if ( pData
[nStartIndex
-1].pPattern
== pData
[nStartIndex
].pPattern
)
2180 DeleteRange( nStartIndex
-1, nStartIndex
-1 );
2183 for (i
= 0; i
< nCount
-1; i
++)
2184 if (pData
[i
].nRow
>= nStartRow
)
2185 pData
[i
].nRow
-= nSize
;
2187 // unten nicht Default-Pattern nachschieben, um Druckbereiche erkennen zu koennen
2188 // stattdessen nur Merge-Flags loeschen
2190 RemoveFlags( MAXROW
-nSize
+1, MAXROW
, SC_MF_HOR
| SC_MF_VER
| SC_MF_AUTO
);
2195 void ScAttrArray::DeleteRange( SCSIZE nStartIndex
, SCSIZE nEndIndex
)
2197 ScDocumentPool
* pDocPool
= pDocument
->GetPool();
2198 for (SCSIZE i
= nStartIndex
; i
<= nEndIndex
; i
++)
2199 pDocPool
->Remove(*pData
[i
].pPattern
);
2201 memmove( &pData
[nStartIndex
], &pData
[nEndIndex
+ 1], (nCount
- nEndIndex
- 1) * sizeof(ScAttrEntry
) );
2202 nCount
-= nEndIndex
-nStartIndex
+1;
2206 void ScAttrArray::DeleteArea(SCROW nStartRow
, SCROW nEndRow
)
2208 RemoveAreaMerge( nStartRow
, nEndRow
); // von zusammengefassten auch die Flags loeschen
2210 if ( !HasAttrib( nStartRow
, nEndRow
, HASATTR_OVERLAPPED
| HASATTR_AUTOFILTER
) )
2211 SetPatternArea( nStartRow
, nEndRow
, pDocument
->GetDefPattern() );
2213 DeleteAreaSafe( nStartRow
, nEndRow
); // Merge-Flags stehenlassen
2217 void ScAttrArray::DeleteHardAttr(SCROW nStartRow
, SCROW nEndRow
)
2219 const ScPatternAttr
* pDefPattern
= pDocument
->GetDefPattern();
2220 const ScPatternAttr
* pOldPattern
;
2226 Search( nStartRow
, nIndex
);
2227 nThisRow
= (nIndex
>0) ? pData
[nIndex
-1].nRow
+1 : 0;
2228 if (nThisRow
< nStartRow
) nThisRow
= nStartRow
;
2230 while ( nThisRow
<= nEndRow
)
2232 pOldPattern
= pData
[nIndex
].pPattern
;
2234 if ( pOldPattern
->GetItemSet().Count() ) // harte Attribute ?
2236 nRow
= pData
[nIndex
].nRow
;
2237 SCROW nAttrRow
= Min( (SCROW
)nRow
, (SCROW
)nEndRow
);
2239 ScPatternAttr
aNewPattern(*pOldPattern
);
2240 SfxItemSet
& rSet
= aNewPattern
.GetItemSet();
2241 for (USHORT nId
= ATTR_PATTERN_START
; nId
<= ATTR_PATTERN_END
; nId
++)
2242 if (nId
!= ATTR_MERGE
&& nId
!= ATTR_MERGE_FLAG
)
2243 rSet
.ClearItem(nId
);
2245 if ( aNewPattern
== *pDefPattern
)
2246 SetPatternArea( nThisRow
, nAttrRow
, pDefPattern
, FALSE
);
2248 SetPatternArea( nThisRow
, nAttrRow
, &aNewPattern
, TRUE
);
2250 Search( nThisRow
, nIndex
); // Daten wurden veraendert !!!
2254 nThisRow
= pData
[nIndex
-1].nRow
+1;
2258 // Verschieben innerhalb eines Dokuments
2260 void ScAttrArray::MoveTo(SCROW nStartRow
, SCROW nEndRow
, ScAttrArray
& rAttrArray
)
2262 SCROW nStart
= nStartRow
;
2263 for (SCSIZE i
= 0; i
< nCount
; i
++)
2265 if ((pData
[i
].nRow
>= nStartRow
) && ((i
==0) ? TRUE
: pData
[i
-1].nRow
< nEndRow
))
2267 // Kopieren (bPutToPool=TRUE)
2268 rAttrArray
.SetPatternArea( nStart
, Min( (SCROW
)pData
[i
].nRow
, (SCROW
)nEndRow
),
2269 pData
[i
].pPattern
, TRUE
);
2271 nStart
= Max( (SCROW
)nStart
, (SCROW
)(pData
[i
].nRow
+ 1) );
2273 DeleteArea(nStartRow
, nEndRow
);
2277 // Kopieren zwischen Dokumenten (Clipboard)
2279 void ScAttrArray::CopyArea( SCROW nStartRow
, SCROW nEndRow
, long nDy
, ScAttrArray
& rAttrArray
,
2282 nStartRow
-= nDy
; // Source
2285 SCROW nDestStart
= Max((long)((long)nStartRow
+ nDy
), (long) 0);
2286 SCROW nDestEnd
= Min((long)((long)nEndRow
+ nDy
), (long) MAXROW
);
2288 ScDocumentPool
* pSourceDocPool
= pDocument
->GetPool();
2289 ScDocumentPool
* pDestDocPool
= rAttrArray
.pDocument
->GetPool();
2290 BOOL bSamePool
= (pSourceDocPool
==pDestDocPool
);
2292 for (SCSIZE i
= 0; (i
< nCount
) && (nDestStart
<= nDestEnd
); i
++)
2294 if (pData
[i
].nRow
>= nStartRow
)
2296 const ScPatternAttr
* pOldPattern
= pData
[i
].pPattern
;
2297 const ScPatternAttr
* pNewPattern
;
2299 if (IsDefaultItem( pOldPattern
))
2301 // am Default muss nichts veraendert werden
2303 pNewPattern
= (const ScPatternAttr
*)
2304 &pDestDocPool
->GetDefaultItem( ATTR_PATTERN
);
2306 else if ( nStripFlags
)
2308 ScPatternAttr
* pTmpPattern
= new ScPatternAttr( *pOldPattern
);
2309 INT16 nNewFlags
= 0;
2310 if ( nStripFlags
!= SC_MF_ALL
)
2311 nNewFlags
= ((const ScMergeFlagAttr
&)pTmpPattern
->GetItem(ATTR_MERGE_FLAG
)).
2312 GetValue() & ~nStripFlags
;
2315 pTmpPattern
->GetItemSet().Put( ScMergeFlagAttr( nNewFlags
) );
2317 pTmpPattern
->GetItemSet().ClearItem( ATTR_MERGE_FLAG
);
2320 pNewPattern
= (ScPatternAttr
*) &pDestDocPool
->Put(*pTmpPattern
);
2322 pNewPattern
= pTmpPattern
->PutInPool( rAttrArray
.pDocument
, pDocument
);
2328 pNewPattern
= (ScPatternAttr
*) &pDestDocPool
->Put(*pOldPattern
);
2330 pNewPattern
= pOldPattern
->PutInPool( rAttrArray
.pDocument
, pDocument
);
2333 rAttrArray
.SetPatternArea(nDestStart
,
2334 Min((SCROW
)(pData
[i
].nRow
+ nDy
), nDestEnd
), pNewPattern
);
2337 // when pasting from clipboard and skipping filtered rows, the adjusted end position
2339 nDestStart
= Max((long)nDestStart
, (long)(pData
[i
].nRow
+ nDy
+ 1));
2343 // Flags stehenlassen
2344 //! mit CopyArea zusammenfassen !!!
2346 void ScAttrArray::CopyAreaSafe( SCROW nStartRow
, SCROW nEndRow
, long nDy
, ScAttrArray
& rAttrArray
)
2348 nStartRow
-= nDy
; // Source
2351 SCROW nDestStart
= Max((long)((long)nStartRow
+ nDy
), (long) 0);
2352 SCROW nDestEnd
= Min((long)((long)nEndRow
+ nDy
), (long) MAXROW
);
2354 if ( !rAttrArray
.HasAttrib( nDestStart
, nDestEnd
, HASATTR_OVERLAPPED
) )
2356 CopyArea( nStartRow
+nDy
, nEndRow
+nDy
, nDy
, rAttrArray
);
2360 ScDocumentPool
* pSourceDocPool
= pDocument
->GetPool();
2361 ScDocumentPool
* pDestDocPool
= rAttrArray
.pDocument
->GetPool();
2362 BOOL bSamePool
= (pSourceDocPool
==pDestDocPool
);
2364 for (SCSIZE i
= 0; (i
< nCount
) && (nDestStart
<= nDestEnd
); i
++)
2366 if (pData
[i
].nRow
>= nStartRow
)
2368 const ScPatternAttr
* pOldPattern
= pData
[i
].pPattern
;
2369 const ScPatternAttr
* pNewPattern
;
2372 pNewPattern
= (ScPatternAttr
*) &pDestDocPool
->Put(*pOldPattern
);
2374 pNewPattern
= pOldPattern
->PutInPool( rAttrArray
.pDocument
, pDocument
);
2376 rAttrArray
.SetPatternAreaSafe(nDestStart
,
2377 Min((SCROW
)(pData
[i
].nRow
+ nDy
), nDestEnd
), pNewPattern
, FALSE
);
2380 // when pasting from clipboard and skipping filtered rows, the adjusted end position
2382 nDestStart
= Max((long)nDestStart
, (long)(pData
[i
].nRow
+ nDy
+ 1));
2387 SCsROW
ScAttrArray::SearchStyle( SCsROW nRow
, const ScStyleSheet
* pSearchStyle
,
2388 BOOL bUp
, ScMarkArray
* pMarkArray
)
2390 BOOL bFound
= FALSE
;
2394 nRow
= pMarkArray
->GetNextMarked( nRow
, bUp
);
2395 if (!VALIDROW(nRow
))
2400 Search(nRow
, nIndex
);
2401 const ScPatternAttr
* pPattern
= pData
[nIndex
].pPattern
;
2403 while (nIndex
< nCount
&& !bFound
)
2405 if (pPattern
->GetStyleSheet() == pSearchStyle
)
2409 nRow
= pMarkArray
->GetNextMarked( nRow
, bUp
);
2410 SCROW nStart
= nIndex
? pData
[nIndex
-1].nRow
+1 : 0;
2411 if (nRow
>= nStart
&& nRow
<= pData
[nIndex
].nRow
)
2430 nRow
= pData
[nIndex
].nRow
;
2431 pPattern
= pData
[nIndex
].pPattern
;
2436 nRow
= pData
[nIndex
].nRow
+1;
2439 pPattern
= pData
[nIndex
].pPattern
;
2444 DBG_ASSERT( bFound
|| !ValidRow(nRow
), "interner Fehler in ScAttrArray::SearchStyle" );
2450 BOOL
ScAttrArray::SearchStyleRange( SCsROW
& rRow
, SCsROW
& rEndRow
,
2451 const ScStyleSheet
* pSearchStyle
, BOOL bUp
, ScMarkArray
* pMarkArray
)
2453 SCsROW nStartRow
= SearchStyle( rRow
, pSearchStyle
, bUp
, pMarkArray
);
2454 if (VALIDROW(nStartRow
))
2457 Search(nStartRow
,nIndex
);
2463 rEndRow
= pData
[nIndex
-1].nRow
+ 1;
2468 SCROW nMarkEnd
= pMarkArray
->GetMarkEnd( nStartRow
, TRUE
);
2469 if (nMarkEnd
>rEndRow
)
2475 rEndRow
= pData
[nIndex
].nRow
;
2478 SCROW nMarkEnd
= pMarkArray
->GetMarkEnd( nStartRow
, FALSE
);
2479 if (nMarkEnd
<rEndRow
)
2490 //------------------------------------------------------------------------
2492 // Laden / Speichern
2497 void ScAttrArray::Save( SvStream
& /* rStream */ ) const
2499 #if SC_ROWLIMIT_STREAM_ACCESS
2500 #error address types changed!
2501 ScWriteHeader
aHdr( rStream
, 8 );
2503 ScDocumentPool
* pDocPool
= pDocument
->GetPool();
2505 USHORT nSaveCount
= nCount
;
2506 SCROW nSaveMaxRow
= pDocument
->GetSrcMaxRow();
2507 if ( nSaveMaxRow
!= MAXROW
)
2509 if ( nSaveCount
> 1 && pData
[nSaveCount
-2].nRow
>= nSaveMaxRow
)
2511 pDocument
->SetLostData(); // Warnung ausgeben
2514 while ( nSaveCount
> 1 && pData
[nSaveCount
-2].nRow
>= nSaveMaxRow
);
2518 rStream
<< nSaveCount
;
2520 const SfxPoolItem
* pItem
;
2521 for (SCSIZE i
=0; i
<nSaveCount
; i
++)
2523 rStream
<< Min( pData
[i
].nRow
, nSaveMaxRow
);
2525 const ScPatternAttr
* pPattern
= pData
[i
].pPattern
;
2526 pDocPool
->StoreSurrogate( rStream
, pPattern
);
2528 // FALSE, weil ATTR_CONDITIONAL (noch) nicht in Vorlagen:
2529 if (pPattern
->GetItemSet().GetItemState(ATTR_CONDITIONAL
,FALSE
,&pItem
) == SFX_ITEM_SET
)
2530 pDocument
->SetConditionalUsed( ((const SfxUInt32Item
*)pItem
)->GetValue() );
2532 if (pPattern
->GetItemSet().GetItemState(ATTR_VALIDDATA
,FALSE
,&pItem
) == SFX_ITEM_SET
)
2533 pDocument
->SetValidationUsed( ((const SfxUInt32Item
*)pItem
)->GetValue() );
2535 #endif // SC_ROWLIMIT_STREAM_ACCESS
2539 void ScAttrArray::Load( SvStream
& /* rStream */ )
2541 #if SC_ROWLIMIT_STREAM_ACCESS
2542 #error address types changed!
2543 ScDocumentPool
* pDocPool
= pDocument
->GetPool();
2545 ScReadHeader
aHdr( rStream
);
2548 rStream
>> nNewCount
;
2549 if ( nNewCount
> MAXROW
+1 ) // wuerde das Array zu gross?
2551 pDocument
->SetLostData();
2552 rStream
.SetError( SVSTREAM_FILEFORMAT_ERROR
);
2556 Reset( pDocument
->GetDefPattern(), FALSE
); // loeschen
2557 pData
= new ScAttrEntry
[nNewCount
]; // neu anlegen
2558 for (SCSIZE i
=0; i
<nNewCount
; i
++)
2560 rStream
>> pData
[i
].nRow
;
2562 USHORT nWhich
= ATTR_PATTERN
;
2563 const ScPatternAttr
* pNewPattern
= (const ScPatternAttr
*)
2564 pDocPool
->LoadSurrogate( rStream
, nWhich
, ATTR_PATTERN
);
2567 // da is was schiefgelaufen
2568 DBG_ERROR("ScAttrArray::Load: Surrogat nicht im Pool");
2569 pNewPattern
= pDocument
->GetDefPattern();
2571 ScDocumentPool::CheckRef( *pNewPattern
);
2572 pData
[i
].pPattern
= pNewPattern
;
2574 // LoadSurrogate erhoeht auch die Ref
2576 nCount
= nLimit
= nNewCount
;
2578 if ( nCount
> 1 && pData
[nCount
-2].nRow
>= MAXROW
) // faengt ein Attribut hinter MAXROW an?
2580 pDocument
->SetLostData();
2581 rStream
.SetError( SVSTREAM_FILEFORMAT_ERROR
);
2585 if ( pDocument
->GetSrcMaxRow() != MAXROW
) // Ende anpassen?
2587 // Ende immer auf MAXROW umsetzen (nur auf 32 Bit)
2589 DBG_ASSERT( pData
[nCount
-1].nRow
== pDocument
->GetSrcMaxRow(), "Attribut-Ende ?!?" );
2590 pData
[nCount
-1].nRow
= MAXROW
;
2592 #endif // SC_ROWLIMIT_STREAM_ACCESS
2597 //UNUSED2008-05 void ScAttrArray::ConvertFontsAfterLoad()
2599 //UNUSED2008-05 ScFontToSubsFontConverter_AutoPtr xFontConverter;
2600 //UNUSED2008-05 const ULONG nFlags = FONTTOSUBSFONT_IMPORT | FONTTOSUBSFONT_ONLYOLDSOSYMBOLFONTS;
2601 //UNUSED2008-05 SCSIZE nIndex = 0;
2602 //UNUSED2008-05 SCROW nThisRow = 0;
2604 //UNUSED2008-05 while ( nThisRow <= MAXROW )
2606 //UNUSED2008-05 const ScPatternAttr* pOldPattern = pData[nIndex].pPattern;
2607 //UNUSED2008-05 const SfxPoolItem* pItem;
2608 //UNUSED2008-05 if( pOldPattern->GetItemSet().GetItemState( ATTR_FONT, FALSE, &pItem ) == SFX_ITEM_SET )
2610 //UNUSED2008-05 const SvxFontItem* pFontItem = (const SvxFontItem*) pItem;
2611 //UNUSED2008-05 const String& rOldName = pFontItem->GetFamilyName();
2612 //UNUSED2008-05 xFontConverter = CreateFontToSubsFontConverter( rOldName, nFlags );
2613 //UNUSED2008-05 if ( xFontConverter )
2615 //UNUSED2008-05 String aNewName( GetFontToSubsFontName( xFontConverter ) );
2616 //UNUSED2008-05 if ( aNewName != rOldName )
2618 //UNUSED2008-05 SCROW nAttrRow = pData[nIndex].nRow;
2619 //UNUSED2008-05 SvxFontItem aNewItem( pFontItem->GetFamily(), aNewName,
2620 //UNUSED2008-05 pFontItem->GetStyleName(), pFontItem->GetPitch(),
2621 //UNUSED2008-05 RTL_TEXTENCODING_DONTKNOW, ATTR_FONT );
2622 //UNUSED2008-05 ScPatternAttr aNewPattern( *pOldPattern );
2623 //UNUSED2008-05 aNewPattern.GetItemSet().Put( aNewItem );
2624 //UNUSED2008-05 SetPatternArea( nThisRow, nAttrRow, &aNewPattern, TRUE );
2625 //UNUSED2008-05 Search( nThisRow, nIndex ); //! data changed
2629 //UNUSED2008-05 ++nIndex;
2630 //UNUSED2008-05 nThisRow = pData[nIndex-1].nRow+1;