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

Generated by: LCOV version 1.10