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

Generated by: LCOV version 1.11