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