merge the formfield patch from ooo-build
[ooovba.git] / sc / source / ui / view / output.cxx
blob989ea0756956b48ed0dad27b4e952702134a0590
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: output.cxx,v $
10 * $Revision: 1.35.100.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 // INCLUDE ---------------------------------------------------------------
36 #include <com/sun/star/embed/EmbedMisc.hpp>
38 #include "scitems.hxx"
39 #include <svx/boxitem.hxx>
40 #include <svx/brshitem.hxx>
41 #include <svx/editdata.hxx>
42 #include <svtools/colorcfg.hxx>
43 #include <svx/rotmodit.hxx>
44 #include <svx/shaditem.hxx>
45 #include <svx/svxfont.hxx>
46 #include <svx/svdoole2.hxx>
47 #include <tools/poly.hxx>
48 #include <vcl/svapp.hxx>
49 #include <vcl/pdfextoutdevdata.hxx>
50 #include <svtools/accessibilityoptions.hxx>
51 #include <svx/framelinkarray.hxx>
53 #include "output.hxx"
54 #include "document.hxx"
55 #include "cell.hxx"
56 #include "attrib.hxx"
57 #include "patattr.hxx"
58 #include "docpool.hxx"
59 #include "tabvwsh.hxx"
60 #include "progress.hxx"
61 #include "pagedata.hxx"
62 #include "chgtrack.hxx"
63 #include "chgviset.hxx"
64 #include "viewutil.hxx"
65 #include "gridmerg.hxx"
66 #include "invmerge.hxx"
67 #include "fillinfo.hxx"
68 #include "scmod.hxx"
69 #include "appoptio.hxx"
70 #include "postit.hxx"
72 #include <math.h>
74 using namespace com::sun::star;
76 // STATIC DATA -----------------------------------------------------------
78 // Farben fuer ChangeTracking "nach Autor" wie im Writer (swmodul1.cxx)
80 #define SC_AUTHORCOLORCOUNT 9
82 static ColorData nAuthorColor[ SC_AUTHORCOLORCOUNT ] = {
83 COL_LIGHTRED, COL_LIGHTBLUE, COL_LIGHTMAGENTA,
84 COL_GREEN, COL_RED, COL_BLUE,
85 COL_BROWN, COL_MAGENTA, COL_CYAN };
87 // Hilfsklasse, fuer die Farbzuordnung,
88 // um nicht mehrfach hintereinander denselben User aus der Liste zu suchen
90 class ScActionColorChanger
92 private:
93 const ScAppOptions& rOpt;
94 const ScStrCollection& rUsers;
95 String aLastUserName;
96 USHORT nLastUserIndex;
97 ColorData nColor;
99 public:
100 ScActionColorChanger( const ScChangeTrack& rTrack );
101 ~ScActionColorChanger() {}
103 void Update( const ScChangeAction& rAction );
104 ColorData GetColor() const { return nColor; }
107 //------------------------------------------------------------------
109 ScActionColorChanger::ScActionColorChanger( const ScChangeTrack& rTrack ) :
110 rOpt( SC_MOD()->GetAppOptions() ),
111 rUsers( rTrack.GetUserCollection() ),
112 nLastUserIndex( 0 ),
113 nColor( COL_BLACK )
117 void ScActionColorChanger::Update( const ScChangeAction& rAction )
119 ColorData nSetColor;
120 switch (rAction.GetType())
122 case SC_CAT_INSERT_COLS:
123 case SC_CAT_INSERT_ROWS:
124 case SC_CAT_INSERT_TABS:
125 nSetColor = rOpt.GetTrackInsertColor();
126 break;
127 case SC_CAT_DELETE_COLS:
128 case SC_CAT_DELETE_ROWS:
129 case SC_CAT_DELETE_TABS:
130 nSetColor = rOpt.GetTrackDeleteColor();
131 break;
132 case SC_CAT_MOVE:
133 nSetColor = rOpt.GetTrackMoveColor();
134 break;
135 default:
136 nSetColor = rOpt.GetTrackContentColor();
137 break;
139 if ( nSetColor != COL_TRANSPARENT ) // Farbe eingestellt
140 nColor = nSetColor;
141 else // nach Autor
143 if ( rAction.GetUser() != aLastUserName )
145 aLastUserName = rAction.GetUser();
146 StrData aData(aLastUserName);
147 USHORT nIndex;
148 if (!rUsers.Search(&aData, nIndex))
150 // empty string is possible if a name wasn't found while saving a 5.0 file
151 DBG_ASSERT( aLastUserName.Len() == 0, "Author not found" );
152 nIndex = 0;
154 nLastUserIndex = nIndex % SC_AUTHORCOLORCOUNT;
156 nColor = nAuthorColor[nLastUserIndex];
160 //==================================================================
162 ScOutputData::ScOutputData( OutputDevice* pNewDev, ScOutputType eNewType,
163 ScTableInfo& rTabInfo, ScDocument* pNewDoc,
164 SCTAB nNewTab, long nNewScrX, long nNewScrY,
165 SCCOL nNewX1, SCROW nNewY1, SCCOL nNewX2, SCROW nNewY2,
166 double nPixelPerTwipsX, double nPixelPerTwipsY,
167 const Fraction* pZoomX, const Fraction* pZoomY ) :
168 pDev( pNewDev ),
169 pRefDevice( pNewDev ), // default is output device
170 pFmtDevice( pNewDev ), // default is output device
171 mrTabInfo( rTabInfo ),
172 pRowInfo( rTabInfo.mpRowInfo ),
173 nArrCount( rTabInfo.mnArrCount ),
174 pDoc( pNewDoc ),
175 nTab( nNewTab ),
176 nScrX( nNewScrX ),
177 nScrY( nNewScrY ),
178 nX1( nNewX1 ),
179 nY1( nNewY1 ),
180 nX2( nNewX2 ),
181 nY2( nNewY2 ),
182 eType( eNewType ),
183 nPPTX( nPixelPerTwipsX ),
184 nPPTY( nPixelPerTwipsY ),
185 pEditObj( NULL ),
186 pViewShell( NULL ),
187 pDrawView( NULL ), // #114135#
188 bEditMode( FALSE ),
189 bMetaFile( FALSE ),
190 bSingleGrid( FALSE ),
191 bPagebreakMode( FALSE ),
192 bSolidBackground( FALSE ),
193 bUseStyleColor( FALSE ),
194 bForceAutoColor( SC_MOD()->GetAccessOptions().GetIsAutomaticFontColor() ),
195 bSyntaxMode( FALSE ),
196 pValueColor( NULL ),
197 pTextColor( NULL ),
198 pFormulaColor( NULL ),
199 aGridColor( COL_BLACK ),
200 bShowNullValues( TRUE ),
201 bShowFormulas( FALSE ),
202 bShowSpellErrors( FALSE ),
203 bMarkClipped( FALSE ), // FALSE fuer Drucker/Metafile etc.
204 bSnapPixel( FALSE ),
205 bAnyRotated( FALSE ),
206 bAnyClipped( FALSE ),
207 mpTargetPaintWindow(0) // #i74769# use SdrPaintWindow direct
209 if (pZoomX)
210 aZoomX = *pZoomX;
211 else
212 aZoomX = Fraction(1,1);
213 if (pZoomY)
214 aZoomY = *pZoomY;
215 else
216 aZoomY = Fraction(1,1);
218 nVisX1 = nX1;
219 nVisY1 = nY1;
220 nVisX2 = nX2;
221 nVisY2 = nY2;
222 pDoc->StripHidden( nVisX1, nVisY1, nVisX2, nVisY2, nTab );
224 nScrW = 0;
225 for (SCCOL nX=nVisX1; nX<=nVisX2; nX++)
226 nScrW += pRowInfo[0].pCellInfo[nX+1].nWidth;
228 nMirrorW = nScrW;
230 nScrH = 0;
231 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
232 nScrH += pRowInfo[nArrY].nHeight;
234 bTabProtected = pDoc->IsTabProtected( nTab );
235 nTabTextDirection = pDoc->GetEditTextDirection( nTab );
236 bLayoutRTL = pDoc->IsLayoutRTL( nTab );
239 ScOutputData::~ScOutputData()
241 delete pValueColor;
242 delete pTextColor;
243 delete pFormulaColor;
246 void ScOutputData::SetContentDevice( OutputDevice* pContentDev )
248 // use pContentDev instead of pDev where used
250 if ( pRefDevice == pDev )
251 pRefDevice = pContentDev;
252 if ( pFmtDevice == pDev )
253 pFmtDevice = pContentDev;
254 pDev = pContentDev;
257 void ScOutputData::SetMirrorWidth( long nNew )
259 nMirrorW = nNew;
262 void ScOutputData::SetGridColor( const Color& rColor )
264 aGridColor = rColor;
267 void ScOutputData::SetMarkClipped( BOOL bSet )
269 bMarkClipped = bSet;
272 void ScOutputData::SetShowNullValues( BOOL bSet )
274 bShowNullValues = bSet;
277 void ScOutputData::SetShowFormulas( BOOL bSet )
279 bShowFormulas = bSet;
282 void ScOutputData::SetShowSpellErrors( BOOL bSet )
284 bShowSpellErrors = bSet;
287 void ScOutputData::SetSnapPixel( BOOL bSet )
289 bSnapPixel = bSet;
292 void ScOutputData::SetEditCell( SCCOL nCol, SCROW nRow )
294 nEditCol = nCol;
295 nEditRow = nRow;
296 bEditMode = TRUE;
299 void ScOutputData::SetMetaFileMode( BOOL bNewMode )
301 bMetaFile = bNewMode;
304 void ScOutputData::SetSingleGrid( BOOL bNewMode )
306 bSingleGrid = bNewMode;
309 void ScOutputData::SetSyntaxMode( BOOL bNewMode )
311 bSyntaxMode = bNewMode;
312 if (bNewMode)
313 if (!pValueColor)
315 pValueColor = new Color( COL_LIGHTBLUE );
316 pTextColor = new Color( COL_BLACK );
317 pFormulaColor = new Color( COL_GREEN );
321 void ScOutputData::DrawGrid( BOOL bGrid, BOOL bPage )
323 SCCOL nX;
324 SCROW nY;
325 long nPosX;
326 long nPosY;
327 SCSIZE nArrY;
328 ScBreakType nBreak = BREAK_NONE;
329 ScBreakType nBreakOld = BREAK_NONE;
331 BOOL bSingle;
332 Color aPageColor;
333 Color aManualColor;
335 if (bPagebreakMode)
336 bPage = FALSE; // keine "normalen" Umbrueche ueber volle Breite/Hoehe
338 //! um den einen Pixel sieht das Metafile (oder die Druck-Ausgabe) anders aus
339 //! als die Bildschirmdarstellung, aber wenigstens passen Druck und Metafile zusammen
341 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
342 long nOneX = aOnePixel.Width();
343 long nOneY = aOnePixel.Height();
344 if (bMetaFile)
345 nOneX = nOneY = 1;
347 long nLayoutSign = bLayoutRTL ? -1 : 1;
348 long nSignedOneX = nOneX * nLayoutSign;
350 if ( eType == OUTTYPE_WINDOW )
352 const svtools::ColorConfig& rColorCfg = SC_MOD()->GetColorConfig();
353 aPageColor.SetColor( rColorCfg.GetColorValue(svtools::CALCPAGEBREAKAUTOMATIC).nColor );
354 aManualColor.SetColor( rColorCfg.GetColorValue(svtools::CALCPAGEBREAKMANUAL).nColor );
356 else
358 aPageColor = aGridColor;
359 aManualColor = aGridColor;
362 pDev->SetLineColor( aGridColor );
363 ScGridMerger aGrid( pDev, nOneX, nOneY );
366 // Vertikale Linien
369 nPosX = nScrX;
370 if ( bLayoutRTL )
371 nPosX += nMirrorW - nOneX;
373 for (nX=nX1; nX<=nX2; nX++)
375 SCCOL nXplus1 = nX+1;
376 SCCOL nXplus2 = nX+2;
377 USHORT nWidth = pRowInfo[0].pCellInfo[nXplus1].nWidth;
378 if (nWidth)
380 nPosX += nWidth * nLayoutSign;
382 if ( bPage )
384 // Seitenumbrueche auch in ausgeblendeten suchen
385 SCCOL nCol = nXplus1;
386 while (nCol <= MAXCOL)
388 BYTE nDocFl = pDoc->GetColFlags( nCol, nTab );
389 nBreak = pDoc->HasColBreak(nCol, nTab);
390 bool bHidden = pDoc->ColHidden(nCol, nTab);
392 if ( nBreak || !bHidden )
393 break;
394 ++nCol;
397 if (nBreak != nBreakOld)
399 aGrid.Flush();
400 pDev->SetLineColor( (nBreak & BREAK_MANUAL) ? aManualColor :
401 nBreak ? aPageColor : aGridColor );
402 nBreakOld = nBreak;
406 BOOL bDraw = bGrid || nBreakOld; // einfaches Gitter nur wenn eingestellt
408 //! Mit dieser Abfrage wird zuviel weggelassen, wenn ein automatischer
409 //! Umbruch mitten in den Wiederholungsspalten liegt.
410 //! Dann lieber den aeusseren Rahmen zweimal ausgeben...
411 #if 0
412 // auf dem Drucker die Aussen-Linien weglassen (werden getrennt ausgegeben)
413 if ( eType == OUTTYPE_PRINTER && !bMetaFile )
415 if ( nX == MAXCOL )
416 bDraw = FALSE;
417 else if (pDoc->HasColBreak(nXplus1, nTab))
418 bDraw = FALSE;
420 #endif
422 USHORT nWidthXplus2 = pRowInfo[0].pCellInfo[nXplus2].nWidth;
423 bSingle = bSingleGrid; //! in Fillinfo holen !!!!!
424 if ( nX<MAXCOL && !bSingle )
426 bSingle = ( nWidthXplus2 == 0 );
427 for (nArrY=1; nArrY+1<nArrCount && !bSingle; nArrY++)
429 if (pRowInfo[nArrY].pCellInfo[nXplus2].bHOverlapped)
430 bSingle = TRUE;
431 if (pRowInfo[nArrY].pCellInfo[nXplus1].bHideGrid)
432 bSingle = TRUE;
436 if (bDraw)
438 if ( nX<MAXCOL && bSingle )
440 SCCOL nVisX = nXplus1;
441 while ( nVisX < MAXCOL && !pDoc->GetColWidth(nVisX,nTab) )
442 ++nVisX;
444 nPosY = nScrY;
445 long nNextY;
446 for (nArrY=1; nArrY+1<nArrCount; nArrY++)
448 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
449 nNextY = nPosY + pThisRowInfo->nHeight;
451 BOOL bHOver = pThisRowInfo->pCellInfo[nXplus1].bHideGrid;
452 if (!bHOver)
454 if (nWidthXplus2)
455 bHOver = pThisRowInfo->pCellInfo[nXplus2].bHOverlapped;
456 else
458 if (nVisX <= nX2)
459 bHOver = pThisRowInfo->pCellInfo[nVisX+1].bHOverlapped;
460 else
461 bHOver = ((ScMergeFlagAttr*)pDoc->GetAttr(
462 nVisX,pThisRowInfo->nRowNo,nTab,ATTR_MERGE_FLAG))
463 ->IsHorOverlapped();
464 if (bHOver)
465 bHOver = ((ScMergeFlagAttr*)pDoc->GetAttr(
466 nXplus1,pThisRowInfo->nRowNo,nTab,ATTR_MERGE_FLAG))
467 ->IsHorOverlapped();
471 if (pThisRowInfo->bChanged && !bHOver)
473 //Point aStart( nPosX-nSignedOneX, nPosY );
474 //Point aEnd( nPosX-nSignedOneX, nNextY-nOneY );
475 //pDev->DrawLine( aStart, aEnd );
476 aGrid.AddVerLine( nPosX-nSignedOneX, nPosY, nNextY-nOneY );
478 nPosY = nNextY;
481 else
483 //Point aStart( nPosX-nSignedOneX, nScrY );
484 //Point aEnd( nPosX-nSignedOneX, nScrY+nScrH-nOneY );
485 //pDev->DrawLine( aStart, aEnd );
486 aGrid.AddVerLine( nPosX-nSignedOneX, nScrY, nScrY+nScrH-nOneY );
493 // Horizontale Linien
496 nPosY = nScrY;
497 for (nArrY=1; nArrY+1<nArrCount; nArrY++)
499 SCSIZE nArrYplus1 = nArrY+1;
500 nY = pRowInfo[nArrY].nRowNo;
501 SCROW nYplus1 = nY+1;
502 nPosY += pRowInfo[nArrY].nHeight;
504 if (pRowInfo[nArrY].bChanged)
506 if ( bPage )
508 for (SCROW i = nYplus1; i <= MAXROW; ++i)
510 nBreak = pDoc->HasRowBreak(i, nTab);
511 bool bHidden = pDoc->RowHidden(i, nTab);
512 if (nBreak || !bHidden)
513 break;
516 if (nBreakOld != nBreak)
518 aGrid.Flush();
519 pDev->SetLineColor( (nBreak & BREAK_MANUAL) ? aManualColor :
520 (nBreak) ? aPageColor : aGridColor );
521 nBreakOld = nBreak;
525 BOOL bDraw = bGrid || nBreakOld; // einfaches Gitter nur wenn eingestellt
527 //! Mit dieser Abfrage wird zuviel weggelassen, wenn ein automatischer
528 //! Umbruch mitten in den Wiederholungszeilen liegt.
529 //! Dann lieber den aeusseren Rahmen zweimal ausgeben...
530 #if 0
531 // auf dem Drucker die Aussen-Linien weglassen (werden getrennt ausgegeben)
532 if ( eType == OUTTYPE_PRINTER && !bMetaFile )
534 if ( nY == MAXROW )
535 bDraw = FALSE;
536 else if (pDoc->HasRowBreak(nYplus1, nTab))
537 bDraw = FALSE;
539 #endif
541 BOOL bNextYisNextRow = (pRowInfo[nArrYplus1].nRowNo == nYplus1);
542 bSingle = !bNextYisNextRow; // Hidden
543 for (SCCOL i=nX1; i<=nX2 && !bSingle; i++)
545 if (pRowInfo[nArrYplus1].pCellInfo[i+1].bVOverlapped)
546 bSingle = TRUE;
549 if (bDraw)
551 if ( bSingle && nY<MAXROW )
553 SCROW nVisY = pRowInfo[nArrYplus1].nRowNo;
555 nPosX = nScrX;
556 if ( bLayoutRTL )
557 nPosX += nMirrorW - nOneX;
559 long nNextX;
560 for (SCCOL i=nX1; i<=nX2; i++)
562 nNextX = nPosX + pRowInfo[0].pCellInfo[i+1].nWidth * nLayoutSign;
563 if (nNextX != nPosX) // sichtbar
565 BOOL bVOver;
566 if ( bNextYisNextRow )
567 bVOver = pRowInfo[nArrYplus1].pCellInfo[i+1].bVOverlapped;
568 else
570 bVOver = ((ScMergeFlagAttr*)pDoc->GetAttr(
571 i,nYplus1,nTab,ATTR_MERGE_FLAG))
572 ->IsVerOverlapped()
573 && ((ScMergeFlagAttr*)pDoc->GetAttr(
574 i,nVisY,nTab,ATTR_MERGE_FLAG))
575 ->IsVerOverlapped();
576 //! nVisY aus Array ??
578 if (!bVOver)
580 //Point aStart( nPosX, nPosY-nOneY );
581 //Point aEnd( nNextX-nSignedOneX, nPosY-nOneY );
582 //pDev->DrawLine( aStart, aEnd );
583 aGrid.AddHorLine( nPosX, nNextX-nSignedOneX, nPosY-nOneY );
586 nPosX = nNextX;
589 else
591 //Point aStart( nScrX, nPosY-nOneY );
592 //Point aEnd( nScrX+nScrW-nOneX, nPosY-nOneY );
593 //pDev->DrawLine( aStart, aEnd );
594 aGrid.AddHorLine( nScrX, nScrX+nScrW-nOneX, nPosY-nOneY );
601 // ----------------------------------------------------------------------------
603 void ScOutputData::SetPagebreakMode( ScPageBreakData* pPageData )
605 bPagebreakMode = TRUE;
606 if (!pPageData)
607 return; // noch nicht initialisiert -> alles "nicht gedruckt"
609 // gedruckten Bereich markieren
610 // (in FillInfo ist schon alles auf FALSE initialisiert)
612 USHORT nRangeCount = sal::static_int_cast<USHORT>(pPageData->GetCount());
613 for (USHORT nPos=0; nPos<nRangeCount; nPos++)
615 ScRange aRange = pPageData->GetData( nPos ).GetPrintRange();
617 SCCOL nStartX = Max( aRange.aStart.Col(), nX1 );
618 SCCOL nEndX = Min( aRange.aEnd.Col(), nX2 );
619 SCROW nStartY = Max( aRange.aStart.Row(), nY1 );
620 SCROW nEndY = Min( aRange.aEnd.Row(), nY2 );
622 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
624 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
625 if ( pThisRowInfo->bChanged && pThisRowInfo->nRowNo >= nStartY &&
626 pThisRowInfo->nRowNo <= nEndY )
628 for (SCCOL nX=nStartX; nX<=nEndX; nX++)
629 pThisRowInfo->pCellInfo[nX+1].bPrinted = TRUE;
635 void ScOutputData::FindRotated()
637 //! nRotMax speichern
638 SCCOL nRotMax = nX2;
639 for (SCSIZE nRotY=0; nRotY<nArrCount; nRotY++)
640 if (pRowInfo[nRotY].nRotMaxCol != SC_ROTMAX_NONE && pRowInfo[nRotY].nRotMaxCol > nRotMax)
641 nRotMax = pRowInfo[nRotY].nRotMaxCol;
643 for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++)
645 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
646 if ( pThisRowInfo->nRotMaxCol != SC_ROTMAX_NONE &&
647 ( pThisRowInfo->bChanged || pRowInfo[nArrY-1].bChanged ||
648 ( nArrY+1<nArrCount && pRowInfo[nArrY+1].bChanged ) ) )
650 SCROW nY = pThisRowInfo->nRowNo;
652 for (SCCOL nX=0; nX<=nRotMax; nX++)
654 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
655 const ScPatternAttr* pPattern = pInfo->pPatternAttr;
656 const SfxItemSet* pCondSet = pInfo->pConditionSet;
658 if ( !pPattern && !pDoc->ColHidden(nX, nTab) )
660 pPattern = pDoc->GetPattern( nX, nY, nTab );
661 pCondSet = pDoc->GetCondResult( nX, nY, nTab );
664 if ( pPattern ) // Spalte nicht ausgeblendet
666 BYTE nDir = pPattern->GetRotateDir( pCondSet );
667 if (nDir != SC_ROTDIR_NONE)
669 pInfo->nRotateDir = nDir;
670 bAnyRotated = TRUE;
678 // ----------------------------------------------------------------------------
680 USHORT lcl_GetRotateDir( ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab )
682 const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
683 const SfxItemSet* pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
685 USHORT nRet = SC_ROTDIR_NONE;
687 long nAttrRotate = pPattern->GetRotateVal( pCondSet );
688 if ( nAttrRotate )
690 SvxRotateMode eRotMode = (SvxRotateMode)((const SvxRotateModeItem&)
691 pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet)).GetValue();
693 if ( eRotMode == SVX_ROTATE_MODE_STANDARD )
694 nRet = SC_ROTDIR_STANDARD;
695 else if ( eRotMode == SVX_ROTATE_MODE_CENTER )
696 nRet = SC_ROTDIR_CENTER;
697 else if ( eRotMode == SVX_ROTATE_MODE_TOP || eRotMode == SVX_ROTATE_MODE_BOTTOM )
699 long nRot180 = nAttrRotate % 18000; // 1/100 Grad
700 if ( nRot180 == 9000 )
701 nRet = SC_ROTDIR_CENTER;
702 else if ( ( eRotMode == SVX_ROTATE_MODE_TOP && nRot180 < 9000 ) ||
703 ( eRotMode == SVX_ROTATE_MODE_BOTTOM && nRot180 > 9000 ) )
704 nRet = SC_ROTDIR_LEFT;
705 else
706 nRet = SC_ROTDIR_RIGHT;
710 return nRet;
713 const SvxBrushItem* lcl_FindBackground( ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab )
715 const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
716 const SfxItemSet* pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
717 const SvxBrushItem* pBackground = (const SvxBrushItem*)
718 &pPattern->GetItem( ATTR_BACKGROUND, pCondSet );
720 USHORT nDir = lcl_GetRotateDir( pDoc, nCol, nRow, nTab );
722 // CENTER wird wie RIGHT behandelt...
723 if ( nDir == SC_ROTDIR_RIGHT || nDir == SC_ROTDIR_CENTER )
725 // Text geht nach rechts -> Hintergrund von links nehmen
726 while ( nCol > 0 && lcl_GetRotateDir( pDoc, nCol, nRow, nTab ) == nDir &&
727 pBackground->GetColor().GetTransparency() != 255 )
729 --nCol;
730 pPattern = pDoc->GetPattern( nCol, nRow, nTab );
731 pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
732 pBackground = (const SvxBrushItem*)&pPattern->GetItem( ATTR_BACKGROUND, pCondSet );
735 else if ( nDir == SC_ROTDIR_LEFT )
737 // Text geht nach links -> Hintergrund von rechts nehmen
738 while ( nCol < MAXCOL && lcl_GetRotateDir( pDoc, nCol, nRow, nTab ) == nDir &&
739 pBackground->GetColor().GetTransparency() != 255 )
741 ++nCol;
742 pPattern = pDoc->GetPattern( nCol, nRow, nTab );
743 pCondSet = pDoc->GetCondResult( nCol, nRow, nTab );
744 pBackground = (const SvxBrushItem*)&pPattern->GetItem( ATTR_BACKGROUND, pCondSet );
748 return pBackground;
751 // ----------------------------------------------------------------------------
753 BOOL lcl_EqualBack( const RowInfo& rFirst, const RowInfo& rOther,
754 SCCOL nX1, SCCOL nX2, BOOL bShowProt, BOOL bPagebreakMode )
756 if ( rFirst.bChanged != rOther.bChanged ||
757 rFirst.bEmptyBack != rOther.bEmptyBack )
758 return FALSE;
760 SCCOL nX;
761 if ( bShowProt )
763 for ( nX=nX1; nX<=nX2; nX++ )
765 const ScPatternAttr* pPat1 = rFirst.pCellInfo[nX+1].pPatternAttr;
766 const ScPatternAttr* pPat2 = rOther.pCellInfo[nX+1].pPatternAttr;
767 if ( !pPat1 || !pPat2 ||
768 &pPat1->GetItem(ATTR_PROTECTION) != &pPat2->GetItem(ATTR_PROTECTION) )
769 return FALSE;
772 else
774 for ( nX=nX1; nX<=nX2; nX++ )
775 if ( rFirst.pCellInfo[nX+1].pBackground != rOther.pCellInfo[nX+1].pBackground )
776 return FALSE;
779 if ( rFirst.nRotMaxCol != SC_ROTMAX_NONE || rOther.nRotMaxCol != SC_ROTMAX_NONE )
780 for ( nX=nX1; nX<=nX2; nX++ )
781 if ( rFirst.pCellInfo[nX+1].nRotateDir != rOther.pCellInfo[nX+1].nRotateDir )
782 return FALSE;
784 if ( bPagebreakMode )
785 for ( nX=nX1; nX<=nX2; nX++ )
786 if ( rFirst.pCellInfo[nX+1].bPrinted != rOther.pCellInfo[nX+1].bPrinted )
787 return FALSE;
789 return TRUE;
792 void ScOutputData::DrawDocumentBackground()
794 if ( !bSolidBackground )
795 return;
797 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
798 long nOneX = aOnePixel.Width();
799 long nOneY = aOnePixel.Height();
800 Rectangle aRect(nScrX - nOneX, nScrY - nOneY, nScrX + nScrW, nScrY + nScrH);
801 Color aBgColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor );
802 pDev->SetFillColor(aBgColor);
803 pDev->DrawRect(aRect);
806 void ScOutputData::DrawBackground()
808 FindRotated(); //! von aussen ?
810 Rectangle aRect;
811 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
812 long nOneX = aOnePixel.Width();
813 long nOneY = aOnePixel.Height();
815 if (bMetaFile)
816 nOneX = nOneY = 0;
818 long nLayoutSign = bLayoutRTL ? -1 : 1;
819 long nSignedOneX = nOneX * nLayoutSign;
821 pDev->SetLineColor();
823 BOOL bShowProt = bSyntaxMode && pDoc->IsTabProtected(nTab);
824 BOOL bDoAll = bShowProt || bPagebreakMode || bSolidBackground;
826 // #105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed TRUE)
827 BOOL bCellContrast = bUseStyleColor &&
828 Application::GetSettings().GetStyleSettings().GetHighContrastMode();
830 long nPosY = nScrY;
831 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
833 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
834 long nRowHeight = pThisRowInfo->nHeight;
836 if ( pThisRowInfo->bChanged )
838 if ( ( ( pThisRowInfo->bEmptyBack ) || bSyntaxMode ) && !bDoAll )
840 // nichts
842 else
844 // scan for rows with the same background:
845 SCSIZE nSkip = 0;
846 while ( nArrY+nSkip+2<nArrCount &&
847 lcl_EqualBack( *pThisRowInfo, pRowInfo[nArrY+nSkip+1],
848 nX1, nX2, bShowProt, bPagebreakMode ) )
850 ++nSkip;
851 nRowHeight += pRowInfo[nArrY+nSkip].nHeight; // after incrementing
854 long nPosX = nScrX;
855 if ( bLayoutRTL )
856 nPosX += nMirrorW - nOneX;
857 aRect = Rectangle( nPosX, nPosY-nOneY, nPosX, nPosY+nRowHeight-nOneY );
859 const SvxBrushItem* pOldBackground = NULL;
860 const SvxBrushItem* pBackground;
861 for (SCCOL nX=nX1; nX<=nX2; nX++)
863 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
865 if (bCellContrast)
867 // high contrast for cell borders and backgrounds -> empty background
868 pBackground = ScGlobal::GetEmptyBrushItem();
870 else if (bShowProt) // show cell protection in syntax mode
872 const ScPatternAttr* pP = pInfo->pPatternAttr;
873 if (pP)
875 const ScProtectionAttr& rProt = (const ScProtectionAttr&)
876 pP->GetItem(ATTR_PROTECTION);
877 if (rProt.GetProtection() || rProt.GetHideCell())
878 pBackground = ScGlobal::GetProtectedBrushItem();
879 else
880 pBackground = ScGlobal::GetEmptyBrushItem();
882 else
883 pBackground = NULL;
885 else
886 pBackground = pInfo->pBackground;
888 if ( bPagebreakMode && !pInfo->bPrinted )
889 pBackground = ScGlobal::GetProtectedBrushItem();
891 if ( pInfo->nRotateDir > SC_ROTDIR_STANDARD &&
892 pBackground->GetColor().GetTransparency() != 255 &&
893 !bCellContrast )
895 SCROW nY = pRowInfo[nArrY].nRowNo;
896 pBackground = lcl_FindBackground( pDoc, nX, nY, nTab );
899 if ( pBackground != pOldBackground )
901 aRect.Right() = nPosX-nSignedOneX;
902 if (pOldBackground) // ==0 if hidden
904 Color aBackCol = pOldBackground->GetColor();
905 if ( !aBackCol.GetTransparency() ) //! partial transparency?
907 pDev->SetFillColor( aBackCol );
908 pDev->DrawRect( aRect );
911 aRect.Left() = nPosX - nSignedOneX;
912 pOldBackground = pBackground;
914 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
916 aRect.Right() = nPosX-nSignedOneX;
917 if (pOldBackground)
919 Color aBackCol = pOldBackground->GetColor();
920 if ( !aBackCol.GetTransparency() ) //! partial transparency?
922 pDev->SetFillColor( aBackCol );
923 pDev->DrawRect( aRect );
927 nArrY += nSkip;
930 nPosY += nRowHeight;
934 void ScOutputData::DrawShadow()
936 DrawExtraShadow( FALSE, FALSE, FALSE, FALSE );
939 void ScOutputData::DrawExtraShadow(BOOL bLeft, BOOL bTop, BOOL bRight, BOOL bBottom)
941 pDev->SetLineColor();
943 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
944 // #105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed TRUE)
945 BOOL bCellContrast = bUseStyleColor && rStyleSettings.GetHighContrastMode();
946 Color aAutoTextColor;
947 if ( bCellContrast )
948 aAutoTextColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
950 long nInitPosX = nScrX;
951 if ( bLayoutRTL )
953 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
954 long nOneX = aOnePixel.Width();
955 nInitPosX += nMirrorW - nOneX;
957 long nLayoutSign = bLayoutRTL ? -1 : 1;
959 long nPosY = nScrY - pRowInfo[0].nHeight;
960 for (SCSIZE nArrY=0; nArrY<nArrCount; nArrY++)
962 BOOL bCornerY = ( nArrY == 0 ) || ( nArrY+1 == nArrCount );
963 BOOL bSkipY = ( nArrY==0 && !bTop ) || ( nArrY+1 == nArrCount && !bBottom );
965 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
966 long nRowHeight = pThisRowInfo->nHeight;
968 if ( pThisRowInfo->bChanged && !bSkipY )
970 long nPosX = nInitPosX - pRowInfo[0].pCellInfo[nX1].nWidth * nLayoutSign;
971 for (SCCOL nArrX=nX1; nArrX<=nX2+2; nArrX++)
973 BOOL bCornerX = ( nArrX==nX1 || nArrX==nX2+2 );
974 BOOL bSkipX = ( nArrX==nX1 && !bLeft ) || ( nArrX==nX2+2 && !bRight );
976 for (USHORT nPass=0; nPass<2; nPass++) // horizontal / vertikal
978 const SvxShadowItem* pAttr = nPass ?
979 pThisRowInfo->pCellInfo[nArrX].pVShadowOrigin :
980 pThisRowInfo->pCellInfo[nArrX].pHShadowOrigin;
981 if ( pAttr && !bSkipX )
983 ScShadowPart ePart = nPass ?
984 pThisRowInfo->pCellInfo[nArrX].eVShadowPart :
985 pThisRowInfo->pCellInfo[nArrX].eHShadowPart;
987 BOOL bDo = TRUE;
988 if ( (nPass==0 && bCornerX) || (nPass==1 && bCornerY) )
989 if ( ePart != SC_SHADOW_CORNER )
990 bDo = FALSE;
992 if (bDo)
994 long nThisWidth = pRowInfo[0].pCellInfo[nArrX].nWidth;
995 long nMaxWidth = nThisWidth;
996 if (!nMaxWidth)
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;
1005 // Rectangle aRect( Point(nPosX,nPosY),
1006 // Size( pRowInfo[0].pCellInfo[nArrX].nWidth,
1007 // pRowInfo[nArrY].nHeight ) );
1009 // rectangle is in logical orientation
1010 Rectangle aRect( nPosX, nPosY,
1011 nPosX + ( nThisWidth - 1 ) * nLayoutSign,
1012 nPosY + pRowInfo[nArrY].nHeight - 1 );
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;
1020 nSizeX *= nLayoutSign; // used only to add to rectangle values
1022 SvxShadowLocation eLoc = pAttr->GetLocation();
1023 if ( bLayoutRTL )
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)
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:
1035 // added to avoid warnings
1040 if (ePart == SC_SHADOW_HORIZ || ePart == SC_SHADOW_HSTART ||
1041 ePart == SC_SHADOW_CORNER)
1043 if (eLoc == SVX_SHADOW_TOPLEFT || eLoc == SVX_SHADOW_TOPRIGHT)
1044 aRect.Top() = aRect.Bottom() - nSizeY;
1045 else
1046 aRect.Bottom() = aRect.Top() + nSizeY;
1048 if (ePart == SC_SHADOW_VERT || ePart == SC_SHADOW_VSTART ||
1049 ePart == SC_SHADOW_CORNER)
1051 if (eLoc == SVX_SHADOW_TOPLEFT || eLoc == SVX_SHADOW_BOTTOMLEFT)
1052 aRect.Left() = aRect.Right() - nSizeX;
1053 else
1054 aRect.Right() = aRect.Left() + nSizeX;
1056 if (ePart == SC_SHADOW_HSTART)
1058 if (eLoc == SVX_SHADOW_TOPLEFT || eLoc == SVX_SHADOW_BOTTOMLEFT)
1059 aRect.Right() -= nSizeX;
1060 else
1061 aRect.Left() += nSizeX;
1063 if (ePart == SC_SHADOW_VSTART)
1065 if (eLoc == SVX_SHADOW_TOPLEFT || eLoc == SVX_SHADOW_TOPRIGHT)
1066 aRect.Bottom() -= nSizeY;
1067 else
1068 aRect.Top() += nSizeY;
1071 //! merge rectangles?
1072 pDev->SetFillColor( bCellContrast ? aAutoTextColor : pAttr->GetColor() );
1073 pDev->DrawRect( aRect );
1078 nPosX += pRowInfo[0].pCellInfo[nArrX].nWidth * nLayoutSign;
1081 nPosY += nRowHeight;
1086 // Loeschen
1089 void ScOutputData::DrawClear()
1091 Rectangle aRect;
1092 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1093 long nOneX = aOnePixel.Width();
1094 long nOneY = aOnePixel.Height();
1096 // (called only for ScGridWindow)
1097 Color aBgColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor );
1099 if (bMetaFile)
1100 nOneX = nOneY = 0;
1102 pDev->SetLineColor();
1104 pDev->SetFillColor( aBgColor );
1106 long nPosY = nScrY;
1107 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
1109 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1110 long nRowHeight = pThisRowInfo->nHeight;
1112 if ( pThisRowInfo->bChanged )
1114 // scan for more rows which must be painted:
1115 SCSIZE nSkip = 0;
1116 while ( nArrY+nSkip+2<nArrCount && pRowInfo[nArrY+nSkip+1].bChanged )
1118 ++nSkip;
1119 nRowHeight += pRowInfo[nArrY+nSkip].nHeight; // after incrementing
1122 aRect = Rectangle( Point( nScrX, nPosY ),
1123 Size( nScrW+1-nOneX, nRowHeight+1-nOneY) );
1124 pDev->DrawRect( aRect );
1126 nArrY += nSkip;
1128 nPosY += nRowHeight;
1134 // Linien
1137 long lclGetSnappedX( OutputDevice& rDev, long nPosX, bool bSnapPixel )
1139 return (bSnapPixel && nPosX) ? rDev.PixelToLogic( rDev.LogicToPixel( Size( nPosX, 0 ) ) ).Width() : nPosX;
1142 long lclGetSnappedY( OutputDevice& rDev, long nPosY, bool bSnapPixel )
1144 return (bSnapPixel && nPosY) ? rDev.PixelToLogic( rDev.LogicToPixel( Size( 0, nPosY ) ) ).Height() : nPosY;
1147 size_t lclGetArrayColFromCellInfoX( USHORT nCellInfoX, USHORT nCellInfoFirstX, USHORT nCellInfoLastX, bool bRTL )
1149 return static_cast< size_t >( bRTL ? (nCellInfoLastX + 2 - nCellInfoX) : (nCellInfoX - nCellInfoFirstX) );
1152 void ScOutputData::DrawFrame()
1154 ULONG nOldDrawMode = pDev->GetDrawMode();
1156 Color aSingleColor;
1157 BOOL bUseSingleColor = FALSE;
1158 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1159 // #105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed TRUE)
1160 BOOL bCellContrast = bUseStyleColor && rStyleSettings.GetHighContrastMode();
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.
1167 if ( ( nOldDrawMode & DRAWMODE_WHITEFILL ) && ( nOldDrawMode & DRAWMODE_BLACKLINE ) )
1169 pDev->SetDrawMode( nOldDrawMode & (~DRAWMODE_WHITEFILL) );
1170 aSingleColor.SetColor( COL_BLACK );
1171 bUseSingleColor = TRUE;
1173 else if ( ( nOldDrawMode & DRAWMODE_SETTINGSFILL ) && ( nOldDrawMode & DRAWMODE_SETTINGSLINE ) )
1175 pDev->SetDrawMode( nOldDrawMode & (~DRAWMODE_SETTINGSFILL) );
1176 aSingleColor = rStyleSettings.GetWindowTextColor(); // same as used in VCL for DRAWMODE_SETTINGSLINE
1177 bUseSingleColor = TRUE;
1179 else if ( bCellContrast )
1181 aSingleColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
1182 bUseSingleColor = TRUE;
1185 const Color* pForceColor = bUseSingleColor ? &aSingleColor : 0;
1187 if (bAnyRotated)
1188 DrawRotatedFrame( pForceColor ); // removes the lines that must not be painted here
1190 long nInitPosX = nScrX;
1191 if ( bLayoutRTL )
1193 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1194 long nOneX = aOnePixel.Width();
1195 nInitPosX += nMirrorW - nOneX;
1197 long nLayoutSign = bLayoutRTL ? -1 : 1;
1200 // *** set column and row sizes of the frame border array ***
1202 svx::frame::Array& rArray = mrTabInfo.maArray;
1203 size_t nColCount = rArray.GetColCount();
1204 size_t nRowCount = rArray.GetRowCount();
1206 // row heights
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 )
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;
1222 // column widths
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( USHORT nInfoIdx = nX1; nInfoIdx <= nX2 + 2; ++nInfoIdx )
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;
1240 if( bLayoutRTL )
1241 rArray.SetXOffset( nOldSnapX );
1243 // *** draw the array ***
1245 size_t nFirstCol = 1;
1246 size_t nFirstRow = 1;
1247 size_t nLastCol = nColCount - 2;
1248 size_t nLastRow = nRowCount - 2;
1250 if( mrTabInfo.mbPageMode )
1251 rArray.SetClipRange( nFirstCol, nFirstRow, nLastCol, nLastRow );
1253 // draw only rows with set RowInfo::bChanged flag
1254 size_t nRow1 = nFirstRow;
1255 while( nRow1 <= nLastRow )
1257 while( (nRow1 <= nLastRow) && !pRowInfo[ nRow1 ].bChanged ) ++nRow1;
1258 if( nRow1 <= nLastRow )
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;
1267 pDev->SetDrawMode(nOldDrawMode);
1270 // -------------------------------------------------------------------------
1272 // Linie unter der Zelle
1274 const SvxBorderLine* lcl_FindHorLine( ScDocument* pDoc,
1275 SCCOL nCol, SCROW nRow, SCTAB nTab, USHORT nRotDir,
1276 BOOL bTopLine )
1278 if ( nRotDir != SC_ROTDIR_LEFT && nRotDir != SC_ROTDIR_RIGHT )
1279 return NULL;
1281 BOOL bFound = FALSE;
1282 while (!bFound)
1284 if ( nRotDir == SC_ROTDIR_LEFT )
1286 // Text nach links -> Linie von rechts
1287 if ( nCol < MAXCOL )
1288 ++nCol;
1289 else
1290 return NULL; // war nix
1292 else
1294 // Text nach rechts -> Linie von links
1295 if ( nCol > 0 )
1296 --nCol;
1297 else
1298 return NULL; // war nix
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 = TRUE;
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;
1321 if ( ScHasPriority( pThisBottom, pNextTop ) )
1322 return pThisBottom;
1323 else
1324 return pNextTop;
1327 // lcl_HorizLine muss genau zu normal ausgegebenen Linien passen!
1329 void lcl_HorizLine( OutputDevice& rDev, const Point& rLeft, const Point& rRight,
1330 const svx::frame::Style& rLine, const Color* pForceColor )
1332 svx::frame::DrawHorFrameBorder( rDev, rLeft, rRight, rLine, pForceColor );
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 )
1339 rDev.SetLineColor(rColor); // PEN_NULL ???
1340 rDev.SetFillColor(rColor);
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();
1347 long nTopLeft = rTop.X() + nXOffs;
1348 long nTopRight = nTopLeft + nWidth - 1;
1350 long nBotLeft = rBottom.X() + nXOffs;
1351 long nBotRight = nBotLeft + nWidth - 1;
1353 // oben abschliessen
1355 if ( rTopLine.Prim() )
1357 long nLineW = rTopLine.GetWidth();
1358 if (nLineW >= 2)
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 );
1369 // unten abschliessen
1371 if ( rBottomLine.Prim() )
1373 long nLineW = rBottomLine.GetWidth();
1374 if (nLineW >= 2)
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 );
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 )
1391 if( rLine.Prim() )
1393 svx::frame::DrawVerFrameBorderSlanted( rDev, rTop, rBottom, rLine, pForceColor );
1395 svx::frame::Style aScaled( rLine );
1396 aScaled.ScaleSelf( 1.0 / cos( svx::frame::GetVerDiagAngle( rTop, rBottom ) ) );
1397 if( pForceColor )
1398 aScaled.SetColor( *pForceColor );
1400 long nXOffs = (aScaled.GetWidth() - 1) / -2L;
1402 lcl_VertLineEnds( rDev, rTop, rBottom, aScaled.GetColor(),
1403 nXOffs, aScaled.Prim(), rTopLine, rBottomLine );
1405 if( aScaled.Secn() )
1406 lcl_VertLineEnds( rDev, rTop, rBottom, aScaled.GetColor(),
1407 nXOffs + aScaled.Prim() + aScaled.Dist(), aScaled.Secn(), rTopLine, rBottomLine );
1411 void ScOutputData::DrawRotatedFrame( const Color* pForceColor )
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;
1419 const ScPatternAttr* pPattern;
1420 const SfxItemSet* pCondSet;
1422 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1423 // #105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed TRUE)
1424 BOOL bCellContrast = bUseStyleColor && rStyleSettings.GetHighContrastMode();
1426 // color (pForceColor) is determined externally, including DrawMode changes
1428 long nInitPosX = nScrX;
1429 if ( bLayoutRTL )
1431 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1432 long nOneX = aOnePixel.Width();
1433 nInitPosX += nMirrorW - nOneX;
1435 long nLayoutSign = bLayoutRTL ? -1 : 1;
1437 Rectangle aClipRect( Point(nScrX, nScrY), Size(nScrW, nScrH) );
1438 if (bMetaFile)
1440 pDev->Push();
1441 pDev->IntersectClipRegion( aClipRect );
1443 else
1444 pDev->SetClipRegion( Region( aClipRect ) );
1446 svx::frame::Array& rArray = mrTabInfo.maArray;
1448 long nPosY = nScrY;
1449 for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++)
1451 // Rotated wird auch 1 Zeile ueber/unter Changed gezeichnet, falls Teile
1452 // in die Zeile hineinragen...
1454 RowInfo& rPrevRowInfo = pRowInfo[nArrY-1];
1455 RowInfo& rThisRowInfo = pRowInfo[nArrY];
1456 RowInfo& rNextRowInfo = pRowInfo[nArrY+1];
1458 size_t nRow = static_cast< size_t >( nArrY );
1460 long nRowHeight = rThisRowInfo.nHeight;
1461 if ( rThisRowInfo.nRotMaxCol != SC_ROTMAX_NONE &&
1462 ( rThisRowInfo.bChanged || rPrevRowInfo.bChanged ||
1463 ( nArrY+1<nArrCount && rNextRowInfo.bChanged ) ) )
1465 SCROW nY = rThisRowInfo.nRowNo;
1466 long nPosX = 0;
1467 SCCOL nX;
1468 for (nX=0; nX<=nRotMax; nX++)
1470 if (nX==nX1) nPosX = nInitPosX; // calculated individually for preceding positions
1472 USHORT nArrX = nX + 1;
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 )
1479 pPattern = pInfo->pPatternAttr;
1480 pCondSet = pInfo->pConditionSet;
1481 if (!pPattern)
1483 pPattern = pDoc->GetPattern( nX, nY, nTab );
1484 pInfo->pPatternAttr = pPattern;
1485 pCondSet = pDoc->GetCondResult( nX, nY, nTab );
1486 pInfo->pConditionSet = pCondSet;
1489 //! LastPattern etc.
1491 long nAttrRotate = pPattern->GetRotateVal( pCondSet );
1492 SvxRotateMode eRotMode = (SvxRotateMode)((const SvxRotateModeItem&)
1493 pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet)).GetValue();
1495 if ( nAttrRotate )
1497 if (nX<nX1) // negative Position berechnen
1499 nPosX = nInitPosX;
1500 SCCOL nCol = nX1;
1501 while (nCol > nX)
1503 --nCol;
1504 nPosX -= nLayoutSign * (long) pRowInfo[0].pCellInfo[nCol+1].nWidth;
1508 // Startposition minus 1, damit auch schraege Hintergruende
1509 // zur Umrandung passen (Umrandung ist auf dem Gitter)
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;
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 );
1526 switch (eRotMode)
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:
1545 // added to avoid warnings
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 );
1555 const SvxBrushItem* pBackground = pInfo->pBackground;
1556 if (!pBackground)
1557 pBackground = (const SvxBrushItem*) &pPattern->GetItem(
1558 ATTR_BACKGROUND, pCondSet );
1559 if (bCellContrast)
1561 // high contrast for cell borders and backgrounds -> empty background
1562 pBackground = ScGlobal::GetEmptyBrushItem();
1564 const Color& rColor = pBackground->GetColor();
1565 if ( rColor.GetTransparency() != 255 )
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 )
1574 Polygon aPoly( 4, aPoints );
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 );
1587 svx::frame::Style aTopLine, aBottomLine, aLeftLine, aRightLine;
1589 if ( nX < nX1 || nX > nX2 ) // Attribute in FillInfo nicht gesetzt
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 );
1603 else
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 );
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 );
1618 lcl_VertLine( *pDev, aPoints[0], aPoints[3], aLeftLine, aTopLine, aBottomLine, pForceColor );
1619 lcl_VertLine( *pDev, aPoints[1], aPoints[2], aRightLine, aTopLine, aBottomLine, pForceColor );
1622 nPosX += nColWidth * nLayoutSign;
1625 // erst hinterher im zweiten Schritt die Linien fuer normale Ausgabe loeschen
1627 nX = nX1 > 0 ? (nX1-1) : static_cast<SCCOL>(0);
1628 for (; nX<=nX2+1; nX++) // sichtbarer Teil +- 1
1630 USHORT nArrX = nX + 1;
1631 CellInfo& rInfo = rThisRowInfo.pCellInfo[nArrX];
1632 if ( rInfo.nRotateDir > SC_ROTDIR_STANDARD &&
1633 !rInfo.bHOverlapped && !rInfo.bVOverlapped )
1635 pPattern = rInfo.pPatternAttr;
1636 pCondSet = rInfo.pConditionSet;
1637 SvxRotateMode eRotMode = (SvxRotateMode)((const SvxRotateModeItem&)
1638 pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet)).GetValue();
1640 size_t nCol = lclGetArrayColFromCellInfoX( nArrX, nX1, nX2, bLayoutRTL );
1642 // horizontal: angrenzende Linie verlaengern
1643 // (nur, wenn die gedrehte Zelle eine Umrandung hat)
1644 USHORT nDir = rInfo.nRotateDir;
1645 if ( rArray.GetCellStyleTop( nCol, nRow ).Prim() && eRotMode != SVX_ROTATE_MODE_TOP )
1647 svx::frame::Style aStyle( lcl_FindHorLine( pDoc, nX, nY, nTab, nDir, TRUE ), nPPTY );
1648 rArray.SetCellStyleTop( nCol, nRow, aStyle );
1649 if( nRow > 0 )
1650 rArray.SetCellStyleBottom( nCol, nRow - 1, aStyle );
1652 if ( rArray.GetCellStyleBottom( nCol, nRow ).Prim() && eRotMode != SVX_ROTATE_MODE_BOTTOM )
1654 svx::frame::Style aStyle( lcl_FindHorLine( pDoc, nX, nY, nTab, nDir, FALSE ), nPPTY );
1655 rArray.SetCellStyleBottom( nCol, nRow, aStyle );
1656 if( nRow + 1 < rArray.GetRowCount() )
1657 rArray.SetCellStyleTop( nCol, nRow + 1, aStyle );
1660 // always remove vertical borders
1661 if( !rArray.IsMergedOverlappedLeft( nCol, nRow ) )
1663 rArray.SetCellStyleLeft( nCol, nRow, svx::frame::Style() );
1664 if( nCol > 0 )
1665 rArray.SetCellStyleRight( nCol - 1, nRow, svx::frame::Style() );
1667 if( !rArray.IsMergedOverlappedRight( nCol, nRow ) )
1669 rArray.SetCellStyleRight( nCol, nRow, svx::frame::Style() );
1670 if( nCol + 1 < rArray.GetColCount() )
1671 rArray.SetCellStyleLeft( nCol + 1, nRow, svx::frame::Style() );
1674 // remove diagonal borders
1675 rArray.SetCellStyleTLBR( nCol, nRow, svx::frame::Style() );
1676 rArray.SetCellStyleBLTR( nCol, nRow, svx::frame::Style() );
1680 nPosY += nRowHeight;
1683 if (bMetaFile)
1684 pDev->Pop();
1685 else
1686 pDev->SetClipRegion();
1689 // Drucker
1691 PolyPolygon ScOutputData::GetChangedArea()
1693 PolyPolygon aPoly;
1695 Rectangle aDrawingRect;
1696 aDrawingRect.Left() = nScrX;
1697 aDrawingRect.Right() = nScrX+nScrW-1;
1699 BOOL bHad = FALSE;
1700 long nPosY = nScrY;
1701 SCSIZE nArrY;
1702 for (nArrY=1; nArrY+1<nArrCount; nArrY++)
1704 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1706 if ( pThisRowInfo->bChanged )
1708 if (!bHad)
1710 aDrawingRect.Top() = nPosY;
1711 bHad = TRUE;
1713 aDrawingRect.Bottom() = nPosY + pRowInfo[nArrY].nHeight - 1;
1715 else if (bHad)
1717 aPoly.Insert( Polygon( pDev->PixelToLogic(aDrawingRect) ) );
1718 bHad = FALSE;
1720 nPosY += pRowInfo[nArrY].nHeight;
1723 if (bHad)
1724 aPoly.Insert( Polygon( pDev->PixelToLogic(aDrawingRect) ) );
1726 return aPoly;
1729 BOOL ScOutputData::SetChangedClip()
1731 PolyPolygon aPoly;
1733 Rectangle aDrawingRect;
1734 aDrawingRect.Left() = nScrX;
1735 aDrawingRect.Right() = nScrX+nScrW-1;
1737 BOOL bHad = FALSE;
1738 long nPosY = nScrY;
1739 SCSIZE nArrY;
1740 for (nArrY=1; nArrY+1<nArrCount; nArrY++)
1742 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1744 if ( pThisRowInfo->bChanged )
1746 if (!bHad)
1748 aDrawingRect.Top() = nPosY;
1749 bHad = TRUE;
1751 aDrawingRect.Bottom() = nPosY + pRowInfo[nArrY].nHeight - 1;
1753 else if (bHad)
1755 aPoly.Insert( Polygon( pDev->PixelToLogic(aDrawingRect) ) );
1756 bHad = FALSE;
1758 nPosY += pRowInfo[nArrY].nHeight;
1761 if (bHad)
1762 aPoly.Insert( Polygon( pDev->PixelToLogic(aDrawingRect) ) );
1764 BOOL bRet = (aPoly.Count() != 0);
1765 if (bRet)
1766 pDev->SetClipRegion(Region(aPoly));
1767 return bRet;
1770 void ScOutputData::FindChanged()
1772 SCCOL nX;
1773 SCSIZE nArrY;
1775 BOOL bWasIdleDisabled = pDoc->IsIdleDisabled();
1776 pDoc->DisableIdle( TRUE );
1777 for (nArrY=0; nArrY<nArrCount; nArrY++)
1778 pRowInfo[nArrY].bChanged = FALSE;
1780 BOOL bProgress = FALSE;
1781 for (nArrY=0; nArrY<nArrCount; nArrY++)
1783 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1784 for (nX=nX1; nX<=nX2; nX++)
1786 ScBaseCell* pCell = pThisRowInfo->pCellInfo[nX+1].pCell;
1787 if (pCell)
1788 if (pCell->GetCellType() == CELLTYPE_FORMULA)
1790 ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
1791 if ( !bProgress && pFCell->GetDirty() )
1793 ScProgress::CreateInterpretProgress( pDoc, TRUE );
1794 bProgress = TRUE;
1796 if (!pFCell->IsRunning())
1798 (void)pFCell->GetValue();
1799 if (pFCell->IsChanged())
1801 pThisRowInfo->bChanged = TRUE;
1802 if ( pThisRowInfo->pCellInfo[nX+1].bMerged )
1804 SCSIZE nOverY = nArrY + 1;
1805 while ( nOverY<nArrCount &&
1806 pRowInfo[nOverY].pCellInfo[nX+1].bVOverlapped )
1808 pRowInfo[nOverY].bChanged = TRUE;
1809 ++nOverY;
1817 if ( bProgress )
1818 ScProgress::DeleteInterpretProgress();
1819 pDoc->DisableIdle( bWasIdleDisabled );
1822 #ifdef OLD_SELECTION_PAINT
1823 void ScOutputData::DrawMark( Window* pWin )
1825 Rectangle aRect;
1826 ScInvertMerger aInvert( pWin );
1827 //! additional method AddLineRect for ScInvertMerger?
1829 long nPosY = nScrY;
1830 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
1832 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1833 if (pThisRowInfo->bChanged)
1835 long nPosX = nScrX;
1836 if (bLayoutRTL)
1837 nPosX += nMirrorW - 1; // always in pixels
1839 aRect = Rectangle( Point( nPosX,nPosY ), Size(1, pThisRowInfo->nHeight) );
1840 if (bLayoutRTL)
1841 aRect.Left() = aRect.Right() + 1;
1842 else
1843 aRect.Right() = aRect.Left() - 1;
1845 BOOL bOldMarked = FALSE;
1846 for (SCCOL nX=nX1; nX<=nX2; nX++)
1848 if (pThisRowInfo->pCellInfo[nX+1].bMarked != bOldMarked)
1850 if (bOldMarked && aRect.Right() >= aRect.Left())
1851 aInvert.AddRect( aRect );
1853 if (bLayoutRTL)
1854 aRect.Right() = nPosX;
1855 else
1856 aRect.Left() = nPosX;
1858 bOldMarked = pThisRowInfo->pCellInfo[nX+1].bMarked;
1861 if (bLayoutRTL)
1863 nPosX -= pRowInfo[0].pCellInfo[nX+1].nWidth;
1864 aRect.Left() = nPosX+1;
1866 else
1868 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth;
1869 aRect.Right() = nPosX-1;
1872 if (bOldMarked && aRect.Right() >= aRect.Left())
1873 aInvert.AddRect( aRect );
1875 nPosY += pThisRowInfo->nHeight;
1878 #endif
1880 void ScOutputData::DrawRefMark( SCCOL nRefStartX, SCROW nRefStartY,
1881 SCCOL nRefEndX, SCROW nRefEndY,
1882 const Color& rColor, BOOL bHandle )
1884 PutInOrder( nRefStartX, nRefEndX );
1885 PutInOrder( nRefStartY, nRefEndY );
1887 if ( nRefStartX == nRefEndX && nRefStartY == nRefEndY )
1888 pDoc->ExtendMerge( nRefStartX, nRefStartY, nRefEndX, nRefEndY, nTab );
1890 if ( nRefStartX <= nVisX2 && nRefEndX >= nVisX1 &&
1891 nRefStartY <= nVisY2 && nRefEndY >= nVisY1 )
1893 long nMinX = nScrX;
1894 long nMinY = nScrY;
1895 long nMaxX = nScrX+nScrW-1;
1896 long nMaxY = nScrY+nScrH-1;
1897 if ( bLayoutRTL )
1899 long nTemp = nMinX;
1900 nMinX = nMaxX;
1901 nMaxX = nTemp;
1903 long nLayoutSign = bLayoutRTL ? -1 : 1;
1905 BOOL bTop = FALSE;
1906 BOOL bBottom = FALSE;
1907 BOOL bLeft = FALSE;
1908 BOOL bRight = FALSE;
1910 long nPosY = nScrY;
1911 BOOL bNoStartY = ( nY1 < nRefStartY );
1912 BOOL bNoEndY = FALSE;
1913 for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++) // loop to end for bNoEndY check
1915 SCROW nY = pRowInfo[nArrY].nRowNo;
1917 if ( nY==nRefStartY || (nY>nRefStartY && bNoStartY) )
1919 nMinY = nPosY;
1920 bTop = TRUE;
1922 if ( nY==nRefEndY )
1924 nMaxY = nPosY + pRowInfo[nArrY].nHeight - 2;
1925 bBottom = TRUE;
1927 if ( nY>nRefEndY && bNoEndY )
1929 nMaxY = nPosY-2;
1930 bBottom = TRUE;
1932 bNoStartY = ( nY < nRefStartY );
1933 bNoEndY = ( nY < nRefEndY );
1934 nPosY += pRowInfo[nArrY].nHeight;
1937 long nPosX = nScrX;
1938 if ( bLayoutRTL )
1939 nPosX += nMirrorW - 1; // always in pixels
1941 for (SCCOL nX=nX1; nX<=nX2; nX++)
1943 if ( nX==nRefStartX )
1945 nMinX = nPosX;
1946 bLeft = TRUE;
1948 if ( nX==nRefEndX )
1950 nMaxX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - 2 ) * nLayoutSign;
1951 bRight = TRUE;
1953 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
1956 if ( nMaxX * nLayoutSign >= nMinX * nLayoutSign &&
1957 nMaxY >= nMinY )
1959 pDev->SetLineColor( rColor );
1960 if (bTop && bBottom && bLeft && bRight)
1962 pDev->SetFillColor();
1963 pDev->DrawRect( Rectangle( nMinX, nMinY, nMaxX, nMaxY ) );
1965 else
1967 if (bTop)
1968 pDev->DrawLine( Point( nMinX,nMinY ), Point( nMaxX,nMinY ) );
1969 if (bBottom)
1970 pDev->DrawLine( Point( nMinX,nMaxY ), Point( nMaxX,nMaxY ) );
1971 if (bLeft)
1972 pDev->DrawLine( Point( nMinX,nMinY ), Point( nMinX,nMaxY ) );
1973 if (bRight)
1974 pDev->DrawLine( Point( nMaxX,nMinY ), Point( nMaxX,nMaxY ) );
1976 if ( bHandle && bRight && bBottom )
1978 pDev->SetLineColor();
1979 pDev->SetFillColor( rColor );
1980 pDev->DrawRect( Rectangle( nMaxX-3*nLayoutSign, nMaxY-3, nMaxX+nLayoutSign, nMaxY+1 ) );
1986 void ScOutputData::DrawOneChange( SCCOL nRefStartX, SCROW nRefStartY,
1987 SCCOL nRefEndX, SCROW nRefEndY,
1988 const Color& rColor, USHORT nType )
1990 PutInOrder( nRefStartX, nRefEndX );
1991 PutInOrder( nRefStartY, nRefEndY );
1993 if ( nRefStartX == nRefEndX && nRefStartY == nRefEndY )
1994 pDoc->ExtendMerge( nRefStartX, nRefStartY, nRefEndX, nRefEndY, nTab );
1996 if ( nRefStartX <= nVisX2 + 1 && nRefEndX >= nVisX1 &&
1997 nRefStartY <= nVisY2 + 1 && nRefEndY >= nVisY1 ) // +1 because it touches next cells left/top
1999 long nMinX = nScrX;
2000 long nMinY = nScrY;
2001 long nMaxX = nScrX+nScrW-1;
2002 long nMaxY = nScrY+nScrH-1;
2003 if ( bLayoutRTL )
2005 long nTemp = nMinX;
2006 nMinX = nMaxX;
2007 nMaxX = nTemp;
2009 long nLayoutSign = bLayoutRTL ? -1 : 1;
2011 BOOL bTop = FALSE;
2012 BOOL bBottom = FALSE;
2013 BOOL bLeft = FALSE;
2014 BOOL bRight = FALSE;
2016 long nPosY = nScrY;
2017 BOOL bNoStartY = ( nY1 < nRefStartY );
2018 BOOL bNoEndY = FALSE;
2019 for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++) // loop to end for bNoEndY check
2021 SCROW nY = pRowInfo[nArrY].nRowNo;
2023 if ( nY==nRefStartY || (nY>nRefStartY && bNoStartY) )
2025 nMinY = nPosY - 1;
2026 bTop = TRUE;
2028 if ( nY==nRefEndY )
2030 nMaxY = nPosY + pRowInfo[nArrY].nHeight - 1;
2031 bBottom = TRUE;
2033 if ( nY>nRefEndY && bNoEndY )
2035 nMaxY = nPosY - 1;
2036 bBottom = TRUE;
2038 bNoStartY = ( nY < nRefStartY );
2039 bNoEndY = ( nY < nRefEndY );
2040 nPosY += pRowInfo[nArrY].nHeight;
2043 long nPosX = nScrX;
2044 if ( bLayoutRTL )
2045 nPosX += nMirrorW - 1; // always in pixels
2047 for (SCCOL nX=nX1; nX<=nX2+1; nX++)
2049 if ( nX==nRefStartX )
2051 nMinX = nPosX - nLayoutSign;
2052 bLeft = TRUE;
2054 if ( nX==nRefEndX )
2056 nMaxX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - 1 ) * nLayoutSign;
2057 bRight = TRUE;
2059 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2062 if ( nMaxX * nLayoutSign >= nMinX * nLayoutSign &&
2063 nMaxY >= nMinY )
2065 if ( nType == SC_CAT_DELETE_ROWS )
2066 bLeft = bRight = bBottom = FALSE; //! dicke Linie ???
2067 else if ( nType == SC_CAT_DELETE_COLS )
2068 bTop = bBottom = bRight = FALSE; //! dicke Linie ???
2070 pDev->SetLineColor( rColor );
2071 if (bTop && bBottom && bLeft && bRight)
2073 pDev->SetFillColor();
2074 pDev->DrawRect( Rectangle( nMinX, nMinY, nMaxX, nMaxY ) );
2076 else
2078 if (bTop)
2080 pDev->DrawLine( Point( nMinX,nMinY ), Point( nMaxX,nMinY ) );
2081 if ( nType == SC_CAT_DELETE_ROWS )
2082 pDev->DrawLine( Point( nMinX,nMinY+1 ), Point( nMaxX,nMinY+1 ) );
2084 if (bBottom)
2085 pDev->DrawLine( Point( nMinX,nMaxY ), Point( nMaxX,nMaxY ) );
2086 if (bLeft)
2088 pDev->DrawLine( Point( nMinX,nMinY ), Point( nMinX,nMaxY ) );
2089 if ( nType == SC_CAT_DELETE_COLS )
2090 pDev->DrawLine( Point( nMinX+nLayoutSign,nMinY ), Point( nMinX+nLayoutSign,nMaxY ) );
2092 if (bRight)
2093 pDev->DrawLine( Point( nMaxX,nMinY ), Point( nMaxX,nMaxY ) );
2095 if ( bLeft && bTop )
2097 pDev->SetLineColor();
2098 pDev->SetFillColor( rColor );
2099 pDev->DrawRect( Rectangle( nMinX+nLayoutSign, nMinY+1, nMinX+3*nLayoutSign, nMinY+3 ) );
2105 void ScOutputData::DrawChangeTrack()
2107 ScChangeTrack* pTrack = pDoc->GetChangeTrack();
2108 ScChangeViewSettings* pSettings = pDoc->GetChangeViewSettings();
2109 if ( !pTrack || !pTrack->GetFirst() || !pSettings || !pSettings->ShowChanges() )
2110 return; // nix da oder abgeschaltet
2112 ScActionColorChanger aColorChanger(*pTrack);
2114 // Clipping passiert von aussen
2115 //! ohne Clipping, nur betroffene Zeilen painten ??!??!?
2117 SCCOL nEndX = nX2;
2118 SCROW nEndY = nY2;
2119 if ( nEndX < MAXCOL ) ++nEndX; // auch noch von der naechsten Zelle, weil die Markierung
2120 if ( nEndY < MAXROW ) ++nEndY; // in die jeweils vorhergehende Zelle hineinragt
2121 ScRange aViewRange( nX1, nY1, nTab, nEndX, nEndY, nTab );
2122 const ScChangeAction* pAction = pTrack->GetFirst();
2123 while (pAction)
2125 ScChangeActionType eActionType;
2126 if ( pAction->IsVisible() )
2128 eActionType = pAction->GetType();
2129 const ScBigRange& rBig = pAction->GetBigRange();
2130 if ( rBig.aStart.Tab() == nTab )
2132 ScRange aRange = rBig.MakeRange();
2134 if ( eActionType == SC_CAT_DELETE_ROWS )
2135 aRange.aEnd.SetRow( aRange.aStart.Row() );
2136 else if ( eActionType == SC_CAT_DELETE_COLS )
2137 aRange.aEnd.SetCol( aRange.aStart.Col() );
2139 if ( aRange.Intersects( aViewRange ) &&
2140 ScViewUtil::IsActionShown( *pAction, *pSettings, *pDoc ) )
2142 aColorChanger.Update( *pAction );
2143 Color aColor( aColorChanger.GetColor() );
2144 DrawOneChange( aRange.aStart.Col(), aRange.aStart.Row(),
2145 aRange.aEnd.Col(), aRange.aEnd.Row(), aColor, sal::static_int_cast<USHORT>(eActionType) );
2149 if ( eActionType == SC_CAT_MOVE &&
2150 ((const ScChangeActionMove*)pAction)->
2151 GetFromRange().aStart.Tab() == nTab )
2153 ScRange aRange = ((const ScChangeActionMove*)pAction)->
2154 GetFromRange().MakeRange();
2155 if ( aRange.Intersects( aViewRange ) &&
2156 ScViewUtil::IsActionShown( *pAction, *pSettings, *pDoc ) )
2158 aColorChanger.Update( *pAction );
2159 Color aColor( aColorChanger.GetColor() );
2160 DrawOneChange( aRange.aStart.Col(), aRange.aStart.Row(),
2161 aRange.aEnd.Col(), aRange.aEnd.Row(), aColor, sal::static_int_cast<USHORT>(eActionType) );
2166 pAction = pAction->GetNext();
2170 void ScOutputData::DrawNoteMarks()
2172 BOOL bFirst = TRUE;
2174 long nInitPosX = nScrX;
2175 if ( bLayoutRTL )
2176 nInitPosX += nMirrorW - 1; // always in pixels
2177 long nLayoutSign = bLayoutRTL ? -1 : 1;
2179 long nPosY = nScrY;
2180 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
2182 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
2183 if ( pThisRowInfo->bChanged )
2185 long nPosX = nInitPosX;
2186 for (SCCOL nX=nX1; nX<=nX2; nX++)
2188 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
2189 ScBaseCell* pCell = pInfo->pCell;
2190 BOOL bIsMerged = FALSE;
2192 if ( nX==nX1 && pInfo->bHOverlapped && !pInfo->bVOverlapped )
2194 // find start of merged cell
2195 bIsMerged = TRUE;
2196 SCROW nY = pRowInfo[nArrY].nRowNo;
2197 SCCOL nMergeX = nX;
2198 SCROW nMergeY = nY;
2199 pDoc->ExtendOverlapped( nMergeX, nMergeY, nX, nY, nTab );
2200 pCell = pDoc->GetCell( ScAddress(nMergeX,nMergeY,nTab) );
2201 // use origin's pCell for NotePtr test below
2204 if ( pCell && pCell->HasNote() && ( bIsMerged ||
2205 ( !pInfo->bHOverlapped && !pInfo->bVOverlapped ) ) )
2207 if (bFirst)
2209 pDev->SetLineColor();
2211 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
2212 if ( bUseStyleColor && rStyleSettings.GetHighContrastMode() )
2213 pDev->SetFillColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
2214 else
2215 pDev->SetFillColor(COL_LIGHTRED);
2217 bFirst = FALSE;
2220 long nMarkX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - 4 ) * nLayoutSign;
2221 if ( bIsMerged || pInfo->bMerged )
2223 // if merged, add widths of all cells
2224 SCCOL nNextX = nX + 1;
2225 while ( nNextX <= nX2 + 1 && pThisRowInfo->pCellInfo[nNextX+1].bHOverlapped )
2227 nMarkX += pRowInfo[0].pCellInfo[nNextX+1].nWidth * nLayoutSign;
2228 ++nNextX;
2231 if ( bLayoutRTL ? ( nMarkX >= 0 ) : ( nMarkX < nScrX+nScrW ) )
2232 pDev->DrawRect( Rectangle( nMarkX,nPosY,nMarkX+2*nLayoutSign,nPosY+2 ) );
2235 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2238 nPosY += pThisRowInfo->nHeight;
2242 void ScOutputData::AddPDFNotes()
2244 vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, pDev->GetExtOutDevData() );
2245 if ( !pPDFData || !pPDFData->GetIsExportNotes() )
2246 return;
2248 long nInitPosX = nScrX;
2249 if ( bLayoutRTL )
2251 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
2252 long nOneX = aOnePixel.Width();
2253 nInitPosX += nMirrorW - nOneX;
2255 long nLayoutSign = bLayoutRTL ? -1 : 1;
2257 long nPosY = nScrY;
2258 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
2260 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
2261 if ( pThisRowInfo->bChanged )
2263 long nPosX = nInitPosX;
2264 for (SCCOL nX=nX1; nX<=nX2; nX++)
2266 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
2267 ScBaseCell* pCell = pInfo->pCell;
2268 BOOL bIsMerged = FALSE;
2269 SCROW nY = pRowInfo[nArrY].nRowNo;
2270 SCCOL nMergeX = nX;
2271 SCROW nMergeY = nY;
2273 if ( nX==nX1 && pInfo->bHOverlapped && !pInfo->bVOverlapped )
2275 // find start of merged cell
2276 bIsMerged = TRUE;
2277 pDoc->ExtendOverlapped( nMergeX, nMergeY, nX, nY, nTab );
2278 pCell = pDoc->GetCell( ScAddress(nMergeX,nMergeY,nTab) );
2279 // use origin's pCell for NotePtr test below
2282 if ( pCell && pCell->HasNote() && ( bIsMerged ||
2283 ( !pInfo->bHOverlapped && !pInfo->bVOverlapped ) ) )
2285 long nNoteWidth = (long)( SC_CLIPMARK_SIZE * nPPTX );
2286 long nNoteHeight = (long)( SC_CLIPMARK_SIZE * nPPTY );
2288 long nMarkX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - nNoteWidth ) * nLayoutSign;
2289 if ( bIsMerged || pInfo->bMerged )
2291 // if merged, add widths of all cells
2292 SCCOL nNextX = nX + 1;
2293 while ( nNextX <= nX2 + 1 && pThisRowInfo->pCellInfo[nNextX+1].bHOverlapped )
2295 nMarkX += pRowInfo[0].pCellInfo[nNextX+1].nWidth * nLayoutSign;
2296 ++nNextX;
2299 if ( bLayoutRTL ? ( nMarkX >= 0 ) : ( nMarkX < nScrX+nScrW ) )
2301 Rectangle aNoteRect( nMarkX, nPosY, nMarkX+nNoteWidth*nLayoutSign, nPosY+nNoteHeight );
2302 const ScPostIt* pNote = pCell->GetNote();
2304 // Note title is the cell address (as on printed note pages)
2305 String aTitle;
2306 ScAddress aAddress( nMergeX, nMergeY, nTab );
2307 aAddress.Format( aTitle, SCA_VALID, pDoc, pDoc->GetAddressConvention() );
2309 // Content has to be a simple string without line breaks
2310 String aContent = pNote->GetText();
2311 xub_StrLen nPos;
2312 while ( (nPos=aContent.Search('\n')) != STRING_NOTFOUND )
2313 aContent.SetChar( nPos, ' ' );
2315 vcl::PDFNote aNote;
2316 aNote.Title = aTitle;
2317 aNote.Contents = aContent;
2318 pPDFData->CreateNote( aNoteRect, aNote );
2322 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2325 nPosY += pThisRowInfo->nHeight;
2329 void ScOutputData::DrawClipMarks()
2331 if (!bAnyClipped)
2332 return;
2334 Color aArrowFillCol( COL_LIGHTRED );
2336 ULONG nOldDrawMode = pDev->GetDrawMode();
2337 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
2338 if ( bUseStyleColor && rStyleSettings.GetHighContrastMode() )
2340 // use DrawMode to change the arrow's outline color
2341 pDev->SetDrawMode( nOldDrawMode | DRAWMODE_SETTINGSLINE );
2342 // use text color also for the fill color
2343 aArrowFillCol.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
2346 long nInitPosX = nScrX;
2347 if ( bLayoutRTL )
2348 nInitPosX += nMirrorW - 1; // always in pixels
2349 long nLayoutSign = bLayoutRTL ? -1 : 1;
2351 Rectangle aCellRect;
2352 long nPosY = nScrY;
2353 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
2355 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
2356 if ( pThisRowInfo->bChanged )
2358 SCROW nY = pThisRowInfo->nRowNo;
2359 long nPosX = nInitPosX;
2360 for (SCCOL nX=nX1; nX<=nX2; nX++)
2362 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
2363 if (pInfo->nClipMark)
2365 if (pInfo->bHOverlapped || pInfo->bVOverlapped)
2367 // merge origin may be outside of visible area - use document functions
2369 SCCOL nOverX = nX;
2370 SCROW nOverY = nY;
2371 long nStartPosX = nPosX;
2372 long nStartPosY = nPosY;
2374 while ( nOverX > 0 && ( ((const ScMergeFlagAttr*)pDoc->GetAttr(
2375 nOverX, nOverY, nTab, ATTR_MERGE_FLAG ))->GetValue() & SC_MF_HOR ) )
2377 --nOverX;
2378 nStartPosX -= nLayoutSign * (long) ( pDoc->GetColWidth(nOverX,nTab) * nPPTX );
2381 while ( nOverY > 0 && ( ((const ScMergeFlagAttr*)pDoc->GetAttr(
2382 nOverX, nOverY, nTab, ATTR_MERGE_FLAG ))->GetValue() & SC_MF_VER ) )
2384 --nOverY;
2385 nStartPosY -= nLayoutSign * (long) ( pDoc->GetRowHeight(nOverY,nTab) * nPPTY );
2388 long nOutWidth = (long) ( pDoc->GetColWidth(nOverX,nTab) * nPPTX );
2389 long nOutHeight = (long) ( pDoc->GetRowHeight(nOverY,nTab) * nPPTY );
2391 const ScMergeAttr* pMerge = (const ScMergeAttr*)
2392 pDoc->GetAttr( nOverX, nOverY, nTab, ATTR_MERGE );
2393 SCCOL nCountX = pMerge->GetColMerge();
2394 for (SCCOL i=1; i<nCountX; i++)
2395 nOutWidth += (long) ( pDoc->GetColWidth(nOverX+i,nTab) * nPPTX );
2396 SCROW nCountY = pMerge->GetRowMerge();
2397 nOutHeight += (long) pDoc->GetScaledRowHeight( nOverY+1, nOverY+nCountY-1, nTab, nPPTY);
2399 if ( bLayoutRTL )
2400 nStartPosX -= nOutWidth - 1;
2401 aCellRect = Rectangle( Point( nStartPosX, nStartPosY ), Size( nOutWidth, nOutHeight ) );
2403 else
2405 long nOutWidth = pRowInfo[0].pCellInfo[nX+1].nWidth;
2406 long nOutHeight = pThisRowInfo->nHeight;
2408 if ( pInfo->bMerged && pInfo->pPatternAttr )
2410 SCCOL nOverX = nX;
2411 SCROW nOverY = nY;
2412 const ScMergeAttr* pMerge =
2413 (ScMergeAttr*)&pInfo->pPatternAttr->GetItem(ATTR_MERGE);
2414 SCCOL nCountX = pMerge->GetColMerge();
2415 for (SCCOL i=1; i<nCountX; i++)
2416 nOutWidth += (long) ( pDoc->GetColWidth(nOverX+i,nTab) * nPPTX );
2417 SCROW nCountY = pMerge->GetRowMerge();
2418 nOutHeight += (long) pDoc->GetScaledRowHeight( nOverY+1, nOverY+nCountY-1, nTab, nPPTY);
2421 long nStartPosX = nPosX;
2422 if ( bLayoutRTL )
2423 nStartPosX -= nOutWidth - 1;
2424 // #i80447# create aCellRect from two points in case nOutWidth is 0
2425 aCellRect = Rectangle( Point( nStartPosX, nPosY ),
2426 Point( nStartPosX+nOutWidth-1, nPosY+nOutHeight-1 ) );
2429 aCellRect.Bottom() -= 1; // don't paint over the cell grid
2430 if ( bLayoutRTL )
2431 aCellRect.Left() += 1;
2432 else
2433 aCellRect.Right() -= 1;
2435 long nMarkPixel = (long)( SC_CLIPMARK_SIZE * nPPTX );
2436 Size aMarkSize( nMarkPixel, (nMarkPixel-1)*2 );
2438 if ( pInfo->nClipMark & ( bLayoutRTL ? SC_CLIPMARK_RIGHT : SC_CLIPMARK_LEFT ) )
2440 // visually left
2441 Rectangle aMarkRect = aCellRect;
2442 aMarkRect.Right() = aCellRect.Left()+nMarkPixel-1;
2443 #if 0
2444 //! Test
2445 pDev->SetLineColor(); pDev->SetFillColor(COL_YELLOW);
2446 pDev->DrawRect(aMarkRect);
2447 //! Test
2448 #endif
2449 SvxFont::DrawArrow( *pDev, aMarkRect, aMarkSize, aArrowFillCol, TRUE );
2451 if ( pInfo->nClipMark & ( bLayoutRTL ? SC_CLIPMARK_LEFT : SC_CLIPMARK_RIGHT ) )
2453 // visually right
2454 Rectangle aMarkRect = aCellRect;
2455 aMarkRect.Left() = aCellRect.Right()-nMarkPixel+1;
2456 #if 0
2457 //! Test
2458 pDev->SetLineColor(); pDev->SetFillColor(COL_LIGHTGREEN);
2459 pDev->DrawRect(aMarkRect);
2460 //! Test
2461 #endif
2462 SvxFont::DrawArrow( *pDev, aMarkRect, aMarkSize, aArrowFillCol, FALSE );
2465 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2468 nPosY += pThisRowInfo->nHeight;
2471 pDev->SetDrawMode(nOldDrawMode);