LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/sc/source/ui/view - output2.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 1463 2694 54.3 %
Date: 2013-07-09 Functions: 74 88 84.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "scitems.hxx"
      21             : #include <editeng/eeitem.hxx>
      22             : 
      23             : #include <editeng/adjustitem.hxx>
      24             : #include <svx/algitem.hxx>
      25             : #include <editeng/brushitem.hxx>
      26             : #include <svtools/colorcfg.hxx>
      27             : #include <editeng/colritem.hxx>
      28             : #include <editeng/editobj.hxx>
      29             : #include <editeng/editstat.hxx>
      30             : #include <editeng/fhgtitem.hxx>
      31             : #include <editeng/forbiddencharacterstable.hxx>
      32             : #include <editeng/frmdiritem.hxx>
      33             : #include <editeng/langitem.hxx>
      34             : #include <editeng/justifyitem.hxx>
      35             : #include <svx/rotmodit.hxx>
      36             : #include <editeng/scripttypeitem.hxx>
      37             : #include <editeng/udlnitem.hxx>
      38             : #include <editeng/unolingu.hxx>
      39             : #include <editeng/fontitem.hxx>
      40             : #include <svl/zforlist.hxx>
      41             : #include <svl/zformat.hxx>
      42             : #include <vcl/svapp.hxx>
      43             : #include <vcl/metric.hxx>
      44             : #include <vcl/outdev.hxx>
      45             : #include <vcl/pdfextoutdevdata.hxx>
      46             : 
      47             : #include "output.hxx"
      48             : #include "document.hxx"
      49             : #include "formulacell.hxx"
      50             : #include "attrib.hxx"
      51             : #include "patattr.hxx"
      52             : #include "cellform.hxx"
      53             : #include "editutil.hxx"
      54             : #include "progress.hxx"
      55             : #include "scmod.hxx"
      56             : #include "fillinfo.hxx"
      57             : #include "viewdata.hxx"
      58             : #include "tabvwsh.hxx"
      59             : #include "docsh.hxx"
      60             : #include "markdata.hxx"
      61             : #include "stlsheet.hxx"
      62             : 
      63             : #include <com/sun/star/i18n/DirectionProperty.hpp>
      64             : #include <comphelper/string.hxx>
      65             : 
      66             : #include <boost/ptr_container/ptr_vector.hpp>
      67             : 
      68             : #include <math.h>
      69             : 
      70             : using namespace com::sun::star;
      71             : 
      72             : //! Autofilter-Breite mit column.cxx zusammenfassen
      73             : #define DROPDOWN_BITMAP_SIZE        18
      74             : 
      75             : #define DRAWTEXT_MAX    32767
      76             : 
      77             : const sal_uInt16 SC_SHRINKAGAIN_MAX = 7;
      78             : 
      79             : // STATIC DATA -----------------------------------------------------------
      80             : 
      81             : 
      82             : // -----------------------------------------------------------------------
      83             : 
      84             : class ScDrawStringsVars
      85             : {
      86             :     ScOutputData*       pOutput;                // Verbindung
      87             : 
      88             :     const ScPatternAttr* pPattern;              // Attribute
      89             :     const SfxItemSet*   pCondSet;               // aus bedingter Formatierung
      90             : 
      91             :     Font                aFont;                  // aus Attributen erzeugt
      92             :     FontMetric          aMetric;
      93             :     long                nAscentPixel;           // always pixels
      94             :     SvxCellOrientation  eAttrOrient;
      95             :     SvxCellHorJustify   eAttrHorJust;
      96             :     SvxCellVerJustify   eAttrVerJust;
      97             :     SvxCellJustifyMethod eAttrHorJustMethod;
      98             :     SvxCellJustifyMethod eAttrVerJustMethod;
      99             :     const SvxMarginItem* pMargin;
     100             :     sal_uInt16              nIndent;
     101             :     sal_Bool                bRotated;
     102             : 
     103             :     String              aString;                // Inhalte
     104             :     Size                aTextSize;
     105             :     long                nOriginalWidth;
     106             :     long                nMaxDigitWidth;
     107             :     long                nSignWidth;
     108             :     long                nDotWidth;
     109             :     long                nExpWidth;
     110             : 
     111             :     ScRefCellValue      maLastCell;
     112             :     sal_uLong               nValueFormat;
     113             :     sal_Bool                bLineBreak;
     114             :     sal_Bool                bRepeat;
     115             :     sal_Bool                bShrink;
     116             : 
     117             :     sal_Bool                bPixelToLogic;
     118             :     sal_Bool                bCellContrast;
     119             : 
     120             :     Color               aBackConfigColor;       // used for ScPatternAttr::GetFont calls
     121             :     Color               aTextConfigColor;
     122             :     sal_Int32           nPos;
     123             :     sal_Unicode         nChar;
     124             : 
     125             : public:
     126             :                 ScDrawStringsVars(ScOutputData* pData, sal_Bool bPTL);
     127             :                 ~ScDrawStringsVars();
     128             : 
     129             :                 //  SetPattern = ex-SetVars
     130             :                 //  SetPatternSimple: ohne Font
     131             : 
     132             :     void SetPattern(
     133             :         const ScPatternAttr* pNew, const SfxItemSet* pSet, const ScRefCellValue& rCell,
     134             :         sal_uInt8 nScript );
     135             : 
     136             :     void        SetPatternSimple( const ScPatternAttr* pNew, const SfxItemSet* pSet );
     137             : 
     138             :     bool SetText( ScRefCellValue& rCell );   // TRUE -> pOldPattern vergessen
     139             :     void        SetHashText();
     140             :     void SetTextToWidthOrHash( ScRefCellValue& rCell, long nWidth );
     141             :     void        SetAutoText( const String& rAutoText );
     142             : 
     143             :     const ScPatternAttr*    GetPattern() const       { return pPattern; }
     144       32534 :     SvxCellOrientation      GetOrient() const        { return eAttrOrient; }
     145       35994 :     SvxCellHorJustify       GetHorJust() const       { return eAttrHorJust; }
     146       11076 :     SvxCellVerJustify       GetVerJust() const       { return eAttrVerJust; }
     147           0 :     SvxCellJustifyMethod    GetHorJustMethod() const { return eAttrHorJustMethod; }
     148             :     SvxCellJustifyMethod    GetVerJustMethod() const { return eAttrVerJustMethod; }
     149       22951 :     const SvxMarginItem*    GetMargin() const        { return pMargin; }
     150             : 
     151       17177 :     sal_uInt16              GetLeftTotal() const     { return pMargin->GetLeftMargin() + nIndent; }
     152        5631 :     sal_uInt16              GetRightTotal() const    { return pMargin->GetRightMargin() + nIndent; }
     153             : 
     154       20934 :     const String&           GetString() const        { return aString; }
     155       39772 :     const Size&             GetTextSize() const      { return aTextSize; }
     156         310 :     long                    GetOriginalWidth() const { return nOriginalWidth; }
     157             : 
     158             :     sal_uLong GetResultValueFormat() const;
     159             : 
     160        9152 :     sal_uLong   GetValueFormat() const                  { return nValueFormat; }
     161       11516 :     sal_Bool    GetLineBreak() const                    { return bLineBreak; }
     162       11516 :     sal_Bool    IsRepeat() const                        { return bRepeat; }
     163       11516 :     sal_Bool    IsShrink() const                        { return bShrink; }
     164             :     void        RepeatToFill( long colWidth );
     165             : 
     166       11076 :     long    GetAscent() const   { return nAscentPixel; }
     167       11892 :     sal_Bool    IsRotated() const   { return bRotated; }
     168             : 
     169             :     void    SetShrinkScale( long nScale, sal_uInt8 nScript );
     170             : 
     171          30 :     sal_Bool    HasCondHeight() const   { return pCondSet && SFX_ITEM_SET ==
     172          30 :                                         pCondSet->GetItemState( ATTR_FONT_HEIGHT, sal_True ); }
     173             : 
     174             :     sal_Bool    HasEditCharacters() const;
     175             : 
     176             : private:
     177             :     long        GetMaxDigitWidth();     // in logic units
     178             :     long        GetSignWidth();
     179             :     long        GetDotWidth();
     180             :     long        GetExpWidth();
     181             :     void        TextChanged();
     182             : };
     183             : 
     184             : //==================================================================
     185             : 
     186        1179 : ScDrawStringsVars::ScDrawStringsVars(ScOutputData* pData, sal_Bool bPTL) :
     187             :     pOutput     ( pData ),
     188             :     pPattern    ( NULL ),
     189             :     pCondSet    ( NULL ),
     190             :     nAscentPixel(0),
     191             :     eAttrOrient ( SVX_ORIENTATION_STANDARD ),
     192             :     eAttrHorJust( SVX_HOR_JUSTIFY_STANDARD ),
     193             :     eAttrVerJust( SVX_VER_JUSTIFY_BOTTOM ),
     194             :     eAttrHorJustMethod( SVX_JUSTIFY_METHOD_AUTO ),
     195             :     eAttrVerJustMethod( SVX_JUSTIFY_METHOD_AUTO ),
     196             :     pMargin     ( NULL ),
     197             :     nIndent     ( 0 ),
     198             :     bRotated    ( false ),
     199             :     nOriginalWidth( 0 ),
     200             :     nMaxDigitWidth( 0 ),
     201             :     nSignWidth( 0 ),
     202             :     nDotWidth( 0 ),
     203             :     nExpWidth( 0 ),
     204             :     nValueFormat( 0 ),
     205             :     bLineBreak  ( false ),
     206             :     bRepeat     ( false ),
     207             :     bShrink     ( false ),
     208             :     bPixelToLogic( bPTL ),
     209             :     nPos( STRING_NOTFOUND ),
     210        1179 :     nChar( 0x0 )
     211             : {
     212        1179 :     ScModule* pScMod = SC_MOD();
     213        2355 :     bCellContrast = pOutput->mbUseStyleColor &&
     214        2355 :             Application::GetSettings().GetStyleSettings().GetHighContrastMode();
     215             : 
     216        1179 :     const svtools::ColorConfig& rColorConfig = pScMod->GetColorConfig();
     217        1179 :     aBackConfigColor.SetColor( rColorConfig.GetColorValue(svtools::DOCCOLOR).nColor );
     218        1179 :     aTextConfigColor.SetColor( rColorConfig.GetColorValue(svtools::FONTCOLOR).nColor );
     219        1179 : }
     220             : 
     221        1179 : ScDrawStringsVars::~ScDrawStringsVars()
     222             : {
     223        1179 : }
     224             : 
     225           0 : void ScDrawStringsVars::SetShrinkScale( long nScale, sal_uInt8 nScript )
     226             : {
     227             :     // text remains valid, size is updated
     228             : 
     229           0 :     OutputDevice* pDev = pOutput->mpDev;
     230           0 :     OutputDevice* pRefDevice = pOutput->mpRefDevice;
     231           0 :     OutputDevice* pFmtDevice = pOutput->pFmtDevice;
     232             : 
     233             :     // call GetFont with a modified fraction, use only the height
     234             : 
     235           0 :     Fraction aFraction( nScale, 100 );
     236           0 :     if ( !bPixelToLogic )
     237           0 :         aFraction *= pOutput->aZoomY;
     238           0 :     Font aTmpFont;
     239           0 :     pPattern->GetFont( aTmpFont, SC_AUTOCOL_RAW, pFmtDevice, &aFraction, pCondSet, nScript );
     240           0 :     long nNewHeight = aTmpFont.GetHeight();
     241           0 :     if ( nNewHeight > 0 )
     242           0 :         aFont.SetHeight( nNewHeight );
     243             : 
     244             :     // set font and dependent variables as in SetPattern
     245             : 
     246           0 :     pDev->SetFont( aFont );
     247           0 :     if ( pFmtDevice != pDev )
     248           0 :         pFmtDevice->SetFont( aFont );
     249             : 
     250           0 :     aMetric = pFmtDevice->GetFontMetric();
     251           0 :     if ( pFmtDevice->GetOutDevType() == OUTDEV_PRINTER && aMetric.GetIntLeading() == 0 )
     252             :     {
     253           0 :         OutputDevice* pDefaultDev = Application::GetDefaultDevice();
     254           0 :         MapMode aOld = pDefaultDev->GetMapMode();
     255           0 :         pDefaultDev->SetMapMode( pFmtDevice->GetMapMode() );
     256           0 :         aMetric = pDefaultDev->GetFontMetric( aFont );
     257           0 :         pDefaultDev->SetMapMode( aOld );
     258             :     }
     259             : 
     260           0 :     nAscentPixel = aMetric.GetAscent();
     261           0 :     if ( bPixelToLogic )
     262           0 :         nAscentPixel = pRefDevice->LogicToPixel( Size( 0, nAscentPixel ) ).Height();
     263             : 
     264           0 :     SetAutoText( aString );     // same text again, to get text size
     265           0 : }
     266             : 
     267             : namespace {
     268             : 
     269             : template<typename _ItemType, typename _EnumType>
     270        7910 : _EnumType lcl_GetValue(const ScPatternAttr& rPattern, sal_uInt16 nWhich, const SfxItemSet* pCondSet)
     271             : {
     272        7910 :     const _ItemType& rItem = static_cast<const _ItemType&>(rPattern.GetItem(nWhich, pCondSet));
     273        7910 :     return static_cast<_EnumType>(rItem.GetValue());
     274             : }
     275             : 
     276         741 : bool lcl_GetBoolValue(const ScPatternAttr& rPattern, sal_uInt16 nWhich, const SfxItemSet* pCondSet)
     277             : {
     278         741 :     return lcl_GetValue<SfxBoolItem, bool>(rPattern, nWhich, pCondSet);
     279             : }
     280             : 
     281             : }
     282             : 
     283        2193 : void ScDrawStringsVars::SetPattern(
     284             :     const ScPatternAttr* pNew, const SfxItemSet* pSet, const ScRefCellValue& rCell,
     285             :     sal_uInt8 nScript )
     286             : {
     287        2193 :     nMaxDigitWidth = 0;
     288        2193 :     nSignWidth     = 0;
     289        2193 :     nDotWidth      = 0;
     290        2193 :     nExpWidth      = 0;
     291             : 
     292        2193 :     pPattern = pNew;
     293        2193 :     pCondSet = pSet;
     294             : 
     295             :     //  pPattern auswerten
     296             : 
     297        2193 :     OutputDevice* pDev = pOutput->mpDev;
     298        2193 :     OutputDevice* pRefDevice = pOutput->mpRefDevice;
     299        2193 :     OutputDevice* pFmtDevice = pOutput->pFmtDevice;
     300             : 
     301             :     //  Font
     302             : 
     303             :     ScAutoFontColorMode eColorMode;
     304        2193 :     if ( pOutput->mbUseStyleColor )
     305             :     {
     306        2192 :         if ( pOutput->mbForceAutoColor )
     307           0 :             eColorMode = bCellContrast ? SC_AUTOCOL_IGNOREALL : SC_AUTOCOL_IGNOREFONT;
     308             :         else
     309        2192 :             eColorMode = bCellContrast ? SC_AUTOCOL_IGNOREBACK : SC_AUTOCOL_DISPLAY;
     310             :     }
     311             :     else
     312           1 :         eColorMode = SC_AUTOCOL_PRINT;
     313             : 
     314        2193 :     if ( bPixelToLogic )
     315             :         pPattern->GetFont( aFont, eColorMode, pFmtDevice, NULL, pCondSet, nScript,
     316          23 :                             &aBackConfigColor, &aTextConfigColor );
     317             :     else
     318             :         pPattern->GetFont( aFont, eColorMode, pFmtDevice, &pOutput->aZoomY, pCondSet, nScript,
     319        2170 :                             &aBackConfigColor, &aTextConfigColor );
     320        2193 :     aFont.SetAlign(ALIGN_BASELINE);
     321             : 
     322             :     //  Orientierung
     323             : 
     324        2193 :     eAttrOrient = pPattern->GetCellOrientation( pCondSet );
     325             : 
     326             :     //  alignment
     327             : 
     328        2193 :     eAttrHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern->GetItem( ATTR_HOR_JUSTIFY, pCondSet )).GetValue();
     329             : 
     330        2193 :     eAttrVerJust = (SvxCellVerJustify)((const SvxVerJustifyItem&)pPattern->GetItem( ATTR_VER_JUSTIFY, pCondSet )).GetValue();
     331        2193 :     if ( eAttrVerJust == SVX_VER_JUSTIFY_STANDARD )
     332        1981 :         eAttrVerJust = SVX_VER_JUSTIFY_BOTTOM;
     333             : 
     334             :     // justification method
     335             : 
     336        2193 :     eAttrHorJustMethod = lcl_GetValue<SvxJustifyMethodItem, SvxCellJustifyMethod>(*pPattern, ATTR_HOR_JUSTIFY_METHOD, pCondSet);
     337        2193 :     eAttrVerJustMethod = lcl_GetValue<SvxJustifyMethodItem, SvxCellJustifyMethod>(*pPattern, ATTR_VER_JUSTIFY_METHOD, pCondSet);
     338             : 
     339             :     //  line break
     340             : 
     341        2193 :     bLineBreak = ((const SfxBoolItem&)pPattern->GetItem( ATTR_LINEBREAK, pCondSet )).GetValue();
     342             : 
     343             :     //  handle "repeat" alignment
     344             : 
     345        2193 :     bRepeat = ( eAttrHorJust == SVX_HOR_JUSTIFY_REPEAT );
     346        2193 :     if ( bRepeat )
     347             :     {
     348             :         // "repeat" disables rotation (before constructing the font)
     349           0 :         eAttrOrient = SVX_ORIENTATION_STANDARD;
     350             : 
     351             :         // #i31843# "repeat" with "line breaks" is treated as default alignment (but rotation is still disabled)
     352           0 :         if ( bLineBreak )
     353           0 :             eAttrHorJust = SVX_HOR_JUSTIFY_STANDARD;
     354             :     }
     355             : 
     356             :     short nRot;
     357        2193 :     switch (eAttrOrient)
     358             :     {
     359             :         case SVX_ORIENTATION_STANDARD:
     360        2135 :             nRot = 0;
     361        2307 :             bRotated = (((const SfxInt32Item&)pPattern->GetItem( ATTR_ROTATE_VALUE, pCondSet )).GetValue() != 0) &&
     362        2307 :                        !bRepeat;
     363        2135 :             break;
     364             :         case SVX_ORIENTATION_STACKED:
     365           0 :             nRot = 0;
     366           0 :             bRotated = false;
     367           0 :             break;
     368             :         case SVX_ORIENTATION_TOPBOTTOM:
     369          58 :             nRot = 2700;
     370          58 :             bRotated = false;
     371          58 :             break;
     372             :         case SVX_ORIENTATION_BOTTOMTOP:
     373           0 :             nRot = 900;
     374           0 :             bRotated = false;
     375           0 :             break;
     376             :         default:
     377             :             OSL_FAIL("Falscher SvxCellOrientation Wert");
     378           0 :             nRot = 0;
     379           0 :             bRotated = false;
     380           0 :             break;
     381             :     }
     382        2193 :     aFont.SetOrientation( nRot );
     383             : 
     384             :     //  Syntax-Modus
     385             : 
     386        2193 :     if (pOutput->mbSyntaxMode)
     387           0 :         pOutput->SetSyntaxColor(&aFont, rCell);
     388             : 
     389        2193 :     pDev->SetFont( aFont );
     390        2193 :     if ( pFmtDevice != pDev )
     391          53 :         pFmtDevice->SetFont( aFont );
     392             : 
     393        2193 :     aMetric = pFmtDevice->GetFontMetric();
     394             : 
     395             :     //
     396             :     //  Wenn auf dem Drucker das Leading 0 ist, gibt es Probleme
     397             :     //  -> Metric vom Bildschirm nehmen (wie EditEngine!)
     398             :     //
     399             : 
     400        2193 :     if ( pFmtDevice->GetOutDevType() == OUTDEV_PRINTER && aMetric.GetIntLeading() == 0 )
     401             :     {
     402           0 :         OutputDevice* pDefaultDev = Application::GetDefaultDevice();
     403           0 :         MapMode aOld = pDefaultDev->GetMapMode();
     404           0 :         pDefaultDev->SetMapMode( pFmtDevice->GetMapMode() );
     405           0 :         aMetric = pDefaultDev->GetFontMetric( aFont );
     406           0 :         pDefaultDev->SetMapMode( aOld );
     407             :     }
     408             : 
     409        2193 :     nAscentPixel = aMetric.GetAscent();
     410        2193 :     if ( bPixelToLogic )
     411          23 :         nAscentPixel = pRefDevice->LogicToPixel( Size( 0, nAscentPixel ) ).Height();
     412             : 
     413        2193 :     Color aULineColor( ((const SvxUnderlineItem&)pPattern->GetItem( ATTR_FONT_UNDERLINE, pCondSet )).GetColor() );
     414        2193 :     pDev->SetTextLineColor( aULineColor );
     415             : 
     416        2193 :     Color aOLineColor( ((const SvxOverlineItem&)pPattern->GetItem( ATTR_FONT_OVERLINE, pCondSet )).GetColor() );
     417        2193 :     pDev->SetOverlineColor( aOLineColor );
     418             : 
     419             :     //  Zahlenformat
     420             : 
     421        2193 :     nValueFormat = pPattern->GetNumberFormat( pOutput->mpDoc->GetFormatTable(), pCondSet );
     422             : 
     423             :     //  Raender
     424             : 
     425        2193 :     pMargin = (const SvxMarginItem*)&pPattern->GetItem( ATTR_MARGIN, pCondSet );
     426        2193 :     if ( eAttrHorJust == SVX_HOR_JUSTIFY_LEFT || eAttrHorJust == SVX_HOR_JUSTIFY_RIGHT )
     427         820 :         nIndent = ((const SfxUInt16Item&)pPattern->GetItem( ATTR_INDENT, pCondSet )).GetValue();
     428             :     else
     429        1373 :         nIndent = 0;
     430             : 
     431             :     //  "Shrink to fit"
     432             : 
     433        2193 :     bShrink = static_cast<const SfxBoolItem&>(pPattern->GetItem( ATTR_SHRINKTOFIT, pCondSet )).GetValue();
     434             : 
     435             :     //  zumindest die Text-Groesse muss neu geholt werden
     436             :     //! unterscheiden, und den Text nicht neu vom Numberformatter holen?
     437             : 
     438        2193 :     maLastCell.clear();
     439        2193 : }
     440             : 
     441        5997 : void ScDrawStringsVars::SetPatternSimple( const ScPatternAttr* pNew, const SfxItemSet* pSet )
     442             : {
     443        5997 :     nMaxDigitWidth = 0;
     444        5997 :     nSignWidth     = 0;
     445        5997 :     nDotWidth      = 0;
     446        5997 :     nExpWidth      = 0;
     447             :     //  wird gerufen, wenn sich die Font-Variablen nicht aendern (!StringDiffer)
     448             : 
     449        5997 :     pPattern = pNew;
     450        5997 :     pCondSet = pSet;        //! noetig ???
     451             : 
     452             :     //  Zahlenformat
     453             : 
     454        5997 :     sal_uLong nOld = nValueFormat;
     455             :     const SfxPoolItem* pFormItem;
     456        5997 :     if ( !pCondSet || pCondSet->GetItemState(ATTR_VALUE_FORMAT,sal_True,&pFormItem) != SFX_ITEM_SET )
     457        5997 :         pFormItem = &pPattern->GetItem(ATTR_VALUE_FORMAT);
     458             :     const SfxPoolItem* pLangItem;
     459        5997 :     if ( !pCondSet || pCondSet->GetItemState(ATTR_LANGUAGE_FORMAT,sal_True,&pLangItem) != SFX_ITEM_SET )
     460        5997 :         pLangItem = &pPattern->GetItem(ATTR_LANGUAGE_FORMAT);
     461             :     nValueFormat = pOutput->mpDoc->GetFormatTable()->GetFormatForLanguageIfBuiltIn(
     462             :                     ((SfxUInt32Item*)pFormItem)->GetValue(),
     463        5997 :                     ((SvxLanguageItem*)pLangItem)->GetLanguage() );
     464             : 
     465        5997 :     if (nValueFormat != nOld)
     466         172 :         maLastCell.clear();           // immer neu formatieren
     467             : 
     468             :     //  Raender
     469             : 
     470        5997 :     pMargin = (const SvxMarginItem*)&pPattern->GetItem( ATTR_MARGIN, pCondSet );
     471             : 
     472        5997 :     if ( eAttrHorJust == SVX_HOR_JUSTIFY_LEFT )
     473         610 :         nIndent = ((const SfxUInt16Item&)pPattern->GetItem( ATTR_INDENT, pCondSet )).GetValue();
     474             :     else
     475        5387 :         nIndent = 0;
     476             : 
     477             :     //  "Shrink to fit"
     478             : 
     479        5997 :     bShrink = static_cast<const SfxBoolItem&>(pPattern->GetItem( ATTR_SHRINKTOFIT, pCondSet )).GetValue();
     480        5997 : }
     481             : 
     482       11516 : inline bool SameValue( const ScRefCellValue& rCell, const ScRefCellValue& rOldCell )
     483             : {
     484       16413 :     return rOldCell.meType == CELLTYPE_VALUE && rCell.meType == CELLTYPE_VALUE &&
     485       16413 :         rCell.mfValue == rOldCell.mfValue;
     486             : }
     487             : 
     488       11516 : bool ScDrawStringsVars::SetText( ScRefCellValue& rCell )
     489             : {
     490       11516 :     bool bChanged = false;
     491             : 
     492       11516 :     if (!rCell.isEmpty())
     493             :     {
     494       11516 :         if (!SameValue(rCell, maLastCell))
     495             :         {
     496        9152 :             maLastCell = rCell;          //  Zelle merken
     497             : 
     498             :             Color* pColor;
     499        9152 :             sal_uLong nFormat = GetValueFormat();
     500        9152 :             OUString aOUString = aString;
     501             :             ScCellFormat::GetString( rCell,
     502             :                                      nFormat, aOUString, &pColor,
     503        9152 :                                      *pOutput->mpDoc->GetFormatTable(),
     504             :                                      pOutput->mbShowNullValues,
     505             :                                      pOutput->mbShowFormulas,
     506       18304 :                                      ftCheck, true );
     507        9152 :             aString = aOUString;
     508        9152 :             if ( nFormat )
     509             :             {
     510         269 :                 nPos = aString.Search( 0x1B );
     511         269 :                 if ( nPos != STRING_NOTFOUND )
     512             :                 {
     513           0 :                     nChar = aString.GetChar( nPos + 1 );
     514             :                     // delete placeholder and char to repeat
     515           0 :                     aString.Erase( nPos, 2 );
     516             :                 }
     517             :             }
     518             :             else
     519             :             {
     520        8883 :                 nPos = STRING_NOTFOUND;
     521        8883 :                 nChar = 0x0;
     522             :             }
     523        9152 :             if (aString.Len() > DRAWTEXT_MAX)
     524           0 :                 aString.Erase(DRAWTEXT_MAX);
     525             : 
     526        9152 :             if ( pColor && !pOutput->mbSyntaxMode && !( pOutput->mbUseStyleColor && pOutput->mbForceAutoColor ) )
     527             :             {
     528           0 :                 OutputDevice* pDev = pOutput->mpDev;
     529           0 :                 aFont.SetColor(*pColor);
     530           0 :                 pDev->SetFont( aFont ); // nur fuer Ausgabe
     531           0 :                 bChanged = true;
     532           0 :                 maLastCell.clear();       // naechstes Mal wieder hierherkommen
     533             :             }
     534             : 
     535        9152 :             TextChanged();
     536             :         }
     537             :         //  sonst String/Groesse behalten
     538             :     }
     539             :     else
     540             :     {
     541           0 :         aString.Erase();
     542           0 :         maLastCell.clear();
     543           0 :         aTextSize = Size(0,0);
     544           0 :         nOriginalWidth = 0;
     545             :     }
     546             : 
     547       11516 :     return bChanged;
     548             : }
     549             : 
     550          76 : void ScDrawStringsVars::SetHashText()
     551             : {
     552          76 :     SetAutoText(OUString("###"));
     553          76 : }
     554             : 
     555       11516 : void ScDrawStringsVars::RepeatToFill( long colWidth )
     556             : {
     557       11516 :     if ( nPos ==  STRING_NOTFOUND || nPos > aString.Len() )
     558       23032 :         return;
     559             : 
     560           0 :     long charWidth = pOutput->pFmtDevice->GetTextWidth(OUString(nChar));
     561           0 :     if ( charWidth < 1) return;
     562           0 :     if (bPixelToLogic)
     563           0 :         colWidth = pOutput->mpRefDevice->PixelToLogic(Size(colWidth,0)).Width();
     564             :     // Are there restrictions on the cell type we should filter out here ?
     565           0 :     long aSpaceToFill = ( colWidth - aTextSize.Width() );
     566             : 
     567           0 :     if ( aSpaceToFill <= charWidth )
     568           0 :         return;
     569             : 
     570           0 :     long nCharsToInsert = aSpaceToFill / charWidth;
     571           0 :     OUStringBuffer aFill;
     572           0 :     comphelper::string::padToLength(aFill, nCharsToInsert, nChar);
     573           0 :     aString.Insert( aFill.makeStringAndClear(), nPos);
     574           0 :     TextChanged();
     575             : }
     576             : 
     577         216 : void ScDrawStringsVars::SetTextToWidthOrHash( ScRefCellValue& rCell, long nWidth )
     578             : {
     579             :     // #i113045# do the single-character width calculations in logic units
     580         216 :     if (bPixelToLogic)
     581           0 :         nWidth = pOutput->mpRefDevice->PixelToLogic(Size(nWidth,0)).Width();
     582             : 
     583         216 :     CellType eType = rCell.meType;
     584         216 :     if (eType != CELLTYPE_VALUE && eType != CELLTYPE_FORMULA)
     585             :         // must be a value or formula cell.
     586           0 :         return;
     587             : 
     588         216 :     if (eType == CELLTYPE_FORMULA)
     589             :     {
     590          50 :         ScFormulaCell* pFCell = rCell.mpFormula;
     591          50 :         if (pFCell->GetErrCode() != 0 || pOutput->mbShowFormulas)
     592             :         {
     593           0 :             SetHashText();      // If the error string doesn't fit, always use "###". Also for "display formulas" (#i116691#)
     594           0 :             return;
     595             :         }
     596             :         // If it's formula, the result must be a value.
     597          50 :         if (!pFCell->IsValue())
     598           0 :             return;
     599             :     }
     600             : 
     601         216 :     sal_uLong nFormat = GetResultValueFormat();
     602         216 :     if ((nFormat % SV_COUNTRY_LANGUAGE_OFFSET) != 0)
     603             :     {
     604             :         // Not 'General' number format.  Set hash text and bail out.
     605          40 :         SetHashText();
     606          40 :         return;
     607             :     }
     608             : 
     609         176 :     double fVal = rCell.getValue();
     610             : 
     611         176 :     const SvNumberformat* pNumFormat = pOutput->mpDoc->GetFormatTable()->GetEntry(nFormat);
     612         176 :     if (!pNumFormat)
     613           0 :         return;
     614             : 
     615         176 :     long nMaxDigit = GetMaxDigitWidth();
     616         176 :     sal_uInt16 nNumDigits = static_cast<sal_uInt16>(nWidth / nMaxDigit);
     617             :     {
     618         176 :         OUString sTempOut(aString);
     619         176 :         if (!pNumFormat->GetOutputString(fVal, nNumDigits, sTempOut))
     620             :         {
     621           0 :             aString = sTempOut;
     622             :             // Failed to get output string.  Bail out.
     623           0 :             return;
     624             :         }
     625         176 :         aString = sTempOut;
     626             :     }
     627         176 :     sal_uInt8 nSignCount = 0, nDecimalCount = 0, nExpCount = 0;
     628         176 :     xub_StrLen nLen = aString.Len();
     629         176 :     sal_Unicode cDecSep = ScGlobal::GetpLocaleData()->getLocaleItem().decimalSeparator.getStr()[0];
     630        1812 :     for (xub_StrLen i = 0; i < nLen; ++i)
     631             :     {
     632        1636 :         sal_Unicode c = aString.GetChar(i);
     633        1636 :         if (c == sal_Unicode('-'))
     634          71 :             ++nSignCount;
     635        1565 :         else if (c == cDecSep)
     636         140 :             ++nDecimalCount;
     637        1425 :         else if (c == sal_Unicode('E'))
     638          37 :             ++nExpCount;
     639             :     }
     640             : 
     641             :     // #i112250# A small value might be formatted as "0" when only counting the digits,
     642             :     // but fit into the column when considering the smaller width of the decimal separator.
     643         176 :     if (aString.EqualsAscii("0") && fVal != 0.0)
     644           0 :         nDecimalCount = 1;
     645             : 
     646         176 :     if (nDecimalCount)
     647         140 :         nWidth += (nMaxDigit - GetDotWidth()) * nDecimalCount;
     648         176 :     if (nSignCount)
     649          71 :         nWidth += (nMaxDigit - GetSignWidth()) * nSignCount;
     650         176 :     if (nExpCount)
     651          37 :         nWidth += (nMaxDigit - GetExpWidth()) * nExpCount;
     652             : 
     653         176 :     if (nDecimalCount || nSignCount || nExpCount)
     654             :     {
     655             :         // Re-calculate.
     656         176 :         nNumDigits = static_cast<sal_uInt16>(nWidth / nMaxDigit);
     657         176 :         OUString sTempOut(aString);
     658         176 :         if (!pNumFormat->GetOutputString(fVal, nNumDigits, sTempOut))
     659             :         {
     660           0 :             aString = sTempOut;
     661             :             // Failed to get output string.  Bail out.
     662           0 :             return;
     663             :         }
     664         176 :         aString = sTempOut;
     665             :     }
     666             : 
     667         176 :     long nActualTextWidth = pOutput->pFmtDevice->GetTextWidth(aString);
     668         176 :     if (nActualTextWidth > nWidth)
     669             :     {
     670             :         // Even after the decimal adjustment the text doesn't fit.  Give up.
     671          36 :         SetHashText();
     672          36 :         return;
     673             :     }
     674             : 
     675         140 :     TextChanged();
     676         140 :     maLastCell.clear();   // #i113022# equal cell and format in another column may give different string
     677             : }
     678             : 
     679          76 : void ScDrawStringsVars::SetAutoText( const String& rAutoText )
     680             : {
     681          76 :     aString = rAutoText;
     682             : 
     683          76 :     OutputDevice* pRefDevice = pOutput->mpRefDevice;
     684          76 :     OutputDevice* pFmtDevice = pOutput->pFmtDevice;
     685          76 :     aTextSize.Width() = pFmtDevice->GetTextWidth( aString );
     686          76 :     aTextSize.Height() = pFmtDevice->GetTextHeight();
     687             : 
     688          76 :     if ( !pRefDevice->GetConnectMetaFile() || pRefDevice->GetOutDevType() == OUTDEV_PRINTER )
     689             :     {
     690          76 :         double fMul = pOutput->GetStretch();
     691          76 :         aTextSize.Width() = (long)(aTextSize.Width() / fMul + 0.5);
     692             :     }
     693             : 
     694          76 :     aTextSize.Height() = aMetric.GetAscent() + aMetric.GetDescent();
     695          76 :     if ( GetOrient() != SVX_ORIENTATION_STANDARD )
     696             :     {
     697          40 :         long nTemp = aTextSize.Height();
     698          40 :         aTextSize.Height() = aTextSize.Width();
     699          40 :         aTextSize.Width() = nTemp;
     700             :     }
     701             : 
     702          76 :     nOriginalWidth = aTextSize.Width();
     703          76 :     if ( bPixelToLogic )
     704           0 :         aTextSize = pRefDevice->LogicToPixel( aTextSize );
     705             : 
     706          76 :     maLastCell.clear();       // derselbe Text kann in der naechsten Zelle wieder passen
     707          76 : }
     708             : 
     709         176 : long ScDrawStringsVars::GetMaxDigitWidth()
     710             : {
     711         176 :     if (nMaxDigitWidth > 0)
     712          37 :         return nMaxDigitWidth;
     713             : 
     714         139 :     sal_Char cZero = '0';
     715        1529 :     for (sal_Char i = 0; i < 10; ++i)
     716             :     {
     717        1390 :         sal_Char cDigit = cZero + i;
     718        1390 :         long n = pOutput->pFmtDevice->GetTextWidth(OUString(cDigit));
     719        1390 :         nMaxDigitWidth = ::std::max(nMaxDigitWidth, n);
     720             :     }
     721         139 :     return nMaxDigitWidth;
     722             : }
     723             : 
     724          71 : long ScDrawStringsVars::GetSignWidth()
     725             : {
     726          71 :     if (nSignWidth > 0)
     727           9 :         return nSignWidth;
     728             : 
     729          62 :     nSignWidth = pOutput->pFmtDevice->GetTextWidth(OUString('-'));
     730          62 :     return nSignWidth;
     731             : }
     732             : 
     733         140 : long ScDrawStringsVars::GetDotWidth()
     734             : {
     735         140 :     if (nDotWidth > 0)
     736           9 :         return nDotWidth;
     737             : 
     738         131 :     const OUString& sep = ScGlobal::GetpLocaleData()->getLocaleItem().decimalSeparator;
     739         131 :     nDotWidth = pOutput->pFmtDevice->GetTextWidth(sep);
     740         131 :     return nDotWidth;
     741             : }
     742             : 
     743          37 : long ScDrawStringsVars::GetExpWidth()
     744             : {
     745          37 :     if (nExpWidth > 0)
     746          28 :         return nExpWidth;
     747             : 
     748           9 :     nExpWidth = pOutput->pFmtDevice->GetTextWidth(OUString('E'));
     749           9 :     return nExpWidth;
     750             : }
     751             : 
     752        9292 : void ScDrawStringsVars::TextChanged()
     753             : {
     754        9292 :     OutputDevice* pRefDevice = pOutput->mpRefDevice;
     755        9292 :     OutputDevice* pFmtDevice = pOutput->pFmtDevice;
     756        9292 :     aTextSize.Width() = pFmtDevice->GetTextWidth( aString );
     757        9292 :     aTextSize.Height() = pFmtDevice->GetTextHeight();
     758             : 
     759        9292 :     if ( !pRefDevice->GetConnectMetaFile() || pRefDevice->GetOutDevType() == OUTDEV_PRINTER )
     760             :     {
     761        9291 :         double fMul = pOutput->GetStretch();
     762        9291 :         aTextSize.Width() = (long)(aTextSize.Width() / fMul + 0.5);
     763             :     }
     764             : 
     765        9292 :     aTextSize.Height() = aMetric.GetAscent() + aMetric.GetDescent();
     766        9292 :     if ( GetOrient() != SVX_ORIENTATION_STANDARD )
     767             :     {
     768         138 :         long nTemp = aTextSize.Height();
     769         138 :         aTextSize.Height() = aTextSize.Width();
     770         138 :         aTextSize.Width() = nTemp;
     771             :     }
     772             : 
     773        9292 :     nOriginalWidth = aTextSize.Width();
     774        9292 :     if ( bPixelToLogic )
     775         358 :         aTextSize = pRefDevice->LogicToPixel( aTextSize );
     776        9292 : }
     777             : 
     778       11516 : sal_Bool ScDrawStringsVars::HasEditCharacters() const
     779             : {
     780             :     static const sal_Unicode pChars[] =
     781             :     {
     782             :         CHAR_NBSP, CHAR_SHY, CHAR_ZWSP, CHAR_LRM, CHAR_RLM, CHAR_NBHY, CHAR_ZWNBSP, 0
     783             :     };
     784       11516 :     return aString.SearchChar( pChars ) != STRING_NOTFOUND;
     785             : }
     786             : 
     787         224 : sal_uLong ScDrawStringsVars::GetResultValueFormat() const
     788             : {
     789             :     // Get the effective number format, including formula result types.
     790             :     // This assumes that a formula cell has already been calculated.
     791             : 
     792         224 :     return nValueFormat;
     793             : }
     794             : 
     795             : //==================================================================
     796             : 
     797        9753 : double ScOutputData::GetStretch()
     798             : {
     799        9753 :     if ( mpRefDevice->IsMapMode() )
     800             :     {
     801             :         //  If a non-trivial MapMode is set, its scale is now already
     802             :         //  taken into account in the OutputDevice's font handling
     803             :         //  (OutputDevice::ImplNewFont, see #95414#).
     804             :         //  The old handling below is only needed for pixel output.
     805         774 :         return 1.0;
     806             :     }
     807             : 
     808             :     // calculation in double is faster than Fraction multiplication
     809             :     // and doesn't overflow
     810             : 
     811        8979 :     if ( mpRefDevice == pFmtDevice )
     812             :     {
     813        8979 :         MapMode aOld = mpRefDevice->GetMapMode();
     814        8979 :         return ((double)aOld.GetScaleY()) / ((double)aOld.GetScaleX()) * ((double)aZoomY) / ((double)aZoomX);
     815             :     }
     816             :     else
     817             :     {
     818             :         // when formatting for printer, device map mode has already been taken care of
     819           0 :         return ((double)aZoomY) / ((double)aZoomX);
     820             :     }
     821             : }
     822             : 
     823             : //==================================================================
     824             : 
     825             : //
     826             : //  output strings
     827             : //
     828             : 
     829           0 : static void lcl_DoHyperlinkResult( OutputDevice* pDev, const Rectangle& rRect, ScRefCellValue& rCell )
     830             : {
     831           0 :     vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, pDev->GetExtOutDevData() );
     832             : 
     833           0 :     OUString aCellText;
     834           0 :     OUString aURL;
     835           0 :     if (rCell.meType == CELLTYPE_FORMULA)
     836             :     {
     837           0 :         ScFormulaCell* pFCell = rCell.mpFormula;
     838           0 :         if ( pFCell->IsHyperLinkCell() )
     839           0 :             pFCell->GetURLResult( aURL, aCellText );
     840             :     }
     841             : 
     842           0 :     if ( !aURL.isEmpty() && pPDFData )
     843             :     {
     844           0 :         vcl::PDFExtOutDevBookmarkEntry aBookmark;
     845           0 :         aBookmark.nLinkId = pPDFData->CreateLink( rRect );
     846           0 :         aBookmark.aBookmark = aURL;
     847           0 :         std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFData->GetBookmarks();
     848           0 :         rBookmarks.push_back( aBookmark );
     849           0 :     }
     850           0 : }
     851             : 
     852           0 : void ScOutputData::SetSyntaxColor( Font* pFont, const ScRefCellValue& rCell )
     853             : {
     854           0 :     switch (rCell.meType)
     855             :     {
     856             :         case CELLTYPE_VALUE:
     857           0 :             pFont->SetColor(*pValueColor);
     858           0 :         break;
     859             :         case CELLTYPE_STRING:
     860           0 :             pFont->SetColor(*pTextColor);
     861           0 :         break;
     862             :         case CELLTYPE_FORMULA:
     863           0 :             pFont->SetColor(*pFormulaColor);
     864           0 :         break;
     865             :         default:
     866             :         {
     867             :             // added to avoid warnings
     868             :         }
     869             :     }
     870           0 : }
     871             : 
     872           0 : static void lcl_SetEditColor( EditEngine& rEngine, const Color& rColor )
     873             : {
     874           0 :     ESelection aSel( 0, 0, rEngine.GetParagraphCount(), 0 );
     875           0 :     SfxItemSet aSet( rEngine.GetEmptyItemSet() );
     876           0 :     aSet.Put( SvxColorItem( rColor, EE_CHAR_COLOR ) );
     877           0 :     rEngine.QuickSetAttribs( aSet, aSel );
     878             :     // function is called with update mode set to FALSE
     879           0 : }
     880             : 
     881           0 : void ScOutputData::SetEditSyntaxColor( EditEngine& rEngine, ScRefCellValue& rCell )
     882             : {
     883           0 :     Color aColor;
     884           0 :     switch (rCell.meType)
     885             :     {
     886             :         case CELLTYPE_VALUE:
     887           0 :             aColor = *pValueColor;
     888           0 :             break;
     889             :         case CELLTYPE_STRING:
     890           0 :             aColor = *pTextColor;
     891           0 :             break;
     892             :         case CELLTYPE_FORMULA:
     893           0 :             aColor = *pFormulaColor;
     894           0 :             break;
     895             :         default:
     896             :         {
     897             :             // added to avoid warnings
     898             :         }
     899             :     }
     900           0 :     lcl_SetEditColor( rEngine, aColor );
     901           0 : }
     902             : 
     903         114 : sal_Bool ScOutputData::GetMergeOrigin( SCCOL nX, SCROW nY, SCSIZE nArrY,
     904             :                                     SCCOL& rOverX, SCROW& rOverY,
     905             :                                     sal_Bool bVisRowChanged )
     906             : {
     907         114 :     sal_Bool bDoMerge = false;
     908         114 :     sal_Bool bIsLeft = ( nX == nVisX1 );
     909         114 :     sal_Bool bIsTop  = ( nY == nVisY1 ) || bVisRowChanged;
     910             : 
     911         114 :     CellInfo* pInfo = &pRowInfo[nArrY].pCellInfo[nX+1];
     912         114 :     if ( pInfo->bHOverlapped && pInfo->bVOverlapped )
     913          48 :         bDoMerge = bIsLeft && bIsTop;
     914          66 :     else if ( pInfo->bHOverlapped )
     915          20 :         bDoMerge = bIsLeft;
     916          46 :     else if ( pInfo->bVOverlapped )
     917          46 :         bDoMerge = bIsTop;
     918             : 
     919         114 :     rOverX = nX;
     920         114 :     rOverY = nY;
     921         114 :     sal_Bool bHOver = pInfo->bHOverlapped;
     922         114 :     sal_Bool bVOver = pInfo->bVOverlapped;
     923             :     sal_Bool bHidden;
     924             : 
     925         228 :     while (bHOver)              // nY konstant
     926             :     {
     927          68 :         --rOverX;
     928          68 :         bHidden = mpDoc->ColHidden(rOverX, nTab);
     929          68 :         if ( !bDoMerge && !bHidden )
     930          68 :             return false;
     931             : 
     932           0 :         if (rOverX >= nX1 && !bHidden)
     933             :         {
     934           0 :             bHOver = pRowInfo[nArrY].pCellInfo[rOverX+1].bHOverlapped;
     935           0 :             bVOver = pRowInfo[nArrY].pCellInfo[rOverX+1].bVOverlapped;
     936             :         }
     937             :         else
     938             :         {
     939             :             sal_uInt16 nOverlap = ((ScMergeFlagAttr*)mpDoc->GetAttr(
     940           0 :                                 rOverX, rOverY, nTab, ATTR_MERGE_FLAG ))->GetValue();
     941           0 :             bHOver = ((nOverlap & SC_MF_HOR) != 0);
     942           0 :             bVOver = ((nOverlap & SC_MF_VER) != 0);
     943             :         }
     944             :     }
     945             : 
     946          94 :     while (bVOver)
     947             :     {
     948          46 :         --rOverY;
     949          46 :         bHidden = mpDoc->RowHidden(rOverY, nTab);
     950          46 :         if ( !bDoMerge && !bHidden )
     951          44 :             return false;
     952             : 
     953           2 :         if (nArrY>0)
     954           2 :             --nArrY;                        // lokale Kopie !
     955             : 
     956           6 :         if (rOverX >= nX1 && rOverY >= nY1 &&
     957           0 :             !mpDoc->ColHidden(rOverX, nTab) &&
     958           2 :             !mpDoc->RowHidden(rOverY, nTab) &&
     959           0 :             pRowInfo[nArrY].nRowNo == rOverY)
     960             :         {
     961           0 :             bHOver = pRowInfo[nArrY].pCellInfo[rOverX+1].bHOverlapped;
     962           0 :             bVOver = pRowInfo[nArrY].pCellInfo[rOverX+1].bVOverlapped;
     963             :         }
     964             :         else
     965             :         {
     966             :             sal_uInt16 nOverlap = ((ScMergeFlagAttr*)mpDoc->GetAttr(
     967           2 :                                 rOverX, rOverY, nTab, ATTR_MERGE_FLAG ))->GetValue();
     968           2 :             bHOver = ((nOverlap & SC_MF_HOR) != 0);
     969           2 :             bVOver = ((nOverlap & SC_MF_VER) != 0);
     970             :         }
     971             :     }
     972             : 
     973           2 :     return sal_True;
     974             : }
     975             : 
     976        8190 : inline sal_Bool StringDiffer( const ScPatternAttr*& rpOldPattern, const ScPatternAttr*& rpNewPattern )
     977             : {
     978             :     OSL_ENSURE( rpNewPattern, "pNewPattern" );
     979             : 
     980        8190 :     if ( rpNewPattern == rpOldPattern )
     981           0 :         return false;
     982        8190 :     else if ( !rpOldPattern )
     983         730 :         return sal_True;
     984        7460 :     else if ( &rpNewPattern->GetItem( ATTR_FONT ) != &rpOldPattern->GetItem( ATTR_FONT ) )
     985         319 :         return sal_True;
     986        7141 :     else if ( &rpNewPattern->GetItem( ATTR_CJK_FONT ) != &rpOldPattern->GetItem( ATTR_CJK_FONT ) )
     987          92 :         return sal_True;
     988        7049 :     else if ( &rpNewPattern->GetItem( ATTR_CTL_FONT ) != &rpOldPattern->GetItem( ATTR_CTL_FONT ) )
     989          40 :         return sal_True;
     990        7009 :     else if ( &rpNewPattern->GetItem( ATTR_FONT_HEIGHT ) != &rpOldPattern->GetItem( ATTR_FONT_HEIGHT ) )
     991         424 :         return sal_True;
     992        6585 :     else if ( &rpNewPattern->GetItem( ATTR_CJK_FONT_HEIGHT ) != &rpOldPattern->GetItem( ATTR_CJK_FONT_HEIGHT ) )
     993          14 :         return sal_True;
     994        6571 :     else if ( &rpNewPattern->GetItem( ATTR_CTL_FONT_HEIGHT ) != &rpOldPattern->GetItem( ATTR_CTL_FONT_HEIGHT ) )
     995          10 :         return sal_True;
     996        6561 :     else if ( &rpNewPattern->GetItem( ATTR_FONT_WEIGHT ) != &rpOldPattern->GetItem( ATTR_FONT_WEIGHT ) )
     997         178 :         return sal_True;
     998        6383 :     else if ( &rpNewPattern->GetItem( ATTR_CJK_FONT_WEIGHT ) != &rpOldPattern->GetItem( ATTR_CJK_FONT_WEIGHT ) )
     999           0 :         return sal_True;
    1000        6383 :     else if ( &rpNewPattern->GetItem( ATTR_CTL_FONT_WEIGHT ) != &rpOldPattern->GetItem( ATTR_CTL_FONT_WEIGHT ) )
    1001           0 :         return sal_True;
    1002        6383 :     else if ( &rpNewPattern->GetItem( ATTR_FONT_POSTURE ) != &rpOldPattern->GetItem( ATTR_FONT_POSTURE ) )
    1003           0 :         return sal_True;
    1004        6383 :     else if ( &rpNewPattern->GetItem( ATTR_CJK_FONT_POSTURE ) != &rpOldPattern->GetItem( ATTR_CJK_FONT_POSTURE ) )
    1005           0 :         return sal_True;
    1006        6383 :     else if ( &rpNewPattern->GetItem( ATTR_CTL_FONT_POSTURE ) != &rpOldPattern->GetItem( ATTR_CTL_FONT_POSTURE ) )
    1007           0 :         return sal_True;
    1008        6383 :     else if ( &rpNewPattern->GetItem( ATTR_FONT_UNDERLINE ) != &rpOldPattern->GetItem( ATTR_FONT_UNDERLINE ) )
    1009           0 :         return sal_True;
    1010        6383 :     else if ( &rpNewPattern->GetItem( ATTR_FONT_OVERLINE ) != &rpOldPattern->GetItem( ATTR_FONT_OVERLINE ) )
    1011           0 :         return sal_True;
    1012        6383 :     else if ( &rpNewPattern->GetItem( ATTR_FONT_WORDLINE ) != &rpOldPattern->GetItem( ATTR_FONT_WORDLINE ) )
    1013           0 :         return sal_True;
    1014        6383 :     else if ( &rpNewPattern->GetItem( ATTR_FONT_CROSSEDOUT ) != &rpOldPattern->GetItem( ATTR_FONT_CROSSEDOUT ) )
    1015           0 :         return sal_True;
    1016        6383 :     else if ( &rpNewPattern->GetItem( ATTR_FONT_CONTOUR ) != &rpOldPattern->GetItem( ATTR_FONT_CONTOUR ) )
    1017           0 :         return sal_True;
    1018        6383 :     else if ( &rpNewPattern->GetItem( ATTR_FONT_SHADOWED ) != &rpOldPattern->GetItem( ATTR_FONT_SHADOWED ) )
    1019           0 :         return sal_True;
    1020        6383 :     else if ( &rpNewPattern->GetItem( ATTR_FONT_COLOR ) != &rpOldPattern->GetItem( ATTR_FONT_COLOR ) )
    1021          16 :         return sal_True;
    1022        6367 :     else if ( &rpNewPattern->GetItem( ATTR_HOR_JUSTIFY ) != &rpOldPattern->GetItem( ATTR_HOR_JUSTIFY ) )
    1023         272 :         return true;
    1024        6095 :     else if ( &rpNewPattern->GetItem( ATTR_HOR_JUSTIFY_METHOD ) != &rpOldPattern->GetItem( ATTR_HOR_JUSTIFY_METHOD ) )
    1025           0 :         return true;
    1026        6095 :     else if ( &rpNewPattern->GetItem( ATTR_VER_JUSTIFY ) != &rpOldPattern->GetItem( ATTR_VER_JUSTIFY ) )
    1027          40 :         return true;
    1028        6055 :     else if ( &rpNewPattern->GetItem( ATTR_VER_JUSTIFY_METHOD ) != &rpOldPattern->GetItem( ATTR_VER_JUSTIFY_METHOD ) )
    1029           0 :         return true;
    1030        6055 :     else if ( &rpNewPattern->GetItem( ATTR_STACKED ) != &rpOldPattern->GetItem( ATTR_STACKED ) )
    1031           0 :         return sal_True;
    1032        6055 :     else if ( &rpNewPattern->GetItem( ATTR_LINEBREAK ) != &rpOldPattern->GetItem( ATTR_LINEBREAK ) )
    1033          54 :         return sal_True;
    1034        6001 :     else if ( &rpNewPattern->GetItem( ATTR_MARGIN ) != &rpOldPattern->GetItem( ATTR_MARGIN ) )
    1035           0 :         return sal_True;
    1036        6001 :     else if ( &rpNewPattern->GetItem( ATTR_ROTATE_VALUE ) != &rpOldPattern->GetItem( ATTR_ROTATE_VALUE ) )
    1037           0 :         return sal_True;
    1038        6001 :     else if ( &rpNewPattern->GetItem( ATTR_FORBIDDEN_RULES ) != &rpOldPattern->GetItem( ATTR_FORBIDDEN_RULES ) )
    1039           0 :         return sal_True;
    1040        6001 :     else if ( &rpNewPattern->GetItem( ATTR_FONT_EMPHASISMARK ) != &rpOldPattern->GetItem( ATTR_FONT_EMPHASISMARK ) )
    1041           0 :         return sal_True;
    1042        6001 :     else if ( &rpNewPattern->GetItem( ATTR_FONT_RELIEF ) != &rpOldPattern->GetItem( ATTR_FONT_RELIEF ) )
    1043           0 :         return sal_True;
    1044        6001 :     else if ( &rpNewPattern->GetItem( ATTR_BACKGROUND ) != &rpOldPattern->GetItem( ATTR_BACKGROUND ) )
    1045           0 :         return sal_True;    // needed with automatic text color
    1046             :     else
    1047             :     {
    1048        6001 :         rpOldPattern = rpNewPattern;
    1049        6001 :         return false;
    1050             :     }
    1051             : }
    1052             : 
    1053         306 : static inline void lcl_CreateInterpretProgress( sal_Bool& bProgress, ScDocument* pDoc,
    1054             :         ScFormulaCell* pFCell )
    1055             : {
    1056         306 :     if ( !bProgress && pFCell->GetDirty() )
    1057             :     {
    1058           2 :         ScProgress::CreateInterpretProgress( pDoc, sal_True );
    1059           2 :         bProgress = sal_True;
    1060             :     }
    1061         306 : }
    1062             : 
    1063           0 : inline sal_Bool IsAmbiguousScript( sal_uInt8 nScript )
    1064             : {
    1065           0 :     return ( nScript != SCRIPTTYPE_LATIN &&
    1066           0 :              nScript != SCRIPTTYPE_ASIAN &&
    1067           0 :              nScript != SCRIPTTYPE_COMPLEX );
    1068             : }
    1069             : 
    1070       50995 : bool ScOutputData::IsEmptyCellText( RowInfo* pThisRowInfo, SCCOL nX, SCROW nY )
    1071             : {
    1072             :     // pThisRowInfo may be NULL
    1073             : 
    1074             :     bool bEmpty;
    1075       50995 :     if ( pThisRowInfo && nX <= nX2 )
    1076       34232 :         bEmpty = pThisRowInfo->pCellInfo[nX+1].bEmptyCellText;
    1077             :     else
    1078             :     {
    1079       16763 :         ScRefCellValue aCell;
    1080       16763 :         aCell.assign(*mpDoc, ScAddress(nX, nY, nTab));
    1081       16763 :         bEmpty = aCell.isEmpty();
    1082             :     }
    1083             : 
    1084       50995 :     if ( !bEmpty && ( nX < nX1 || nX > nX2 || !pThisRowInfo ) )
    1085             :     {
    1086             :         //  for the range nX1..nX2 in RowInfo, cell protection attribute is already evaluated
    1087             :         //  into bEmptyCellText in ScDocument::FillInfo / lcl_HidePrint (printfun)
    1088             : 
    1089        1204 :         bool bIsPrint = ( eType == OUTTYPE_PRINTER );
    1090             : 
    1091        1204 :         if ( bIsPrint || bTabProtected )
    1092             :         {
    1093             :             const ScProtectionAttr* pAttr = (const ScProtectionAttr*)
    1094           0 :                     mpDoc->GetEffItem( nX, nY, nTab, ATTR_PROTECTION );
    1095           0 :             if ( bIsPrint && pAttr->GetHidePrint() )
    1096           0 :                 bEmpty = true;
    1097           0 :             else if ( bTabProtected )
    1098             :             {
    1099           0 :                 if ( pAttr->GetHideCell() )
    1100           0 :                     bEmpty = true;
    1101           0 :                 else if ( mbShowFormulas && pAttr->GetHideFormula() )
    1102             :                 {
    1103           0 :                     if (mpDoc->GetCellType(ScAddress(nX, nY, nTab)) == CELLTYPE_FORMULA)
    1104           0 :                         bEmpty = true;
    1105             :                 }
    1106             :             }
    1107             :         }
    1108             :     }
    1109       50995 :     return bEmpty;
    1110             : }
    1111             : 
    1112         372 : void ScOutputData::GetVisibleCell( SCCOL nCol, SCROW nRow, SCTAB nTabP, ScRefCellValue& rCell )
    1113             : {
    1114         372 :     rCell.assign(*mpDoc, ScAddress(nCol, nRow, nTabP));
    1115         372 :     if (!rCell.isEmpty() && IsEmptyCellText(NULL, nCol, nRow))
    1116           0 :         rCell.clear();
    1117         372 : }
    1118             : 
    1119         764 : bool ScOutputData::IsAvailable( SCCOL nX, SCROW nY )
    1120             : {
    1121             :     //  apply the same logic here as in DrawStrings/DrawEdit:
    1122             :     //  Stop at non-empty or merged or overlapped cell,
    1123             :     //  where a note is empty as well as a cell that's hidden by protection settings
    1124             : 
    1125         764 :     ScRefCellValue aCell;
    1126         764 :     aCell.assign(*mpDoc, ScAddress(nX, nY, nTab));
    1127         764 :     if (!aCell.isEmpty() && !IsEmptyCellText(NULL, nX, nY))
    1128         216 :         return false;
    1129             : 
    1130         548 :     const ScPatternAttr* pPattern = mpDoc->GetPattern( nX, nY, nTab );
    1131        1096 :     if ( ((const ScMergeAttr&)pPattern->GetItem(ATTR_MERGE)).IsMerged() ||
    1132         548 :          ((const ScMergeFlagAttr&)pPattern->GetItem(ATTR_MERGE_FLAG)).IsOverlapped() )
    1133             :     {
    1134           0 :         return false;
    1135             :     }
    1136             : 
    1137         548 :     return sal_True;
    1138             : }
    1139             : 
    1140             : // nX, nArrY:       loop variables from DrawStrings / DrawEdit
    1141             : // nPosX, nPosY:    corresponding positions for nX, nArrY
    1142             : // nCellX, nCellY:  position of the cell that contains the text
    1143             : // nNeeded:         Text width, including margin
    1144             : // rPattern:        cell format at nCellX, nCellY
    1145             : // nHorJustify:     horizontal alignment (visual) to determine which cells to use for long strings
    1146             : // bCellIsValue:    if set, don't extend into empty cells
    1147             : // bBreak:          if set, don't extend, and don't set clip marks (but rLeftClip/rRightClip is set)
    1148             : // bOverwrite:      if set, also extend into non-empty cells (for rotated text)
    1149             : // rParam           output: various area parameters.
    1150             : 
    1151       12066 : void ScOutputData::GetOutputArea( SCCOL nX, SCSIZE nArrY, long nPosX, long nPosY,
    1152             :                                   SCCOL nCellX, SCROW nCellY, long nNeeded,
    1153             :                                   const ScPatternAttr& rPattern,
    1154             :                                   sal_uInt16 nHorJustify, bool bCellIsValue,
    1155             :                                   bool bBreak, bool bOverwrite,
    1156             :                                   OutputAreaParam& rParam )
    1157             : {
    1158             :     //  rThisRowInfo may be for a different row than nCellY, is still used for clip marks
    1159       12066 :     RowInfo& rThisRowInfo = pRowInfo[nArrY];
    1160             : 
    1161       12066 :     long nLayoutSign = bLayoutRTL ? -1 : 1;
    1162             : 
    1163       12066 :     long nCellPosX = nPosX;         // find nCellX position, starting at nX/nPosX
    1164       12066 :     SCCOL nCompCol = nX;
    1165       24794 :     while ( nCellX > nCompCol )
    1166             :     {
    1167             :         //! extra member function for width?
    1168         662 :         long nColWidth = ( nCompCol <= nX2 ) ?
    1169         174 :                 pRowInfo[0].pCellInfo[nCompCol+1].nWidth :
    1170         836 :                 (long) ( mpDoc->GetColWidth( nCompCol, nTab ) * mnPPTX );
    1171         662 :         nCellPosX += nColWidth * nLayoutSign;
    1172         662 :         ++nCompCol;
    1173             :     }
    1174       27969 :     while ( nCellX < nCompCol )
    1175             :     {
    1176        3837 :         --nCompCol;
    1177        3837 :         long nColWidth = ( nCompCol <= nX2 ) ?
    1178        3837 :                 pRowInfo[0].pCellInfo[nCompCol+1].nWidth :
    1179        7674 :                 (long) ( mpDoc->GetColWidth( nCompCol, nTab ) * mnPPTX );
    1180        3837 :         nCellPosX -= nColWidth * nLayoutSign;
    1181             :     }
    1182             : 
    1183       12066 :     long nCellPosY = nPosY;         // find nCellY position, starting at nArrY/nPosY
    1184       12066 :     SCSIZE nCompArr = nArrY;
    1185       12066 :     SCROW nCompRow = pRowInfo[nCompArr].nRowNo;
    1186       24132 :     while ( nCellY > nCompRow )
    1187             :     {
    1188           0 :         if ( nCompArr + 1 < nArrCount )
    1189             :         {
    1190           0 :             nCellPosY += pRowInfo[nCompArr].nHeight;
    1191           0 :             ++nCompArr;
    1192           0 :             nCompRow = pRowInfo[nCompArr].nRowNo;
    1193             :         }
    1194             :         else
    1195             :         {
    1196           0 :             sal_uInt16 nDocHeight = mpDoc->GetRowHeight( nCompRow, nTab );
    1197           0 :             if ( nDocHeight )
    1198           0 :                 nCellPosY += (long) ( nDocHeight * mnPPTY );
    1199           0 :             ++nCompRow;
    1200             :         }
    1201             :     }
    1202       12066 :     nCellPosY -= (long) mpDoc->GetScaledRowHeight( nCellY, nCompRow-1, nTab, mnPPTY );
    1203             : 
    1204       12066 :     const ScMergeAttr* pMerge = (const ScMergeAttr*)&rPattern.GetItem( ATTR_MERGE );
    1205       12066 :     sal_Bool bMerged = pMerge->IsMerged();
    1206       12066 :     long nMergeCols = pMerge->GetColMerge();
    1207       12066 :     if ( nMergeCols == 0 )
    1208       12064 :         nMergeCols = 1;
    1209       12066 :     long nMergeRows = pMerge->GetRowMerge();
    1210       12066 :     if ( nMergeRows == 0 )
    1211       12064 :         nMergeRows = 1;
    1212             : 
    1213             :     long i;
    1214       12066 :     long nMergeSizeX = 0;
    1215       24136 :     for ( i=0; i<nMergeCols; i++ )
    1216             :     {
    1217       12070 :         long nColWidth = ( nCellX+i <= nX2 ) ?
    1218       11896 :                 pRowInfo[0].pCellInfo[nCellX+i+1].nWidth :
    1219       23966 :                 (long) ( mpDoc->GetColWidth( sal::static_int_cast<SCCOL>(nCellX+i), nTab ) * mnPPTX );
    1220       12070 :         nMergeSizeX += nColWidth;
    1221             :     }
    1222       12066 :     long nMergeSizeY = 0;
    1223       12066 :     short nDirect = 0;
    1224       12066 :     if ( rThisRowInfo.nRowNo == nCellY )
    1225             :     {
    1226             :         // take first row's height from row info
    1227       12066 :         nMergeSizeY += rThisRowInfo.nHeight;
    1228       12066 :         nDirect = 1;        // skip in loop
    1229             :     }
    1230             :     // following rows always from document
    1231       12066 :     nMergeSizeY += (long) mpDoc->GetScaledRowHeight( nCellY+nDirect, nCellY+nMergeRows-1, nTab, mnPPTY);
    1232             : 
    1233       12066 :     --nMergeSizeX;      // leave out the grid horizontally, also for alignment (align between grid lines)
    1234             : 
    1235       12066 :     rParam.mnColWidth = nMergeSizeX; // store the actual column width.
    1236             : 
    1237             :     //
    1238             :     // construct the rectangles using logical left/right values (justify is called at the end)
    1239             :     //
    1240             : 
    1241             :     //  rAlignRect is the single cell or merged area, used for alignment.
    1242             : 
    1243       12066 :     rParam.maAlignRect.Left() = nCellPosX;
    1244       12066 :     rParam.maAlignRect.Right() = nCellPosX + ( nMergeSizeX - 1 ) * nLayoutSign;
    1245       12066 :     rParam.maAlignRect.Top() = nCellPosY;
    1246       12066 :     rParam.maAlignRect.Bottom() = nCellPosY + nMergeSizeY - 1;
    1247             : 
    1248             :     //  rClipRect is all cells that are used for output.
    1249             :     //  For merged cells this is the same as rAlignRect, otherwise neighboring cells can also be used.
    1250             : 
    1251       12066 :     rParam.maClipRect = rParam.maAlignRect;
    1252       12066 :     if ( nNeeded > nMergeSizeX )
    1253             :     {
    1254         995 :         SvxCellHorJustify eHorJust = (SvxCellHorJustify)nHorJustify;
    1255             : 
    1256         995 :         long nMissing = nNeeded - nMergeSizeX;
    1257         995 :         long nLeftMissing = 0;
    1258         995 :         long nRightMissing = 0;
    1259         995 :         switch ( eHorJust )
    1260             :         {
    1261             :             case SVX_HOR_JUSTIFY_LEFT:
    1262         546 :                 nRightMissing = nMissing;
    1263         546 :                 break;
    1264             :             case SVX_HOR_JUSTIFY_RIGHT:
    1265         246 :                 nLeftMissing = nMissing;
    1266         246 :                 break;
    1267             :             case SVX_HOR_JUSTIFY_CENTER:
    1268         172 :                 nLeftMissing = nMissing / 2;
    1269         172 :                 nRightMissing = nMissing - nLeftMissing;
    1270         172 :                 break;
    1271             :             default:
    1272             :             {
    1273             :                 // added to avoid warnings
    1274             :             }
    1275             :         }
    1276             : 
    1277             :         // nLeftMissing, nRightMissing are logical, eHorJust values are visual
    1278         995 :         if ( bLayoutRTL )
    1279           0 :             ::std::swap( nLeftMissing, nRightMissing );
    1280             : 
    1281         995 :         SCCOL nRightX = nCellX;
    1282         995 :         SCCOL nLeftX = nCellX;
    1283         995 :         if ( !bMerged && !bCellIsValue && !bBreak )
    1284             :         {
    1285             :             //  look for empty cells into which the text can be extended
    1286             : 
    1287        2231 :             while ( nRightMissing > 0 && nRightX < MAXCOL && ( bOverwrite || IsAvailable( nRightX+1, nCellY ) ) )
    1288             :             {
    1289         703 :                 ++nRightX;
    1290         703 :                 long nAdd = (long) ( mpDoc->GetColWidth( nRightX, nTab ) * mnPPTX );
    1291         703 :                 nRightMissing -= nAdd;
    1292         703 :                 rParam.maClipRect.Right() += nAdd * nLayoutSign;
    1293             : 
    1294         703 :                 if ( rThisRowInfo.nRowNo == nCellY && nRightX >= nX1 && nRightX <= nX2 )
    1295         626 :                     rThisRowInfo.pCellInfo[nRightX].bHideGrid = sal_True;
    1296             :             }
    1297             : 
    1298        1644 :             while ( nLeftMissing > 0 && nLeftX > 0 && ( bOverwrite || IsAvailable( nLeftX-1, nCellY ) ) )
    1299             :             {
    1300         116 :                 if ( rThisRowInfo.nRowNo == nCellY && nLeftX >= nX1 && nLeftX <= nX2 )
    1301         116 :                     rThisRowInfo.pCellInfo[nLeftX].bHideGrid = sal_True;
    1302             : 
    1303         116 :                 --nLeftX;
    1304         116 :                 long nAdd = (long) ( mpDoc->GetColWidth( nLeftX, nTab ) * mnPPTX );
    1305         116 :                 nLeftMissing -= nAdd;
    1306         116 :                 rParam.maClipRect.Left() -= nAdd * nLayoutSign;
    1307             :             }
    1308             :         }
    1309             : 
    1310             :         //  Set flag and reserve space for clipping mark triangle,
    1311             :         //  even if rThisRowInfo isn't for nCellY (merged cells).
    1312         995 :         if ( nRightMissing > 0 && bMarkClipped && nRightX >= nX1 && nRightX <= nX2 && !bBreak && !bCellIsValue )
    1313             :         {
    1314         207 :             rThisRowInfo.pCellInfo[nRightX+1].nClipMark |= SC_CLIPMARK_RIGHT;
    1315         207 :             bAnyClipped = sal_True;
    1316         207 :             long nMarkPixel = (long)( SC_CLIPMARK_SIZE * mnPPTX );
    1317         207 :             rParam.maClipRect.Right() -= nMarkPixel * nLayoutSign;
    1318             :         }
    1319         995 :         if ( nLeftMissing > 0 && bMarkClipped && nLeftX >= nX1 && nLeftX <= nX2 && !bBreak && !bCellIsValue )
    1320             :         {
    1321         128 :             rThisRowInfo.pCellInfo[nLeftX+1].nClipMark |= SC_CLIPMARK_LEFT;
    1322         128 :             bAnyClipped = sal_True;
    1323         128 :             long nMarkPixel = (long)( SC_CLIPMARK_SIZE * mnPPTX );
    1324         128 :             rParam.maClipRect.Left() += nMarkPixel * nLayoutSign;
    1325             :         }
    1326             : 
    1327         995 :         rParam.mbLeftClip = ( nLeftMissing > 0 );
    1328         995 :         rParam.mbRightClip = ( nRightMissing > 0 );
    1329             :     }
    1330             :     else
    1331             :     {
    1332       11071 :         rParam.mbLeftClip = rParam.mbRightClip = false;
    1333             : 
    1334             :         // leave space for AutoFilter on screen
    1335             :         // (for automatic line break: only if not formatting for printer, as in ScColumn::GetNeededSize)
    1336             : 
    1337       33184 :         if ( eType==OUTTYPE_WINDOW &&
    1338       11331 :              ( static_cast<const ScMergeFlagAttr&>(rPattern.GetItem(ATTR_MERGE_FLAG)).GetValue() & (SC_MF_AUTO|SC_MF_BUTTON|SC_MF_BUTTON_POPUP) ) &&
    1339         130 :              ( !bBreak || mpRefDevice == pFmtDevice ) )
    1340             :         {
    1341             :             // filter drop-down width is now independent from row height
    1342         130 :             const long nFilter = DROPDOWN_BITMAP_SIZE;
    1343         130 :             sal_Bool bFit = ( nNeeded + nFilter <= nMergeSizeX );
    1344         130 :             if ( bFit || bCellIsValue )
    1345             :             {
    1346             :                 // content fits even in the remaining area without the filter button
    1347             :                 // -> align within that remaining area
    1348             : 
    1349         130 :                 rParam.maAlignRect.Right() -= nFilter * nLayoutSign;
    1350         130 :                 rParam.maClipRect.Right() -= nFilter * nLayoutSign;
    1351             : 
    1352             :                 // if a number doesn't fit, don't hide part of the number behind the button
    1353             :                 // -> set clip flags, so "###" replacement is used (but also within the smaller area)
    1354             : 
    1355         130 :                 if ( !bFit )
    1356           0 :                     rParam.mbLeftClip = rParam.mbRightClip = sal_True;
    1357             :             }
    1358             :         }
    1359             :     }
    1360             : 
    1361             :     //  justify both rectangles for alignment calculation, use with DrawText etc.
    1362             : 
    1363       12066 :     rParam.maAlignRect.Justify();
    1364       12066 :     rParam.maClipRect.Justify();
    1365       12066 : }
    1366             : 
    1367             : namespace {
    1368             : 
    1369       10408 : bool beginsWithRTLCharacter(const OUString& rStr)
    1370             : {
    1371       10408 :     if (rStr.isEmpty())
    1372           2 :         return false;
    1373             : 
    1374       10406 :     switch (ScGlobal::pCharClass->getCharacterDirection(rStr, 0))
    1375             :     {
    1376             :         case i18n::DirectionProperty_RIGHT_TO_LEFT:
    1377             :         case i18n::DirectionProperty_RIGHT_TO_LEFT_ARABIC:
    1378             :         case i18n::DirectionProperty_RIGHT_TO_LEFT_EMBEDDING:
    1379             :         case i18n::DirectionProperty_RIGHT_TO_LEFT_OVERRIDE:
    1380           0 :             return true;
    1381             :         default:
    1382             :             ;
    1383             :     }
    1384             : 
    1385       10406 :     return false;
    1386             : }
    1387             : 
    1388             : }
    1389             : 
    1390        1179 : void ScOutputData::DrawStrings( sal_Bool bPixelToLogic )
    1391             : {
    1392             :     OSL_ENSURE( mpDev == mpRefDevice ||
    1393             :                 mpDev->GetMapMode().GetMapUnit() == mpRefDevice->GetMapMode().GetMapUnit(),
    1394             :                 "DrawStrings: unterschiedliche MapUnits ?!?!" );
    1395             : 
    1396        1179 :     vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, mpDev->GetExtOutDevData() );
    1397             : 
    1398        1179 :     bool bWasIdleEnabled = mpDoc->IsIdleEnabled();
    1399        1179 :     mpDoc->EnableIdle(false);
    1400             : 
    1401        1179 :     ScDrawStringsVars aVars( this, bPixelToLogic );
    1402             : 
    1403        1179 :     sal_Bool bProgress = false;
    1404             : 
    1405        1179 :     long nInitPosX = nScrX;
    1406        1179 :     if ( bLayoutRTL )
    1407           1 :         nInitPosX += nMirrorW - 1;              // pixels
    1408        1179 :     long nLayoutSign = bLayoutRTL ? -1 : 1;
    1409             : 
    1410        1179 :     SCCOL nLastContentCol = MAXCOL;
    1411        1179 :     if ( nX2 < MAXCOL )
    1412             :         nLastContentCol = sal::static_int_cast<SCCOL>(
    1413        1178 :             nLastContentCol - mpDoc->GetEmptyLinesInBlock( nX2+1, nY1, nTab, MAXCOL, nY2, nTab, DIR_RIGHT ) );
    1414        1179 :     SCCOL nLoopStartX = nX1;
    1415        1179 :     if ( nX1 > 0 )
    1416         178 :         --nLoopStartX;          // start before nX1 for rest of long text to the left
    1417             : 
    1418             :     // variables for GetOutputArea
    1419        1179 :     OutputAreaParam aAreaParam;
    1420        1179 :     sal_Bool bCellIsValue = false;
    1421        1179 :     long nNeededWidth = 0;
    1422        1179 :     SvxCellHorJustify eOutHorJust = SVX_HOR_JUSTIFY_STANDARD;
    1423        1179 :     const ScPatternAttr* pPattern = NULL;
    1424        1179 :     const SfxItemSet* pCondSet = NULL;
    1425        1179 :     const ScPatternAttr* pOldPattern = NULL;
    1426        1179 :     const SfxItemSet* pOldCondSet = NULL;
    1427        1179 :     sal_uInt8 nOldScript = 0;
    1428             : 
    1429             :     // alternative pattern instances in case we need to modify the pattern
    1430             :     // before processing the cell value.
    1431        2358 :     ::boost::ptr_vector<ScPatternAttr> aAltPatterns;
    1432             : 
    1433        1179 :     long nPosY = nScrY;
    1434       19858 :     for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
    1435             :     {
    1436       18679 :         RowInfo* pThisRowInfo = &pRowInfo[nArrY];
    1437       18679 :         if ( pThisRowInfo->bChanged )
    1438             :         {
    1439       18679 :             SCROW nY = pThisRowInfo->nRowNo;
    1440       18679 :             long nPosX = nInitPosX;
    1441       18679 :             if ( nLoopStartX < nX1 )
    1442        1312 :                 nPosX -= pRowInfo[0].pCellInfo[nLoopStartX+1].nWidth * nLayoutSign;
    1443      206136 :             for (SCCOL nX=nLoopStartX; nX<=nX2; nX++)
    1444             :             {
    1445      187457 :                 sal_Bool bMergeEmpty = false;
    1446      187457 :                 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
    1447      187457 :                 sal_Bool bEmpty = nX < nX1 || pInfo->bEmptyCellText;
    1448             : 
    1449      187457 :                 SCCOL nCellX = nX;                  // position where the cell really starts
    1450      187457 :                 SCROW nCellY = nY;
    1451      187457 :                 sal_Bool bDoCell = false;
    1452      187457 :                 sal_Bool bNeedEdit = false;
    1453             : 
    1454             :                 //
    1455             :                 //  Part of a merged cell?
    1456             :                 //
    1457             : 
    1458      187457 :                 sal_Bool bOverlapped = ( pInfo->bHOverlapped || pInfo->bVOverlapped );
    1459      187457 :                 if ( bOverlapped )
    1460             :                 {
    1461         114 :                     bEmpty = sal_True;
    1462             : 
    1463             :                     SCCOL nOverX;                   // start of the merged cells
    1464             :                     SCROW nOverY;
    1465         114 :                     sal_Bool bVisChanged = !pRowInfo[nArrY-1].bChanged;
    1466         114 :                     if (GetMergeOrigin( nX,nY, nArrY, nOverX,nOverY, bVisChanged ))
    1467             :                     {
    1468           2 :                         nCellX = nOverX;
    1469           2 :                         nCellY = nOverY;
    1470           2 :                         bDoCell = sal_True;
    1471             :                     }
    1472             :                     else
    1473         112 :                         bMergeEmpty = sal_True;
    1474             :                 }
    1475             : 
    1476             :                 //
    1477             :                 //  Rest of a long text further to the left?
    1478             :                 //
    1479             : 
    1480      187457 :                 if ( bEmpty && !bMergeEmpty && nX < nX1 && !bOverlapped )
    1481             :                 {
    1482        1312 :                     SCCOL nTempX=nX1;
    1483       33438 :                     while (nTempX > 0 && IsEmptyCellText( pThisRowInfo, nTempX, nY ))
    1484       30814 :                         --nTempX;
    1485             : 
    1486        3304 :                     if ( nTempX < nX1 &&
    1487        1514 :                          !IsEmptyCellText( pThisRowInfo, nTempX, nY ) &&
    1488         202 :                          !mpDoc->HasAttrib( nTempX,nY,nTab, nX1,nY,nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ) )
    1489             :                     {
    1490         196 :                         nCellX = nTempX;
    1491         196 :                         bDoCell = sal_True;
    1492             :                     }
    1493             :                 }
    1494             : 
    1495             :                 //
    1496             :                 //  Rest of a long text further to the right?
    1497             :                 //
    1498             : 
    1499      187457 :                 if ( bEmpty && !bMergeEmpty && nX == nX2 && !bOverlapped )
    1500             :                 {
    1501             :                     //  don't have to look further than nLastContentCol
    1502             : 
    1503       17946 :                     SCCOL nTempX=nX;
    1504       51965 :                     while (nTempX < nLastContentCol && IsEmptyCellText( pThisRowInfo, nTempX, nY ))
    1505       16073 :                         ++nTempX;
    1506             : 
    1507       19536 :                     if ( nTempX > nX &&
    1508       18120 :                          !IsEmptyCellText( pThisRowInfo, nTempX, nY ) &&
    1509         174 :                          !mpDoc->HasAttrib( nTempX,nY,nTab, nX,nY,nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ) )
    1510             :                     {
    1511         174 :                         nCellX = nTempX;
    1512         174 :                         bDoCell = sal_True;
    1513             :                     }
    1514             :                 }
    1515             : 
    1516             :                 //
    1517             :                 //  normal visible cell
    1518             :                 //
    1519             : 
    1520      187457 :                 if (!bEmpty)
    1521       11626 :                     bDoCell = sal_True;
    1522             : 
    1523             :                 //
    1524             :                 //  don't output the cell that's being edited
    1525             :                 //
    1526             : 
    1527      187457 :                 if ( bDoCell && bEditMode && nCellX == nEditCol && nCellY == nEditRow )
    1528           0 :                     bDoCell = false;
    1529             : 
    1530             :                 // skip text in cell if data bar/icon set is set and only value selected
    1531      187457 :                 if ( bDoCell )
    1532             :                 {
    1533       11998 :                     if(pInfo->pDataBar && !pInfo->pDataBar->mbShowValue)
    1534           0 :                         bDoCell = false;
    1535       11998 :                     if(pInfo->pIconSet && !pInfo->pIconSet->mbShowValue)
    1536           0 :                         bDoCell = false;
    1537             :                 }
    1538             : 
    1539             :                 //
    1540             :                 //  output the cell text
    1541             :                 //
    1542             : 
    1543      187457 :                 ScRefCellValue aCell;
    1544      187457 :                 if (bDoCell)
    1545             :                 {
    1546       11998 :                     if ( nCellY == nY && nCellX == nX && nCellX >= nX1 && nCellX <= nX2 )
    1547       11626 :                         aCell = pThisRowInfo->pCellInfo[nCellX+1].maCell;
    1548             :                     else
    1549         372 :                         GetVisibleCell( nCellX, nCellY, nTab, aCell );      // get from document
    1550       11998 :                     if (aCell.isEmpty())
    1551           2 :                         bDoCell = false;
    1552       11996 :                     else if (aCell.meType == CELLTYPE_EDIT)
    1553         104 :                         bNeedEdit = true;
    1554             :                 }
    1555      187457 :                 if (bDoCell && !bNeedEdit)
    1556             :                 {
    1557       11892 :                     if ( nCellY == nY && nCellX >= nX1 && nCellX <= nX2 )
    1558             :                     {
    1559       11522 :                         CellInfo& rCellInfo = pThisRowInfo->pCellInfo[nCellX+1];
    1560       11522 :                         pPattern = rCellInfo.pPatternAttr;
    1561       11522 :                         pCondSet = rCellInfo.pConditionSet;
    1562             : 
    1563       11522 :                         if ( !pPattern )
    1564             :                         {
    1565             :                             // #i68085# pattern from cell info for hidden columns is null,
    1566             :                             // test for null is quicker than using column flags
    1567           0 :                             pPattern = mpDoc->GetPattern( nCellX, nCellY, nTab );
    1568           0 :                             pCondSet = mpDoc->GetCondResult( nCellX, nCellY, nTab );
    1569       11522 :                         }
    1570             :                     }
    1571             :                     else        // get from document
    1572             :                     {
    1573         370 :                         pPattern = mpDoc->GetPattern( nCellX, nCellY, nTab );
    1574         370 :                         pCondSet = mpDoc->GetCondResult( nCellX, nCellY, nTab );
    1575             :                     }
    1576       11892 :                     if ( mpDoc->GetPreviewFont() )
    1577             :                     {
    1578        7176 :                         aAltPatterns.push_back(new ScPatternAttr(*pPattern));
    1579        7176 :                         ScPatternAttr* pAltPattern = &aAltPatterns.back();
    1580        7176 :                         if ( SfxItemSet* pFontSet = mpDoc->GetPreviewFont( nCellX, nCellY, nTab ) )
    1581             :                         {
    1582             :                             const SfxPoolItem* pItem;
    1583         209 :                             if ( pFontSet->GetItemState( ATTR_FONT, true, &pItem ) == SFX_ITEM_SET )
    1584         209 :                                 pAltPattern->GetItemSet().Put( (const SvxFontItem&)*pItem );
    1585         209 :                             if ( pFontSet->GetItemState( ATTR_CJK_FONT, true, &pItem ) == SFX_ITEM_SET )
    1586           0 :                                 pAltPattern->GetItemSet().Put( (const SvxFontItem&)*pItem );
    1587         209 :                             if ( pFontSet->GetItemState( ATTR_CTL_FONT, true, &pItem ) == SFX_ITEM_SET )
    1588           0 :                                 pAltPattern->GetItemSet().Put( (const SvxFontItem&)*pItem );
    1589             :                         }
    1590        7176 :                         pPattern = pAltPattern;
    1591             :                     }
    1592             : 
    1593       18668 :                     if (aCell.hasNumeric() &&
    1594             :                         static_cast<const SfxBoolItem&>(
    1595        6776 :                             pPattern->GetItem(ATTR_LINEBREAK, pCondSet)).GetValue())
    1596             :                     {
    1597             :                         // Disable line break when the cell content is numeric.
    1598         329 :                         aAltPatterns.push_back(new ScPatternAttr(*pPattern));
    1599         329 :                         ScPatternAttr* pAltPattern = &aAltPatterns.back();
    1600         329 :                         SfxBoolItem aLineBreak(ATTR_LINEBREAK, false);
    1601         329 :                         pAltPattern->GetItemSet().Put(aLineBreak);
    1602         329 :                         pPattern = pAltPattern;
    1603             :                     }
    1604             : 
    1605             :                     sal_uInt8 nScript = mpDoc->GetCellScriptType(
    1606             :                         ScAddress(nCellX, nCellY, nTab),
    1607       11892 :                         pPattern->GetNumberFormat(mpDoc->GetFormatTable(), pCondSet));
    1608             : 
    1609       11892 :                     if (nScript == 0)
    1610          50 :                         nScript = ScGlobal::GetDefaultScriptType();
    1611             : 
    1612       11892 :                     if ( pPattern != pOldPattern || pCondSet != pOldCondSet ||
    1613        3702 :                          nScript != nOldScript || mbSyntaxMode )
    1614             :                     {
    1615       22381 :                         if ( StringDiffer(pOldPattern,pPattern) ||
    1616       14187 :                              pCondSet != pOldCondSet || nScript != nOldScript || mbSyntaxMode )
    1617             :                         {
    1618        2193 :                             aVars.SetPattern(pPattern, pCondSet, aCell, nScript);
    1619             :                         }
    1620             :                         else
    1621        5997 :                             aVars.SetPatternSimple( pPattern, pCondSet );
    1622        8190 :                         pOldPattern = pPattern;
    1623        8190 :                         pOldCondSet = pCondSet;
    1624        8190 :                         nOldScript = nScript;
    1625             :                     }
    1626             : 
    1627             :                     //  use edit engine for rotated, stacked or mixed-script text
    1628       35676 :                     if ( aVars.GetOrient() == SVX_ORIENTATION_STACKED ||
    1629       23408 :                          aVars.IsRotated() || IsAmbiguousScript(nScript) )
    1630         376 :                         bNeedEdit = sal_True;
    1631             :                 }
    1632      187457 :                 if (bDoCell && !bNeedEdit)
    1633             :                 {
    1634       11516 :                     bool bFormulaCell = (aCell.meType == CELLTYPE_FORMULA);
    1635       11516 :                     if ( bFormulaCell )
    1636         306 :                         lcl_CreateInterpretProgress(bProgress, mpDoc, aCell.mpFormula);
    1637       11516 :                     if ( aVars.SetText(aCell) )
    1638           0 :                         pOldPattern = NULL;
    1639       11516 :                     bNeedEdit = aVars.HasEditCharacters() || (bFormulaCell && aCell.mpFormula->IsMultilineResult());
    1640             :                 }
    1641      187457 :                 long nTotalMargin = 0;
    1642      187457 :                 if (bDoCell && !bNeedEdit)
    1643             :                 {
    1644       11516 :                     CellType eCellType = aCell.meType;
    1645       11516 :                     bCellIsValue = ( eCellType == CELLTYPE_VALUE );
    1646       11516 :                     if ( eCellType == CELLTYPE_FORMULA )
    1647             :                     {
    1648         306 :                         ScFormulaCell* pFCell = aCell.mpFormula;
    1649         306 :                         bCellIsValue = pFCell->IsRunning() || pFCell->IsValue();
    1650             :                     }
    1651             : 
    1652       11516 :                     if (aVars.GetHorJust() == SVX_HOR_JUSTIFY_STANDARD)
    1653             :                     {
    1654             :                         // fdo#32530: Default alignment depends on value vs
    1655             :                         // string, and the direction of the 1st letter.
    1656        9858 :                         if (beginsWithRTLCharacter(aVars.GetString()))
    1657           0 :                             eOutHorJust = bCellIsValue ? SVX_HOR_JUSTIFY_LEFT : SVX_HOR_JUSTIFY_RIGHT;
    1658             :                         else
    1659        9858 :                             eOutHorJust = bCellIsValue ? SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_LEFT;
    1660             :                     }
    1661             :                     else
    1662        1658 :                         eOutHorJust = aVars.GetHorJust();
    1663             : 
    1664       11516 :                     if ( eOutHorJust == SVX_HOR_JUSTIFY_BLOCK || eOutHorJust == SVX_HOR_JUSTIFY_REPEAT )
    1665             :                     {
    1666          12 :                         const SfxPoolItem* pItem =  mpDoc->GetAttr( nCellX, nCellY, nTab, ATTR_WRITINGDIR );
    1667          12 :                         const SvxFrameDirectionItem* pCurrentWritingMode = (const SvxFrameDirectionItem*) pItem;
    1668          12 :                         if (pCurrentWritingMode->GetValue() == FRMDIR_HORI_LEFT_TOP)
    1669           0 :                             eOutHorJust = SVX_HOR_JUSTIFY_LEFT;
    1670             :                         else
    1671          12 :                             eOutHorJust = SVX_HOR_JUSTIFY_RIGHT;
    1672             :                     }
    1673             : 
    1674       11516 :                     bool bBreak = ( aVars.GetLineBreak() || aVars.GetHorJust() == SVX_HOR_JUSTIFY_BLOCK );
    1675             :                     // #i111387# #o11817313# disable automatic line breaks only for "General" number format
    1676       11516 :                     if (bBreak && bCellIsValue && (aVars.GetResultValueFormat() % SV_COUNTRY_LANGUAGE_OFFSET) == 0)
    1677           0 :                         bBreak = false;
    1678             : 
    1679       11516 :                     bool bRepeat = aVars.IsRepeat() && !bBreak;
    1680       11516 :                     bool bShrink = aVars.IsShrink() && !bBreak && !bRepeat;
    1681             : 
    1682             :                     nTotalMargin =
    1683       23032 :                         static_cast<long>(aVars.GetLeftTotal() * mnPPTX) +
    1684       23032 :                         static_cast<long>(aVars.GetMargin()->GetRightMargin() * mnPPTX);
    1685             : 
    1686       11516 :                     nNeededWidth = aVars.GetTextSize().Width() + nTotalMargin;
    1687             : 
    1688             :                     // GetOutputArea gives justfied rectangles
    1689             :                     GetOutputArea( nX, nArrY, nPosX, nPosY, nCellX, nCellY, nNeededWidth,
    1690       11516 :                                    *pPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
    1691       11516 :                                    bCellIsValue || bRepeat || bShrink, bBreak, false,
    1692       34548 :                                    aAreaParam );
    1693             : 
    1694       11516 :                     aVars.RepeatToFill( aAreaParam.mnColWidth - nTotalMargin );
    1695       11516 :                     if ( bShrink )
    1696             :                     {
    1697          44 :                         if ( aVars.GetOrient() != SVX_ORIENTATION_STANDARD )
    1698             :                         {
    1699             :                             // Only horizontal scaling is handled here.
    1700             :                             // DrawEdit is used to vertically scale 90 deg rotated text.
    1701          44 :                             bNeedEdit = sal_True;
    1702             :                         }
    1703           0 :                         else if ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip )     // horizontal
    1704             :                         {
    1705           0 :                             long nAvailable = aAreaParam.maAlignRect.GetWidth() - nTotalMargin;
    1706           0 :                             long nScaleSize = aVars.GetTextSize().Width();         // without margin
    1707             : 
    1708           0 :                             if ( nScaleSize > 0 )       // 0 if the text is empty (formulas, number formats)
    1709             :                             {
    1710           0 :                                 long nScale = ( nAvailable * 100 ) / nScaleSize;
    1711             : 
    1712           0 :                                 aVars.SetShrinkScale( nScale, nOldScript );
    1713           0 :                                 long nNewSize = aVars.GetTextSize().Width();
    1714             : 
    1715           0 :                                 sal_uInt16 nShrinkAgain = 0;
    1716           0 :                                 while ( nNewSize > nAvailable && nShrinkAgain < SC_SHRINKAGAIN_MAX )
    1717             :                                 {
    1718             :                                     // If the text is still too large, reduce the scale again by 10%, until it fits,
    1719             :                                     // at most 7 times (it's less than 50% of the calculated scale then).
    1720             : 
    1721           0 :                                     nScale = ( nScale * 9 ) / 10;
    1722           0 :                                     aVars.SetShrinkScale( nScale, nOldScript );
    1723           0 :                                     nNewSize = aVars.GetTextSize().Width();
    1724           0 :                                     ++nShrinkAgain;
    1725             :                                 }
    1726             :                                 // If even at half the size the font still isn't rendered smaller,
    1727             :                                 // fall back to normal clipping (showing ### for numbers).
    1728           0 :                                 if ( nNewSize <= nAvailable )
    1729           0 :                                     aAreaParam.mbLeftClip = aAreaParam.mbRightClip = false;
    1730             : 
    1731           0 :                                 pOldPattern = NULL;
    1732             :                             }
    1733             :                         }
    1734             :                     }
    1735             : 
    1736       11516 :                     if ( bRepeat && !aAreaParam.mbLeftClip && !aAreaParam.mbRightClip )
    1737             :                     {
    1738           0 :                         long nAvailable = aAreaParam.maAlignRect.GetWidth() - nTotalMargin;
    1739           0 :                         long nRepeatSize = aVars.GetTextSize().Width();         // without margin
    1740             :                         // When formatting for the printer, the text sizes don't always add up.
    1741             :                         // Round down (too few repetitions) rather than exceeding the cell size then:
    1742           0 :                         if ( pFmtDevice != mpRefDevice )
    1743           0 :                             ++nRepeatSize;
    1744           0 :                         if ( nRepeatSize > 0 )
    1745             :                         {
    1746           0 :                             long nRepeatCount = nAvailable / nRepeatSize;
    1747           0 :                             if ( nRepeatCount > 1 )
    1748             :                             {
    1749           0 :                                 String aCellStr = aVars.GetString();
    1750           0 :                                 String aRepeated = aCellStr;
    1751           0 :                                 for ( long nRepeat = 1; nRepeat < nRepeatCount; nRepeat++ )
    1752           0 :                                     aRepeated.Append( aCellStr );
    1753           0 :                                 aVars.SetAutoText( aRepeated );
    1754             :                             }
    1755             :                         }
    1756             :                     }
    1757             : 
    1758             :                     //  use edit engine if automatic line breaks are needed
    1759       11516 :                     if ( bBreak )
    1760             :                     {
    1761         154 :                         if ( aVars.GetOrient() == SVX_ORIENTATION_STANDARD )
    1762         118 :                             bNeedEdit = ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip );
    1763             :                         else
    1764             :                         {
    1765          72 :                             long nHeight = aVars.GetTextSize().Height() +
    1766          72 :                                             (long)(aVars.GetMargin()->GetTopMargin()*mnPPTY) +
    1767          72 :                                             (long)(aVars.GetMargin()->GetBottomMargin()*mnPPTY);
    1768          36 :                             bNeedEdit = ( nHeight > aAreaParam.maClipRect.GetHeight() );
    1769             :                         }
    1770             :                     }
    1771       11516 :                     if (!bNeedEdit)
    1772             :                     {
    1773             :                         bNeedEdit =
    1774       11446 :                             aVars.GetHorJust() == SVX_HOR_JUSTIFY_BLOCK &&
    1775       11446 :                             aVars.GetHorJustMethod() == SVX_JUSTIFY_METHOD_DISTRIBUTE;
    1776             :                     }
    1777             :                 }
    1778      187457 :                 if (bNeedEdit)
    1779             :                 {
    1780             :                     //  mark the cell in CellInfo to be drawn in DrawEdit:
    1781             :                     //  Cells to the left are marked directly, cells to the
    1782             :                     //  right are handled by the flag for nX2
    1783         550 :                     SCCOL nMarkX = ( nCellX <= nX2 ) ? nCellX : nX2;
    1784         550 :                     RowInfo* pMarkRowInfo = ( nCellY == nY ) ? pThisRowInfo : &pRowInfo[0];
    1785         550 :                     pMarkRowInfo->pCellInfo[nMarkX+1].bEditEngine = sal_True;
    1786         550 :                     bDoCell = false;    // don't draw here
    1787             :                 }
    1788      187457 :                 if ( bDoCell )
    1789             :                 {
    1790       11446 :                     if ( bCellIsValue && ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) )
    1791             :                     {
    1792         216 :                         if (mbShowFormulas)
    1793           0 :                             aVars.SetHashText();
    1794             :                         else
    1795             :                             // Adjust the decimals to fit the available column width.
    1796         216 :                             aVars.SetTextToWidthOrHash(aCell, aAreaParam.mnColWidth - nTotalMargin);
    1797             : 
    1798         432 :                         nNeededWidth = aVars.GetTextSize().Width() +
    1799         432 :                                     (long) ( aVars.GetLeftTotal() * mnPPTX ) +
    1800         432 :                                     (long) ( aVars.GetMargin()->GetRightMargin() * mnPPTX );
    1801         216 :                         if ( nNeededWidth <= aAreaParam.maClipRect.GetWidth() )
    1802         176 :                             aAreaParam.mbLeftClip = aAreaParam.mbRightClip = false;
    1803             : 
    1804             :                         //  If the "###" replacement doesn't fit into the cells, no clip marks
    1805             :                         //  are shown, as the "###" already denotes too little space.
    1806             :                         //  The rectangles from the first GetOutputArea call remain valid.
    1807             :                     }
    1808             : 
    1809       11446 :                     long nJustPosX = aAreaParam.maAlignRect.Left();     // "justified" - effect of alignment will be added
    1810       11446 :                     long nJustPosY = aAreaParam.maAlignRect.Top();
    1811       11446 :                     long nAvailWidth = aAreaParam.maAlignRect.GetWidth();
    1812       11446 :                     long nOutHeight = aAreaParam.maAlignRect.GetHeight();
    1813             : 
    1814       11446 :                     sal_Bool bOutside = ( aAreaParam.maClipRect.Right() < nScrX || aAreaParam.maClipRect.Left() >= nScrX + nScrW );
    1815       11446 :                     if ( aAreaParam.maClipRect.Left() < nScrX )
    1816             :                     {
    1817         196 :                         aAreaParam.maClipRect.Left() = nScrX;
    1818         196 :                         aAreaParam.mbLeftClip = sal_True;
    1819             :                     }
    1820       11446 :                     if ( aAreaParam.maClipRect.Right() > nScrX + nScrW )
    1821             :                     {
    1822         189 :                         aAreaParam.maClipRect.Right() = nScrX + nScrW;          //! minus one?
    1823         189 :                         aAreaParam.mbRightClip = sal_True;
    1824             :                     }
    1825             : 
    1826       11446 :                     sal_Bool bHClip = aAreaParam.mbLeftClip || aAreaParam.mbRightClip;
    1827       11446 :                     sal_Bool bVClip = false;
    1828             : 
    1829       11446 :                     if ( aAreaParam.maClipRect.Top() < nScrY )
    1830             :                     {
    1831           0 :                         aAreaParam.maClipRect.Top() = nScrY;
    1832           0 :                         bVClip = sal_True;
    1833             :                     }
    1834       11446 :                     if ( aAreaParam.maClipRect.Bottom() > nScrY + nScrH )
    1835             :                     {
    1836           0 :                         aAreaParam.maClipRect.Bottom() = nScrY + nScrH;         //! minus one?
    1837           0 :                         bVClip = sal_True;
    1838             :                     }
    1839             : 
    1840             :                     //
    1841             :                     //      horizontalen Platz testen
    1842             :                     //
    1843             : 
    1844       11446 :                     sal_Bool bRightAdjusted = false;        // to correct text width calculation later
    1845       11446 :                     sal_Bool bNeedEditEngine = false;
    1846       11446 :                     if ( !bNeedEditEngine && !bOutside )
    1847             :                     {
    1848       11076 :                         switch (eOutHorJust)
    1849             :                         {
    1850             :                             case SVX_HOR_JUSTIFY_LEFT:
    1851        5386 :                                 nJustPosX += (long) ( aVars.GetLeftTotal() * mnPPTX );
    1852        5386 :                                 break;
    1853             :                             case SVX_HOR_JUSTIFY_RIGHT:
    1854       11262 :                                 nJustPosX += nAvailWidth - aVars.GetTextSize().Width() -
    1855       11262 :                                             (long) ( aVars.GetRightTotal() * mnPPTX );
    1856        5631 :                                 bRightAdjusted = sal_True;
    1857        5631 :                                 break;
    1858             :                             case SVX_HOR_JUSTIFY_CENTER:
    1859         118 :                                 nJustPosX += ( nAvailWidth - aVars.GetTextSize().Width() +
    1860         118 :                                             (long) ( aVars.GetLeftTotal() * mnPPTX ) -
    1861         118 :                                             (long) ( aVars.GetMargin()->GetRightMargin() * mnPPTX ) ) / 2;
    1862          59 :                                 break;
    1863             :                             default:
    1864             :                             {
    1865             :                                 // added to avoid warnings
    1866             :                             }
    1867             :                         }
    1868             : 
    1869       11076 :                         long nTestClipHeight = aVars.GetTextSize().Height();
    1870       11076 :                         switch (aVars.GetVerJust())
    1871             :                         {
    1872             :                             case SVX_VER_JUSTIFY_TOP:
    1873             :                             case SVX_VER_JUSTIFY_BLOCK:
    1874             :                                 {
    1875         217 :                                     long nTop = (long)( aVars.GetMargin()->GetTopMargin() * mnPPTY );
    1876         217 :                                     nJustPosY += nTop;
    1877         217 :                                     nTestClipHeight += nTop;
    1878             :                                 }
    1879         217 :                                 break;
    1880             :                             case SVX_VER_JUSTIFY_BOTTOM:
    1881             :                                 {
    1882       10847 :                                     long nBot = (long)( aVars.GetMargin()->GetBottomMargin() * mnPPTY );
    1883       10847 :                                     nJustPosY += nOutHeight - aVars.GetTextSize().Height() - nBot;
    1884       10847 :                                     nTestClipHeight += nBot;
    1885             :                                 }
    1886       10847 :                                 break;
    1887             :                             case SVX_VER_JUSTIFY_CENTER:
    1888             :                                 {
    1889          12 :                                     long nTop = (long)( aVars.GetMargin()->GetTopMargin() * mnPPTY );
    1890          12 :                                     long nBot = (long)( aVars.GetMargin()->GetBottomMargin() * mnPPTY );
    1891          24 :                                     nJustPosY += ( nOutHeight + nTop -
    1892          24 :                                                     aVars.GetTextSize().Height() - nBot ) / 2;
    1893          12 :                                     nTestClipHeight += std::abs( nTop - nBot );
    1894             :                                 }
    1895          12 :                                 break;
    1896             :                             default:
    1897             :                             {
    1898             :                                 // added to avoid warnings
    1899             :                             }
    1900             :                         }
    1901             : 
    1902       11076 :                         if ( nTestClipHeight > nOutHeight )
    1903             :                         {
    1904             :                             //  kein vertikales Clipping beim Drucken von Zellen mit
    1905             :                             //  optimaler Hoehe, ausser bei Groesse in bedingter Formatierung
    1906         204 :                             if ( eType != OUTTYPE_PRINTER ||
    1907         117 :                                     ( mpDoc->GetRowFlags( nCellY, nTab ) & CR_MANUALSIZE ) ||
    1908          30 :                                     ( aVars.HasCondHeight() ) )
    1909          57 :                                 bVClip = sal_True;
    1910             :                         }
    1911             : 
    1912       11076 :                         if ( bHClip || bVClip )
    1913             :                         {
    1914             :                             //  nur die betroffene Dimension clippen,
    1915             :                             //  damit bei nicht-proportionalem Resize nicht alle
    1916             :                             //  rechtsbuendigen Zahlen abgeschnitten werden:
    1917             : 
    1918         285 :                             if (!bHClip)
    1919             :                             {
    1920          17 :                                 aAreaParam.maClipRect.Left() = nScrX;
    1921          17 :                                 aAreaParam.maClipRect.Right() = nScrX+nScrW;
    1922             :                             }
    1923         285 :                             if (!bVClip)
    1924             :                             {
    1925         228 :                                 aAreaParam.maClipRect.Top() = nScrY;
    1926         228 :                                 aAreaParam.maClipRect.Bottom() = nScrY+nScrH;
    1927             :                             }
    1928             : 
    1929             :                             //  aClipRect is not used after SetClipRegion/IntersectClipRegion,
    1930             :                             //  so it can be modified here
    1931         285 :                             if (bPixelToLogic)
    1932           0 :                                 aAreaParam.maClipRect = mpRefDevice->PixelToLogic( aAreaParam.maClipRect );
    1933             : 
    1934         285 :                             if (bMetaFile)
    1935             :                             {
    1936           0 :                                 mpDev->Push();
    1937           0 :                                 mpDev->IntersectClipRegion( aAreaParam.maClipRect );
    1938             :                             }
    1939             :                             else
    1940         285 :                                 mpDev->SetClipRegion( Region( aAreaParam.maClipRect ) );
    1941             :                         }
    1942             : 
    1943       11076 :                         Point aURLStart( nJustPosX, nJustPosY );    // copy before modifying for orientation
    1944             : 
    1945       11076 :                         switch (aVars.GetOrient())
    1946             :                         {
    1947             :                             case SVX_ORIENTATION_STANDARD:
    1948       11007 :                                 nJustPosY += aVars.GetAscent();
    1949       11007 :                                 break;
    1950             :                             case SVX_ORIENTATION_TOPBOTTOM:
    1951          69 :                                 nJustPosX += aVars.GetTextSize().Width() - aVars.GetAscent();
    1952          69 :                                 break;
    1953             :                             case SVX_ORIENTATION_BOTTOMTOP:
    1954           0 :                                 nJustPosY += aVars.GetTextSize().Height();
    1955           0 :                                 nJustPosX += aVars.GetAscent();
    1956           0 :                                 break;
    1957             :                             default:
    1958             :                             {
    1959             :                                 // added to avoid warnings
    1960             :                             }
    1961             :                         }
    1962             : 
    1963             :                         // When clipping, the visible part is now completely defined by the alignment,
    1964             :                         // there's no more special handling to show the right part of RTL text.
    1965             : 
    1966       11076 :                         Point aDrawTextPos( nJustPosX, nJustPosY );
    1967       11076 :                         if ( bPixelToLogic )
    1968             :                         {
    1969             :                             //  undo text width adjustment in pixels
    1970         356 :                             if (bRightAdjusted)
    1971         310 :                                 aDrawTextPos.X() += aVars.GetTextSize().Width();
    1972             : 
    1973         356 :                             aDrawTextPos = mpRefDevice->PixelToLogic( aDrawTextPos );
    1974             : 
    1975             :                             //  redo text width adjustment in logic units
    1976         356 :                             if (bRightAdjusted)
    1977         310 :                                 aDrawTextPos.X() -= aVars.GetOriginalWidth();
    1978             :                         }
    1979             : 
    1980             :                         //  in Metafiles immer DrawTextArray, damit die Positionen mit
    1981             :                         //  aufgezeichnet werden (fuer nicht-proportionales Resize):
    1982             : 
    1983       11076 :                         String aString = aVars.GetString();
    1984       11076 :                         if (bMetaFile || pFmtDevice != mpDev || aZoomX != aZoomY)
    1985             :                         {
    1986         387 :                             sal_Int32* pDX = new sal_Int32[aString.Len()];
    1987         387 :                             pFmtDevice->GetTextArray( aString, pDX );
    1988             : 
    1989         388 :                             if ( !mpRefDevice->GetConnectMetaFile() ||
    1990           1 :                                     mpRefDevice->GetOutDevType() == OUTDEV_PRINTER )
    1991             :                             {
    1992         386 :                                 double fMul = GetStretch();
    1993         386 :                                 xub_StrLen nLen = aString.Len();
    1994        1468 :                                 for (xub_StrLen i=0; i<nLen; i++)
    1995        1082 :                                     pDX[i] = (long)(pDX[i] / fMul + 0.5);
    1996             :                             }
    1997             : 
    1998         387 :                             mpDev->DrawTextArray( aDrawTextPos, aString, pDX );
    1999         387 :                             delete[] pDX;
    2000             :                         }
    2001             :                         else
    2002       10689 :                             mpDev->DrawText( aDrawTextPos, aString );
    2003             : 
    2004       11076 :                         if ( bHClip || bVClip )
    2005             :                         {
    2006         285 :                             if (bMetaFile)
    2007           0 :                                 mpDev->Pop();
    2008             :                             else
    2009         285 :                                 mpDev->SetClipRegion();
    2010             :                         }
    2011             : 
    2012             :                         // PDF: whole-cell hyperlink from formula?
    2013       11076 :                         bool bHasURL = pPDFData && aCell.meType == CELLTYPE_FORMULA && aCell.mpFormula->IsHyperLinkCell();
    2014       11076 :                         if ( bHasURL )
    2015             :                         {
    2016           0 :                             Rectangle aURLRect( aURLStart, aVars.GetTextSize() );
    2017           0 :                             lcl_DoHyperlinkResult(mpDev, aURLRect, aCell);
    2018       11076 :                         }
    2019             :                     }
    2020             :                 }
    2021      187457 :                 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
    2022      187457 :             }
    2023             :         }
    2024       18679 :         nPosY += pRowInfo[nArrY].nHeight;
    2025             :     }
    2026        1179 :     if ( bProgress )
    2027           2 :         ScProgress::DeleteInterpretProgress();
    2028        2358 :     mpDoc->EnableIdle(bWasIdleEnabled);
    2029        1179 : }
    2030             : 
    2031             : //  -------------------------------------------------------------------------------
    2032             : 
    2033         251 : ScFieldEditEngine* ScOutputData::CreateOutputEditEngine()
    2034             : {
    2035         251 :     ScFieldEditEngine* pEngine = new ScFieldEditEngine(mpDoc, mpDoc->GetEnginePool());
    2036         251 :     pEngine->SetUpdateMode( false );
    2037             :     // a RefDevice always has to be set, otherwise EditEngine would create a VirtualDevice
    2038         251 :     pEngine->SetRefDevice( pFmtDevice );
    2039         251 :     sal_uLong nCtrl = pEngine->GetControlWord();
    2040         251 :     if ( bShowSpellErrors )
    2041         248 :         nCtrl |= EE_CNTRL_ONLINESPELLING;
    2042         251 :     if ( eType == OUTTYPE_PRINTER )
    2043           3 :         nCtrl &= ~EE_CNTRL_MARKFIELDS;
    2044         251 :     if ( eType == OUTTYPE_WINDOW && mpRefDevice == pFmtDevice )
    2045         248 :         nCtrl &= ~EE_CNTRL_FORMAT100;       // use the actual MapMode
    2046         251 :     pEngine->SetControlWord( nCtrl );
    2047         251 :     mpDoc->ApplyAsianEditSettings( *pEngine );
    2048         251 :     pEngine->EnableAutoColor( mbUseStyleColor );
    2049         251 :     pEngine->SetDefaultHorizontalTextDirection( (EEHorizontalTextDirection)mpDoc->GetEditTextDirection( nTab ) );
    2050         251 :     return pEngine;
    2051             : }
    2052             : 
    2053        1329 : static void lcl_ClearEdit( EditEngine& rEngine )       // Text und Attribute
    2054             : {
    2055        1329 :     rEngine.SetUpdateMode( false );
    2056             : 
    2057        1329 :     rEngine.SetText(EMPTY_STRING);
    2058             :     //  keine Para-Attribute uebrigbehalten...
    2059        1329 :     const SfxItemSet& rPara = rEngine.GetParaAttribs(0);
    2060        1329 :     if (rPara.Count())
    2061             :         rEngine.SetParaAttribs( 0,
    2062         435 :                     SfxItemSet( *rPara.GetPool(), rPara.GetRanges() ) );
    2063        1329 : }
    2064             : 
    2065         550 : static bool lcl_SafeIsValue( ScRefCellValue& rCell )
    2066             : {
    2067         550 :     switch (rCell.meType)
    2068             :     {
    2069             :         case CELLTYPE_VALUE:
    2070         294 :             return true;
    2071             :         case CELLTYPE_FORMULA:
    2072             :         {
    2073           0 :             ScFormulaCell* pFCell = rCell.mpFormula;
    2074           0 :             if (pFCell->IsRunning() || pFCell->IsValue())
    2075           0 :                 return true;
    2076             :         }
    2077           0 :         break;
    2078             :         default:
    2079             :         {
    2080             :             // added to avoid warnings
    2081             :         }
    2082             :     }
    2083         256 :     return false;
    2084             : }
    2085             : 
    2086           0 : static void lcl_ScaleFonts( EditEngine& rEngine, long nPercent )
    2087             : {
    2088           0 :     sal_Bool bUpdateMode = rEngine.GetUpdateMode();
    2089           0 :     if ( bUpdateMode )
    2090           0 :         rEngine.SetUpdateMode( false );
    2091             : 
    2092           0 :     sal_Int32 nParCount = rEngine.GetParagraphCount();
    2093           0 :     for (sal_Int32 nPar=0; nPar<nParCount; nPar++)
    2094             :     {
    2095           0 :         std::vector<sal_uInt16> aPortions;
    2096           0 :         rEngine.GetPortions( nPar, aPortions );
    2097             : 
    2098           0 :         sal_uInt16 nStart = 0;
    2099           0 :         for ( std::vector<sal_uInt16>::const_iterator it(aPortions.begin()); it != aPortions.end(); ++it )
    2100             :         {
    2101           0 :             sal_uInt16 nEnd = *it;
    2102           0 :             ESelection aSel( nPar, nStart, nPar, nEnd );
    2103           0 :             SfxItemSet aAttribs = rEngine.GetAttribs( aSel );
    2104             : 
    2105           0 :             long nWestern = static_cast<const SvxFontHeightItem&>(aAttribs.Get(EE_CHAR_FONTHEIGHT)).GetHeight();
    2106           0 :             long nCJK = static_cast<const SvxFontHeightItem&>(aAttribs.Get(EE_CHAR_FONTHEIGHT_CJK)).GetHeight();
    2107           0 :             long nCTL = static_cast<const SvxFontHeightItem&>(aAttribs.Get(EE_CHAR_FONTHEIGHT_CTL)).GetHeight();
    2108             : 
    2109           0 :             nWestern = ( nWestern * nPercent ) / 100;
    2110           0 :             nCJK     = ( nCJK     * nPercent ) / 100;
    2111           0 :             nCTL     = ( nCTL     * nPercent ) / 100;
    2112             : 
    2113           0 :             aAttribs.Put( SvxFontHeightItem( nWestern, 100, EE_CHAR_FONTHEIGHT ) );
    2114           0 :             aAttribs.Put( SvxFontHeightItem( nCJK, 100, EE_CHAR_FONTHEIGHT_CJK ) );
    2115           0 :             aAttribs.Put( SvxFontHeightItem( nCTL, 100, EE_CHAR_FONTHEIGHT_CTL ) );
    2116             : 
    2117           0 :             rEngine.QuickSetAttribs( aAttribs, aSel );      //! remove paragraph attributes from aAttribs?
    2118             : 
    2119           0 :             nStart = nEnd;
    2120           0 :         }
    2121           0 :     }
    2122             : 
    2123           0 :     if ( bUpdateMode )
    2124           0 :         rEngine.SetUpdateMode( sal_True );
    2125           0 : }
    2126             : 
    2127           0 : static long lcl_GetEditSize( EditEngine& rEngine, sal_Bool bWidth, sal_Bool bSwap, long nAttrRotate )
    2128             : {
    2129           0 :     if ( bSwap )
    2130           0 :         bWidth = !bWidth;
    2131             : 
    2132           0 :     if ( nAttrRotate )
    2133             :     {
    2134           0 :         long nRealWidth  = (long) rEngine.CalcTextWidth();
    2135           0 :         long nRealHeight = rEngine.GetTextHeight();
    2136             : 
    2137             :         // assuming standard mode, otherwise width isn't used
    2138             : 
    2139           0 :         double nRealOrient = nAttrRotate * F_PI18000;   // 1/100th degrees
    2140           0 :         double nAbsCos = fabs( cos( nRealOrient ) );
    2141           0 :         double nAbsSin = fabs( sin( nRealOrient ) );
    2142           0 :         if ( bWidth )
    2143           0 :             return (long) ( nRealWidth * nAbsCos + nRealHeight * nAbsSin );
    2144             :         else
    2145           0 :             return (long) ( nRealHeight * nAbsCos + nRealWidth * nAbsSin );
    2146             :     }
    2147           0 :     else if ( bWidth )
    2148           0 :         return (long) rEngine.CalcTextWidth();
    2149             :     else
    2150           0 :         return rEngine.GetTextHeight();
    2151             : }
    2152             : 
    2153             : 
    2154         156 : void ScOutputData::ShrinkEditEngine( EditEngine& rEngine, const Rectangle& rAlignRect,
    2155             :             long nLeftM, long nTopM, long nRightM, long nBottomM,
    2156             :             sal_Bool bWidth, sal_uInt16 nOrient, long nAttrRotate, sal_Bool bPixelToLogic,
    2157             :             long& rEngineWidth, long& rEngineHeight, long& rNeededPixel, bool& rLeftClip, bool& rRightClip )
    2158             : {
    2159         156 :     if ( !bWidth )
    2160             :     {
    2161             :         // vertical
    2162             : 
    2163             :         long nScaleSize = bPixelToLogic ?
    2164          78 :             mpRefDevice->LogicToPixel(Size(0,rEngineHeight)).Height() : rEngineHeight;
    2165             : 
    2166             :         // Don't scale if it fits already.
    2167             :         // Allowing to extend into the margin, to avoid scaling at optimal height.
    2168          78 :         if ( nScaleSize <= rAlignRect.GetHeight() )
    2169          78 :             return;
    2170             : 
    2171           0 :         sal_Bool bSwap = ( nOrient == SVX_ORIENTATION_TOPBOTTOM || nOrient == SVX_ORIENTATION_BOTTOMTOP );
    2172           0 :         long nAvailable = rAlignRect.GetHeight() - nTopM - nBottomM;
    2173           0 :         long nScale = ( nAvailable * 100 ) / nScaleSize;
    2174             : 
    2175           0 :         lcl_ScaleFonts( rEngine, nScale );
    2176           0 :         rEngineHeight = lcl_GetEditSize( rEngine, false, bSwap, nAttrRotate );
    2177             :         long nNewSize = bPixelToLogic ?
    2178           0 :             mpRefDevice->LogicToPixel(Size(0,rEngineHeight)).Height() : rEngineHeight;
    2179             : 
    2180           0 :         sal_uInt16 nShrinkAgain = 0;
    2181           0 :         while ( nNewSize > nAvailable && nShrinkAgain < SC_SHRINKAGAIN_MAX )
    2182             :         {
    2183             :             // further reduce, like in DrawStrings
    2184           0 :             lcl_ScaleFonts( rEngine, 90 );     // reduce by 10%
    2185           0 :             rEngineHeight = lcl_GetEditSize( rEngine, false, bSwap, nAttrRotate );
    2186             :             nNewSize = bPixelToLogic ?
    2187           0 :                 mpRefDevice->LogicToPixel(Size(0,rEngineHeight)).Height() : rEngineHeight;
    2188           0 :             ++nShrinkAgain;
    2189             :         }
    2190             : 
    2191             :         // sizes for further processing (alignment etc):
    2192           0 :         rEngineWidth = lcl_GetEditSize( rEngine, sal_True, bSwap, nAttrRotate );
    2193             :         long nPixelWidth = bPixelToLogic ?
    2194           0 :             mpRefDevice->LogicToPixel(Size(rEngineWidth,0)).Width() : rEngineWidth;
    2195           0 :         rNeededPixel = nPixelWidth + nLeftM + nRightM;
    2196             :     }
    2197          78 :     else if ( rLeftClip || rRightClip )
    2198             :     {
    2199             :         // horizontal
    2200             : 
    2201          78 :         long nAvailable = rAlignRect.GetWidth() - nLeftM - nRightM;
    2202          78 :         long nScaleSize = rNeededPixel - nLeftM - nRightM;      // without margin
    2203             : 
    2204          78 :         if ( nScaleSize <= nAvailable )
    2205          78 :             return;
    2206             : 
    2207           0 :         long nScale = ( nAvailable * 100 ) / nScaleSize;
    2208             : 
    2209           0 :         lcl_ScaleFonts( rEngine, nScale );
    2210           0 :         rEngineWidth = lcl_GetEditSize( rEngine, sal_True, false, nAttrRotate );
    2211             :         long nNewSize = bPixelToLogic ?
    2212           0 :             mpRefDevice->LogicToPixel(Size(rEngineWidth,0)).Width() : rEngineWidth;
    2213             : 
    2214           0 :         sal_uInt16 nShrinkAgain = 0;
    2215           0 :         while ( nNewSize > nAvailable && nShrinkAgain < SC_SHRINKAGAIN_MAX )
    2216             :         {
    2217             :             // further reduce, like in DrawStrings
    2218           0 :             lcl_ScaleFonts( rEngine, 90 );     // reduce by 10%
    2219           0 :             rEngineWidth = lcl_GetEditSize( rEngine, sal_True, false, nAttrRotate );
    2220             :             nNewSize = bPixelToLogic ?
    2221           0 :                 mpRefDevice->LogicToPixel(Size(rEngineWidth,0)).Width() : rEngineWidth;
    2222           0 :             ++nShrinkAgain;
    2223             :         }
    2224           0 :         if ( nNewSize <= nAvailable )
    2225           0 :             rLeftClip = rRightClip = false;
    2226             : 
    2227             :         // sizes for further processing (alignment etc):
    2228           0 :         rNeededPixel = nNewSize + nLeftM + nRightM;
    2229           0 :         rEngineHeight = lcl_GetEditSize( rEngine, false, false, nAttrRotate );
    2230             :     }
    2231             : }
    2232             : 
    2233         550 : ScOutputData::DrawEditParam::DrawEditParam(const ScPatternAttr* pPattern, const SfxItemSet* pCondSet, bool bCellIsValue) :
    2234         550 :     meHorJust( lcl_GetValue<SvxHorJustifyItem, SvxCellHorJustify>(*pPattern, ATTR_HOR_JUSTIFY, pCondSet) ),
    2235         550 :     meVerJust( lcl_GetValue<SvxVerJustifyItem, SvxCellVerJustify>(*pPattern, ATTR_VER_JUSTIFY, pCondSet) ),
    2236         550 :     meHorJustMethod( lcl_GetValue<SvxJustifyMethodItem, SvxCellJustifyMethod>(*pPattern, ATTR_HOR_JUSTIFY_METHOD, pCondSet) ),
    2237         550 :     meVerJustMethod( lcl_GetValue<SvxJustifyMethodItem, SvxCellJustifyMethod>(*pPattern, ATTR_VER_JUSTIFY_METHOD, pCondSet) ),
    2238         550 :     meOrient( pPattern->GetCellOrientation(pCondSet) ),
    2239             :     mnArrY(0),
    2240             :     mnX(0), mnY(0), mnCellX(0), mnCellY(0),
    2241             :     mnPosX(0), mnPosY(0), mnInitPosX(0),
    2242         550 :     mbBreak( (meHorJust == SVX_HOR_JUSTIFY_BLOCK) || lcl_GetBoolValue(*pPattern, ATTR_LINEBREAK, pCondSet) ),
    2243             :     mbCellIsValue(bCellIsValue),
    2244             :     mbAsianVertical(false),
    2245             :     mbPixelToLogic(false),
    2246             :     mbHyphenatorSet(false),
    2247             :     mbRTL(false),
    2248             :     mpEngine(NULL),
    2249             :     mpPattern(pPattern),
    2250             :     mpCondSet(pCondSet),
    2251             :     mpPreviewFontSet(NULL),
    2252             :     mpOldPattern(NULL),
    2253             :     mpOldCondSet(NULL),
    2254        3300 :     mpThisRowInfo(NULL)
    2255         550 : {}
    2256             : 
    2257         172 : bool ScOutputData::DrawEditParam::readCellContent(
    2258             :     ScDocument* pDoc, bool bShowNullValues, bool bShowFormulas, bool bSyntaxMode, bool bUseStyleColor, bool bForceAutoColor, bool& rWrapFields)
    2259             : {
    2260         172 :     if (maCell.meType == CELLTYPE_EDIT)
    2261             :     {
    2262         102 :         const EditTextObject* pData = maCell.mpEditText;
    2263         102 :         if (pData)
    2264             :         {
    2265         102 :             mpEngine->SetText(*pData);
    2266             : 
    2267         102 :             if ( mbBreak && !mbAsianVertical && pData->HasField() )
    2268             :             {
    2269             :                 //  Fields aren't wrapped, so clipping is enabled to prevent
    2270             :                 //  a field from being drawn beyond the cell size
    2271             : 
    2272           0 :                 rWrapFields = true;
    2273             :             }
    2274             :         }
    2275             :         else
    2276             :         {
    2277             :             OSL_FAIL("pData == 0");
    2278           0 :             return false;
    2279             :         }
    2280             :     }
    2281             :     else
    2282             :     {
    2283             :         sal_uLong nFormat = mpPattern->GetNumberFormat(
    2284          70 :                                     pDoc->GetFormatTable(), mpCondSet );
    2285          70 :         OUString aString;
    2286             :         Color* pColor;
    2287             :         ScCellFormat::GetString( maCell,
    2288             :                                  nFormat,aString, &pColor,
    2289          70 :                                  *pDoc->GetFormatTable(),
    2290             :                                  bShowNullValues,
    2291             :                                  bShowFormulas,
    2292         140 :                                  ftCheck );
    2293             : 
    2294          70 :         mpEngine->SetText(aString);
    2295          70 :         if ( pColor && !bSyntaxMode && !( bUseStyleColor && bForceAutoColor ) )
    2296           0 :             lcl_SetEditColor( *mpEngine, *pColor );
    2297             :     }
    2298         172 :     return true;
    2299             : }
    2300             : 
    2301         172 : void ScOutputData::DrawEditParam::setPatternToEngine(bool bUseStyleColor)
    2302             : {
    2303             :     // syntax highlighting mode is ignored here
    2304             :     // StringDiffer doesn't look at hyphenate, language items
    2305             : 
    2306         172 :     if (mpPattern == mpOldPattern && mpCondSet == mpOldCondSet && !mpPreviewFontSet)
    2307         229 :         return;
    2308             : 
    2309         115 :     sal_Int32 nConfBackColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor;
    2310         230 :     bool bCellContrast = bUseStyleColor &&
    2311         230 :             Application::GetSettings().GetStyleSettings().GetHighContrastMode();
    2312             : 
    2313         115 :     SfxItemSet* pSet = new SfxItemSet( mpEngine->GetEmptyItemSet() );
    2314         115 :     mpPattern->FillEditItemSet( pSet, mpCondSet );
    2315         115 :     if ( mpPreviewFontSet )
    2316             :     {
    2317             :         const SfxPoolItem* pItem;
    2318           7 :         if ( mpPreviewFontSet->GetItemState( ATTR_FONT, true, &pItem ) == SFX_ITEM_SET )
    2319             :         {
    2320           7 :             SvxFontItem aFontItem(EE_CHAR_FONTINFO);
    2321           7 :             aFontItem = (const SvxFontItem&)*pItem;
    2322           7 :             pSet->Put( aFontItem );
    2323             :         }
    2324           7 :         if ( mpPreviewFontSet->GetItemState( ATTR_CJK_FONT, true, &pItem ) == SFX_ITEM_SET )
    2325             :         {
    2326           0 :             SvxFontItem aCjkFontItem(EE_CHAR_FONTINFO_CJK);
    2327           0 :             aCjkFontItem = (const SvxFontItem&)*pItem;
    2328           0 :             pSet->Put( aCjkFontItem );
    2329             :         }
    2330           7 :         if ( mpPreviewFontSet->GetItemState( ATTR_CTL_FONT, true, &pItem ) == SFX_ITEM_SET )
    2331             :         {
    2332           0 :             SvxFontItem aCtlFontItem(EE_CHAR_FONTINFO_CTL);
    2333           0 :             aCtlFontItem = (const SvxFontItem&)*pItem;
    2334           0 :             pSet->Put( aCtlFontItem );
    2335             :         }
    2336             :     }
    2337         115 :     mpEngine->SetDefaults( pSet );
    2338         115 :     mpOldPattern = mpPattern;
    2339         115 :     mpOldCondSet = mpCondSet;
    2340             : 
    2341         115 :     sal_uLong nControl = mpEngine->GetControlWord();
    2342         115 :     if (meOrient == SVX_ORIENTATION_STACKED)
    2343           0 :         nControl |= EE_CNTRL_ONECHARPERLINE;
    2344             :     else
    2345         115 :         nControl &= ~EE_CNTRL_ONECHARPERLINE;
    2346         115 :     mpEngine->SetControlWord( nControl );
    2347             : 
    2348         115 :     if ( !mbHyphenatorSet && ((const SfxBoolItem&)pSet->Get(EE_PARA_HYPHENATE)).GetValue() )
    2349             :     {
    2350             :         //  set hyphenator the first time it is needed
    2351           3 :         com::sun::star::uno::Reference<com::sun::star::linguistic2::XHyphenator> xXHyphenator( LinguMgr::GetHyphenator() );
    2352           3 :         mpEngine->SetHyphenator( xXHyphenator );
    2353           3 :         mbHyphenatorSet = true;
    2354             :     }
    2355             : 
    2356         115 :     Color aBackCol = ((const SvxBrushItem&)mpPattern->GetItem( ATTR_BACKGROUND, mpCondSet )).GetColor();
    2357         115 :     if ( bUseStyleColor && ( aBackCol.GetTransparency() > 0 || bCellContrast ) )
    2358         104 :         aBackCol.SetColor( nConfBackColor );
    2359         115 :     mpEngine->SetBackgroundColor( aBackCol );
    2360             : }
    2361             : 
    2362         245 : void ScOutputData::DrawEditParam::calcMargins(long& rTopM, long& rLeftM, long& rBottomM, long& rRightM, double nPPTX, double nPPTY) const
    2363             : {
    2364             :     const SvxMarginItem& rMargin =
    2365         245 :         static_cast<const SvxMarginItem&>(mpPattern->GetItem(ATTR_MARGIN, mpCondSet));
    2366             : 
    2367         245 :     sal_uInt16 nIndent = 0;
    2368         245 :     if (meHorJust == SVX_HOR_JUSTIFY_LEFT || meHorJust == SVX_HOR_JUSTIFY_RIGHT)
    2369         102 :         nIndent = lcl_GetValue<SfxUInt16Item, sal_uInt16>(*mpPattern, ATTR_INDENT, mpCondSet);
    2370             : 
    2371         245 :     rLeftM   = static_cast<long>(((rMargin.GetLeftMargin() + nIndent) * nPPTX));
    2372         245 :     rTopM    = static_cast<long>((rMargin.GetTopMargin() * nPPTY));
    2373         245 :     rRightM  = static_cast<long>((rMargin.GetRightMargin() * nPPTX));
    2374         245 :     rBottomM = static_cast<long>((rMargin.GetBottomMargin() * nPPTY));
    2375         245 :     if(meHorJust == SVX_HOR_JUSTIFY_RIGHT)
    2376             :     {
    2377           0 :         rLeftM   = static_cast<long>((rMargin.GetLeftMargin()  * nPPTX));
    2378           0 :         rRightM  = static_cast<long>(((rMargin.GetRightMargin() + nIndent) * nPPTX));
    2379             :     }
    2380         245 : }
    2381             : 
    2382          73 : void ScOutputData::DrawEditParam::calcPaperSize(
    2383             :     Size& rPaperSize, const Rectangle& rAlignRect, double nPPTX, double nPPTY) const
    2384             : {
    2385             :     long nTopM, nLeftM, nBottomM, nRightM;
    2386          73 :     calcMargins(nTopM, nLeftM, nBottomM, nRightM, nPPTX, nPPTY);
    2387             : 
    2388          73 :     if (isVerticallyOriented())
    2389             :     {
    2390          69 :         rPaperSize.Width() = rAlignRect.GetHeight() - nTopM - nBottomM;
    2391          69 :         rPaperSize.Height() = rAlignRect.GetWidth() - nLeftM - nRightM;
    2392             :     }
    2393             :     else
    2394             :     {
    2395           4 :         rPaperSize.Width() = rAlignRect.GetWidth() - nLeftM - nRightM;
    2396           4 :         rPaperSize.Height() = rAlignRect.GetHeight() - nTopM - nBottomM;
    2397             :     }
    2398             : 
    2399          73 :     if (mbAsianVertical)
    2400             :     {
    2401           0 :         rPaperSize.Height() = rAlignRect.GetHeight() - nTopM - nBottomM;
    2402             :         // Subtract some extra value from the height or else the text would go
    2403             :         // outside the cell area.  The value of 5 is arbitrary, and is based
    2404             :         // entirely on heuristics.
    2405           0 :         rPaperSize.Height() -= 5;
    2406             :     }
    2407          73 : }
    2408             : 
    2409         172 : void ScOutputData::DrawEditParam::getEngineSize(ScFieldEditEngine* pEngine, long& rWidth, long& rHeight) const
    2410             : {
    2411         172 :     long nEngineWidth = 0;
    2412         172 :     if (!mbBreak || meOrient == SVX_ORIENTATION_STACKED || mbAsianVertical)
    2413          99 :         nEngineWidth = static_cast<long>(pEngine->CalcTextWidth());
    2414             : 
    2415         172 :     long nEngineHeight = pEngine->GetTextHeight();
    2416             : 
    2417         172 :     if (isVerticallyOriented())
    2418             :     {
    2419          69 :         long nTemp = nEngineWidth;
    2420          69 :         nEngineWidth = nEngineHeight;
    2421          69 :         nEngineHeight = nTemp;
    2422             :     }
    2423             : 
    2424         172 :     if (meOrient == SVX_ORIENTATION_STACKED)
    2425           0 :         nEngineWidth = nEngineWidth * 11 / 10;
    2426             : 
    2427         172 :     rWidth = nEngineWidth;
    2428         172 :     rHeight = nEngineHeight;
    2429         172 : }
    2430             : 
    2431          69 : bool ScOutputData::DrawEditParam::hasLineBreak() const
    2432             : {
    2433          69 :     return (mbBreak || (meOrient == SVX_ORIENTATION_STACKED) || mbAsianVertical);
    2434             : }
    2435             : 
    2436           0 : bool ScOutputData::DrawEditParam::isHyperlinkCell() const
    2437             : {
    2438           0 :     if (maCell.meType != CELLTYPE_FORMULA)
    2439           0 :         return false;
    2440             : 
    2441           0 :     return maCell.mpFormula->IsHyperLinkCell();
    2442             : }
    2443             : 
    2444         417 : bool ScOutputData::DrawEditParam::isVerticallyOriented() const
    2445             : {
    2446         417 :     return (meOrient == SVX_ORIENTATION_TOPBOTTOM || meOrient == SVX_ORIENTATION_BOTTOMTOP);
    2447             : }
    2448             : 
    2449          69 : void ScOutputData::DrawEditParam::calcStartPosForVertical(
    2450             :     Point& rLogicStart, long nCellWidth, long nEngineWidth, long nTopM, OutputDevice* pRefDevice)
    2451             : {
    2452             :     OSL_ENSURE(isVerticallyOriented(), "Use this only for vertically oriented cell!");
    2453             : 
    2454          69 :     if (mbPixelToLogic)
    2455          69 :         rLogicStart = pRefDevice->PixelToLogic(rLogicStart);
    2456             : 
    2457          69 :     if (mbBreak)
    2458             :     {
    2459             :         // vertical adjustment is within the EditEngine
    2460          69 :         if (mbPixelToLogic)
    2461          69 :             rLogicStart.Y() += pRefDevice->PixelToLogic(Size(0,nTopM)).Height();
    2462             :         else
    2463           0 :             rLogicStart.Y() += nTopM;
    2464             : 
    2465          69 :         switch (meHorJust)
    2466             :         {
    2467             :             case SVX_HOR_JUSTIFY_CENTER:
    2468           7 :                 rLogicStart.X() += (nCellWidth - nEngineWidth) / 2;
    2469           7 :             break;
    2470             :             case SVX_HOR_JUSTIFY_RIGHT:
    2471           0 :                 rLogicStart.X() += nCellWidth - nEngineWidth;
    2472           0 :             break;
    2473             :             default:
    2474             :                 ; // do nothing
    2475             :         }
    2476             :     }
    2477          69 : }
    2478             : 
    2479         172 : void ScOutputData::DrawEditParam::setAlignmentToEngine()
    2480             : {
    2481         172 :     if (isVerticallyOriented() || mbAsianVertical)
    2482             :     {
    2483          69 :         SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT;
    2484          69 :         switch (meVerJust)
    2485             :         {
    2486             :             case SVX_VER_JUSTIFY_TOP:
    2487           0 :                 eSvxAdjust = (meOrient == SVX_ORIENTATION_TOPBOTTOM || mbAsianVertical) ?
    2488           0 :                             SVX_ADJUST_LEFT : SVX_ADJUST_RIGHT;
    2489           0 :                 break;
    2490             :             case SVX_VER_JUSTIFY_CENTER:
    2491           0 :                 eSvxAdjust = SVX_ADJUST_CENTER;
    2492           0 :                 break;
    2493             :             case SVX_VER_JUSTIFY_BOTTOM:
    2494             :             case SVX_VER_JUSTIFY_STANDARD:
    2495          69 :                 eSvxAdjust = (meOrient == SVX_ORIENTATION_TOPBOTTOM || mbAsianVertical) ?
    2496         138 :                             SVX_ADJUST_RIGHT : SVX_ADJUST_LEFT;
    2497          69 :                 break;
    2498             :             case SVX_VER_JUSTIFY_BLOCK:
    2499           0 :                 eSvxAdjust = SVX_ADJUST_BLOCK;
    2500           0 :                 break;
    2501             :         }
    2502             : 
    2503          69 :         mpEngine->SetDefaultItem( SvxAdjustItem(eSvxAdjust, EE_PARA_JUST) );
    2504          69 :         mpEngine->SetDefaultItem( SvxJustifyMethodItem(meVerJustMethod, EE_PARA_JUST_METHOD) );
    2505             : 
    2506          69 :         if (meHorJust == SVX_HOR_JUSTIFY_BLOCK)
    2507          12 :             mpEngine->SetDefaultItem( SvxVerJustifyItem(SVX_VER_JUSTIFY_BLOCK, EE_PARA_VER_JUST) );
    2508             :     }
    2509             :     else
    2510             :     {
    2511             :         //  horizontal alignment now may depend on cell content
    2512             :         //  (for values with number formats with mixed script types)
    2513             :         //  -> always set adjustment
    2514             : 
    2515         103 :         SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT;
    2516         103 :         if (meOrient == SVX_ORIENTATION_STACKED)
    2517           0 :             eSvxAdjust = SVX_ADJUST_CENTER;
    2518         103 :         else if (mbBreak)
    2519             :         {
    2520           4 :             if (meOrient == SVX_ORIENTATION_STANDARD)
    2521           4 :                 switch (meHorJust)
    2522             :                 {
    2523             :                     case SVX_HOR_JUSTIFY_STANDARD:
    2524           4 :                         eSvxAdjust = mbCellIsValue ? SVX_ADJUST_RIGHT : SVX_ADJUST_LEFT;
    2525           4 :                         break;
    2526             :                     case SVX_HOR_JUSTIFY_LEFT:
    2527             :                     case SVX_HOR_JUSTIFY_REPEAT:            // nicht implementiert
    2528           0 :                         eSvxAdjust = SVX_ADJUST_LEFT;
    2529           0 :                         break;
    2530             :                     case SVX_HOR_JUSTIFY_RIGHT:
    2531           0 :                         eSvxAdjust = SVX_ADJUST_RIGHT;
    2532           0 :                         break;
    2533             :                     case SVX_HOR_JUSTIFY_CENTER:
    2534           0 :                         eSvxAdjust = SVX_ADJUST_CENTER;
    2535           0 :                         break;
    2536             :                     case SVX_HOR_JUSTIFY_BLOCK:
    2537           0 :                         eSvxAdjust = SVX_ADJUST_BLOCK;
    2538           0 :                         break;
    2539             :                 }
    2540             :             else
    2541           0 :                 switch (meVerJust)
    2542             :                 {
    2543             :                     case SVX_VER_JUSTIFY_TOP:
    2544           0 :                         eSvxAdjust = SVX_ADJUST_RIGHT;
    2545           0 :                         break;
    2546             :                     case SVX_VER_JUSTIFY_CENTER:
    2547           0 :                         eSvxAdjust = SVX_ADJUST_CENTER;
    2548           0 :                         break;
    2549             :                     case SVX_VER_JUSTIFY_BOTTOM:
    2550             :                     case SVX_VER_JUSTIFY_STANDARD:
    2551           0 :                         eSvxAdjust = SVX_ADJUST_LEFT;
    2552           0 :                         break;
    2553             :                     case SVX_VER_JUSTIFY_BLOCK:
    2554           0 :                         eSvxAdjust = SVX_ADJUST_BLOCK;
    2555           0 :                         break;
    2556             :                 }
    2557             :         }
    2558             : 
    2559         103 :         mpEngine->SetDefaultItem( SvxAdjustItem(eSvxAdjust, EE_PARA_JUST) );
    2560             : 
    2561         103 :         if (mbAsianVertical)
    2562             :         {
    2563           0 :             mpEngine->SetDefaultItem( SvxJustifyMethodItem(meVerJustMethod, EE_PARA_JUST_METHOD) );
    2564           0 :             if (meHorJust == SVX_HOR_JUSTIFY_BLOCK)
    2565           0 :                 mpEngine->SetDefaultItem( SvxVerJustifyItem(SVX_VER_JUSTIFY_BLOCK, EE_PARA_VER_JUST) );
    2566             :         }
    2567             :         else
    2568             :         {
    2569         103 :             mpEngine->SetDefaultItem( SvxJustifyMethodItem(meHorJustMethod, EE_PARA_JUST_METHOD) );
    2570         103 :             if (meVerJust == SVX_VER_JUSTIFY_BLOCK)
    2571           0 :                 mpEngine->SetDefaultItem( SvxVerJustifyItem(SVX_VER_JUSTIFY_BLOCK, EE_PARA_VER_JUST) );
    2572             :         }
    2573             :     }
    2574             : 
    2575         172 :     mpEngine->SetVertical(mbAsianVertical);
    2576         172 :     if (maCell.meType == CELLTYPE_EDIT)
    2577             :     {
    2578             :         // We need to synchronize the vertical mode in the EditTextObject
    2579             :         // instance too.  No idea why we keep this state in two separate
    2580             :         // instances.
    2581         102 :         const EditTextObject* pData = maCell.mpEditText;
    2582         102 :         if (pData)
    2583         102 :             const_cast<EditTextObject*>(pData)->SetVertical(mbAsianVertical);
    2584             :     }
    2585         172 : }
    2586             : 
    2587          99 : bool ScOutputData::DrawEditParam::adjustHorAlignment(ScFieldEditEngine* pEngine)
    2588             : {
    2589         198 :     if (meHorJust == SVX_HOR_JUSTIFY_RIGHT || meHorJust == SVX_HOR_JUSTIFY_CENTER ||
    2590         196 :         (meHorJust == SVX_HOR_JUSTIFY_STANDARD && mbCellIsValue))
    2591             :     {
    2592           0 :         SvxAdjust eEditAdjust = (meHorJust == SVX_HOR_JUSTIFY_CENTER) ?
    2593           0 :             SVX_ADJUST_CENTER : SVX_ADJUST_RIGHT;
    2594             : 
    2595           0 :         pEngine->SetUpdateMode(false);
    2596           0 :         pEngine->SetDefaultItem( SvxAdjustItem(eEditAdjust, EE_PARA_JUST) );
    2597           0 :         pEngine->SetUpdateMode(true);
    2598           0 :         return true;
    2599             :     }
    2600          99 :     return false;
    2601             : }
    2602             : 
    2603         172 : void ScOutputData::DrawEditParam::adjustForRTL()
    2604             : {
    2605         172 :     if (!mpEngine->IsRightToLeft(0))
    2606             :         // No RTL mode.
    2607         344 :         return;
    2608             : 
    2609             :     //  For right-to-left, EditEngine always calculates its lines
    2610             :     //  beginning from the right edge, but EditLine::nStartPosX is
    2611             :     //  of sal_uInt16 type, so the PaperSize must be limited to USHRT_MAX.
    2612           0 :     Size aLogicPaper = mpEngine->GetPaperSize();
    2613           0 :     if ( aLogicPaper.Width() > USHRT_MAX )
    2614             :     {
    2615           0 :         aLogicPaper.Width() = USHRT_MAX;
    2616           0 :         mpEngine->SetPaperSize(aLogicPaper);
    2617             :     }
    2618             : }
    2619             : 
    2620         172 : void ScOutputData::DrawEditParam::adjustForHyperlinkInPDF(Point aURLStart, OutputDevice* pDev)
    2621             : {
    2622             :     // PDF: whole-cell hyperlink from formula?
    2623         172 :     vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, pDev->GetExtOutDevData() );
    2624         172 :     bool bHasURL = pPDFData && isHyperlinkCell();
    2625         172 :     if (!bHasURL)
    2626         344 :         return;
    2627             : 
    2628           0 :     long nURLWidth = (long) mpEngine->CalcTextWidth();
    2629           0 :     long nURLHeight = mpEngine->GetTextHeight();
    2630           0 :     if (mbBreak)
    2631             :     {
    2632           0 :         Size aPaper = mpEngine->GetPaperSize();
    2633           0 :         if ( mbAsianVertical )
    2634           0 :             nURLHeight = aPaper.Height();
    2635             :         else
    2636           0 :             nURLWidth = aPaper.Width();
    2637             :     }
    2638           0 :     if (isVerticallyOriented())
    2639           0 :         std::swap( nURLWidth, nURLHeight );
    2640           0 :     else if (mbAsianVertical)
    2641           0 :         aURLStart.X() -= nURLWidth;
    2642             : 
    2643           0 :     Rectangle aURLRect( aURLStart, Size( nURLWidth, nURLHeight ) );
    2644           0 :     lcl_DoHyperlinkResult(pDev, aURLRect, maCell);
    2645             : }
    2646             : 
    2647         481 : void ScOutputData::DrawEditStandard(DrawEditParam& rParam)
    2648             : {
    2649             :     OSL_ASSERT(rParam.meOrient == SVX_ORIENTATION_STANDARD);
    2650             :     OSL_ASSERT(!rParam.mbAsianVertical);
    2651             : 
    2652         481 :     Size aRefOne = mpRefDevice->PixelToLogic(Size(1,1));
    2653             : 
    2654         481 :     bool bHidden = false;
    2655         481 :     bool bRepeat = (rParam.meHorJust == SVX_HOR_JUSTIFY_REPEAT && !rParam.mbBreak);
    2656         481 :     bool bShrink = !rParam.mbBreak && !bRepeat && lcl_GetBoolValue(*rParam.mpPattern, ATTR_SHRINKTOFIT, rParam.mpCondSet);
    2657         481 :     long nAttrRotate = lcl_GetValue<SfxInt32Item, long>(*rParam.mpPattern, ATTR_ROTATE_VALUE, rParam.mpCondSet);
    2658             : 
    2659         481 :     if ( rParam.meHorJust == SVX_HOR_JUSTIFY_REPEAT )
    2660             :     {
    2661             :         // ignore orientation/rotation if "repeat" is active
    2662           0 :         rParam.meOrient = SVX_ORIENTATION_STANDARD;
    2663           0 :         nAttrRotate = 0;
    2664             : 
    2665             :         // #i31843# "repeat" with "line breaks" is treated as default alignment
    2666             :         // (but rotation is still disabled)
    2667           0 :         if ( rParam.mbBreak )
    2668           0 :             rParam.meHorJust = SVX_HOR_JUSTIFY_STANDARD;
    2669             :     }
    2670             : 
    2671         481 :     if (nAttrRotate)
    2672             :     {
    2673             :         //! Flag setzen, um die Zelle in DrawRotated wiederzufinden ?
    2674             :         //! (oder Flag schon bei DrawBackground, dann hier keine Abfrage)
    2675         378 :         bHidden = true;     // gedreht wird getrennt ausgegeben
    2676             :     }
    2677             : 
    2678         481 :     SvxCellHorJustify eOutHorJust = rParam.meHorJust;
    2679         481 :     if (eOutHorJust == SVX_HOR_JUSTIFY_STANDARD)
    2680             :     {
    2681             :         // fdo#32530: Default alignment depends on value vs string, and the
    2682             :         // direction of the 1st letter.
    2683         101 :         if (rParam.mbRTL)
    2684           0 :             eOutHorJust = rParam.mbCellIsValue ? SVX_HOR_JUSTIFY_LEFT : SVX_HOR_JUSTIFY_RIGHT;
    2685             :         else
    2686         101 :             eOutHorJust = rParam.mbCellIsValue ? SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_LEFT;
    2687             :     }
    2688             : 
    2689         481 :     if ( eOutHorJust == SVX_HOR_JUSTIFY_BLOCK || eOutHorJust == SVX_HOR_JUSTIFY_REPEAT )
    2690          36 :         eOutHorJust = SVX_HOR_JUSTIFY_LEFT;     // repeat is not yet implemented
    2691             : 
    2692         481 :     if (bHidden)
    2693         756 :         return;
    2694             : 
    2695             :     //! mirror margin values for RTL?
    2696             :     //! move margin down to after final GetOutputArea call
    2697             :     long nTopM, nLeftM, nBottomM, nRightM;
    2698         103 :     rParam.calcMargins(nTopM, nLeftM, nBottomM, nRightM, mnPPTX, mnPPTY);
    2699             : 
    2700         103 :     SCCOL nXForPos = rParam.mnX;
    2701         103 :     if ( nXForPos < nX1 )
    2702             :     {
    2703           0 :         nXForPos = nX1;
    2704           0 :         rParam.mnPosX = rParam.mnInitPosX;
    2705             :     }
    2706         103 :     SCSIZE nArrYForPos = rParam.mnArrY;
    2707         103 :     if ( nArrYForPos < 1 )
    2708             :     {
    2709           0 :         nArrYForPos = 1;
    2710           0 :         rParam.mnPosY = nScrY;
    2711             :     }
    2712             : 
    2713         103 :     OutputAreaParam aAreaParam;
    2714             : 
    2715             :     //
    2716             :     //  Initial page size - large for normal text, cell size for automatic line breaks
    2717             :     //
    2718             : 
    2719         103 :     Size aPaperSize = Size( 1000000, 1000000 );
    2720         103 :     if (rParam.mbBreak)
    2721             :     {
    2722             :         //  call GetOutputArea with nNeeded=0, to get only the cell width
    2723             : 
    2724             :         //! handle nArrY == 0
    2725             :         GetOutputArea( nXForPos, nArrYForPos, rParam.mnPosX, rParam.mnPosY, rParam.mnCellX, rParam.mnCellY, 0,
    2726           4 :                        *rParam.mpPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
    2727           8 :                        rParam.mbCellIsValue, true, false, aAreaParam );
    2728             : 
    2729             :         //! special ScEditUtil handling if formatting for printer
    2730           4 :         rParam.calcPaperSize(aPaperSize, aAreaParam.maAlignRect, mnPPTX, mnPPTY);
    2731             :     }
    2732         103 :     if (rParam.mbPixelToLogic)
    2733             :     {
    2734         100 :         Size aLogicSize = mpRefDevice->PixelToLogic(aPaperSize);
    2735         100 :         if ( rParam.mbBreak && !rParam.mbAsianVertical && mpRefDevice != pFmtDevice )
    2736             :         {
    2737             :             // #i85342# screen display and formatting for printer,
    2738             :             // use same GetEditArea call as in ScViewData::SetEditEngine
    2739             : 
    2740           0 :             Fraction aFract(1,1);
    2741             :             Rectangle aUtilRect = ScEditUtil( mpDoc, rParam.mnCellX, rParam.mnCellY, nTab, Point(0,0), pFmtDevice,
    2742           0 :                 HMM_PER_TWIPS, HMM_PER_TWIPS, aFract, aFract ).GetEditArea( rParam.mpPattern, false );
    2743           0 :             aLogicSize.Width() = aUtilRect.GetWidth();
    2744             :         }
    2745         100 :         rParam.mpEngine->SetPaperSize(aLogicSize);
    2746             :     }
    2747             :     else
    2748           3 :         rParam.mpEngine->SetPaperSize(aPaperSize);
    2749             : 
    2750             :     //
    2751             :     //  Fill the EditEngine (cell attributes and text)
    2752             :     //
    2753             : 
    2754             :     // default alignment for asian vertical mode is top-right
    2755         103 :     if ( rParam.mbAsianVertical && rParam.meVerJust == SVX_VER_JUSTIFY_STANDARD )
    2756           0 :         rParam.meVerJust = SVX_VER_JUSTIFY_TOP;
    2757             : 
    2758         103 :     rParam.setPatternToEngine(mbUseStyleColor);
    2759         103 :     rParam.setAlignmentToEngine();
    2760             : 
    2761             :     //  Read content from cell
    2762             : 
    2763         103 :     bool bWrapFields = false;
    2764         103 :     if (!rParam.readCellContent(mpDoc, mbShowNullValues, mbShowFormulas, mbSyntaxMode, mbUseStyleColor, mbForceAutoColor, bWrapFields))
    2765             :         // Failed to read cell content.  Bail out.
    2766           0 :         return;
    2767             : 
    2768         103 :     if ( mbSyntaxMode )
    2769           0 :         SetEditSyntaxColor(*rParam.mpEngine, rParam.maCell);
    2770         103 :     else if ( mbUseStyleColor && mbForceAutoColor )
    2771           0 :         lcl_SetEditColor( *rParam.mpEngine, COL_AUTO );     //! or have a flag at EditEngine
    2772             : 
    2773         103 :     rParam.mpEngine->SetUpdateMode( true );     // after SetText, before CalcTextWidth/GetTextHeight
    2774             : 
    2775             :     //
    2776             :     //  Get final output area using the calculated width
    2777             :     //
    2778             : 
    2779             :     long nEngineWidth, nEngineHeight;
    2780         103 :     rParam.getEngineSize(rParam.mpEngine, nEngineWidth, nEngineHeight);
    2781             : 
    2782         103 :     long nNeededPixel = nEngineWidth;
    2783         103 :     if (rParam.mbPixelToLogic)
    2784         100 :         nNeededPixel = mpRefDevice->LogicToPixel(Size(nNeededPixel,0)).Width();
    2785         103 :     nNeededPixel += nLeftM + nRightM;
    2786             : 
    2787         103 :     if (!rParam.mbBreak || bShrink)
    2788             :     {
    2789             :         // for break, the first GetOutputArea call is sufficient
    2790             :         GetOutputArea( nXForPos, nArrYForPos, rParam.mnPosX, rParam.mnPosY, rParam.mnCellX, rParam.mnCellY, nNeededPixel,
    2791          99 :                        *rParam.mpPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
    2792         198 :                        rParam.mbCellIsValue || bRepeat || bShrink, false, false, aAreaParam );
    2793             : 
    2794          99 :         if ( bShrink )
    2795             :         {
    2796             :             ShrinkEditEngine( *rParam.mpEngine, aAreaParam.maAlignRect,
    2797             :                 nLeftM, nTopM, nRightM, nBottomM, true,
    2798           0 :                 sal::static_int_cast<sal_uInt16>(rParam.meOrient), 0, rParam.mbPixelToLogic,
    2799             :                 nEngineWidth, nEngineHeight, nNeededPixel,
    2800           0 :                 aAreaParam.mbLeftClip, aAreaParam.mbRightClip );
    2801             :         }
    2802          99 :         if ( bRepeat && !aAreaParam.mbLeftClip && !aAreaParam.mbRightClip && rParam.mpEngine->GetParagraphCount() == 1 )
    2803             :         {
    2804             :             // First check if twice the space for the formatted text is available
    2805             :             // (otherwise just keep it unchanged).
    2806             : 
    2807           0 :             long nFormatted = nNeededPixel - nLeftM - nRightM;      // without margin
    2808           0 :             long nAvailable = aAreaParam.maAlignRect.GetWidth() - nLeftM - nRightM;
    2809           0 :             if ( nAvailable >= 2 * nFormatted )
    2810             :             {
    2811             :                 // "repeat" is handled with unformatted text (for performance reasons)
    2812           0 :                 String aCellStr = rParam.mpEngine->GetText();
    2813           0 :                 rParam.mpEngine->SetText( aCellStr );
    2814             : 
    2815           0 :                 long nRepeatSize = (long) rParam.mpEngine->CalcTextWidth();
    2816           0 :                 if (rParam.mbPixelToLogic)
    2817           0 :                     nRepeatSize = mpRefDevice->LogicToPixel(Size(nRepeatSize,0)).Width();
    2818           0 :                 if ( pFmtDevice != mpRefDevice )
    2819           0 :                     ++nRepeatSize;
    2820           0 :                 if ( nRepeatSize > 0 )
    2821             :                 {
    2822           0 :                     long nRepeatCount = nAvailable / nRepeatSize;
    2823           0 :                     if ( nRepeatCount > 1 )
    2824             :                     {
    2825           0 :                         String aRepeated = aCellStr;
    2826           0 :                         for ( long nRepeat = 1; nRepeat < nRepeatCount; nRepeat++ )
    2827           0 :                             aRepeated.Append( aCellStr );
    2828           0 :                         rParam.mpEngine->SetText( aRepeated );
    2829             : 
    2830           0 :                         nEngineHeight = rParam.mpEngine->GetTextHeight();
    2831           0 :                         nEngineWidth = (long) rParam.mpEngine->CalcTextWidth();
    2832           0 :                         if (rParam.mbPixelToLogic)
    2833           0 :                             nNeededPixel = mpRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
    2834             :                         else
    2835           0 :                             nNeededPixel = nEngineWidth;
    2836           0 :                         nNeededPixel += nLeftM + nRightM;
    2837             :                     }
    2838           0 :                 }
    2839             :             }
    2840             :         }
    2841             : 
    2842          99 :         if ( rParam.mbCellIsValue && ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) )
    2843             :         {
    2844           0 :             rParam.mpEngine->SetText(OUString("###"));
    2845           0 :             nEngineWidth = (long) rParam.mpEngine->CalcTextWidth();
    2846           0 :             if (rParam.mbPixelToLogic)
    2847           0 :                 nNeededPixel = mpRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
    2848             :             else
    2849           0 :                 nNeededPixel = nEngineWidth;
    2850           0 :             nNeededPixel += nLeftM + nRightM;
    2851             : 
    2852             :             //  No clip marks if "###" doesn't fit (same as in DrawStrings)
    2853             :         }
    2854             : 
    2855          99 :         if (eOutHorJust != SVX_HOR_JUSTIFY_LEFT)
    2856             :         {
    2857           0 :             aPaperSize.Width() = nNeededPixel + 1;
    2858           0 :             if (rParam.mbPixelToLogic)
    2859           0 :                 rParam.mpEngine->SetPaperSize(mpRefDevice->PixelToLogic(aPaperSize));
    2860             :             else
    2861           0 :                 rParam.mpEngine->SetPaperSize(aPaperSize);
    2862             :         }
    2863             :     }
    2864             : 
    2865         103 :     long nStartX = aAreaParam.maAlignRect.Left();
    2866         103 :     long nStartY = aAreaParam.maAlignRect.Top();
    2867         103 :     long nCellWidth = aAreaParam.maAlignRect.GetWidth();
    2868         103 :     long nOutWidth = nCellWidth - 1 - nLeftM - nRightM;
    2869         103 :     long nOutHeight = aAreaParam.maAlignRect.GetHeight() - nTopM - nBottomM;
    2870             : 
    2871         103 :     if (rParam.mbBreak)
    2872             :     {
    2873             :         //  text with automatic breaks is aligned only within the
    2874             :         //  edit engine's paper size, the output of the whole area
    2875             :         //  is always left-aligned
    2876             : 
    2877           4 :         nStartX += nLeftM;
    2878             :     }
    2879             :     else
    2880             :     {
    2881          99 :         if ( eOutHorJust == SVX_HOR_JUSTIFY_RIGHT )
    2882           0 :             nStartX -= nNeededPixel - nCellWidth + nRightM + 1;
    2883          99 :         else if ( eOutHorJust == SVX_HOR_JUSTIFY_CENTER )
    2884           0 :             nStartX -= ( nNeededPixel - nCellWidth + nRightM + 1 - nLeftM ) / 2;
    2885             :         else
    2886          99 :             nStartX += nLeftM;
    2887             :     }
    2888             : 
    2889         103 :     bool bOutside = (aAreaParam.maClipRect.Right() < nScrX || aAreaParam.maClipRect.Left() >= nScrX + nScrW);
    2890         103 :     if (bOutside)
    2891           0 :         return;
    2892             : 
    2893         103 :     if ( aAreaParam.maClipRect.Left() < nScrX )
    2894             :     {
    2895           0 :         aAreaParam.maClipRect.Left() = nScrX;
    2896           0 :         aAreaParam.mbLeftClip = true;
    2897             :     }
    2898         103 :     if ( aAreaParam.maClipRect.Right() > nScrX + nScrW )
    2899             :     {
    2900           3 :         aAreaParam.maClipRect.Right() = nScrX + nScrW;          //! minus one?
    2901           3 :         aAreaParam.mbRightClip = true;
    2902             :     }
    2903             : 
    2904         103 :     bool bClip = aAreaParam.mbLeftClip || aAreaParam.mbRightClip;
    2905         103 :     bool bSimClip = false;
    2906             : 
    2907         103 :     if ( bWrapFields )
    2908             :     {
    2909             :         //  Fields in a cell with automatic breaks: clip to cell width
    2910           0 :         bClip = true;
    2911             :     }
    2912             : 
    2913         103 :     if ( aAreaParam.maClipRect.Top() < nScrY )
    2914             :     {
    2915           0 :         aAreaParam.maClipRect.Top() = nScrY;
    2916           0 :         bClip = true;
    2917             :     }
    2918         103 :     if ( aAreaParam.maClipRect.Bottom() > nScrY + nScrH )
    2919             :     {
    2920           0 :         aAreaParam.maClipRect.Bottom() = nScrY + nScrH;     //! minus one?
    2921           0 :         bClip = true;
    2922             :     }
    2923             : 
    2924         103 :     Size aCellSize;         // output area, excluding margins, in logical units
    2925         103 :     if (rParam.mbPixelToLogic)
    2926         100 :         aCellSize = mpRefDevice->PixelToLogic( Size( nOutWidth, nOutHeight ) );
    2927             :     else
    2928           3 :         aCellSize = Size( nOutWidth, nOutHeight );
    2929             : 
    2930         103 :     if ( nEngineHeight >= aCellSize.Height() + aRefOne.Height() )
    2931             :     {
    2932             :         const ScMergeAttr* pMerge =
    2933          62 :                 (ScMergeAttr*)&rParam.mpPattern->GetItem(ATTR_MERGE);
    2934          62 :         bool bMerged = pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1;
    2935             : 
    2936             :         //  Don't clip for text height when printing rows with optimal height,
    2937             :         //  except when font size is from conditional formatting.
    2938             :         //! Allow clipping when vertically merged?
    2939         127 :         if ( eType != OUTTYPE_PRINTER ||
    2940         124 :             ( mpDoc->GetRowFlags( rParam.mnCellY, nTab ) & CR_MANUALSIZE ) ||
    2941           0 :             ( rParam.mpCondSet && SFX_ITEM_SET ==
    2942           0 :                 rParam.mpCondSet->GetItemState(ATTR_FONT_HEIGHT, true) ) )
    2943          59 :             bClip = true;
    2944             :         else
    2945           3 :             bSimClip = true;
    2946             : 
    2947             :         //  Show clip marks if height is at least 5pt too small and
    2948             :         //  there are several lines of text.
    2949             :         //  Not for asian vertical text, because that would interfere
    2950             :         //  with the default right position of the text.
    2951             :         //  Only with automatic line breaks, to avoid having to find
    2952             :         //  the cells with the horizontal end of the text again.
    2953         127 :         if ( nEngineHeight - aCellSize.Height() > 100 &&
    2954          62 :              rParam.mbBreak && bMarkClipped &&
    2955           0 :              ( rParam.mpEngine->GetParagraphCount() > 1 || rParam.mpEngine->GetLineCount(0) > 1 ) )
    2956             :         {
    2957           0 :             CellInfo* pClipMarkCell = NULL;
    2958           0 :             if ( bMerged )
    2959             :             {
    2960             :                 //  anywhere in the merged area...
    2961           0 :                 SCCOL nClipX = ( rParam.mnX < nX1 ) ? nX1 : rParam.mnX;
    2962           0 :                 pClipMarkCell = &pRowInfo[(rParam.mnArrY != 0) ? rParam.mnArrY : 1].pCellInfo[nClipX+1];
    2963             :             }
    2964             :             else
    2965           0 :                 pClipMarkCell = &rParam.mpThisRowInfo->pCellInfo[rParam.mnX+1];
    2966             : 
    2967           0 :             pClipMarkCell->nClipMark |= SC_CLIPMARK_RIGHT;      //! also allow left?
    2968           0 :             bAnyClipped = true;
    2969             : 
    2970           0 :             long nMarkPixel = (long)( SC_CLIPMARK_SIZE * mnPPTX );
    2971           0 :             if ( aAreaParam.maClipRect.Right() - nMarkPixel > aAreaParam.maClipRect.Left() )
    2972           0 :                 aAreaParam.maClipRect.Right() -= nMarkPixel;
    2973             :         }
    2974             :     }
    2975             : 
    2976         103 :     Rectangle aLogicClip;
    2977         103 :     if (bClip || bSimClip)
    2978             :     {
    2979             :         // Clip marks are already handled in GetOutputArea
    2980             : 
    2981          62 :         if (rParam.mbPixelToLogic)
    2982          59 :             aLogicClip = mpRefDevice->PixelToLogic( aAreaParam.maClipRect );
    2983             :         else
    2984           3 :             aLogicClip = aAreaParam.maClipRect;
    2985             : 
    2986          62 :         if (bClip)  // bei bSimClip nur aClipRect initialisieren
    2987             :         {
    2988          62 :             if (bMetaFile)
    2989             :             {
    2990           0 :                 mpDev->Push();
    2991           0 :                 mpDev->IntersectClipRegion( aLogicClip );
    2992             :             }
    2993             :             else
    2994          62 :                 mpDev->SetClipRegion( Region( aLogicClip ) );
    2995             :         }
    2996             :     }
    2997             : 
    2998         103 :     Point aLogicStart;
    2999         103 :     if (rParam.mbPixelToLogic)
    3000         100 :         aLogicStart = mpRefDevice->PixelToLogic( Point(nStartX,nStartY) );
    3001             :     else
    3002           3 :         aLogicStart = Point(nStartX, nStartY);
    3003             : 
    3004         103 :     if (!rParam.mbBreak)
    3005             :     {
    3006             :         //  horizontal alignment
    3007          99 :         if (rParam.adjustHorAlignment(rParam.mpEngine))
    3008             :             // reset adjustment for the next cell
    3009           0 :             rParam.mpOldPattern = NULL;
    3010             :     }
    3011             : 
    3012         206 :     if (rParam.meVerJust==SVX_VER_JUSTIFY_BOTTOM ||
    3013         103 :         rParam.meVerJust==SVX_VER_JUSTIFY_STANDARD)
    3014             :     {
    3015             :         //! if pRefDevice != pFmtDevice, keep heights in logic units,
    3016             :         //! only converting margin?
    3017             : 
    3018         196 :         if (rParam.mbPixelToLogic)
    3019         190 :             aLogicStart.Y() += mpRefDevice->PixelToLogic( Size(0, nTopM +
    3020         190 :                             mpRefDevice->LogicToPixel(aCellSize).Height() -
    3021         190 :                             mpRefDevice->LogicToPixel(Size(0,nEngineHeight)).Height()
    3022         190 :                             )).Height();
    3023             :         else
    3024           3 :             aLogicStart.Y() += nTopM + aCellSize.Height() - nEngineHeight;
    3025             :     }
    3026           5 :     else if (rParam.meVerJust==SVX_VER_JUSTIFY_CENTER)
    3027             :     {
    3028           0 :         if (rParam.mbPixelToLogic)
    3029           0 :             aLogicStart.Y() += mpRefDevice->PixelToLogic( Size(0, nTopM + (
    3030           0 :                             mpRefDevice->LogicToPixel(aCellSize).Height() -
    3031           0 :                             mpRefDevice->LogicToPixel(Size(0,nEngineHeight)).Height() )
    3032           0 :                             / 2)).Height();
    3033             :         else
    3034           0 :             aLogicStart.Y() += nTopM + (aCellSize.Height() - nEngineHeight) / 2;
    3035             :     }
    3036             :     else        // top
    3037             :     {
    3038           5 :         if (rParam.mbPixelToLogic)
    3039           5 :             aLogicStart.Y() += mpRefDevice->PixelToLogic(Size(0,nTopM)).Height();
    3040             :         else
    3041           0 :             aLogicStart.Y() += nTopM;
    3042             :     }
    3043             : 
    3044         103 :     Point aURLStart = aLogicStart;      // copy before modifying for orientation
    3045             : 
    3046         103 :     rParam.adjustForRTL();
    3047             : 
    3048             :     // bMoveClipped handling has been replaced by complete alignment
    3049             :     // handling (also extending to the left).
    3050             : 
    3051         103 :     if (bSimClip)
    3052             :     {
    3053             :         //  kein hartes Clipping, aber nur die betroffenen
    3054             :         //  Zeilen ausgeben
    3055             : 
    3056           3 :         Point aDocStart = aLogicClip.TopLeft();
    3057           3 :         aDocStart -= aLogicStart;
    3058           3 :         rParam.mpEngine->Draw( mpDev, aLogicClip, aDocStart, false );
    3059             :     }
    3060             :     else
    3061             :     {
    3062         100 :         rParam.mpEngine->Draw(mpDev, aLogicStart, 0);
    3063             :     }
    3064             : 
    3065         103 :     if (bClip)
    3066             :     {
    3067          62 :         if (bMetaFile)
    3068           0 :             mpDev->Pop();
    3069             :         else
    3070          62 :             mpDev->SetClipRegion();
    3071             :     }
    3072             : 
    3073         103 :     rParam.adjustForHyperlinkInPDF(aURLStart, mpDev);
    3074             : }
    3075             : 
    3076           0 : void ScOutputData::ShowClipMarks( DrawEditParam& rParam, long nEngineHeight, const Size& aCellSize,
    3077             :                                   bool bMerged, OutputAreaParam& aAreaParam)
    3078             : {
    3079             :     //  Show clip marks if height is at least 5pt too small and
    3080             :     //  there are several lines of text.
    3081             :     //  Not for asian vertical text, because that would interfere
    3082             :     //  with the default right position of the text.
    3083             :     //  Only with automatic line breaks, to avoid having to find
    3084             :     //  the cells with the horizontal end of the text again.
    3085           0 :     if ( nEngineHeight - aCellSize.Height() > 100 &&
    3086           0 :             rParam.mbBreak && bMarkClipped &&
    3087           0 :             ( rParam.mpEngine->GetParagraphCount() > 1 || rParam.mpEngine->GetLineCount(0) > 1 ) )
    3088             :     {
    3089           0 :         CellInfo* pClipMarkCell = NULL;
    3090           0 :         if ( bMerged )
    3091             :         {
    3092             :             //  anywhere in the merged area...
    3093           0 :             SCCOL nClipX = ( rParam.mnX < nX1 ) ? nX1 : rParam.mnX;
    3094           0 :             pClipMarkCell = &pRowInfo[(rParam.mnArrY != 0) ? rParam.mnArrY : 1].pCellInfo[nClipX+1];
    3095             :         }
    3096             :         else
    3097           0 :             pClipMarkCell = &rParam.mpThisRowInfo->pCellInfo[rParam.mnX+1];
    3098             : 
    3099           0 :         pClipMarkCell->nClipMark |= SC_CLIPMARK_RIGHT;      //! also allow left?
    3100           0 :         bAnyClipped = true;
    3101             : 
    3102           0 :         const long nMarkPixel = static_cast<long>( SC_CLIPMARK_SIZE * mnPPTX );
    3103           0 :         if ( aAreaParam.maClipRect.Right() - nMarkPixel > aAreaParam.maClipRect.Left() )
    3104           0 :             aAreaParam.maClipRect.Right() -= nMarkPixel;
    3105             :     }
    3106           0 : }
    3107             : 
    3108          69 : bool ScOutputData::Clip( DrawEditParam& rParam, const Size& aCellSize,
    3109             :                          OutputAreaParam& aAreaParam, long nEngineHeight,
    3110             :                          bool bWrapFields)
    3111             : {
    3112          69 :     if ( aAreaParam.maClipRect.Left() < nScrX )
    3113             :     {
    3114           0 :         aAreaParam.maClipRect.Left() = nScrX;
    3115           0 :         aAreaParam.mbLeftClip = true;
    3116             :     }
    3117          69 :     if ( aAreaParam.maClipRect.Right() > nScrX + nScrW )
    3118             :     {
    3119           0 :         aAreaParam.maClipRect.Right() = nScrX + nScrW;          //! minus one?
    3120           0 :         aAreaParam.mbRightClip = true;
    3121             :     }
    3122             : 
    3123          69 :     bool bClip = aAreaParam.mbLeftClip || aAreaParam.mbRightClip;
    3124          69 :     bool bSimClip = false;
    3125             : 
    3126          69 :     if ( bWrapFields )
    3127             :     {
    3128             :         //  Fields in a cell with automatic breaks: clip to cell width
    3129           0 :         bClip = true;
    3130             :     }
    3131             : 
    3132          69 :     if ( aAreaParam.maClipRect.Top() < nScrY )
    3133             :     {
    3134           0 :         aAreaParam.maClipRect.Top() = nScrY;
    3135           0 :         bClip = true;
    3136             :     }
    3137          69 :     if ( aAreaParam.maClipRect.Bottom() > nScrY + nScrH )
    3138             :     {
    3139           0 :         aAreaParam.maClipRect.Bottom() = nScrY + nScrH;     //! minus one?
    3140           0 :         bClip = true;
    3141             :     }
    3142             : 
    3143          69 :     const Size& aRefOne = mpRefDevice->PixelToLogic(Size(1,1));
    3144          69 :     if ( nEngineHeight >= aCellSize.Height() + aRefOne.Height() )
    3145             :     {
    3146             :         const ScMergeAttr* pMerge =
    3147           0 :                 (ScMergeAttr*)&rParam.mpPattern->GetItem(ATTR_MERGE);
    3148           0 :         const bool bMerged = pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1;
    3149             : 
    3150             :         //  Don't clip for text height when printing rows with optimal height,
    3151             :         //  except when font size is from conditional formatting.
    3152             :         //! Allow clipping when vertically merged?
    3153           0 :         if ( eType != OUTTYPE_PRINTER ||
    3154           0 :             ( mpDoc->GetRowFlags( rParam.mnCellY, nTab ) & CR_MANUALSIZE ) ||
    3155           0 :             ( rParam.mpCondSet && SFX_ITEM_SET ==
    3156           0 :                 rParam.mpCondSet->GetItemState(ATTR_FONT_HEIGHT, true) ) )
    3157           0 :             bClip = true;
    3158             :         else
    3159           0 :             bSimClip = true;
    3160             : 
    3161           0 :         ShowClipMarks( rParam, nEngineHeight, aCellSize, bMerged, aAreaParam);
    3162             :     }
    3163             : 
    3164          69 :     Rectangle aLogicClip;
    3165          69 :     if (bClip || bSimClip)
    3166             :     {
    3167             :         // Clip marks are already handled in GetOutputArea
    3168             : 
    3169           0 :         if (rParam.mbPixelToLogic)
    3170           0 :             aLogicClip = mpRefDevice->PixelToLogic( aAreaParam.maClipRect );
    3171             :         else
    3172           0 :             aLogicClip = aAreaParam.maClipRect;
    3173             : 
    3174           0 :         if (bClip)  // bei bSimClip nur aClipRect initialisieren
    3175             :         {
    3176           0 :             if (bMetaFile)
    3177             :             {
    3178           0 :                 mpDev->Push();
    3179           0 :                 mpDev->IntersectClipRegion( aLogicClip );
    3180             :             }
    3181             :             else
    3182           0 :                 mpDev->SetClipRegion( Region( aLogicClip ) );
    3183             :         }
    3184             :     }
    3185             : 
    3186          69 :     return bClip;
    3187             : }
    3188             : 
    3189           0 : void ScOutputData::DrawEditBottomTop(DrawEditParam& rParam)
    3190             : {
    3191             :     OSL_ASSERT(rParam.meHorJust != SVX_HOR_JUSTIFY_REPEAT);
    3192             : 
    3193           0 :     const bool bRepeat = (rParam.meHorJust == SVX_HOR_JUSTIFY_REPEAT && !rParam.mbBreak);
    3194           0 :     const bool bShrink = !rParam.mbBreak && !bRepeat && lcl_GetBoolValue(*rParam.mpPattern, ATTR_SHRINKTOFIT, rParam.mpCondSet);
    3195             : 
    3196             :     SvxCellHorJustify eOutHorJust =
    3197           0 :         ( rParam.meHorJust != SVX_HOR_JUSTIFY_STANDARD ) ? rParam.meHorJust :
    3198           0 :         ( rParam.mbCellIsValue ? SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_LEFT );
    3199             : 
    3200           0 :     if ( eOutHorJust == SVX_HOR_JUSTIFY_BLOCK || eOutHorJust == SVX_HOR_JUSTIFY_REPEAT )
    3201           0 :         eOutHorJust = SVX_HOR_JUSTIFY_LEFT;     // repeat is not yet implemented
    3202             : 
    3203             :     //! mirror margin values for RTL?
    3204             :     //! move margin down to after final GetOutputArea call
    3205             :     long nTopM, nLeftM, nBottomM, nRightM;
    3206           0 :     rParam.calcMargins(nTopM, nLeftM, nBottomM, nRightM, mnPPTX, mnPPTY);
    3207             : 
    3208           0 :     SCCOL nXForPos = rParam.mnX;
    3209           0 :     if ( nXForPos < nX1 )
    3210             :     {
    3211           0 :         nXForPos = nX1;
    3212           0 :         rParam.mnPosX = rParam.mnInitPosX;
    3213             :     }
    3214           0 :     SCSIZE nArrYForPos = rParam.mnArrY;
    3215           0 :     if ( nArrYForPos < 1 )
    3216             :     {
    3217           0 :         nArrYForPos = 1;
    3218           0 :         rParam.mnPosY = nScrY;
    3219             :     }
    3220             : 
    3221           0 :     OutputAreaParam aAreaParam;
    3222             : 
    3223             :     //
    3224             :     //  Initial page size - large for normal text, cell size for automatic line breaks
    3225             :     //
    3226             : 
    3227           0 :     Size aPaperSize = Size( 1000000, 1000000 );
    3228           0 :     if (rParam.mbBreak)
    3229             :     {
    3230             :         //  call GetOutputArea with nNeeded=0, to get only the cell width
    3231             : 
    3232             :         //! handle nArrY == 0
    3233             :         GetOutputArea( nXForPos, nArrYForPos, rParam.mnPosX, rParam.mnPosY, rParam.mnCellX, rParam.mnCellY, 0,
    3234           0 :                        *rParam.mpPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
    3235           0 :                        rParam.mbCellIsValue, true, false, aAreaParam );
    3236             : 
    3237             :         //! special ScEditUtil handling if formatting for printer
    3238           0 :         rParam.calcPaperSize(aPaperSize, aAreaParam.maAlignRect, mnPPTX, mnPPTY);
    3239             :     }
    3240           0 :     if (rParam.mbPixelToLogic)
    3241             :     {
    3242           0 :         Size aLogicSize = mpRefDevice->PixelToLogic(aPaperSize);
    3243           0 :         rParam.mpEngine->SetPaperSize(aLogicSize);
    3244             :     }
    3245             :     else
    3246           0 :         rParam.mpEngine->SetPaperSize(aPaperSize);
    3247             : 
    3248             :     //
    3249             :     //  Fill the EditEngine (cell attributes and text)
    3250             :     //
    3251             : 
    3252           0 :     rParam.setPatternToEngine(mbUseStyleColor);
    3253           0 :     rParam.setAlignmentToEngine();
    3254             : 
    3255             :     //  Read content from cell
    3256             : 
    3257           0 :     bool bWrapFields = false;
    3258           0 :     if (!rParam.readCellContent(mpDoc, mbShowNullValues, mbShowFormulas, mbSyntaxMode, mbUseStyleColor, mbForceAutoColor, bWrapFields))
    3259             :         // Failed to read cell content.  Bail out.
    3260           0 :         return;
    3261             : 
    3262           0 :     if ( mbSyntaxMode )
    3263           0 :         SetEditSyntaxColor( *rParam.mpEngine, rParam.maCell );
    3264           0 :     else if ( mbUseStyleColor && mbForceAutoColor )
    3265           0 :         lcl_SetEditColor( *rParam.mpEngine, COL_AUTO );     //! or have a flag at EditEngine
    3266             : 
    3267           0 :     rParam.mpEngine->SetUpdateMode( true );     // after SetText, before CalcTextWidth/GetTextHeight
    3268             : 
    3269             :     //
    3270             :     //  Get final output area using the calculated width
    3271             :     //
    3272             : 
    3273             :     long nEngineWidth, nEngineHeight;
    3274           0 :     rParam.getEngineSize(rParam.mpEngine, nEngineWidth, nEngineHeight);
    3275             : 
    3276           0 :     long nNeededPixel = nEngineWidth;
    3277           0 :     if (rParam.mbPixelToLogic)
    3278           0 :         nNeededPixel = mpRefDevice->LogicToPixel(Size(nNeededPixel,0)).Width();
    3279           0 :     nNeededPixel += nLeftM + nRightM;
    3280             : 
    3281           0 :     if (!rParam.mbBreak || bShrink)
    3282             :     {
    3283             :         // for break, the first GetOutputArea call is sufficient
    3284             :         GetOutputArea( nXForPos, nArrYForPos, rParam.mnPosX, rParam.mnPosY, rParam.mnCellX, rParam.mnCellY, nNeededPixel,
    3285           0 :                        *rParam.mpPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
    3286           0 :                        rParam.mbCellIsValue || bRepeat || bShrink, false, false, aAreaParam );
    3287             : 
    3288           0 :         if ( bShrink )
    3289             :         {
    3290             :             ShrinkEditEngine( *rParam.mpEngine, aAreaParam.maAlignRect,
    3291             :                 nLeftM, nTopM, nRightM, nBottomM, false,
    3292           0 :                 sal::static_int_cast<sal_uInt16>(rParam.meOrient), 0, rParam.mbPixelToLogic,
    3293             :                 nEngineWidth, nEngineHeight, nNeededPixel,
    3294           0 :                 aAreaParam.mbLeftClip, aAreaParam.mbRightClip );
    3295             :         }
    3296           0 :         if ( bRepeat && !aAreaParam.mbLeftClip && !aAreaParam.mbRightClip && rParam.mpEngine->GetParagraphCount() == 1 )
    3297             :         {
    3298             :             // First check if twice the space for the formatted text is available
    3299             :             // (otherwise just keep it unchanged).
    3300             : 
    3301           0 :             const long nFormatted = nNeededPixel - nLeftM - nRightM;      // without margin
    3302           0 :             const long nAvailable = aAreaParam.maAlignRect.GetWidth() - nLeftM - nRightM;
    3303           0 :             if ( nAvailable >= 2 * nFormatted )
    3304             :             {
    3305             :                 // "repeat" is handled with unformatted text (for performance reasons)
    3306           0 :                 String aCellStr = rParam.mpEngine->GetText();
    3307           0 :                 rParam.mpEngine->SetText( aCellStr );
    3308             : 
    3309           0 :                 long nRepeatSize = static_cast<long>( rParam.mpEngine->CalcTextWidth() );
    3310           0 :                 if (rParam.mbPixelToLogic)
    3311           0 :                     nRepeatSize = mpRefDevice->LogicToPixel(Size(nRepeatSize,0)).Width();
    3312           0 :                 if ( pFmtDevice != mpRefDevice )
    3313           0 :                     ++nRepeatSize;
    3314           0 :                 if ( nRepeatSize > 0 )
    3315             :                 {
    3316           0 :                     const long nRepeatCount = nAvailable / nRepeatSize;
    3317           0 :                     if ( nRepeatCount > 1 )
    3318             :                     {
    3319           0 :                         String aRepeated = aCellStr;
    3320           0 :                         for ( long nRepeat = 1; nRepeat < nRepeatCount; nRepeat++ )
    3321           0 :                             aRepeated.Append( aCellStr );
    3322           0 :                         rParam.mpEngine->SetText( aRepeated );
    3323             : 
    3324           0 :                         nEngineHeight = rParam.mpEngine->GetTextHeight();
    3325           0 :                         nEngineWidth = static_cast<long>( rParam.mpEngine->CalcTextWidth() );
    3326           0 :                         if (rParam.mbPixelToLogic)
    3327           0 :                             nNeededPixel = mpRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
    3328             :                         else
    3329           0 :                             nNeededPixel = nEngineWidth;
    3330           0 :                         nNeededPixel += nLeftM + nRightM;
    3331             :                     }
    3332           0 :                 }
    3333             :             }
    3334             :         }
    3335             : 
    3336           0 :         if ( rParam.mbCellIsValue && ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) )
    3337             :         {
    3338           0 :             rParam.mpEngine->SetText(OUString("###"));
    3339           0 :             nEngineWidth = (long) rParam.mpEngine->CalcTextWidth();
    3340           0 :             if (rParam.mbPixelToLogic)
    3341           0 :                 nNeededPixel = mpRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
    3342             :             else
    3343           0 :                 nNeededPixel = nEngineWidth;
    3344           0 :             nNeededPixel += nLeftM + nRightM;
    3345             : 
    3346             :             //  No clip marks if "###" doesn't fit (same as in DrawStrings)
    3347             :         }
    3348             :     }
    3349             : 
    3350           0 :     long nStartX = aAreaParam.maAlignRect.Left();
    3351           0 :     const long nStartY = aAreaParam.maAlignRect.Top();
    3352           0 :     const long nCellWidth = aAreaParam.maAlignRect.GetWidth();
    3353           0 :     const long nOutWidth = nCellWidth - 1 - nLeftM - nRightM;
    3354           0 :     const long nOutHeight = aAreaParam.maAlignRect.GetHeight() - nTopM - nBottomM;
    3355             : 
    3356           0 :     if (rParam.mbBreak)
    3357             :     {
    3358             :         //  text with automatic breaks is aligned only within the
    3359             :         //  edit engine's paper size, the output of the whole area
    3360             :         //  is always left-aligned
    3361             : 
    3362           0 :         nStartX += nLeftM;
    3363             :     }
    3364             :     else
    3365             :     {
    3366           0 :         if ( eOutHorJust == SVX_HOR_JUSTIFY_RIGHT )
    3367           0 :             nStartX -= nNeededPixel - nCellWidth + nRightM + 1;
    3368           0 :         else if ( eOutHorJust == SVX_HOR_JUSTIFY_CENTER )
    3369           0 :             nStartX -= ( nNeededPixel - nCellWidth + nRightM + 1 - nLeftM ) / 2;
    3370             :         else
    3371           0 :             nStartX += nLeftM;
    3372             :     }
    3373             : 
    3374           0 :     const bool bOutside = (aAreaParam.maClipRect.Right() < nScrX || aAreaParam.maClipRect.Left() >= nScrX + nScrW);
    3375           0 :     if (bOutside)
    3376           0 :         return;
    3377             : 
    3378             :     // output area, excluding margins, in logical units
    3379             :     const Size& aCellSize = rParam.mbPixelToLogic
    3380           0 :         ? mpRefDevice->PixelToLogic( Size( nOutWidth, nOutHeight ) )
    3381           0 :         : Size( nOutWidth, nOutHeight );
    3382             : 
    3383           0 :     const bool bClip = Clip( rParam, aCellSize, aAreaParam, nEngineHeight, bWrapFields );
    3384             : 
    3385           0 :     Point aLogicStart(nStartX, nStartY);
    3386           0 :     rParam.calcStartPosForVertical(aLogicStart, aCellSize.Width(), nEngineWidth, nTopM, mpRefDevice);
    3387             : 
    3388           0 :     Point aURLStart = aLogicStart;      // copy before modifying for orientation
    3389             : 
    3390           0 :     if (rParam.meHorJust == SVX_HOR_JUSTIFY_BLOCK || rParam.mbBreak)
    3391             :     {
    3392           0 :         Size aPSize = rParam.mpEngine->GetPaperSize();
    3393           0 :         aPSize.Width() = aCellSize.Height();
    3394           0 :         rParam.mpEngine->SetPaperSize(aPSize);
    3395           0 :         aLogicStart.Y() +=
    3396           0 :             rParam.mbBreak ? aPSize.Width() : nEngineHeight;
    3397             :     }
    3398             :     else
    3399             :     {
    3400             :         // Note that the "paper" is rotated 90 degrees to the left, so
    3401             :         // paper's width is in vertical direction.  Also, the whole text
    3402             :         // is on a single line, as text wrap is not in effect.
    3403             : 
    3404             :         // Set the paper width to be the width of the text.
    3405           0 :         Size aPSize = rParam.mpEngine->GetPaperSize();
    3406           0 :         aPSize.Width() = rParam.mpEngine->CalcTextWidth();
    3407           0 :         rParam.mpEngine->SetPaperSize(aPSize);
    3408             : 
    3409           0 :         long nGap = 0;
    3410           0 :         long nTopOffset = 0;
    3411           0 :         if (rParam.mbPixelToLogic)
    3412             :         {
    3413           0 :             nGap = mpRefDevice->LogicToPixel(aCellSize).Height() - mpRefDevice->LogicToPixel(aPSize).Width();
    3414           0 :             nGap = mpRefDevice->PixelToLogic(Size(0, nGap)).Height();
    3415           0 :             nTopOffset = mpRefDevice->PixelToLogic(Size(0,nTopM)).Height();
    3416             :         }
    3417             :         else
    3418             :         {
    3419           0 :             nGap = aCellSize.Height() - aPSize.Width();
    3420           0 :             nTopOffset = nTopM;
    3421             :         }
    3422             : 
    3423             :         // First, align text to bottom.
    3424           0 :         aLogicStart.Y() += aCellSize.Height();
    3425           0 :         aLogicStart.Y() += nTopOffset;
    3426             : 
    3427           0 :         switch (rParam.meVerJust)
    3428             :         {
    3429             :             case SVX_VER_JUSTIFY_STANDARD:
    3430             :             case SVX_VER_JUSTIFY_BOTTOM:
    3431             :                 // align to bottom (do nothing).
    3432           0 :             break;
    3433             :             case SVX_VER_JUSTIFY_CENTER:
    3434             :                 // center it.
    3435           0 :                 aLogicStart.Y() -= nGap / 2;
    3436           0 :             break;
    3437             :             case SVX_VER_JUSTIFY_BLOCK:
    3438             :             case SVX_VER_JUSTIFY_TOP:
    3439             :                 // align to top
    3440           0 :                 aLogicStart.Y() -= nGap;
    3441             :             default:
    3442             :                 ;
    3443             :         }
    3444             :     }
    3445             : 
    3446           0 :     rParam.adjustForRTL();
    3447           0 :     rParam.mpEngine->Draw(mpDev, aLogicStart, 900);
    3448             : 
    3449           0 :     if (bClip)
    3450             :     {
    3451           0 :         if (bMetaFile)
    3452           0 :             mpDev->Pop();
    3453             :         else
    3454           0 :             mpDev->SetClipRegion();
    3455             :     }
    3456             : 
    3457           0 :     rParam.adjustForHyperlinkInPDF(aURLStart, mpDev);
    3458             : }
    3459             : 
    3460          69 : void ScOutputData::DrawEditTopBottom(DrawEditParam& rParam)
    3461             : {
    3462             :     OSL_ASSERT(rParam.meHorJust != SVX_HOR_JUSTIFY_REPEAT);
    3463             : 
    3464          69 :     const bool bRepeat = (rParam.meHorJust == SVX_HOR_JUSTIFY_REPEAT && !rParam.mbBreak);
    3465          69 :     const bool bShrink = !rParam.mbBreak && !bRepeat && lcl_GetBoolValue(*rParam.mpPattern, ATTR_SHRINKTOFIT, rParam.mpCondSet);
    3466             : 
    3467             :     SvxCellHorJustify eOutHorJust =
    3468          69 :         ( rParam.meHorJust != SVX_HOR_JUSTIFY_STANDARD ) ? rParam.meHorJust :
    3469          69 :         ( rParam.mbCellIsValue ? SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_LEFT );
    3470             : 
    3471          69 :     if ( eOutHorJust == SVX_HOR_JUSTIFY_BLOCK || eOutHorJust == SVX_HOR_JUSTIFY_REPEAT )
    3472          12 :         eOutHorJust = SVX_HOR_JUSTIFY_LEFT;     // repeat is not yet implemented
    3473             : 
    3474             :     //! mirror margin values for RTL?
    3475             :     //! move margin down to after final GetOutputArea call
    3476             :     long nTopM, nLeftM, nBottomM, nRightM;
    3477          69 :     rParam.calcMargins(nTopM, nLeftM, nBottomM, nRightM, mnPPTX, mnPPTY);
    3478             : 
    3479          69 :     SCCOL nXForPos = rParam.mnX;
    3480          69 :     if ( nXForPos < nX1 )
    3481             :     {
    3482           0 :         nXForPos = nX1;
    3483           0 :         rParam.mnPosX = rParam.mnInitPosX;
    3484             :     }
    3485          69 :     SCSIZE nArrYForPos = rParam.mnArrY;
    3486          69 :     if ( nArrYForPos < 1 )
    3487             :     {
    3488           0 :         nArrYForPos = 1;
    3489           0 :         rParam.mnPosY = nScrY;
    3490             :     }
    3491             : 
    3492          69 :     OutputAreaParam aAreaParam;
    3493             : 
    3494             :     //
    3495             :     //  Initial page size - large for normal text, cell size for automatic line breaks
    3496             :     //
    3497             : 
    3498          69 :     Size aPaperSize = Size( 1000000, 1000000 );
    3499          69 :     if (rParam.hasLineBreak())
    3500             :     {
    3501             :         //  call GetOutputArea with nNeeded=0, to get only the cell width
    3502             : 
    3503             :         //! handle nArrY == 0
    3504             :         GetOutputArea( nXForPos, nArrYForPos, rParam.mnPosX, rParam.mnPosY, rParam.mnCellX, rParam.mnCellY, 0,
    3505          69 :                        *rParam.mpPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
    3506         138 :                        rParam.mbCellIsValue, true, false, aAreaParam );
    3507             : 
    3508             :         //! special ScEditUtil handling if formatting for printer
    3509          69 :         rParam.calcPaperSize(aPaperSize, aAreaParam.maAlignRect, mnPPTX, mnPPTY);
    3510             :     }
    3511          69 :     if (rParam.mbPixelToLogic)
    3512             :     {
    3513          69 :         Size aLogicSize = mpRefDevice->PixelToLogic(aPaperSize);
    3514          69 :         rParam.mpEngine->SetPaperSize(aLogicSize);
    3515             :     }
    3516             :     else
    3517           0 :         rParam.mpEngine->SetPaperSize(aPaperSize);
    3518             : 
    3519             :     //
    3520             :     //  Fill the EditEngine (cell attributes and text)
    3521             :     //
    3522             : 
    3523          69 :     rParam.setPatternToEngine(mbUseStyleColor);
    3524          69 :     rParam.setAlignmentToEngine();
    3525             : 
    3526             :     //  Read content from cell
    3527             : 
    3528          69 :     bool bWrapFields = false;
    3529          69 :     if (!rParam.readCellContent(mpDoc, mbShowNullValues, mbShowFormulas, mbSyntaxMode, mbUseStyleColor, mbForceAutoColor, bWrapFields))
    3530             :         // Failed to read cell content.  Bail out.
    3531           0 :         return;
    3532             : 
    3533          69 :     if ( mbSyntaxMode )
    3534           0 :         SetEditSyntaxColor( *rParam.mpEngine, rParam.maCell );
    3535          69 :     else if ( mbUseStyleColor && mbForceAutoColor )
    3536           0 :         lcl_SetEditColor( *rParam.mpEngine, COL_AUTO );     //! or have a flag at EditEngine
    3537             : 
    3538          69 :     rParam.mpEngine->SetUpdateMode( true );     // after SetText, before CalcTextWidth/GetTextHeight
    3539             : 
    3540             :     //
    3541             :     //  Get final output area using the calculated width
    3542             :     //
    3543             : 
    3544             :     long nEngineWidth, nEngineHeight;
    3545          69 :     rParam.getEngineSize(rParam.mpEngine, nEngineWidth, nEngineHeight);
    3546             : 
    3547          69 :     long nNeededPixel = nEngineWidth;
    3548          69 :     if (rParam.mbPixelToLogic)
    3549          69 :         nNeededPixel = mpRefDevice->LogicToPixel(Size(nNeededPixel,0)).Width();
    3550          69 :     nNeededPixel += nLeftM + nRightM;
    3551             : 
    3552          69 :     if (!rParam.mbBreak || bShrink)
    3553             :     {
    3554             :         // for break, the first GetOutputArea call is sufficient
    3555             :         GetOutputArea( nXForPos, nArrYForPos, rParam.mnPosX, rParam.mnPosY, rParam.mnCellX, rParam.mnCellY, nNeededPixel,
    3556           0 :                        *rParam.mpPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
    3557           0 :                        rParam.mbCellIsValue || bRepeat || bShrink, false, false, aAreaParam );
    3558             : 
    3559           0 :         if ( bShrink )
    3560             :         {
    3561             :             ShrinkEditEngine( *rParam.mpEngine, aAreaParam.maAlignRect,
    3562             :                 nLeftM, nTopM, nRightM, nBottomM, false,
    3563           0 :                 sal::static_int_cast<sal_uInt16>(rParam.meOrient), 0, rParam.mbPixelToLogic,
    3564             :                 nEngineWidth, nEngineHeight, nNeededPixel,
    3565           0 :                 aAreaParam.mbLeftClip, aAreaParam.mbRightClip );
    3566             :         }
    3567           0 :         if ( bRepeat && !aAreaParam.mbLeftClip && !aAreaParam.mbRightClip && rParam.mpEngine->GetParagraphCount() == 1 )
    3568             :         {
    3569             :             // First check if twice the space for the formatted text is available
    3570             :             // (otherwise just keep it unchanged).
    3571             : 
    3572           0 :             const long nFormatted = nNeededPixel - nLeftM - nRightM;      // without margin
    3573           0 :             const long nAvailable = aAreaParam.maAlignRect.GetWidth() - nLeftM - nRightM;
    3574           0 :             if ( nAvailable >= 2 * nFormatted )
    3575             :             {
    3576             :                 // "repeat" is handled with unformatted text (for performance reasons)
    3577           0 :                 String aCellStr = rParam.mpEngine->GetText();
    3578           0 :                 rParam.mpEngine->SetText( aCellStr );
    3579             : 
    3580           0 :                 long nRepeatSize = static_cast<long>( rParam.mpEngine->CalcTextWidth() );
    3581           0 :                 if (rParam.mbPixelToLogic)
    3582           0 :                     nRepeatSize = mpRefDevice->LogicToPixel(Size(nRepeatSize,0)).Width();
    3583           0 :                 if ( pFmtDevice != mpRefDevice )
    3584           0 :                     ++nRepeatSize;
    3585           0 :                 if ( nRepeatSize > 0 )
    3586             :                 {
    3587           0 :                     const long nRepeatCount = nAvailable / nRepeatSize;
    3588           0 :                     if ( nRepeatCount > 1 )
    3589             :                     {
    3590           0 :                         String aRepeated = aCellStr;
    3591           0 :                         for ( long nRepeat = 1; nRepeat < nRepeatCount; nRepeat++ )
    3592           0 :                             aRepeated.Append( aCellStr );
    3593           0 :                         rParam.mpEngine->SetText( aRepeated );
    3594             : 
    3595           0 :                         nEngineHeight = rParam.mpEngine->GetTextHeight();
    3596           0 :                         nEngineWidth = static_cast<long>( rParam.mpEngine->CalcTextWidth() );
    3597           0 :                         if (rParam.mbPixelToLogic)
    3598           0 :                             nNeededPixel = mpRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
    3599             :                         else
    3600           0 :                             nNeededPixel = nEngineWidth;
    3601           0 :                         nNeededPixel += nLeftM + nRightM;
    3602             :                     }
    3603           0 :                 }
    3604             :             }
    3605             :         }
    3606             : 
    3607           0 :         if ( rParam.mbCellIsValue && ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) )
    3608             :         {
    3609           0 :             rParam.mpEngine->SetText(OUString("###"));
    3610           0 :             nEngineWidth = static_cast<long>( rParam.mpEngine->CalcTextWidth() );
    3611           0 :             if (rParam.mbPixelToLogic)
    3612           0 :                 nNeededPixel = mpRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
    3613             :             else
    3614           0 :                 nNeededPixel = nEngineWidth;
    3615           0 :             nNeededPixel += nLeftM + nRightM;
    3616             : 
    3617             :             //  No clip marks if "###" doesn't fit (same as in DrawStrings)
    3618             :         }
    3619             :     }
    3620             : 
    3621          69 :     long nStartX = aAreaParam.maAlignRect.Left();
    3622          69 :     const long nStartY = aAreaParam.maAlignRect.Top();
    3623          69 :     const long nCellWidth = aAreaParam.maAlignRect.GetWidth();
    3624          69 :     const long nOutWidth = nCellWidth - 1 - nLeftM - nRightM;
    3625          69 :     const long nOutHeight = aAreaParam.maAlignRect.GetHeight() - nTopM - nBottomM;
    3626             : 
    3627          69 :     if (rParam.mbBreak)
    3628             :     {
    3629             :         //  text with automatic breaks is aligned only within the
    3630             :         //  edit engine's paper size, the output of the whole area
    3631             :         //  is always left-aligned
    3632             : 
    3633          69 :         nStartX += nLeftM;
    3634          69 :         if (rParam.meHorJust == SVX_HOR_JUSTIFY_BLOCK)
    3635          12 :             nStartX += aPaperSize.Height();
    3636             :     }
    3637             :     else
    3638             :     {
    3639           0 :         if ( eOutHorJust == SVX_HOR_JUSTIFY_RIGHT )
    3640           0 :             nStartX -= nNeededPixel - nCellWidth + nRightM + 1;
    3641           0 :         else if ( eOutHorJust == SVX_HOR_JUSTIFY_CENTER )
    3642           0 :             nStartX -= ( nNeededPixel - nCellWidth + nRightM + 1 - nLeftM ) / 2;
    3643             :         else
    3644           0 :             nStartX += nLeftM;
    3645             :     }
    3646             : 
    3647          69 :     const bool bOutside = (aAreaParam.maClipRect.Right() < nScrX || aAreaParam.maClipRect.Left() >= nScrX + nScrW);
    3648          69 :     if (bOutside)
    3649           0 :         return;
    3650             : 
    3651             :     // output area, excluding margins, in logical units
    3652             :     const Size& aCellSize = rParam.mbPixelToLogic
    3653         276 :         ? mpRefDevice->PixelToLogic( Size( nOutWidth, nOutHeight ) )
    3654         207 :         : Size( nOutWidth, nOutHeight );
    3655             : 
    3656          69 :     const bool bClip = Clip( rParam, aCellSize, aAreaParam, nEngineHeight, bWrapFields );
    3657             : 
    3658          69 :     Point aLogicStart(nStartX, nStartY);
    3659          69 :     rParam.calcStartPosForVertical(aLogicStart, aCellSize.Width(), nEngineWidth, nTopM, mpRefDevice);
    3660             : 
    3661          69 :     Point aURLStart = aLogicStart;      // copy before modifying for orientation
    3662             : 
    3663          69 :     if (rParam.meHorJust != SVX_HOR_JUSTIFY_BLOCK)
    3664             :     {
    3665          57 :         aLogicStart.X() += nEngineWidth;
    3666          57 :         if (!rParam.mbBreak)
    3667             :         {
    3668             :             // Set the paper width to text size.
    3669           0 :             Size aPSize = rParam.mpEngine->GetPaperSize();
    3670           0 :             aPSize.Width() = rParam.mpEngine->CalcTextWidth();
    3671           0 :             rParam.mpEngine->SetPaperSize(aPSize);
    3672             : 
    3673           0 :             long nGap = 0;
    3674           0 :             long nTopOffset = 0; // offset by top margin
    3675           0 :             if (rParam.mbPixelToLogic)
    3676             :             {
    3677           0 :                 nGap = mpRefDevice->LogicToPixel(aPSize).Width() - mpRefDevice->LogicToPixel(aCellSize).Height();
    3678           0 :                 nGap = mpRefDevice->PixelToLogic(Size(0, nGap)).Height();
    3679           0 :                 nTopOffset = mpRefDevice->PixelToLogic(Size(0,nTopM)).Height();
    3680             :             }
    3681             :             else
    3682             :             {
    3683           0 :                 nGap = aPSize.Width() - aCellSize.Height();
    3684           0 :                 nTopOffset = nTopM;
    3685             :             }
    3686           0 :             aLogicStart.Y() += nTopOffset;
    3687             : 
    3688           0 :             switch (rParam.meVerJust)
    3689             :             {
    3690             :                 case SVX_VER_JUSTIFY_STANDARD:
    3691             :                 case SVX_VER_JUSTIFY_BOTTOM:
    3692             :                     // align to bottom
    3693           0 :                     aLogicStart.Y() -= nGap;
    3694           0 :                 break;
    3695             :                 case SVX_VER_JUSTIFY_CENTER:
    3696             :                     // center it.
    3697           0 :                     aLogicStart.Y() -= nGap / 2;
    3698           0 :                 break;
    3699             :                 case SVX_VER_JUSTIFY_BLOCK:
    3700             :                 case SVX_VER_JUSTIFY_TOP:
    3701             :                     // align to top (do nothing)
    3702             :                 default:
    3703             :                     ;
    3704             :             }
    3705             :         }
    3706             :     }
    3707             : 
    3708          69 :     rParam.adjustForRTL();
    3709             : 
    3710             :     // bMoveClipped handling has been replaced by complete alignment
    3711             :     // handling (also extending to the left).
    3712             : 
    3713          69 :     rParam.mpEngine->Draw(mpDev, aLogicStart, 2700);
    3714             : 
    3715          69 :     if (bClip)
    3716             :     {
    3717           0 :         if (bMetaFile)
    3718           0 :             mpDev->Pop();
    3719             :         else
    3720           0 :             mpDev->SetClipRegion();
    3721             :     }
    3722             : 
    3723          69 :     rParam.adjustForHyperlinkInPDF(aURLStart, mpDev);
    3724             : }
    3725             : 
    3726           0 : void ScOutputData::DrawEditStacked(DrawEditParam& rParam)
    3727             : {
    3728             :     OSL_ASSERT(rParam.meHorJust != SVX_HOR_JUSTIFY_REPEAT);
    3729           0 :     Size aRefOne = mpRefDevice->PixelToLogic(Size(1,1));
    3730             : 
    3731           0 :     bool bRepeat = (rParam.meHorJust == SVX_HOR_JUSTIFY_REPEAT && !rParam.mbBreak);
    3732           0 :     bool bShrink = !rParam.mbBreak && !bRepeat && lcl_GetBoolValue(*rParam.mpPattern, ATTR_SHRINKTOFIT, rParam.mpCondSet);
    3733             : 
    3734             :     rParam.mbAsianVertical =
    3735           0 :         lcl_GetBoolValue(*rParam.mpPattern, ATTR_VERTICAL_ASIAN, rParam.mpCondSet);
    3736             : 
    3737           0 :     if ( rParam.mbAsianVertical )
    3738             :     {
    3739             :         // in asian mode, use EditEngine::SetVertical instead of EE_CNTRL_ONECHARPERLINE
    3740           0 :         rParam.meOrient = SVX_ORIENTATION_STANDARD;
    3741           0 :         DrawEditAsianVertical(rParam);
    3742           0 :         return;
    3743             :     }
    3744             : 
    3745             :     SvxCellHorJustify eOutHorJust =
    3746           0 :         ( rParam.meHorJust != SVX_HOR_JUSTIFY_STANDARD ) ? rParam.meHorJust :
    3747           0 :         ( rParam.mbCellIsValue ? SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_LEFT );
    3748             : 
    3749           0 :     if ( eOutHorJust == SVX_HOR_JUSTIFY_BLOCK || eOutHorJust == SVX_HOR_JUSTIFY_REPEAT )
    3750           0 :         eOutHorJust = SVX_HOR_JUSTIFY_LEFT;     // repeat is not yet implemented
    3751             : 
    3752             :     //! mirror margin values for RTL?
    3753             :     //! move margin down to after final GetOutputArea call
    3754             :     long nTopM, nLeftM, nBottomM, nRightM;
    3755           0 :     rParam.calcMargins(nTopM, nLeftM, nBottomM, nRightM, mnPPTX, mnPPTY);
    3756             : 
    3757           0 :     SCCOL nXForPos = rParam.mnX;
    3758           0 :     if ( nXForPos < nX1 )
    3759             :     {
    3760           0 :         nXForPos = nX1;
    3761           0 :         rParam.mnPosX = rParam.mnInitPosX;
    3762             :     }
    3763           0 :     SCSIZE nArrYForPos = rParam.mnArrY;
    3764           0 :     if ( nArrYForPos < 1 )
    3765             :     {
    3766           0 :         nArrYForPos = 1;
    3767           0 :         rParam.mnPosY = nScrY;
    3768             :     }
    3769             : 
    3770           0 :     OutputAreaParam aAreaParam;
    3771             : 
    3772             :     //
    3773             :     //  Initial page size - large for normal text, cell size for automatic line breaks
    3774             :     //
    3775             : 
    3776           0 :     Size aPaperSize = Size( 1000000, 1000000 );
    3777             :     //  call GetOutputArea with nNeeded=0, to get only the cell width
    3778             : 
    3779             :     //! handle nArrY == 0
    3780             :     GetOutputArea( nXForPos, nArrYForPos, rParam.mnPosX, rParam.mnPosY, rParam.mnCellX, rParam.mnCellY, 0,
    3781           0 :                    *rParam.mpPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
    3782           0 :                    rParam.mbCellIsValue, true, false, aAreaParam );
    3783             : 
    3784             :     //! special ScEditUtil handling if formatting for printer
    3785           0 :     rParam.calcPaperSize(aPaperSize, aAreaParam.maAlignRect, mnPPTX, mnPPTY);
    3786             : 
    3787           0 :     if (rParam.mbPixelToLogic)
    3788             :     {
    3789           0 :         Size aLogicSize = mpRefDevice->PixelToLogic(aPaperSize);
    3790           0 :         if ( rParam.mbBreak && mpRefDevice != pFmtDevice )
    3791             :         {
    3792             :             // #i85342# screen display and formatting for printer,
    3793             :             // use same GetEditArea call as in ScViewData::SetEditEngine
    3794             : 
    3795           0 :             Fraction aFract(1,1);
    3796             :             Rectangle aUtilRect = ScEditUtil( mpDoc, rParam.mnCellX, rParam.mnCellY, nTab, Point(0,0), pFmtDevice,
    3797           0 :                 HMM_PER_TWIPS, HMM_PER_TWIPS, aFract, aFract ).GetEditArea( rParam.mpPattern, false );
    3798           0 :             aLogicSize.Width() = aUtilRect.GetWidth();
    3799             :         }
    3800           0 :         rParam.mpEngine->SetPaperSize(aLogicSize);
    3801             :     }
    3802             :     else
    3803           0 :         rParam.mpEngine->SetPaperSize(aPaperSize);
    3804             : 
    3805             :     //
    3806             :     //  Fill the EditEngine (cell attributes and text)
    3807             :     //
    3808             : 
    3809           0 :     rParam.setPatternToEngine(mbUseStyleColor);
    3810           0 :     rParam.setAlignmentToEngine();
    3811             : 
    3812             :     //  Read content from cell
    3813             : 
    3814           0 :     bool bWrapFields = false;
    3815           0 :     if (!rParam.readCellContent(mpDoc, mbShowNullValues, mbShowFormulas, mbSyntaxMode, mbUseStyleColor, mbForceAutoColor, bWrapFields))
    3816             :         // Failed to read cell content.  Bail out.
    3817           0 :         return;
    3818             : 
    3819           0 :     if ( mbSyntaxMode )
    3820           0 :         SetEditSyntaxColor( *rParam.mpEngine, rParam.maCell );
    3821           0 :     else if ( mbUseStyleColor && mbForceAutoColor )
    3822           0 :         lcl_SetEditColor( *rParam.mpEngine, COL_AUTO );     //! or have a flag at EditEngine
    3823             : 
    3824           0 :     rParam.mpEngine->SetUpdateMode( true );     // after SetText, before CalcTextWidth/GetTextHeight
    3825             : 
    3826             :     //
    3827             :     //  Get final output area using the calculated width
    3828             :     //
    3829             : 
    3830             :     long nEngineWidth, nEngineHeight;
    3831           0 :     rParam.getEngineSize(rParam.mpEngine, nEngineWidth, nEngineHeight);
    3832             : 
    3833           0 :     long nNeededPixel = nEngineWidth;
    3834           0 :     if (rParam.mbPixelToLogic)
    3835           0 :         nNeededPixel = mpRefDevice->LogicToPixel(Size(nNeededPixel,0)).Width();
    3836           0 :     nNeededPixel += nLeftM + nRightM;
    3837             : 
    3838           0 :     if (bShrink)
    3839             :     {
    3840             :         // for break, the first GetOutputArea call is sufficient
    3841             :         GetOutputArea( nXForPos, nArrYForPos, rParam.mnPosX, rParam.mnPosY, rParam.mnCellX, rParam.mnCellY, nNeededPixel,
    3842           0 :                        *rParam.mpPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
    3843           0 :                        true, false, false, aAreaParam );
    3844             : 
    3845             :         ShrinkEditEngine( *rParam.mpEngine, aAreaParam.maAlignRect,
    3846             :             nLeftM, nTopM, nRightM, nBottomM, true,
    3847           0 :             sal::static_int_cast<sal_uInt16>(rParam.meOrient), 0, rParam.mbPixelToLogic,
    3848             :             nEngineWidth, nEngineHeight, nNeededPixel,
    3849           0 :             aAreaParam.mbLeftClip, aAreaParam.mbRightClip );
    3850             : 
    3851           0 :         if ( bRepeat && !aAreaParam.mbLeftClip && !aAreaParam.mbRightClip && rParam.mpEngine->GetParagraphCount() == 1 )
    3852             :         {
    3853             :             // First check if twice the space for the formatted text is available
    3854             :             // (otherwise just keep it unchanged).
    3855             : 
    3856           0 :             long nFormatted = nNeededPixel - nLeftM - nRightM;      // without margin
    3857           0 :             long nAvailable = aAreaParam.maAlignRect.GetWidth() - nLeftM - nRightM;
    3858           0 :             if ( nAvailable >= 2 * nFormatted )
    3859             :             {
    3860             :                 // "repeat" is handled with unformatted text (for performance reasons)
    3861           0 :                 String aCellStr = rParam.mpEngine->GetText();
    3862           0 :                 rParam.mpEngine->SetText( aCellStr );
    3863             : 
    3864           0 :                 long nRepeatSize = (long) rParam.mpEngine->CalcTextWidth();
    3865           0 :                 if (rParam.mbPixelToLogic)
    3866           0 :                     nRepeatSize = mpRefDevice->LogicToPixel(Size(nRepeatSize,0)).Width();
    3867           0 :                 if ( pFmtDevice != mpRefDevice )
    3868           0 :                     ++nRepeatSize;
    3869           0 :                 if ( nRepeatSize > 0 )
    3870             :                 {
    3871           0 :                     long nRepeatCount = nAvailable / nRepeatSize;
    3872           0 :                     if ( nRepeatCount > 1 )
    3873             :                     {
    3874           0 :                         String aRepeated = aCellStr;
    3875           0 :                         for ( long nRepeat = 1; nRepeat < nRepeatCount; nRepeat++ )
    3876           0 :                             aRepeated.Append( aCellStr );
    3877           0 :                         rParam.mpEngine->SetText( aRepeated );
    3878             : 
    3879           0 :                         nEngineHeight = rParam.mpEngine->GetTextHeight();
    3880           0 :                         nEngineWidth = (long) rParam.mpEngine->CalcTextWidth();
    3881           0 :                         if (rParam.mbPixelToLogic)
    3882           0 :                             nNeededPixel = mpRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
    3883             :                         else
    3884           0 :                             nNeededPixel = nEngineWidth;
    3885           0 :                         nNeededPixel += nLeftM + nRightM;
    3886             :                     }
    3887           0 :                 }
    3888             :             }
    3889             :         }
    3890             : 
    3891           0 :         if ( rParam.mbCellIsValue && ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) )
    3892             :         {
    3893           0 :             rParam.mpEngine->SetText(OUString("###"));
    3894           0 :             nEngineWidth = (long) rParam.mpEngine->CalcTextWidth();
    3895           0 :             if (rParam.mbPixelToLogic)
    3896           0 :                 nNeededPixel = mpRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
    3897             :             else
    3898           0 :                 nNeededPixel = nEngineWidth;
    3899           0 :             nNeededPixel += nLeftM + nRightM;
    3900             : 
    3901             :             //  No clip marks if "###" doesn't fit (same as in DrawStrings)
    3902             :         }
    3903             : 
    3904           0 :         if ( eOutHorJust != SVX_HOR_JUSTIFY_LEFT )
    3905             :         {
    3906           0 :             aPaperSize.Width() = nNeededPixel + 1;
    3907           0 :             if (rParam.mbPixelToLogic)
    3908           0 :                 rParam.mpEngine->SetPaperSize(mpRefDevice->PixelToLogic(aPaperSize));
    3909             :             else
    3910           0 :                 rParam.mpEngine->SetPaperSize(aPaperSize);
    3911             :         }
    3912             :     }
    3913             : 
    3914           0 :     long nStartX = aAreaParam.maAlignRect.Left();
    3915           0 :     long nStartY = aAreaParam.maAlignRect.Top();
    3916           0 :     long nCellWidth = aAreaParam.maAlignRect.GetWidth();
    3917           0 :     long nOutWidth = nCellWidth - 1 - nLeftM - nRightM;
    3918           0 :     long nOutHeight = aAreaParam.maAlignRect.GetHeight() - nTopM - nBottomM;
    3919             : 
    3920           0 :     if (rParam.mbBreak)
    3921             :     {
    3922             :         //  text with automatic breaks is aligned only within the
    3923             :         //  edit engine's paper size, the output of the whole area
    3924             :         //  is always left-aligned
    3925             : 
    3926           0 :         nStartX += nLeftM;
    3927             :     }
    3928             :     else
    3929             :     {
    3930           0 :         if ( eOutHorJust == SVX_HOR_JUSTIFY_RIGHT )
    3931           0 :             nStartX -= nNeededPixel - nCellWidth + nRightM + 1;
    3932           0 :         else if ( eOutHorJust == SVX_HOR_JUSTIFY_CENTER )
    3933           0 :             nStartX -= ( nNeededPixel - nCellWidth + nRightM + 1 - nLeftM ) / 2;
    3934             :         else
    3935           0 :             nStartX += nLeftM;
    3936             :     }
    3937             : 
    3938           0 :     bool bOutside = (aAreaParam.maClipRect.Right() < nScrX || aAreaParam.maClipRect.Left() >= nScrX + nScrW);
    3939           0 :     if (bOutside)
    3940           0 :         return;
    3941             : 
    3942           0 :     if ( aAreaParam.maClipRect.Left() < nScrX )
    3943             :     {
    3944           0 :         aAreaParam.maClipRect.Left() = nScrX;
    3945           0 :         aAreaParam.mbLeftClip = true;
    3946             :     }
    3947           0 :     if ( aAreaParam.maClipRect.Right() > nScrX + nScrW )
    3948             :     {
    3949           0 :         aAreaParam.maClipRect.Right() = nScrX + nScrW;          //! minus one?
    3950           0 :         aAreaParam.mbRightClip = true;
    3951             :     }
    3952             : 
    3953           0 :     bool bClip = aAreaParam.mbLeftClip || aAreaParam.mbRightClip;
    3954           0 :     bool bSimClip = false;
    3955             : 
    3956           0 :     if ( bWrapFields )
    3957             :     {
    3958             :         //  Fields in a cell with automatic breaks: clip to cell width
    3959           0 :         bClip = true;
    3960             :     }
    3961             : 
    3962           0 :     if ( aAreaParam.maClipRect.Top() < nScrY )
    3963             :     {
    3964           0 :         aAreaParam.maClipRect.Top() = nScrY;
    3965           0 :         bClip = true;
    3966             :     }
    3967           0 :     if ( aAreaParam.maClipRect.Bottom() > nScrY + nScrH )
    3968             :     {
    3969           0 :         aAreaParam.maClipRect.Bottom() = nScrY + nScrH;     //! minus one?
    3970           0 :         bClip = true;
    3971             :     }
    3972             : 
    3973           0 :     Size aCellSize;         // output area, excluding margins, in logical units
    3974           0 :     if (rParam.mbPixelToLogic)
    3975           0 :         aCellSize = mpRefDevice->PixelToLogic( Size( nOutWidth, nOutHeight ) );
    3976             :     else
    3977           0 :         aCellSize = Size( nOutWidth, nOutHeight );
    3978             : 
    3979           0 :     if ( nEngineHeight >= aCellSize.Height() + aRefOne.Height() )
    3980             :     {
    3981             :         const ScMergeAttr* pMerge =
    3982           0 :                 (ScMergeAttr*)&rParam.mpPattern->GetItem(ATTR_MERGE);
    3983           0 :         bool bMerged = pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1;
    3984             : 
    3985             :         //  Don't clip for text height when printing rows with optimal height,
    3986             :         //  except when font size is from conditional formatting.
    3987             :         //! Allow clipping when vertically merged?
    3988           0 :         if ( eType != OUTTYPE_PRINTER ||
    3989           0 :             ( mpDoc->GetRowFlags( rParam.mnCellY, nTab ) & CR_MANUALSIZE ) ||
    3990           0 :             ( rParam.mpCondSet && SFX_ITEM_SET ==
    3991           0 :                 rParam.mpCondSet->GetItemState(ATTR_FONT_HEIGHT, true) ) )
    3992           0 :             bClip = true;
    3993             :         else
    3994           0 :             bSimClip = true;
    3995             : 
    3996             :         //  Show clip marks if height is at least 5pt too small and
    3997             :         //  there are several lines of text.
    3998             :         //  Not for asian vertical text, because that would interfere
    3999             :         //  with the default right position of the text.
    4000             :         //  Only with automatic line breaks, to avoid having to find
    4001             :         //  the cells with the horizontal end of the text again.
    4002           0 :         if ( nEngineHeight - aCellSize.Height() > 100 &&
    4003           0 :              rParam.mbBreak && bMarkClipped &&
    4004           0 :              ( rParam.mpEngine->GetParagraphCount() > 1 || rParam.mpEngine->GetLineCount(0) > 1 ) )
    4005             :         {
    4006           0 :             CellInfo* pClipMarkCell = NULL;
    4007           0 :             if ( bMerged )
    4008             :             {
    4009             :                 //  anywhere in the merged area...
    4010           0 :                 SCCOL nClipX = ( rParam.mnX < nX1 ) ? nX1 : rParam.mnX;
    4011           0 :                 pClipMarkCell = &pRowInfo[(rParam.mnArrY != 0) ? rParam.mnArrY : 1].pCellInfo[nClipX+1];
    4012             :             }
    4013             :             else
    4014           0 :                 pClipMarkCell = &rParam.mpThisRowInfo->pCellInfo[rParam.mnX+1];
    4015             : 
    4016           0 :             pClipMarkCell->nClipMark |= SC_CLIPMARK_RIGHT;      //! also allow left?
    4017           0 :             bAnyClipped = true;
    4018             : 
    4019           0 :             long nMarkPixel = (long)( SC_CLIPMARK_SIZE * mnPPTX );
    4020           0 :             if ( aAreaParam.maClipRect.Right() - nMarkPixel > aAreaParam.maClipRect.Left() )
    4021           0 :                 aAreaParam.maClipRect.Right() -= nMarkPixel;
    4022             :         }
    4023             :     }
    4024             : 
    4025           0 :     Rectangle aLogicClip;
    4026           0 :     if (bClip || bSimClip)
    4027             :     {
    4028             :         // Clip marks are already handled in GetOutputArea
    4029             : 
    4030           0 :         if (rParam.mbPixelToLogic)
    4031           0 :             aLogicClip = mpRefDevice->PixelToLogic( aAreaParam.maClipRect );
    4032             :         else
    4033           0 :             aLogicClip = aAreaParam.maClipRect;
    4034             : 
    4035           0 :         if (bClip)  // bei bSimClip nur aClipRect initialisieren
    4036             :         {
    4037           0 :             if (bMetaFile)
    4038             :             {
    4039           0 :                 mpDev->Push();
    4040           0 :                 mpDev->IntersectClipRegion( aLogicClip );
    4041             :             }
    4042             :             else
    4043           0 :                 mpDev->SetClipRegion( Region( aLogicClip ) );
    4044             :         }
    4045             :     }
    4046             : 
    4047           0 :     Point aLogicStart;
    4048           0 :     if (rParam.mbPixelToLogic)
    4049           0 :         aLogicStart = mpRefDevice->PixelToLogic( Point(nStartX,nStartY) );
    4050             :     else
    4051           0 :         aLogicStart = Point(nStartX, nStartY);
    4052             : 
    4053           0 :     if (rParam.meVerJust==SVX_VER_JUSTIFY_BOTTOM ||
    4054           0 :         rParam.meVerJust==SVX_VER_JUSTIFY_STANDARD)
    4055             :     {
    4056             :         //! if pRefDevice != pFmtDevice, keep heights in logic units,
    4057             :         //! only converting margin?
    4058             : 
    4059           0 :         if (rParam.mbPixelToLogic)
    4060           0 :             aLogicStart.Y() += mpRefDevice->PixelToLogic( Size(0, nTopM +
    4061           0 :                             mpRefDevice->LogicToPixel(aCellSize).Height() -
    4062           0 :                             mpRefDevice->LogicToPixel(Size(0,nEngineHeight)).Height()
    4063           0 :                             )).Height();
    4064             :         else
    4065           0 :             aLogicStart.Y() += nTopM + aCellSize.Height() - nEngineHeight;
    4066             :     }
    4067           0 :     else if (rParam.meVerJust==SVX_VER_JUSTIFY_CENTER)
    4068             :     {
    4069           0 :         if (rParam.mbPixelToLogic)
    4070           0 :             aLogicStart.Y() += mpRefDevice->PixelToLogic( Size(0, nTopM + (
    4071           0 :                             mpRefDevice->LogicToPixel(aCellSize).Height() -
    4072           0 :                             mpRefDevice->LogicToPixel(Size(0,nEngineHeight)).Height() )
    4073           0 :                             / 2)).Height();
    4074             :         else
    4075           0 :             aLogicStart.Y() += nTopM + (aCellSize.Height() - nEngineHeight) / 2;
    4076             :     }
    4077             :     else        // top
    4078             :     {
    4079           0 :         if (rParam.mbPixelToLogic)
    4080           0 :             aLogicStart.Y() += mpRefDevice->PixelToLogic(Size(0,nTopM)).Height();
    4081             :         else
    4082           0 :             aLogicStart.Y() += nTopM;
    4083             :     }
    4084             : 
    4085           0 :     Point aURLStart = aLogicStart;      // copy before modifying for orientation
    4086             : 
    4087           0 :     Size aPaperLogic = rParam.mpEngine->GetPaperSize();
    4088           0 :     aPaperLogic.Width() = nEngineWidth;
    4089           0 :     rParam.mpEngine->SetPaperSize(aPaperLogic);
    4090             : 
    4091           0 :     rParam.adjustForRTL();
    4092             : 
    4093             :     // bMoveClipped handling has been replaced by complete alignment
    4094             :     // handling (also extending to the left).
    4095             : 
    4096           0 :     if (bSimClip)
    4097             :     {
    4098             :         //  kein hartes Clipping, aber nur die betroffenen
    4099             :         //  Zeilen ausgeben
    4100             : 
    4101           0 :         Point aDocStart = aLogicClip.TopLeft();
    4102           0 :         aDocStart -= aLogicStart;
    4103           0 :         rParam.mpEngine->Draw( mpDev, aLogicClip, aDocStart, false );
    4104             :     }
    4105             :     else
    4106             :     {
    4107           0 :         rParam.mpEngine->Draw( mpDev, aLogicStart, 0 );
    4108             :     }
    4109             : 
    4110           0 :     if (bClip)
    4111             :     {
    4112           0 :         if (bMetaFile)
    4113           0 :             mpDev->Pop();
    4114             :         else
    4115           0 :             mpDev->SetClipRegion();
    4116             :     }
    4117             : 
    4118           0 :     rParam.adjustForHyperlinkInPDF(aURLStart, mpDev);
    4119             : }
    4120             : 
    4121           0 : void ScOutputData::DrawEditAsianVertical(DrawEditParam& rParam)
    4122             : {
    4123             :     // When in asian vertical orientation, the orientation value is STANDARD,
    4124             :     // and the asian vertical boolean is true.
    4125             :     OSL_ASSERT(rParam.meOrient == SVX_ORIENTATION_STANDARD);
    4126             :     OSL_ASSERT(rParam.mbAsianVertical);
    4127             :     OSL_ASSERT(rParam.meHorJust != SVX_HOR_JUSTIFY_REPEAT);
    4128             : 
    4129           0 :     Size aRefOne = mpRefDevice->PixelToLogic(Size(1,1));
    4130             : 
    4131           0 :     bool bHidden = false;
    4132           0 :     bool bRepeat = false;
    4133           0 :     bool bShrink = !rParam.mbBreak && !bRepeat && lcl_GetBoolValue(*rParam.mpPattern, ATTR_SHRINKTOFIT, rParam.mpCondSet);
    4134           0 :     long nAttrRotate = lcl_GetValue<SfxInt32Item, long>(*rParam.mpPattern, ATTR_ROTATE_VALUE, rParam.mpCondSet);
    4135             : 
    4136           0 :     if (nAttrRotate)
    4137             :     {
    4138             :         //! Flag setzen, um die Zelle in DrawRotated wiederzufinden ?
    4139             :         //! (oder Flag schon bei DrawBackground, dann hier keine Abfrage)
    4140           0 :         bHidden = true;     // gedreht wird getrennt ausgegeben
    4141             :     }
    4142             : 
    4143             :     // default alignment for asian vertical mode is top-right
    4144           0 :     if ( rParam.meHorJust == SVX_HOR_JUSTIFY_STANDARD )
    4145           0 :         rParam.meHorJust = SVX_HOR_JUSTIFY_RIGHT;
    4146             : 
    4147             :     SvxCellHorJustify eOutHorJust =
    4148           0 :         ( rParam.meHorJust != SVX_HOR_JUSTIFY_STANDARD ) ? rParam.meHorJust :
    4149           0 :         ( rParam.mbCellIsValue ? SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_LEFT );
    4150             : 
    4151           0 :     if ( eOutHorJust == SVX_HOR_JUSTIFY_BLOCK || eOutHorJust == SVX_HOR_JUSTIFY_REPEAT )
    4152           0 :         eOutHorJust = SVX_HOR_JUSTIFY_LEFT;     // repeat is not yet implemented
    4153             : 
    4154           0 :     if (bHidden)
    4155           0 :         return;
    4156             : 
    4157             :     //! mirror margin values for RTL?
    4158             :     //! move margin down to after final GetOutputArea call
    4159             :     long nTopM, nLeftM, nBottomM, nRightM;
    4160           0 :     rParam.calcMargins(nTopM, nLeftM, nBottomM, nRightM, mnPPTX, mnPPTY);
    4161             : 
    4162           0 :     SCCOL nXForPos = rParam.mnX;
    4163           0 :     if ( nXForPos < nX1 )
    4164             :     {
    4165           0 :         nXForPos = nX1;
    4166           0 :         rParam.mnPosX = rParam.mnInitPosX;
    4167             :     }
    4168           0 :     SCSIZE nArrYForPos = rParam.mnArrY;
    4169           0 :     if ( nArrYForPos < 1 )
    4170             :     {
    4171           0 :         nArrYForPos = 1;
    4172           0 :         rParam.mnPosY = nScrY;
    4173             :     }
    4174             : 
    4175           0 :     OutputAreaParam aAreaParam;
    4176             : 
    4177             :     //
    4178             :     //  Initial page size - large for normal text, cell size for automatic line breaks
    4179             :     //
    4180             : 
    4181           0 :     Size aPaperSize = Size( 1000000, 1000000 );
    4182             :     //  call GetOutputArea with nNeeded=0, to get only the cell width
    4183             : 
    4184             :     //! handle nArrY == 0
    4185             :     GetOutputArea( nXForPos, nArrYForPos, rParam.mnPosX, rParam.mnPosY, rParam.mnCellX, rParam.mnCellY, 0,
    4186           0 :                    *rParam.mpPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
    4187           0 :                    rParam.mbCellIsValue, true, false, aAreaParam );
    4188             : 
    4189             :     //! special ScEditUtil handling if formatting for printer
    4190           0 :     rParam.calcPaperSize(aPaperSize, aAreaParam.maAlignRect, mnPPTX, mnPPTY);
    4191             : 
    4192           0 :     if (rParam.mbPixelToLogic)
    4193             :     {
    4194           0 :         Size aLogicSize = mpRefDevice->PixelToLogic(aPaperSize);
    4195           0 :         if ( rParam.mbBreak && !rParam.mbAsianVertical && mpRefDevice != pFmtDevice )
    4196             :         {
    4197             :             // #i85342# screen display and formatting for printer,
    4198             :             // use same GetEditArea call as in ScViewData::SetEditEngine
    4199             : 
    4200           0 :             Fraction aFract(1,1);
    4201             :             Rectangle aUtilRect = ScEditUtil( mpDoc, rParam.mnCellX, rParam.mnCellY, nTab, Point(0,0), pFmtDevice,
    4202           0 :                 HMM_PER_TWIPS, HMM_PER_TWIPS, aFract, aFract ).GetEditArea( rParam.mpPattern, false );
    4203           0 :             aLogicSize.Width() = aUtilRect.GetWidth();
    4204             :         }
    4205           0 :         rParam.mpEngine->SetPaperSize(aLogicSize);
    4206             :     }
    4207             :     else
    4208           0 :         rParam.mpEngine->SetPaperSize(aPaperSize);
    4209             : 
    4210             :     //
    4211             :     //  Fill the EditEngine (cell attributes and text)
    4212             :     //
    4213             : 
    4214             :     // default alignment for asian vertical mode is top-right
    4215           0 :     if ( rParam.meVerJust == SVX_VER_JUSTIFY_STANDARD )
    4216           0 :         rParam.meVerJust = SVX_VER_JUSTIFY_TOP;
    4217             : 
    4218           0 :     rParam.setPatternToEngine(mbUseStyleColor);
    4219           0 :     rParam.setAlignmentToEngine();
    4220             : 
    4221             :     //  Read content from cell
    4222             : 
    4223           0 :     bool bWrapFields = false;
    4224           0 :     if (!rParam.readCellContent(mpDoc, mbShowNullValues, mbShowFormulas, mbSyntaxMode, mbUseStyleColor, mbForceAutoColor, bWrapFields))
    4225             :         // Failed to read cell content.  Bail out.
    4226           0 :         return;
    4227             : 
    4228           0 :     if ( mbSyntaxMode )
    4229           0 :         SetEditSyntaxColor( *rParam.mpEngine, rParam.maCell );
    4230           0 :     else if ( mbUseStyleColor && mbForceAutoColor )
    4231           0 :         lcl_SetEditColor( *rParam.mpEngine, COL_AUTO );     //! or have a flag at EditEngine
    4232             : 
    4233           0 :     rParam.mpEngine->SetUpdateMode( true );     // after SetText, before CalcTextWidth/GetTextHeight
    4234             : 
    4235             :     //
    4236             :     //  Get final output area using the calculated width
    4237             :     //
    4238             : 
    4239             :     long nEngineWidth, nEngineHeight;
    4240           0 :     rParam.getEngineSize(rParam.mpEngine, nEngineWidth, nEngineHeight);
    4241             : 
    4242           0 :     long nNeededPixel = nEngineWidth;
    4243           0 :     if (rParam.mbPixelToLogic)
    4244           0 :         nNeededPixel = mpRefDevice->LogicToPixel(Size(nNeededPixel,0)).Width();
    4245           0 :     nNeededPixel += nLeftM + nRightM;
    4246             : 
    4247             :     // for break, the first GetOutputArea call is sufficient
    4248             :     GetOutputArea( nXForPos, nArrYForPos, rParam.mnPosX, rParam.mnPosY, rParam.mnCellX, rParam.mnCellY, nNeededPixel,
    4249           0 :                    *rParam.mpPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
    4250           0 :                    rParam.mbCellIsValue || bRepeat || bShrink, false, false, aAreaParam );
    4251             : 
    4252           0 :     if ( bShrink )
    4253             :     {
    4254             :         ShrinkEditEngine( *rParam.mpEngine, aAreaParam.maAlignRect,
    4255             :             nLeftM, nTopM, nRightM, nBottomM, false,
    4256           0 :             sal::static_int_cast<sal_uInt16>(rParam.meOrient), 0, rParam.mbPixelToLogic,
    4257             :             nEngineWidth, nEngineHeight, nNeededPixel,
    4258           0 :             aAreaParam.mbLeftClip, aAreaParam.mbRightClip );
    4259             :     }
    4260           0 :     if ( bRepeat && !aAreaParam.mbLeftClip && !aAreaParam.mbRightClip && rParam.mpEngine->GetParagraphCount() == 1 )
    4261             :     {
    4262             :         // First check if twice the space for the formatted text is available
    4263             :         // (otherwise just keep it unchanged).
    4264             : 
    4265           0 :         long nFormatted = nNeededPixel - nLeftM - nRightM;      // without margin
    4266           0 :         long nAvailable = aAreaParam.maAlignRect.GetWidth() - nLeftM - nRightM;
    4267           0 :         if ( nAvailable >= 2 * nFormatted )
    4268             :         {
    4269             :             // "repeat" is handled with unformatted text (for performance reasons)
    4270           0 :             String aCellStr = rParam.mpEngine->GetText();
    4271           0 :             rParam.mpEngine->SetText( aCellStr );
    4272             : 
    4273           0 :             long nRepeatSize = (long) rParam.mpEngine->CalcTextWidth();
    4274           0 :             if (rParam.mbPixelToLogic)
    4275           0 :                 nRepeatSize = mpRefDevice->LogicToPixel(Size(nRepeatSize,0)).Width();
    4276           0 :             if ( pFmtDevice != mpRefDevice )
    4277           0 :                 ++nRepeatSize;
    4278           0 :             if ( nRepeatSize > 0 )
    4279             :             {
    4280           0 :                 long nRepeatCount = nAvailable / nRepeatSize;
    4281           0 :                 if ( nRepeatCount > 1 )
    4282             :                 {
    4283           0 :                     String aRepeated = aCellStr;
    4284           0 :                     for ( long nRepeat = 1; nRepeat < nRepeatCount; nRepeat++ )
    4285           0 :                         aRepeated.Append( aCellStr );
    4286           0 :                     rParam.mpEngine->SetText( aRepeated );
    4287             : 
    4288           0 :                     nEngineHeight = rParam.mpEngine->GetTextHeight();
    4289           0 :                     nEngineWidth = (long) rParam.mpEngine->CalcTextWidth();
    4290           0 :                     if (rParam.mbPixelToLogic)
    4291           0 :                         nNeededPixel = mpRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
    4292             :                     else
    4293           0 :                         nNeededPixel = nEngineWidth;
    4294           0 :                     nNeededPixel += nLeftM + nRightM;
    4295             :                 }
    4296           0 :             }
    4297             :         }
    4298             :     }
    4299             : 
    4300           0 :     if ( rParam.mbCellIsValue && ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) )
    4301             :     {
    4302           0 :         rParam.mpEngine->SetText(OUString("###"));
    4303           0 :         nEngineWidth = (long) rParam.mpEngine->CalcTextWidth();
    4304           0 :         if (rParam.mbPixelToLogic)
    4305           0 :             nNeededPixel = mpRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
    4306             :         else
    4307           0 :             nNeededPixel = nEngineWidth;
    4308           0 :         nNeededPixel += nLeftM + nRightM;
    4309             : 
    4310             :         //  No clip marks if "###" doesn't fit (same as in DrawStrings)
    4311             :     }
    4312             : 
    4313           0 :     if (eOutHorJust != SVX_HOR_JUSTIFY_LEFT)
    4314             :     {
    4315           0 :         aPaperSize.Width() = nNeededPixel + 1;
    4316           0 :         if (rParam.mbPixelToLogic)
    4317           0 :             rParam.mpEngine->SetPaperSize(mpRefDevice->PixelToLogic(aPaperSize));
    4318             :         else
    4319           0 :             rParam.mpEngine->SetPaperSize(aPaperSize);
    4320             :     }
    4321             : 
    4322           0 :     long nStartX = aAreaParam.maAlignRect.Left();
    4323           0 :     long nStartY = aAreaParam.maAlignRect.Top();
    4324           0 :     long nCellWidth = aAreaParam.maAlignRect.GetWidth();
    4325           0 :     long nOutWidth = nCellWidth - 1 - nLeftM - nRightM;
    4326           0 :     long nOutHeight = aAreaParam.maAlignRect.GetHeight() - nTopM - nBottomM;
    4327             : 
    4328             :     //  text with automatic breaks is aligned only within the
    4329             :     //  edit engine's paper size, the output of the whole area
    4330             :     //  is always left-aligned
    4331             : 
    4332           0 :     nStartX += nLeftM;
    4333             : 
    4334           0 :     bool bOutside = (aAreaParam.maClipRect.Right() < nScrX || aAreaParam.maClipRect.Left() >= nScrX + nScrW);
    4335           0 :     if (bOutside)
    4336           0 :         return;
    4337             : 
    4338           0 :     if ( aAreaParam.maClipRect.Left() < nScrX )
    4339             :     {
    4340           0 :         aAreaParam.maClipRect.Left() = nScrX;
    4341           0 :         aAreaParam.mbLeftClip = true;
    4342             :     }
    4343           0 :     if ( aAreaParam.maClipRect.Right() > nScrX + nScrW )
    4344             :     {
    4345           0 :         aAreaParam.maClipRect.Right() = nScrX + nScrW;          //! minus one?
    4346           0 :         aAreaParam.mbRightClip = true;
    4347             :     }
    4348             : 
    4349           0 :     bool bClip = aAreaParam.mbLeftClip || aAreaParam.mbRightClip;
    4350           0 :     bool bSimClip = false;
    4351             : 
    4352           0 :     if ( bWrapFields )
    4353             :     {
    4354             :         //  Fields in a cell with automatic breaks: clip to cell width
    4355           0 :         bClip = true;
    4356             :     }
    4357             : 
    4358           0 :     if ( aAreaParam.maClipRect.Top() < nScrY )
    4359             :     {
    4360           0 :         aAreaParam.maClipRect.Top() = nScrY;
    4361           0 :         bClip = true;
    4362             :     }
    4363           0 :     if ( aAreaParam.maClipRect.Bottom() > nScrY + nScrH )
    4364             :     {
    4365           0 :         aAreaParam.maClipRect.Bottom() = nScrY + nScrH;     //! minus one?
    4366           0 :         bClip = true;
    4367             :     }
    4368             : 
    4369           0 :     Size aCellSize;         // output area, excluding margins, in logical units
    4370           0 :     if (rParam.mbPixelToLogic)
    4371           0 :         aCellSize = mpRefDevice->PixelToLogic( Size( nOutWidth, nOutHeight ) );
    4372             :     else
    4373           0 :         aCellSize = Size( nOutWidth, nOutHeight );
    4374             : 
    4375           0 :     if ( nEngineHeight >= aCellSize.Height() + aRefOne.Height() )
    4376             :     {
    4377             :         const ScMergeAttr* pMerge =
    4378           0 :                 (ScMergeAttr*)&rParam.mpPattern->GetItem(ATTR_MERGE);
    4379           0 :         bool bMerged = pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1;
    4380             : 
    4381             :         //  Don't clip for text height when printing rows with optimal height,
    4382             :         //  except when font size is from conditional formatting.
    4383             :         //! Allow clipping when vertically merged?
    4384           0 :         if ( eType != OUTTYPE_PRINTER ||
    4385           0 :             ( mpDoc->GetRowFlags( rParam.mnCellY, nTab ) & CR_MANUALSIZE ) ||
    4386           0 :             ( rParam.mpCondSet && SFX_ITEM_SET ==
    4387           0 :                 rParam.mpCondSet->GetItemState(ATTR_FONT_HEIGHT, true) ) )
    4388           0 :             bClip = true;
    4389             :         else
    4390           0 :             bSimClip = true;
    4391             : 
    4392             :         //  Show clip marks if height is at least 5pt too small and
    4393             :         //  there are several lines of text.
    4394             :         //  Not for asian vertical text, because that would interfere
    4395             :         //  with the default right position of the text.
    4396             :         //  Only with automatic line breaks, to avoid having to find
    4397             :         //  the cells with the horizontal end of the text again.
    4398           0 :         if ( nEngineHeight - aCellSize.Height() > 100 &&
    4399           0 :              ( rParam.mbBreak || rParam.meOrient == SVX_ORIENTATION_STACKED ) &&
    4400           0 :              !rParam.mbAsianVertical && bMarkClipped &&
    4401           0 :              ( rParam.mpEngine->GetParagraphCount() > 1 || rParam.mpEngine->GetLineCount(0) > 1 ) )
    4402             :         {
    4403           0 :             CellInfo* pClipMarkCell = NULL;
    4404           0 :             if ( bMerged )
    4405             :             {
    4406             :                 //  anywhere in the merged area...
    4407           0 :                 SCCOL nClipX = ( rParam.mnX < nX1 ) ? nX1 : rParam.mnX;
    4408           0 :                 pClipMarkCell = &pRowInfo[(rParam.mnArrY != 0) ? rParam.mnArrY : 1].pCellInfo[nClipX+1];
    4409             :             }
    4410             :             else
    4411           0 :                 pClipMarkCell = &rParam.mpThisRowInfo->pCellInfo[rParam.mnX+1];
    4412             : 
    4413           0 :             pClipMarkCell->nClipMark |= SC_CLIPMARK_RIGHT;      //! also allow left?
    4414           0 :             bAnyClipped = true;
    4415             : 
    4416           0 :             long nMarkPixel = (long)( SC_CLIPMARK_SIZE * mnPPTX );
    4417           0 :             if ( aAreaParam.maClipRect.Right() - nMarkPixel > aAreaParam.maClipRect.Left() )
    4418           0 :                 aAreaParam.maClipRect.Right() -= nMarkPixel;
    4419             :         }
    4420             :     }
    4421             : 
    4422           0 :     Rectangle aLogicClip;
    4423           0 :     if (bClip || bSimClip)
    4424             :     {
    4425             :         // Clip marks are already handled in GetOutputArea
    4426             : 
    4427           0 :         if (rParam.mbPixelToLogic)
    4428           0 :             aLogicClip = mpRefDevice->PixelToLogic( aAreaParam.maClipRect );
    4429             :         else
    4430           0 :             aLogicClip = aAreaParam.maClipRect;
    4431             : 
    4432           0 :         if (bClip)  // bei bSimClip nur aClipRect initialisieren
    4433             :         {
    4434           0 :             if (bMetaFile)
    4435             :             {
    4436           0 :                 mpDev->Push();
    4437           0 :                 mpDev->IntersectClipRegion( aLogicClip );
    4438             :             }
    4439             :             else
    4440           0 :                 mpDev->SetClipRegion( Region( aLogicClip ) );
    4441             :         }
    4442             :     }
    4443             : 
    4444           0 :     Point aLogicStart;
    4445           0 :     if (rParam.mbPixelToLogic)
    4446           0 :         aLogicStart = mpRefDevice->PixelToLogic( Point(nStartX,nStartY) );
    4447             :     else
    4448           0 :         aLogicStart = Point(nStartX, nStartY);
    4449             : 
    4450           0 :     long nAvailWidth = aCellSize.Width();
    4451             :     // space for AutoFilter is already handled in GetOutputArea
    4452             : 
    4453             :     //  horizontal alignment
    4454             : 
    4455           0 :     if (rParam.meHorJust==SVX_HOR_JUSTIFY_RIGHT)
    4456           0 :         aLogicStart.X() += nAvailWidth - nEngineWidth;
    4457           0 :     else if (rParam.meHorJust==SVX_HOR_JUSTIFY_CENTER)
    4458           0 :         aLogicStart.X() += (nAvailWidth - nEngineWidth) / 2;
    4459             : 
    4460             :     // paper size is subtracted below
    4461           0 :     aLogicStart.X() += nEngineWidth;
    4462             : 
    4463             :     // vertical adjustment is within the EditEngine
    4464           0 :     if (rParam.mbPixelToLogic)
    4465           0 :         aLogicStart.Y() += mpRefDevice->PixelToLogic(Size(0,nTopM)).Height();
    4466             :     else
    4467           0 :         aLogicStart.Y() += nTopM;
    4468             : 
    4469           0 :     Point aURLStart = aLogicStart;      // copy before modifying for orientation
    4470             : 
    4471           0 :     rParam.adjustForRTL();
    4472             : 
    4473             :     // bMoveClipped handling has been replaced by complete alignment
    4474             :     // handling (also extending to the left).
    4475             : 
    4476             :     //  with SetVertical, the start position is top left of
    4477             :     //  the whole output area, not the text itself
    4478           0 :     aLogicStart.X() -= rParam.mpEngine->GetPaperSize().Width();
    4479             : 
    4480           0 :     rParam.mpEngine->Draw(mpDev, aLogicStart, 0);
    4481             : 
    4482           0 :     if (bClip)
    4483             :     {
    4484           0 :         if (bMetaFile)
    4485           0 :             mpDev->Pop();
    4486             :         else
    4487           0 :             mpDev->SetClipRegion();
    4488             :     }
    4489             : 
    4490           0 :     rParam.adjustForHyperlinkInPDF(aURLStart, mpDev);
    4491             : }
    4492             : 
    4493        1179 : void ScOutputData::DrawEdit(sal_Bool bPixelToLogic)
    4494             : {
    4495        1179 :     ScFieldEditEngine* pEngine = NULL;
    4496        1179 :     bool bHyphenatorSet = false;
    4497        1179 :     const ScPatternAttr* pOldPattern = NULL;
    4498        1179 :     const SfxItemSet*    pOldCondSet = NULL;
    4499        1179 :     ScRefCellValue aCell;
    4500             : 
    4501        1179 :     long nInitPosX = nScrX;
    4502        1179 :     if ( bLayoutRTL )
    4503             :     {
    4504           1 :         nInitPosX += nMirrorW - 1;
    4505             :     }
    4506        1179 :     long nLayoutSign = bLayoutRTL ? -1 : 1;
    4507             : 
    4508             :     //! store nLastContentCol as member!
    4509        1179 :     SCCOL nLastContentCol = MAXCOL;
    4510        1179 :     if ( nX2 < MAXCOL )
    4511             :         nLastContentCol = sal::static_int_cast<SCCOL>(
    4512        1178 :             nLastContentCol - mpDoc->GetEmptyLinesInBlock( nX2+1, nY1, nTab, MAXCOL, nY2, nTab, DIR_RIGHT ) );
    4513             : 
    4514        1179 :     long nRowPosY = nScrY;
    4515       21037 :     for (SCSIZE nArrY=0; nArrY+1<nArrCount; nArrY++)            // 0 fuer Reste von zusammengefassten
    4516             :     {
    4517       19858 :         RowInfo* pThisRowInfo = &pRowInfo[nArrY];
    4518             : 
    4519       19858 :         if (nArrY==1) nRowPosY = nScrY;                         // vorher wird einzeln berechnet
    4520             : 
    4521       19858 :         if ( pThisRowInfo->bChanged || nArrY==0 )
    4522             :         {
    4523       19858 :             long nPosX = 0;
    4524      252104 :             for (SCCOL nX=0; nX<=nX2; nX++)                 // wegen Ueberhaengen
    4525             :             {
    4526      232246 :                 if (nX==nX1) nPosX = nInitPosX;                 // positions before nX1 are calculated individually
    4527             : 
    4528      232246 :                 CellInfo*   pInfo = &pThisRowInfo->pCellInfo[nX+1];
    4529      232246 :                 if (pInfo->bEditEngine)
    4530             :                 {
    4531         550 :                     SCROW nY = pThisRowInfo->nRowNo;
    4532             : 
    4533         550 :                     SCCOL nCellX = nX;                  // position where the cell really starts
    4534         550 :                     SCROW nCellY = nY;
    4535         550 :                     sal_Bool bDoCell = false;
    4536             : 
    4537         550 :                     long nPosY = nRowPosY;
    4538         550 :                     if ( nArrY == 0 )
    4539             :                     {
    4540           0 :                         nPosY = nScrY;
    4541           0 :                         nY = pRowInfo[1].nRowNo;
    4542             :                         SCCOL nOverX;                   // start of the merged cells
    4543             :                         SCROW nOverY;
    4544           0 :                         if (GetMergeOrigin( nX,nY, 1, nOverX,nOverY, sal_True ))
    4545             :                         {
    4546           0 :                             nCellX = nOverX;
    4547           0 :                             nCellY = nOverY;
    4548           0 :                             bDoCell = sal_True;
    4549             :                         }
    4550             :                     }
    4551         550 :                     else if ( nX == nX2 && pThisRowInfo->pCellInfo[nX+1].maCell.isEmpty() )
    4552             :                     {
    4553             :                         //  Rest of a long text further to the right?
    4554             : 
    4555           0 :                         SCCOL nTempX=nX;
    4556           0 :                         while (nTempX < nLastContentCol && IsEmptyCellText( pThisRowInfo, nTempX, nY ))
    4557           0 :                             ++nTempX;
    4558             : 
    4559           0 :                         if ( nTempX > nX &&
    4560           0 :                              !IsEmptyCellText( pThisRowInfo, nTempX, nY ) &&
    4561           0 :                              !mpDoc->HasAttrib( nTempX,nY,nTab, nX,nY,nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ) )
    4562             :                         {
    4563           0 :                             nCellX = nTempX;
    4564           0 :                             bDoCell = sal_True;
    4565             :                         }
    4566             :                     }
    4567             :                     else
    4568             :                     {
    4569         550 :                         bDoCell = sal_True;
    4570             :                     }
    4571             : 
    4572         550 :                     if ( bDoCell && bEditMode && nCellX == nEditCol && nCellY == nEditRow )
    4573           0 :                         bDoCell = false;
    4574             : 
    4575         550 :                     const ScPatternAttr* pPattern = NULL;
    4576         550 :                     const SfxItemSet* pCondSet = NULL;
    4577         550 :                     if (bDoCell)
    4578             :                     {
    4579        1100 :                         if ( nCellY == nY && nCellX >= nX1 && nCellX <= nX2 &&
    4580         550 :                              !mpDoc->ColHidden(nCellX, nTab) )
    4581             :                         {
    4582         550 :                             CellInfo& rCellInfo = pThisRowInfo->pCellInfo[nCellX+1];
    4583         550 :                             pPattern = rCellInfo.pPatternAttr;
    4584         550 :                             pCondSet = rCellInfo.pConditionSet;
    4585         550 :                             aCell = rCellInfo.maCell;
    4586             :                         }
    4587             :                         else        // get from document
    4588             :                         {
    4589           0 :                             pPattern = mpDoc->GetPattern( nCellX, nCellY, nTab );
    4590           0 :                             pCondSet = mpDoc->GetCondResult( nCellX, nCellY, nTab );
    4591           0 :                             GetVisibleCell( nCellX, nCellY, nTab, aCell );
    4592             :                         }
    4593         550 :                         if (aCell.isEmpty())
    4594           0 :                             bDoCell = false;
    4595             :                     }
    4596         550 :                     if (bDoCell)
    4597             :                     {
    4598         550 :                         SfxItemSet* pPreviewFontSet = mpDoc->GetPreviewFont( nCellX, nCellY, nTab );
    4599         550 :                         if (!pEngine)
    4600         182 :                             pEngine = CreateOutputEditEngine();
    4601             :                         else
    4602         368 :                             lcl_ClearEdit( *pEngine );      // also calls SetUpdateMode(sal_False)
    4603             : 
    4604             :                         // fdo#32530: Check if the first character is RTL.
    4605         550 :                         OUString aStr = mpDoc->GetString(nCellX, nCellY, nTab);
    4606             : 
    4607        1100 :                         DrawEditParam aParam(pPattern, pCondSet, lcl_SafeIsValue(aCell));
    4608         550 :                         aParam.mbPixelToLogic = bPixelToLogic;
    4609         550 :                         aParam.mbHyphenatorSet = bHyphenatorSet;
    4610         550 :                         aParam.mbRTL = beginsWithRTLCharacter(aStr);
    4611         550 :                         aParam.mpEngine = pEngine;
    4612         550 :                         aParam.maCell = aCell;
    4613         550 :                         aParam.mnArrY = nArrY;
    4614         550 :                         aParam.mnX = nX;
    4615         550 :                         aParam.mnY = nY;
    4616         550 :                         aParam.mnCellX = nCellX;
    4617         550 :                         aParam.mnCellY = nCellY;
    4618         550 :                         aParam.mnPosX = nPosX;
    4619         550 :                         aParam.mnPosY = nPosY;
    4620         550 :                         aParam.mnInitPosX = nInitPosX;
    4621         550 :                         aParam.mpPreviewFontSet = pPreviewFontSet;
    4622         550 :                         aParam.mpOldPattern = pOldPattern;
    4623         550 :                         aParam.mpOldCondSet = pOldCondSet;
    4624         550 :                         aParam.mpThisRowInfo = pThisRowInfo;
    4625         550 :                         if (aParam.meHorJust == SVX_HOR_JUSTIFY_REPEAT)
    4626             :                         {
    4627             :                             // ignore orientation/rotation if "repeat" is active
    4628           0 :                             aParam.meOrient = SVX_ORIENTATION_STANDARD;
    4629             :                         }
    4630         550 :                         switch (aParam.meOrient)
    4631             :                         {
    4632             :                             case SVX_ORIENTATION_BOTTOMTOP:
    4633           0 :                                 DrawEditBottomTop(aParam);
    4634           0 :                             break;
    4635             :                             case SVX_ORIENTATION_TOPBOTTOM:
    4636          69 :                                 DrawEditTopBottom(aParam);
    4637          69 :                             break;
    4638             :                             case SVX_ORIENTATION_STACKED:
    4639             :                                 // this can be vertically stacked or asian vertical.
    4640           0 :                                 DrawEditStacked(aParam);
    4641           0 :                             break;
    4642             :                             default:
    4643         481 :                                 DrawEditStandard(aParam);
    4644             :                         }
    4645             : 
    4646             :                         // Retrieve parameters for next iteration.
    4647         550 :                         pOldPattern = aParam.mpOldPattern;
    4648         550 :                         pOldCondSet = aParam.mpOldCondSet;
    4649        1100 :                         bHyphenatorSet = aParam.mbHyphenatorSet;
    4650             :                     }
    4651             :                 }
    4652      232246 :                 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
    4653             :             }
    4654             :         }
    4655       19858 :         nRowPosY += pRowInfo[nArrY].nHeight;
    4656             :     }
    4657             : 
    4658        1179 :     delete pEngine;
    4659             : 
    4660        1179 :     if (bAnyRotated)
    4661          69 :         DrawRotated(bPixelToLogic);     //! von aussen rufen ?
    4662        1179 : }
    4663             : 
    4664             : //  -------------------------------------------------------------------------------
    4665             : 
    4666          69 : void ScOutputData::DrawRotated(sal_Bool bPixelToLogic)
    4667             : {
    4668             :     //! nRotMax speichern
    4669          69 :     SCCOL nRotMax = nX2;
    4670         499 :     for (SCSIZE nRotY=0; nRotY<nArrCount; nRotY++)
    4671         430 :         if (pRowInfo[nRotY].nRotMaxCol != SC_ROTMAX_NONE && pRowInfo[nRotY].nRotMaxCol > nRotMax)
    4672           0 :             nRotMax = pRowInfo[nRotY].nRotMaxCol;
    4673             : 
    4674             : 
    4675          69 :     ScModule* pScMod = SC_MOD();
    4676          69 :     sal_Int32 nConfBackColor = pScMod->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor;
    4677         138 :     sal_Bool bCellContrast = mbUseStyleColor &&
    4678         138 :             Application::GetSettings().GetStyleSettings().GetHighContrastMode();
    4679             : 
    4680          69 :     ScFieldEditEngine* pEngine = NULL;
    4681          69 :     sal_Bool bHyphenatorSet = false;
    4682             :     const ScPatternAttr* pPattern;
    4683             :     const SfxItemSet*    pCondSet;
    4684          69 :     const ScPatternAttr* pOldPattern = NULL;
    4685          69 :     const SfxItemSet*    pOldCondSet = NULL;
    4686          69 :     ScRefCellValue aCell;
    4687             : 
    4688          69 :     long nInitPosX = nScrX;
    4689          69 :     if ( bLayoutRTL )
    4690             :     {
    4691           0 :         nInitPosX += nMirrorW - 1;
    4692             :     }
    4693          69 :     long nLayoutSign = bLayoutRTL ? -1 : 1;
    4694             : 
    4695          69 :     long nRowPosY = nScrY;
    4696         430 :     for (SCSIZE nArrY=0; nArrY+1<nArrCount; nArrY++)            // 0 fuer Reste von zusammengefassten
    4697             :     {
    4698         361 :         RowInfo* pThisRowInfo = &pRowInfo[nArrY];
    4699         361 :         long nCellHeight = (long) pThisRowInfo->nHeight;
    4700         361 :         if (nArrY==1) nRowPosY = nScrY;                         // vorher wird einzeln berechnet
    4701             : 
    4702         361 :         if ( ( pThisRowInfo->bChanged || nArrY==0 ) && pThisRowInfo->nRotMaxCol != SC_ROTMAX_NONE )
    4703             :         {
    4704         259 :             long nPosX = 0;
    4705        2849 :             for (SCCOL nX=0; nX<=nRotMax; nX++)
    4706             :             {
    4707        2590 :                 if (nX==nX1) nPosX = nInitPosX;                 // positions before nX1 are calculated individually
    4708             : 
    4709        2590 :                 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
    4710        2590 :                 if ( pInfo->nRotateDir != SC_ROTDIR_NONE )
    4711             :                 {
    4712        1030 :                     SCROW nY = pThisRowInfo->nRowNo;
    4713             : 
    4714        1030 :                     sal_Bool bHidden = false;
    4715        1030 :                     if (bEditMode)
    4716           0 :                         if ( nX == nEditCol && nY == nEditRow )
    4717           0 :                             bHidden = sal_True;
    4718             : 
    4719        1030 :                     if (!bHidden)
    4720             :                     {
    4721        1030 :                         if (!pEngine)
    4722          69 :                             pEngine = CreateOutputEditEngine();
    4723             :                         else
    4724         961 :                             lcl_ClearEdit( *pEngine );      // also calls SetUpdateMode(sal_False)
    4725             : 
    4726        1030 :                         long nPosY = nRowPosY;
    4727        1030 :                         sal_Bool bVisChanged = false;
    4728             : 
    4729             :                         //! Rest von zusammengefasster Zelle weiter oben funktioniert nicht!
    4730             : 
    4731        1030 :                         sal_Bool bFromDoc = false;
    4732        1030 :                         pPattern = pInfo->pPatternAttr;
    4733        1030 :                         pCondSet = pInfo->pConditionSet;
    4734        1030 :                         if (!pPattern)
    4735             :                         {
    4736           0 :                             pPattern = mpDoc->GetPattern( nX, nY, nTab );
    4737           0 :                             bFromDoc = sal_True;
    4738             :                         }
    4739        1030 :                         aCell = pInfo->maCell;
    4740        1030 :                         if (bFromDoc)
    4741           0 :                             pCondSet = mpDoc->GetCondResult( nX, nY, nTab );
    4742             : 
    4743        1030 :                         if (aCell.isEmpty() && nX>nX2)
    4744           0 :                             GetVisibleCell( nX, nY, nTab, aCell );
    4745             : 
    4746        1030 :                         if (aCell.isEmpty() || IsEmptyCellText(pThisRowInfo, nX, nY))
    4747         652 :                             bHidden = true;     // nRotateDir is also set without a cell
    4748             : 
    4749        1030 :                         long nCellWidth = (long) pRowInfo[0].pCellInfo[nX+1].nWidth;
    4750             : 
    4751             :                         SvxCellHorJustify eHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem&)
    4752        1030 :                                             pPattern->GetItem(ATTR_HOR_JUSTIFY, pCondSet)).GetValue();
    4753        1960 :                         sal_Bool bBreak = ( eHorJust == SVX_HOR_JUSTIFY_BLOCK ) ||
    4754        1960 :                                     ((const SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK, pCondSet)).GetValue();
    4755        1030 :                         sal_Bool bRepeat = ( eHorJust == SVX_HOR_JUSTIFY_REPEAT && !bBreak );
    4756        1354 :                         sal_Bool bShrink = !bBreak && !bRepeat && static_cast<const SfxBoolItem&>
    4757        1354 :                                         (pPattern->GetItem( ATTR_SHRINKTOFIT, pCondSet )).GetValue();
    4758        1030 :                         SvxCellOrientation eOrient = pPattern->GetCellOrientation( pCondSet );
    4759             : 
    4760             :                         const ScMergeAttr* pMerge =
    4761        1030 :                                 (ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE);
    4762        1030 :                         sal_Bool bMerged = pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1;
    4763             : 
    4764        1030 :                         long nStartX = nPosX;
    4765        1030 :                         long nStartY = nPosY;
    4766        1030 :                         if (nX<nX1)
    4767             :                         {
    4768           0 :                             if ((bBreak || eOrient!=SVX_ORIENTATION_STANDARD) && !bMerged)
    4769           0 :                                 bHidden = sal_True;
    4770             :                             else
    4771             :                             {
    4772           0 :                                 nStartX = nInitPosX;
    4773           0 :                                 SCCOL nCol = nX1;
    4774           0 :                                 while (nCol > nX)
    4775             :                                 {
    4776           0 :                                     --nCol;
    4777           0 :                                     nStartX -= nLayoutSign * (long) pRowInfo[0].pCellInfo[nCol+1].nWidth;
    4778             :                                 }
    4779             :                             }
    4780             :                         }
    4781        1030 :                         long nCellStartX = nStartX;
    4782             : 
    4783             :                         //  Ersatzdarstellung fuer zu kleinen Text weggelassen
    4784             : 
    4785        1030 :                         if (!bHidden)
    4786             :                         {
    4787         378 :                             long nOutWidth = nCellWidth - 1;
    4788         378 :                             long nOutHeight = nCellHeight;
    4789             : 
    4790         378 :                             if ( bMerged )                              // Zusammengefasst
    4791             :                             {
    4792           0 :                                 SCCOL nCountX = pMerge->GetColMerge();
    4793           0 :                                 for (SCCOL i=1; i<nCountX; i++)
    4794           0 :                                     nOutWidth += (long) ( mpDoc->GetColWidth(nX+i,nTab) * mnPPTX );
    4795           0 :                                 SCROW nCountY = pMerge->GetRowMerge();
    4796           0 :                                 nOutHeight += (long) mpDoc->GetScaledRowHeight( nY+1, nY+nCountY-1, nTab, mnPPTY);
    4797             :                             }
    4798             : 
    4799             :                             SvxCellVerJustify eVerJust = (SvxCellVerJustify)((const SvxVerJustifyItem&)
    4800         378 :                                                 pPattern->GetItem(ATTR_VER_JUSTIFY, pCondSet)).GetValue();
    4801             : 
    4802             :                             // Syntax-Modus wird hier ignoriert...
    4803             : 
    4804             :                             // StringDiffer doesn't look at hyphenate, language items
    4805         378 :                             if ( pPattern != pOldPattern || pCondSet != pOldCondSet )
    4806             :                             {
    4807          69 :                                 SfxItemSet* pSet = new SfxItemSet( pEngine->GetEmptyItemSet() );
    4808          69 :                                 pPattern->FillEditItemSet( pSet, pCondSet );
    4809             : 
    4810             :                                                                     // Ausrichtung fuer EditEngine
    4811          69 :                                 SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT;
    4812          69 :                                 if (eOrient==SVX_ORIENTATION_STACKED)
    4813           0 :                                     eSvxAdjust = SVX_ADJUST_CENTER;
    4814             :                                 // Adjustment fuer bBreak ist hier weggelassen
    4815          69 :                                 pSet->Put( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) );
    4816             : 
    4817          69 :                                 pEngine->SetDefaults( pSet );
    4818          69 :                                 pOldPattern = pPattern;
    4819          69 :                                 pOldCondSet = pCondSet;
    4820             : 
    4821          69 :                                 sal_uLong nControl = pEngine->GetControlWord();
    4822          69 :                                 if (eOrient==SVX_ORIENTATION_STACKED)
    4823           0 :                                     nControl |= EE_CNTRL_ONECHARPERLINE;
    4824             :                                 else
    4825          69 :                                     nControl &= ~EE_CNTRL_ONECHARPERLINE;
    4826          69 :                                 pEngine->SetControlWord( nControl );
    4827             : 
    4828          69 :                                 if ( !bHyphenatorSet && ((const SfxBoolItem&)pSet->Get(EE_PARA_HYPHENATE)).GetValue() )
    4829             :                                 {
    4830             :                                     //  set hyphenator the first time it is needed
    4831          40 :                                     com::sun::star::uno::Reference<com::sun::star::linguistic2::XHyphenator> xXHyphenator( LinguMgr::GetHyphenator() );
    4832          40 :                                     pEngine->SetHyphenator( xXHyphenator );
    4833          40 :                                     bHyphenatorSet = sal_True;
    4834             :                                 }
    4835             : 
    4836             :                                 Color aBackCol = ((const SvxBrushItem&)
    4837          69 :                                     pPattern->GetItem( ATTR_BACKGROUND, pCondSet )).GetColor();
    4838          69 :                                 if ( mbUseStyleColor && ( aBackCol.GetTransparency() > 0 || bCellContrast ) )
    4839          26 :                                     aBackCol.SetColor( nConfBackColor );
    4840          69 :                                 pEngine->SetBackgroundColor( aBackCol );
    4841             :                             }
    4842             : 
    4843             :                             //  Raender
    4844             : 
    4845             :                             //!     Position und Papersize auf EditUtil umstellen !!!
    4846             : 
    4847             :                             const SvxMarginItem* pMargin = (const SvxMarginItem*)
    4848         378 :                                                     &pPattern->GetItem(ATTR_MARGIN, pCondSet);
    4849         378 :                             sal_uInt16 nIndent = 0;
    4850         378 :                             if ( eHorJust == SVX_HOR_JUSTIFY_LEFT )
    4851             :                                 nIndent = ((const SfxUInt16Item&)pPattern->
    4852         116 :                                                     GetItem(ATTR_INDENT, pCondSet)).GetValue();
    4853             : 
    4854         378 :                             long nTotalHeight = nOutHeight; // ohne Rand abzuziehen
    4855         378 :                             if ( bPixelToLogic )
    4856         378 :                                 nTotalHeight = mpRefDevice->PixelToLogic(Size(0,nTotalHeight)).Height();
    4857             : 
    4858         378 :                             long nLeftM = (long) ( (pMargin->GetLeftMargin() + nIndent) * mnPPTX );
    4859         378 :                             long nTopM  = (long) ( pMargin->GetTopMargin() * mnPPTY );
    4860         378 :                             long nRightM  = (long) ( pMargin->GetRightMargin() * mnPPTX );
    4861         378 :                             long nBottomM = (long) ( pMargin->GetBottomMargin() * mnPPTY );
    4862         378 :                             nStartX += nLeftM;
    4863         378 :                             nStartY += nTopM;
    4864         378 :                             nOutWidth -= nLeftM + nRightM;
    4865         378 :                             nOutHeight -= nTopM + nBottomM;
    4866             : 
    4867             :                             //  Rotation schon hier, um bei Umbruch auch PaperSize anzupassen
    4868         378 :                             long nAttrRotate = 0;
    4869         378 :                             double nSin = 0.0;
    4870         378 :                             double nCos = 1.0;
    4871         378 :                             SvxRotateMode eRotMode = SVX_ROTATE_MODE_STANDARD;
    4872         378 :                             if ( eOrient == SVX_ORIENTATION_STANDARD )
    4873             :                             {
    4874             :                                 nAttrRotate = ((const SfxInt32Item&)pPattern->
    4875         378 :                                                     GetItem(ATTR_ROTATE_VALUE, pCondSet)).GetValue();
    4876         378 :                                 if ( nAttrRotate )
    4877             :                                 {
    4878             :                                     eRotMode = (SvxRotateMode)((const SvxRotateModeItem&)
    4879         378 :                                                 pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet)).GetValue();
    4880             : 
    4881         378 :                                     if ( nAttrRotate == 18000 )
    4882           0 :                                         eRotMode = SVX_ROTATE_MODE_STANDARD;    // keinen Ueberlauf
    4883             : 
    4884         378 :                                     if ( bLayoutRTL )
    4885           0 :                                         nAttrRotate = -nAttrRotate;
    4886             : 
    4887         378 :                                     double nRealOrient = nAttrRotate * F_PI18000;   // 1/100 Grad
    4888         378 :                                     nCos = cos( nRealOrient );
    4889         378 :                                     nSin = sin( nRealOrient );
    4890             :                                 }
    4891             :                             }
    4892             : 
    4893         378 :                             Size aPaperSize = Size( 1000000, 1000000 );
    4894         378 :                             if (eOrient==SVX_ORIENTATION_STACKED)
    4895           0 :                                 aPaperSize.Width() = nOutWidth;             // zum Zentrieren
    4896         378 :                             else if (bBreak)
    4897             :                             {
    4898         238 :                                 if (nAttrRotate)
    4899             :                                 {
    4900             :                                     //! richtige PaperSize fuer Umbruch haengt von der Zeilenzahl
    4901             :                                     //! ab, solange die Zeilen nicht einzeln versetzt ausgegeben
    4902             :                                     //! werden koennen -> darum unbegrenzt, also kein Umbruch.
    4903             :                                     //! Mit versetzten Zeilen waere das folgende richtig:
    4904         238 :                                     aPaperSize.Width() = (long)(nOutHeight / fabs(nSin));
    4905             :                                 }
    4906           0 :                                 else if (eOrient == SVX_ORIENTATION_STANDARD)
    4907           0 :                                     aPaperSize.Width() = nOutWidth;
    4908             :                                 else
    4909           0 :                                     aPaperSize.Width() = nOutHeight - 1;
    4910             :                             }
    4911         378 :                             if (bPixelToLogic)
    4912         378 :                                 pEngine->SetPaperSize(mpRefDevice->PixelToLogic(aPaperSize));
    4913             :                             else
    4914           0 :                                 pEngine->SetPaperSize(aPaperSize);  // Scale ist immer 1
    4915             : 
    4916             :                             //  Daten aus Zelle lesen
    4917             : 
    4918         378 :                             if (aCell.meType == CELLTYPE_EDIT)
    4919             :                             {
    4920           2 :                                 if (aCell.mpEditText)
    4921           2 :                                     pEngine->SetText(*aCell.mpEditText);
    4922             :                                 else
    4923             :                                 {
    4924             :                                     OSL_FAIL("pData == 0");
    4925             :                                 }
    4926             :                             }
    4927             :                             else
    4928             :                             {
    4929             :                                 sal_uLong nFormat = pPattern->GetNumberFormat(
    4930         376 :                                                             mpDoc->GetFormatTable(), pCondSet );
    4931         376 :                                 OUString aString;
    4932             :                                 Color* pColor;
    4933             :                                 ScCellFormat::GetString( aCell,
    4934             :                                                          nFormat,aString, &pColor,
    4935         376 :                                                          *mpDoc->GetFormatTable(),
    4936             :                                                          mbShowNullValues,
    4937             :                                                          mbShowFormulas,
    4938         752 :                                                          ftCheck );
    4939             : 
    4940         376 :                                 pEngine->SetText(aString);
    4941         376 :                                 if ( pColor && !mbSyntaxMode && !( mbUseStyleColor && mbForceAutoColor ) )
    4942           0 :                                     lcl_SetEditColor( *pEngine, *pColor );
    4943             :                             }
    4944             : 
    4945         378 :                             if ( mbSyntaxMode )
    4946             :                             {
    4947           0 :                                 SetEditSyntaxColor(*pEngine, aCell);
    4948             :                             }
    4949         378 :                             else if ( mbUseStyleColor && mbForceAutoColor )
    4950           0 :                                 lcl_SetEditColor( *pEngine, COL_AUTO );     //! or have a flag at EditEngine
    4951             : 
    4952         378 :                             pEngine->SetUpdateMode( sal_True );     // after SetText, before CalcTextWidth/GetTextHeight
    4953             : 
    4954         378 :                             long nEngineWidth  = (long) pEngine->CalcTextWidth();
    4955         378 :                             long nEngineHeight = pEngine->GetTextHeight();
    4956             : 
    4957         378 :                             if (nAttrRotate && bBreak)
    4958             :                             {
    4959         238 :                                 double nAbsCos = fabs( nCos );
    4960         238 :                                 double nAbsSin = fabs( nSin );
    4961             : 
    4962             :                                 // adjust witdh of papersize for height of text
    4963         238 :                                 int nSteps = 5;
    4964         844 :                                 while (nSteps > 0)
    4965             :                                 {
    4966             :                                     // everything is in pixels
    4967             :                                     long nEnginePixel = mpRefDevice->LogicToPixel(
    4968         368 :                                                             Size(0,nEngineHeight)).Height();
    4969         368 :                                     long nEffHeight = nOutHeight - (long)(nEnginePixel * nAbsCos) + 2;
    4970         368 :                                     long nNewWidth = (long)(nEffHeight / nAbsSin) + 2;
    4971         368 :                                     sal_Bool bFits = ( nNewWidth >= aPaperSize.Width() );
    4972         368 :                                     if ( bFits )
    4973         238 :                                         nSteps = 0;
    4974             :                                     else
    4975             :                                     {
    4976         130 :                                         if ( nNewWidth < 4 )
    4977             :                                         {
    4978             :                                             // can't fit -> fall back to using half height
    4979           0 :                                             nEffHeight = nOutHeight / 2;
    4980           0 :                                             nNewWidth = (long)(nEffHeight / nAbsSin) + 2;
    4981           0 :                                             nSteps = 0;
    4982             :                                         }
    4983             :                                         else
    4984         130 :                                             --nSteps;
    4985             : 
    4986             :                                         // set paper width and get new text height
    4987         130 :                                         aPaperSize.Width() = nNewWidth;
    4988         130 :                                         if (bPixelToLogic)
    4989         130 :                                             pEngine->SetPaperSize(mpRefDevice->PixelToLogic(aPaperSize));
    4990             :                                         else
    4991           0 :                                             pEngine->SetPaperSize(aPaperSize);  // Scale ist immer 1
    4992             :                                         //pEngine->QuickFormatDoc( sal_True );
    4993         130 :                                         nEngineWidth  = (long) pEngine->CalcTextWidth();
    4994         130 :                                         nEngineHeight = pEngine->GetTextHeight();
    4995             :                                     }
    4996             :                                 }
    4997             :                             }
    4998             : 
    4999         378 :                             long nRealWidth  = nEngineWidth;
    5000         378 :                             long nRealHeight = nEngineHeight;
    5001             : 
    5002             :                             //  wenn gedreht, Groesse anpassen
    5003         378 :                             if (nAttrRotate)
    5004             :                             {
    5005         378 :                                 double nAbsCos = fabs( nCos );
    5006         378 :                                 double nAbsSin = fabs( nSin );
    5007             : 
    5008         378 :                                 if ( eRotMode == SVX_ROTATE_MODE_STANDARD )
    5009         756 :                                     nEngineWidth = (long) ( nRealWidth * nAbsCos +
    5010         756 :                                                             nRealHeight * nAbsSin );
    5011             :                                 else
    5012           0 :                                     nEngineWidth = (long) ( nRealHeight / nAbsSin );
    5013             :                                 //! begrenzen !!!
    5014             : 
    5015         756 :                                 nEngineHeight = (long) ( nRealHeight * nAbsCos +
    5016         756 :                                                          nRealWidth * nAbsSin );
    5017             :                             }
    5018             : 
    5019         378 :                             if (!nAttrRotate)           //  hier nur gedrehter Text
    5020           0 :                                 bHidden = sal_True;         //! vorher abfragen !!!
    5021             : 
    5022             :                             //! weglassen, was nicht hereinragt
    5023             : 
    5024         378 :                             if (!bHidden)
    5025             :                             {
    5026         378 :                                 sal_Bool bClip = false;
    5027         378 :                                 Size aClipSize = Size( nScrX+nScrW-nStartX, nScrY+nScrH-nStartY );
    5028             : 
    5029             :                                 //  weiterschreiben
    5030             : 
    5031         378 :                                 Size aCellSize;
    5032         378 :                                 if (bPixelToLogic)
    5033         378 :                                     aCellSize = mpRefDevice->PixelToLogic( Size( nOutWidth, nOutHeight ) );
    5034             :                                 else
    5035           0 :                                     aCellSize = Size( nOutWidth, nOutHeight );  // Scale ist 1
    5036             : 
    5037         378 :                                 long nGridWidth = nEngineWidth;
    5038         378 :                                 sal_Bool bNegative = false;
    5039         378 :                                 if ( eRotMode != SVX_ROTATE_MODE_STANDARD )
    5040             :                                 {
    5041           0 :                                     nGridWidth = aCellSize.Width() +
    5042           0 :                                             std::abs((long) ( aCellSize.Height() * nCos / nSin ));
    5043           0 :                                     bNegative = ( pInfo->nRotateDir == SC_ROTDIR_LEFT );
    5044           0 :                                     if ( bLayoutRTL )
    5045           0 :                                         bNegative = !bNegative;
    5046             :                                 }
    5047             : 
    5048             :                                 // use GetOutputArea to hide the grid
    5049             :                                 // (clip region is done manually below)
    5050         378 :                                 OutputAreaParam aAreaParam;
    5051             : 
    5052         378 :                                 SCCOL nCellX = nX;
    5053         378 :                                 SCROW nCellY = nY;
    5054         378 :                                 SvxCellHorJustify eOutHorJust = eHorJust;
    5055         378 :                                 if ( eRotMode != SVX_ROTATE_MODE_STANDARD )
    5056           0 :                                     eOutHorJust = bNegative ? SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_LEFT;
    5057         378 :                                 long nNeededWidth = nGridWidth;     // in pixel for GetOutputArea
    5058         378 :                                 if ( bPixelToLogic )
    5059         378 :                                     nNeededWidth =  mpRefDevice->LogicToPixel(Size(nNeededWidth,0)).Width();
    5060             : 
    5061             :                                 GetOutputArea( nX, nArrY, nCellStartX, nPosY, nCellX, nCellY, nNeededWidth,
    5062         378 :                                                 *pPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
    5063         378 :                                                 false, false, sal_True, aAreaParam );
    5064             : 
    5065         378 :                                 if ( bShrink )
    5066             :                                 {
    5067             :                                     long nPixelWidth = bPixelToLogic ?
    5068          78 :                                         mpRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width() : nEngineWidth;
    5069          78 :                                     long nNeededPixel = nPixelWidth + nLeftM + nRightM;
    5070             : 
    5071          78 :                                     aAreaParam.mbLeftClip = aAreaParam.mbRightClip = sal_True;
    5072             : 
    5073             :                                     // always do height
    5074             :                                     ShrinkEditEngine( *pEngine, aAreaParam.maAlignRect, nLeftM, nTopM, nRightM, nBottomM,
    5075          78 :                                         false, sal::static_int_cast<sal_uInt16>(eOrient), nAttrRotate, bPixelToLogic,
    5076         156 :                                         nEngineWidth, nEngineHeight, nNeededPixel, aAreaParam.mbLeftClip, aAreaParam.mbRightClip );
    5077             : 
    5078          78 :                                     if ( eRotMode == SVX_ROTATE_MODE_STANDARD )
    5079             :                                     {
    5080             :                                         // do width only if rotating within the cell (standard mode)
    5081             :                                         ShrinkEditEngine( *pEngine, aAreaParam.maAlignRect, nLeftM, nTopM, nRightM, nBottomM,
    5082          78 :                                             sal_True, sal::static_int_cast<sal_uInt16>(eOrient), nAttrRotate, bPixelToLogic,
    5083         156 :                                             nEngineWidth, nEngineHeight, nNeededPixel, aAreaParam.mbLeftClip, aAreaParam.mbRightClip );
    5084             :                                     }
    5085             : 
    5086             :                                     // nEngineWidth/nEngineHeight is updated in ShrinkEditEngine
    5087             :                                     // (but width is only valid for standard mode)
    5088          78 :                                     nRealWidth  = (long) pEngine->CalcTextWidth();
    5089          78 :                                     nRealHeight = pEngine->GetTextHeight();
    5090             : 
    5091          78 :                                     if ( eRotMode != SVX_ROTATE_MODE_STANDARD )
    5092           0 :                                         nEngineWidth = (long) ( nRealHeight / fabs( nSin ) );
    5093             :                                 }
    5094             : 
    5095         378 :                                 long nClipStartX = nStartX;
    5096         378 :                                 if (nX<nX1)
    5097             :                                 {
    5098             :                                     //! Clipping unnoetig, wenn links am Fenster
    5099             : 
    5100           0 :                                     bClip = sal_True;                   // nur Rest ausgeben!
    5101           0 :                                     if (nStartX<nScrX)
    5102             :                                     {
    5103           0 :                                         long nDif = nScrX - nStartX;
    5104           0 :                                         nClipStartX = nScrX;
    5105           0 :                                         aClipSize.Width() -= nDif;
    5106             :                                     }
    5107             :                                 }
    5108             : 
    5109         378 :                                 long nClipStartY = nStartY;
    5110         378 :                                 if (nArrY==0 || bVisChanged)
    5111             :                                 {
    5112           0 :                                     if ( nClipStartY < nRowPosY )
    5113             :                                     {
    5114           0 :                                         long nDif = nRowPosY - nClipStartY;
    5115           0 :                                         bClip = sal_True;
    5116           0 :                                         nClipStartY = nRowPosY;
    5117           0 :                                         aClipSize.Height() -= nDif;
    5118             :                                     }
    5119             :                                 }
    5120             : 
    5121         378 :                                 bClip = sal_True;       // always clip at the window/page border
    5122             : 
    5123             :                                 //Rectangle aClipRect;
    5124         378 :                                 if (bClip)
    5125             :                                 {
    5126         378 :                                     if ( nAttrRotate /* && eRotMode != SVX_ROTATE_MODE_STANDARD */ )
    5127             :                                     {
    5128             :                                         //  gedrehten, ausgerichteten Text nur an den
    5129             :                                         //  Seitengrenzen clippen
    5130         378 :                                         nClipStartX = nScrX;
    5131         378 :                                         aClipSize.Width() = nScrW;
    5132             :                                     }
    5133             : 
    5134         378 :                                     if (bPixelToLogic)
    5135             :                                         aAreaParam.maClipRect = mpRefDevice->PixelToLogic( Rectangle(
    5136         378 :                                                         Point(nClipStartX,nClipStartY), aClipSize ) );
    5137             :                                     else
    5138             :                                         aAreaParam.maClipRect = Rectangle(Point(nClipStartX, nClipStartY),
    5139           0 :                                                                 aClipSize );    // Scale = 1
    5140             : 
    5141         378 :                                     if (bMetaFile)
    5142             :                                     {
    5143           0 :                                         mpDev->Push();
    5144           0 :                                         mpDev->IntersectClipRegion( aAreaParam.maClipRect );
    5145             :                                     }
    5146             :                                     else
    5147         378 :                                         mpDev->SetClipRegion( Region( aAreaParam.maClipRect ) );
    5148             :                                 }
    5149             : 
    5150         378 :                                 Point aLogicStart;
    5151         378 :                                 if (bPixelToLogic)
    5152         378 :                                     aLogicStart = mpRefDevice->PixelToLogic( Point(nStartX,nStartY) );
    5153             :                                 else
    5154           0 :                                     aLogicStart = Point(nStartX, nStartY);
    5155         378 :                                 if ( eOrient!=SVX_ORIENTATION_STANDARD || !bBreak )
    5156             :                                 {
    5157         140 :                                     long nAvailWidth = aCellSize.Width();
    5158         140 :                                     if (eType==OUTTYPE_WINDOW &&
    5159         140 :                                             eOrient!=SVX_ORIENTATION_STACKED &&
    5160         140 :                                             pInfo && pInfo->bAutoFilter)
    5161             :                                     {
    5162             :                                         // filter drop-down width is now independent from row height
    5163           0 :                                         if (bPixelToLogic)
    5164           0 :                                             nAvailWidth -= mpRefDevice->PixelToLogic(Size(0,DROPDOWN_BITMAP_SIZE)).Height();
    5165             :                                         else
    5166           0 :                                             nAvailWidth -= DROPDOWN_BITMAP_SIZE;
    5167           0 :                                         long nComp = nEngineWidth;
    5168           0 :                                         if (nAvailWidth<nComp) nAvailWidth=nComp;
    5169             :                                     }
    5170             : 
    5171             :                                     //  horizontale Ausrichtung
    5172             : 
    5173         140 :                                     if (eOrient==SVX_ORIENTATION_STANDARD && !nAttrRotate)
    5174             :                                     {
    5175           0 :                                         if (eHorJust==SVX_HOR_JUSTIFY_RIGHT ||
    5176             :                                             eHorJust==SVX_HOR_JUSTIFY_CENTER)
    5177             :                                         {
    5178           0 :                                             pEngine->SetUpdateMode( false );
    5179             : 
    5180             :                                             SvxAdjust eSvxAdjust =
    5181             :                                                 (eHorJust==SVX_HOR_JUSTIFY_RIGHT) ?
    5182           0 :                                                     SVX_ADJUST_RIGHT : SVX_ADJUST_CENTER;
    5183             :                                             pEngine->SetDefaultItem(
    5184           0 :                                                 SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) );
    5185             : 
    5186           0 :                                             aPaperSize.Width() = nOutWidth;
    5187           0 :                                             if (bPixelToLogic)
    5188           0 :                                                 pEngine->SetPaperSize(mpRefDevice->PixelToLogic(aPaperSize));
    5189             :                                             else
    5190           0 :                                                 pEngine->SetPaperSize(aPaperSize);
    5191             : 
    5192           0 :                                             pEngine->SetUpdateMode( sal_True );
    5193           0 :                                         }
    5194             :                                     }
    5195             :                                     else
    5196             :                                     {
    5197             :                                         //  bei gedrehtem Text ist Standard zentriert
    5198         140 :                                         if (eHorJust==SVX_HOR_JUSTIFY_RIGHT)
    5199          24 :                                             aLogicStart.X() += nAvailWidth - nEngineWidth;
    5200         116 :                                         else if (eHorJust==SVX_HOR_JUSTIFY_CENTER ||
    5201             :                                                  eHorJust==SVX_HOR_JUSTIFY_STANDARD)
    5202           0 :                                             aLogicStart.X() += (nAvailWidth - nEngineWidth) / 2;
    5203             :                                     }
    5204             :                                 }
    5205             : 
    5206         378 :                                 if ( bLayoutRTL )
    5207             :                                 {
    5208           0 :                                     if (bPixelToLogic)
    5209           0 :                                         aLogicStart.X() -= mpRefDevice->PixelToLogic(
    5210           0 :                                                         Size( nCellWidth, 0 ) ).Width();
    5211             :                                     else
    5212           0 :                                         aLogicStart.X() -= nCellWidth;
    5213             :                                 }
    5214             : 
    5215         378 :                                 if ( eOrient==SVX_ORIENTATION_STANDARD ||
    5216           0 :                                      eOrient==SVX_ORIENTATION_STACKED || !bBreak )
    5217             :                                 {
    5218         378 :                                     if (eVerJust==SVX_VER_JUSTIFY_BOTTOM ||
    5219             :                                         eVerJust==SVX_VER_JUSTIFY_STANDARD)
    5220             :                                     {
    5221         756 :                                         if (bPixelToLogic)
    5222         378 :                                             aLogicStart.Y() += mpRefDevice->PixelToLogic( Size(0,
    5223         756 :                                                             mpRefDevice->LogicToPixel(aCellSize).Height() -
    5224         756 :                                                             mpRefDevice->LogicToPixel(Size(0,nEngineHeight)).Height()
    5225        1134 :                                                             )).Height();
    5226             :                                         else
    5227           0 :                                             aLogicStart.Y() += aCellSize.Height() - nEngineHeight;
    5228             :                                     }
    5229             : 
    5230           0 :                                     else if (eVerJust==SVX_VER_JUSTIFY_CENTER)
    5231             :                                     {
    5232           0 :                                         if (bPixelToLogic)
    5233           0 :                                             aLogicStart.Y() += mpRefDevice->PixelToLogic( Size(0,(
    5234           0 :                                                             mpRefDevice->LogicToPixel(aCellSize).Height() -
    5235           0 :                                                             mpRefDevice->LogicToPixel(Size(0,nEngineHeight)).Height())
    5236           0 :                                                             / 2)).Height();
    5237             :                                         else
    5238           0 :                                             aLogicStart.Y() += (aCellSize.Height() - nEngineHeight) / 2;
    5239             :                                     }
    5240             :                                 }
    5241             : 
    5242             :                                 // TOPBOTTON and BOTTOMTOP are handled in DrawStrings/DrawEdit
    5243             :                                 OSL_ENSURE( eOrient == SVX_ORIENTATION_STANDARD && nAttrRotate,
    5244             :                                             "DrawRotated: no rotation" );
    5245             : 
    5246         378 :                                 long nOriVal = 0;
    5247         378 :                                 if ( nAttrRotate )
    5248             :                                 {
    5249             :                                     // Attribut ist 1/100, Font 1/10 Grad
    5250         378 :                                     nOriVal = nAttrRotate / 10;
    5251             : 
    5252         378 :                                     double nAddX = 0.0;
    5253         378 :                                     double nAddY = 0.0;
    5254         378 :                                     if ( nCos > 0.0 && eRotMode != SVX_ROTATE_MODE_STANDARD )
    5255             :                                     {
    5256             :                                         //! begrenzen !!!
    5257           0 :                                         double nH = nRealHeight * nCos;
    5258           0 :                                         nAddX += nH * ( nCos / fabs(nSin) );
    5259             :                                     }
    5260         378 :                                     if ( nCos < 0.0 && eRotMode == SVX_ROTATE_MODE_STANDARD )
    5261           0 :                                         nAddX -= nRealWidth * nCos;
    5262         378 :                                     if ( nSin < 0.0 )
    5263         248 :                                         nAddX -= nRealHeight * nSin;
    5264         378 :                                     if ( nSin > 0.0 )
    5265         130 :                                         nAddY += nRealWidth * nSin;
    5266         378 :                                     if ( nCos < 0.0 )
    5267           0 :                                         nAddY -= nRealHeight * nCos;
    5268             : 
    5269         378 :                                     if ( eRotMode != SVX_ROTATE_MODE_STANDARD )
    5270             :                                     {
    5271             :                                         //! begrenzen !!!
    5272           0 :                                         double nSkew = nTotalHeight * nCos / fabs(nSin);
    5273           0 :                                         if ( eRotMode == SVX_ROTATE_MODE_CENTER )
    5274           0 :                                             nAddX -= nSkew * 0.5;
    5275           0 :                                         if ( ( eRotMode == SVX_ROTATE_MODE_TOP && nSin > 0.0 ) ||
    5276           0 :                                              ( eRotMode == SVX_ROTATE_MODE_BOTTOM && nSin < 0.0 ) )
    5277           0 :                                             nAddX -= nSkew;
    5278             : 
    5279           0 :                                         long nUp = 0;
    5280           0 :                                         if ( eVerJust == SVX_VER_JUSTIFY_CENTER )
    5281           0 :                                             nUp = ( aCellSize.Height() - nEngineHeight ) / 2;
    5282           0 :                                         else if ( eVerJust == SVX_VER_JUSTIFY_TOP )
    5283             :                                         {
    5284           0 :                                             if ( nSin > 0.0 )
    5285           0 :                                                 nUp = aCellSize.Height() - nEngineHeight;
    5286             :                                         }
    5287             :                                         else    // BOTTOM / STANDARD
    5288             :                                         {
    5289           0 :                                             if ( nSin < 0.0 )
    5290           0 :                                                 nUp = aCellSize.Height() - nEngineHeight;
    5291             :                                         }
    5292           0 :                                         if ( nUp )
    5293           0 :                                             nAddX += ( nUp * nCos / fabs(nSin) );
    5294             :                                     }
    5295             : 
    5296         378 :                                     aLogicStart.X() += (long) nAddX;
    5297         378 :                                     aLogicStart.Y() += (long) nAddY;
    5298             :                                 }
    5299             : 
    5300             :                                 //  bSimClip is not used here (because nOriVal is set)
    5301             : 
    5302         378 :                                 if ( pEngine->IsRightToLeft( 0 ) )
    5303             :                                 {
    5304             :                                     //  For right-to-left, EditEngine always calculates its lines
    5305             :                                     //  beginning from the right edge, but EditLine::nStartPosX is
    5306             :                                     //  of sal_uInt16 type, so the PaperSize must be limited to USHRT_MAX.
    5307           0 :                                     Size aLogicPaper = pEngine->GetPaperSize();
    5308           0 :                                     if ( aLogicPaper.Width() > USHRT_MAX )
    5309             :                                     {
    5310           0 :                                         aLogicPaper.Width() = USHRT_MAX;
    5311           0 :                                         pEngine->SetPaperSize(aLogicPaper);
    5312             :                                     }
    5313             :                                 }
    5314             : 
    5315         378 :                                 pEngine->Draw( mpDev, aLogicStart, (short)nOriVal );
    5316             : 
    5317         378 :                                 if (bClip)
    5318             :                                 {
    5319         378 :                                     if (bMetaFile)
    5320           0 :                                         mpDev->Pop();
    5321             :                                     else
    5322         378 :                                         mpDev->SetClipRegion();
    5323             :                                 }
    5324             :                             }
    5325             :                         }
    5326             :                     }
    5327             :                 }
    5328        2590 :                 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
    5329             :             }
    5330             :         }
    5331         361 :         nRowPosY += pRowInfo[nArrY].nHeight;
    5332             :     }
    5333             : 
    5334          69 :     delete pEngine;
    5335         162 : }
    5336             : 
    5337             : 
    5338             : 
    5339             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10