xref: /aoo41x/main/sc/source/ui/view/prevloc.cxx (revision cdf0e10c)
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