xref: /AOO41X/main/sc/source/ui/view/output.cxx (revision 3ea0c3d5cfef7203d1d18b0d5fde9ed31f4a4181)
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