xref: /aoo41x/main/sc/source/ui/view/output.cxx (revision 4d7c9de0)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 
27 // INCLUDE ---------------------------------------------------------------
28 
29 #include <com/sun/star/embed/EmbedMisc.hpp>
30 
31 #include "scitems.hxx"
32 #include <editeng/boxitem.hxx>
33 #include <editeng/brshitem.hxx>
34 #include <editeng/editdata.hxx>
35 #include <svtools/colorcfg.hxx>
36 #include <svx/rotmodit.hxx>
37 #include <editeng/shaditem.hxx>
38 #include <editeng/svxfont.hxx>
39 #include <svx/svdoole2.hxx>
40 #include <tools/poly.hxx>
41 #include <vcl/svapp.hxx>
42 #include <vcl/pdfextoutdevdata.hxx>
43 #include <svtools/accessibilityoptions.hxx>
44 #include <svx/framelinkarray.hxx>
45 
46 #include "output.hxx"
47 #include "document.hxx"
48 #include "cell.hxx"
49 #include "attrib.hxx"
50 #include "patattr.hxx"
51 #include "docpool.hxx"
52 #include "tabvwsh.hxx"
53 #include "progress.hxx"
54 #include "pagedata.hxx"
55 #include "chgtrack.hxx"
56 #include "chgviset.hxx"
57 #include "viewutil.hxx"
58 #include "gridmerg.hxx"
59 #include "invmerge.hxx"
60 #include "fillinfo.hxx"
61 #include "scmod.hxx"
62 #include "appoptio.hxx"
63 #include "postit.hxx"
64 
65 #include <math.h>
66 
67 using namespace com::sun::star;
68 
69 // STATIC DATA -----------------------------------------------------------
70 
71 //	Farben fuer ChangeTracking "nach Autor" wie im Writer (swmodul1.cxx)
72 
73 #define SC_AUTHORCOLORCOUNT		9
74 
75 static ColorData nAuthorColor[ SC_AUTHORCOLORCOUNT ] = {
76 					COL_LIGHTRED, 		COL_LIGHTBLUE,		COL_LIGHTMAGENTA,
77 					COL_GREEN,			COL_RED,			COL_BLUE,
78 					COL_BROWN,			COL_MAGENTA,		COL_CYAN };
79 
80 //	Hilfsklasse, fuer die Farbzuordnung,
81 //	um nicht mehrfach hintereinander denselben User aus der Liste zu suchen
82 
83 //Move this class declare to Chgtrack.hxx
84 /*
85 class ScActionColorChanger
86 {
87 private:
88 	const ScAppOptions&		rOpt;
89 	const ScStrCollection&	rUsers;
90 	String					aLastUserName;
91 	sal_uInt16					nLastUserIndex;
92 	ColorData				nColor;
93 
94 public:
95 				ScActionColorChanger( const ScChangeTrack& rTrack );
96 				~ScActionColorChanger() {}
97 
98 	void		Update( const ScChangeAction& rAction );
99 	ColorData	GetColor() const	{ return nColor; }
100 };
101 */
102 
103 //------------------------------------------------------------------
104 
105 ScActionColorChanger::ScActionColorChanger( const ScChangeTrack& rTrack ) :
106 	rOpt( SC_MOD()->GetAppOptions() ),
107 	rUsers( rTrack.GetUserCollection() ),
108 	nLastUserIndex( 0 ),
109 	nColor( COL_BLACK )
110 {
111 }
112 
113 void ScActionColorChanger::Update( const ScChangeAction& rAction )
114 {
115 	ColorData nSetColor;
116 	switch (rAction.GetType())
117 	{
118 		case SC_CAT_INSERT_COLS:
119 		case SC_CAT_INSERT_ROWS:
120 		case SC_CAT_INSERT_TABS:
121 			nSetColor = rOpt.GetTrackInsertColor();
122 			break;
123 		case SC_CAT_DELETE_COLS:
124 		case SC_CAT_DELETE_ROWS:
125 		case SC_CAT_DELETE_TABS:
126 			nSetColor = rOpt.GetTrackDeleteColor();
127 			break;
128 		case SC_CAT_MOVE:
129 			nSetColor = rOpt.GetTrackMoveColor();
130 			break;
131 		default:
132 			nSetColor = rOpt.GetTrackContentColor();
133 			break;
134 	}
135 	if ( nSetColor != COL_TRANSPARENT )		// Farbe eingestellt
136 		nColor = nSetColor;
137 	else									// nach Autor
138 	{
139 		if ( rAction.GetUser() != aLastUserName )
140 		{
141 			aLastUserName = rAction.GetUser();
142 			StrData aData(aLastUserName);
143 			sal_uInt16 nIndex;
144 			if (!rUsers.Search(&aData, nIndex))
145 			{
146 				// empty string is possible if a name wasn't found while saving a 5.0 file
147 				DBG_ASSERT( aLastUserName.Len() == 0, "Author not found" );
148 				nIndex = 0;
149 			}
150 			nLastUserIndex = nIndex % SC_AUTHORCOLORCOUNT;
151 		}
152 		nColor = nAuthorColor[nLastUserIndex];
153 	}
154 }
155 
156 //==================================================================
157 
158 ScOutputData::ScOutputData( OutputDevice* pNewDev, ScOutputType eNewType,
159                             ScTableInfo& rTabInfo, ScDocument* pNewDoc,
160 							SCTAB nNewTab, long nNewScrX, long nNewScrY,
161 							SCCOL nNewX1, SCROW nNewY1, SCCOL nNewX2, SCROW nNewY2,
162 							double nPixelPerTwipsX, double nPixelPerTwipsY,
163 							const Fraction* pZoomX, const Fraction* pZoomY ) :
164 	pDev( pNewDev ),
165 	pRefDevice( pNewDev ),		// default is output device
166 	pFmtDevice( pNewDev ),		// default is output device
167     mrTabInfo( rTabInfo ),
168     pRowInfo( rTabInfo.mpRowInfo ),
169     nArrCount( rTabInfo.mnArrCount ),
170 	pDoc( pNewDoc ),
171 	nTab( nNewTab ),
172 	nScrX( nNewScrX ),
173 	nScrY( nNewScrY ),
174 	nX1( nNewX1 ),
175 	nY1( nNewY1 ),
176 	nX2( nNewX2 ),
177 	nY2( nNewY2 ),
178 	eType( eNewType ),
179 	nPPTX( nPixelPerTwipsX ),
180 	nPPTY( nPixelPerTwipsY ),
181 	pEditObj( NULL ),
182 	pViewShell( NULL ),
183 	pDrawView( NULL ), // #114135#
184 	bEditMode( sal_False ),
185 	bMetaFile( sal_False ),
186 	bSingleGrid( sal_False ),
187 	bPagebreakMode( sal_False ),
188 	bSolidBackground( sal_False ),
189 	bUseStyleColor( sal_False ),
190 	bForceAutoColor( SC_MOD()->GetAccessOptions().GetIsAutomaticFontColor() ),
191 	bSyntaxMode( sal_False ),
192 	pValueColor( NULL ),
193 	pTextColor( NULL ),
194 	pFormulaColor( NULL ),
195 	aGridColor( COL_BLACK ),
196 	bShowNullValues( sal_True ),
197 	bShowFormulas( sal_False ),
198 	bShowSpellErrors( sal_False ),
199 	bMarkClipped( sal_False ),			// sal_False fuer Drucker/Metafile etc.
200 	bSnapPixel( sal_False ),
201 	bAnyRotated( sal_False ),
202 	bAnyClipped( sal_False ),
203 	mpTargetPaintWindow(0) // #i74769# use SdrPaintWindow direct
204 {
205 	if (pZoomX)
206 		aZoomX = *pZoomX;
207 	else
208 		aZoomX = Fraction(1,1);
209 	if (pZoomY)
210 		aZoomY = *pZoomY;
211 	else
212 		aZoomY = Fraction(1,1);
213 
214 	nVisX1 = nX1;
215 	nVisY1 = nY1;
216 	nVisX2 = nX2;
217 	nVisY2 = nY2;
218 	pDoc->StripHidden( nVisX1, nVisY1, nVisX2, nVisY2, nTab );
219 
220 	nScrW = 0;
221 	for (SCCOL nX=nVisX1; nX<=nVisX2; nX++)
222 		nScrW += pRowInfo[0].pCellInfo[nX+1].nWidth;
223 
224 	nMirrorW = nScrW;
225 
226 	nScrH = 0;
227 	for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
228 		nScrH += pRowInfo[nArrY].nHeight;
229 
230 	bTabProtected = pDoc->IsTabProtected( nTab );
231 	nTabTextDirection = pDoc->GetEditTextDirection( nTab );
232 	bLayoutRTL = pDoc->IsLayoutRTL( nTab );
233 }
234 
235 ScOutputData::~ScOutputData()
236 {
237 	delete pValueColor;
238 	delete pTextColor;
239 	delete pFormulaColor;
240 }
241 
242 void ScOutputData::SetContentDevice( OutputDevice* pContentDev )
243 {
244     // use pContentDev instead of pDev where used
245 
246     if ( pRefDevice == pDev )
247         pRefDevice = pContentDev;
248     if ( pFmtDevice == pDev )
249         pFmtDevice = pContentDev;
250     pDev = pContentDev;
251 }
252 
253 void ScOutputData::SetMirrorWidth( long nNew )
254 {
255 	nMirrorW = nNew;
256 }
257 
258 void ScOutputData::SetGridColor( const Color& rColor )
259 {
260 	aGridColor = rColor;
261 }
262 
263 void ScOutputData::SetMarkClipped( sal_Bool bSet )
264 {
265 	bMarkClipped = bSet;
266 }
267 
268 void ScOutputData::SetShowNullValues( sal_Bool bSet )
269 {
270 	bShowNullValues = bSet;
271 }
272 
273 void ScOutputData::SetShowFormulas( sal_Bool bSet )
274 {
275 	bShowFormulas = bSet;
276 }
277 
278 void ScOutputData::SetShowSpellErrors( sal_Bool bSet )
279 {
280 	bShowSpellErrors = bSet;
281 }
282 
283 void ScOutputData::SetSnapPixel( sal_Bool bSet )
284 {
285 	bSnapPixel = bSet;
286 }
287 
288 void ScOutputData::SetEditCell( SCCOL nCol, SCROW nRow )
289 {
290 	nEditCol = nCol;
291 	nEditRow = nRow;
292 	bEditMode = sal_True;
293 }
294 
295 void ScOutputData::SetMetaFileMode( sal_Bool bNewMode )
296 {
297 	bMetaFile = bNewMode;
298 }
299 
300 void ScOutputData::SetSingleGrid( sal_Bool bNewMode )
301 {
302 	bSingleGrid = bNewMode;
303 }
304 
305 void ScOutputData::SetSyntaxMode( sal_Bool bNewMode )
306 {
307 	bSyntaxMode = bNewMode;
308 	if (bNewMode)
309 		if (!pValueColor)
310 		{
311 			pValueColor = new Color( COL_LIGHTBLUE );
312 			pTextColor = new Color( COL_BLACK );
313 			pFormulaColor = new Color( COL_GREEN );
314 		}
315 }
316 
317 void ScOutputData::DrawGrid( sal_Bool bGrid, sal_Bool bPage )
318 {
319 	SCCOL nX;
320 	SCROW nY;
321 	long nPosX;
322 	long nPosY;
323 	SCSIZE nArrY;
324     ScBreakType nBreak    = BREAK_NONE;
325     ScBreakType nBreakOld = BREAK_NONE;
326 
327 	sal_Bool bSingle;
328 	Color aPageColor;
329 	Color aManualColor;
330 
331 	if (bPagebreakMode)
332 		bPage = sal_False;			// keine "normalen" Umbrueche ueber volle Breite/Hoehe
333 
334 	//!	um den einen Pixel sieht das Metafile (oder die Druck-Ausgabe) anders aus
335 	//!	als die Bildschirmdarstellung, aber wenigstens passen Druck und Metafile zusammen
336 
337 	Size aOnePixel = pDev->PixelToLogic(Size(1,1));
338 	long nOneX = aOnePixel.Width();
339 	long nOneY = aOnePixel.Height();
340 	if (bMetaFile)
341 		nOneX = nOneY = 1;
342 
343 	long nLayoutSign = bLayoutRTL ? -1 : 1;
344 	long nSignedOneX = nOneX * nLayoutSign;
345 
346 	if ( eType == OUTTYPE_WINDOW )
347 	{
348         const svtools::ColorConfig& rColorCfg = SC_MOD()->GetColorConfig();
349         aPageColor.SetColor( rColorCfg.GetColorValue(svtools::CALCPAGEBREAKAUTOMATIC).nColor );
350         aManualColor.SetColor( rColorCfg.GetColorValue(svtools::CALCPAGEBREAKMANUAL).nColor );
351 	}
352 	else
353 	{
354 		aPageColor = aGridColor;
355 		aManualColor = aGridColor;
356 	}
357 
358 	pDev->SetLineColor( aGridColor );
359 	ScGridMerger aGrid( pDev, nOneX, nOneY );
360 
361 										//
362 										//	Vertikale Linien
363 										//
364 
365 	nPosX = nScrX;
366 	if ( bLayoutRTL )
367 		nPosX += nMirrorW - nOneX;
368 
369 	for (nX=nX1; nX<=nX2; nX++)
370 	{
371 		SCCOL nXplus1 = nX+1;
372 		SCCOL nXplus2 = nX+2;
373 		sal_uInt16 nWidth = pRowInfo[0].pCellInfo[nXplus1].nWidth;
374 		if (nWidth)
375 		{
376 			nPosX += nWidth * nLayoutSign;
377 
378 			if ( bPage )
379 			{
380 				//	Seitenumbrueche auch in ausgeblendeten suchen
381 				SCCOL nCol = nXplus1;
382 				while (nCol <= MAXCOL)
383 				{
384                     nBreak = pDoc->HasColBreak(nCol, nTab);
385                     bool bHidden = pDoc->ColHidden(nCol, nTab);
386 
387                     if ( nBreak || !bHidden )
388 						break;
389 					++nCol;
390 				}
391 
392                 if (nBreak != nBreakOld)
393 				{
394 					aGrid.Flush();
395                     pDev->SetLineColor( (nBreak & BREAK_MANUAL) ? aManualColor :
396                                         nBreak ? aPageColor : aGridColor );
397                     nBreakOld = nBreak;
398 				}
399 			}
400 
401 			sal_Bool bDraw = bGrid || nBreakOld;	// einfaches Gitter nur wenn eingestellt
402 
403 			//!	Mit dieser Abfrage wird zuviel weggelassen, wenn ein automatischer
404 			//!	Umbruch mitten in den Wiederholungsspalten liegt.
405 			//!	Dann lieber den aeusseren Rahmen zweimal ausgeben...
406 #if 0
407 			//	auf dem Drucker die Aussen-Linien weglassen (werden getrennt ausgegeben)
408 			if ( eType == OUTTYPE_PRINTER && !bMetaFile )
409 			{
410 				if ( nX == MAXCOL )
411 					bDraw = sal_False;
412                 else if (pDoc->HasColBreak(nXplus1, nTab))
413 					bDraw = sal_False;
414 			}
415 #endif
416 
417 			sal_uInt16 nWidthXplus2 = pRowInfo[0].pCellInfo[nXplus2].nWidth;
418 			bSingle = bSingleGrid;									//! in Fillinfo holen !!!!!
419 			if ( nX<MAXCOL && !bSingle )
420 			{
421 				bSingle = ( nWidthXplus2 == 0 );
422 				for (nArrY=1; nArrY+1<nArrCount && !bSingle; nArrY++)
423 				{
424 					if (pRowInfo[nArrY].pCellInfo[nXplus2].bHOverlapped)
425 						bSingle = sal_True;
426 					if (pRowInfo[nArrY].pCellInfo[nXplus1].bHideGrid)
427 						bSingle = sal_True;
428 				}
429 			}
430 
431 			if (bDraw)
432 			{
433 				if ( nX<MAXCOL && bSingle )
434 				{
435 					SCCOL nVisX = nXplus1;
436 					while ( nVisX < MAXCOL && !pDoc->GetColWidth(nVisX,nTab) )
437 						++nVisX;
438 
439 					nPosY = nScrY;
440 					long nNextY;
441 					for (nArrY=1; nArrY+1<nArrCount; nArrY++)
442 					{
443 						RowInfo* pThisRowInfo = &pRowInfo[nArrY];
444 						nNextY = nPosY + pThisRowInfo->nHeight;
445 
446 						sal_Bool bHOver = pThisRowInfo->pCellInfo[nXplus1].bHideGrid;
447 						if (!bHOver)
448 						{
449 							if (nWidthXplus2)
450 								bHOver = pThisRowInfo->pCellInfo[nXplus2].bHOverlapped;
451 							else
452 							{
453 								if (nVisX <= nX2)
454 									bHOver = pThisRowInfo->pCellInfo[nVisX+1].bHOverlapped;
455 								else
456 									bHOver = ((ScMergeFlagAttr*)pDoc->GetAttr(
457 												nVisX,pThisRowInfo->nRowNo,nTab,ATTR_MERGE_FLAG))
458 												->IsHorOverlapped();
459 								if (bHOver)
460 									bHOver = ((ScMergeFlagAttr*)pDoc->GetAttr(
461 												nXplus1,pThisRowInfo->nRowNo,nTab,ATTR_MERGE_FLAG))
462 												->IsHorOverlapped();
463 							}
464 						}
465 
466 						if (pThisRowInfo->bChanged && !bHOver)
467 						{
468 							//Point aStart( nPosX-nSignedOneX, nPosY );
469 							//Point aEnd( nPosX-nSignedOneX, nNextY-nOneY );
470 							//pDev->DrawLine( aStart, aEnd );
471 							aGrid.AddVerLine( nPosX-nSignedOneX, nPosY, nNextY-nOneY );
472 						}
473 						nPosY = nNextY;
474 					}
475 				}
476 				else
477 				{
478 					//Point aStart( nPosX-nSignedOneX, nScrY );
479 					//Point aEnd( nPosX-nSignedOneX, nScrY+nScrH-nOneY );
480 					//pDev->DrawLine( aStart, aEnd );
481 					aGrid.AddVerLine( nPosX-nSignedOneX, nScrY, nScrY+nScrH-nOneY );
482 				}
483 			}
484 		}
485 	}
486 
487 										//
488 										//	Horizontale Linien
489 										//
490 
491     bool bHiddenRow = true;
492     SCROW nHiddenEndRow = -1;
493 	nPosY = nScrY;
494 	for (nArrY=1; nArrY+1<nArrCount; nArrY++)
495 	{
496 		SCSIZE nArrYplus1 = nArrY+1;
497 		nY = pRowInfo[nArrY].nRowNo;
498 		SCROW nYplus1 = nY+1;
499 		nPosY += pRowInfo[nArrY].nHeight;
500 
501 		if (pRowInfo[nArrY].bChanged)
502 		{
503 			if ( bPage )
504 			{
505                 for (SCROW i = nYplus1; i <= MAXROW; ++i)
506                 {
507                     if (i > nHiddenEndRow)
508                         bHiddenRow = pDoc->RowHidden(i, nTab, nHiddenEndRow);
509                     /* TODO: optimize the row break thing for large hidden
510                      * segments where HasRowBreak() has to be called
511                      * nevertheless for each row, as a row break is drawn also
512                      * for hidden rows, above them. This needed to be done only
513                      * once per hidden segment, maybe giving manual breaks
514                      * priority. Something like GetNextRowBreak() and
515                      * GetNextManualRowBreak(). */
516                     nBreak = pDoc->HasRowBreak(i, nTab);
517                     if (!bHiddenRow || nBreak)
518                         break;
519                 }
520 
521                 if (nBreakOld != nBreak)
522 				{
523 					aGrid.Flush();
524 					pDev->SetLineColor( (nBreak & BREAK_MANUAL) ? aManualColor :
525                                         (nBreak) ? aPageColor : aGridColor );
526                     nBreakOld = nBreak;
527 				}
528 			}
529 
530 			sal_Bool bDraw = bGrid || nBreakOld;	// einfaches Gitter nur wenn eingestellt
531 
532 			//!	Mit dieser Abfrage wird zuviel weggelassen, wenn ein automatischer
533 			//!	Umbruch mitten in den Wiederholungszeilen liegt.
534 			//!	Dann lieber den aeusseren Rahmen zweimal ausgeben...
535 #if 0
536 			//	auf dem Drucker die Aussen-Linien weglassen (werden getrennt ausgegeben)
537 			if ( eType == OUTTYPE_PRINTER && !bMetaFile )
538 			{
539 				if ( nY == MAXROW )
540 					bDraw = sal_False;
541                 else if (pDoc->HasRowBreak(nYplus1, nTab))
542 					bDraw = sal_False;
543 			}
544 #endif
545 
546 			sal_Bool bNextYisNextRow = (pRowInfo[nArrYplus1].nRowNo == nYplus1);
547 			bSingle = !bNextYisNextRow;				// Hidden
548 			for (SCCOL i=nX1; i<=nX2 && !bSingle; i++)
549 			{
550 				if (pRowInfo[nArrYplus1].pCellInfo[i+1].bVOverlapped)
551 					bSingle = sal_True;
552 			}
553 
554 			if (bDraw)
555 			{
556 				if ( bSingle && nY<MAXROW )
557 				{
558 					SCROW nVisY = pRowInfo[nArrYplus1].nRowNo;
559 
560 					nPosX = nScrX;
561 					if ( bLayoutRTL )
562 						nPosX += nMirrorW - nOneX;
563 
564 					long nNextX;
565 					for (SCCOL i=nX1; i<=nX2; i++)
566 					{
567 						nNextX = nPosX + pRowInfo[0].pCellInfo[i+1].nWidth * nLayoutSign;
568 						if (nNextX != nPosX)								// sichtbar
569 						{
570 							sal_Bool bVOver;
571 							if ( bNextYisNextRow )
572 								bVOver = pRowInfo[nArrYplus1].pCellInfo[i+1].bVOverlapped;
573 							else
574 							{
575 								bVOver = ((ScMergeFlagAttr*)pDoc->GetAttr(
576 											i,nYplus1,nTab,ATTR_MERGE_FLAG))
577 											->IsVerOverlapped()
578 									&& 	 ((ScMergeFlagAttr*)pDoc->GetAttr(
579 											i,nVisY,nTab,ATTR_MERGE_FLAG))
580 											->IsVerOverlapped();
581 									//! nVisY aus Array ??
582 							}
583 							if (!bVOver)
584 							{
585 								//Point aStart( nPosX, nPosY-nOneY );
586 								//Point aEnd( nNextX-nSignedOneX, nPosY-nOneY );
587 								//pDev->DrawLine( aStart, aEnd );
588 								aGrid.AddHorLine( nPosX, nNextX-nSignedOneX, nPosY-nOneY );
589 							}
590 						}
591 						nPosX = nNextX;
592 					}
593 				}
594 				else
595 				{
596 					//Point aStart( nScrX, nPosY-nOneY );
597 					//Point aEnd( nScrX+nScrW-nOneX, nPosY-nOneY );
598 					//pDev->DrawLine( aStart, aEnd );
599 					aGrid.AddHorLine( nScrX, nScrX+nScrW-nOneX, nPosY-nOneY );
600 				}
601 			}
602 		}
603 	}
604 }
605 
606 //	----------------------------------------------------------------------------
607 
608 void ScOutputData::SetPagebreakMode( ScPageBreakData* pPageData )
609 {
610 	bPagebreakMode = sal_True;
611 	if (!pPageData)
612 		return;						// noch nicht initialisiert -> alles "nicht gedruckt"
613 
614 	//	gedruckten Bereich markieren
615 	//	(in FillInfo ist schon alles auf sal_False initialisiert)
616 
617     sal_uInt16 nRangeCount = sal::static_int_cast<sal_uInt16>(pPageData->GetCount());
618 	for (sal_uInt16 nPos=0; nPos<nRangeCount; nPos++)
619 	{
620 		ScRange aRange = pPageData->GetData( nPos ).GetPrintRange();
621 
622 		SCCOL nStartX = Max( aRange.aStart.Col(), nX1 );
623 		SCCOL nEndX   = Min( aRange.aEnd.Col(),   nX2 );
624 		SCROW nStartY = Max( aRange.aStart.Row(), nY1 );
625 		SCROW nEndY   = Min( aRange.aEnd.Row(),   nY2 );
626 
627 		for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
628 		{
629 			RowInfo* pThisRowInfo = &pRowInfo[nArrY];
630 			if ( pThisRowInfo->bChanged && pThisRowInfo->nRowNo >= nStartY &&
631 										   pThisRowInfo->nRowNo <= nEndY )
632 			{
633 				for (SCCOL nX=nStartX; nX<=nEndX; nX++)
634 					pThisRowInfo->pCellInfo[nX+1].bPrinted = sal_True;
635 			}
636 		}
637 	}
638 }
639 
640 void ScOutputData::FindRotated()
641 {
642 	//!	nRotMax speichern
643 	SCCOL nRotMax = nX2;
644 	for (SCSIZE nRotY=0; nRotY<nArrCount; nRotY++)
645 		if (pRowInfo[nRotY].nRotMaxCol != SC_ROTMAX_NONE && pRowInfo[nRotY].nRotMaxCol > nRotMax)
646 			nRotMax = pRowInfo[nRotY].nRotMaxCol;
647 
648 	for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++)
649 	{
650 		RowInfo* pThisRowInfo = &pRowInfo[nArrY];
651 		if ( pThisRowInfo->nRotMaxCol != SC_ROTMAX_NONE &&
652 			 ( pThisRowInfo->bChanged || pRowInfo[nArrY-1].bChanged ||
653 			   ( nArrY+1<nArrCount && pRowInfo[nArrY+1].bChanged ) ) )
654 		{
655 			SCROW nY = pThisRowInfo->nRowNo;
656 
657 			for (SCCOL nX=0; nX<=nRotMax; nX++)
658 			{
659 				CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
660 				const ScPatternAttr* pPattern = pInfo->pPatternAttr;
661 				const SfxItemSet* pCondSet = pInfo->pConditionSet;
662 
663                 if ( !pPattern && !pDoc->ColHidden(nX, nTab) )
664 				{
665 					pPattern = pDoc->GetPattern( nX, nY, nTab );
666 					pCondSet = pDoc->GetCondResult( nX, nY, nTab );
667 				}
668 
669 				if ( pPattern )		// Spalte nicht ausgeblendet
670 				{
671 					sal_uInt8 nDir = pPattern->GetRotateDir( pCondSet );
672 					if (nDir != SC_ROTDIR_NONE)
673 					{
674 						pInfo->nRotateDir = nDir;
675 						bAnyRotated = sal_True;
676 					}
677 				}
678 			}
679 		}
680 	}
681 }
682 
683 //	----------------------------------------------------------------------------
684 
685 sal_uInt16 lcl_GetRotateDir( ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab )
686 {
687 	const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
688 	const SfxItemSet* pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
689 
690 	sal_uInt16 nRet = SC_ROTDIR_NONE;
691 
692 	long nAttrRotate = pPattern->GetRotateVal( pCondSet );
693 	if ( nAttrRotate )
694 	{
695 		SvxRotateMode eRotMode = (SvxRotateMode)((const SvxRotateModeItem&)
696 					pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet)).GetValue();
697 
698 		if ( eRotMode == SVX_ROTATE_MODE_STANDARD )
699 			nRet = SC_ROTDIR_STANDARD;
700 		else if ( eRotMode == SVX_ROTATE_MODE_CENTER )
701 			nRet = SC_ROTDIR_CENTER;
702 		else if ( eRotMode == SVX_ROTATE_MODE_TOP || eRotMode == SVX_ROTATE_MODE_BOTTOM )
703 		{
704 			long nRot180 = nAttrRotate % 18000;		// 1/100 Grad
705 			if ( nRot180 == 9000 )
706 				nRet = SC_ROTDIR_CENTER;
707 			else if ( ( eRotMode == SVX_ROTATE_MODE_TOP && nRot180 < 9000 ) ||
708 					  ( eRotMode == SVX_ROTATE_MODE_BOTTOM && nRot180 > 9000 ) )
709 				nRet = SC_ROTDIR_LEFT;
710 			else
711 				nRet = SC_ROTDIR_RIGHT;
712 		}
713 	}
714 
715 	return nRet;
716 }
717 
718 const SvxBrushItem* lcl_FindBackground( ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab )
719 {
720 	const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
721 	const SfxItemSet* pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
722 	const SvxBrushItem* pBackground = (const SvxBrushItem*)
723 							&pPattern->GetItem( ATTR_BACKGROUND, pCondSet );
724 
725 	sal_uInt16 nDir = lcl_GetRotateDir( pDoc, nCol, nRow, nTab );
726 
727 	//	CENTER wird wie RIGHT behandelt...
728 	if ( nDir == SC_ROTDIR_RIGHT || nDir == SC_ROTDIR_CENTER )
729 	{
730 		//	Text geht nach rechts -> Hintergrund von links nehmen
731 		while ( nCol > 0 && lcl_GetRotateDir( pDoc, nCol, nRow, nTab ) == nDir &&
732 							pBackground->GetColor().GetTransparency() != 255 )
733 		{
734 			--nCol;
735 			pPattern = pDoc->GetPattern( nCol, nRow, nTab );
736 			pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
737 			pBackground = (const SvxBrushItem*)&pPattern->GetItem( ATTR_BACKGROUND, pCondSet );
738 		}
739 	}
740 	else if ( nDir == SC_ROTDIR_LEFT )
741 	{
742 		//	Text geht nach links -> Hintergrund von rechts nehmen
743 		while ( nCol < MAXCOL && lcl_GetRotateDir( pDoc, nCol, nRow, nTab ) == nDir &&
744 							pBackground->GetColor().GetTransparency() != 255 )
745 		{
746 			++nCol;
747 			pPattern = pDoc->GetPattern( nCol, nRow, nTab );
748 			pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
749 			pBackground = (const SvxBrushItem*)&pPattern->GetItem( ATTR_BACKGROUND, pCondSet );
750 		}
751 	}
752 
753 	return pBackground;
754 }
755 
756 //	----------------------------------------------------------------------------
757 
758 sal_Bool lcl_EqualBack( const RowInfo& rFirst, const RowInfo& rOther,
759 					SCCOL nX1, SCCOL nX2, sal_Bool bShowProt, sal_Bool bPagebreakMode )
760 {
761 	if ( rFirst.bChanged   != rOther.bChanged ||
762 		 rFirst.bEmptyBack != rOther.bEmptyBack )
763 		return sal_False;
764 
765 	SCCOL nX;
766 	if ( bShowProt )
767 	{
768 		for ( nX=nX1; nX<=nX2; nX++ )
769 		{
770 			const ScPatternAttr* pPat1 = rFirst.pCellInfo[nX+1].pPatternAttr;
771 			const ScPatternAttr* pPat2 = rOther.pCellInfo[nX+1].pPatternAttr;
772 			if ( !pPat1 || !pPat2 ||
773 					&pPat1->GetItem(ATTR_PROTECTION) != &pPat2->GetItem(ATTR_PROTECTION) )
774 				return sal_False;
775 		}
776 	}
777 	else
778 	{
779 		for ( nX=nX1; nX<=nX2; nX++ )
780 			if ( rFirst.pCellInfo[nX+1].pBackground != rOther.pCellInfo[nX+1].pBackground )
781 				return sal_False;
782 	}
783 
784 	if ( rFirst.nRotMaxCol != SC_ROTMAX_NONE || rOther.nRotMaxCol != SC_ROTMAX_NONE )
785 		for ( nX=nX1; nX<=nX2; nX++ )
786 			if ( rFirst.pCellInfo[nX+1].nRotateDir != rOther.pCellInfo[nX+1].nRotateDir )
787 				return sal_False;
788 
789 	if ( bPagebreakMode )
790 		for ( nX=nX1; nX<=nX2; nX++ )
791 			if ( rFirst.pCellInfo[nX+1].bPrinted != rOther.pCellInfo[nX+1].bPrinted )
792 				return sal_False;
793 
794 	return sal_True;
795 }
796 
797 void ScOutputData::DrawBackground()
798 {
799 	FindRotated();				//! von aussen ?
800 
801 	ScModule* pScMod = SC_MOD();
802 
803 	// used only if bSolidBackground is set (only for ScGridWindow):
804     Color aBgColor( pScMod->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor );
805 
806 	Rectangle aRect;
807 	Size aOnePixel = pDev->PixelToLogic(Size(1,1));
808 	long nOneX = aOnePixel.Width();
809 	long nOneY = aOnePixel.Height();
810 
811 	if (bMetaFile)
812 		nOneX = nOneY = 0;
813 
814 	long nLayoutSign = bLayoutRTL ? -1 : 1;
815 	long nSignedOneX = nOneX * nLayoutSign;
816 
817 	pDev->SetLineColor();
818 
819 	sal_Bool bShowProt = bSyntaxMode && pDoc->IsTabProtected(nTab);
820 	sal_Bool bDoAll = bShowProt || bPagebreakMode || bSolidBackground;
821 
822 	//	#105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed sal_True)
823 	sal_Bool bCellContrast = bUseStyleColor &&
824 			Application::GetSettings().GetStyleSettings().GetHighContrastMode();
825 
826 	long nPosY = nScrY;
827 	for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
828 	{
829 		RowInfo* pThisRowInfo = &pRowInfo[nArrY];
830 		long nRowHeight = pThisRowInfo->nHeight;
831 
832 		if ( pThisRowInfo->bChanged )
833 		{
834 			if ( ( ( pThisRowInfo->bEmptyBack ) || bSyntaxMode ) && !bDoAll )
835 			{
836 				//	nichts
837 			}
838 			else
839 			{
840 				// scan for rows with the same background:
841 				SCSIZE nSkip = 0;
842 				while ( nArrY+nSkip+2<nArrCount &&
843 						lcl_EqualBack( *pThisRowInfo, pRowInfo[nArrY+nSkip+1],
844 										nX1, nX2, bShowProt, bPagebreakMode ) )
845 				{
846 					++nSkip;
847 					nRowHeight += pRowInfo[nArrY+nSkip].nHeight;	// after incrementing
848 				}
849 
850 				long nPosX = nScrX;
851 				if ( bLayoutRTL )
852 					nPosX += nMirrorW - nOneX;
853 				aRect = Rectangle( nPosX,nPosY, nPosX,nPosY+nRowHeight-nOneY );
854 
855 				const SvxBrushItem* pOldBackground = NULL;
856 				const SvxBrushItem* pBackground;
857 				for (SCCOL nX=nX1; nX<=nX2; nX++)
858 				{
859 					CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
860 
861 					if (bCellContrast)
862 					{
863 						//	high contrast for cell borders and backgrounds -> empty background
864 						pBackground = ScGlobal::GetEmptyBrushItem();
865 					}
866 					else if (bShowProt)			// show cell protection in syntax mode
867 					{
868 						const ScPatternAttr* pP = pInfo->pPatternAttr;
869 						if (pP)
870 						{
871 							const ScProtectionAttr& rProt = (const ScProtectionAttr&)
872 																pP->GetItem(ATTR_PROTECTION);
873 							if (rProt.GetProtection() || rProt.GetHideCell())
874 								pBackground = ScGlobal::GetProtectedBrushItem();
875 							else
876 								pBackground = ScGlobal::GetEmptyBrushItem();
877 						}
878 						else
879 							pBackground = NULL;
880 					}
881 					else
882 						pBackground = pInfo->pBackground;
883 
884 					if ( bPagebreakMode && !pInfo->bPrinted )
885 						pBackground = ScGlobal::GetProtectedBrushItem();
886 
887 					if ( pInfo->nRotateDir > SC_ROTDIR_STANDARD &&
888 							pBackground->GetColor().GetTransparency() != 255 &&
889 							!bCellContrast )
890 					{
891 						SCROW nY = pRowInfo[nArrY].nRowNo;
892 						pBackground = lcl_FindBackground( pDoc, nX, nY, nTab );
893 					}
894 
895 					if ( pBackground != pOldBackground )
896 					{
897 						aRect.Right() = nPosX-nSignedOneX;
898 						if (pOldBackground)				// ==0 if hidden
899 						{
900 							Color aBackCol = pOldBackground->GetColor();
901 							if ( bSolidBackground && aBackCol.GetTransparency() )
902 								aBackCol = aBgColor;
903 							if ( !aBackCol.GetTransparency() )		//! partial transparency?
904 							{
905 								pDev->SetFillColor( aBackCol );
906 								pDev->DrawRect( aRect );
907 							}
908 						}
909 						aRect.Left() = nPosX;
910 						pOldBackground = pBackground;
911 					}
912 					nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
913 				}
914 				aRect.Right() = nPosX-nSignedOneX;
915 				if (pOldBackground)
916 				{
917 					Color aBackCol = pOldBackground->GetColor();
918 					if ( bSolidBackground && aBackCol.GetTransparency() )
919 						aBackCol = aBgColor;
920 					if ( !aBackCol.GetTransparency() )		//! partial transparency?
921 					{
922 						pDev->SetFillColor( aBackCol );
923 						pDev->DrawRect( aRect );
924 					}
925 				}
926 
927 				nArrY += nSkip;
928 			}
929 		}
930 		nPosY += nRowHeight;
931 	}
932 }
933 
934 void ScOutputData::DrawShadow()
935 {
936 	DrawExtraShadow( sal_False, sal_False, sal_False, sal_False );
937 }
938 
939 void ScOutputData::DrawExtraShadow(sal_Bool bLeft, sal_Bool bTop, sal_Bool bRight, sal_Bool bBottom)
940 {
941 	pDev->SetLineColor();
942 
943 	const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
944 	//	#105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed sal_True)
945 	sal_Bool bCellContrast = bUseStyleColor && rStyleSettings.GetHighContrastMode();
946 	Color aAutoTextColor;
947 	if ( bCellContrast )
948         aAutoTextColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
949 
950 	long nInitPosX = nScrX;
951 	if ( bLayoutRTL )
952 	{
953 		Size aOnePixel = pDev->PixelToLogic(Size(1,1));
954 		long nOneX = aOnePixel.Width();
955 		nInitPosX += nMirrorW - nOneX;
956 	}
957 	long nLayoutSign = bLayoutRTL ? -1 : 1;
958 
959 	long nPosY = nScrY - pRowInfo[0].nHeight;
960 	for (SCSIZE nArrY=0; nArrY<nArrCount; nArrY++)
961 	{
962 		sal_Bool bCornerY = ( nArrY == 0 ) || ( nArrY+1 == nArrCount );
963 		sal_Bool bSkipY = ( nArrY==0 && !bTop ) || ( nArrY+1 == nArrCount && !bBottom );
964 
965 		RowInfo* pThisRowInfo = &pRowInfo[nArrY];
966 		long nRowHeight = pThisRowInfo->nHeight;
967 
968 		if ( pThisRowInfo->bChanged && !bSkipY )
969 		{
970 			long nPosX = nInitPosX - pRowInfo[0].pCellInfo[nX1].nWidth * nLayoutSign;
971 			for (SCCOL nArrX=nX1; nArrX<=nX2+2; nArrX++)
972 			{
973 				sal_Bool bCornerX = ( nArrX==nX1 || nArrX==nX2+2 );
974 				sal_Bool bSkipX = ( nArrX==nX1 && !bLeft ) || ( nArrX==nX2+2 && !bRight );
975 
976 				for (sal_uInt16 nPass=0; nPass<2; nPass++)			// horizontal / vertikal
977 				{
978 					const SvxShadowItem* pAttr = nPass ?
979 							pThisRowInfo->pCellInfo[nArrX].pVShadowOrigin :
980 							pThisRowInfo->pCellInfo[nArrX].pHShadowOrigin;
981 					if ( pAttr && !bSkipX )
982 					{
983 						ScShadowPart ePart = nPass ?
984 								pThisRowInfo->pCellInfo[nArrX].eVShadowPart :
985 								pThisRowInfo->pCellInfo[nArrX].eHShadowPart;
986 
987 						sal_Bool bDo = sal_True;
988 						if ( (nPass==0 && bCornerX) || (nPass==1 && bCornerY) )
989 							if ( ePart != SC_SHADOW_CORNER )
990 								bDo = sal_False;
991 
992 						if (bDo)
993 						{
994 							long nThisWidth = pRowInfo[0].pCellInfo[nArrX].nWidth;
995 							long nMaxWidth = nThisWidth;
996 							if (!nMaxWidth)
997 							{
998 								//!	direction must depend on shadow location
999 								SCCOL nWx = nArrX;		// nX+1
1000 								while (nWx<nX2 && !pRowInfo[0].pCellInfo[nWx+1].nWidth)
1001 									++nWx;
1002 								nMaxWidth = pRowInfo[0].pCellInfo[nWx+1].nWidth;
1003 							}
1004 
1005 //							Rectangle aRect( Point(nPosX,nPosY),
1006 //											 Size( pRowInfo[0].pCellInfo[nArrX].nWidth,
1007 //													pRowInfo[nArrY].nHeight ) );
1008 
1009 							// rectangle is in logical orientation
1010 							Rectangle aRect( nPosX, nPosY,
1011 											 nPosX + ( nThisWidth - 1 ) * nLayoutSign,
1012 											 nPosY + pRowInfo[nArrY].nHeight - 1 );
1013 
1014 							long nSize = pAttr->GetWidth();
1015 							long nSizeX = (long)(nSize*nPPTX);
1016 							if (nSizeX >= nMaxWidth) nSizeX = nMaxWidth-1;
1017 							long nSizeY = (long)(nSize*nPPTY);
1018 							if (nSizeY >= nRowHeight) nSizeY = nRowHeight-1;
1019 
1020 							nSizeX *= nLayoutSign;		// used only to add to rectangle values
1021 
1022 							SvxShadowLocation eLoc = pAttr->GetLocation();
1023 							if ( bLayoutRTL )
1024 							{
1025 								//	Shadow location is specified as "visual" (right is always right),
1026 								//	so the attribute's location value is mirrored here and in FillInfo.
1027 								switch (eLoc)
1028 								{
1029 									case SVX_SHADOW_BOTTOMRIGHT: eLoc = SVX_SHADOW_BOTTOMLEFT;	break;
1030 									case SVX_SHADOW_BOTTOMLEFT:	 eLoc = SVX_SHADOW_BOTTOMRIGHT;	break;
1031 									case SVX_SHADOW_TOPRIGHT:	 eLoc = SVX_SHADOW_TOPLEFT;		break;
1032 									case SVX_SHADOW_TOPLEFT:	 eLoc = SVX_SHADOW_TOPRIGHT;	break;
1033                                     default:
1034                                     {
1035                                         // added to avoid warnings
1036                                     }
1037 								}
1038 							}
1039 
1040 							if (ePart == SC_SHADOW_HORIZ || ePart == SC_SHADOW_HSTART ||
1041 								ePart == SC_SHADOW_CORNER)
1042 							{
1043 								if (eLoc == SVX_SHADOW_TOPLEFT || eLoc == SVX_SHADOW_TOPRIGHT)
1044 									aRect.Top() = aRect.Bottom() - nSizeY;
1045 								else
1046 									aRect.Bottom() = aRect.Top() + nSizeY;
1047 							}
1048 							if (ePart == SC_SHADOW_VERT || ePart == SC_SHADOW_VSTART ||
1049 								ePart == SC_SHADOW_CORNER)
1050 							{
1051 								if (eLoc == SVX_SHADOW_TOPLEFT || eLoc == SVX_SHADOW_BOTTOMLEFT)
1052 									aRect.Left() = aRect.Right() - nSizeX;
1053 								else
1054 									aRect.Right() = aRect.Left() + nSizeX;
1055 							}
1056 							if (ePart == SC_SHADOW_HSTART)
1057 							{
1058 								if (eLoc == SVX_SHADOW_TOPLEFT || eLoc == SVX_SHADOW_BOTTOMLEFT)
1059 									aRect.Right() -= nSizeX;
1060 								else
1061 									aRect.Left() += nSizeX;
1062 							}
1063 							if (ePart == SC_SHADOW_VSTART)
1064 							{
1065 								if (eLoc == SVX_SHADOW_TOPLEFT || eLoc == SVX_SHADOW_TOPRIGHT)
1066 									aRect.Bottom() -= nSizeY;
1067 								else
1068 									aRect.Top() += nSizeY;
1069 							}
1070 
1071 							//! merge rectangles?
1072 							pDev->SetFillColor( bCellContrast ? aAutoTextColor : pAttr->GetColor() );
1073 							pDev->DrawRect( aRect );
1074 						}
1075 					}
1076 				}
1077 
1078 				nPosX += pRowInfo[0].pCellInfo[nArrX].nWidth * nLayoutSign;
1079 			}
1080 		}
1081 		nPosY += nRowHeight;
1082 	}
1083 }
1084 
1085 //
1086 //	Loeschen
1087 //
1088 
1089 void ScOutputData::DrawClear()
1090 {
1091 	Rectangle aRect;
1092 	Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1093 	long nOneX = aOnePixel.Width();
1094 	long nOneY = aOnePixel.Height();
1095 
1096 	// (called only for ScGridWindow)
1097     Color aBgColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor );
1098 
1099 	if (bMetaFile)
1100 		nOneX = nOneY = 0;
1101 
1102 	pDev->SetLineColor();
1103 
1104 	pDev->SetFillColor( aBgColor );
1105 
1106 	long nPosY = nScrY;
1107 	for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
1108 	{
1109 		RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1110 		long nRowHeight = pThisRowInfo->nHeight;
1111 
1112 		if ( pThisRowInfo->bChanged )
1113 		{
1114 			// scan for more rows which must be painted:
1115 			SCSIZE nSkip = 0;
1116 			while ( nArrY+nSkip+2<nArrCount && pRowInfo[nArrY+nSkip+1].bChanged )
1117 			{
1118 				++nSkip;
1119 				nRowHeight += pRowInfo[nArrY+nSkip].nHeight;	// after incrementing
1120 			}
1121 
1122 			aRect = Rectangle( Point( nScrX, nPosY ),
1123 					Size( nScrW+1-nOneX, nRowHeight+1-nOneY) );
1124 			pDev->DrawRect( aRect );
1125 
1126 			nArrY += nSkip;
1127 		}
1128 		nPosY += nRowHeight;
1129 	}
1130 }
1131 
1132 
1133 //
1134 //	Linien
1135 //
1136 
1137 long lclGetSnappedX( OutputDevice& rDev, long nPosX, bool bSnapPixel )
1138 {
1139     return (bSnapPixel && nPosX) ? rDev.PixelToLogic( rDev.LogicToPixel( Size( nPosX, 0 ) ) ).Width() : nPosX;
1140 }
1141 
1142 long lclGetSnappedY( OutputDevice& rDev, long nPosY, bool bSnapPixel )
1143 {
1144     return (bSnapPixel && nPosY) ? rDev.PixelToLogic( rDev.LogicToPixel( Size( 0, nPosY ) ) ).Height() : nPosY;
1145 }
1146 
1147 size_t lclGetArrayColFromCellInfoX( sal_uInt16 nCellInfoX, sal_uInt16 nCellInfoFirstX, sal_uInt16 nCellInfoLastX, bool bRTL )
1148 {
1149     return static_cast< size_t >( bRTL ? (nCellInfoLastX + 2 - nCellInfoX) : (nCellInfoX - nCellInfoFirstX) );
1150 }
1151 
1152 void ScOutputData::DrawFrame()
1153 {
1154 	sal_uLong nOldDrawMode = pDev->GetDrawMode();
1155 
1156 	Color aSingleColor;
1157 	sal_Bool bUseSingleColor = sal_False;
1158 	const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1159 	//	#105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed sal_True)
1160 	sal_Bool bCellContrast = bUseStyleColor && rStyleSettings.GetHighContrastMode();
1161 
1162 	//	#107519# if a Calc OLE object is embedded in Draw/Impress, the VCL DrawMode is used
1163 	//	for display mode / B&W printing. The VCL DrawMode handling doesn't work for lines
1164 	//	that are drawn with DrawRect, so if the line/background bits are set, the DrawMode
1165 	//	must be reset and the border colors handled here.
1166 
1167 	if ( ( nOldDrawMode & DRAWMODE_WHITEFILL ) && ( nOldDrawMode & DRAWMODE_BLACKLINE ) )
1168 	{
1169 		pDev->SetDrawMode( nOldDrawMode & (~DRAWMODE_WHITEFILL) );
1170 		aSingleColor.SetColor( COL_BLACK );
1171 		bUseSingleColor = sal_True;
1172 	}
1173 	else if ( ( nOldDrawMode & DRAWMODE_SETTINGSFILL ) && ( nOldDrawMode & DRAWMODE_SETTINGSLINE ) )
1174 	{
1175 		pDev->SetDrawMode( nOldDrawMode & (~DRAWMODE_SETTINGSFILL) );
1176 		aSingleColor = rStyleSettings.GetWindowTextColor();		// same as used in VCL for DRAWMODE_SETTINGSLINE
1177 		bUseSingleColor = sal_True;
1178 	}
1179 	else if ( bCellContrast )
1180 	{
1181 		aSingleColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
1182 		bUseSingleColor = sal_True;
1183 	}
1184 
1185     const Color* pForceColor = bUseSingleColor ? &aSingleColor : 0;
1186 
1187 	if (bAnyRotated)
1188 		DrawRotatedFrame( pForceColor );		// removes the lines that must not be painted here
1189 
1190 	long nInitPosX = nScrX;
1191 	if ( bLayoutRTL )
1192 	{
1193 		Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1194 		long nOneX = aOnePixel.Width();
1195 		nInitPosX += nMirrorW - nOneX;
1196 	}
1197 	long nLayoutSign = bLayoutRTL ? -1 : 1;
1198 
1199 
1200     // *** set column and row sizes of the frame border array ***
1201 
1202     svx::frame::Array& rArray = mrTabInfo.maArray;
1203     size_t nColCount = rArray.GetColCount();
1204     size_t nRowCount = rArray.GetRowCount();
1205 
1206     // row heights
1207 
1208     // row 0 is not visible (dummy for borders from top) - subtract its height from initial position
1209     // subtract 1 unit more, because position 0 is first *in* cell, grid line is one unit before
1210     long nOldPosY = nScrY - 1 - pRowInfo[ 0 ].nHeight;
1211     long nOldSnapY = lclGetSnappedY( *pDev, nOldPosY, bSnapPixel );
1212     rArray.SetYOffset( nOldSnapY );
1213     for( size_t nRow = 0; nRow < nRowCount; ++nRow )
1214     {
1215         long nNewPosY = nOldPosY + pRowInfo[ nRow ].nHeight;
1216         long nNewSnapY = lclGetSnappedY( *pDev, nNewPosY, bSnapPixel );
1217         rArray.SetRowHeight( nRow, nNewSnapY - nOldSnapY );
1218         nOldPosY = nNewPosY;
1219         nOldSnapY = nNewSnapY;
1220     }
1221 
1222     // column widths
1223 
1224     // column nX1 is not visible (dummy for borders from left) - subtract its width from initial position
1225     // subtract 1 unit more, because position 0 is first *in* cell, grid line is one unit above
1226     long nOldPosX = nInitPosX - nLayoutSign * (1 + pRowInfo[ 0 ].pCellInfo[ nX1 ].nWidth);
1227     long nOldSnapX = lclGetSnappedX( *pDev, nOldPosX, bSnapPixel );
1228     // set X offset for left-to-right sheets; for right-to-left sheets this is done after for() loop
1229     if( !bLayoutRTL )
1230         rArray.SetXOffset( nOldSnapX );
1231     for( sal_uInt16 nInfoIdx = nX1; nInfoIdx <= nX2 + 2; ++nInfoIdx )
1232     {
1233         size_t nCol = lclGetArrayColFromCellInfoX( nInfoIdx, nX1, nX2, bLayoutRTL );
1234         long nNewPosX = nOldPosX + pRowInfo[ 0 ].pCellInfo[ nInfoIdx ].nWidth * nLayoutSign;
1235         long nNewSnapX = lclGetSnappedX( *pDev, nNewPosX, bSnapPixel );
1236         rArray.SetColWidth( nCol, Abs( nNewSnapX - nOldSnapX ) );
1237         nOldPosX = nNewPosX;
1238         nOldSnapX = nNewSnapX;
1239     }
1240     if( bLayoutRTL )
1241         rArray.SetXOffset( nOldSnapX );
1242 
1243     // *** draw the array ***
1244 
1245     size_t nFirstCol = 1;
1246     size_t nFirstRow = 1;
1247     size_t nLastCol = nColCount - 2;
1248     size_t nLastRow = nRowCount - 2;
1249 
1250     if( mrTabInfo.mbPageMode )
1251         rArray.SetClipRange( nFirstCol, nFirstRow, nLastCol, nLastRow );
1252 
1253     // draw only rows with set RowInfo::bChanged flag
1254     size_t nRow1 = nFirstRow;
1255     while( nRow1 <= nLastRow )
1256     {
1257         while( (nRow1 <= nLastRow) && !pRowInfo[ nRow1 ].bChanged ) ++nRow1;
1258         if( nRow1 <= nLastRow )
1259         {
1260             size_t nRow2 = nRow1;
1261             while( (nRow2 + 1 <= nLastRow) && pRowInfo[ nRow2 + 1 ].bChanged ) ++nRow2;
1262             rArray.DrawRange( *pDev, nFirstCol, nRow1, nLastCol, nRow2, pForceColor );
1263             nRow1 = nRow2 + 1;
1264         }
1265     }
1266 
1267 	pDev->SetDrawMode(nOldDrawMode);
1268 }
1269 
1270 //	-------------------------------------------------------------------------
1271 
1272 //	Linie unter der Zelle
1273 
1274 const SvxBorderLine* lcl_FindHorLine( ScDocument* pDoc,
1275 						SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nRotDir,
1276 						sal_Bool bTopLine )
1277 {
1278 	if ( nRotDir != SC_ROTDIR_LEFT && nRotDir != SC_ROTDIR_RIGHT )
1279 		return NULL;
1280 
1281 	sal_Bool bFound = sal_False;
1282 	while (!bFound)
1283 	{
1284 		if ( nRotDir == SC_ROTDIR_LEFT )
1285 		{
1286 			//	Text nach links -> Linie von rechts
1287 			if ( nCol < MAXCOL )
1288 				++nCol;
1289 			else
1290 				return NULL;				// war nix
1291 		}
1292 		else
1293 		{
1294 			//	Text nach rechts -> Linie von links
1295 			if ( nCol > 0 )
1296 				--nCol;
1297 			else
1298 				return NULL;				// war nix
1299 		}
1300 		const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
1301 		const SfxItemSet* pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
1302 		if ( !pPattern->GetRotateVal( pCondSet ) ||
1303 				((const SvxRotateModeItem&)pPattern->GetItem(
1304 					ATTR_ROTATE_MODE, pCondSet)).GetValue() == SVX_ROTATE_MODE_STANDARD )
1305 			bFound = sal_True;
1306 	}
1307 
1308 	if (bTopLine)
1309 		--nRow;
1310 	const SvxBorderLine* pThisBottom;
1311 	if ( ValidRow(nRow) )
1312 		pThisBottom = ((const SvxBoxItem*)pDoc->GetAttr( nCol, nRow, nTab, ATTR_BORDER ))->GetBottom();
1313 	else
1314 		pThisBottom = NULL;
1315 	const SvxBorderLine* pNextTop;
1316 	if ( nRow < MAXROW )
1317 		pNextTop = ((const SvxBoxItem*)pDoc->GetAttr( nCol, nRow+1, nTab, ATTR_BORDER ))->GetTop();
1318 	else
1319 		pNextTop = NULL;
1320 
1321 	if ( ScHasPriority( pThisBottom, pNextTop ) )
1322 		return pThisBottom;
1323 	else
1324 		return pNextTop;
1325 }
1326 
1327 // lcl_HorizLine muss genau zu normal ausgegebenen Linien passen!
1328 
1329 void lcl_HorizLine( OutputDevice& rDev, const Point& rLeft, const Point& rRight,
1330                     const svx::frame::Style& rLine, const Color* pForceColor )
1331 {
1332     svx::frame::DrawHorFrameBorder( rDev, rLeft, rRight, rLine, pForceColor );
1333 }
1334 
1335 void lcl_VertLineEnds( OutputDevice& rDev, const Point& rTop, const Point& rBottom,
1336         const Color& rColor, long nXOffs, long nWidth,
1337         const svx::frame::Style& rTopLine, const svx::frame::Style& rBottomLine )
1338 {
1339     rDev.SetLineColor(rColor);              // PEN_NULL ???
1340     rDev.SetFillColor(rColor);
1341 
1342 	//	Position oben/unten muss unabhaengig von der Liniendicke sein,
1343 	//	damit der Winkel stimmt (oder X-Position auch anpassen)
1344 	long nTopPos = rTop.Y();
1345 	long nBotPos = rBottom.Y();
1346 
1347     long nTopLeft = rTop.X() + nXOffs;
1348     long nTopRight = nTopLeft + nWidth - 1;
1349 
1350     long nBotLeft = rBottom.X() + nXOffs;
1351     long nBotRight = nBotLeft + nWidth - 1;
1352 
1353 	//	oben abschliessen
1354 
1355     if ( rTopLine.Prim() )
1356 	{
1357         long nLineW = rTopLine.GetWidth();
1358         if (nLineW >= 2)
1359 		{
1360 			Point aTriangle[3];
1361 			aTriangle[0] = Point( nTopLeft, nTopPos );		// wie aPoints[0]
1362 			aTriangle[1] = Point( nTopRight, nTopPos );		// wie aPoints[1]
1363             aTriangle[2] = Point( rTop.X(), nTopPos - (nLineW - 1) / 2 );
1364 			Polygon aTriPoly( 3, aTriangle );
1365             rDev.DrawPolygon( aTriPoly );
1366 		}
1367 	}
1368 
1369 	//	unten abschliessen
1370 
1371     if ( rBottomLine.Prim() )
1372 	{
1373         long nLineW = rBottomLine.GetWidth();
1374         if (nLineW >= 2)
1375 		{
1376 			Point aTriangle[3];
1377 			aTriangle[0] = Point( nBotLeft, nBotPos );		// wie aPoints[3]
1378 			aTriangle[1] = Point( nBotRight, nBotPos );		// wie aPoints[2]
1379             aTriangle[2] = Point( rBottom.X(), nBotPos - (nLineW - 1) / 2 + nLineW - 1 );
1380 			Polygon aTriPoly( 3, aTriangle );
1381             rDev.DrawPolygon( aTriPoly );
1382 		}
1383 	}
1384 }
1385 
1386 void lcl_VertLine( OutputDevice& rDev, const Point& rTop, const Point& rBottom,
1387                     const svx::frame::Style& rLine,
1388                     const svx::frame::Style& rTopLine, const svx::frame::Style& rBottomLine,
1389                     const Color* pForceColor )
1390 {
1391     if( rLine.Prim() )
1392     {
1393         svx::frame::DrawVerFrameBorderSlanted( rDev, rTop, rBottom, rLine, pForceColor );
1394 
1395         svx::frame::Style aScaled( rLine );
1396         aScaled.ScaleSelf( 1.0 / cos( svx::frame::GetVerDiagAngle( rTop, rBottom ) ) );
1397         if( pForceColor )
1398             aScaled.SetColor( *pForceColor );
1399 
1400         long nXOffs = (aScaled.GetWidth() - 1) / -2L;
1401 
1402         lcl_VertLineEnds( rDev, rTop, rBottom, aScaled.GetColor(),
1403             nXOffs, aScaled.Prim(), rTopLine, rBottomLine );
1404 
1405         if( aScaled.Secn() )
1406             lcl_VertLineEnds( rDev, rTop, rBottom, aScaled.GetColor(),
1407                 nXOffs + aScaled.Prim() + aScaled.Dist(), aScaled.Secn(), rTopLine, rBottomLine );
1408     }
1409 }
1410 
1411 void ScOutputData::DrawRotatedFrame( const Color* pForceColor )
1412 {
1413 	//!	nRotMax speichern
1414 	SCCOL nRotMax = nX2;
1415 	for (SCSIZE nRotY=0; nRotY<nArrCount; nRotY++)
1416 		if (pRowInfo[nRotY].nRotMaxCol != SC_ROTMAX_NONE && pRowInfo[nRotY].nRotMaxCol > nRotMax)
1417 			nRotMax = pRowInfo[nRotY].nRotMaxCol;
1418 
1419 	const ScPatternAttr* pPattern;
1420 	const SfxItemSet*	 pCondSet;
1421 
1422 	const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1423 	//	#105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed sal_True)
1424 	sal_Bool bCellContrast = bUseStyleColor && rStyleSettings.GetHighContrastMode();
1425 
1426 	//	color (pForceColor) is determined externally, including DrawMode changes
1427 
1428 	long nInitPosX = nScrX;
1429 	if ( bLayoutRTL )
1430 	{
1431 		Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1432 		long nOneX = aOnePixel.Width();
1433 		nInitPosX += nMirrorW - nOneX;
1434 	}
1435 	long nLayoutSign = bLayoutRTL ? -1 : 1;
1436 
1437 	Rectangle aClipRect( Point(nScrX, nScrY), Size(nScrW, nScrH) );
1438 	if (bMetaFile)
1439 	{
1440 		pDev->Push();
1441 		pDev->IntersectClipRegion( aClipRect );
1442 	}
1443 	else
1444 		pDev->SetClipRegion( Region( aClipRect ) );
1445 
1446     svx::frame::Array& rArray = mrTabInfo.maArray;
1447 
1448 	long nPosY = nScrY;
1449 	for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++)
1450 	{
1451 		//	Rotated wird auch 1 Zeile ueber/unter Changed gezeichnet, falls Teile
1452 		//	in die Zeile hineinragen...
1453 
1454         RowInfo& rPrevRowInfo = pRowInfo[nArrY-1];
1455         RowInfo& rThisRowInfo = pRowInfo[nArrY];
1456         RowInfo& rNextRowInfo = pRowInfo[nArrY+1];
1457 
1458         size_t nRow = static_cast< size_t >( nArrY );
1459 
1460         long nRowHeight = rThisRowInfo.nHeight;
1461         if ( rThisRowInfo.nRotMaxCol != SC_ROTMAX_NONE &&
1462              ( rThisRowInfo.bChanged || rPrevRowInfo.bChanged ||
1463                ( nArrY+1<nArrCount && rNextRowInfo.bChanged ) ) )
1464 		{
1465             SCROW nY = rThisRowInfo.nRowNo;
1466 			long nPosX = 0;
1467 			SCCOL nX;
1468 			for (nX=0; nX<=nRotMax; nX++)
1469 			{
1470 				if (nX==nX1) nPosX = nInitPosX;		// calculated individually for preceding positions
1471 
1472                 sal_uInt16 nArrX = nX + 1;
1473 
1474                 CellInfo* pInfo = &rThisRowInfo.pCellInfo[nArrX];
1475                 long nColWidth = pRowInfo[0].pCellInfo[nArrX].nWidth;
1476 				if ( pInfo->nRotateDir > SC_ROTDIR_STANDARD &&
1477 						!pInfo->bHOverlapped && !pInfo->bVOverlapped )
1478 				{
1479 					pPattern = pInfo->pPatternAttr;
1480 					pCondSet = pInfo->pConditionSet;
1481 					if (!pPattern)
1482 					{
1483 						pPattern = pDoc->GetPattern( nX, nY, nTab );
1484 						pInfo->pPatternAttr = pPattern;
1485 						pCondSet = pDoc->GetCondResult( nX, nY, nTab );
1486 						pInfo->pConditionSet = pCondSet;
1487 					}
1488 
1489 					//!	LastPattern etc.
1490 
1491 					long nAttrRotate = pPattern->GetRotateVal( pCondSet );
1492 					SvxRotateMode eRotMode = (SvxRotateMode)((const SvxRotateModeItem&)
1493 									pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet)).GetValue();
1494 
1495 					if ( nAttrRotate )
1496 					{
1497 						if (nX<nX1)			// negative Position berechnen
1498 						{
1499 							nPosX = nInitPosX;
1500 							SCCOL nCol = nX1;
1501 							while (nCol > nX)
1502 							{
1503 								--nCol;
1504 								nPosX -= nLayoutSign * (long) pRowInfo[0].pCellInfo[nCol+1].nWidth;
1505 							}
1506 						}
1507 
1508 						//	Startposition minus 1, damit auch schraege Hintergruende
1509 						//	zur Umrandung passen (Umrandung ist auf dem Gitter)
1510 
1511 						long nTop = nPosY - 1;
1512 						long nBottom = nPosY + nRowHeight - 1;
1513 						long nTopLeft = nPosX - nLayoutSign;
1514 						long nTopRight = nPosX + ( nColWidth - 1 ) * nLayoutSign;
1515 						long nBotLeft = nTopLeft;
1516 						long nBotRight = nTopRight;
1517 
1518 						//	inclusion of the sign here hasn't been decided yet
1519 						//	(if not, the extension of the non-rotated background must also be changed)
1520 						double nRealOrient = nLayoutSign * nAttrRotate * F_PI18000;		// 1/100th degrees
1521 						double nCos = cos( nRealOrient );
1522 						double nSin = sin( nRealOrient );
1523 						//!	begrenzen !!!
1524 						long nSkew = (long) ( nRowHeight * nCos / nSin );
1525 
1526 						switch (eRotMode)
1527 						{
1528 							case SVX_ROTATE_MODE_BOTTOM:
1529 								nTopLeft += nSkew;
1530 								nTopRight += nSkew;
1531 								break;
1532 							case SVX_ROTATE_MODE_CENTER:
1533 								nSkew /= 2;
1534 								nTopLeft += nSkew;
1535 								nTopRight += nSkew;
1536 								nBotLeft -= nSkew;
1537 								nBotRight -= nSkew;
1538 								break;
1539 							case SVX_ROTATE_MODE_TOP:
1540 								nBotLeft -= nSkew;
1541 								nBotRight -= nSkew;
1542 								break;
1543                             default:
1544                             {
1545                                 // added to avoid warnings
1546                             }
1547 						}
1548 
1549 						Point aPoints[4];
1550 						aPoints[0] = Point( nTopLeft, nTop );
1551 						aPoints[1] = Point( nTopRight, nTop );
1552 						aPoints[2] = Point( nBotRight, nBottom );
1553 						aPoints[3] = Point( nBotLeft, nBottom );
1554 
1555 						const SvxBrushItem* pBackground = pInfo->pBackground;
1556 						if (!pBackground)
1557 							pBackground = (const SvxBrushItem*) &pPattern->GetItem(
1558 												ATTR_BACKGROUND, pCondSet );
1559 						if (bCellContrast)
1560 						{
1561 							//	high contrast for cell borders and backgrounds -> empty background
1562 							pBackground = ScGlobal::GetEmptyBrushItem();
1563 						}
1564 						const Color& rColor = pBackground->GetColor();
1565 						if ( rColor.GetTransparency() != 255 )
1566 						{
1567 							//	#95879# draw background only for the changed row itself
1568 							//	(background doesn't extend into other cells).
1569 							//	For the borders (rotated and normal), clipping should be
1570 							//	set if the row isn't changed, but at least the borders
1571 							//	don't cover the cell contents.
1572                             if ( rThisRowInfo.bChanged )
1573 							{
1574 								Polygon aPoly( 4, aPoints );
1575 
1576 								//	ohne Pen wird bei DrawPolygon rechts und unten
1577 								//	ein Pixel weggelassen...
1578 								if ( rColor.GetTransparency() == 0 )
1579 									pDev->SetLineColor(rColor);
1580 								else
1581 									pDev->SetLineColor();
1582 								pDev->SetFillColor(rColor);
1583 								pDev->DrawPolygon( aPoly );
1584 							}
1585 						}
1586 
1587                         svx::frame::Style aTopLine, aBottomLine, aLeftLine, aRightLine;
1588 
1589 						if ( nX < nX1 || nX > nX2 )		// Attribute in FillInfo nicht gesetzt
1590 						{
1591 							//!	Seitengrenzen fuer Druck beruecksichtigen !!!!!
1592                             const SvxBorderLine* pLeftLine;
1593                             const SvxBorderLine* pTopLine;
1594                             const SvxBorderLine* pRightLine;
1595                             const SvxBorderLine* pBottomLine;
1596 							pDoc->GetBorderLines( nX, nY, nTab,
1597 									&pLeftLine, &pTopLine, &pRightLine, &pBottomLine );
1598                             aTopLine.Set( pTopLine, nPPTY );
1599                             aBottomLine.Set( pBottomLine, nPPTY );
1600                             aLeftLine.Set( pLeftLine, nPPTX );
1601                             aRightLine.Set( pRightLine, nPPTX );
1602 						}
1603                         else
1604                         {
1605                             size_t nCol = lclGetArrayColFromCellInfoX( nArrX, nX1, nX2, bLayoutRTL );
1606                             aTopLine = rArray.GetCellStyleTop( nCol, nRow );
1607                             aBottomLine = rArray.GetCellStyleBottom( nCol, nRow );
1608                             aLeftLine = rArray.GetCellStyleLeft( nCol, nRow );
1609                             aRightLine = rArray.GetCellStyleRight( nCol, nRow );
1610                             // in RTL mode the array is already mirrored -> swap back left/right borders
1611                             if( bLayoutRTL )
1612                                 std::swap( aLeftLine, aRightLine );
1613                         }
1614 
1615                         lcl_HorizLine( *pDev, aPoints[bLayoutRTL?1:0], aPoints[bLayoutRTL?0:1], aTopLine, pForceColor );
1616                         lcl_HorizLine( *pDev, aPoints[bLayoutRTL?2:3], aPoints[bLayoutRTL?3:2], aBottomLine, pForceColor );
1617 
1618                         lcl_VertLine( *pDev, aPoints[0], aPoints[3], aLeftLine, aTopLine, aBottomLine, pForceColor );
1619                         lcl_VertLine( *pDev, aPoints[1], aPoints[2], aRightLine, aTopLine, aBottomLine, pForceColor );
1620 					}
1621 				}
1622 				nPosX += nColWidth * nLayoutSign;
1623 			}
1624 
1625 			//	erst hinterher im zweiten Schritt die Linien fuer normale Ausgabe loeschen
1626 
1627 			nX = nX1 > 0 ? (nX1-1) : static_cast<SCCOL>(0);
1628 			for (; nX<=nX2+1; nX++)			// sichtbarer Teil +- 1
1629 			{
1630                 sal_uInt16 nArrX = nX + 1;
1631                 CellInfo& rInfo = rThisRowInfo.pCellInfo[nArrX];
1632                 if ( rInfo.nRotateDir > SC_ROTDIR_STANDARD &&
1633                         !rInfo.bHOverlapped && !rInfo.bVOverlapped )
1634 				{
1635                     pPattern = rInfo.pPatternAttr;
1636                     pCondSet = rInfo.pConditionSet;
1637 					SvxRotateMode eRotMode = (SvxRotateMode)((const SvxRotateModeItem&)
1638 									pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet)).GetValue();
1639 
1640                     size_t nCol = lclGetArrayColFromCellInfoX( nArrX, nX1, nX2, bLayoutRTL );
1641 
1642 					//	horizontal: angrenzende Linie verlaengern
1643 					//	(nur, wenn die gedrehte Zelle eine Umrandung hat)
1644                     sal_uInt16 nDir = rInfo.nRotateDir;
1645                     if ( rArray.GetCellStyleTop( nCol, nRow ).Prim() && eRotMode != SVX_ROTATE_MODE_TOP )
1646                     {
1647                         svx::frame::Style aStyle( lcl_FindHorLine( pDoc, nX, nY, nTab, nDir, sal_True ), nPPTY );
1648                         rArray.SetCellStyleTop( nCol, nRow, aStyle );
1649                         if( nRow > 0 )
1650                             rArray.SetCellStyleBottom( nCol, nRow - 1, aStyle );
1651                     }
1652                     if ( rArray.GetCellStyleBottom( nCol, nRow ).Prim() && eRotMode != SVX_ROTATE_MODE_BOTTOM )
1653                     {
1654                         svx::frame::Style aStyle( lcl_FindHorLine( pDoc, nX, nY, nTab, nDir, sal_False ), nPPTY );
1655                         rArray.SetCellStyleBottom( nCol, nRow, aStyle );
1656                         if( nRow + 1 < rArray.GetRowCount() )
1657                             rArray.SetCellStyleTop( nCol, nRow + 1, aStyle );
1658                     }
1659 
1660                     // always remove vertical borders
1661                     if( !rArray.IsMergedOverlappedLeft( nCol, nRow ) )
1662                     {
1663                         rArray.SetCellStyleLeft( nCol, nRow, svx::frame::Style() );
1664                         if( nCol > 0 )
1665                             rArray.SetCellStyleRight( nCol - 1, nRow, svx::frame::Style() );
1666                     }
1667                     if( !rArray.IsMergedOverlappedRight( nCol, nRow ) )
1668                     {
1669                         rArray.SetCellStyleRight( nCol, nRow, svx::frame::Style() );
1670                         if( nCol + 1 < rArray.GetColCount() )
1671                             rArray.SetCellStyleLeft( nCol + 1, nRow, svx::frame::Style() );
1672                     }
1673 
1674                     // remove diagonal borders
1675                     rArray.SetCellStyleTLBR( nCol, nRow, svx::frame::Style() );
1676                     rArray.SetCellStyleBLTR( nCol, nRow, svx::frame::Style() );
1677 				}
1678 			}
1679 		}
1680 		nPosY += nRowHeight;
1681 	}
1682 
1683 	if (bMetaFile)
1684 		pDev->Pop();
1685 	else
1686 		pDev->SetClipRegion();
1687 }
1688 
1689 //	Drucker
1690 
1691 Region ScOutputData::GetChangedAreaRegion()
1692 {
1693     Region aRegion;
1694     Rectangle aDrawingRect;
1695     bool bHad(false);
1696     long nPosY = nScrY;
1697     SCSIZE nArrY;
1698 
1699     aDrawingRect.Left() = nScrX;
1700     aDrawingRect.Right() = nScrX+nScrW-1;
1701 
1702     for(nArrY=1; nArrY+1<nArrCount; nArrY++)
1703     {
1704         RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1705 
1706         if(pThisRowInfo->bChanged)
1707         {
1708             if(!bHad)
1709             {
1710                 aDrawingRect.Top() = nPosY;
1711                 bHad = true;
1712             }
1713 
1714             aDrawingRect.Bottom() = nPosY + pRowInfo[nArrY].nHeight - 1;
1715         }
1716         else if(bHad)
1717         {
1718             aRegion.Union(pDev->PixelToLogic(aDrawingRect));
1719             bHad = false;
1720         }
1721 
1722         nPosY += pRowInfo[nArrY].nHeight;
1723     }
1724 
1725     if(bHad)
1726     {
1727         aRegion.Union(pDev->PixelToLogic(aDrawingRect));
1728     }
1729 
1730     return aRegion;
1731 }
1732 
1733 sal_Bool ScOutputData::SetChangedClip()
1734 {
1735 	PolyPolygon aPoly;
1736 
1737 	Rectangle aDrawingRect;
1738 	aDrawingRect.Left() = nScrX;
1739 	aDrawingRect.Right() = nScrX+nScrW-1;
1740 
1741 	sal_Bool	bHad	= sal_False;
1742 	long	nPosY	= nScrY;
1743 	SCSIZE	nArrY;
1744 	for (nArrY=1; nArrY+1<nArrCount; nArrY++)
1745 	{
1746 		RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1747 
1748 		if ( pThisRowInfo->bChanged )
1749 		{
1750 			if (!bHad)
1751 			{
1752 				aDrawingRect.Top() = nPosY;
1753 				bHad = sal_True;
1754 			}
1755 			aDrawingRect.Bottom() = nPosY + pRowInfo[nArrY].nHeight - 1;
1756 		}
1757 		else if (bHad)
1758 		{
1759 			aPoly.Insert( Polygon( pDev->PixelToLogic(aDrawingRect) ) );
1760 			bHad = sal_False;
1761 		}
1762 		nPosY += pRowInfo[nArrY].nHeight;
1763 	}
1764 
1765 	if (bHad)
1766 		aPoly.Insert( Polygon( pDev->PixelToLogic(aDrawingRect) ) );
1767 
1768 	sal_Bool bRet = (aPoly.Count() != 0);
1769 	if (bRet)
1770 		pDev->SetClipRegion(Region(aPoly));
1771 	return bRet;
1772 }
1773 
1774 void ScOutputData::FindChanged()
1775 {
1776 	SCCOL	nX;
1777 	SCSIZE	nArrY;
1778 
1779 	sal_Bool bWasIdleDisabled = pDoc->IsIdleDisabled();
1780 	pDoc->DisableIdle( sal_True );
1781 	for (nArrY=0; nArrY<nArrCount; nArrY++)
1782 		pRowInfo[nArrY].bChanged = sal_False;
1783 
1784 	sal_Bool bProgress = sal_False;
1785 	for (nArrY=0; nArrY<nArrCount; nArrY++)
1786 	{
1787 		RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1788 		for (nX=nX1; nX<=nX2; nX++)
1789 		{
1790 			ScBaseCell* pCell = pThisRowInfo->pCellInfo[nX+1].pCell;
1791 			if (pCell)
1792 				if (pCell->GetCellType() == CELLTYPE_FORMULA)
1793 				{
1794 					ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
1795 					if ( !bProgress && pFCell->GetDirty() )
1796 					{
1797 						ScProgress::CreateInterpretProgress( pDoc, sal_True );
1798 						bProgress = sal_True;
1799 					}
1800 					if (!pFCell->IsRunning())
1801 					{
1802                         (void)pFCell->GetValue();
1803 						if (pFCell->IsChanged())
1804 						{
1805 							pThisRowInfo->bChanged = sal_True;
1806 							if ( pThisRowInfo->pCellInfo[nX+1].bMerged )
1807 							{
1808 								SCSIZE nOverY = nArrY + 1;
1809 								while ( nOverY<nArrCount &&
1810 										pRowInfo[nOverY].pCellInfo[nX+1].bVOverlapped )
1811 								{
1812 									pRowInfo[nOverY].bChanged = sal_True;
1813 									++nOverY;
1814 								}
1815 							}
1816 						}
1817 					}
1818 				}
1819 		}
1820 	}
1821 	if ( bProgress )
1822 		ScProgress::DeleteInterpretProgress();
1823 	pDoc->DisableIdle( bWasIdleDisabled );
1824 }
1825 
1826 #ifdef OLD_SELECTION_PAINT
1827 void ScOutputData::DrawMark( Window* pWin )
1828 {
1829     Rectangle aRect;
1830     ScInvertMerger aInvert( pWin );
1831     //!	additional method AddLineRect for ScInvertMerger?
1832 
1833     long nPosY = nScrY;
1834     for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
1835     {
1836         RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1837         if (pThisRowInfo->bChanged)
1838         {
1839             long nPosX = nScrX;
1840             if (bLayoutRTL)
1841                 nPosX += nMirrorW - 1;      // always in pixels
1842 
1843             aRect = Rectangle( Point( nPosX,nPosY ), Size(1, pThisRowInfo->nHeight) );
1844             if (bLayoutRTL)
1845                 aRect.Left() = aRect.Right() + 1;
1846             else
1847                 aRect.Right() = aRect.Left() - 1;
1848 
1849             sal_Bool bOldMarked = sal_False;
1850             for (SCCOL nX=nX1; nX<=nX2; nX++)
1851             {
1852                 if (pThisRowInfo->pCellInfo[nX+1].bMarked != bOldMarked)
1853                 {
1854                     if (bOldMarked && aRect.Right() >= aRect.Left())
1855                         aInvert.AddRect( aRect );
1856 
1857                     if (bLayoutRTL)
1858                         aRect.Right() = nPosX;
1859                     else
1860                         aRect.Left() = nPosX;
1861 
1862                     bOldMarked = pThisRowInfo->pCellInfo[nX+1].bMarked;
1863                 }
1864 
1865                 if (bLayoutRTL)
1866                 {
1867                     nPosX -= pRowInfo[0].pCellInfo[nX+1].nWidth;
1868                     aRect.Left() = nPosX+1;
1869                 }
1870                 else
1871                 {
1872                     nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth;
1873                     aRect.Right() = nPosX-1;
1874                 }
1875             }
1876             if (bOldMarked && aRect.Right() >= aRect.Left())
1877                 aInvert.AddRect( aRect );
1878         }
1879         nPosY += pThisRowInfo->nHeight;
1880     }
1881 }
1882 #endif
1883 
1884 void ScOutputData::DrawRefMark( SCCOL nRefStartX, SCROW nRefStartY,
1885 								SCCOL nRefEndX, SCROW nRefEndY,
1886 								const Color& rColor, sal_Bool bHandle )
1887 {
1888 	PutInOrder( nRefStartX, nRefEndX );
1889 	PutInOrder( nRefStartY, nRefEndY );
1890 
1891 	if ( nRefStartX == nRefEndX && nRefStartY == nRefEndY )
1892 		pDoc->ExtendMerge( nRefStartX, nRefStartY, nRefEndX, nRefEndY, nTab );
1893 
1894 	if ( nRefStartX <= nVisX2 && nRefEndX >= nVisX1 &&
1895 		 nRefStartY <= nVisY2 && nRefEndY >= nVisY1 )
1896 	{
1897 		long nMinX = nScrX;
1898 		long nMinY = nScrY;
1899 		long nMaxX = nScrX+nScrW-1;
1900 		long nMaxY = nScrY+nScrH-1;
1901 		if ( bLayoutRTL )
1902 		{
1903 			long nTemp = nMinX;
1904 			nMinX = nMaxX;
1905 			nMaxX = nTemp;
1906 		}
1907 		long nLayoutSign = bLayoutRTL ? -1 : 1;
1908 
1909 		sal_Bool bTop    = sal_False;
1910 		sal_Bool bBottom = sal_False;
1911 		sal_Bool bLeft   = sal_False;
1912 		sal_Bool bRight	 = sal_False;
1913 
1914 		long nPosY = nScrY;
1915 		sal_Bool bNoStartY = ( nY1 < nRefStartY );
1916 		sal_Bool bNoEndY   = sal_False;
1917 		for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++)		// loop to end for bNoEndY check
1918 		{
1919 			SCROW nY = pRowInfo[nArrY].nRowNo;
1920 
1921 			if ( nY==nRefStartY || (nY>nRefStartY && bNoStartY) )
1922 			{
1923 				nMinY = nPosY;
1924 				bTop = sal_True;
1925 			}
1926 			if ( nY==nRefEndY )
1927 			{
1928 				nMaxY = nPosY + pRowInfo[nArrY].nHeight - 2;
1929 				bBottom = sal_True;
1930 			}
1931 			if ( nY>nRefEndY && bNoEndY )
1932 			{
1933 				nMaxY = nPosY-2;
1934 				bBottom = sal_True;
1935 			}
1936 			bNoStartY = ( nY < nRefStartY );
1937 			bNoEndY   = ( nY < nRefEndY );
1938 			nPosY += pRowInfo[nArrY].nHeight;
1939 		}
1940 
1941 		long nPosX = nScrX;
1942 		if ( bLayoutRTL )
1943 			nPosX += nMirrorW - 1;		// always in pixels
1944 
1945 		for (SCCOL nX=nX1; nX<=nX2; nX++)
1946 		{
1947 			if ( nX==nRefStartX )
1948 			{
1949 				nMinX = nPosX;
1950 				bLeft = sal_True;
1951 			}
1952 			if ( nX==nRefEndX )
1953 			{
1954 				nMaxX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - 2 ) * nLayoutSign;
1955 				bRight = sal_True;
1956 			}
1957 			nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
1958 		}
1959 
1960 		if ( nMaxX * nLayoutSign >= nMinX * nLayoutSign &&
1961 			 nMaxY >= nMinY )
1962 		{
1963 			pDev->SetLineColor( rColor );
1964 			if (bTop && bBottom && bLeft && bRight)
1965 			{
1966 				pDev->SetFillColor();
1967 				pDev->DrawRect( Rectangle( nMinX, nMinY, nMaxX, nMaxY ) );
1968 			}
1969 			else
1970 			{
1971 				if (bTop)
1972 					pDev->DrawLine( Point( nMinX,nMinY ), Point( nMaxX,nMinY ) );
1973 				if (bBottom)
1974 					pDev->DrawLine( Point( nMinX,nMaxY ), Point( nMaxX,nMaxY ) );
1975 				if (bLeft)
1976 					pDev->DrawLine( Point( nMinX,nMinY ), Point( nMinX,nMaxY ) );
1977 				if (bRight)
1978 					pDev->DrawLine( Point( nMaxX,nMinY ), Point( nMaxX,nMaxY ) );
1979 			}
1980 			if ( bHandle && bRight && bBottom )
1981 			{
1982 				pDev->SetLineColor();
1983 				pDev->SetFillColor( rColor );
1984 				pDev->DrawRect( Rectangle( nMaxX-3*nLayoutSign, nMaxY-3, nMaxX+nLayoutSign, nMaxY+1 ) );
1985 			}
1986 		}
1987 	}
1988 }
1989 
1990 void ScOutputData::DrawOneChange( SCCOL nRefStartX, SCROW nRefStartY,
1991 								SCCOL nRefEndX, SCROW nRefEndY,
1992 								const Color& rColor, sal_uInt16 nType )
1993 {
1994 	PutInOrder( nRefStartX, nRefEndX );
1995 	PutInOrder( nRefStartY, nRefEndY );
1996 
1997 	if ( nRefStartX == nRefEndX && nRefStartY == nRefEndY )
1998 		pDoc->ExtendMerge( nRefStartX, nRefStartY, nRefEndX, nRefEndY, nTab );
1999 
2000 	if ( nRefStartX <= nVisX2 + 1 && nRefEndX >= nVisX1 &&
2001 		 nRefStartY <= nVisY2 + 1 && nRefEndY >= nVisY1 )		// +1 because it touches next cells left/top
2002 	{
2003 		long nMinX = nScrX;
2004 		long nMinY = nScrY;
2005 		long nMaxX = nScrX+nScrW-1;
2006 		long nMaxY = nScrY+nScrH-1;
2007 		if ( bLayoutRTL )
2008 		{
2009 			long nTemp = nMinX;
2010 			nMinX = nMaxX;
2011 			nMaxX = nTemp;
2012 		}
2013 		long nLayoutSign = bLayoutRTL ? -1 : 1;
2014 
2015 		sal_Bool bTop    = sal_False;
2016 		sal_Bool bBottom = sal_False;
2017 		sal_Bool bLeft   = sal_False;
2018 		sal_Bool bRight	 = sal_False;
2019 
2020 		long nPosY = nScrY;
2021 		sal_Bool bNoStartY = ( nY1 < nRefStartY );
2022 		sal_Bool bNoEndY   = sal_False;
2023 		for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++)		// loop to end for bNoEndY check
2024 		{
2025 			SCROW nY = pRowInfo[nArrY].nRowNo;
2026 
2027 			if ( nY==nRefStartY || (nY>nRefStartY && bNoStartY) )
2028 			{
2029 				nMinY = nPosY - 1;
2030 				bTop = sal_True;
2031 			}
2032 			if ( nY==nRefEndY )
2033 			{
2034 				nMaxY = nPosY + pRowInfo[nArrY].nHeight - 1;
2035 				bBottom = sal_True;
2036 			}
2037 			if ( nY>nRefEndY && bNoEndY )
2038 			{
2039 				nMaxY = nPosY - 1;
2040 				bBottom = sal_True;
2041 			}
2042 			bNoStartY = ( nY < nRefStartY );
2043 			bNoEndY   = ( nY < nRefEndY );
2044 			nPosY += pRowInfo[nArrY].nHeight;
2045 		}
2046 
2047 		long nPosX = nScrX;
2048 		if ( bLayoutRTL )
2049 			nPosX += nMirrorW - 1;		// always in pixels
2050 
2051 		for (SCCOL nX=nX1; nX<=nX2+1; nX++)
2052 		{
2053 			if ( nX==nRefStartX )
2054 			{
2055 				nMinX = nPosX - nLayoutSign;
2056 				bLeft = sal_True;
2057 			}
2058 			if ( nX==nRefEndX )
2059 			{
2060 				nMaxX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - 1 ) * nLayoutSign;
2061 				bRight = sal_True;
2062 			}
2063 			nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2064 		}
2065 
2066 		if ( nMaxX * nLayoutSign >= nMinX * nLayoutSign &&
2067 			 nMaxY >= nMinY )
2068 		{
2069 			if ( nType == SC_CAT_DELETE_ROWS )
2070 				bLeft = bRight = bBottom = sal_False;		//! dicke Linie ???
2071 			else if ( nType == SC_CAT_DELETE_COLS )
2072 				bTop = bBottom = bRight = sal_False;		//! dicke Linie ???
2073 
2074 			pDev->SetLineColor( rColor );
2075 			if (bTop && bBottom && bLeft && bRight)
2076 			{
2077 				pDev->SetFillColor();
2078 				pDev->DrawRect( Rectangle( nMinX, nMinY, nMaxX, nMaxY ) );
2079 			}
2080 			else
2081 			{
2082 				if (bTop)
2083 				{
2084 					pDev->DrawLine( Point( nMinX,nMinY ), Point( nMaxX,nMinY ) );
2085 					if ( nType == SC_CAT_DELETE_ROWS )
2086 						pDev->DrawLine( Point( nMinX,nMinY+1 ), Point( nMaxX,nMinY+1 ) );
2087 				}
2088 				if (bBottom)
2089 					pDev->DrawLine( Point( nMinX,nMaxY ), Point( nMaxX,nMaxY ) );
2090 				if (bLeft)
2091 				{
2092 					pDev->DrawLine( Point( nMinX,nMinY ), Point( nMinX,nMaxY ) );
2093 					if ( nType == SC_CAT_DELETE_COLS )
2094 						pDev->DrawLine( Point( nMinX+nLayoutSign,nMinY ), Point( nMinX+nLayoutSign,nMaxY ) );
2095 				}
2096 				if (bRight)
2097 					pDev->DrawLine( Point( nMaxX,nMinY ), Point( nMaxX,nMaxY ) );
2098 			}
2099 			if ( bLeft && bTop )
2100 			{
2101 				pDev->SetLineColor();
2102 				pDev->SetFillColor( rColor );
2103 				pDev->DrawRect( Rectangle( nMinX+nLayoutSign, nMinY+1, nMinX+3*nLayoutSign, nMinY+3 ) );
2104 			}
2105 		}
2106 	}
2107 }
2108 
2109 void ScOutputData::DrawChangeTrack()
2110 {
2111 	ScChangeTrack* pTrack = pDoc->GetChangeTrack();
2112 	ScChangeViewSettings* pSettings = pDoc->GetChangeViewSettings();
2113 	if ( !pTrack || !pTrack->GetFirst() || !pSettings || !pSettings->ShowChanges() )
2114 		return;			// nix da oder abgeschaltet
2115 
2116 	ScActionColorChanger aColorChanger(*pTrack);
2117 
2118 	//	Clipping passiert von aussen
2119 	//!	ohne Clipping, nur betroffene Zeilen painten ??!??!?
2120 
2121 	SCCOL nEndX = nX2;
2122 	SCROW nEndY = nY2;
2123 	if ( nEndX < MAXCOL ) ++nEndX;		// auch noch von der naechsten Zelle, weil die Markierung
2124 	if ( nEndY < MAXROW ) ++nEndY;		// in die jeweils vorhergehende Zelle hineinragt
2125 	ScRange aViewRange( nX1, nY1, nTab, nEndX, nEndY, nTab );
2126 	const ScChangeAction* pAction = pTrack->GetFirst();
2127 	while (pAction)
2128 	{
2129 		ScChangeActionType eActionType;
2130 		if ( pAction->IsVisible() )
2131 		{
2132 			eActionType = pAction->GetType();
2133 			const ScBigRange& rBig = pAction->GetBigRange();
2134 			if ( rBig.aStart.Tab() == nTab )
2135 			{
2136 				ScRange aRange = rBig.MakeRange();
2137 
2138 				if ( eActionType == SC_CAT_DELETE_ROWS )
2139 					aRange.aEnd.SetRow( aRange.aStart.Row() );
2140 				else if ( eActionType == SC_CAT_DELETE_COLS )
2141 					aRange.aEnd.SetCol( aRange.aStart.Col() );
2142 
2143 				if ( aRange.Intersects( aViewRange ) &&
2144 					 ScViewUtil::IsActionShown( *pAction, *pSettings, *pDoc ) )
2145 				{
2146 					aColorChanger.Update( *pAction );
2147 					Color aColor( aColorChanger.GetColor() );
2148 					DrawOneChange( aRange.aStart.Col(), aRange.aStart.Row(),
2149                                     aRange.aEnd.Col(), aRange.aEnd.Row(), aColor, sal::static_int_cast<sal_uInt16>(eActionType) );
2150 
2151 				}
2152 			}
2153 			if ( eActionType == SC_CAT_MOVE &&
2154 					((const ScChangeActionMove*)pAction)->
2155 						GetFromRange().aStart.Tab() == nTab )
2156 			{
2157 				ScRange aRange = ((const ScChangeActionMove*)pAction)->
2158 						GetFromRange().MakeRange();
2159 				if ( aRange.Intersects( aViewRange ) &&
2160 					 ScViewUtil::IsActionShown( *pAction, *pSettings, *pDoc ) )
2161 				{
2162 					aColorChanger.Update( *pAction );
2163 					Color aColor( aColorChanger.GetColor() );
2164 					DrawOneChange( aRange.aStart.Col(), aRange.aStart.Row(),
2165                                     aRange.aEnd.Col(), aRange.aEnd.Row(), aColor, sal::static_int_cast<sal_uInt16>(eActionType) );
2166 				}
2167 			}
2168 		}
2169 
2170 		pAction = pAction->GetNext();
2171 	}
2172 }
2173 
2174 void ScOutputData::DrawNoteMarks()
2175 {
2176 	sal_Bool bFirst = sal_True;
2177 
2178 	long nInitPosX = nScrX;
2179 	if ( bLayoutRTL )
2180 		nInitPosX += nMirrorW - 1;				// always in pixels
2181 	long nLayoutSign = bLayoutRTL ? -1 : 1;
2182 
2183 	long nPosY = nScrY;
2184 	for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
2185 	{
2186 		RowInfo* pThisRowInfo = &pRowInfo[nArrY];
2187 		if ( pThisRowInfo->bChanged )
2188 		{
2189 			long nPosX = nInitPosX;
2190 			for (SCCOL nX=nX1; nX<=nX2; nX++)
2191 			{
2192 				CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
2193 				ScBaseCell* pCell = pInfo->pCell;
2194 				sal_Bool bIsMerged = sal_False;
2195 
2196 				if ( nX==nX1 && pInfo->bHOverlapped && !pInfo->bVOverlapped )
2197 				{
2198 					// find start of merged cell
2199 					bIsMerged = sal_True;
2200 					SCROW nY = pRowInfo[nArrY].nRowNo;
2201 					SCCOL nMergeX = nX;
2202 					SCROW nMergeY = nY;
2203 					pDoc->ExtendOverlapped( nMergeX, nMergeY, nX, nY, nTab );
2204 					pCell = pDoc->GetCell( ScAddress(nMergeX,nMergeY,nTab) );
2205 					// use origin's pCell for NotePtr test below
2206 				}
2207 
2208                 if ( pCell && pCell->HasNote() && ( bIsMerged ||
2209 						( !pInfo->bHOverlapped && !pInfo->bVOverlapped ) ) )
2210 				{
2211 					if (bFirst)
2212 					{
2213 						pDev->SetLineColor();
2214 
2215 						const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
2216 						if ( bUseStyleColor && rStyleSettings.GetHighContrastMode() )
2217                             pDev->SetFillColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
2218 						else
2219 							pDev->SetFillColor(COL_LIGHTRED);
2220 
2221 						bFirst = sal_False;
2222 					}
2223 
2224 					long nMarkX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - 4 ) * nLayoutSign;
2225 					if ( bIsMerged || pInfo->bMerged )
2226 					{
2227 						//	if merged, add widths of all cells
2228 						SCCOL nNextX = nX + 1;
2229 						while ( nNextX <= nX2 + 1 && pThisRowInfo->pCellInfo[nNextX+1].bHOverlapped )
2230 						{
2231 							nMarkX += pRowInfo[0].pCellInfo[nNextX+1].nWidth * nLayoutSign;
2232 							++nNextX;
2233 						}
2234 					}
2235 					if ( bLayoutRTL ? ( nMarkX >= 0 ) : ( nMarkX < nScrX+nScrW ) )
2236 						pDev->DrawRect( Rectangle( nMarkX,nPosY,nMarkX+2*nLayoutSign,nPosY+2 ) );
2237 				}
2238 
2239 				nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2240 			}
2241 		}
2242 		nPosY += pThisRowInfo->nHeight;
2243 	}
2244 }
2245 
2246 void ScOutputData::AddPDFNotes()
2247 {
2248     vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, pDev->GetExtOutDevData() );
2249     if ( !pPDFData || !pPDFData->GetIsExportNotes() )
2250         return;
2251 
2252     long nInitPosX = nScrX;
2253     if ( bLayoutRTL )
2254     {
2255         Size aOnePixel = pDev->PixelToLogic(Size(1,1));
2256         long nOneX = aOnePixel.Width();
2257         nInitPosX += nMirrorW - nOneX;
2258     }
2259     long nLayoutSign = bLayoutRTL ? -1 : 1;
2260 
2261     long nPosY = nScrY;
2262     for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
2263     {
2264         RowInfo* pThisRowInfo = &pRowInfo[nArrY];
2265         if ( pThisRowInfo->bChanged )
2266         {
2267             long nPosX = nInitPosX;
2268             for (SCCOL nX=nX1; nX<=nX2; nX++)
2269             {
2270                 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
2271                 ScBaseCell* pCell = pInfo->pCell;
2272                 sal_Bool bIsMerged = sal_False;
2273                 SCROW nY = pRowInfo[nArrY].nRowNo;
2274                 SCCOL nMergeX = nX;
2275                 SCROW nMergeY = nY;
2276 
2277                 if ( nX==nX1 && pInfo->bHOverlapped && !pInfo->bVOverlapped )
2278                 {
2279                     // find start of merged cell
2280                     bIsMerged = sal_True;
2281                     pDoc->ExtendOverlapped( nMergeX, nMergeY, nX, nY, nTab );
2282                     pCell = pDoc->GetCell( ScAddress(nMergeX,nMergeY,nTab) );
2283                     // use origin's pCell for NotePtr test below
2284                 }
2285 
2286                 if ( pCell && pCell->HasNote() && ( bIsMerged ||
2287                         ( !pInfo->bHOverlapped && !pInfo->bVOverlapped ) ) )
2288                 {
2289                     long nNoteWidth = (long)( SC_CLIPMARK_SIZE * nPPTX );
2290                     long nNoteHeight = (long)( SC_CLIPMARK_SIZE * nPPTY );
2291 
2292                     long nMarkX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - nNoteWidth ) * nLayoutSign;
2293                     if ( bIsMerged || pInfo->bMerged )
2294                     {
2295                         //  if merged, add widths of all cells
2296                         SCCOL nNextX = nX + 1;
2297                         while ( nNextX <= nX2 + 1 && pThisRowInfo->pCellInfo[nNextX+1].bHOverlapped )
2298                         {
2299                             nMarkX += pRowInfo[0].pCellInfo[nNextX+1].nWidth * nLayoutSign;
2300                             ++nNextX;
2301                         }
2302                     }
2303                     if ( bLayoutRTL ? ( nMarkX >= 0 ) : ( nMarkX < nScrX+nScrW ) )
2304                     {
2305                         Rectangle aNoteRect( nMarkX, nPosY, nMarkX+nNoteWidth*nLayoutSign, nPosY+nNoteHeight );
2306                         const ScPostIt* pNote = pCell->GetNote();
2307 
2308                         // Note title is the cell address (as on printed note pages)
2309                         String aTitle;
2310                         ScAddress aAddress( nMergeX, nMergeY, nTab );
2311                         aAddress.Format( aTitle, SCA_VALID, pDoc, pDoc->GetAddressConvention() );
2312 
2313                         // Content has to be a simple string without line breaks
2314                         String aContent = pNote->GetText();
2315                         xub_StrLen nPos;
2316                         while ( (nPos=aContent.Search('\n')) != STRING_NOTFOUND )
2317                             aContent.SetChar( nPos, ' ' );
2318 
2319                         vcl::PDFNote aNote;
2320                         aNote.Title = aTitle;
2321                         aNote.Contents = aContent;
2322                         pPDFData->CreateNote( aNoteRect, aNote );
2323                     }
2324                 }
2325 
2326                 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2327             }
2328         }
2329         nPosY += pThisRowInfo->nHeight;
2330     }
2331 }
2332 
2333 void ScOutputData::DrawClipMarks()
2334 {
2335 	if (!bAnyClipped)
2336 		return;
2337 
2338 	Color aArrowFillCol( COL_LIGHTRED );
2339 
2340 	sal_uLong nOldDrawMode = pDev->GetDrawMode();
2341 	const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
2342 	if ( bUseStyleColor && rStyleSettings.GetHighContrastMode() )
2343 	{
2344 		//	use DrawMode to change the arrow's outline color
2345 		pDev->SetDrawMode( nOldDrawMode | DRAWMODE_SETTINGSLINE );
2346 		//	use text color also for the fill color
2347         aArrowFillCol.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
2348 	}
2349 
2350 	long nInitPosX = nScrX;
2351 	if ( bLayoutRTL )
2352 		nInitPosX += nMirrorW - 1;				// always in pixels
2353 	long nLayoutSign = bLayoutRTL ? -1 : 1;
2354 
2355 	Rectangle aCellRect;
2356 	long nPosY = nScrY;
2357 	for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
2358 	{
2359 		RowInfo* pThisRowInfo = &pRowInfo[nArrY];
2360 		if ( pThisRowInfo->bChanged )
2361 		{
2362 			SCROW nY = pThisRowInfo->nRowNo;
2363 			long nPosX = nInitPosX;
2364 			for (SCCOL nX=nX1; nX<=nX2; nX++)
2365 			{
2366 				CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
2367 				if (pInfo->nClipMark)
2368 				{
2369 					if (pInfo->bHOverlapped || pInfo->bVOverlapped)
2370 					{
2371 						//	merge origin may be outside of visible area - use document functions
2372 
2373 						SCCOL nOverX = nX;
2374 						SCROW nOverY = nY;
2375 						long nStartPosX = nPosX;
2376 						long nStartPosY = nPosY;
2377 
2378 						while ( nOverX > 0 && ( ((const ScMergeFlagAttr*)pDoc->GetAttr(
2379 								nOverX, nOverY, nTab, ATTR_MERGE_FLAG ))->GetValue() & SC_MF_HOR ) )
2380 						{
2381 							--nOverX;
2382 							nStartPosX -= nLayoutSign * (long) ( pDoc->GetColWidth(nOverX,nTab) * nPPTX );
2383 						}
2384 
2385 						while ( nOverY > 0 && ( ((const ScMergeFlagAttr*)pDoc->GetAttr(
2386 								nOverX, nOverY, nTab, ATTR_MERGE_FLAG ))->GetValue() & SC_MF_VER ) )
2387 						{
2388 							--nOverY;
2389 							nStartPosY -= nLayoutSign * (long) ( pDoc->GetRowHeight(nOverY,nTab) * nPPTY );
2390 						}
2391 
2392 						long nOutWidth = (long) ( pDoc->GetColWidth(nOverX,nTab) * nPPTX );
2393 						long nOutHeight = (long) ( pDoc->GetRowHeight(nOverY,nTab) * nPPTY );
2394 
2395 						const ScMergeAttr* pMerge = (const ScMergeAttr*)
2396 									pDoc->GetAttr( nOverX, nOverY, nTab, ATTR_MERGE );
2397 						SCCOL nCountX = pMerge->GetColMerge();
2398 						for (SCCOL i=1; i<nCountX; i++)
2399 							nOutWidth += (long) ( pDoc->GetColWidth(nOverX+i,nTab) * nPPTX );
2400 						SCROW nCountY = pMerge->GetRowMerge();
2401                         nOutHeight += (long) pDoc->GetScaledRowHeight( nOverY+1, nOverY+nCountY-1, nTab, nPPTY);
2402 
2403 						if ( bLayoutRTL )
2404 							nStartPosX -= nOutWidth - 1;
2405 						aCellRect = Rectangle( Point( nStartPosX, nStartPosY ), Size( nOutWidth, nOutHeight ) );
2406 					}
2407 					else
2408 					{
2409 						long nOutWidth = pRowInfo[0].pCellInfo[nX+1].nWidth;
2410 						long nOutHeight = pThisRowInfo->nHeight;
2411 
2412 						if ( pInfo->bMerged && pInfo->pPatternAttr )
2413 						{
2414 							SCCOL nOverX = nX;
2415 							SCROW nOverY = nY;
2416 							const ScMergeAttr* pMerge =
2417 									(ScMergeAttr*)&pInfo->pPatternAttr->GetItem(ATTR_MERGE);
2418 							SCCOL nCountX = pMerge->GetColMerge();
2419 							for (SCCOL i=1; i<nCountX; i++)
2420 								nOutWidth += (long) ( pDoc->GetColWidth(nOverX+i,nTab) * nPPTX );
2421 							SCROW nCountY = pMerge->GetRowMerge();
2422                             nOutHeight += (long) pDoc->GetScaledRowHeight( nOverY+1, nOverY+nCountY-1, nTab, nPPTY);
2423 						}
2424 
2425 						long nStartPosX = nPosX;
2426 						if ( bLayoutRTL )
2427 							nStartPosX -= nOutWidth - 1;
2428                         // #i80447# create aCellRect from two points in case nOutWidth is 0
2429                         aCellRect = Rectangle( Point( nStartPosX, nPosY ),
2430                                                Point( nStartPosX+nOutWidth-1, nPosY+nOutHeight-1 ) );
2431 					}
2432 
2433 					aCellRect.Bottom() -= 1;	// don't paint over the cell grid
2434 					if ( bLayoutRTL )
2435 						aCellRect.Left() += 1;
2436 					else
2437 						aCellRect.Right() -= 1;
2438 
2439 					long nMarkPixel = (long)( SC_CLIPMARK_SIZE * nPPTX );
2440 					Size aMarkSize( nMarkPixel, (nMarkPixel-1)*2 );
2441 
2442 					if ( pInfo->nClipMark & ( bLayoutRTL ? SC_CLIPMARK_RIGHT : SC_CLIPMARK_LEFT ) )
2443 					{
2444 						//	visually left
2445 						Rectangle aMarkRect = aCellRect;
2446 						aMarkRect.Right() = aCellRect.Left()+nMarkPixel-1;
2447 #if 0
2448 						//!	Test
2449 						pDev->SetLineColor(); pDev->SetFillColor(COL_YELLOW);
2450 						pDev->DrawRect(aMarkRect);
2451 						//!	Test
2452 #endif
2453 						SvxFont::DrawArrow( *pDev, aMarkRect, aMarkSize, aArrowFillCol, sal_True );
2454 					}
2455 					if ( pInfo->nClipMark & ( bLayoutRTL ? SC_CLIPMARK_LEFT : SC_CLIPMARK_RIGHT ) )
2456 					{
2457 						//	visually right
2458 						Rectangle aMarkRect = aCellRect;
2459 						aMarkRect.Left() = aCellRect.Right()-nMarkPixel+1;
2460 #if 0
2461 						//!	Test
2462 						pDev->SetLineColor(); pDev->SetFillColor(COL_LIGHTGREEN);
2463 						pDev->DrawRect(aMarkRect);
2464 						//!	Test
2465 #endif
2466 						SvxFont::DrawArrow( *pDev, aMarkRect, aMarkSize, aArrowFillCol, sal_False );
2467 					}
2468 				}
2469 				nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2470 			}
2471 		}
2472 		nPosY += pThisRowInfo->nHeight;
2473 	}
2474 
2475 	pDev->SetDrawMode(nOldDrawMode);
2476 }
2477 
2478 
2479 
2480