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: markdata.cxx,v $
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 // INCLUDE ---------------------------------------------------------------
38 #include <tools/debug.hxx>
40 #include "markdata.hxx"
41 #include "markarr.hxx"
42 #include "rangelst.hxx"
44 // STATIC DATA -----------------------------------------------------------
46 //------------------------------------------------------------------------
48 ScMarkData::ScMarkData() :
51 for (SCTAB i
=0; i
<=MAXTAB
; i
++)
52 bTabMarked
[i
] = FALSE
;
57 ScMarkData::ScMarkData(const ScMarkData
& rData
) :
58 aMarkRange( rData
.aMarkRange
),
59 aMultiRange( rData
.aMultiRange
),
62 bMarked
= rData
.bMarked
;
63 bMultiMarked
= rData
.bMultiMarked
;
64 bMarking
= rData
.bMarking
;
65 bMarkIsNeg
= rData
.bMarkIsNeg
;
67 for (SCTAB i
=0; i
<=MAXTAB
; i
++)
68 bTabMarked
[i
] = rData
.bTabMarked
[i
];
72 pMultiSel
= new ScMarkArray
[MAXCOLCOUNT
];
73 for (SCCOL j
=0; j
<MAXCOLCOUNT
; j
++)
74 rData
.pMultiSel
[j
].CopyMarksTo( pMultiSel
[j
] );
78 ScMarkData
& ScMarkData::operator=(const ScMarkData
& rData
)
86 aMarkRange
= rData
.aMarkRange
;
87 aMultiRange
= rData
.aMultiRange
;
88 bMarked
= rData
.bMarked
;
89 bMultiMarked
= rData
.bMultiMarked
;
90 bMarking
= rData
.bMarking
;
91 bMarkIsNeg
= rData
.bMarkIsNeg
;
93 for (SCTAB i
=0; i
<=MAXTAB
; i
++)
94 bTabMarked
[i
] = rData
.bTabMarked
[i
];
98 pMultiSel
= new ScMarkArray
[MAXCOLCOUNT
];
99 for (SCCOL j
=0; j
<MAXCOLCOUNT
; j
++)
100 rData
.pMultiSel
[j
].CopyMarksTo( pMultiSel
[j
] );
106 ScMarkData::~ScMarkData()
111 void ScMarkData::ResetMark()
116 bMarked
= bMultiMarked
= FALSE
;
117 bMarking
= bMarkIsNeg
= FALSE
;
120 void ScMarkData::SetMarkArea( const ScRange
& rRange
)
123 aMarkRange
.Justify();
126 // #77987# Upon creation of a document ScFormatShell GetTextAttrState
127 // may query (default) attributes although no sheet is marked yet.
129 if ( !GetSelectCount() )
130 bTabMarked
[ aMarkRange
.aStart
.Tab() ] = TRUE
;
135 void ScMarkData::GetMarkArea( ScRange
& rRange
) const
137 rRange
= aMarkRange
; //! inline ?
140 void ScMarkData::GetMultiMarkArea( ScRange
& rRange
) const
142 rRange
= aMultiRange
;
145 void ScMarkData::SetMultiMarkArea( const ScRange
& rRange
, BOOL bMark
)
149 pMultiSel
= new ScMarkArray
[MAXCOL
+1];
151 // if simple mark range is set, copy to multi marks
152 if ( bMarked
&& !bMarkIsNeg
)
155 SetMultiMarkArea( aMarkRange
, TRUE
);
159 SCCOL nStartCol
= rRange
.aStart
.Col();
160 SCROW nStartRow
= rRange
.aStart
.Row();
161 SCCOL nEndCol
= rRange
.aEnd
.Col();
162 SCROW nEndRow
= rRange
.aEnd
.Row();
163 PutInOrder( nStartRow
, nEndRow
);
164 PutInOrder( nStartCol
, nEndCol
);
167 for (nCol
=nStartCol
; nCol
<=nEndCol
; nCol
++)
168 pMultiSel
[nCol
].SetMarkArea( nStartRow
, nEndRow
, bMark
);
170 if ( bMultiMarked
) // aMultiRange updaten
172 if ( nStartCol
< aMultiRange
.aStart
.Col() )
173 aMultiRange
.aStart
.SetCol( nStartCol
);
174 if ( nStartRow
< aMultiRange
.aStart
.Row() )
175 aMultiRange
.aStart
.SetRow( nStartRow
);
176 if ( nEndCol
> aMultiRange
.aEnd
.Col() )
177 aMultiRange
.aEnd
.SetCol( nEndCol
);
178 if ( nEndRow
> aMultiRange
.aEnd
.Row() )
179 aMultiRange
.aEnd
.SetRow( nEndRow
);
183 aMultiRange
= rRange
; // neu
188 void ScMarkData::SetAreaTab( SCTAB nTab
)
190 aMarkRange
.aStart
.SetTab(nTab
);
191 aMarkRange
.aEnd
.SetTab(nTab
);
192 aMultiRange
.aStart
.SetTab(nTab
);
193 aMultiRange
.aEnd
.SetTab(nTab
);
196 void ScMarkData::SelectOneTable( SCTAB nTab
)
198 for (SCTAB i
=0; i
<=MAXTAB
; i
++)
199 bTabMarked
[i
] = ( nTab
== i
);
202 SCTAB
ScMarkData::GetSelectCount() const
205 for (SCTAB i
=0; i
<=MAXTAB
; i
++)
212 SCTAB
ScMarkData::GetFirstSelected() const
214 for (SCTAB i
=0; i
<=MAXTAB
; i
++)
218 DBG_ERROR("GetFirstSelected: keine markiert");
222 void ScMarkData::MarkToMulti()
224 if ( bMarked
&& !bMarking
)
226 SetMultiMarkArea( aMarkRange
, !bMarkIsNeg
);
229 // check if all multi mark ranges have been removed
230 if ( bMarkIsNeg
&& !HasAnyMultiMarks() )
235 void ScMarkData::MarkToSimple()
240 if ( bMultiMarked
&& bMarked
)
241 MarkToMulti(); // may result in bMarked and bMultiMarked reset
245 DBG_ASSERT(pMultiSel
, "bMultiMarked, aber pMultiSel == 0");
247 ScRange aNew
= aMultiRange
;
250 SCCOL nStartCol
= aNew
.aStart
.Col();
251 SCCOL nEndCol
= aNew
.aEnd
.Col();
253 while ( nStartCol
< nEndCol
&& !pMultiSel
[nStartCol
].HasMarks() )
255 while ( nStartCol
< nEndCol
&& !pMultiSel
[nEndCol
].HasMarks() )
258 // Zeilen werden nur aus MarkArray genommen
259 SCROW nStartRow
, nEndRow
;
260 if ( pMultiSel
[nStartCol
].HasOneMark( nStartRow
, nEndRow
) )
263 SCROW nCmpStart
, nCmpEnd
;
264 for (SCCOL nCol
=nStartCol
+1; nCol
<=nEndCol
&& bOk
; nCol
++)
265 if ( !pMultiSel
[nCol
].HasOneMark( nCmpStart
, nCmpEnd
)
266 || nCmpStart
!= nStartRow
|| nCmpEnd
!= nEndRow
)
272 aNew
.aStart
.SetCol(nStartCol
);
273 aNew
.aStart
.SetRow(nStartRow
);
274 aNew
.aEnd
.SetCol(nEndCol
);
275 aNew
.aEnd
.SetRow(nEndRow
);
285 BOOL
ScMarkData::IsCellMarked( SCCOL nCol
, SCROW nRow
, BOOL bNoSimple
) const
287 if ( bMarked
&& !bNoSimple
&& !bMarkIsNeg
)
288 if ( aMarkRange
.aStart
.Col() <= nCol
&& aMarkRange
.aEnd
.Col() >= nCol
&&
289 aMarkRange
.aStart
.Row() <= nRow
&& aMarkRange
.aEnd
.Row() >= nRow
)
294 //! hier auf negative Markierung testen ?
296 DBG_ASSERT(pMultiSel
, "bMultiMarked, aber pMultiSel == 0");
297 return pMultiSel
[nCol
].GetMark( nRow
);
303 BOOL
ScMarkData::IsColumnMarked( SCCOL nCol
) const
305 // bMarkIsNeg inzwischen auch fuer Spaltenkoepfe
306 //! GetMarkColumnRanges fuer komplett markierte Spalten
308 if ( bMarked
&& !bMarkIsNeg
&&
309 aMarkRange
.aStart
.Col() <= nCol
&& aMarkRange
.aEnd
.Col() >= nCol
&&
310 aMarkRange
.aStart
.Row() == 0 && aMarkRange
.aEnd
.Row() == MAXROW
)
313 if ( bMultiMarked
&& pMultiSel
[nCol
].IsAllMarked(0,MAXROW
) )
319 BOOL
ScMarkData::IsRowMarked( SCROW nRow
) const
321 // bMarkIsNeg inzwischen auch fuer Zeilenkoepfe
322 //! GetMarkRowRanges fuer komplett markierte Zeilen
324 if ( bMarked
&& !bMarkIsNeg
&&
325 aMarkRange
.aStart
.Col() == 0 && aMarkRange
.aEnd
.Col() == MAXCOL
&&
326 aMarkRange
.aStart
.Row() <= nRow
&& aMarkRange
.aEnd
.Row() >= nRow
)
331 DBG_ASSERT(pMultiSel
, "bMultiMarked, aber pMultiSel == 0");
332 for (SCCOL nCol
=0; nCol
<=MAXCOL
; nCol
++)
333 if (!pMultiSel
[nCol
].GetMark(nRow
))
341 void ScMarkData::MarkFromRangeList( const ScRangeList
& rList
, BOOL bReset
)
345 for (SCTAB i
=0; i
<=MAXTAB
; i
++)
346 bTabMarked
[i
] = FALSE
; // Tabellen sind nicht in ResetMark
350 ULONG nCount
= rList
.Count();
351 if ( nCount
== 1 && !bMarked
&& !bMultiMarked
)
353 ScRange aRange
= *rList
.GetObject(0);
354 SetMarkArea( aRange
);
355 SelectTable( aRange
.aStart
.Tab(), TRUE
);
359 for (ULONG i
=0; i
<nCount
; i
++)
361 ScRange aRange
= *rList
.GetObject(i
);
362 SetMultiMarkArea( aRange
, TRUE
);
363 SelectTable( aRange
.aStart
.Tab(), TRUE
);
368 void ScMarkData::FillRangeListWithMarks( ScRangeList
* pList
, BOOL bClear
) const
376 //! bei mehreren selektierten Tabellen mehrere Ranges eintragen !!!
380 DBG_ASSERT(pMultiSel
, "bMultiMarked, aber pMultiSel == 0");
382 SCTAB nTab
= aMultiRange
.aStart
.Tab();
384 SCCOL nStartCol
= aMultiRange
.aStart
.Col();
385 SCCOL nEndCol
= aMultiRange
.aEnd
.Col();
386 for (SCCOL nCol
=nStartCol
; nCol
<=nEndCol
; nCol
++)
387 if (pMultiSel
[nCol
].HasMarks())
390 ScRange
aRange( nCol
, 0, nTab
);
391 ScMarkArrayIter
aMarkIter( &pMultiSel
[nCol
] );
392 while ( aMarkIter
.Next( nTop
, nBottom
) )
394 aRange
.aStart
.SetRow( nTop
);
395 aRange
.aEnd
.SetRow( nBottom
);
396 pList
->Join( aRange
);
402 pList
->Append( aMarkRange
);
405 void ScMarkData::ExtendRangeListTables( ScRangeList
* pList
) const
410 ScRangeList
aOldList(*pList
);
411 pList
->RemoveAll(); //! oder die vorhandenen unten weglassen
413 for (SCTAB nTab
=0; nTab
<=MAXTAB
; nTab
++)
414 if (bTabMarked
[nTab
])
416 ULONG nCount
= aOldList
.Count();
417 for (ULONG i
=0; i
<nCount
; i
++)
419 ScRange aRange
= *aOldList
.GetObject(i
);
420 aRange
.aStart
.SetTab(nTab
);
421 aRange
.aEnd
.SetTab(nTab
);
422 pList
->Append( aRange
);
427 SCCOLROW
ScMarkData::GetMarkColumnRanges( SCCOLROW
* pRanges
)
435 DBG_ASSERT(pMultiSel
, "bMultiMarked, aber pMultiSel == 0");
437 SCCOLROW nRangeCnt
= 0;
439 while (nStart
<=MAXCOL
)
441 while (nStart
<MAXCOL
&& !pMultiSel
[nStart
].HasMarks())
443 if (pMultiSel
[nStart
].HasMarks())
445 SCCOLROW nEnd
= nStart
;
446 while (nEnd
<MAXCOL
&& pMultiSel
[nEnd
].HasMarks())
448 if (!pMultiSel
[nEnd
].HasMarks())
450 pRanges
[2*nRangeCnt
] = nStart
;
451 pRanges
[2*nRangeCnt
+1] = nEnd
;
462 SCCOLROW
ScMarkData::GetMarkRowRanges( SCCOLROW
* pRanges
)
470 DBG_ASSERT(pMultiSel
, "bMultiMarked, aber pMultiSel == 0");
472 // Welche Zeilen sind markiert?
474 BOOL
* bRowMarked
= new BOOL
[MAXROW
+1];
477 for (nRow
=0; nRow
<=MAXROW
; nRow
++)
478 bRowMarked
[nRow
] = FALSE
;
481 for (nCol
=0; nCol
<=MAXCOL
; nCol
++)
483 ScMarkArrayIter
aMarkIter( &pMultiSel
[nCol
] );
484 while (aMarkIter
.Next( nTop
, nBottom
))
485 for (nRow
=nTop
; nRow
<=nBottom
; nRow
++)
486 bRowMarked
[nRow
] = TRUE
;
489 // zu Bereichen zusammenfassen
491 SCCOLROW nRangeCnt
= 0;
493 while (nStart
<=MAXROW
)
495 while (nStart
<MAXROW
&& !bRowMarked
[nStart
])
497 if (bRowMarked
[nStart
])
499 SCCOLROW nEnd
= nStart
;
500 while (nEnd
<MAXROW
&& bRowMarked
[nEnd
])
502 if (!bRowMarked
[nEnd
])
504 pRanges
[2*nRangeCnt
] = nStart
;
505 pRanges
[2*nRangeCnt
+1] = nEnd
;
517 BOOL
ScMarkData::IsAllMarked( const ScRange
& rRange
) const
522 DBG_ASSERT(pMultiSel
, "bMultiMarked, aber pMultiSel == 0");
524 SCCOL nStartCol
= rRange
.aStart
.Col();
525 SCROW nStartRow
= rRange
.aStart
.Row();
526 SCCOL nEndCol
= rRange
.aEnd
.Col();
527 SCROW nEndRow
= rRange
.aEnd
.Row();
529 for (SCCOL nCol
=nStartCol
; nCol
<=nEndCol
&& bOk
; nCol
++)
530 if ( !pMultiSel
[nCol
].IsAllMarked( nStartRow
, nEndRow
) )
536 SCsROW
ScMarkData::GetNextMarked( SCCOL nCol
, SCsROW nRow
, BOOL bUp
) const
541 DBG_ASSERT(pMultiSel
, "bMultiMarked, aber pMultiSel == 0");
543 return pMultiSel
[nCol
].GetNextMarked( nRow
, bUp
);
546 BOOL
ScMarkData::HasMultiMarks( SCCOL nCol
) const
551 DBG_ASSERT(pMultiSel
, "bMultiMarked, aber pMultiSel == 0");
553 return pMultiSel
[nCol
].HasMarks();
556 BOOL
ScMarkData::HasAnyMultiMarks() const
561 DBG_ASSERT(pMultiSel
, "bMultiMarked, aber pMultiSel == 0");
563 for (SCCOL nCol
=0; nCol
<=MAXCOL
; nCol
++)
564 if ( pMultiSel
[nCol
].HasMarks() )
570 void ScMarkData::InsertTab( SCTAB nTab
)
572 for (SCTAB i
=MAXTAB
; i
>nTab
; i
--)
573 bTabMarked
[i
] = bTabMarked
[i
-1];
574 bTabMarked
[nTab
] = FALSE
;
577 void ScMarkData::DeleteTab( SCTAB nTab
)
579 for (SCTAB i
=nTab
; i
<MAXTAB
; i
++)
580 bTabMarked
[i
] = bTabMarked
[i
+1];
581 bTabMarked
[MAXTAB
] = FALSE
;