update dev300-m58
[ooovba.git] / sc / source / core / data / markdata.cxx
blobb2744f0414ec2b384a1317bdab45da0d73978f75
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: markdata.cxx,v $
10 * $Revision: 1.8 $
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() :
49 pMultiSel( NULL )
51 for (SCTAB i=0; i<=MAXTAB; i++)
52 bTabMarked[i] = FALSE;
54 ResetMark();
57 ScMarkData::ScMarkData(const ScMarkData& rData) :
58 aMarkRange( rData.aMarkRange ),
59 aMultiRange( rData.aMultiRange ),
60 pMultiSel( NULL )
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];
70 if (rData.pMultiSel)
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)
80 if ( &rData == this )
81 return *this;
83 delete[] pMultiSel;
84 pMultiSel = NULL;
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];
96 if (rData.pMultiSel)
98 pMultiSel = new ScMarkArray[MAXCOLCOUNT];
99 for (SCCOL j=0; j<MAXCOLCOUNT; j++)
100 rData.pMultiSel[j].CopyMarksTo( pMultiSel[j] );
103 return *this;
106 ScMarkData::~ScMarkData()
108 delete[] pMultiSel;
111 void ScMarkData::ResetMark()
113 delete[] pMultiSel;
114 pMultiSel = NULL;
116 bMarked = bMultiMarked = FALSE;
117 bMarking = bMarkIsNeg = FALSE;
120 void ScMarkData::SetMarkArea( const ScRange& rRange )
122 aMarkRange = rRange;
123 aMarkRange.Justify();
124 if ( !bMarked )
126 // #77987# Upon creation of a document ScFormatShell GetTextAttrState
127 // may query (default) attributes although no sheet is marked yet.
128 // => mark that one.
129 if ( !GetSelectCount() )
130 bTabMarked[ aMarkRange.aStart.Tab() ] = TRUE;
131 bMarked = 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 )
147 if (!pMultiSel)
149 pMultiSel = new ScMarkArray[MAXCOL+1];
151 // if simple mark range is set, copy to multi marks
152 if ( bMarked && !bMarkIsNeg )
154 bMarked = FALSE;
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 );
166 SCCOL nCol;
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 );
181 else
183 aMultiRange = rRange; // neu
184 bMultiMarked = TRUE;
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
204 SCTAB nCount = 0;
205 for (SCTAB i=0; i<=MAXTAB; i++)
206 if (bTabMarked[i])
207 ++nCount;
209 return nCount;
212 SCTAB ScMarkData::GetFirstSelected() const
214 for (SCTAB i=0; i<=MAXTAB; i++)
215 if (bTabMarked[i])
216 return i;
218 DBG_ERROR("GetFirstSelected: keine markiert");
219 return 0;
222 void ScMarkData::MarkToMulti()
224 if ( bMarked && !bMarking )
226 SetMultiMarkArea( aMarkRange, !bMarkIsNeg );
227 bMarked = FALSE;
229 // check if all multi mark ranges have been removed
230 if ( bMarkIsNeg && !HasAnyMultiMarks() )
231 ResetMark();
235 void ScMarkData::MarkToSimple()
237 if ( bMarking )
238 return;
240 if ( bMultiMarked && bMarked )
241 MarkToMulti(); // may result in bMarked and bMultiMarked reset
243 if ( bMultiMarked )
245 DBG_ASSERT(pMultiSel, "bMultiMarked, aber pMultiSel == 0");
247 ScRange aNew = aMultiRange;
249 BOOL bOk = FALSE;
250 SCCOL nStartCol = aNew.aStart.Col();
251 SCCOL nEndCol = aNew.aEnd.Col();
253 while ( nStartCol < nEndCol && !pMultiSel[nStartCol].HasMarks() )
254 ++nStartCol;
255 while ( nStartCol < nEndCol && !pMultiSel[nEndCol].HasMarks() )
256 --nEndCol;
258 // Zeilen werden nur aus MarkArray genommen
259 SCROW nStartRow, nEndRow;
260 if ( pMultiSel[nStartCol].HasOneMark( nStartRow, nEndRow ) )
262 bOk = TRUE;
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 )
267 bOk = FALSE;
270 if (bOk)
272 aNew.aStart.SetCol(nStartCol);
273 aNew.aStart.SetRow(nStartRow);
274 aNew.aEnd.SetCol(nEndCol);
275 aNew.aEnd.SetRow(nEndRow);
277 ResetMark();
278 aMarkRange = aNew;
279 bMarked = TRUE;
280 bMarkIsNeg = FALSE;
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 )
290 return TRUE;
292 if (bMultiMarked)
294 //! hier auf negative Markierung testen ?
296 DBG_ASSERT(pMultiSel, "bMultiMarked, aber pMultiSel == 0");
297 return pMultiSel[nCol].GetMark( nRow );
300 return FALSE;
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 )
311 return TRUE;
313 if ( bMultiMarked && pMultiSel[nCol].IsAllMarked(0,MAXROW) )
314 return TRUE;
316 return FALSE;
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 )
327 return TRUE;
329 if ( bMultiMarked )
331 DBG_ASSERT(pMultiSel, "bMultiMarked, aber pMultiSel == 0");
332 for (SCCOL nCol=0; nCol<=MAXCOL; nCol++)
333 if (!pMultiSel[nCol].GetMark(nRow))
334 return FALSE;
335 return TRUE;
338 return FALSE;
341 void ScMarkData::MarkFromRangeList( const ScRangeList& rList, BOOL bReset )
343 if (bReset)
345 for (SCTAB i=0; i<=MAXTAB; i++)
346 bTabMarked[i] = FALSE; // Tabellen sind nicht in ResetMark
347 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 );
357 else
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
370 if (!pList)
371 return;
373 if (bClear)
374 pList->RemoveAll();
376 //! bei mehreren selektierten Tabellen mehrere Ranges eintragen !!!
378 if ( bMultiMarked )
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())
389 SCROW nTop, nBottom;
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 );
401 if ( bMarked )
402 pList->Append( aMarkRange );
405 void ScMarkData::ExtendRangeListTables( ScRangeList* pList ) const
407 if (!pList)
408 return;
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 )
429 if (bMarked)
430 MarkToMulti();
432 if (!bMultiMarked)
433 return 0;
435 DBG_ASSERT(pMultiSel, "bMultiMarked, aber pMultiSel == 0");
437 SCCOLROW nRangeCnt = 0;
438 SCCOLROW nStart = 0;
439 while (nStart<=MAXCOL)
441 while (nStart<MAXCOL && !pMultiSel[nStart].HasMarks())
442 ++nStart;
443 if (pMultiSel[nStart].HasMarks())
445 SCCOLROW nEnd = nStart;
446 while (nEnd<MAXCOL && pMultiSel[nEnd].HasMarks())
447 ++nEnd;
448 if (!pMultiSel[nEnd].HasMarks())
449 --nEnd;
450 pRanges[2*nRangeCnt ] = nStart;
451 pRanges[2*nRangeCnt+1] = nEnd;
452 ++nRangeCnt;
453 nStart = nEnd+1;
455 else
456 nStart = MAXCOL+1;
459 return nRangeCnt;
462 SCCOLROW ScMarkData::GetMarkRowRanges( SCCOLROW* pRanges )
464 if (bMarked)
465 MarkToMulti();
467 if (!bMultiMarked)
468 return 0;
470 DBG_ASSERT(pMultiSel, "bMultiMarked, aber pMultiSel == 0");
472 // Welche Zeilen sind markiert?
474 BOOL* bRowMarked = new BOOL[MAXROW+1];
475 SCROW nRow;
476 SCCOL nCol;
477 for (nRow=0; nRow<=MAXROW; nRow++)
478 bRowMarked[nRow] = FALSE;
480 SCROW nTop, nBottom;
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;
492 SCCOLROW nStart = 0;
493 while (nStart<=MAXROW)
495 while (nStart<MAXROW && !bRowMarked[nStart])
496 ++nStart;
497 if (bRowMarked[nStart])
499 SCCOLROW nEnd = nStart;
500 while (nEnd<MAXROW && bRowMarked[nEnd])
501 ++nEnd;
502 if (!bRowMarked[nEnd])
503 --nEnd;
504 pRanges[2*nRangeCnt ] = nStart;
505 pRanges[2*nRangeCnt+1] = nEnd;
506 ++nRangeCnt;
507 nStart = nEnd+1;
509 else
510 nStart = MAXROW+1;
513 delete[] bRowMarked;
514 return nRangeCnt;
517 BOOL ScMarkData::IsAllMarked( const ScRange& rRange ) const
519 if ( !bMultiMarked )
520 return FALSE;
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();
528 BOOL bOk = TRUE;
529 for (SCCOL nCol=nStartCol; nCol<=nEndCol && bOk; nCol++)
530 if ( !pMultiSel[nCol].IsAllMarked( nStartRow, nEndRow ) )
531 bOk = FALSE;
533 return bOk;
536 SCsROW ScMarkData::GetNextMarked( SCCOL nCol, SCsROW nRow, BOOL bUp ) const
538 if ( !bMultiMarked )
539 return nRow;
541 DBG_ASSERT(pMultiSel, "bMultiMarked, aber pMultiSel == 0");
543 return pMultiSel[nCol].GetNextMarked( nRow, bUp );
546 BOOL ScMarkData::HasMultiMarks( SCCOL nCol ) const
548 if ( !bMultiMarked )
549 return FALSE;
551 DBG_ASSERT(pMultiSel, "bMultiMarked, aber pMultiSel == 0");
553 return pMultiSel[nCol].HasMarks();
556 BOOL ScMarkData::HasAnyMultiMarks() const
558 if ( !bMultiMarked )
559 return FALSE;
561 DBG_ASSERT(pMultiSel, "bMultiMarked, aber pMultiSel == 0");
563 for (SCCOL nCol=0; nCol<=MAXCOL; nCol++)
564 if ( pMultiSel[nCol].HasMarks() )
565 return TRUE;
567 return FALSE; // nix
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;