xref: /trunk/main/sc/source/ui/view/prevloc.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 
32 
33 // INCLUDE ---------------------------------------------------------------
34 
35 #include <vcl/outdev.hxx>
36 #include <tools/debug.hxx>
37 
38 #include "prevloc.hxx"
39 #include "document.hxx"
40 
41 //==================================================================
42 
43 enum ScPreviewLocationType
44 {
45     SC_PLOC_CELLRANGE,
46     SC_PLOC_COLHEADER,
47     SC_PLOC_ROWHEADER,
48     SC_PLOC_LEFTHEADER,
49     SC_PLOC_RIGHTHEADER,
50     SC_PLOC_LEFTFOOTER,
51     SC_PLOC_RIGHTFOOTER,
52     SC_PLOC_NOTEMARK,
53     SC_PLOC_NOTETEXT
54 };
55 
56 struct ScPreviewLocationEntry
57 {
58     ScPreviewLocationType   eType;
59     Rectangle               aPixelRect;
60     ScRange                 aCellRange;
61     sal_Bool                    bRepeatCol;
62     sal_Bool                    bRepeatRow;
63 
64     ScPreviewLocationEntry( ScPreviewLocationType eNewType, const Rectangle& rPixel, const ScRange& rRange,
65                             sal_Bool bRepCol, sal_Bool bRepRow ) :
66         eType( eNewType ),
67         aPixelRect( rPixel ),
68         aCellRange( rRange ),
69         bRepeatCol( bRepCol ),
70         bRepeatRow( bRepRow )
71     {
72     }
73 };
74 
75 //==================================================================
76 
77 ScPreviewTableInfo::ScPreviewTableInfo() :
78     nTab(0),
79     nCols(0),
80     nRows(0),
81     pColInfo(NULL),
82     pRowInfo(NULL)
83 {
84 }
85 
86 ScPreviewTableInfo::~ScPreviewTableInfo()
87 {
88     delete[] pColInfo;
89     delete[] pRowInfo;
90 }
91 
92 void ScPreviewTableInfo::SetTab( SCTAB nNewTab )
93 {
94     nTab = nNewTab;
95 }
96 
97 void ScPreviewTableInfo::SetColInfo( SCCOL nCount, ScPreviewColRowInfo* pNewInfo )
98 {
99     delete[] pColInfo;
100     pColInfo = pNewInfo;
101     nCols = nCount;
102 }
103 
104 void ScPreviewTableInfo::SetRowInfo( SCROW nCount, ScPreviewColRowInfo* pNewInfo )
105 {
106     delete[] pRowInfo;
107     pRowInfo = pNewInfo;
108     nRows = nCount;
109 }
110 
111 void ScPreviewTableInfo::LimitToArea( const Rectangle& rPixelArea )
112 {
113     if ( pColInfo )
114     {
115         //  cells completely left of the visible area
116         SCCOL nStart = 0;
117         while ( nStart < nCols && pColInfo[nStart].nPixelEnd < rPixelArea.Left() )
118             ++nStart;
119 
120         //  cells completely right of the visible area
121         SCCOL nEnd = nCols;
122         while ( nEnd > 0 && pColInfo[nEnd-1].nPixelStart > rPixelArea.Right() )
123             --nEnd;
124 
125         if ( nStart > 0 || nEnd < nCols )
126         {
127             if ( nEnd > nStart )
128             {
129                 SCCOL nNewCount = nEnd - nStart;
130                 ScPreviewColRowInfo* pNewInfo = new ScPreviewColRowInfo[nNewCount];
131                 for (SCCOL i=0; i<nNewCount; i++)
132                     pNewInfo[i] = pColInfo[nStart + i];
133                 SetColInfo( nNewCount, pNewInfo );
134             }
135             else
136                 SetColInfo( 0, NULL );      // all invisible
137         }
138     }
139 
140     if ( pRowInfo )
141     {
142         //  cells completely above the visible area
143         SCROW nStart = 0;
144         while ( nStart < nRows && pRowInfo[nStart].nPixelEnd < rPixelArea.Top() )
145             ++nStart;
146 
147         //  cells completely below the visible area
148         SCROW nEnd = nRows;
149         while ( nEnd > 0 && pRowInfo[nEnd-1].nPixelStart > rPixelArea.Bottom() )
150             --nEnd;
151 
152         if ( nStart > 0 || nEnd < nRows )
153         {
154             if ( nEnd > nStart )
155             {
156                 SCROW nNewCount = nEnd - nStart;
157                 ScPreviewColRowInfo* pNewInfo = new ScPreviewColRowInfo[nNewCount];
158                 for (SCROW i=0; i<nNewCount; i++)
159                     pNewInfo[i] = pRowInfo[nStart + i];
160                 SetRowInfo( nNewCount, pNewInfo );
161             }
162             else
163                 SetRowInfo( 0, NULL );      // all invisible
164         }
165     }
166 }
167 
168 //------------------------------------------------------------------
169 
170 ScPreviewLocationData::ScPreviewLocationData( ScDocument* pDocument, OutputDevice* pWin ) :
171     pWindow( pWin ),
172     pDoc( pDocument ),
173     nDrawRanges( 0 ),
174     nPrintTab( 0 )
175 {
176 }
177 
178 ScPreviewLocationData::~ScPreviewLocationData()
179 {
180     Clear();
181 }
182 
183 void ScPreviewLocationData::SetCellMapMode( const MapMode& rMapMode )
184 {
185     aCellMapMode = rMapMode;
186 }
187 
188 void ScPreviewLocationData::SetPrintTab( SCTAB nNew )
189 {
190     nPrintTab = nNew;
191 }
192 
193 void ScPreviewLocationData::Clear()
194 {
195     void* pEntry = aEntries.First();
196     while ( pEntry )
197     {
198         delete (ScPreviewLocationEntry*) pEntry;
199         pEntry = aEntries.Next();
200     }
201     aEntries.Clear();
202 
203     nDrawRanges = 0;
204 }
205 
206 void ScPreviewLocationData::AddCellRange( const Rectangle& rRect, const ScRange& rRange, sal_Bool bRepCol, sal_Bool bRepRow,
207                                             const MapMode& rDrawMap )
208 {
209     Rectangle aPixelRect( pWindow->LogicToPixel( rRect ) );
210     aEntries.Insert( new ScPreviewLocationEntry( SC_PLOC_CELLRANGE, aPixelRect, rRange, bRepCol, bRepRow ) );
211 
212     DBG_ASSERT( nDrawRanges < SC_PREVIEW_MAXRANGES, "too many ranges" );
213     if ( nDrawRanges < SC_PREVIEW_MAXRANGES )
214     {
215         aDrawRectangle[nDrawRanges] = aPixelRect;
216         aDrawMapMode[nDrawRanges] = rDrawMap;
217             if (bRepCol)
218                 if (bRepRow)
219                     aDrawRangeId[nDrawRanges] = SC_PREVIEW_RANGE_EDGE;
220                 else
221                     aDrawRangeId[nDrawRanges] = SC_PREVIEW_RANGE_REPCOL;
222             else
223                 if (bRepRow)
224                     aDrawRangeId[nDrawRanges] = SC_PREVIEW_RANGE_REPROW;
225                 else
226                     aDrawRangeId[nDrawRanges] = SC_PREVIEW_RANGE_TAB;
227         ++nDrawRanges;
228     }
229 }
230 
231 void ScPreviewLocationData::AddColHeaders( const Rectangle& rRect, SCCOL nStartCol, SCCOL nEndCol, sal_Bool bRepCol )
232 {
233     SCTAB nTab = 0; //! ?
234     ScRange aRange( nStartCol, 0, nTab, nEndCol, 0, nTab );
235     Rectangle aPixelRect( pWindow->LogicToPixel( rRect ) );
236     aEntries.Insert( new ScPreviewLocationEntry( SC_PLOC_COLHEADER, aPixelRect, aRange, bRepCol, sal_False ) );
237 }
238 
239 void ScPreviewLocationData::AddRowHeaders( const Rectangle& rRect, SCROW nStartRow, SCROW nEndRow, sal_Bool bRepRow )
240 {
241     SCTAB nTab = 0; //! ?
242     ScRange aRange( 0, nStartRow, nTab, 0, nEndRow, nTab );
243     Rectangle aPixelRect( pWindow->LogicToPixel( rRect ) );
244     aEntries.Insert( new ScPreviewLocationEntry( SC_PLOC_ROWHEADER, aPixelRect, aRange, sal_False, bRepRow ) );
245 }
246 
247 void ScPreviewLocationData::AddHeaderFooter( const Rectangle& rRect, sal_Bool bHeader, sal_Bool bLeft )
248 {
249     ScRange aRange;     //! ?
250     Rectangle aPixelRect( pWindow->LogicToPixel( rRect ) );
251 
252     ScPreviewLocationType eType = bHeader ?
253                 ( bLeft ? SC_PLOC_LEFTHEADER : SC_PLOC_RIGHTHEADER ) :
254                 ( bLeft ? SC_PLOC_LEFTFOOTER : SC_PLOC_RIGHTFOOTER );
255     aEntries.Insert( new ScPreviewLocationEntry( eType, aPixelRect, aRange, sal_False, sal_False ) );
256 }
257 
258 void ScPreviewLocationData::AddNoteMark( const Rectangle& rRect, const ScAddress& rPos )
259 {
260     ScRange aRange( rPos );
261     Rectangle aPixelRect( pWindow->LogicToPixel( rRect ) );
262     aEntries.Insert( new ScPreviewLocationEntry( SC_PLOC_NOTEMARK, aPixelRect, aRange, sal_False, sal_False ) );
263 }
264 
265 void ScPreviewLocationData::AddNoteText( const Rectangle& rRect, const ScAddress& rPos )
266 {
267     ScRange aRange( rPos );
268     Rectangle aPixelRect( pWindow->LogicToPixel( rRect ) );
269     aEntries.Insert( new ScPreviewLocationEntry( SC_PLOC_NOTETEXT, aPixelRect, aRange, sal_False, sal_False ) );
270 }
271 
272 //------------------------------------------------------------------
273 
274 void ScPreviewLocationData::GetDrawRange( sal_uInt16 nPos, Rectangle& rPixelRect, MapMode& rMapMode, sal_uInt8& rRangeId ) const
275 {
276     DBG_ASSERT( nPos < nDrawRanges, "wrong position" );
277     if ( nPos < nDrawRanges )
278     {
279         rPixelRect = aDrawRectangle[nPos];
280         rMapMode = aDrawMapMode[nPos];
281         rRangeId = aDrawRangeId[nPos];
282     }
283 }
284 
285 ScPreviewLocationEntry* lcl_GetEntryByAddress( const List& rEntries, const ScAddress& rPos, ScPreviewLocationType eType )
286 {
287     sal_uLong nCount = rEntries.Count();
288     for (sal_uLong nListPos=0; nListPos<nCount; nListPos++)
289     {
290         ScPreviewLocationEntry* pEntry = (ScPreviewLocationEntry*)rEntries.GetObject(nListPos);
291         if ( pEntry->eType == eType && pEntry->aCellRange.In( rPos ) )
292             return pEntry;
293     }
294     return NULL;
295 }
296 
297 //UNUSED2008-05  ScAddress ScPreviewLocationData::GetCellFromRange( const Size& rOffsetPixel, const ScRange& rRange ) const
298 //UNUSED2008-05  {
299 //UNUSED2008-05      const double nScaleX = HMM_PER_TWIPS;
300 //UNUSED2008-05      const double nScaleY = HMM_PER_TWIPS;
301 //UNUSED2008-05
302 //UNUSED2008-05      Size aOffsetLogic = pWindow->PixelToLogic( rOffsetPixel, aCellMapMode );
303 //UNUSED2008-05      SCTAB nTab = rRange.aStart.Tab();
304 //UNUSED2008-05
305 //UNUSED2008-05      long nPosX = 0;
306 //UNUSED2008-05      SCCOL nCol = rRange.aStart.Col();
307 //UNUSED2008-05      SCCOL nEndCol = rRange.aEnd.Col();
308 //UNUSED2008-05      while ( nCol <= nEndCol && nPosX < aOffsetLogic.Width() )
309 //UNUSED2008-05      {
310 //UNUSED2008-05          sal_uInt16 nDocW = pDoc->GetColWidth( nCol, nTab );
311 //UNUSED2008-05          if (nDocW)
312 //UNUSED2008-05              nPosX += (long) (nDocW * nScaleX);
313 //UNUSED2008-05          ++nCol;
314 //UNUSED2008-05      }
315 //UNUSED2008-05      if ( nCol > rRange.aStart.Col() )
316 //UNUSED2008-05          --nCol;
317 //UNUSED2008-05
318 //UNUSED2008-05      long nPosY = 0;
319 //UNUSED2008-05      ScCoupledCompressedArrayIterator< SCROW, sal_uInt8, sal_uInt16> aIter(
320 //UNUSED2008-05              pDoc->GetRowFlagsArray( nTab), rRange.aStart.Row(),
321 //UNUSED2008-05              rRange.aEnd.Row(), CR_HIDDEN, 0, pDoc->GetRowHeightArray( nTab));
322 //UNUSED2008-05      while ( aIter && nPosY < aOffsetLogic.Height() )
323 //UNUSED2008-05      {
324 //UNUSED2008-05          sal_uInt16 nDocH = *aIter;
325 //UNUSED2008-05          if (nDocH)
326 //UNUSED2008-05              nPosY += (long) (nDocH * nScaleY);
327 //UNUSED2008-05          ++aIter;
328 //UNUSED2008-05      }
329 //UNUSED2008-05      SCROW nRow = aIter.GetPos();
330 //UNUSED2008-05      if ( nRow > rRange.aStart.Row() )
331 //UNUSED2008-05          --nRow;
332 //UNUSED2008-05
333 //UNUSED2008-05      return ScAddress( nCol, nRow, nTab );
334 //UNUSED2008-05  }
335 
336 Rectangle ScPreviewLocationData::GetOffsetPixel( const ScAddress& rCellPos, const ScRange& rRange ) const
337 {
338     const double nScaleX = HMM_PER_TWIPS;
339     const double nScaleY = HMM_PER_TWIPS;
340     SCTAB nTab = rRange.aStart.Tab();
341 
342     long nPosX = 0;
343     SCCOL nEndCol = rCellPos.Col();
344     for (SCCOL nCol = rRange.aStart.Col(); nCol < nEndCol; nCol++)
345     {
346         sal_uInt16 nDocW = pDoc->GetColWidth( nCol, nTab );
347         if (nDocW)
348             nPosX += (long) (nDocW * nScaleX);
349     }
350     long nSizeX = (long) ( pDoc->GetColWidth( nEndCol, nTab ) * nScaleX );
351 
352     SCROW nEndRow = rCellPos.Row();
353     long nPosY = (long) pDoc->GetScaledRowHeight( rRange.aStart.Row(),
354             nEndRow, nTab, nScaleY);
355     long nSizeY = (long) ( pDoc->GetRowHeight( nEndRow, nTab ) * nScaleY );
356 
357     Size aOffsetLogic( nPosX, nPosY );
358     Size aSizeLogic( nSizeX, nSizeY );
359     Size aOffsetPixel = pWindow->LogicToPixel( aOffsetLogic, aCellMapMode );
360     Size aSizePixel = pWindow->LogicToPixel( aSizeLogic, aCellMapMode );
361 
362     return Rectangle( Point( aOffsetPixel.Width(), aOffsetPixel.Height() ), aSizePixel );
363 }
364 
365 sal_Bool ScPreviewLocationData::GetCellPosition( const ScAddress& rCellPos, Rectangle& rCellRect ) const
366 {
367     ScPreviewLocationEntry* pEntry = lcl_GetEntryByAddress( aEntries, rCellPos, SC_PLOC_CELLRANGE );
368     if ( pEntry )
369     {
370         Rectangle aOffsetRect = GetOffsetPixel( rCellPos, pEntry->aCellRange );
371         rCellRect = Rectangle( aOffsetRect.Left() + pEntry->aPixelRect.Left(),
372                                aOffsetRect.Top() + pEntry->aPixelRect.Top(),
373                                aOffsetRect.Right() + pEntry->aPixelRect.Left(),
374                                aOffsetRect.Bottom() + pEntry->aPixelRect.Top() );
375         return sal_True;
376     }
377     return sal_False;
378 }
379 
380 sal_Bool ScPreviewLocationData::HasCellsInRange( const Rectangle& rVisiblePixel ) const
381 {
382     sal_uLong nCount = aEntries.Count();
383     for (sal_uLong nListPos=0; nListPos<nCount; nListPos++)
384     {
385         ScPreviewLocationEntry* pEntry = (ScPreviewLocationEntry*)aEntries.GetObject(nListPos);
386         ScPreviewLocationType eType = pEntry->eType;
387         if ( eType == SC_PLOC_CELLRANGE || eType == SC_PLOC_COLHEADER || eType == SC_PLOC_ROWHEADER )
388             if ( pEntry->aPixelRect.IsOver( rVisiblePixel ) )
389                 return sal_True;
390     }
391     return sal_False;
392 }
393 
394 sal_Bool ScPreviewLocationData::GetHeaderPosition( Rectangle& rRect ) const
395 {
396     sal_uLong nCount = aEntries.Count();
397     for (sal_uLong nListPos=0; nListPos<nCount; nListPos++)
398     {
399         ScPreviewLocationEntry* pEntry = (ScPreviewLocationEntry*)aEntries.GetObject(nListPos);
400         if ( pEntry->eType == SC_PLOC_LEFTHEADER || pEntry->eType == SC_PLOC_RIGHTHEADER )
401         {
402             rRect = pEntry->aPixelRect;
403             return sal_True;
404         }
405     }
406     return sal_False;
407 }
408 
409 sal_Bool ScPreviewLocationData::GetFooterPosition( Rectangle& rRect ) const
410 {
411     sal_uLong nCount = aEntries.Count();
412     for (sal_uLong nListPos=0; nListPos<nCount; nListPos++)
413     {
414         ScPreviewLocationEntry* pEntry = (ScPreviewLocationEntry*)aEntries.GetObject(nListPos);
415         if ( pEntry->eType == SC_PLOC_LEFTFOOTER || pEntry->eType == SC_PLOC_RIGHTFOOTER )
416         {
417             rRect = pEntry->aPixelRect;
418             return sal_True;
419         }
420     }
421     return sal_False;
422 }
423 
424 sal_Bool ScPreviewLocationData::IsHeaderLeft() const
425 {
426     sal_uLong nCount = aEntries.Count();
427     for (sal_uLong nListPos=0; nListPos<nCount; nListPos++)
428     {
429         ScPreviewLocationEntry* pEntry = (ScPreviewLocationEntry*)aEntries.GetObject(nListPos);
430         if ( pEntry->eType == SC_PLOC_LEFTHEADER )
431             return sal_True;
432         if ( pEntry->eType == SC_PLOC_RIGHTHEADER )
433             return sal_False;
434     }
435     return sal_False;
436 }
437 
438 sal_Bool ScPreviewLocationData::IsFooterLeft() const
439 {
440     sal_uLong nCount = aEntries.Count();
441     for (sal_uLong nListPos=0; nListPos<nCount; nListPos++)
442     {
443         ScPreviewLocationEntry* pEntry = (ScPreviewLocationEntry*)aEntries.GetObject(nListPos);
444         if ( pEntry->eType == SC_PLOC_LEFTFOOTER )
445             return sal_True;
446         if ( pEntry->eType == SC_PLOC_RIGHTFOOTER )
447             return sal_False;
448     }
449     return sal_False;
450 }
451 
452 long ScPreviewLocationData::GetNoteCountInRange( const Rectangle& rVisiblePixel, sal_Bool bNoteMarks ) const
453 {
454     ScPreviewLocationType eType = bNoteMarks ? SC_PLOC_NOTEMARK : SC_PLOC_NOTETEXT;
455 
456     sal_uLong nRet = 0;
457     sal_uLong nCount = aEntries.Count();
458     for (sal_uLong nListPos=0; nListPos<nCount; nListPos++)
459     {
460         ScPreviewLocationEntry* pEntry = (ScPreviewLocationEntry*)aEntries.GetObject(nListPos);
461         if ( pEntry->eType == eType && pEntry->aPixelRect.IsOver( rVisiblePixel ) )
462             ++nRet;
463     }
464     return nRet;
465 }
466 
467 sal_Bool ScPreviewLocationData::GetNoteInRange( const Rectangle& rVisiblePixel, long nIndex, sal_Bool bNoteMarks,
468                                             ScAddress& rCellPos, Rectangle& rNoteRect ) const
469 {
470     ScPreviewLocationType eType = bNoteMarks ? SC_PLOC_NOTEMARK : SC_PLOC_NOTETEXT;
471 
472     sal_uLong nPos = 0;
473     sal_uLong nCount = aEntries.Count();
474     for (sal_uLong nListPos=0; nListPos<nCount; nListPos++)
475     {
476         ScPreviewLocationEntry* pEntry = (ScPreviewLocationEntry*)aEntries.GetObject(nListPos);
477         if ( pEntry->eType == eType && pEntry->aPixelRect.IsOver( rVisiblePixel ) )
478         {
479             if ( nPos == sal::static_int_cast<sal_uLong>(nIndex) )
480             {
481                 rCellPos = pEntry->aCellRange.aStart;
482                 rNoteRect = pEntry->aPixelRect;
483                 return sal_True;
484             }
485             ++nPos;
486         }
487     }
488     return sal_False;
489 }
490 
491 Rectangle ScPreviewLocationData::GetNoteInRangeOutputRect(const Rectangle& rVisiblePixel, sal_Bool bNoteMarks, const ScAddress& aCellPos) const
492 {
493     ScPreviewLocationType eType = bNoteMarks ? SC_PLOC_NOTEMARK : SC_PLOC_NOTETEXT;
494 
495     sal_uLong nPos = 0;
496     sal_uLong nCount = aEntries.Count();
497     for (sal_uLong nListPos=0; nListPos<nCount; nListPos++)
498     {
499         ScPreviewLocationEntry* pEntry = (ScPreviewLocationEntry*)aEntries.GetObject(nListPos);
500         if ( pEntry->eType == eType && pEntry->aPixelRect.IsOver( rVisiblePixel ) )
501         {
502             if ( aCellPos == pEntry->aCellRange.aStart )
503                 return pEntry->aPixelRect;
504             ++nPos;
505         }
506     }
507     return Rectangle();
508 }
509 
510 void ScPreviewLocationData::GetTableInfo( const Rectangle& rVisiblePixel, ScPreviewTableInfo& rInfo ) const
511 {
512     const double nScaleX = HMM_PER_TWIPS;
513     const double nScaleY = HMM_PER_TWIPS;
514 
515     // from left to right:
516     sal_Bool bHasHeaderCol = sal_False;
517     sal_Bool bHasRepCols   = sal_False;
518     sal_Bool bHasMainCols  = sal_False;
519     SCCOL nRepeatColStart = 0;
520     SCCOL nRepeatColEnd   = 0;
521     SCCOL nMainColStart   = 0;
522     SCCOL nMainColEnd     = 0;
523 
524     // from top to bottom:
525     sal_Bool bHasHeaderRow = sal_False;
526     sal_Bool bHasRepRows   = sal_False;
527     sal_Bool bHasMainRows  = sal_False;
528     SCROW nRepeatRowStart = 0;
529     SCROW nRepeatRowEnd   = 0;
530     SCROW nMainRowStart   = 0;
531     SCROW nMainRowEnd     = 0;
532 
533     Rectangle aHeaderRect, aRepeatRect, aMainRect;
534     SCTAB nTab = 0;
535 
536     sal_uLong nCount = aEntries.Count();
537     for (sal_uLong nListPos=0; nListPos<nCount; nListPos++)
538     {
539         ScPreviewLocationEntry* pEntry = (ScPreviewLocationEntry*)aEntries.GetObject(nListPos);
540         if ( pEntry->eType == SC_PLOC_CELLRANGE )
541         {
542             if ( pEntry->bRepeatCol )
543             {
544                 bHasRepCols = sal_True;
545                 nRepeatColStart = pEntry->aCellRange.aStart.Col();
546                 nRepeatColEnd = pEntry->aCellRange.aEnd.Col();
547                 aRepeatRect.Left() = pEntry->aPixelRect.Left();
548                 aRepeatRect.Right() = pEntry->aPixelRect.Right();
549             }
550             else
551             {
552                 bHasMainCols = sal_True;
553                 nMainColStart = pEntry->aCellRange.aStart.Col();
554                 nMainColEnd = pEntry->aCellRange.aEnd.Col();
555                 aMainRect.Left() = pEntry->aPixelRect.Left();
556                 aMainRect.Right() = pEntry->aPixelRect.Right();
557             }
558             if ( pEntry->bRepeatRow )
559             {
560                 bHasRepRows = sal_True;
561                 nRepeatRowStart = pEntry->aCellRange.aStart.Row();
562                 nRepeatRowEnd = pEntry->aCellRange.aEnd.Row();
563                 aRepeatRect.Top() = pEntry->aPixelRect.Top();
564                 aRepeatRect.Bottom() = pEntry->aPixelRect.Bottom();
565             }
566             else
567             {
568                 bHasMainRows = sal_True;
569                 nMainRowStart = pEntry->aCellRange.aStart.Row();
570                 nMainRowEnd = pEntry->aCellRange.aEnd.Row();
571                 aMainRect.Top() = pEntry->aPixelRect.Top();
572                 aMainRect.Bottom() = pEntry->aPixelRect.Bottom();
573             }
574             nTab = pEntry->aCellRange.aStart.Tab();     //! store separately?
575         }
576         else if ( pEntry->eType == SC_PLOC_ROWHEADER )
577         {
578             // row headers result in an additional column
579             bHasHeaderCol = sal_True;
580             aHeaderRect.Left() = pEntry->aPixelRect.Left();
581             aHeaderRect.Right() = pEntry->aPixelRect.Right();
582         }
583         else if ( pEntry->eType == SC_PLOC_COLHEADER )
584         {
585             // column headers result in an additional row
586             bHasHeaderRow = sal_True;
587             aHeaderRect.Top() = pEntry->aPixelRect.Top();
588             aHeaderRect.Bottom() = pEntry->aPixelRect.Bottom();
589         }
590     }
591 
592     //
593     //  get column info
594     //
595 
596     SCCOL nColCount = 0;
597     SCCOL nCol;
598     if ( bHasHeaderCol )
599         ++nColCount;
600     if ( bHasRepCols )
601         for ( nCol=nRepeatColStart; nCol<=nRepeatColEnd; nCol++ )
602             if (!pDoc->ColHidden(nCol, nTab))
603                 ++nColCount;
604     if ( bHasMainCols )
605         for ( nCol=nMainColStart; nCol<=nMainColEnd; nCol++ )
606             if (!pDoc->ColHidden(nCol, nTab))
607                 ++nColCount;
608 
609     if ( nColCount > 0 )
610     {
611         ScPreviewColRowInfo* pColInfo = new ScPreviewColRowInfo[ nColCount ];
612         SCCOL nColPos = 0;
613 
614         if ( bHasHeaderCol )
615         {
616             pColInfo[nColPos].Set( sal_True, 0, aHeaderRect.Left(), aHeaderRect.Right() );
617             ++nColPos;
618         }
619         if ( bHasRepCols )
620         {
621             long nPosX = 0;
622             for ( nCol=nRepeatColStart; nCol<=nRepeatColEnd; nCol++ )
623                 if (!pDoc->ColHidden(nCol, nTab))
624                 {
625                     sal_uInt16 nDocW = pDoc->GetColWidth( nCol, nTab );
626                     long nNextX = nPosX + (long) (nDocW * nScaleX);
627 
628                     long nPixelStart = pWindow->LogicToPixel( Size( nPosX, 0 ), aCellMapMode ).Width();
629                     long nPixelEnd = pWindow->LogicToPixel( Size( nNextX, 0 ), aCellMapMode ).Width() - 1;
630                     pColInfo[nColPos].Set( sal_False, nCol,
631                                                 aRepeatRect.Left() + nPixelStart,
632                                                 aRepeatRect.Left() + nPixelEnd );
633 
634                     nPosX = nNextX;
635                     ++nColPos;
636                 }
637         }
638         if ( bHasMainCols )
639         {
640             long nPosX = 0;
641             for ( nCol=nMainColStart; nCol<=nMainColEnd; nCol++ )
642                 if (!pDoc->ColHidden(nCol, nTab))
643                 {
644                     sal_uInt16 nDocW = pDoc->GetColWidth( nCol, nTab );
645                     long nNextX = nPosX + (long) (nDocW * nScaleX);
646 
647                     long nPixelStart = pWindow->LogicToPixel( Size( nPosX, 0 ), aCellMapMode ).Width();
648                     long nPixelEnd = pWindow->LogicToPixel( Size( nNextX, 0 ), aCellMapMode ).Width() - 1;
649                     pColInfo[nColPos].Set( sal_False, nCol,
650                                                 aMainRect.Left() + nPixelStart,
651                                                 aMainRect.Left() + nPixelEnd );
652 
653                     nPosX = nNextX;
654                     ++nColPos;
655                 }
656         }
657         rInfo.SetColInfo( nColCount, pColInfo );
658     }
659     else
660         rInfo.SetColInfo( 0, NULL );
661 
662     //
663     //  get row info
664     //
665 
666     SCROW nRowCount = 0;
667     if ( bHasHeaderRow )
668         ++nRowCount;
669     if ( bHasRepRows )
670         nRowCount += pDoc->CountVisibleRows(nRepeatRowStart, nRepeatRowEnd, nTab);
671     if ( bHasMainRows )
672         nRowCount += pDoc->CountVisibleRows(nMainRowStart, nMainRowEnd, nTab);
673 
674     if ( nRowCount > 0 )
675     {
676         ScPreviewColRowInfo* pRowInfo = new ScPreviewColRowInfo[ nRowCount ];
677         SCROW nRowPos = 0;
678 
679         if ( bHasHeaderRow )
680         {
681             pRowInfo[nRowPos].Set( sal_True, 0, aHeaderRect.Top(), aHeaderRect.Bottom() );
682             ++nRowPos;
683         }
684         if ( bHasRepRows )
685         {
686             long nPosY = 0;
687             for (SCROW nRow = nRepeatRowStart; nRow <= nRepeatRowEnd; ++nRow)
688             {
689                 if (pDoc->RowHidden(nRow, nTab))
690                     continue;
691 
692                 sal_uInt16 nDocH = pDoc->GetOriginalHeight( nRow, nTab );
693                 long nNextY = nPosY + (long) (nDocH * nScaleY);
694 
695                 long nPixelStart = pWindow->LogicToPixel( Size( 0, nPosY ), aCellMapMode ).Height();
696                 long nPixelEnd = pWindow->LogicToPixel( Size( 0, nNextY ), aCellMapMode ).Height() - 1;
697                 pRowInfo[nRowPos].Set( sal_False, nRow,
698                         aRepeatRect.Top() + nPixelStart,
699                         aRepeatRect.Top() + nPixelEnd );
700 
701                 nPosY = nNextY;
702                 ++nRowPos;
703             }
704         }
705         if ( bHasMainRows )
706         {
707             long nPosY = 0;
708             for (SCROW nRow = nMainRowStart; nRow <= nMainRowEnd; ++nRow)
709             {
710                 if (pDoc->RowHidden(nRow, nTab))
711                     continue;
712 
713                 sal_uInt16 nDocH = pDoc->GetOriginalHeight( nRow, nTab );
714                 long nNextY = nPosY + (long) (nDocH * nScaleY);
715 
716                 long nPixelStart = pWindow->LogicToPixel( Size( 0, nPosY ), aCellMapMode ).Height();
717                 long nPixelEnd = pWindow->LogicToPixel( Size( 0, nNextY ), aCellMapMode ).Height() - 1;
718                 pRowInfo[nRowPos].Set( sal_False, nRow,
719                         aMainRect.Top() + nPixelStart,
720                         aMainRect.Top() + nPixelEnd );
721 
722                 nPosY = nNextY;
723                 ++nRowPos;
724             }
725         }
726         rInfo.SetRowInfo( nRowCount, pRowInfo );
727     }
728     else
729         rInfo.SetRowInfo( 0, NULL );
730 
731     //
732     //  limit to visible area
733     //
734 
735     rInfo.SetTab( nTab );
736     rInfo.LimitToArea( rVisiblePixel );
737 }
738 
739 Rectangle ScPreviewLocationData::GetHeaderCellOutputRect(const Rectangle& rVisRect, const ScAddress& rCellPos, sal_Bool bColHeader) const
740 {
741     // first a stupid implementation
742     // NN says here should be done more
743     Rectangle aClipRect;
744     ScPreviewTableInfo aTableInfo;
745     GetTableInfo( rVisRect, aTableInfo );
746 
747     if ( (rCellPos.Col() >= 0) &&
748         (rCellPos.Row() >= 0) && (rCellPos.Col() < aTableInfo.GetCols()) &&
749         (rCellPos.Row() < aTableInfo.GetRows()) )
750     {
751         SCCOL nCol(0);
752         SCROW nRow(0);
753         if (bColHeader)
754             nCol = rCellPos.Col();
755         else
756             nRow = rCellPos.Row();
757         const ScPreviewColRowInfo& rColInfo = aTableInfo.GetColInfo()[nCol];
758         const ScPreviewColRowInfo& rRowInfo = aTableInfo.GetRowInfo()[nRow];
759 
760         if ( rColInfo.bIsHeader || rRowInfo.bIsHeader )
761             aClipRect = Rectangle( rColInfo.nPixelStart, rRowInfo.nPixelStart, rColInfo.nPixelEnd, rRowInfo.nPixelEnd );
762     }
763     return aClipRect;
764 }
765 
766 Rectangle ScPreviewLocationData::GetCellOutputRect(const ScAddress& rCellPos) const
767 {
768     // first a stupid implementation
769     // NN says here should be done more
770     Rectangle aRect;
771     GetCellPosition(rCellPos, aRect);
772     return aRect;
773 }
774 
775 // GetMainCellRange is used for links in PDF export
776 
777 sal_Bool ScPreviewLocationData::GetMainCellRange( ScRange& rRange, Rectangle& rPixRect ) const
778 {
779     sal_uLong nCount = aEntries.Count();
780     for (sal_uLong nListPos=0; nListPos<nCount; nListPos++)
781     {
782         ScPreviewLocationEntry* pEntry = (ScPreviewLocationEntry*)aEntries.GetObject(nListPos);
783         if ( pEntry->eType == SC_PLOC_CELLRANGE && !pEntry->bRepeatCol && !pEntry->bRepeatRow )
784         {
785             rRange = pEntry->aCellRange;
786             rPixRect = pEntry->aPixelRect;
787             return sal_True;
788         }
789     }
790     return sal_False;       // not found
791 }
792 
793