xref: /AOO41X/main/sc/source/ui/view/output2.cxx (revision b3f79822e811ac3493b185030a72c3c5a51f32d8)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 
27 
28 
29 
30 // INCLUDE ---------------------------------------------------------------
31 
32 #include "scitems.hxx"
33 #include <editeng/eeitem.hxx>
34 
35 
36 #include <editeng/adjitem.hxx>
37 #include <svx/algitem.hxx>
38 #include <editeng/brshitem.hxx>
39 #include <svtools/colorcfg.hxx>
40 #include <editeng/colritem.hxx>
41 #include <editeng/editobj.hxx>
42 #include <editeng/editstat.hxx>
43 #include <editeng/fhgtitem.hxx>
44 #include <editeng/forbiddencharacterstable.hxx>
45 #include <editeng/frmdiritem.hxx>
46 #include <editeng/langitem.hxx>
47 #include <svx/rotmodit.hxx>
48 #include <editeng/scripttypeitem.hxx>
49 #include <editeng/udlnitem.hxx>
50 #include <editeng/unolingu.hxx>
51 #include <svl/zforlist.hxx>
52 #include <svl/zformat.hxx>
53 #include <vcl/svapp.hxx>
54 #include <vcl/metric.hxx>
55 #include <vcl/outdev.hxx>
56 #include <vcl/pdfextoutdevdata.hxx>
57 
58 #ifndef _SVSTDARR_USHORTS
59 #define _SVSTDARR_USHORTS
60 #include <svl/svstdarr.hxx>
61 #endif
62 
63 #include "output.hxx"
64 #include "document.hxx"
65 #include "cell.hxx"
66 #include "attrib.hxx"
67 #include "patattr.hxx"
68 #include "cellform.hxx"
69 #include "editutil.hxx"
70 #include "progress.hxx"
71 #include "scmod.hxx"
72 #include "fillinfo.hxx"
73 
74 #include <math.h>
75 
76 //! Autofilter-Breite mit column.cxx zusammenfassen
77 #define DROPDOWN_BITMAP_SIZE        18
78 
79 #define DRAWTEXT_MAX    32767
80 
81 const sal_uInt16 SC_SHRINKAGAIN_MAX = 7;
82 
83 // STATIC DATA -----------------------------------------------------------
84 
85 
86 // -----------------------------------------------------------------------
87 
88 class ScDrawStringsVars
89 {
90     ScOutputData*       pOutput;                // Verbindung
91 
92     const ScPatternAttr* pPattern;              // Attribute
93     const SfxItemSet*   pCondSet;               // aus bedingter Formatierung
94 
95     Font                aFont;                  // aus Attributen erzeugt
96     FontMetric          aMetric;
97     long                nAscentPixel;           // always pixels
98     SvxCellOrientation  eAttrOrient;
99     SvxCellHorJustify   eAttrHorJust;
100     SvxCellVerJustify   eAttrVerJust;
101     const SvxMarginItem* pMargin;
102     sal_uInt16              nIndent;
103     sal_Bool                bRotated;
104 
105     String              aString;                // Inhalte
106     Size                aTextSize;
107     long                nOriginalWidth;
108     long                nMaxDigitWidth;
109     long                nSignWidth;
110     long                nDotWidth;
111     long                nExpWidth;
112 
113     ScBaseCell*         pLastCell;
114     sal_uLong               nValueFormat;
115     sal_Bool                bLineBreak;
116     sal_Bool                bRepeat;
117     sal_Bool                bShrink;
118 
119     sal_Bool                bPixelToLogic;
120     sal_Bool                bCellContrast;
121 
122     Color               aBackConfigColor;       // used for ScPatternAttr::GetFont calls
123     Color               aTextConfigColor;
124 
125 public:
126                 ScDrawStringsVars(ScOutputData* pData, sal_Bool bPTL);
127                 ~ScDrawStringsVars();
128 
129                 //  SetPattern = ex-SetVars
130                 //  SetPatternSimple: ohne Font
131 
132     void        SetPattern( const ScPatternAttr* pNew, const SfxItemSet* pSet, ScBaseCell* pCell, sal_uInt8 nScript );
133     void        SetPatternSimple( const ScPatternAttr* pNew, const SfxItemSet* pSet );
134 
135     sal_Bool        SetText( ScBaseCell* pCell );   // sal_True -> pOldPattern vergessen
136     void        SetTextToWidthOrHash( ScBaseCell* pCell, long nWidth );
137     void        SetAutoText( const String& rAutoText );
138 
GetPattern() const139     const ScPatternAttr*    GetPattern() const      { return pPattern; }
GetOrient() const140     SvxCellOrientation      GetOrient() const       { return eAttrOrient; }
GetHorJust() const141     SvxCellHorJustify       GetHorJust() const      { return eAttrHorJust; }
GetVerJust() const142     SvxCellVerJustify       GetVerJust() const      { return eAttrVerJust; }
GetMargin() const143     const SvxMarginItem*    GetMargin() const       { return pMargin; }
144 
GetLeftTotal() const145     sal_uInt16  GetLeftTotal() const        { return pMargin->GetLeftMargin() + nIndent; }
146 
GetString() const147     const String&           GetString() const       { return aString; }
GetTextSize() const148     const Size&             GetTextSize() const     { return aTextSize; }
GetOriginalWidth() const149     long                    GetOriginalWidth() const { return nOriginalWidth; }
150 
151     sal_uLong   GetResultValueFormat( const ScBaseCell* pCell ) const;
152 
GetValueFormat() const153     sal_uLong   GetValueFormat() const                  { return nValueFormat; }
GetLineBreak() const154     sal_Bool    GetLineBreak() const                    { return bLineBreak; }
IsRepeat() const155     sal_Bool    IsRepeat() const                        { return bRepeat; }
IsShrink() const156     sal_Bool    IsShrink() const                        { return bShrink; }
157 
GetAscent() const158     long    GetAscent() const   { return nAscentPixel; }
IsRotated() const159     sal_Bool    IsRotated() const   { return bRotated; }
160 
161     void    SetShrinkScale( long nScale, sal_uInt8 nScript );
162 
HasCondHeight() const163     sal_Bool    HasCondHeight() const   { return pCondSet && SFX_ITEM_SET ==
164                                         pCondSet->GetItemState( ATTR_FONT_HEIGHT, sal_True ); }
165 
166     sal_Bool    HasEditCharacters() const;
167 
168 private:
169     void        SetHashText();
170     long        GetMaxDigitWidth();     // in logic units
171     long        GetSignWidth();
172     long        GetDotWidth();
173     long        GetExpWidth();
174     void        TextChanged();
175 };
176 
177 //==================================================================
178 
ScDrawStringsVars(ScOutputData * pData,sal_Bool bPTL)179 ScDrawStringsVars::ScDrawStringsVars(ScOutputData* pData, sal_Bool bPTL) :
180     pOutput     ( pData ),
181     pPattern    ( NULL ),
182     pCondSet    ( NULL ),
183     eAttrOrient ( SVX_ORIENTATION_STANDARD ),
184     eAttrHorJust( SVX_HOR_JUSTIFY_STANDARD ),
185     eAttrVerJust( SVX_VER_JUSTIFY_BOTTOM ),
186     pMargin     ( NULL ),
187     nIndent     ( 0 ),
188     bRotated    ( sal_False ),
189     nOriginalWidth( 0 ),
190     nMaxDigitWidth( 0 ),
191     nSignWidth( 0 ),
192     nDotWidth( 0 ),
193     nExpWidth( 0 ),
194     pLastCell   ( NULL ),
195     nValueFormat( 0 ),
196     bLineBreak  ( sal_False ),
197     bRepeat     ( sal_False ),
198     bShrink     ( sal_False ),
199     bPixelToLogic( bPTL )
200 {
201     ScModule* pScMod = SC_MOD();
202     //  #105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed sal_True)
203     bCellContrast = pOutput->bUseStyleColor &&
204             Application::GetSettings().GetStyleSettings().GetHighContrastMode();
205 
206     const svtools::ColorConfig& rColorConfig = pScMod->GetColorConfig();
207     aBackConfigColor.SetColor( rColorConfig.GetColorValue(svtools::DOCCOLOR).nColor );
208     aTextConfigColor.SetColor( rColorConfig.GetColorValue(svtools::FONTCOLOR).nColor );
209 }
210 
~ScDrawStringsVars()211 ScDrawStringsVars::~ScDrawStringsVars()
212 {
213 }
214 
SetShrinkScale(long nScale,sal_uInt8 nScript)215 void ScDrawStringsVars::SetShrinkScale( long nScale, sal_uInt8 nScript )
216 {
217     // text remains valid, size is updated
218 
219     OutputDevice* pDev = pOutput->pDev;
220     OutputDevice* pRefDevice = pOutput->pRefDevice;
221     OutputDevice* pFmtDevice = pOutput->pFmtDevice;
222 
223     // call GetFont with a modified fraction, use only the height
224 
225     Fraction aFraction( nScale, 100 );
226     if ( !bPixelToLogic )
227         aFraction *= pOutput->aZoomY;
228     Font aTmpFont;
229     pPattern->GetFont( aTmpFont, SC_AUTOCOL_RAW, pFmtDevice, &aFraction, pCondSet, nScript );
230     long nNewHeight = aTmpFont.GetHeight();
231     if ( nNewHeight > 0 )
232         aFont.SetHeight( nNewHeight );
233 
234     // set font and dependent variables as in SetPattern
235 
236     pDev->SetFont( aFont );
237     if ( pFmtDevice != pDev )
238         pFmtDevice->SetFont( aFont );
239 
240     aMetric = pFmtDevice->GetFontMetric();
241     if ( pFmtDevice->GetOutDevType() == OUTDEV_PRINTER && aMetric.GetIntLeading() == 0 )
242     {
243         OutputDevice* pDefaultDev = Application::GetDefaultDevice();
244         MapMode aOld = pDefaultDev->GetMapMode();
245         pDefaultDev->SetMapMode( pFmtDevice->GetMapMode() );
246         aMetric = pDefaultDev->GetFontMetric( aFont );
247         pDefaultDev->SetMapMode( aOld );
248     }
249 
250     nAscentPixel = aMetric.GetAscent();
251     if ( bPixelToLogic )
252         nAscentPixel = pRefDevice->LogicToPixel( Size( 0, nAscentPixel ) ).Height();
253 
254     SetAutoText( aString );     // same text again, to get text size
255 }
256 
SetPattern(const ScPatternAttr * pNew,const SfxItemSet * pSet,ScBaseCell * pCell,sal_uInt8 nScript)257 void ScDrawStringsVars::SetPattern( const ScPatternAttr* pNew, const SfxItemSet* pSet,
258                                     ScBaseCell* pCell, sal_uInt8 nScript )
259 {
260     nMaxDigitWidth = 0;
261     nSignWidth     = 0;
262     nDotWidth      = 0;
263     nExpWidth      = 0;
264 
265     pPattern = pNew;
266     pCondSet = pSet;
267 
268     //  pPattern auswerten
269 
270     OutputDevice* pDev = pOutput->pDev;
271     OutputDevice* pRefDevice = pOutput->pRefDevice;
272     OutputDevice* pFmtDevice = pOutput->pFmtDevice;
273 
274     //  Font
275 
276     ScAutoFontColorMode eColorMode;
277     if ( pOutput->bUseStyleColor )
278     {
279         if ( pOutput->bForceAutoColor )
280             eColorMode = bCellContrast ? SC_AUTOCOL_IGNOREALL : SC_AUTOCOL_IGNOREFONT;
281         else
282             eColorMode = bCellContrast ? SC_AUTOCOL_IGNOREBACK : SC_AUTOCOL_DISPLAY;
283     }
284     else
285         eColorMode = SC_AUTOCOL_PRINT;
286 
287     if ( bPixelToLogic )
288         pPattern->GetFont( aFont, eColorMode, pFmtDevice, NULL, pCondSet, nScript,
289                             &aBackConfigColor, &aTextConfigColor );
290     else
291         pPattern->GetFont( aFont, eColorMode, pFmtDevice, &pOutput->aZoomY, pCondSet, nScript,
292                             &aBackConfigColor, &aTextConfigColor );
293     aFont.SetAlign(ALIGN_BASELINE);
294 
295     //  Orientierung
296 
297     eAttrOrient = pPattern->GetCellOrientation( pCondSet );
298 
299     //  alignment
300 
301     eAttrHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern->GetItem( ATTR_HOR_JUSTIFY, pCondSet )).GetValue();
302 
303     eAttrVerJust = (SvxCellVerJustify)((const SvxVerJustifyItem&)pPattern->GetItem( ATTR_VER_JUSTIFY, pCondSet )).GetValue();
304     if ( eAttrVerJust == SVX_VER_JUSTIFY_STANDARD )
305         eAttrVerJust = SVX_VER_JUSTIFY_BOTTOM;
306 
307     //  line break
308 
309     bLineBreak = ((const SfxBoolItem&)pPattern->GetItem( ATTR_LINEBREAK, pCondSet )).GetValue();
310 
311     //  handle "repeat" alignment
312 
313     bRepeat = ( eAttrHorJust == SVX_HOR_JUSTIFY_REPEAT );
314     if ( bRepeat )
315     {
316         // "repeat" disables rotation (before constructing the font)
317         eAttrOrient = SVX_ORIENTATION_STANDARD;
318 
319         // #i31843# "repeat" with "line breaks" is treated as default alignment (but rotation is still disabled)
320         if ( bLineBreak )
321             eAttrHorJust = SVX_HOR_JUSTIFY_STANDARD;
322     }
323 
324     short nRot;
325     switch (eAttrOrient)
326     {
327         case SVX_ORIENTATION_STANDARD:
328             nRot = 0;
329             bRotated = (((const SfxInt32Item&)pPattern->GetItem( ATTR_ROTATE_VALUE, pCondSet )).GetValue() != 0) &&
330                        !bRepeat;
331             break;
332         case SVX_ORIENTATION_STACKED:
333             nRot = 0;
334             bRotated = sal_False;
335             break;
336         case SVX_ORIENTATION_TOPBOTTOM:
337             nRot = 2700;
338             bRotated = sal_False;
339             break;
340         case SVX_ORIENTATION_BOTTOMTOP:
341             nRot = 900;
342             bRotated = sal_False;
343             break;
344         default:
345             DBG_ERROR("Falscher SvxCellOrientation Wert");
346             nRot = 0;
347             bRotated = sal_False;
348             break;
349     }
350     aFont.SetOrientation( nRot );
351 
352     //  Syntax-Modus
353 
354     if (pOutput->bSyntaxMode)
355         pOutput->SetSyntaxColor( &aFont, pCell );
356 
357     pDev->SetFont( aFont );
358     if ( pFmtDevice != pDev )
359         pFmtDevice->SetFont( aFont );
360 
361     aMetric = pFmtDevice->GetFontMetric();
362 
363     //
364     //  Wenn auf dem Drucker das Leading 0 ist, gibt es Probleme
365     //  -> Metric vom Bildschirm nehmen (wie EditEngine!)
366     //
367 
368     if ( pFmtDevice->GetOutDevType() == OUTDEV_PRINTER && aMetric.GetIntLeading() == 0 )
369     {
370         OutputDevice* pDefaultDev = Application::GetDefaultDevice();
371         MapMode aOld = pDefaultDev->GetMapMode();
372         pDefaultDev->SetMapMode( pFmtDevice->GetMapMode() );
373         aMetric = pDefaultDev->GetFontMetric( aFont );
374         pDefaultDev->SetMapMode( aOld );
375     }
376 
377     nAscentPixel = aMetric.GetAscent();
378     if ( bPixelToLogic )
379         nAscentPixel = pRefDevice->LogicToPixel( Size( 0, nAscentPixel ) ).Height();
380 
381     Color aULineColor( ((const SvxUnderlineItem&)pPattern->GetItem( ATTR_FONT_UNDERLINE, pCondSet )).GetColor() );
382     pDev->SetTextLineColor( aULineColor );
383 
384     Color aOLineColor( ((const SvxOverlineItem&)pPattern->GetItem( ATTR_FONT_OVERLINE, pCondSet )).GetColor() );
385     pDev->SetOverlineColor( aOLineColor );
386 
387     //  Zahlenformat
388 
389 //    sal_uLong nOld = nValueFormat;
390     nValueFormat = pPattern->GetNumberFormat( pOutput->pDoc->GetFormatTable(), pCondSet );
391 
392 /*  s.u.
393     if (nValueFormat != nOld)
394         pLastCell = NULL;           // immer neu formatieren
395 */
396     //  Raender
397 
398     pMargin = (const SvxMarginItem*)&pPattern->GetItem( ATTR_MARGIN, pCondSet );
399     if ( eAttrHorJust == SVX_HOR_JUSTIFY_LEFT )
400         nIndent = ((const SfxUInt16Item&)pPattern->GetItem( ATTR_INDENT, pCondSet )).GetValue();
401     else
402         nIndent = 0;
403 
404     //  "Shrink to fit"
405 
406     bShrink = static_cast<const SfxBoolItem&>(pPattern->GetItem( ATTR_SHRINKTOFIT, pCondSet )).GetValue();
407 
408     //  zumindest die Text-Groesse muss neu geholt werden
409     //! unterscheiden, und den Text nicht neu vom Numberformatter holen?
410 
411     pLastCell = NULL;
412 }
413 
SetPatternSimple(const ScPatternAttr * pNew,const SfxItemSet * pSet)414 void ScDrawStringsVars::SetPatternSimple( const ScPatternAttr* pNew, const SfxItemSet* pSet )
415 {
416     nMaxDigitWidth = 0;
417     nSignWidth     = 0;
418     nDotWidth      = 0;
419     nExpWidth      = 0;
420     //  wird gerufen, wenn sich die Font-Variablen nicht aendern (!StringDiffer)
421 
422     pPattern = pNew;
423     pCondSet = pSet;        //! noetig ???
424 
425     //  Zahlenformat
426 
427     sal_uLong nOld = nValueFormat;
428 //  nValueFormat = pPattern->GetNumberFormat( pFormatter );
429     const SfxPoolItem* pFormItem;
430     if ( !pCondSet || pCondSet->GetItemState(ATTR_VALUE_FORMAT,sal_True,&pFormItem) != SFX_ITEM_SET )
431         pFormItem = &pPattern->GetItem(ATTR_VALUE_FORMAT);
432     const SfxPoolItem* pLangItem;
433     if ( !pCondSet || pCondSet->GetItemState(ATTR_LANGUAGE_FORMAT,sal_True,&pLangItem) != SFX_ITEM_SET )
434         pLangItem = &pPattern->GetItem(ATTR_LANGUAGE_FORMAT);
435     nValueFormat = pOutput->pDoc->GetFormatTable()->GetFormatForLanguageIfBuiltIn(
436                     ((SfxUInt32Item*)pFormItem)->GetValue(),
437                     ((SvxLanguageItem*)pLangItem)->GetLanguage() );
438 
439     if (nValueFormat != nOld)
440         pLastCell = NULL;           // immer neu formatieren
441 
442     //  Raender
443 
444     pMargin = (const SvxMarginItem*)&pPattern->GetItem( ATTR_MARGIN, pCondSet );
445 
446     if ( eAttrHorJust == SVX_HOR_JUSTIFY_LEFT )
447         nIndent = ((const SfxUInt16Item&)pPattern->GetItem( ATTR_INDENT, pCondSet )).GetValue();
448     else
449         nIndent = 0;
450 
451     //  "Shrink to fit"
452 
453     bShrink = static_cast<const SfxBoolItem&>(pPattern->GetItem( ATTR_SHRINKTOFIT, pCondSet )).GetValue();
454 }
455 
SameValue(ScBaseCell * pCell,ScBaseCell * pOldCell)456 inline sal_Bool SameValue( ScBaseCell* pCell, ScBaseCell* pOldCell )    // pCell ist != 0
457 {
458     return pOldCell && pOldCell->GetCellType() == CELLTYPE_VALUE &&
459             pCell->GetCellType() == CELLTYPE_VALUE &&
460             ((ScValueCell*)pCell)->GetValue() == ((ScValueCell*)pOldCell)->GetValue();
461 }
462 
SetText(ScBaseCell * pCell)463 sal_Bool ScDrawStringsVars::SetText( ScBaseCell* pCell )
464 {
465     sal_Bool bChanged = sal_False;
466 
467     if (pCell)
468     {
469         if ( !SameValue( pCell, pLastCell ) )
470         {
471             pLastCell = pCell;          //  Zelle merken
472 
473             Color* pColor;
474             sal_uLong nFormat = GetValueFormat();
475             ScCellFormat::GetString( pCell,
476                                      nFormat, aString, &pColor,
477                                      *pOutput->pDoc->GetFormatTable(),
478                                      pOutput->bShowNullValues,
479                                      pOutput->bShowFormulas,
480                                      ftCheck );
481 
482             if (aString.Len() > DRAWTEXT_MAX)
483                 aString.Erase(DRAWTEXT_MAX);
484 
485             if ( pColor && !pOutput->bSyntaxMode && !( pOutput->bUseStyleColor && pOutput->bForceAutoColor ) )
486             {
487                 OutputDevice* pDev = pOutput->pDev;
488                 aFont.SetColor(*pColor);
489                 pDev->SetFont( aFont ); // nur fuer Ausgabe
490                 bChanged = sal_True;
491                 pLastCell = NULL;       // naechstes Mal wieder hierherkommen
492             }
493 
494             TextChanged();
495         }
496         //  sonst String/Groesse behalten
497     }
498     else
499     {
500         aString.Erase();
501         pLastCell = NULL;
502         aTextSize = Size(0,0);
503         nOriginalWidth = 0;
504     }
505 
506     return bChanged;
507 }
508 
SetHashText()509 void ScDrawStringsVars::SetHashText()
510 {
511     SetAutoText( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("###")) );
512 }
513 
SetTextToWidthOrHash(ScBaseCell * pCell,long nWidth)514 void ScDrawStringsVars::SetTextToWidthOrHash( ScBaseCell* pCell, long nWidth )
515 {
516     // #i113045# do the single-character width calculations in logic units
517     if (bPixelToLogic)
518         nWidth = pOutput->pRefDevice->PixelToLogic(Size(nWidth,0)).Width();
519 
520     if (!pCell)
521         return;
522 
523     CellType eType = pCell->GetCellType();
524     if (eType != CELLTYPE_VALUE && eType != CELLTYPE_FORMULA)
525         // must be a value or formula cell.
526         return;
527 
528     if (eType == CELLTYPE_FORMULA)
529     {
530         ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
531         if (pFCell->GetErrCode() != 0 || pOutput->bShowFormulas)
532         {
533             SetHashText();      // If the error string doesn't fit, always use "###". Also for "display formulas" (#i116691#)
534             return;
535         }
536         // If it's formula, the result must be a value.
537         if (!pFCell->IsValue())
538             return;
539     }
540 
541     sal_uLong nFormat = GetResultValueFormat(pCell);
542     if ((nFormat % SV_COUNTRY_LANGUAGE_OFFSET) != 0)
543     {
544         // Not 'General' number format.  Set hash text and bail out.
545         SetHashText();
546         return;
547     }
548 
549     double fVal = (eType == CELLTYPE_VALUE) ?
550         static_cast<ScValueCell*>(pCell)->GetValue() : static_cast<ScFormulaCell*>(pCell)->GetValue();
551 
552     const SvNumberformat* pNumFormat = pOutput->pDoc->GetFormatTable()->GetEntry(nFormat);
553     if (!pNumFormat)
554         return;
555 
556     long nMaxDigit = GetMaxDigitWidth();
557     sal_uInt16 nNumDigits = static_cast<sal_uInt16>(nWidth / nMaxDigit);
558 
559     if (!pNumFormat->GetOutputString(fVal, nNumDigits, aString))
560         // Failed to get output string.  Bail out.
561         return;
562 
563     sal_uInt8 nSignCount = 0, nDecimalCount = 0, nExpCount = 0;
564     xub_StrLen nLen = aString.Len();
565     sal_Unicode cDecSep = ScGlobal::GetpLocaleData()->getLocaleItem().decimalSeparator.getStr()[0];
566     for (xub_StrLen i = 0; i < nLen; ++i)
567     {
568         sal_Unicode c = aString.GetChar(i);
569         if (c == sal_Unicode('-'))
570             ++nSignCount;
571         else if (c == cDecSep)
572             ++nDecimalCount;
573         else if (c == sal_Unicode('E'))
574             ++nExpCount;
575     }
576 
577     // #i112250# A small value might be formatted as "0" when only counting the digits,
578     // but fit into the column when considering the smaller width of the decimal separator.
579     if (aString.EqualsAscii("0") && fVal != 0.0)
580         nDecimalCount = 1;
581 
582     if (nDecimalCount)
583         nWidth += (nMaxDigit - GetDotWidth()) * nDecimalCount;
584     if (nSignCount)
585         nWidth += (nMaxDigit - GetSignWidth()) * nSignCount;
586     if (nExpCount)
587         nWidth += (nMaxDigit - GetExpWidth()) * nExpCount;
588 
589     if (nDecimalCount || nSignCount || nExpCount)
590     {
591         // Re-calculate.
592         nNumDigits = static_cast<sal_uInt16>(nWidth / nMaxDigit);
593         if (!pNumFormat->GetOutputString(fVal, nNumDigits, aString))
594             // Failed to get output string.  Bail out.
595             return;
596     }
597 
598     long nActualTextWidth = pOutput->pFmtDevice->GetTextWidth(aString);
599     if (nActualTextWidth > nWidth)
600     {
601         // Even after the decimal adjustment the text doesn't fit.  Give up.
602         SetHashText();
603         return;
604     }
605 
606     TextChanged();
607     pLastCell = NULL;   // #i113022# equal cell and format in another column may give different string
608 }
609 
SetAutoText(const String & rAutoText)610 void ScDrawStringsVars::SetAutoText( const String& rAutoText )
611 {
612     aString = rAutoText;
613 
614     OutputDevice* pRefDevice = pOutput->pRefDevice;
615     OutputDevice* pFmtDevice = pOutput->pFmtDevice;
616     aTextSize.Width() = pFmtDevice->GetTextWidth( aString );
617     aTextSize.Height() = pFmtDevice->GetTextHeight();
618 
619     if ( !pRefDevice->GetConnectMetaFile() || pRefDevice->GetOutDevType() == OUTDEV_PRINTER )
620     {
621         double fMul = pOutput->GetStretch();
622         aTextSize.Width() = (long)(aTextSize.Width() / fMul + 0.5);
623     }
624 
625     aTextSize.Height() = aMetric.GetAscent() + aMetric.GetDescent();
626     if ( GetOrient() != SVX_ORIENTATION_STANDARD )
627     {
628         long nTemp = aTextSize.Height();
629         aTextSize.Height() = aTextSize.Width();
630         aTextSize.Width() = nTemp;
631     }
632 
633     nOriginalWidth = aTextSize.Width();
634     if ( bPixelToLogic )
635         aTextSize = pRefDevice->LogicToPixel( aTextSize );
636 
637     pLastCell = NULL;       // derselbe Text kann in der naechsten Zelle wieder passen
638 }
639 
GetMaxDigitWidth()640 long ScDrawStringsVars::GetMaxDigitWidth()
641 {
642     if (nMaxDigitWidth > 0)
643         return nMaxDigitWidth;
644 
645     sal_Char cZero = '0';
646     for (sal_Char i = 0; i < 10; ++i)
647     {
648         sal_Char cDigit = cZero + i;
649         long n = pOutput->pFmtDevice->GetTextWidth(String(cDigit));
650         nMaxDigitWidth = ::std::max(nMaxDigitWidth, n);
651     }
652     return nMaxDigitWidth;
653 }
654 
GetSignWidth()655 long ScDrawStringsVars::GetSignWidth()
656 {
657     if (nSignWidth > 0)
658         return nSignWidth;
659 
660     nSignWidth = pOutput->pFmtDevice->GetTextWidth(String('-'));
661     return nSignWidth;
662 }
663 
GetDotWidth()664 long ScDrawStringsVars::GetDotWidth()
665 {
666     if (nDotWidth > 0)
667         return nDotWidth;
668 
669     const ::rtl::OUString& sep = ScGlobal::GetpLocaleData()->getLocaleItem().decimalSeparator;
670     nDotWidth = pOutput->pFmtDevice->GetTextWidth(sep);
671     return nDotWidth;
672 }
673 
GetExpWidth()674 long ScDrawStringsVars::GetExpWidth()
675 {
676     if (nExpWidth > 0)
677         return nExpWidth;
678 
679     nExpWidth = pOutput->pFmtDevice->GetTextWidth(String('E'));
680     return nExpWidth;
681 }
682 
TextChanged()683 void ScDrawStringsVars::TextChanged()
684 {
685     OutputDevice* pRefDevice = pOutput->pRefDevice;
686     OutputDevice* pFmtDevice = pOutput->pFmtDevice;
687     aTextSize.Width() = pFmtDevice->GetTextWidth( aString );
688     aTextSize.Height() = pFmtDevice->GetTextHeight();
689 
690     if ( !pRefDevice->GetConnectMetaFile() || pRefDevice->GetOutDevType() == OUTDEV_PRINTER )
691     {
692         double fMul = pOutput->GetStretch();
693         aTextSize.Width() = (long)(aTextSize.Width() / fMul + 0.5);
694     }
695 
696     aTextSize.Height() = aMetric.GetAscent() + aMetric.GetDescent();
697     if ( GetOrient() != SVX_ORIENTATION_STANDARD )
698     {
699         long nTemp = aTextSize.Height();
700         aTextSize.Height() = aTextSize.Width();
701         aTextSize.Width() = nTemp;
702     }
703 
704     nOriginalWidth = aTextSize.Width();
705     if ( bPixelToLogic )
706         aTextSize = pRefDevice->LogicToPixel( aTextSize );
707 }
708 
HasEditCharacters() const709 sal_Bool ScDrawStringsVars::HasEditCharacters() const
710 {
711     static const sal_Unicode pChars[] =
712     {
713         CHAR_NBSP, CHAR_SHY, CHAR_ZWSP, CHAR_LRM, CHAR_RLM, CHAR_NBHY, CHAR_ZWNBSP, 0
714     };
715     return aString.SearchChar( pChars ) != STRING_NOTFOUND;
716 }
717 
GetResultValueFormat(const ScBaseCell * pCell) const718 sal_uLong ScDrawStringsVars::GetResultValueFormat( const ScBaseCell* pCell ) const
719 {
720     // Get the effective number format, including formula result types.
721     // This assumes that a formula cell has already been calculated.
722 
723     if ( (nValueFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 && pCell && pCell->GetCellType() == CELLTYPE_FORMULA )
724         return static_cast<const ScFormulaCell*>(pCell)->GetStandardFormat(*pOutput->pDoc->GetFormatTable(), nValueFormat);
725     else
726         return nValueFormat;
727 }
728 
729 //==================================================================
730 
GetStretch()731 double ScOutputData::GetStretch()
732 {
733     if ( pRefDevice->IsMapMode() )
734     {
735         //  #95920# If a non-trivial MapMode is set, its scale is now already
736         //  taken into account in the OutputDevice's font handling
737         //  (OutputDevice::ImplNewFont, see #95414#).
738         //  The old handling below is only needed for pixel output.
739         return 1.0;
740     }
741 
742     // calculation in double is faster than Fraction multiplication
743     // and doesn't overflow
744 
745     if ( pRefDevice == pFmtDevice )
746     {
747         MapMode aOld = pRefDevice->GetMapMode();
748         return ((double)aOld.GetScaleY()) / ((double)aOld.GetScaleX()) * ((double)aZoomY) / ((double)aZoomX);
749     }
750     else
751     {
752         // when formatting for printer, device map mode has already been taken care of
753         return ((double)aZoomY) / ((double)aZoomX);
754     }
755 }
756 
757 //==================================================================
758 
759 //
760 //  output strings
761 //
762 
lcl_DoHyperlinkResult(OutputDevice * pDev,const Rectangle & rRect,ScBaseCell * pCell)763 void lcl_DoHyperlinkResult( OutputDevice* pDev, const Rectangle& rRect, ScBaseCell* pCell )
764 {
765     vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, pDev->GetExtOutDevData() );
766 
767     String aCellText;
768     String aURL;
769     if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA )
770     {
771         ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
772         if ( pFCell->IsHyperLinkCell() )
773             pFCell->GetURLResult( aURL, aCellText );
774     }
775 
776     if ( aURL.Len() && pPDFData )
777     {
778         vcl::PDFExtOutDevBookmarkEntry aBookmark;
779         aBookmark.nLinkId = pPDFData->CreateLink( rRect );
780         aBookmark.aBookmark = aURL;
781         std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFData->GetBookmarks();
782         rBookmarks.push_back( aBookmark );
783     }
784 }
785 
SetSyntaxColor(Font * pFont,ScBaseCell * pCell)786 void ScOutputData::SetSyntaxColor( Font* pFont, ScBaseCell* pCell )
787 {
788     if (pCell)
789     {
790         switch (pCell->GetCellType())
791         {
792             case CELLTYPE_VALUE:
793                 pFont->SetColor( *pValueColor );
794                 break;
795             case CELLTYPE_STRING:
796                 pFont->SetColor( *pTextColor );
797                 break;
798             case CELLTYPE_FORMULA:
799                 pFont->SetColor( *pFormulaColor );
800                 break;
801             default:
802             {
803                 // added to avoid warnings
804             }
805         }
806     }
807 }
808 
lcl_SetEditColor(EditEngine & rEngine,const Color & rColor)809 void lcl_SetEditColor( EditEngine& rEngine, const Color& rColor )
810 {
811     ESelection aSel( 0, 0, rEngine.GetParagraphCount(), 0 );
812     SfxItemSet aSet( rEngine.GetEmptyItemSet() );
813     aSet.Put( SvxColorItem( rColor, EE_CHAR_COLOR ) );
814     rEngine.QuickSetAttribs( aSet, aSel );
815     // function is called with update mode set to FALSE
816 }
817 
SetEditSyntaxColor(EditEngine & rEngine,ScBaseCell * pCell)818 void ScOutputData::SetEditSyntaxColor( EditEngine& rEngine, ScBaseCell* pCell )
819 {
820     if (pCell)
821     {
822         Color aColor;
823         switch (pCell->GetCellType())
824         {
825             case CELLTYPE_VALUE:
826                 aColor = *pValueColor;
827                 break;
828             case CELLTYPE_STRING:
829                 aColor = *pTextColor;
830                 break;
831             case CELLTYPE_FORMULA:
832                 aColor = *pFormulaColor;
833                 break;
834             default:
835             {
836                 // added to avoid warnings
837             }
838         }
839         lcl_SetEditColor( rEngine, aColor );
840     }
841 }
842 
GetMergeOrigin(SCCOL nX,SCROW nY,SCSIZE nArrY,SCCOL & rOverX,SCROW & rOverY,sal_Bool bVisRowChanged)843 sal_Bool ScOutputData::GetMergeOrigin( SCCOL nX, SCROW nY, SCSIZE nArrY,
844                                     SCCOL& rOverX, SCROW& rOverY,
845                                     sal_Bool bVisRowChanged )
846 {
847     sal_Bool bDoMerge = sal_False;
848     sal_Bool bIsLeft = ( nX == nVisX1 );
849     sal_Bool bIsTop  = ( nY == nVisY1 ) || bVisRowChanged;
850 
851     CellInfo* pInfo = &pRowInfo[nArrY].pCellInfo[nX+1];
852     if ( pInfo->bHOverlapped && pInfo->bVOverlapped )
853         bDoMerge = bIsLeft && bIsTop;
854     else if ( pInfo->bHOverlapped )
855         bDoMerge = bIsLeft;
856     else if ( pInfo->bVOverlapped )
857         bDoMerge = bIsTop;
858 
859                                     // weiter solange versteckt
860 /*  if (!bDoMerge)
861         return sal_False;
862 */
863 
864     rOverX = nX;
865     rOverY = nY;
866     sal_Bool bHOver = pInfo->bHOverlapped;
867     sal_Bool bVOver = pInfo->bVOverlapped;
868     sal_Bool bHidden;
869 
870     while (bHOver)              // nY konstant
871     {
872         --rOverX;
873         bHidden = pDoc->ColHidden(rOverX, nTab);
874         if ( !bDoMerge && !bHidden )
875             return sal_False;
876 
877         if (rOverX >= nX1 && !bHidden)
878         {
879 //          rVirtPosX -= pRowInfo[0].pCellInfo[rOverX+1].nWidth;
880             bHOver = pRowInfo[nArrY].pCellInfo[rOverX+1].bHOverlapped;
881             bVOver = pRowInfo[nArrY].pCellInfo[rOverX+1].bVOverlapped;
882         }
883         else
884         {
885 //          if (!bClipVirt)
886 //              rVirtPosX -= (long) (pDoc->GetColWidth( rOverX, nTab ) * nPPTX);
887             sal_uInt16 nOverlap = ((ScMergeFlagAttr*)pDoc->GetAttr(
888                                 rOverX, rOverY, nTab, ATTR_MERGE_FLAG ))->GetValue();
889             bHOver = ((nOverlap & SC_MF_HOR) != 0);
890             bVOver = ((nOverlap & SC_MF_VER) != 0);
891         }
892     }
893 
894     while (bVOver)
895     {
896         --rOverY;
897         bHidden = pDoc->RowHidden(rOverY, nTab);
898         if ( !bDoMerge && !bHidden )
899             return sal_False;
900 
901         if (nArrY>0)
902             --nArrY;                        // lokale Kopie !
903 
904         if (rOverX >= nX1 && rOverY >= nY1 &&
905             !pDoc->ColHidden(rOverX, nTab) &&
906             !pDoc->RowHidden(rOverY, nTab) &&
907             pRowInfo[nArrY].nRowNo == rOverY)
908         {
909 //          rVirtPosY -= pRowInfo[nArrY].nHeight;
910             bHOver = pRowInfo[nArrY].pCellInfo[rOverX+1].bHOverlapped;
911             bVOver = pRowInfo[nArrY].pCellInfo[rOverX+1].bVOverlapped;
912         }
913         else
914         {
915 //          if (!bClipVirt)
916 //              rVirtPosY -= (long) (pDoc->GetRowHeight( rOverY, nTab ) * nPPTY);
917             sal_uInt16 nOverlap = ((ScMergeFlagAttr*)pDoc->GetAttr(
918                                 rOverX, rOverY, nTab, ATTR_MERGE_FLAG ))->GetValue();
919             bHOver = ((nOverlap & SC_MF_HOR) != 0);
920             bVOver = ((nOverlap & SC_MF_VER) != 0);
921         }
922     }
923 
924     return sal_True;
925 }
926 
StringDiffer(const ScPatternAttr * & rpOldPattern,const ScPatternAttr * & rpNewPattern)927 inline sal_Bool StringDiffer( const ScPatternAttr*& rpOldPattern, const ScPatternAttr*& rpNewPattern )
928 {
929     DBG_ASSERT( rpNewPattern, "pNewPattern" );
930 
931     if ( rpNewPattern == rpOldPattern )
932         return sal_False;
933     else if ( !rpOldPattern )
934         return sal_True;
935     else if ( &rpNewPattern->GetItem( ATTR_FONT ) != &rpOldPattern->GetItem( ATTR_FONT ) )
936         return sal_True;
937     else if ( &rpNewPattern->GetItem( ATTR_CJK_FONT ) != &rpOldPattern->GetItem( ATTR_CJK_FONT ) )
938         return sal_True;
939     else if ( &rpNewPattern->GetItem( ATTR_CTL_FONT ) != &rpOldPattern->GetItem( ATTR_CTL_FONT ) )
940         return sal_True;
941     else if ( &rpNewPattern->GetItem( ATTR_FONT_HEIGHT ) != &rpOldPattern->GetItem( ATTR_FONT_HEIGHT ) )
942         return sal_True;
943     else if ( &rpNewPattern->GetItem( ATTR_CJK_FONT_HEIGHT ) != &rpOldPattern->GetItem( ATTR_CJK_FONT_HEIGHT ) )
944         return sal_True;
945     else if ( &rpNewPattern->GetItem( ATTR_CTL_FONT_HEIGHT ) != &rpOldPattern->GetItem( ATTR_CTL_FONT_HEIGHT ) )
946         return sal_True;
947     else if ( &rpNewPattern->GetItem( ATTR_FONT_WEIGHT ) != &rpOldPattern->GetItem( ATTR_FONT_WEIGHT ) )
948         return sal_True;
949     else if ( &rpNewPattern->GetItem( ATTR_CJK_FONT_WEIGHT ) != &rpOldPattern->GetItem( ATTR_CJK_FONT_WEIGHT ) )
950         return sal_True;
951     else if ( &rpNewPattern->GetItem( ATTR_CTL_FONT_WEIGHT ) != &rpOldPattern->GetItem( ATTR_CTL_FONT_WEIGHT ) )
952         return sal_True;
953     else if ( &rpNewPattern->GetItem( ATTR_FONT_POSTURE ) != &rpOldPattern->GetItem( ATTR_FONT_POSTURE ) )
954         return sal_True;
955     else if ( &rpNewPattern->GetItem( ATTR_CJK_FONT_POSTURE ) != &rpOldPattern->GetItem( ATTR_CJK_FONT_POSTURE ) )
956         return sal_True;
957     else if ( &rpNewPattern->GetItem( ATTR_CTL_FONT_POSTURE ) != &rpOldPattern->GetItem( ATTR_CTL_FONT_POSTURE ) )
958         return sal_True;
959     else if ( &rpNewPattern->GetItem( ATTR_FONT_UNDERLINE ) != &rpOldPattern->GetItem( ATTR_FONT_UNDERLINE ) )
960         return sal_True;
961     else if ( &rpNewPattern->GetItem( ATTR_FONT_OVERLINE ) != &rpOldPattern->GetItem( ATTR_FONT_OVERLINE ) )
962         return sal_True;
963     else if ( &rpNewPattern->GetItem( ATTR_FONT_WORDLINE ) != &rpOldPattern->GetItem( ATTR_FONT_WORDLINE ) )
964         return sal_True;
965     else if ( &rpNewPattern->GetItem( ATTR_FONT_CROSSEDOUT ) != &rpOldPattern->GetItem( ATTR_FONT_CROSSEDOUT ) )
966         return sal_True;
967     else if ( &rpNewPattern->GetItem( ATTR_FONT_CONTOUR ) != &rpOldPattern->GetItem( ATTR_FONT_CONTOUR ) )
968         return sal_True;
969     else if ( &rpNewPattern->GetItem( ATTR_FONT_SHADOWED ) != &rpOldPattern->GetItem( ATTR_FONT_SHADOWED ) )
970         return sal_True;
971     else if ( &rpNewPattern->GetItem( ATTR_FONT_COLOR ) != &rpOldPattern->GetItem( ATTR_FONT_COLOR ) )
972         return sal_True;
973     else if ( &rpNewPattern->GetItem( ATTR_HOR_JUSTIFY ) != &rpOldPattern->GetItem( ATTR_HOR_JUSTIFY ) )
974         return sal_True;
975     else if ( &rpNewPattern->GetItem( ATTR_VER_JUSTIFY ) != &rpOldPattern->GetItem( ATTR_VER_JUSTIFY ) )
976         return sal_True;
977     else if ( &rpNewPattern->GetItem( ATTR_STACKED ) != &rpOldPattern->GetItem( ATTR_STACKED ) )
978         return sal_True;
979     else if ( &rpNewPattern->GetItem( ATTR_LINEBREAK ) != &rpOldPattern->GetItem( ATTR_LINEBREAK ) )
980         return sal_True;
981     else if ( &rpNewPattern->GetItem( ATTR_MARGIN ) != &rpOldPattern->GetItem( ATTR_MARGIN ) )
982         return sal_True;
983     else if ( &rpNewPattern->GetItem( ATTR_ROTATE_VALUE ) != &rpOldPattern->GetItem( ATTR_ROTATE_VALUE ) )
984         return sal_True;
985     else if ( &rpNewPattern->GetItem( ATTR_FORBIDDEN_RULES ) != &rpOldPattern->GetItem( ATTR_FORBIDDEN_RULES ) )
986         return sal_True;
987     else if ( &rpNewPattern->GetItem( ATTR_FONT_EMPHASISMARK ) != &rpOldPattern->GetItem( ATTR_FONT_EMPHASISMARK ) )
988         return sal_True;
989     else if ( &rpNewPattern->GetItem( ATTR_FONT_RELIEF ) != &rpOldPattern->GetItem( ATTR_FONT_RELIEF ) )
990         return sal_True;
991     else if ( &rpNewPattern->GetItem( ATTR_BACKGROUND ) != &rpOldPattern->GetItem( ATTR_BACKGROUND ) )
992         return sal_True;    // needed with automatic text color
993     else
994     {
995         rpOldPattern = rpNewPattern;
996         return sal_False;
997     }
998 }
999 
lcl_CreateInterpretProgress(sal_Bool & bProgress,ScDocument * pDoc,ScFormulaCell * pFCell)1000 inline void lcl_CreateInterpretProgress( sal_Bool& bProgress, ScDocument* pDoc,
1001         ScFormulaCell* pFCell )
1002 {
1003     if ( !bProgress && pFCell->GetDirty() )
1004     {
1005         ScProgress::CreateInterpretProgress( pDoc, sal_True );
1006         bProgress = sal_True;
1007     }
1008 }
1009 
GetScriptType(ScDocument * pDoc,ScBaseCell * pCell,const ScPatternAttr * pPattern,const SfxItemSet * pCondSet)1010 inline sal_uInt8 GetScriptType( ScDocument* pDoc, ScBaseCell* pCell,
1011                             const ScPatternAttr* pPattern,
1012                             const SfxItemSet* pCondSet )
1013 {
1014     return pDoc->GetCellScriptType( pCell, pPattern->GetNumberFormat( pDoc->GetFormatTable(), pCondSet ) );
1015 }
1016 
IsAmbiguousScript(sal_uInt8 nScript)1017 inline sal_Bool IsAmbiguousScript( sal_uInt8 nScript )
1018 {
1019     return ( nScript != SCRIPTTYPE_LATIN &&
1020              nScript != SCRIPTTYPE_ASIAN &&
1021              nScript != SCRIPTTYPE_COMPLEX );
1022 }
1023 
IsEmptyCellText(RowInfo * pThisRowInfo,SCCOL nX,SCROW nY)1024 sal_Bool ScOutputData::IsEmptyCellText( RowInfo* pThisRowInfo, SCCOL nX, SCROW nY )
1025 {
1026     // pThisRowInfo may be NULL
1027 
1028     sal_Bool bEmpty;
1029     if ( pThisRowInfo && nX <= nX2 )
1030         bEmpty = pThisRowInfo->pCellInfo[nX+1].bEmptyCellText;
1031     else
1032         bEmpty = ( pDoc->GetCell( ScAddress( nX, nY, nTab ) ) == NULL );
1033 
1034     if ( !bEmpty && ( nX < nX1 || nX > nX2 || !pThisRowInfo ) )
1035     {
1036         //  for the range nX1..nX2 in RowInfo, cell protection attribute is already evaluated
1037         //  into bEmptyCellText in ScDocument::FillInfo / lcl_HidePrint (printfun)
1038 
1039         sal_Bool bIsPrint = ( eType == OUTTYPE_PRINTER );
1040 
1041         if ( bIsPrint || bTabProtected )
1042         {
1043             const ScProtectionAttr* pAttr = (const ScProtectionAttr*)
1044                     pDoc->GetEffItem( nX, nY, nTab, ATTR_PROTECTION );
1045             if ( bIsPrint && pAttr->GetHidePrint() )
1046                 bEmpty = sal_True;
1047             else if ( bTabProtected )
1048             {
1049                 if ( pAttr->GetHideCell() )
1050                     bEmpty = sal_True;
1051                 else if ( bShowFormulas && pAttr->GetHideFormula() )
1052                 {
1053                     ScBaseCell* pCell = pDoc->GetCell( ScAddress( nX, nY, nTab ) );
1054                     if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA )
1055                         bEmpty = sal_True;
1056                 }
1057             }
1058         }
1059     }
1060     return bEmpty;
1061 }
1062 
GetVisibleCell(SCCOL nCol,SCROW nRow,SCTAB nTabP,ScBaseCell * & rpCell)1063 void ScOutputData::GetVisibleCell( SCCOL nCol, SCROW nRow, SCTAB nTabP, ScBaseCell*& rpCell )
1064 {
1065     pDoc->GetCell( nCol, nRow, nTabP, rpCell );
1066     if ( rpCell && IsEmptyCellText( NULL, nCol, nRow ) )
1067         rpCell = NULL;
1068 }
1069 
IsAvailable(SCCOL nX,SCROW nY)1070 sal_Bool ScOutputData::IsAvailable( SCCOL nX, SCROW nY )
1071 {
1072     //  apply the same logic here as in DrawStrings/DrawEdit:
1073     //  Stop at non-empty or merged or overlapped cell,
1074     //  where a note is empty as well as a cell that's hidden by protection settings
1075 
1076     const ScBaseCell* pCell = pDoc->GetCell( ScAddress( nX, nY, nTab ) );
1077     if ( pCell && pCell->GetCellType() != CELLTYPE_NOTE && !IsEmptyCellText( NULL, nX, nY ) )
1078     {
1079         return sal_False;
1080     }
1081 
1082     const ScPatternAttr* pPattern = pDoc->GetPattern( nX, nY, nTab );
1083     if ( ((const ScMergeAttr&)pPattern->GetItem(ATTR_MERGE)).IsMerged() ||
1084          ((const ScMergeFlagAttr&)pPattern->GetItem(ATTR_MERGE_FLAG)).IsOverlapped() )
1085     {
1086         return sal_False;
1087     }
1088 
1089     return sal_True;
1090 }
1091 
1092 // nX, nArrY:       loop variables from DrawStrings / DrawEdit
1093 // nPosX, nPosY:    corresponding positions for nX, nArrY
1094 // nCellX, nCellY:  position of the cell that contains the text
1095 // nNeeded:         Text width, including margin
1096 // rPattern:        cell format at nCellX, nCellY
1097 // nHorJustify:     horizontal alignment (visual) to determine which cells to use for long strings
1098 // bCellIsValue:    if set, don't extend into empty cells
1099 // bBreak:          if set, don't extend, and don't set clip marks (but rLeftClip/rRightClip is set)
1100 // bOverwrite:      if set, also extend into non-empty cells (for rotated text)
1101 // rParam           output: various area parameters.
1102 
GetOutputArea(SCCOL nX,SCSIZE nArrY,long nPosX,long nPosY,SCCOL nCellX,SCROW nCellY,long nNeeded,const ScPatternAttr & rPattern,sal_uInt16 nHorJustify,bool bCellIsValue,bool bBreak,bool bOverwrite,OutputAreaParam & rParam)1103 void ScOutputData::GetOutputArea( SCCOL nX, SCSIZE nArrY, long nPosX, long nPosY,
1104                                   SCCOL nCellX, SCROW nCellY, long nNeeded,
1105                                   const ScPatternAttr& rPattern,
1106                                   sal_uInt16 nHorJustify, bool bCellIsValue,
1107                                   bool bBreak, bool bOverwrite,
1108                                   OutputAreaParam& rParam )
1109 {
1110     //  rThisRowInfo may be for a different row than nCellY, is still used for clip marks
1111     RowInfo& rThisRowInfo = pRowInfo[nArrY];
1112 
1113     long nLayoutSign = bLayoutRTL ? -1 : 1;
1114 
1115     long nCellPosX = nPosX;         // find nCellX position, starting at nX/nPosX
1116     SCCOL nCompCol = nX;
1117     while ( nCellX > nCompCol )
1118     {
1119         //! extra member function for width?
1120         long nColWidth = ( nCompCol <= nX2 ) ?
1121                 pRowInfo[0].pCellInfo[nCompCol+1].nWidth :
1122                 (long) ( pDoc->GetColWidth( nCompCol, nTab ) * nPPTX );
1123         nCellPosX += nColWidth * nLayoutSign;
1124         ++nCompCol;
1125     }
1126     while ( nCellX < nCompCol )
1127     {
1128         --nCompCol;
1129         long nColWidth = ( nCompCol <= nX2 ) ?
1130                 pRowInfo[0].pCellInfo[nCompCol+1].nWidth :
1131                 (long) ( pDoc->GetColWidth( nCompCol, nTab ) * nPPTX );
1132         nCellPosX -= nColWidth * nLayoutSign;
1133     }
1134 
1135     long nCellPosY = nPosY;         // find nCellY position, starting at nArrY/nPosY
1136     SCSIZE nCompArr = nArrY;
1137     SCROW nCompRow = pRowInfo[nCompArr].nRowNo;
1138     while ( nCellY > nCompRow )
1139     {
1140         if ( nCompArr + 1 < nArrCount )
1141         {
1142             nCellPosY += pRowInfo[nCompArr].nHeight;
1143             ++nCompArr;
1144             nCompRow = pRowInfo[nCompArr].nRowNo;
1145         }
1146         else
1147         {
1148             sal_uInt16 nDocHeight = pDoc->GetRowHeight( nCompRow, nTab );
1149             if ( nDocHeight )
1150                 nCellPosY += (long) ( nDocHeight * nPPTY );
1151             ++nCompRow;
1152         }
1153     }
1154     nCellPosY -= (long) pDoc->GetScaledRowHeight( nCellY, nCompRow-1, nTab, nPPTY );
1155 
1156     const ScMergeAttr* pMerge = (const ScMergeAttr*)&rPattern.GetItem( ATTR_MERGE );
1157     sal_Bool bMerged = pMerge->IsMerged();
1158     long nMergeCols = pMerge->GetColMerge();
1159     if ( nMergeCols == 0 )
1160         nMergeCols = 1;
1161     long nMergeRows = pMerge->GetRowMerge();
1162     if ( nMergeRows == 0 )
1163         nMergeRows = 1;
1164 
1165     long i;
1166     long nMergeSizeX = 0;
1167     for ( i=0; i<nMergeCols; i++ )
1168     {
1169         long nColWidth = ( nCellX+i <= nX2 ) ?
1170                 pRowInfo[0].pCellInfo[nCellX+i+1].nWidth :
1171                 (long) ( pDoc->GetColWidth( sal::static_int_cast<SCCOL>(nCellX+i), nTab ) * nPPTX );
1172         nMergeSizeX += nColWidth;
1173     }
1174     long nMergeSizeY = 0;
1175     short nDirect = 0;
1176     if ( rThisRowInfo.nRowNo == nCellY )
1177     {
1178         // take first row's height from row info
1179         nMergeSizeY += rThisRowInfo.nHeight;
1180         nDirect = 1;        // skip in loop
1181     }
1182     // following rows always from document
1183     nMergeSizeY += (long) pDoc->GetScaledRowHeight( nCellY+nDirect, nCellY+nMergeRows-1, nTab, nPPTY);
1184 
1185     --nMergeSizeX;      // leave out the grid horizontally, also for alignment (align between grid lines)
1186 
1187     rParam.mnColWidth = nMergeSizeX; // store the actual column width.
1188 
1189     //
1190     // construct the rectangles using logical left/right values (justify is called at the end)
1191     //
1192 
1193     //  rAlignRect is the single cell or merged area, used for alignment.
1194 
1195     rParam.maAlignRect.Left() = nCellPosX;
1196     rParam.maAlignRect.Right() = nCellPosX + ( nMergeSizeX - 1 ) * nLayoutSign;
1197     rParam.maAlignRect.Top() = nCellPosY;
1198     rParam.maAlignRect.Bottom() = nCellPosY + nMergeSizeY - 1;
1199 
1200     //  rClipRect is all cells that are used for output.
1201     //  For merged cells this is the same as rAlignRect, otherwise neighboring cells can also be used.
1202 
1203     rParam.maClipRect = rParam.maAlignRect;
1204     if ( nNeeded > nMergeSizeX )
1205     {
1206         SvxCellHorJustify eHorJust = (SvxCellHorJustify)nHorJustify;
1207 
1208         long nMissing = nNeeded - nMergeSizeX;
1209         long nLeftMissing = 0;
1210         long nRightMissing = 0;
1211         switch ( eHorJust )
1212         {
1213             case SVX_HOR_JUSTIFY_LEFT:
1214                 nRightMissing = nMissing;
1215                 break;
1216             case SVX_HOR_JUSTIFY_RIGHT:
1217                 nLeftMissing = nMissing;
1218                 break;
1219             case SVX_HOR_JUSTIFY_CENTER:
1220                 nLeftMissing = nMissing / 2;
1221                 nRightMissing = nMissing - nLeftMissing;
1222                 break;
1223             default:
1224             {
1225                 // added to avoid warnings
1226             }
1227         }
1228 
1229         // nLeftMissing, nRightMissing are logical, eHorJust values are visual
1230         if ( bLayoutRTL )
1231             ::std::swap( nLeftMissing, nRightMissing );
1232 
1233         SCCOL nRightX = nCellX;
1234         SCCOL nLeftX = nCellX;
1235         if ( !bMerged && !bCellIsValue && !bBreak )
1236         {
1237             //  look for empty cells into which the text can be extended
1238 
1239             while ( nRightMissing > 0 && nRightX < MAXCOL && ( bOverwrite || IsAvailable( nRightX+1, nCellY ) ) )
1240             {
1241                 ++nRightX;
1242                 long nAdd = (long) ( pDoc->GetColWidth( nRightX, nTab ) * nPPTX );
1243                 nRightMissing -= nAdd;
1244                 rParam.maClipRect.Right() += nAdd * nLayoutSign;
1245 
1246                 if ( rThisRowInfo.nRowNo == nCellY && nRightX >= nX1 && nRightX <= nX2 )
1247                     rThisRowInfo.pCellInfo[nRightX].bHideGrid = sal_True;
1248             }
1249 
1250             while ( nLeftMissing > 0 && nLeftX > 0 && ( bOverwrite || IsAvailable( nLeftX-1, nCellY ) ) )
1251             {
1252                 if ( rThisRowInfo.nRowNo == nCellY && nLeftX >= nX1 && nLeftX <= nX2 )
1253                     rThisRowInfo.pCellInfo[nLeftX].bHideGrid = sal_True;
1254 
1255                 --nLeftX;
1256                 long nAdd = (long) ( pDoc->GetColWidth( nLeftX, nTab ) * nPPTX );
1257                 nLeftMissing -= nAdd;
1258                 rParam.maClipRect.Left() -= nAdd * nLayoutSign;
1259             }
1260         }
1261 
1262         //  Set flag and reserve space for clipping mark triangle,
1263         //  even if rThisRowInfo isn't for nCellY (merged cells).
1264         if ( nRightMissing > 0 && bMarkClipped && nRightX >= nX1 && nRightX <= nX2 && !bBreak && !bCellIsValue )
1265         {
1266             rThisRowInfo.pCellInfo[nRightX+1].nClipMark |= SC_CLIPMARK_RIGHT;
1267             bAnyClipped = sal_True;
1268             long nMarkPixel = (long)( SC_CLIPMARK_SIZE * nPPTX );
1269             rParam.maClipRect.Right() -= nMarkPixel * nLayoutSign;
1270         }
1271         if ( nLeftMissing > 0 && bMarkClipped && nLeftX >= nX1 && nLeftX <= nX2 && !bBreak && !bCellIsValue )
1272         {
1273             rThisRowInfo.pCellInfo[nLeftX+1].nClipMark |= SC_CLIPMARK_LEFT;
1274             bAnyClipped = sal_True;
1275             long nMarkPixel = (long)( SC_CLIPMARK_SIZE * nPPTX );
1276             rParam.maClipRect.Left() += nMarkPixel * nLayoutSign;
1277         }
1278 
1279         rParam.mbLeftClip = ( nLeftMissing > 0 );
1280         rParam.mbRightClip = ( nRightMissing > 0 );
1281     }
1282     else
1283     {
1284         rParam.mbLeftClip = rParam.mbRightClip = sal_False;
1285 
1286         // leave space for AutoFilter on screen
1287         // (for automatic line break: only if not formatting for printer, as in ScColumn::GetNeededSize)
1288 
1289         if ( eType==OUTTYPE_WINDOW &&
1290              ( static_cast<const ScMergeFlagAttr&>(rPattern.GetItem(ATTR_MERGE_FLAG)).GetValue() & SC_MF_AUTO ) &&
1291              ( !bBreak || pRefDevice == pFmtDevice ) )
1292         {
1293             // filter drop-down width is now independent from row height
1294             const long nFilter = DROPDOWN_BITMAP_SIZE;
1295             sal_Bool bFit = ( nNeeded + nFilter <= nMergeSizeX );
1296             if ( bFit || bCellIsValue )
1297             {
1298                 // content fits even in the remaining area without the filter button
1299                 // -> align within that remaining area
1300 
1301                 rParam.maAlignRect.Right() -= nFilter * nLayoutSign;
1302                 rParam.maClipRect.Right() -= nFilter * nLayoutSign;
1303 
1304                 // if a number doesn't fit, don't hide part of the number behind the button
1305                 // -> set clip flags, so "###" replacement is used (but also within the smaller area)
1306 
1307                 if ( !bFit )
1308                     rParam.mbLeftClip = rParam.mbRightClip = sal_True;
1309             }
1310         }
1311     }
1312 
1313     //  justify both rectangles for alignment calculation, use with DrawText etc.
1314 
1315     rParam.maAlignRect.Justify();
1316     rParam.maClipRect.Justify();
1317 
1318 #if 0
1319     //! Test !!!
1320     pDev->Push();
1321     pDev->SetLineColor();
1322     pDev->SetFillColor( COL_LIGHTGREEN );
1323     pDev->DrawRect( pDev->PixelToLogic(rParam.maClipRect) );
1324     pDev->DrawRect( rParam.maClipRect );    // print preview
1325     pDev->Pop();
1326     //! Test !!!
1327 #endif
1328 }
1329 
DrawStrings(sal_Bool bPixelToLogic)1330 void ScOutputData::DrawStrings( sal_Bool bPixelToLogic )
1331 {
1332     DBG_ASSERT( pDev == pRefDevice ||
1333                 pDev->GetMapMode().GetMapUnit() == pRefDevice->GetMapMode().GetMapUnit(),
1334                 "DrawStrings: unterschiedliche MapUnits ?!?!" );
1335 
1336     vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, pDev->GetExtOutDevData() );
1337 
1338     sal_Bool bWasIdleDisabled = pDoc->IsIdleDisabled();
1339     pDoc->DisableIdle( sal_True );
1340     Size aMinSize = pRefDevice->PixelToLogic(Size(0,100));      // erst darueber wird ausgegeben
1341 //    sal_uInt32 nMinHeight = aMinSize.Height() / 200;                // 1/2 Pixel
1342 
1343     ScDrawStringsVars aVars( this, bPixelToLogic );
1344 
1345     sal_Bool bProgress = sal_False;
1346 
1347     long nInitPosX = nScrX;
1348     if ( bLayoutRTL )
1349         nInitPosX += nMirrorW - 1;              // pixels
1350     long nLayoutSign = bLayoutRTL ? -1 : 1;
1351 
1352     SCCOL nLastContentCol = MAXCOL;
1353     if ( nX2 < MAXCOL )
1354         nLastContentCol = sal::static_int_cast<SCCOL>(
1355             nLastContentCol - pDoc->GetEmptyLinesInBlock( nX2+1, nY1, nTab, MAXCOL, nY2, nTab, DIR_RIGHT ) );
1356     SCCOL nLoopStartX = nX1;
1357     if ( nX1 > 0 )
1358         --nLoopStartX;          // start before nX1 for rest of long text to the left
1359 
1360     // variables for GetOutputArea
1361     OutputAreaParam aAreaParam;
1362     sal_Bool bCellIsValue = sal_False;
1363     long nNeededWidth = 0;
1364     SvxCellHorJustify eOutHorJust = SVX_HOR_JUSTIFY_STANDARD;
1365     const ScPatternAttr* pPattern = NULL;
1366     const SfxItemSet* pCondSet = NULL;
1367     const ScPatternAttr* pOldPattern = NULL;
1368     const SfxItemSet* pOldCondSet = NULL;
1369     sal_uInt8 nOldScript = 0;
1370 
1371     long nPosY = nScrY;
1372     for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
1373     {
1374         RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1375         if ( pThisRowInfo->bChanged )
1376         {
1377             SCROW nY = pThisRowInfo->nRowNo;
1378 //            long nCellHeight = (long) pThisRowInfo->nHeight;
1379             long nPosX = nInitPosX;
1380             if ( nLoopStartX < nX1 )
1381                 nPosX -= pRowInfo[0].pCellInfo[nLoopStartX+1].nWidth * nLayoutSign;
1382             for (SCCOL nX=nLoopStartX; nX<=nX2; nX++)
1383             {
1384                 sal_Bool bMergeEmpty = sal_False;
1385                 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
1386                 sal_Bool bEmpty = nX < nX1 || pInfo->bEmptyCellText;
1387 
1388                 SCCOL nCellX = nX;                  // position where the cell really starts
1389                 SCROW nCellY = nY;
1390                 sal_Bool bDoCell = sal_False;
1391                 sal_Bool bNeedEdit = sal_False;
1392 
1393                 //
1394                 //  Part of a merged cell?
1395                 //
1396 
1397                 sal_Bool bOverlapped = ( pInfo->bHOverlapped || pInfo->bVOverlapped );
1398                 if ( bOverlapped )
1399                 {
1400                     bEmpty = sal_True;
1401 
1402                     SCCOL nOverX;                   // start of the merged cells
1403                     SCROW nOverY;
1404                     sal_Bool bVisChanged = !pRowInfo[nArrY-1].bChanged;
1405                     if (GetMergeOrigin( nX,nY, nArrY, nOverX,nOverY, bVisChanged ))
1406                     {
1407                         nCellX = nOverX;
1408                         nCellY = nOverY;
1409                         bDoCell = sal_True;
1410                     }
1411                     else
1412                         bMergeEmpty = sal_True;
1413                 }
1414 
1415                 //
1416                 //  Rest of a long text further to the left?
1417                 //
1418 
1419                 if ( bEmpty && !bMergeEmpty && nX < nX1 && !bOverlapped )
1420                 {
1421                     SCCOL nTempX=nX1;
1422                     while (nTempX > 0 && IsEmptyCellText( pThisRowInfo, nTempX, nY ))
1423                         --nTempX;
1424 
1425                     if ( nTempX < nX1 &&
1426                          !IsEmptyCellText( pThisRowInfo, nTempX, nY ) &&
1427                          !pDoc->HasAttrib( nTempX,nY,nTab, nX1,nY,nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ) )
1428                     {
1429                         nCellX = nTempX;
1430                         bDoCell = sal_True;
1431                     }
1432                 }
1433 
1434                 //
1435                 //  Rest of a long text further to the right?
1436                 //
1437 
1438                 if ( bEmpty && !bMergeEmpty && nX == nX2 && !bOverlapped )
1439                 {
1440                     //  don't have to look further than nLastContentCol
1441 
1442                     SCCOL nTempX=nX;
1443                     while (nTempX < nLastContentCol && IsEmptyCellText( pThisRowInfo, nTempX, nY ))
1444                         ++nTempX;
1445 
1446                     if ( nTempX > nX &&
1447                          !IsEmptyCellText( pThisRowInfo, nTempX, nY ) &&
1448                          !pDoc->HasAttrib( nTempX,nY,nTab, nX,nY,nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ) )
1449                     {
1450                         nCellX = nTempX;
1451                         bDoCell = sal_True;
1452                     }
1453                 }
1454 
1455                 //
1456                 //  normal visible cell
1457                 //
1458 
1459                 if (!bEmpty)
1460                     bDoCell = sal_True;
1461 
1462                 //
1463                 //  don't output the cell that's being edited
1464                 //
1465 
1466                 if ( bDoCell && bEditMode && nCellX == nEditCol && nCellY == nEditRow )
1467                     bDoCell = sal_False;
1468 
1469                 //
1470                 //  output the cell text
1471                 //
1472 
1473                 ScBaseCell* pCell = NULL;
1474                 if (bDoCell)
1475                 {
1476                     if ( nCellY == nY && nCellX == nX && nCellX >= nX1 && nCellX <= nX2 )
1477                         pCell = pThisRowInfo->pCellInfo[nCellX+1].pCell;
1478                     else
1479                         GetVisibleCell( nCellX, nCellY, nTab, pCell );      // get from document
1480                     if ( !pCell )
1481                         bDoCell = sal_False;
1482                     else if ( pCell->GetCellType() == CELLTYPE_EDIT )
1483                         bNeedEdit = sal_True;
1484                 }
1485                 if (bDoCell && !bNeedEdit)
1486                 {
1487                     if ( nCellY == nY && nCellX >= nX1 && nCellX <= nX2 )
1488                     {
1489                         CellInfo& rCellInfo = pThisRowInfo->pCellInfo[nCellX+1];
1490                         pPattern = rCellInfo.pPatternAttr;
1491                         pCondSet = rCellInfo.pConditionSet;
1492 
1493                         if ( !pPattern )
1494                         {
1495                             // #i68085# pattern from cell info for hidden columns is null,
1496                             // test for null is quicker than using column flags
1497                             pPattern = pDoc->GetPattern( nCellX, nCellY, nTab );
1498                             pCondSet = pDoc->GetCondResult( nCellX, nCellY, nTab );
1499                         }
1500                     }
1501                     else        // get from document
1502                     {
1503                         pPattern = pDoc->GetPattern( nCellX, nCellY, nTab );
1504                         pCondSet = pDoc->GetCondResult( nCellX, nCellY, nTab );
1505                     }
1506 
1507                     sal_uInt8 nScript = GetScriptType( pDoc, pCell, pPattern, pCondSet );
1508                     if (nScript == 0) nScript = ScGlobal::GetDefaultScriptType();
1509                     if ( pPattern != pOldPattern || pCondSet != pOldCondSet ||
1510                          nScript != nOldScript || bSyntaxMode )
1511                     {
1512                         if ( StringDiffer(pOldPattern,pPattern) ||
1513                              pCondSet != pOldCondSet || nScript != nOldScript || bSyntaxMode )
1514                             aVars.SetPattern( pPattern, pCondSet, pCell, nScript );
1515                         else
1516                             aVars.SetPatternSimple( pPattern, pCondSet );
1517                         pOldPattern = pPattern;
1518                         pOldCondSet = pCondSet;
1519                         nOldScript = nScript;
1520                     }
1521 
1522                     //  use edit engine for rotated, stacked or mixed-script text
1523                     if ( aVars.GetOrient() == SVX_ORIENTATION_STACKED ||
1524                          aVars.IsRotated() || IsAmbiguousScript(nScript) )
1525                         bNeedEdit = sal_True;
1526                 }
1527                 if (bDoCell && !bNeedEdit)
1528                 {
1529                     sal_Bool bFormulaCell = (pCell->GetCellType() == CELLTYPE_FORMULA );
1530                     if ( bFormulaCell )
1531                         lcl_CreateInterpretProgress( bProgress, pDoc, (ScFormulaCell*)pCell );
1532                     if ( aVars.SetText(pCell) )
1533                         pOldPattern = NULL;
1534                     bNeedEdit = aVars.HasEditCharacters() ||
1535                                     (bFormulaCell && ((ScFormulaCell*)pCell)->IsMultilineResult());
1536                 }
1537                 long nTotalMargin = 0;
1538                 if (bDoCell && !bNeedEdit)
1539                 {
1540                     CellType eCellType = pCell->GetCellType();
1541                     bCellIsValue = ( eCellType == CELLTYPE_VALUE );
1542                     if ( eCellType == CELLTYPE_FORMULA )
1543                     {
1544                         ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
1545                         bCellIsValue = pFCell->IsRunning() || pFCell->IsValue();
1546                     }
1547 
1548                     eOutHorJust = ( aVars.GetHorJust() != SVX_HOR_JUSTIFY_STANDARD ) ?
1549                                   aVars.GetHorJust() :
1550                                   ( bCellIsValue ? SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_LEFT );
1551 
1552                     if ( eOutHorJust == SVX_HOR_JUSTIFY_BLOCK || eOutHorJust == SVX_HOR_JUSTIFY_REPEAT )
1553                         eOutHorJust = SVX_HOR_JUSTIFY_LEFT;     // repeat is not yet implemented
1554 
1555                     sal_Bool bBreak = ( aVars.GetLineBreak() || aVars.GetHorJust() == SVX_HOR_JUSTIFY_BLOCK );
1556 
1557                     // #i111387# #o11817313# disable automatic line breaks only for "General" number format
1558                     if ( bBreak && bCellIsValue && ( aVars.GetResultValueFormat(pCell) % SV_COUNTRY_LANGUAGE_OFFSET ) == 0 )
1559                         bBreak = sal_False;
1560 
1561                     sal_Bool bRepeat = aVars.IsRepeat() && !bBreak;
1562                     sal_Bool bShrink = aVars.IsShrink() && !bBreak && !bRepeat;
1563 
1564                     nTotalMargin =
1565                         static_cast<long>(aVars.GetLeftTotal() * nPPTX) +
1566                         static_cast<long>(aVars.GetMargin()->GetRightMargin() * nPPTX);
1567 
1568                     nNeededWidth = aVars.GetTextSize().Width() + nTotalMargin;
1569 
1570                     // GetOutputArea gives justfied rectangles
1571                     GetOutputArea( nX, nArrY, nPosX, nPosY, nCellX, nCellY, nNeededWidth,
1572                                    *pPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
1573                                    bCellIsValue || bRepeat || bShrink, bBreak, sal_False,
1574                                    aAreaParam );
1575 
1576                     if ( bShrink )
1577                     {
1578                         if ( aVars.GetOrient() != SVX_ORIENTATION_STANDARD )
1579                         {
1580                             // Only horizontal scaling is handled here.
1581                             // DrawEdit is used to vertically scale 90 deg rotated text.
1582                             bNeedEdit = sal_True;
1583                         }
1584                         else if ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip )     // horizontal
1585                         {
1586                             long nAvailable = aAreaParam.maAlignRect.GetWidth() - nTotalMargin;
1587                             long nScaleSize = aVars.GetTextSize().Width();         // without margin
1588 
1589                             if ( nScaleSize > 0 )       // 0 if the text is empty (formulas, number formats)
1590                             {
1591                                 long nScale = ( nAvailable * 100 ) / nScaleSize;
1592 
1593                                 aVars.SetShrinkScale( nScale, nOldScript );
1594                                 long nNewSize = aVars.GetTextSize().Width();
1595 
1596                                 sal_uInt16 nShrinkAgain = 0;
1597                                 while ( nNewSize > nAvailable && nShrinkAgain < SC_SHRINKAGAIN_MAX )
1598                                 {
1599                                     // If the text is still too large, reduce the scale again by 10%, until it fits,
1600                                     // at most 7 times (it's less than 50% of the calculated scale then).
1601 
1602                                     nScale = ( nScale * 9 ) / 10;
1603                                     aVars.SetShrinkScale( nScale, nOldScript );
1604                                     nNewSize = aVars.GetTextSize().Width();
1605                                     ++nShrinkAgain;
1606                                 }
1607                                 // If even at half the size the font still isn't rendered smaller,
1608                                 // fall back to normal clipping (showing ### for numbers).
1609                                 if ( nNewSize <= nAvailable )
1610                                     aAreaParam.mbLeftClip = aAreaParam.mbRightClip = sal_False;
1611 
1612                                 pOldPattern = NULL;
1613                             }
1614                         }
1615                     }
1616 
1617                     if ( bRepeat && !aAreaParam.mbLeftClip && !aAreaParam.mbRightClip )
1618                     {
1619                         long nAvailable = aAreaParam.maAlignRect.GetWidth() - nTotalMargin;
1620                         long nRepeatSize = aVars.GetTextSize().Width();         // without margin
1621                         // When formatting for the printer, the text sizes don't always add up.
1622                         // Round down (too few repetitions) rather than exceeding the cell size then:
1623                         if ( pFmtDevice != pRefDevice )
1624                             ++nRepeatSize;
1625                         if ( nRepeatSize > 0 )
1626                         {
1627                             long nRepeatCount = nAvailable / nRepeatSize;
1628                             if ( nRepeatCount > 1 )
1629                             {
1630                                 String aCellStr = aVars.GetString();
1631                                 String aRepeated = aCellStr;
1632                                 for ( long nRepeat = 1; nRepeat < nRepeatCount; nRepeat++ )
1633                                     aRepeated.Append( aCellStr );
1634                                 aVars.SetAutoText( aRepeated );
1635                             }
1636                         }
1637                     }
1638 
1639                     //  use edit engine if automatic line breaks are needed
1640                     if ( bBreak )
1641                     {
1642                         if ( aVars.GetOrient() == SVX_ORIENTATION_STANDARD )
1643                             bNeedEdit = ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip );
1644                         else
1645                         {
1646                             long nHeight = aVars.GetTextSize().Height() +
1647                                             (long)(aVars.GetMargin()->GetTopMargin()*nPPTY) +
1648                                             (long)(aVars.GetMargin()->GetBottomMargin()*nPPTY);
1649                             bNeedEdit = ( nHeight > aAreaParam.maClipRect.GetHeight() );
1650                         }
1651                     }
1652                 }
1653                 if (bNeedEdit)
1654                 {
1655                     //  mark the cell in CellInfo to be drawn in DrawEdit:
1656                     //  Cells to the left are marked directly, cells to the
1657                     //  right are handled by the flag for nX2
1658                     SCCOL nMarkX = ( nCellX <= nX2 ) ? nCellX : nX2;
1659                     RowInfo* pMarkRowInfo = ( nCellY == nY ) ? pThisRowInfo : &pRowInfo[0];
1660                     pMarkRowInfo->pCellInfo[nMarkX+1].bEditEngine = sal_True;
1661                     bDoCell = sal_False;    // don't draw here
1662                 }
1663                 if ( bDoCell )
1664                 {
1665                     if ( bCellIsValue && ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) )
1666                     {
1667                         // Adjust the decimals to fit the available column width.
1668                         aVars.SetTextToWidthOrHash(pCell, aAreaParam.mnColWidth - nTotalMargin);
1669                         nNeededWidth = aVars.GetTextSize().Width() +
1670                                     (long) ( aVars.GetLeftTotal() * nPPTX ) +
1671                                     (long) ( aVars.GetMargin()->GetRightMargin() * nPPTX );
1672                         if ( nNeededWidth <= aAreaParam.maClipRect.GetWidth() )
1673                             aAreaParam.mbLeftClip = aAreaParam.mbRightClip = sal_False;
1674 
1675                         //  If the "###" replacement doesn't fit into the cells, no clip marks
1676                         //  are shown, as the "###" already denotes too little space.
1677                         //  The rectangles from the first GetOutputArea call remain valid.
1678                     }
1679 
1680                     long nJustPosX = aAreaParam.maAlignRect.Left();     // "justified" - effect of alignment will be added
1681                     long nJustPosY = aAreaParam.maAlignRect.Top();
1682                     long nAvailWidth = aAreaParam.maAlignRect.GetWidth();
1683                     long nOutHeight = aAreaParam.maAlignRect.GetHeight();
1684 
1685                     sal_Bool bOutside = ( aAreaParam.maClipRect.Right() < nScrX || aAreaParam.maClipRect.Left() >= nScrX + nScrW );
1686                     if ( aAreaParam.maClipRect.Left() < nScrX )
1687                     {
1688                         aAreaParam.maClipRect.Left() = nScrX;
1689                         aAreaParam.mbLeftClip = sal_True;
1690                     }
1691                     if ( aAreaParam.maClipRect.Right() > nScrX + nScrW )
1692                     {
1693                         aAreaParam.maClipRect.Right() = nScrX + nScrW;          //! minus one?
1694                         aAreaParam.mbRightClip = sal_True;
1695                     }
1696 
1697                     sal_Bool bHClip = aAreaParam.mbLeftClip || aAreaParam.mbRightClip;
1698                     sal_Bool bVClip = sal_False;
1699 
1700                     if ( aAreaParam.maClipRect.Top() < nScrY )
1701                     {
1702                         aAreaParam.maClipRect.Top() = nScrY;
1703                         bVClip = sal_True;
1704                     }
1705                     if ( aAreaParam.maClipRect.Bottom() > nScrY + nScrH )
1706                     {
1707                         aAreaParam.maClipRect.Bottom() = nScrY + nScrH;         //! minus one?
1708                         bVClip = sal_True;
1709                     }
1710 
1711                     //
1712                     //      horizontalen Platz testen
1713                     //
1714 
1715                     sal_Bool bRightAdjusted = sal_False;        // to correct text width calculation later
1716                     sal_Bool bNeedEditEngine = sal_False;
1717                     if ( !bNeedEditEngine && !bOutside )
1718                     {
1719                         switch (eOutHorJust)
1720                         {
1721                             case SVX_HOR_JUSTIFY_LEFT:
1722                                 nJustPosX += (long) ( aVars.GetLeftTotal() * nPPTX );
1723                                 break;
1724                             case SVX_HOR_JUSTIFY_RIGHT:
1725                                 nJustPosX += nAvailWidth - aVars.GetTextSize().Width() -
1726                                             (long) ( aVars.GetMargin()->GetRightMargin() * nPPTX );
1727                                 bRightAdjusted = sal_True;
1728                                 break;
1729                             case SVX_HOR_JUSTIFY_CENTER:
1730                                 nJustPosX += ( nAvailWidth - aVars.GetTextSize().Width() +
1731                                             (long) ( aVars.GetLeftTotal() * nPPTX ) -
1732                                             (long) ( aVars.GetMargin()->GetRightMargin() * nPPTX ) ) / 2;
1733                                 break;
1734                             default:
1735                             {
1736                                 // added to avoid warnings
1737                             }
1738                         }
1739 
1740                         long nTestClipHeight = aVars.GetTextSize().Height();
1741                         switch (aVars.GetVerJust())
1742                         {
1743                             case SVX_VER_JUSTIFY_TOP:
1744                                 {
1745                                     long nTop = (long)( aVars.GetMargin()->GetTopMargin() * nPPTY );
1746                                     nJustPosY += nTop;
1747                                     nTestClipHeight += nTop;
1748                                 }
1749                                 break;
1750                             case SVX_VER_JUSTIFY_BOTTOM:
1751                                 {
1752                                     long nBot = (long)( aVars.GetMargin()->GetBottomMargin() * nPPTY );
1753                                     nJustPosY += nOutHeight - aVars.GetTextSize().Height() - nBot;
1754                                     nTestClipHeight += nBot;
1755                                 }
1756                                 break;
1757                             case SVX_VER_JUSTIFY_CENTER:
1758                                 {
1759                                     long nTop = (long)( aVars.GetMargin()->GetTopMargin() * nPPTY );
1760                                     long nBot = (long)( aVars.GetMargin()->GetBottomMargin() * nPPTY );
1761                                     nJustPosY += ( nOutHeight + nTop -
1762                                                     aVars.GetTextSize().Height() - nBot ) / 2;
1763                                     nTestClipHeight += Abs( nTop - nBot );
1764                                 }
1765                                 break;
1766                             default:
1767                             {
1768                                 // added to avoid warnings
1769                             }
1770                         }
1771 
1772                         if ( nTestClipHeight > nOutHeight )
1773                         {
1774                             //  kein vertikales Clipping beim Drucken von Zellen mit
1775                             //  optimaler Hoehe, ausser bei Groesse in bedingter Formatierung
1776                             if ( eType != OUTTYPE_PRINTER ||
1777                                     ( pDoc->GetRowFlags( nCellY, nTab ) & CR_MANUALSIZE ) ||
1778                                     ( aVars.HasCondHeight() ) )
1779                                 bVClip = sal_True;
1780                         }
1781 
1782                         if ( bHClip || bVClip )
1783                         {
1784                             //  nur die betroffene Dimension clippen,
1785                             //  damit bei nicht-proportionalem Resize nicht alle
1786                             //  rechtsbuendigen Zahlen abgeschnitten werden:
1787 
1788                             if (!bHClip)
1789                             {
1790                                 aAreaParam.maClipRect.Left() = nScrX;
1791                                 aAreaParam.maClipRect.Right() = nScrX+nScrW;
1792                             }
1793                             if (!bVClip)
1794                             {
1795                                 aAreaParam.maClipRect.Top() = nScrY;
1796                                 aAreaParam.maClipRect.Bottom() = nScrY+nScrH;
1797                             }
1798 
1799                             //  aClipRect is not used after SetClipRegion/IntersectClipRegion,
1800                             //  so it can be modified here
1801                             if (bPixelToLogic)
1802                                 aAreaParam.maClipRect = pRefDevice->PixelToLogic( aAreaParam.maClipRect );
1803 
1804                             if (bMetaFile)
1805                             {
1806                                 pDev->Push();
1807                                 pDev->IntersectClipRegion( aAreaParam.maClipRect );
1808                             }
1809                             else
1810                                 pDev->SetClipRegion( Region( aAreaParam.maClipRect ) );
1811                         }
1812 
1813                         Point aURLStart( nJustPosX, nJustPosY );    // copy before modifying for orientation
1814 
1815                         switch (aVars.GetOrient())
1816                         {
1817                             case SVX_ORIENTATION_STANDARD:
1818                                 nJustPosY += aVars.GetAscent();
1819                                 break;
1820                             case SVX_ORIENTATION_TOPBOTTOM:
1821                                 nJustPosX += aVars.GetTextSize().Width() - aVars.GetAscent();
1822                                 break;
1823                             case SVX_ORIENTATION_BOTTOMTOP:
1824                                 nJustPosY += aVars.GetTextSize().Height();
1825                                 nJustPosX += aVars.GetAscent();
1826                                 break;
1827                             default:
1828                             {
1829                                 // added to avoid warnings
1830                             }
1831                         }
1832 
1833                         // When clipping, the visible part is now completely defined by the alignment,
1834                         // there's no more special handling to show the right part of RTL text.
1835 
1836                         Point aDrawTextPos( nJustPosX, nJustPosY );
1837                         if ( bPixelToLogic )
1838                         {
1839                             //  undo text width adjustment in pixels
1840                             if (bRightAdjusted)
1841                                 aDrawTextPos.X() += aVars.GetTextSize().Width();
1842 
1843                             aDrawTextPos = pRefDevice->PixelToLogic( aDrawTextPos );
1844 
1845                             //  redo text width adjustment in logic units
1846                             if (bRightAdjusted)
1847                                 aDrawTextPos.X() -= aVars.GetOriginalWidth();
1848                         }
1849 
1850                         //  in Metafiles immer DrawTextArray, damit die Positionen mit
1851                         //  aufgezeichnet werden (fuer nicht-proportionales Resize):
1852 
1853                         String aString = aVars.GetString();
1854                         if (bMetaFile || pFmtDevice != pDev || aZoomX != aZoomY)
1855                         {
1856                             sal_Int32* pDX = new sal_Int32[aString.Len()];
1857                             pFmtDevice->GetTextArray( aString, pDX );
1858 
1859                             if ( !pRefDevice->GetConnectMetaFile() ||
1860                                     pRefDevice->GetOutDevType() == OUTDEV_PRINTER )
1861                             {
1862                                 double fMul = GetStretch();
1863                                 xub_StrLen nLen = aString.Len();
1864                                 for (xub_StrLen i=0; i<nLen; i++)
1865                                     pDX[i] = (long)(pDX[i] / fMul + 0.5);
1866                             }
1867 
1868                             pDev->DrawTextArray( aDrawTextPos, aString, pDX );
1869                             delete[] pDX;
1870                         }
1871                         else
1872                             pDev->DrawText( aDrawTextPos, aString );
1873 
1874                         if ( bHClip || bVClip )
1875                         {
1876                             if (bMetaFile)
1877                                 pDev->Pop();
1878                             else
1879                                 pDev->SetClipRegion();
1880                         }
1881 
1882                         // PDF: whole-cell hyperlink from formula?
1883                         sal_Bool bHasURL = pPDFData && pCell && pCell->GetCellType() == CELLTYPE_FORMULA &&
1884                                         static_cast<ScFormulaCell*>(pCell)->IsHyperLinkCell();
1885                         if ( bHasURL )
1886                         {
1887                             Rectangle aURLRect( aURLStart, aVars.GetTextSize() );
1888                             lcl_DoHyperlinkResult( pDev, aURLRect, pCell );
1889                         }
1890                     }
1891                 }
1892                 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
1893             }
1894         }
1895         nPosY += pRowInfo[nArrY].nHeight;
1896     }
1897     if ( bProgress )
1898         ScProgress::DeleteInterpretProgress();
1899     pDoc->DisableIdle( bWasIdleDisabled );
1900 }
1901 
1902 //  -------------------------------------------------------------------------------
1903 
CreateOutputEditEngine()1904 ScFieldEditEngine* ScOutputData::CreateOutputEditEngine()
1905 {
1906     ScFieldEditEngine* pEngine = new ScFieldEditEngine( pDoc->GetEnginePool() );
1907     pEngine->SetUpdateMode( sal_False );
1908     // a RefDevice always has to be set, otherwise EditEngine would create a VirtualDevice
1909     pEngine->SetRefDevice( pFmtDevice );
1910     sal_uInt32 nCtrl = pEngine->GetControlWord();
1911     if ( bShowSpellErrors )
1912         nCtrl |= EE_CNTRL_ONLINESPELLING;
1913     if ( eType == OUTTYPE_PRINTER )
1914         nCtrl &= ~EE_CNTRL_MARKFIELDS;
1915     if ( eType == OUTTYPE_WINDOW && pRefDevice == pFmtDevice )
1916         nCtrl &= ~EE_CNTRL_FORMAT100;       // use the actual MapMode
1917     pEngine->SetControlWord( nCtrl );
1918     pDoc->ApplyAsianEditSettings( *pEngine );
1919     pEngine->EnableAutoColor( bUseStyleColor );
1920     pEngine->SetDefaultHorizontalTextDirection( (EEHorizontalTextDirection)pDoc->GetEditTextDirection( nTab ) );
1921     return pEngine;
1922 }
1923 
lcl_ClearEdit(EditEngine & rEngine)1924 void lcl_ClearEdit( EditEngine& rEngine )       // Text und Attribute
1925 {
1926     rEngine.SetUpdateMode( sal_False );
1927 
1928     rEngine.SetText(EMPTY_STRING);
1929     //  keine Para-Attribute uebrigbehalten...
1930     const SfxItemSet& rPara = rEngine.GetParaAttribs(0);
1931     if (rPara.Count())
1932         rEngine.SetParaAttribs( 0,
1933                     SfxItemSet( *rPara.GetPool(), rPara.GetRanges() ) );
1934 }
1935 
lcl_SafeIsValue(ScBaseCell * pCell)1936 sal_Bool lcl_SafeIsValue( ScBaseCell* pCell )
1937 {
1938     if (!pCell)
1939         return sal_False;
1940 
1941     sal_Bool bRet = sal_False;
1942     switch ( pCell->GetCellType() )
1943     {
1944         case CELLTYPE_VALUE:
1945             bRet = sal_True;
1946             break;
1947         case CELLTYPE_FORMULA:
1948             {
1949                 ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
1950                 if ( pFCell->IsRunning() || pFCell->IsValue() )
1951                     bRet = sal_True;
1952             }
1953             break;
1954         default:
1955         {
1956             // added to avoid warnings
1957         }
1958     }
1959     return bRet;
1960 }
1961 
lcl_ScaleFonts(EditEngine & rEngine,long nPercent)1962 void lcl_ScaleFonts( EditEngine& rEngine, long nPercent )
1963 {
1964     sal_Bool bUpdateMode = rEngine.GetUpdateMode();
1965     if ( bUpdateMode )
1966         rEngine.SetUpdateMode( sal_False );
1967 
1968     sal_uInt16 nParCount = rEngine.GetParagraphCount();
1969     for (sal_uInt16 nPar=0; nPar<nParCount; nPar++)
1970     {
1971         SvUShorts aPortions;
1972         rEngine.GetPortions( nPar, aPortions );
1973 
1974         sal_uInt16 nPCount = aPortions.Count();
1975         sal_uInt16 nStart = 0;
1976         for ( sal_uInt16 nPos=0; nPos<nPCount; nPos++ )
1977         {
1978             sal_uInt16 nEnd = aPortions.GetObject( nPos );
1979             ESelection aSel( nPar, nStart, nPar, nEnd );
1980             SfxItemSet aAttribs = rEngine.GetAttribs( aSel );
1981 
1982             long nWestern = static_cast<const SvxFontHeightItem&>(aAttribs.Get(EE_CHAR_FONTHEIGHT)).GetHeight();
1983             long nCJK = static_cast<const SvxFontHeightItem&>(aAttribs.Get(EE_CHAR_FONTHEIGHT_CJK)).GetHeight();
1984             long nCTL = static_cast<const SvxFontHeightItem&>(aAttribs.Get(EE_CHAR_FONTHEIGHT_CTL)).GetHeight();
1985 
1986             nWestern = ( nWestern * nPercent ) / 100;
1987             nCJK     = ( nCJK     * nPercent ) / 100;
1988             nCTL     = ( nCTL     * nPercent ) / 100;
1989 
1990             aAttribs.Put( SvxFontHeightItem( nWestern, 100, EE_CHAR_FONTHEIGHT ) );
1991             aAttribs.Put( SvxFontHeightItem( nCJK, 100, EE_CHAR_FONTHEIGHT_CJK ) );
1992             aAttribs.Put( SvxFontHeightItem( nCTL, 100, EE_CHAR_FONTHEIGHT_CTL ) );
1993 
1994             rEngine.QuickSetAttribs( aAttribs, aSel );      //! remove paragraph attributes from aAttribs?
1995 
1996             nStart = nEnd;
1997         }
1998     }
1999 
2000     if ( bUpdateMode )
2001         rEngine.SetUpdateMode( sal_True );
2002 }
2003 
lcl_GetEditSize(EditEngine & rEngine,sal_Bool bWidth,sal_Bool bSwap,long nAttrRotate)2004 long lcl_GetEditSize( EditEngine& rEngine, sal_Bool bWidth, sal_Bool bSwap, long nAttrRotate )
2005 {
2006     if ( bSwap )
2007         bWidth = !bWidth;
2008 
2009     if ( nAttrRotate )
2010     {
2011         long nRealWidth  = (long) rEngine.CalcTextWidth();
2012         long nRealHeight = rEngine.GetTextHeight();
2013 
2014         // assuming standard mode, otherwise width isn't used
2015 
2016         double nRealOrient = nAttrRotate * F_PI18000;   // 1/100th degrees
2017         double nAbsCos = fabs( cos( nRealOrient ) );
2018         double nAbsSin = fabs( sin( nRealOrient ) );
2019         if ( bWidth )
2020             return (long) ( nRealWidth * nAbsCos + nRealHeight * nAbsSin );
2021         else
2022             return (long) ( nRealHeight * nAbsCos + nRealWidth * nAbsSin );
2023     }
2024     else if ( bWidth )
2025         return (long) rEngine.CalcTextWidth();
2026     else
2027         return rEngine.GetTextHeight();
2028 }
2029 
2030 
ShrinkEditEngine(EditEngine & rEngine,const Rectangle & rAlignRect,long nLeftM,long nTopM,long nRightM,long nBottomM,sal_Bool bWidth,sal_uInt16 nOrient,long nAttrRotate,sal_Bool bPixelToLogic,long & rEngineWidth,long & rEngineHeight,long & rNeededPixel,bool & rLeftClip,bool & rRightClip)2031 void ScOutputData::ShrinkEditEngine( EditEngine& rEngine, const Rectangle& rAlignRect,
2032             long nLeftM, long nTopM, long nRightM, long nBottomM,
2033             sal_Bool bWidth, sal_uInt16 nOrient, long nAttrRotate, sal_Bool bPixelToLogic,
2034             long& rEngineWidth, long& rEngineHeight, long& rNeededPixel, bool& rLeftClip, bool& rRightClip )
2035 {
2036     if ( !bWidth )
2037     {
2038         // vertical
2039 
2040         long nScaleSize = bPixelToLogic ?
2041             pRefDevice->LogicToPixel(Size(0,rEngineHeight)).Height() : rEngineHeight;
2042 
2043         // Don't scale if it fits already.
2044         // Allowing to extend into the margin, to avoid scaling at optimal height.
2045         if ( nScaleSize <= rAlignRect.GetHeight() )
2046             return;
2047 
2048         sal_Bool bSwap = ( nOrient == SVX_ORIENTATION_TOPBOTTOM || nOrient == SVX_ORIENTATION_BOTTOMTOP );
2049         long nAvailable = rAlignRect.GetHeight() - nTopM - nBottomM;
2050         long nScale = ( nAvailable * 100 ) / nScaleSize;
2051 
2052         lcl_ScaleFonts( rEngine, nScale );
2053         rEngineHeight = lcl_GetEditSize( rEngine, sal_False, bSwap, nAttrRotate );
2054         long nNewSize = bPixelToLogic ?
2055             pRefDevice->LogicToPixel(Size(0,rEngineHeight)).Height() : rEngineHeight;
2056 
2057         sal_uInt16 nShrinkAgain = 0;
2058         while ( nNewSize > nAvailable && nShrinkAgain < SC_SHRINKAGAIN_MAX )
2059         {
2060             // further reduce, like in DrawStrings
2061             lcl_ScaleFonts( rEngine, 90 );     // reduce by 10%
2062             rEngineHeight = lcl_GetEditSize( rEngine, sal_False, bSwap, nAttrRotate );
2063             nNewSize = bPixelToLogic ?
2064                 pRefDevice->LogicToPixel(Size(0,rEngineHeight)).Height() : rEngineHeight;
2065             ++nShrinkAgain;
2066         }
2067 
2068         // sizes for further processing (alignment etc):
2069         rEngineWidth = lcl_GetEditSize( rEngine, sal_True, bSwap, nAttrRotate );
2070         long nPixelWidth = bPixelToLogic ?
2071             pRefDevice->LogicToPixel(Size(rEngineWidth,0)).Width() : rEngineWidth;
2072         rNeededPixel = nPixelWidth + nLeftM + nRightM;
2073     }
2074     else if ( rLeftClip || rRightClip )
2075     {
2076         // horizontal
2077 
2078         long nAvailable = rAlignRect.GetWidth() - nLeftM - nRightM;
2079         long nScaleSize = rNeededPixel - nLeftM - nRightM;      // without margin
2080 
2081         if ( nScaleSize <= nAvailable )
2082             return;
2083 
2084         long nScale = ( nAvailable * 100 ) / nScaleSize;
2085 
2086         lcl_ScaleFonts( rEngine, nScale );
2087         rEngineWidth = lcl_GetEditSize( rEngine, sal_True, sal_False, nAttrRotate );
2088         long nNewSize = bPixelToLogic ?
2089             pRefDevice->LogicToPixel(Size(rEngineWidth,0)).Width() : rEngineWidth;
2090 
2091         sal_uInt16 nShrinkAgain = 0;
2092         while ( nNewSize > nAvailable && nShrinkAgain < SC_SHRINKAGAIN_MAX )
2093         {
2094             // further reduce, like in DrawStrings
2095             lcl_ScaleFonts( rEngine, 90 );     // reduce by 10%
2096             rEngineWidth = lcl_GetEditSize( rEngine, sal_True, sal_False, nAttrRotate );
2097             nNewSize = bPixelToLogic ?
2098                 pRefDevice->LogicToPixel(Size(rEngineWidth,0)).Width() : rEngineWidth;
2099             ++nShrinkAgain;
2100         }
2101         if ( nNewSize <= nAvailable )
2102             rLeftClip = rRightClip = sal_False;
2103 
2104         // sizes for further processing (alignment etc):
2105         rNeededPixel = nNewSize + nLeftM + nRightM;
2106         rEngineHeight = lcl_GetEditSize( rEngine, sal_False, sal_False, nAttrRotate );
2107     }
2108 }
2109 
DrawEdit(sal_Bool bPixelToLogic)2110 void ScOutputData::DrawEdit(sal_Bool bPixelToLogic)
2111 {
2112     vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, pDev->GetExtOutDevData() );
2113 
2114     Size aMinSize = pRefDevice->PixelToLogic(Size(0,100));      // erst darueber wird ausgegeben
2115 //    sal_uInt32 nMinHeight = aMinSize.Height() / 200;                // 1/2 Pixel
2116 
2117     ScModule* pScMod = SC_MOD();
2118     sal_Int32 nConfBackColor = pScMod->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor;
2119     //  #105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed sal_True)
2120     sal_Bool bCellContrast = bUseStyleColor &&
2121             Application::GetSettings().GetStyleSettings().GetHighContrastMode();
2122 
2123     ScFieldEditEngine* pEngine = NULL;
2124     sal_Bool bHyphenatorSet = sal_False;
2125     const ScPatternAttr* pOldPattern = NULL;
2126     const SfxItemSet*    pOldCondSet = NULL;
2127     ScBaseCell* pCell = NULL;
2128 
2129     Size aRefOne = pRefDevice->PixelToLogic(Size(1,1));
2130 
2131     long nInitPosX = nScrX;
2132     if ( bLayoutRTL )
2133     {
2134 #if 0
2135         Size aOnePixel = pDev->PixelToLogic(Size(1,1));
2136         long nOneX = aOnePixel.Width();
2137         nInitPosX += nMirrorW - nOneX;
2138 #endif
2139         nInitPosX += nMirrorW - 1;
2140     }
2141     long nLayoutSign = bLayoutRTL ? -1 : 1;
2142 
2143     //! store nLastContentCol as member!
2144     SCCOL nLastContentCol = MAXCOL;
2145     if ( nX2 < MAXCOL )
2146         nLastContentCol = sal::static_int_cast<SCCOL>(
2147             nLastContentCol - pDoc->GetEmptyLinesInBlock( nX2+1, nY1, nTab, MAXCOL, nY2, nTab, DIR_RIGHT ) );
2148 
2149     long nRowPosY = nScrY;
2150     for (SCSIZE nArrY=0; nArrY+1<nArrCount; nArrY++)            // 0 fuer Reste von zusammengefassten
2151     {
2152         RowInfo* pThisRowInfo = &pRowInfo[nArrY];
2153 //        long nCellHeight = (long) pThisRowInfo->nHeight;
2154         if (nArrY==1) nRowPosY = nScrY;                         // vorher wird einzeln berechnet
2155 
2156         if ( pThisRowInfo->bChanged || nArrY==0 )
2157         {
2158             long nPosX = 0;
2159             for (SCCOL nX=0; nX<=nX2; nX++)                 // wegen Ueberhaengen
2160             {
2161                 if (nX==nX1) nPosX = nInitPosX;                 // positions before nX1 are calculated individually
2162 
2163                 CellInfo*   pInfo = &pThisRowInfo->pCellInfo[nX+1];
2164                 if (pInfo->bEditEngine)
2165                 {
2166                     SCROW nY = pThisRowInfo->nRowNo;
2167 
2168                     SCCOL nCellX = nX;                  // position where the cell really starts
2169                     SCROW nCellY = nY;
2170                     sal_Bool bDoCell = sal_False;
2171 
2172                     long nPosY = nRowPosY;
2173                     if ( nArrY == 0 )
2174                     {
2175                         nPosY = nScrY;
2176                         nY = pRowInfo[1].nRowNo;
2177                         SCCOL nOverX;                   // start of the merged cells
2178                         SCROW nOverY;
2179                         if (GetMergeOrigin( nX,nY, 1, nOverX,nOverY, sal_True ))
2180                         {
2181                             nCellX = nOverX;
2182                             nCellY = nOverY;
2183                             bDoCell = sal_True;
2184                         }
2185                     }
2186                     else if ( nX == nX2 && !pThisRowInfo->pCellInfo[nX+1].pCell )
2187                     {
2188                         //  Rest of a long text further to the right?
2189 
2190                         SCCOL nTempX=nX;
2191                         while (nTempX < nLastContentCol && IsEmptyCellText( pThisRowInfo, nTempX, nY ))
2192                             ++nTempX;
2193 
2194                         if ( nTempX > nX &&
2195                              !IsEmptyCellText( pThisRowInfo, nTempX, nY ) &&
2196                              !pDoc->HasAttrib( nTempX,nY,nTab, nX,nY,nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ) )
2197                         {
2198                             nCellX = nTempX;
2199                             bDoCell = sal_True;
2200                         }
2201                     }
2202                     else
2203                     {
2204                         bDoCell = sal_True;
2205                     }
2206 
2207                     if ( bDoCell && bEditMode && nCellX == nEditCol && nCellY == nEditRow )
2208                         bDoCell = sal_False;
2209 
2210                     const ScPatternAttr* pPattern = NULL;
2211                     const SfxItemSet* pCondSet = NULL;
2212                     if (bDoCell)
2213                     {
2214                         if ( nCellY == nY && nCellX >= nX1 && nCellX <= nX2 &&
2215                              !pDoc->ColHidden(nCellX, nTab) )
2216                         {
2217                             CellInfo& rCellInfo = pThisRowInfo->pCellInfo[nCellX+1];
2218                             pPattern = rCellInfo.pPatternAttr;
2219                             pCondSet = rCellInfo.pConditionSet;
2220                             pCell = rCellInfo.pCell;
2221                         }
2222                         else        // get from document
2223                         {
2224                             pPattern = pDoc->GetPattern( nCellX, nCellY, nTab );
2225                             pCondSet = pDoc->GetCondResult( nCellX, nCellY, nTab );
2226                             GetVisibleCell( nCellX, nCellY, nTab, pCell );
2227                         }
2228                         if ( !pCell )
2229                             bDoCell = sal_False;
2230                     }
2231                     if (bDoCell)
2232                     {
2233                         sal_Bool bHidden = sal_False;
2234 
2235                         //
2236                         //  Create EditEngine
2237                         //
2238 
2239                         if (!pEngine)
2240                             pEngine = CreateOutputEditEngine();
2241                         else
2242                             lcl_ClearEdit( *pEngine );      // also calls SetUpdateMode(sal_False)
2243 
2244                         sal_Bool bCellIsValue = lcl_SafeIsValue(pCell);
2245 
2246                         SvxCellHorJustify eHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem&)
2247                                             pPattern->GetItem(ATTR_HOR_JUSTIFY, pCondSet)).GetValue();
2248                         sal_Bool bBreak = ( eHorJust == SVX_HOR_JUSTIFY_BLOCK ) ||
2249                                         ((const SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK, pCondSet)).GetValue();
2250                         sal_Bool bRepeat = ( eHorJust == SVX_HOR_JUSTIFY_REPEAT && !bBreak );
2251                         sal_Bool bShrink = !bBreak && !bRepeat && static_cast<const SfxBoolItem&>
2252                                         (pPattern->GetItem( ATTR_SHRINKTOFIT, pCondSet )).GetValue();
2253                         SvxCellOrientation eOrient = pPattern->GetCellOrientation( pCondSet );
2254                         long nAttrRotate = ((const SfxInt32Item&)pPattern->
2255                                             GetItem(ATTR_ROTATE_VALUE, pCondSet)).GetValue();
2256                         if ( eHorJust == SVX_HOR_JUSTIFY_REPEAT )
2257                         {
2258                             // ignore orientation/rotation if "repeat" is active
2259                             eOrient = SVX_ORIENTATION_STANDARD;
2260                             nAttrRotate = 0;
2261 
2262                             // #i31843# "repeat" with "line breaks" is treated as default alignment
2263                             // (but rotation is still disabled)
2264                             if ( bBreak )
2265                                 eHorJust = SVX_HOR_JUSTIFY_STANDARD;
2266                         }
2267                         if ( eOrient==SVX_ORIENTATION_STANDARD && nAttrRotate )
2268                         {
2269                             //! Flag setzen, um die Zelle in DrawRotated wiederzufinden ?
2270                             //! (oder Flag schon bei DrawBackground, dann hier keine Abfrage)
2271                             bHidden = sal_True;     // gedreht wird getrennt ausgegeben
2272                         }
2273 
2274                         sal_Bool bAsianVertical = ( eOrient == SVX_ORIENTATION_STACKED &&
2275                                 ((const SfxBoolItem&)pPattern->GetItem( ATTR_VERTICAL_ASIAN, pCondSet )).GetValue() );
2276                         if ( bAsianVertical )
2277                         {
2278                             // in asian mode, use EditEngine::SetVertical instead of EE_CNTRL_ONECHARPERLINE
2279                             eOrient = SVX_ORIENTATION_STANDARD;
2280                             // default alignment for asian vertical mode is top-right
2281                             if ( eHorJust == SVX_HOR_JUSTIFY_STANDARD )
2282                                 eHorJust = SVX_HOR_JUSTIFY_RIGHT;
2283                         }
2284 
2285                         SvxCellHorJustify eOutHorJust =
2286                             ( eHorJust != SVX_HOR_JUSTIFY_STANDARD ) ? eHorJust :
2287                             ( bCellIsValue ? SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_LEFT );
2288 
2289                         if ( eOutHorJust == SVX_HOR_JUSTIFY_BLOCK || eOutHorJust == SVX_HOR_JUSTIFY_REPEAT )
2290                             eOutHorJust = SVX_HOR_JUSTIFY_LEFT;     // repeat is not yet implemented
2291 
2292 
2293 //!                     if ( !bHidden && eType == OUTTYPE_PRINTER &&
2294 //!                         pDev->GetOutDevType() == OUTDEV_WINDOW &&
2295 //!                         ((const SvxFontHeightItem&)pPattern->
2296 //!                         GetItem(ATTR_FONT_HEIGHT)).GetHeight() <= nMinHeight )
2297 //!                     {
2298 //!                         Point aPos( nStartX, nStartY );
2299 //!                         pDev->DrawPixel( aPos,
2300 //!                                         ((const SvxColorItem&)pPattern->
2301 //!                                         GetItem( ATTR_FONT_COLOR )).GetValue() );
2302 //!                         bHidden = sal_True;
2303 //!                     }
2304 
2305                         if (!bHidden)
2306                         {
2307                             //! mirror margin values for RTL?
2308                             //! move margin down to after final GetOutputArea call
2309 
2310                             const SvxMarginItem* pMargin = (const SvxMarginItem*)
2311                                                     &pPattern->GetItem(ATTR_MARGIN, pCondSet);
2312                             sal_uInt16 nIndent = 0;
2313                             if ( eHorJust == SVX_HOR_JUSTIFY_LEFT )
2314                                 nIndent = ((const SfxUInt16Item&)pPattern->
2315                                                     GetItem(ATTR_INDENT, pCondSet)).GetValue();
2316 
2317                             long nLeftM = (long) ( (pMargin->GetLeftMargin() + nIndent) * nPPTX );
2318                             long nTopM  = (long) ( pMargin->GetTopMargin() * nPPTY );
2319                             long nRightM = (long) ( pMargin->GetRightMargin() * nPPTX );
2320                             long nBottomM = (long) ( pMargin->GetBottomMargin() * nPPTY );
2321 
2322                             SCCOL nXForPos = nX;
2323                             if ( nXForPos < nX1 )
2324                             {
2325                                 nXForPos = nX1;
2326                                 nPosX = nInitPosX;
2327                             }
2328                             SCSIZE nArrYForPos = nArrY;
2329                             if ( nArrYForPos < 1 )
2330                             {
2331                                 nArrYForPos = 1;
2332                                 nPosY = nScrY;
2333                             }
2334 
2335                             OutputAreaParam aAreaParam;
2336 
2337                             //
2338                             //  Initial page size - large for normal text, cell size for automatic line breaks
2339                             //
2340 
2341                             Size aPaperSize = Size( 1000000, 1000000 );
2342                             if ( bBreak || eOrient == SVX_ORIENTATION_STACKED || bAsianVertical )
2343                             {
2344                                 //! also stacked, AsianVertical
2345 
2346                                 //  call GetOutputArea with nNeeded=0, to get only the cell width
2347 
2348                                 //! handle nArrY == 0
2349                                 GetOutputArea( nXForPos, nArrYForPos, nPosX, nPosY, nCellX, nCellY, 0,
2350                                                *pPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
2351                                                bCellIsValue, true, false, aAreaParam );
2352 
2353                                 //! special ScEditUtil handling if formatting for printer
2354 
2355                                 if ( eOrient == SVX_ORIENTATION_TOPBOTTOM || eOrient == SVX_ORIENTATION_BOTTOMTOP )
2356                                     aPaperSize.Width() = aAreaParam.maAlignRect.GetHeight() - nTopM - nBottomM;
2357                                 else
2358                                     aPaperSize.Width() = aAreaParam.maAlignRect.GetWidth() - nLeftM - nRightM;
2359 
2360                                 if (bAsianVertical && bBreak)
2361                                 {
2362                                     //  add some extra height (default margin value) for safety
2363                                     //  as long as GetEditArea isn't used below
2364                                     long nExtraHeight = (long)( 20 * nPPTY );
2365                                     aPaperSize.Height() = aAreaParam.maAlignRect.GetHeight() - nTopM - nBottomM + nExtraHeight;
2366                                 }
2367                             }
2368                             if (bPixelToLogic)
2369                             {
2370                                 Size aLogicSize = pRefDevice->PixelToLogic(aPaperSize);
2371                                 if ( bBreak && !bAsianVertical && pRefDevice != pFmtDevice )
2372                                 {
2373                                     // #i85342# screen display and formatting for printer,
2374                                     // use same GetEditArea call as in ScViewData::SetEditEngine
2375 
2376                                     Fraction aFract(1,1);
2377                                     Rectangle aUtilRect = ScEditUtil( pDoc, nCellX, nCellY, nTab, Point(0,0), pFmtDevice,
2378                                         HMM_PER_TWIPS, HMM_PER_TWIPS, aFract, aFract ).GetEditArea( pPattern, sal_False );
2379                                     aLogicSize.Width() = aUtilRect.GetWidth();
2380                                 }
2381                                 pEngine->SetPaperSize(aLogicSize);
2382                             }
2383                             else
2384                                 pEngine->SetPaperSize(aPaperSize);
2385 
2386                             //
2387                             //  Fill the EditEngine (cell attributes and text)
2388                             //
2389 
2390                             SvxCellVerJustify eVerJust = (SvxCellVerJustify)((const SvxVerJustifyItem&)
2391                                                 pPattern->GetItem(ATTR_VER_JUSTIFY, pCondSet)).GetValue();
2392 
2393                             // default alignment for asian vertical mode is top-right
2394                             if ( bAsianVertical && eVerJust == SVX_VER_JUSTIFY_STANDARD )
2395                                 eVerJust = SVX_VER_JUSTIFY_TOP;
2396 
2397                             // syntax highlighting mode is ignored here
2398                             // StringDiffer doesn't look at hyphenate, language items
2399                             if ( pPattern != pOldPattern || pCondSet != pOldCondSet )
2400                             {
2401                                 SfxItemSet* pSet = new SfxItemSet( pEngine->GetEmptyItemSet() );
2402                                 pPattern->FillEditItemSet( pSet, pCondSet );
2403 
2404                                 pEngine->SetDefaults( pSet );
2405                                 pOldPattern = pPattern;
2406                                 pOldCondSet = pCondSet;
2407 
2408                                 sal_uLong nControl = pEngine->GetControlWord();
2409                                 if (eOrient==SVX_ORIENTATION_STACKED)
2410                                     nControl |= EE_CNTRL_ONECHARPERLINE;
2411                                 else
2412                                     nControl &= ~EE_CNTRL_ONECHARPERLINE;
2413                                 pEngine->SetControlWord( nControl );
2414 
2415                                 if ( !bHyphenatorSet && ((const SfxBoolItem&)pSet->Get(EE_PARA_HYPHENATE)).GetValue() )
2416                                 {
2417                                     //  set hyphenator the first time it is needed
2418                                     com::sun::star::uno::Reference<com::sun::star::linguistic2::XHyphenator> xXHyphenator( LinguMgr::GetHyphenator() );
2419                                     pEngine->SetHyphenator( xXHyphenator );
2420                                     bHyphenatorSet = sal_True;
2421                                 }
2422 
2423                                 Color aBackCol = ((const SvxBrushItem&)
2424                                     pPattern->GetItem( ATTR_BACKGROUND, pCondSet )).GetColor();
2425                                 if ( bUseStyleColor && ( aBackCol.GetTransparency() > 0 || bCellContrast ) )
2426                                     aBackCol.SetColor( nConfBackColor );
2427                                 pEngine->SetBackgroundColor( aBackCol );
2428                             }
2429 
2430                             //  horizontal alignment now may depend on cell content
2431                             //  (for values with number formats with mixed script types)
2432                             //  -> always set adjustment
2433 
2434                             SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT;
2435                             if (eOrient==SVX_ORIENTATION_STACKED)
2436                                 eSvxAdjust = SVX_ADJUST_CENTER;
2437                             else if (bBreak)
2438                             {
2439                                 if (eOrient==SVX_ORIENTATION_STANDARD && !bAsianVertical)
2440                                     switch (eHorJust)
2441                                     {
2442                                         case SVX_HOR_JUSTIFY_STANDARD:
2443                                             eSvxAdjust = bCellIsValue ? SVX_ADJUST_RIGHT : SVX_ADJUST_LEFT;
2444                                             break;
2445                                         case SVX_HOR_JUSTIFY_LEFT:
2446                                         case SVX_HOR_JUSTIFY_REPEAT:            // nicht implementiert
2447                                             eSvxAdjust = SVX_ADJUST_LEFT;
2448                                             break;
2449                                         case SVX_HOR_JUSTIFY_RIGHT:
2450                                             eSvxAdjust = SVX_ADJUST_RIGHT;
2451                                             break;
2452                                         case SVX_HOR_JUSTIFY_CENTER:
2453                                             eSvxAdjust = SVX_ADJUST_CENTER;
2454                                             break;
2455                                         case SVX_HOR_JUSTIFY_BLOCK:
2456                                             eSvxAdjust = SVX_ADJUST_BLOCK;
2457                                             break;
2458                                     }
2459                                 else
2460                                     switch (eVerJust)
2461                                     {
2462                                         case SVX_VER_JUSTIFY_TOP:
2463                                             eSvxAdjust = (eOrient==SVX_ORIENTATION_TOPBOTTOM || bAsianVertical) ?
2464                                                         SVX_ADJUST_LEFT : SVX_ADJUST_RIGHT;
2465                                             break;
2466                                         case SVX_VER_JUSTIFY_CENTER:
2467                                             eSvxAdjust = SVX_ADJUST_CENTER;
2468                                             break;
2469                                         case SVX_VER_JUSTIFY_BOTTOM:
2470                                         case SVX_HOR_JUSTIFY_STANDARD:
2471                                             eSvxAdjust = (eOrient==SVX_ORIENTATION_TOPBOTTOM || bAsianVertical) ?
2472                                                         SVX_ADJUST_RIGHT : SVX_ADJUST_LEFT;
2473                                             break;
2474                                     }
2475                             }
2476                             pEngine->SetDefaultItem( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) );
2477 
2478                             //  Read content from cell
2479 
2480                             sal_Bool bWrapFields = sal_False;
2481                             if (pCell)
2482                             {
2483                                 if (pCell->GetCellType() == CELLTYPE_EDIT)
2484                                 {
2485                                     const EditTextObject* pData;
2486                                     ((ScEditCell*)pCell)->GetData(pData);
2487 
2488                                     if (pData)
2489                                     {
2490                                         pEngine->SetText(*pData);
2491 
2492                                         if ( bBreak && !bAsianVertical && pData->HasField() )
2493                                         {
2494                                             //  Fields aren't wrapped, so clipping is enabled to prevent
2495                                             //  a field from being drawn beyond the cell size
2496 
2497                                             bWrapFields = sal_True;
2498                                         }
2499                                     }
2500                                     else
2501                                     {
2502                                         DBG_ERROR("pData == 0");
2503                                     }
2504                                 }
2505                                 else
2506                                 {
2507                                     sal_uLong nFormat = pPattern->GetNumberFormat(
2508                                                                 pDoc->GetFormatTable(), pCondSet );
2509                                     String aString;
2510                                     Color* pColor;
2511                                     ScCellFormat::GetString( pCell,
2512                                                              nFormat,aString, &pColor,
2513                                                              *pDoc->GetFormatTable(),
2514                                                              bShowNullValues,
2515                                                              bShowFormulas,
2516                                                              ftCheck );
2517 
2518                                     pEngine->SetText(aString);
2519                                     if ( pColor && !bSyntaxMode && !( bUseStyleColor && bForceAutoColor ) )
2520                                         lcl_SetEditColor( *pEngine, *pColor );
2521                                 }
2522 
2523                                 if ( bSyntaxMode )
2524                                     SetEditSyntaxColor( *pEngine, pCell );
2525                                 else if ( bUseStyleColor && bForceAutoColor )
2526                                     lcl_SetEditColor( *pEngine, COL_AUTO );     //! or have a flag at EditEngine
2527                             }
2528                             else
2529                             {
2530                                 DBG_ERROR("pCell == NULL");
2531                             }
2532 
2533                             pEngine->SetVertical( bAsianVertical );
2534                             pEngine->SetUpdateMode( sal_True );     // after SetText, before CalcTextWidth/GetTextHeight
2535 
2536                             //
2537                             //  Get final output area using the calculated width
2538                             //
2539 
2540                             long nEngineWidth;
2541                             if ( bBreak && eOrient != SVX_ORIENTATION_STACKED && !bAsianVertical )
2542                                 nEngineWidth = 0;
2543                             else
2544                                 nEngineWidth = (long) pEngine->CalcTextWidth();
2545                             long nEngineHeight = pEngine->GetTextHeight();
2546 
2547                             if (eOrient != SVX_ORIENTATION_STANDARD &&
2548                                 eOrient != SVX_ORIENTATION_STACKED)
2549                             {
2550                                 long nTemp = nEngineWidth;
2551                                 nEngineWidth = nEngineHeight;
2552                                 nEngineHeight = nTemp;
2553                             }
2554 
2555                             if (eOrient == SVX_ORIENTATION_STACKED)
2556                                 nEngineWidth = nEngineWidth * 11 / 10;
2557 
2558                             long nNeededPixel = nEngineWidth;
2559                             if (bPixelToLogic)
2560                                 nNeededPixel = pRefDevice->LogicToPixel(Size(nNeededPixel,0)).Width();
2561                             nNeededPixel += nLeftM + nRightM;
2562 
2563                             if ( ( !bBreak && eOrient != SVX_ORIENTATION_STACKED ) || bAsianVertical || bShrink )
2564                             {
2565                                 // for break, the first GetOutputArea call is sufficient
2566                                 GetOutputArea( nXForPos, nArrYForPos, nPosX, nPosY, nCellX, nCellY, nNeededPixel,
2567                                                *pPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
2568                                                bCellIsValue || bRepeat || bShrink, false, false, aAreaParam );
2569 
2570                                 if ( bShrink )
2571                                 {
2572                                     sal_Bool bWidth = ( eOrient == SVX_ORIENTATION_STANDARD && !bAsianVertical );
2573                                     ShrinkEditEngine( *pEngine, aAreaParam.maAlignRect,
2574                                         nLeftM, nTopM, nRightM, nBottomM, bWidth,
2575                                         sal::static_int_cast<sal_uInt16>(eOrient), 0, bPixelToLogic,
2576                                         nEngineWidth, nEngineHeight, nNeededPixel,
2577                                         aAreaParam.mbLeftClip, aAreaParam.mbRightClip );
2578                                 }
2579 
2580                                 if ( bRepeat && !aAreaParam.mbLeftClip && !aAreaParam.mbRightClip && pEngine->GetParagraphCount() == 1 )
2581                                 {
2582                                     // First check if twice the space for the formatted text is available
2583                                     // (otherwise just keep it unchanged).
2584 
2585                                     long nFormatted = nNeededPixel - nLeftM - nRightM;      // without margin
2586                                     long nAvailable = aAreaParam.maAlignRect.GetWidth() - nLeftM - nRightM;
2587                                     if ( nAvailable >= 2 * nFormatted )
2588                                     {
2589                                         // "repeat" is handled with unformatted text (for performance reasons)
2590                                         String aCellStr = pEngine->GetText();
2591                                         pEngine->SetText( aCellStr );
2592 
2593                                         long nRepeatSize = (long) pEngine->CalcTextWidth();
2594                                         if (bPixelToLogic)
2595                                             nRepeatSize = pRefDevice->LogicToPixel(Size(nRepeatSize,0)).Width();
2596                                         if ( pFmtDevice != pRefDevice )
2597                                             ++nRepeatSize;
2598                                         if ( nRepeatSize > 0 )
2599                                         {
2600                                             long nRepeatCount = nAvailable / nRepeatSize;
2601                                             if ( nRepeatCount > 1 )
2602                                             {
2603                                                 String aRepeated = aCellStr;
2604                                                 for ( long nRepeat = 1; nRepeat < nRepeatCount; nRepeat++ )
2605                                                     aRepeated.Append( aCellStr );
2606                                                 pEngine->SetText( aRepeated );
2607 
2608                                                 nEngineHeight = pEngine->GetTextHeight();
2609                                                 nEngineWidth = (long) pEngine->CalcTextWidth();
2610                                                 if (bPixelToLogic)
2611                                                     nNeededPixel = pRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
2612                                                 else
2613                                                     nNeededPixel = nEngineWidth;
2614                                                 nNeededPixel += nLeftM + nRightM;
2615                                             }
2616                                         }
2617                                     }
2618                                 }
2619 
2620                                 if ( bCellIsValue && ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) )
2621                                 {
2622                                     pEngine->SetText( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("###")) );
2623                                     nEngineWidth = (long) pEngine->CalcTextWidth();
2624                                     if (bPixelToLogic)
2625                                         nNeededPixel = pRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
2626                                     else
2627                                         nNeededPixel = nEngineWidth;
2628                                     nNeededPixel += nLeftM + nRightM;
2629 
2630                                     //  No clip marks if "###" doesn't fit (same as in DrawStrings)
2631                                 }
2632 
2633                                 if ( eOutHorJust != SVX_HOR_JUSTIFY_LEFT && eOrient == SVX_ORIENTATION_STANDARD )
2634                                 {
2635                                     aPaperSize.Width() = nNeededPixel + 1;
2636                                     if (bPixelToLogic)
2637                                         pEngine->SetPaperSize(pRefDevice->PixelToLogic(aPaperSize));
2638                                     else
2639                                         pEngine->SetPaperSize(aPaperSize);
2640                                 }
2641                             }
2642 
2643                             long nStartX = aAreaParam.maAlignRect.Left();
2644                             long nStartY = aAreaParam.maAlignRect.Top();
2645                             long nCellWidth = aAreaParam.maAlignRect.GetWidth();
2646                             long nOutWidth = nCellWidth - 1 - nLeftM - nRightM;
2647                             long nOutHeight = aAreaParam.maAlignRect.GetHeight() - nTopM - nBottomM;
2648 
2649                             if ( bBreak || eOrient != SVX_ORIENTATION_STANDARD || bAsianVertical )
2650                             {
2651                                 //  text with automatic breaks is aligned only within the
2652                                 //  edit engine's paper size, the output of the whole area
2653                                 //  is always left-aligned
2654 
2655                                 nStartX += nLeftM;
2656                             }
2657                             else
2658                             {
2659                                 if ( eOutHorJust == SVX_HOR_JUSTIFY_RIGHT )
2660                                     nStartX -= nNeededPixel - nCellWidth + nRightM + 1;
2661                                 else if ( eOutHorJust == SVX_HOR_JUSTIFY_CENTER )
2662                                     nStartX -= ( nNeededPixel - nCellWidth + nRightM + 1 - nLeftM ) / 2;
2663                                 else
2664                                     nStartX += nLeftM;
2665                             }
2666 
2667                             sal_Bool bOutside = ( aAreaParam.maClipRect.Right() < nScrX || aAreaParam.maClipRect.Left() >= nScrX + nScrW );
2668                             if ( aAreaParam.maClipRect.Left() < nScrX )
2669                             {
2670                                 aAreaParam.maClipRect.Left() = nScrX;
2671                                 aAreaParam.mbLeftClip = true;
2672                             }
2673                             if ( aAreaParam.maClipRect.Right() > nScrX + nScrW )
2674                             {
2675                                 aAreaParam.maClipRect.Right() = nScrX + nScrW;          //! minus one?
2676                                 aAreaParam.mbRightClip = true;
2677                             }
2678 
2679                             if ( !bHidden && !bOutside )
2680                             {
2681                                 bool bClip = aAreaParam.mbLeftClip || aAreaParam.mbRightClip;
2682                                 sal_Bool bSimClip = sal_False;
2683 
2684                                 if ( bWrapFields )
2685                                 {
2686                                     //  Fields in a cell with automatic breaks: clip to cell width
2687                                     bClip = sal_True;
2688                                 }
2689 
2690                                 if ( aAreaParam.maClipRect.Top() < nScrY )
2691                                 {
2692                                     aAreaParam.maClipRect.Top() = nScrY;
2693                                     bClip = sal_True;
2694                                 }
2695                                 if ( aAreaParam.maClipRect.Bottom() > nScrY + nScrH )
2696                                 {
2697                                     aAreaParam.maClipRect.Bottom() = nScrY + nScrH;     //! minus one?
2698                                     bClip = sal_True;
2699                                 }
2700 
2701                                 Size aCellSize;         // output area, excluding margins, in logical units
2702                                 if (bPixelToLogic)
2703                                     aCellSize = pRefDevice->PixelToLogic( Size( nOutWidth, nOutHeight ) );
2704                                 else
2705                                     aCellSize = Size( nOutWidth, nOutHeight );
2706 
2707                                 if ( nEngineHeight >= aCellSize.Height() + aRefOne.Height() )
2708                                 {
2709                                     const ScMergeAttr* pMerge =
2710                                             (ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE);
2711                                     sal_Bool bMerged = pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1;
2712 
2713                                     //  Don't clip for text height when printing rows with optimal height,
2714                                     //  except when font size is from conditional formatting.
2715                                     //! Allow clipping when vertically merged?
2716                                     if ( eType != OUTTYPE_PRINTER ||
2717                                         ( pDoc->GetRowFlags( nCellY, nTab ) & CR_MANUALSIZE ) ||
2718                                         ( pCondSet && SFX_ITEM_SET ==
2719                                             pCondSet->GetItemState(ATTR_FONT_HEIGHT, sal_True) ) )
2720                                         bClip = sal_True;
2721                                     else
2722                                         bSimClip = sal_True;
2723 
2724                                     //  Show clip marks if height is at least 5pt too small and
2725                                     //  there are several lines of text.
2726                                     //  Not for asian vertical text, because that would interfere
2727                                     //  with the default right position of the text.
2728                                     //  Only with automatic line breaks, to avoid having to find
2729                                     //  the cells with the horizontal end of the text again.
2730                                     if ( nEngineHeight - aCellSize.Height() > 100 &&
2731                                          ( bBreak || eOrient == SVX_ORIENTATION_STACKED ) &&
2732                                          !bAsianVertical && bMarkClipped &&
2733                                          ( pEngine->GetParagraphCount() > 1 || pEngine->GetLineCount(0) > 1 ) )
2734                                     {
2735                                         CellInfo* pClipMarkCell = NULL;
2736                                         if ( bMerged )
2737                                         {
2738                                             //  anywhere in the merged area...
2739                                             SCCOL nClipX = ( nX < nX1 ) ? nX1 : nX;
2740                                             pClipMarkCell = &pRowInfo[(nArrY != 0) ? nArrY : 1].pCellInfo[nClipX+1];
2741                                         }
2742                                         else
2743                                             pClipMarkCell = &pThisRowInfo->pCellInfo[nX+1];
2744 
2745                                         pClipMarkCell->nClipMark |= SC_CLIPMARK_RIGHT;      //! also allow left?
2746                                         bAnyClipped = sal_True;
2747 
2748                                         long nMarkPixel = (long)( SC_CLIPMARK_SIZE * nPPTX );
2749                                         if ( aAreaParam.maClipRect.Right() - nMarkPixel > aAreaParam.maClipRect.Left() )
2750                                             aAreaParam.maClipRect.Right() -= nMarkPixel;
2751                                     }
2752                                 }
2753 
2754 #if 0
2755                                 long nClipStartY = nStartY;
2756                                 if (nArrY==0 || bVisChanged)
2757                                 {
2758                                     if ( nClipStartY < nRowPosY )
2759                                     {
2760                                         long nDif = nRowPosY - nClipStartY;
2761                                         bClip = sal_True;
2762                                         nClipStartY = nRowPosY;
2763                                         aClipSize.Height() -= nDif;
2764                                     }
2765                                 }
2766 #endif
2767 
2768                                 Rectangle aLogicClip;
2769                                 if (bClip || bSimClip)
2770                                 {
2771                                     // Clip marks are already handled in GetOutputArea
2772 
2773                                     if (bPixelToLogic)
2774                                         aLogicClip = pRefDevice->PixelToLogic( aAreaParam.maClipRect );
2775                                     else
2776                                         aLogicClip = aAreaParam.maClipRect;
2777 
2778                                     if (bClip)  // bei bSimClip nur aClipRect initialisieren
2779                                     {
2780                                         if (bMetaFile)
2781                                         {
2782                                             pDev->Push();
2783                                             pDev->IntersectClipRegion( aLogicClip );
2784                                         }
2785                                         else
2786                                             pDev->SetClipRegion( Region( aLogicClip ) );
2787                                     }
2788                                 }
2789 
2790                                 Point aLogicStart;
2791                                 if (bPixelToLogic)
2792                                     aLogicStart = pRefDevice->PixelToLogic( Point(nStartX,nStartY) );
2793                                 else
2794                                     aLogicStart = Point(nStartX, nStartY);
2795                                 if ( eOrient!=SVX_ORIENTATION_STANDARD || bAsianVertical || !bBreak )
2796                                 {
2797                                     long nAvailWidth = aCellSize.Width();
2798                                     // space for AutoFilter is already handled in GetOutputArea
2799 
2800                                     //  horizontal alignment
2801 
2802                                     if (eOrient==SVX_ORIENTATION_STANDARD && !bAsianVertical)
2803                                     {
2804                                         if (eHorJust==SVX_HOR_JUSTIFY_RIGHT ||
2805                                             eHorJust==SVX_HOR_JUSTIFY_CENTER ||
2806                                             (eHorJust==SVX_HOR_JUSTIFY_STANDARD && bCellIsValue) )
2807                                         {
2808                                             pEngine->SetUpdateMode( sal_False );
2809 
2810                                             SvxAdjust eEditAdjust =
2811                                                 (eHorJust==SVX_HOR_JUSTIFY_CENTER) ?
2812                                                     SVX_ADJUST_CENTER : SVX_ADJUST_RIGHT;
2813                                             pEngine->SetDefaultItem(
2814                                                 SvxAdjustItem( eEditAdjust, EE_PARA_JUST ) );
2815 
2816                                             // #55142# reset adjustment for the next cell
2817                                             pOldPattern = NULL;
2818 
2819                                             pEngine->SetUpdateMode( sal_True );
2820                                         }
2821                                     }
2822                                     else
2823                                     {
2824                                         if (eHorJust==SVX_HOR_JUSTIFY_RIGHT)
2825                                             aLogicStart.X() += nAvailWidth - nEngineWidth;
2826                                         else if (eHorJust==SVX_HOR_JUSTIFY_CENTER)
2827                                             aLogicStart.X() += (nAvailWidth - nEngineWidth) / 2;
2828                                     }
2829                                 }
2830 
2831                                 if ( bAsianVertical )
2832                                 {
2833                                     // paper size is subtracted below
2834                                     aLogicStart.X() += nEngineWidth;
2835                                 }
2836 
2837                                 if ( ( bAsianVertical || eOrient == SVX_ORIENTATION_TOPBOTTOM ||
2838                                         eOrient == SVX_ORIENTATION_BOTTOMTOP ) && bBreak )
2839                                 {
2840                                     // vertical adjustment is within the EditEngine
2841                                     if (bPixelToLogic)
2842                                         aLogicStart.Y() += pRefDevice->PixelToLogic(Size(0,nTopM)).Height();
2843                                     else
2844                                         aLogicStart.Y() += nTopM;
2845                                 }
2846 
2847                                 if ( ( eOrient==SVX_ORIENTATION_STANDARD && !bAsianVertical ) ||
2848                                      eOrient==SVX_ORIENTATION_STACKED || !bBreak )
2849                                 {
2850                                     if (eVerJust==SVX_VER_JUSTIFY_BOTTOM ||
2851                                         eVerJust==SVX_VER_JUSTIFY_STANDARD)
2852                                     {
2853                                         //! if pRefDevice != pFmtDevice, keep heights in logic units,
2854                                         //! only converting margin?
2855 
2856                                         if (bPixelToLogic)
2857                                             aLogicStart.Y() += pRefDevice->PixelToLogic( Size(0, nTopM +
2858                                                             pRefDevice->LogicToPixel(aCellSize).Height() -
2859                                                             pRefDevice->LogicToPixel(Size(0,nEngineHeight)).Height()
2860                                                             )).Height();
2861                                         else
2862                                             aLogicStart.Y() += nTopM + aCellSize.Height() - nEngineHeight;
2863                                     }
2864                                     else if (eVerJust==SVX_VER_JUSTIFY_CENTER)
2865                                     {
2866                                         if (bPixelToLogic)
2867                                             aLogicStart.Y() += pRefDevice->PixelToLogic( Size(0, nTopM + (
2868                                                             pRefDevice->LogicToPixel(aCellSize).Height() -
2869                                                             pRefDevice->LogicToPixel(Size(0,nEngineHeight)).Height() )
2870                                                             / 2)).Height();
2871                                         else
2872                                             aLogicStart.Y() += nTopM + (aCellSize.Height() - nEngineHeight) / 2;
2873                                     }
2874                                     else        // top
2875                                     {
2876                                         if (bPixelToLogic)
2877                                             aLogicStart.Y() += pRefDevice->PixelToLogic(Size(0,nTopM)).Height();
2878                                         else
2879                                             aLogicStart.Y() += nTopM;
2880                                     }
2881                                 }
2882 
2883                                 Point aURLStart = aLogicStart;      // copy before modifying for orientation
2884 
2885                                 short nOriVal = 0;
2886                                 if (eOrient==SVX_ORIENTATION_TOPBOTTOM)
2887                                 {
2888                                     // nOriVal = -900;
2889                                     nOriVal = 2700;
2890                                     aLogicStart.X() += nEngineWidth;
2891                                 }
2892                                 else if (eOrient==SVX_ORIENTATION_BOTTOMTOP)
2893                                 {
2894                                     nOriVal = 900;
2895                                     aLogicStart.Y() += bBreak ? pEngine->GetPaperSize().Width() :
2896                                                                 nEngineHeight;
2897                                 }
2898                                 else if (eOrient==SVX_ORIENTATION_STACKED)
2899                                 {
2900                                     Size aPaperLogic = pEngine->GetPaperSize();
2901                                     aPaperLogic.Width() = nEngineWidth;
2902                                     pEngine->SetPaperSize(aPaperLogic);
2903                                 }
2904 
2905                                 if ( pEngine->IsRightToLeft( 0 ) )
2906                                 {
2907                                     //  For right-to-left, EditEngine always calculates its lines
2908                                     //  beginning from the right edge, but EditLine::nStartPosX is
2909                                     //  of sal_uInt16 type, so the PaperSize must be limited to USHRT_MAX.
2910                                     Size aLogicPaper = pEngine->GetPaperSize();
2911                                     if ( aLogicPaper.Width() > USHRT_MAX )
2912                                     {
2913                                         aLogicPaper.Width() = USHRT_MAX;
2914                                         pEngine->SetPaperSize(aLogicPaper);
2915                                     }
2916                                 }
2917 
2918                                 // bMoveClipped handling has been replaced by complete alignment
2919                                 // handling (also extending to the left).
2920 
2921                                 if ( bSimClip && !nOriVal && !bAsianVertical )
2922                                 {
2923                                     //  kein hartes Clipping, aber nur die betroffenen
2924                                     //  Zeilen ausgeben
2925 
2926                                     Point aDocStart = aLogicClip.TopLeft();
2927                                     aDocStart -= aLogicStart;
2928                                     pEngine->Draw( pDev, aLogicClip, aDocStart, sal_False );
2929                                 }
2930                                 else
2931                                 {
2932                                     if (bAsianVertical)
2933                                     {
2934                                         //  with SetVertical, the start position is top left of
2935                                         //  the whole output area, not the text itself
2936                                         aLogicStart.X() -= pEngine->GetPaperSize().Width();
2937                                     }
2938                                     pEngine->Draw( pDev, aLogicStart, nOriVal );
2939                                 }
2940 
2941                                 if (bClip)
2942                                 {
2943                                     if (bMetaFile)
2944                                         pDev->Pop();
2945                                     else
2946                                         pDev->SetClipRegion();
2947                                 }
2948 
2949                                 // PDF: whole-cell hyperlink from formula?
2950                                 sal_Bool bHasURL = pPDFData && pCell && pCell->GetCellType() == CELLTYPE_FORMULA &&
2951                                                 static_cast<ScFormulaCell*>(pCell)->IsHyperLinkCell();
2952                                 if ( bHasURL )
2953                                 {
2954                                     long nURLWidth = (long) pEngine->CalcTextWidth();
2955                                     long nURLHeight = pEngine->GetTextHeight();
2956                                     if ( bBreak )
2957                                     {
2958                                         Size aPaper = pEngine->GetPaperSize();
2959                                         if ( bAsianVertical )
2960                                             nURLHeight = aPaper.Height();
2961                                         else
2962                                             nURLWidth = aPaper.Width();
2963                                     }
2964                                     if ( eOrient == SVX_ORIENTATION_TOPBOTTOM || eOrient == SVX_ORIENTATION_BOTTOMTOP )
2965                                         std::swap( nURLWidth, nURLHeight );
2966                                     else if ( bAsianVertical )
2967                                         aURLStart.X() -= nURLWidth;
2968 
2969                                     Rectangle aURLRect( aURLStart, Size( nURLWidth, nURLHeight ) );
2970                                     lcl_DoHyperlinkResult( pDev, aURLRect, pCell );
2971                                 }
2972                             }
2973                         }
2974                     }
2975                 }
2976                 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2977             }
2978         }
2979         nRowPosY += pRowInfo[nArrY].nHeight;
2980     }
2981 
2982     delete pEngine;
2983 
2984     if (bAnyRotated)
2985         DrawRotated(bPixelToLogic);     //! von aussen rufen ?
2986 }
2987 
2988 //  -------------------------------------------------------------------------------
2989 
DrawRotated(sal_Bool bPixelToLogic)2990 void ScOutputData::DrawRotated(sal_Bool bPixelToLogic)
2991 {
2992     //! nRotMax speichern
2993     SCCOL nRotMax = nX2;
2994     for (SCSIZE nRotY=0; nRotY<nArrCount; nRotY++)
2995         if (pRowInfo[nRotY].nRotMaxCol != SC_ROTMAX_NONE && pRowInfo[nRotY].nRotMaxCol > nRotMax)
2996             nRotMax = pRowInfo[nRotY].nRotMaxCol;
2997 
2998 
2999     ScModule* pScMod = SC_MOD();
3000     sal_Int32 nConfBackColor = pScMod->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor;
3001     //  #105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed sal_True)
3002     sal_Bool bCellContrast = bUseStyleColor &&
3003             Application::GetSettings().GetStyleSettings().GetHighContrastMode();
3004 
3005     ScFieldEditEngine* pEngine = NULL;
3006     sal_Bool bHyphenatorSet = sal_False;
3007     const ScPatternAttr* pPattern;
3008     const SfxItemSet*    pCondSet;
3009     const ScPatternAttr* pOldPattern = NULL;
3010     const SfxItemSet*    pOldCondSet = NULL;
3011     ScBaseCell* pCell = NULL;
3012 
3013     long nInitPosX = nScrX;
3014     if ( bLayoutRTL )
3015     {
3016 #if 0
3017         Size aOnePixel = pDev->PixelToLogic(Size(1,1));
3018         long nOneX = aOnePixel.Width();
3019         nInitPosX += nMirrorW - nOneX;
3020 #endif
3021         nInitPosX += nMirrorW - 1;
3022     }
3023     long nLayoutSign = bLayoutRTL ? -1 : 1;
3024 
3025     long nRowPosY = nScrY;
3026     for (SCSIZE nArrY=0; nArrY+1<nArrCount; nArrY++)            // 0 fuer Reste von zusammengefassten
3027     {
3028         RowInfo* pThisRowInfo = &pRowInfo[nArrY];
3029         long nCellHeight = (long) pThisRowInfo->nHeight;
3030         if (nArrY==1) nRowPosY = nScrY;                         // vorher wird einzeln berechnet
3031 
3032         if ( ( pThisRowInfo->bChanged || nArrY==0 ) && pThisRowInfo->nRotMaxCol != SC_ROTMAX_NONE )
3033         {
3034             long nPosX = 0;
3035             for (SCCOL nX=0; nX<=nRotMax; nX++)
3036             {
3037                 if (nX==nX1) nPosX = nInitPosX;                 // positions before nX1 are calculated individually
3038 
3039                 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
3040                 if ( pInfo->nRotateDir != SC_ROTDIR_NONE )
3041                 {
3042                     SCROW nY = pThisRowInfo->nRowNo;
3043 
3044                     sal_Bool bHidden = sal_False;
3045                     if (bEditMode)
3046                         if ( nX == nEditCol && nY == nEditRow )
3047                             bHidden = sal_True;
3048 
3049                     if (!bHidden)
3050                     {
3051                         if (!pEngine)
3052                             pEngine = CreateOutputEditEngine();
3053                         else
3054                             lcl_ClearEdit( *pEngine );      // also calls SetUpdateMode(sal_False)
3055 
3056                         long nPosY = nRowPosY;
3057                         sal_Bool bVisChanged = sal_False;
3058 
3059                         //! Rest von zusammengefasster Zelle weiter oben funktioniert nicht!
3060 
3061                         sal_Bool bFromDoc = sal_False;
3062                         pPattern = pInfo->pPatternAttr;
3063                         pCondSet = pInfo->pConditionSet;
3064                         if (!pPattern)
3065                         {
3066                             pPattern = pDoc->GetPattern( nX, nY, nTab );
3067                             bFromDoc = sal_True;
3068                         }
3069                         pCell = pInfo->pCell;
3070                         if (bFromDoc)
3071                             pCondSet = pDoc->GetCondResult( nX, nY, nTab );
3072 
3073                         if (!pCell && nX>nX2)
3074                             GetVisibleCell( nX, nY, nTab, pCell );
3075 
3076                         if ( !pCell || IsEmptyCellText( pThisRowInfo, nX, nY ) )
3077                             bHidden = sal_True;     // nRotateDir is also set without a cell
3078 
3079                         long nCellWidth = (long) pRowInfo[0].pCellInfo[nX+1].nWidth;
3080 
3081                         SvxCellHorJustify eHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem&)
3082                                             pPattern->GetItem(ATTR_HOR_JUSTIFY, pCondSet)).GetValue();
3083                         sal_Bool bBreak = ( eHorJust == SVX_HOR_JUSTIFY_BLOCK ) ||
3084                                     ((const SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK, pCondSet)).GetValue();
3085                         sal_Bool bRepeat = ( eHorJust == SVX_HOR_JUSTIFY_REPEAT && !bBreak );
3086                         sal_Bool bShrink = !bBreak && !bRepeat && static_cast<const SfxBoolItem&>
3087                                         (pPattern->GetItem( ATTR_SHRINKTOFIT, pCondSet )).GetValue();
3088                         SvxCellOrientation eOrient = pPattern->GetCellOrientation( pCondSet );
3089 
3090                         const ScMergeAttr* pMerge =
3091                                 (ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE);
3092                         sal_Bool bMerged = pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1;
3093 
3094                         long nStartX = nPosX;
3095                         long nStartY = nPosY;
3096                         if (nX<nX1)
3097                         {
3098                             if ((bBreak || eOrient!=SVX_ORIENTATION_STANDARD) && !bMerged)
3099                                 bHidden = sal_True;
3100                             else
3101                             {
3102                                 nStartX = nInitPosX;
3103                                 SCCOL nCol = nX1;
3104                                 while (nCol > nX)
3105                                 {
3106                                     --nCol;
3107                                     nStartX -= nLayoutSign * (long) pRowInfo[0].pCellInfo[nCol+1].nWidth;
3108                                 }
3109                             }
3110                         }
3111                         long nCellStartX = nStartX;
3112 
3113                         //  Ersatzdarstellung fuer zu kleinen Text weggelassen
3114 
3115                         if (!bHidden)
3116                         {
3117                             long nOutWidth = nCellWidth - 1;
3118                             long nOutHeight;
3119                             if (pInfo)
3120                                 nOutHeight = nCellHeight;
3121                             else
3122                                 nOutHeight = (long) ( pDoc->GetRowHeight(nY,nTab) * nPPTY );
3123 
3124                             if ( bMerged )                              // Zusammengefasst
3125                             {
3126                                 SCCOL nCountX = pMerge->GetColMerge();
3127                                 for (SCCOL i=1; i<nCountX; i++)
3128                                     nOutWidth += (long) ( pDoc->GetColWidth(nX+i,nTab) * nPPTX );
3129                                 SCROW nCountY = pMerge->GetRowMerge();
3130                                 nOutHeight += (long) pDoc->GetScaledRowHeight( nY+1, nY+nCountY-1, nTab, nPPTY);
3131                             }
3132 
3133                             SvxCellVerJustify eVerJust = (SvxCellVerJustify)((const SvxVerJustifyItem&)
3134                                                 pPattern->GetItem(ATTR_VER_JUSTIFY, pCondSet)).GetValue();
3135 
3136                             // Syntax-Modus wird hier ignoriert...
3137 
3138                             // StringDiffer doesn't look at hyphenate, language items
3139                             if ( pPattern != pOldPattern || pCondSet != pOldCondSet )
3140                             {
3141                                 SfxItemSet* pSet = new SfxItemSet( pEngine->GetEmptyItemSet() );
3142                                 pPattern->FillEditItemSet( pSet, pCondSet );
3143 
3144                                                                     // Ausrichtung fuer EditEngine
3145                                 SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT;
3146                                 if (eOrient==SVX_ORIENTATION_STACKED)
3147                                     eSvxAdjust = SVX_ADJUST_CENTER;
3148                                 // Adjustment fuer bBreak ist hier weggelassen
3149                                 pSet->Put( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) );
3150 
3151                                 pEngine->SetDefaults( pSet );
3152                                 pOldPattern = pPattern;
3153                                 pOldCondSet = pCondSet;
3154 
3155                                 sal_uLong nControl = pEngine->GetControlWord();
3156                                 if (eOrient==SVX_ORIENTATION_STACKED)
3157                                     nControl |= EE_CNTRL_ONECHARPERLINE;
3158                                 else
3159                                     nControl &= ~EE_CNTRL_ONECHARPERLINE;
3160                                 pEngine->SetControlWord( nControl );
3161 
3162                                 if ( !bHyphenatorSet && ((const SfxBoolItem&)pSet->Get(EE_PARA_HYPHENATE)).GetValue() )
3163                                 {
3164                                     //  set hyphenator the first time it is needed
3165                                     com::sun::star::uno::Reference<com::sun::star::linguistic2::XHyphenator> xXHyphenator( LinguMgr::GetHyphenator() );
3166                                     pEngine->SetHyphenator( xXHyphenator );
3167                                     bHyphenatorSet = sal_True;
3168                                 }
3169 
3170                                 Color aBackCol = ((const SvxBrushItem&)
3171                                     pPattern->GetItem( ATTR_BACKGROUND, pCondSet )).GetColor();
3172                                 if ( bUseStyleColor && ( aBackCol.GetTransparency() > 0 || bCellContrast ) )
3173                                     aBackCol.SetColor( nConfBackColor );
3174                                 pEngine->SetBackgroundColor( aBackCol );
3175                             }
3176 
3177                             //  Raender
3178 
3179                             //!     Position und Papersize auf EditUtil umstellen !!!
3180 
3181                             const SvxMarginItem* pMargin = (const SvxMarginItem*)
3182                                                     &pPattern->GetItem(ATTR_MARGIN, pCondSet);
3183                             sal_uInt16 nIndent = 0;
3184                             if ( eHorJust == SVX_HOR_JUSTIFY_LEFT )
3185                                 nIndent = ((const SfxUInt16Item&)pPattern->
3186                                                     GetItem(ATTR_INDENT, pCondSet)).GetValue();
3187 
3188                             long nTotalHeight = nOutHeight; // ohne Rand abzuziehen
3189                             if ( bPixelToLogic )
3190                                 nTotalHeight = pRefDevice->PixelToLogic(Size(0,nTotalHeight)).Height();
3191 
3192                             long nLeftM = (long) ( (pMargin->GetLeftMargin() + nIndent) * nPPTX );
3193                             long nTopM  = (long) ( pMargin->GetTopMargin() * nPPTY );
3194                             long nRightM  = (long) ( pMargin->GetRightMargin() * nPPTX );
3195                             long nBottomM = (long) ( pMargin->GetBottomMargin() * nPPTY );
3196                             nStartX += nLeftM;
3197                             nStartY += nTopM;
3198                             nOutWidth -= nLeftM + nRightM;
3199                             nOutHeight -= nTopM + nBottomM;
3200 
3201                             //  Rotation schon hier, um bei Umbruch auch PaperSize anzupassen
3202                             long nAttrRotate = 0;
3203                             double nSin = 0.0;
3204                             double nCos = 1.0;
3205                             SvxRotateMode eRotMode = SVX_ROTATE_MODE_STANDARD;
3206                             if ( eOrient == SVX_ORIENTATION_STANDARD )
3207                             {
3208                                 nAttrRotate = ((const SfxInt32Item&)pPattern->
3209                                                     GetItem(ATTR_ROTATE_VALUE, pCondSet)).GetValue();
3210                                 if ( nAttrRotate )
3211                                 {
3212                                     eRotMode = (SvxRotateMode)((const SvxRotateModeItem&)
3213                                                 pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet)).GetValue();
3214 
3215                                     if ( nAttrRotate == 18000 )
3216                                         eRotMode = SVX_ROTATE_MODE_STANDARD;    // keinen Ueberlauf
3217 
3218                                     if ( bLayoutRTL )
3219                                         nAttrRotate = -nAttrRotate;
3220 
3221                                     double nRealOrient = nAttrRotate * F_PI18000;   // 1/100 Grad
3222                                     nCos = cos( nRealOrient );
3223                                     nSin = sin( nRealOrient );
3224                                 }
3225                             }
3226 
3227                             Size aPaperSize = Size( 1000000, 1000000 );
3228                             if (eOrient==SVX_ORIENTATION_STACKED)
3229                                 aPaperSize.Width() = nOutWidth;             // zum Zentrieren
3230                             else if (bBreak)
3231                             {
3232                                 if (nAttrRotate)
3233                                 {
3234                                     //! richtige PaperSize fuer Umbruch haengt von der Zeilenzahl
3235                                     //! ab, solange die Zeilen nicht einzeln versetzt ausgegeben
3236                                     //! werden koennen -> darum unbegrenzt, also kein Umbruch.
3237                                     //! Mit versetzten Zeilen waere das folgende richtig:
3238                                     aPaperSize.Width() = (long)(nOutHeight / fabs(nSin));
3239                                 }
3240                                 else if (eOrient == SVX_ORIENTATION_STANDARD)
3241                                     aPaperSize.Width() = nOutWidth;
3242                                 else
3243                                     aPaperSize.Width() = nOutHeight - 1;
3244                             }
3245                             if (bPixelToLogic)
3246                                 pEngine->SetPaperSize(pRefDevice->PixelToLogic(aPaperSize));
3247                             else
3248                                 pEngine->SetPaperSize(aPaperSize);  // Scale ist immer 1
3249 
3250                             //  Daten aus Zelle lesen
3251 
3252                             if (pCell)
3253                             {
3254                                 if (pCell->GetCellType() == CELLTYPE_EDIT)
3255                                 {
3256                                     const EditTextObject* pData;
3257                                     ((ScEditCell*)pCell)->GetData(pData);
3258 
3259                                     if (pData)
3260                                         pEngine->SetText(*pData);
3261                                     else
3262                                     {
3263                                         DBG_ERROR("pData == 0");
3264                                     }
3265                                 }
3266                                 else
3267                                 {
3268                                     sal_uLong nFormat = pPattern->GetNumberFormat(
3269                                                                 pDoc->GetFormatTable(), pCondSet );
3270                                     String aString;
3271                                     Color* pColor;
3272                                     ScCellFormat::GetString( pCell,
3273                                                              nFormat,aString, &pColor,
3274                                                              *pDoc->GetFormatTable(),
3275                                                              bShowNullValues,
3276                                                              bShowFormulas,
3277                                                              ftCheck );
3278 
3279                                     pEngine->SetText(aString);
3280                                     if ( pColor && !bSyntaxMode && !( bUseStyleColor && bForceAutoColor ) )
3281                                         lcl_SetEditColor( *pEngine, *pColor );
3282                                 }
3283 
3284                                 if ( bSyntaxMode )
3285                                     SetEditSyntaxColor( *pEngine, pCell );
3286                                 else if ( bUseStyleColor && bForceAutoColor )
3287                                     lcl_SetEditColor( *pEngine, COL_AUTO );     //! or have a flag at EditEngine
3288                             }
3289                             else
3290                             {
3291                                 DBG_ERROR("pCell == NULL");
3292                             }
3293 
3294                             pEngine->SetUpdateMode( sal_True );     // after SetText, before CalcTextWidth/GetTextHeight
3295 
3296                             long nEngineWidth  = (long) pEngine->CalcTextWidth();
3297                             long nEngineHeight = pEngine->GetTextHeight();
3298 
3299                             if (nAttrRotate && bBreak)
3300                             {
3301                                 double nAbsCos = fabs( nCos );
3302                                 double nAbsSin = fabs( nSin );
3303 
3304                                 // #47740# adjust witdh of papersize for height of text
3305                                 int nSteps = 5;
3306                                 while (nSteps > 0)
3307                                 {
3308                                     // everything is in pixels
3309                                     long nEnginePixel = pRefDevice->LogicToPixel(
3310                                                             Size(0,nEngineHeight)).Height();
3311                                     long nEffHeight = nOutHeight - (long)(nEnginePixel * nAbsCos) + 2;
3312                                     long nNewWidth = (long)(nEffHeight / nAbsSin) + 2;
3313                                     sal_Bool bFits = ( nNewWidth >= aPaperSize.Width() );
3314                                     if ( bFits )
3315                                         nSteps = 0;
3316                                     else
3317                                     {
3318                                         if ( nNewWidth < 4 )
3319                                         {
3320                                             // can't fit -> fall back to using half height
3321                                             nEffHeight = nOutHeight / 2;
3322                                             nNewWidth = (long)(nEffHeight / nAbsSin) + 2;
3323                                             nSteps = 0;
3324                                         }
3325                                         else
3326                                             --nSteps;
3327 
3328                                         // set paper width and get new text height
3329                                         aPaperSize.Width() = nNewWidth;
3330                                         if (bPixelToLogic)
3331                                             pEngine->SetPaperSize(pRefDevice->PixelToLogic(aPaperSize));
3332                                         else
3333                                             pEngine->SetPaperSize(aPaperSize);  // Scale ist immer 1
3334                                         //pEngine->QuickFormatDoc( sal_True );
3335                                         nEngineWidth  = (long) pEngine->CalcTextWidth();
3336                                         nEngineHeight = pEngine->GetTextHeight();
3337                                     }
3338                                 }
3339                             }
3340 
3341                             long nRealWidth  = nEngineWidth;
3342                             long nRealHeight = nEngineHeight;
3343 
3344                             //  wenn gedreht, Groesse anpassen
3345                             if (nAttrRotate)
3346                             {
3347                                 double nAbsCos = fabs( nCos );
3348                                 double nAbsSin = fabs( nSin );
3349 
3350                                 if ( eRotMode == SVX_ROTATE_MODE_STANDARD )
3351                                     nEngineWidth = (long) ( nRealWidth * nAbsCos +
3352                                                             nRealHeight * nAbsSin );
3353                                 else
3354                                     nEngineWidth = (long) ( nRealHeight / nAbsSin );
3355                                 //! begrenzen !!!
3356 
3357                                 nEngineHeight = (long) ( nRealHeight * nAbsCos +
3358                                                          nRealWidth * nAbsSin );
3359                             }
3360 
3361                             if (!nAttrRotate)           //  hier nur gedrehter Text
3362                                 bHidden = sal_True;         //! vorher abfragen !!!
3363 
3364                             //! weglassen, was nicht hereinragt
3365 
3366                             if (!bHidden)
3367                             {
3368                                 sal_Bool bClip = sal_False;
3369                                 Size aClipSize = Size( nScrX+nScrW-nStartX, nScrY+nScrH-nStartY );
3370 
3371                                 //  weiterschreiben
3372 
3373                                 Size aCellSize;
3374                                 if (bPixelToLogic)
3375                                     aCellSize = pRefDevice->PixelToLogic( Size( nOutWidth, nOutHeight ) );
3376                                 else
3377                                     aCellSize = Size( nOutWidth, nOutHeight );  // Scale ist 1
3378 
3379                                 long nGridWidth = nEngineWidth;
3380                                 sal_Bool bNegative = sal_False;
3381                                 if ( eRotMode != SVX_ROTATE_MODE_STANDARD )
3382                                 {
3383                                     nGridWidth = aCellSize.Width() +
3384                                             Abs((long) ( aCellSize.Height() * nCos / nSin ));
3385                                     bNegative = ( pInfo->nRotateDir == SC_ROTDIR_LEFT );
3386                                     if ( bLayoutRTL )
3387                                         bNegative = !bNegative;
3388                                 }
3389 
3390                                 // use GetOutputArea to hide the grid
3391                                 // (clip region is done manually below)
3392                                 OutputAreaParam aAreaParam;
3393 
3394                                 SCCOL nCellX = nX;
3395                                 SCROW nCellY = nY;
3396                                 SvxCellHorJustify eOutHorJust = eHorJust;
3397                                 if ( eRotMode != SVX_ROTATE_MODE_STANDARD )
3398                                     eOutHorJust = bNegative ? SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_LEFT;
3399                                 long nNeededWidth = nGridWidth;     // in pixel for GetOutputArea
3400                                 if ( bPixelToLogic )
3401                                     nNeededWidth =  pRefDevice->LogicToPixel(Size(nNeededWidth,0)).Width();
3402 
3403                                 GetOutputArea( nX, nArrY, nCellStartX, nPosY, nCellX, nCellY, nNeededWidth,
3404                                                 *pPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
3405                                                 sal_False, sal_False, sal_True, aAreaParam );
3406 
3407                                 if ( bShrink )
3408                                 {
3409                                     long nPixelWidth = bPixelToLogic ?
3410                                         pRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width() : nEngineWidth;
3411                                     long nNeededPixel = nPixelWidth + nLeftM + nRightM;
3412 
3413                                     aAreaParam.mbLeftClip = aAreaParam.mbRightClip = sal_True;
3414 
3415                                     // always do height
3416                                     ShrinkEditEngine( *pEngine, aAreaParam.maAlignRect, nLeftM, nTopM, nRightM, nBottomM,
3417                                         sal_False, sal::static_int_cast<sal_uInt16>(eOrient), nAttrRotate, bPixelToLogic,
3418                                         nEngineWidth, nEngineHeight, nNeededPixel, aAreaParam.mbLeftClip, aAreaParam.mbRightClip );
3419 
3420                                     if ( eRotMode == SVX_ROTATE_MODE_STANDARD )
3421                                     {
3422                                         // do width only if rotating within the cell (standard mode)
3423                                         ShrinkEditEngine( *pEngine, aAreaParam.maAlignRect, nLeftM, nTopM, nRightM, nBottomM,
3424                                             sal_True, sal::static_int_cast<sal_uInt16>(eOrient), nAttrRotate, bPixelToLogic,
3425                                             nEngineWidth, nEngineHeight, nNeededPixel, aAreaParam.mbLeftClip, aAreaParam.mbRightClip );
3426                                     }
3427 
3428                                     // nEngineWidth/nEngineHeight is updated in ShrinkEditEngine
3429                                     // (but width is only valid for standard mode)
3430                                     nRealWidth  = (long) pEngine->CalcTextWidth();
3431                                     nRealHeight = pEngine->GetTextHeight();
3432 
3433                                     if ( eRotMode != SVX_ROTATE_MODE_STANDARD )
3434                                         nEngineWidth = (long) ( nRealHeight / fabs( nSin ) );
3435                                 }
3436 
3437                                 // sal_Bool bVClip = ( nEngineHeight > aCellSize.Height() );
3438 
3439                                 long nClipStartX = nStartX;
3440                                 if (nX<nX1)
3441                                 {
3442                                     //! Clipping unnoetig, wenn links am Fenster
3443 
3444                                     bClip = sal_True;                   // nur Rest ausgeben!
3445                                     if (nStartX<nScrX)
3446                                     {
3447                                         long nDif = nScrX - nStartX;
3448                                         nClipStartX = nScrX;
3449                                         aClipSize.Width() -= nDif;
3450                                     }
3451                                 }
3452 
3453                                 long nClipStartY = nStartY;
3454                                 if (nArrY==0 || bVisChanged)
3455                                 {
3456                                     if ( nClipStartY < nRowPosY )
3457                                     {
3458                                         long nDif = nRowPosY - nClipStartY;
3459                                         bClip = sal_True;
3460                                         nClipStartY = nRowPosY;
3461                                         aClipSize.Height() -= nDif;
3462                                     }
3463                                 }
3464 
3465                                 bClip = sal_True;       // always clip at the window/page border
3466 
3467                                 //Rectangle aClipRect;
3468                                 if (bClip)
3469                                 {
3470                                     if ( nAttrRotate /* && eRotMode != SVX_ROTATE_MODE_STANDARD */ )
3471                                     {
3472                                         //  gedrehten, ausgerichteten Text nur an den
3473                                         //  Seitengrenzen clippen
3474                                         nClipStartX = nScrX;
3475                                         aClipSize.Width() = nScrW;
3476                                     }
3477 
3478                                     if (bPixelToLogic)
3479                                         aAreaParam.maClipRect = pRefDevice->PixelToLogic( Rectangle(
3480                                                         Point(nClipStartX,nClipStartY), aClipSize ) );
3481                                     else
3482                                         aAreaParam.maClipRect = Rectangle(Point(nClipStartX, nClipStartY),
3483                                                                 aClipSize );    // Scale = 1
3484 
3485                                     if (bMetaFile)
3486                                     {
3487                                         pDev->Push();
3488                                         pDev->IntersectClipRegion( aAreaParam.maClipRect );
3489                                     }
3490                                     else
3491                                         pDev->SetClipRegion( Region( aAreaParam.maClipRect ) );
3492                                 }
3493 
3494                                 Point aLogicStart;
3495                                 if (bPixelToLogic)
3496                                     aLogicStart = pRefDevice->PixelToLogic( Point(nStartX,nStartY) );
3497                                 else
3498                                     aLogicStart = Point(nStartX, nStartY);
3499                                 if ( eOrient!=SVX_ORIENTATION_STANDARD || !bBreak )
3500                                 {
3501                                     long nAvailWidth = aCellSize.Width();
3502                                     if (eType==OUTTYPE_WINDOW &&
3503                                             eOrient!=SVX_ORIENTATION_STACKED &&
3504                                             pInfo && pInfo->bAutoFilter)
3505                                     {
3506                                         // filter drop-down width is now independent from row height
3507                                         if (bPixelToLogic)
3508                                             nAvailWidth -= pRefDevice->PixelToLogic(Size(0,DROPDOWN_BITMAP_SIZE)).Height();
3509                                         else
3510                                             nAvailWidth -= DROPDOWN_BITMAP_SIZE;
3511                                         long nComp = nEngineWidth;
3512                                         if (nAvailWidth<nComp) nAvailWidth=nComp;
3513                                     }
3514 
3515                                     //  horizontale Ausrichtung
3516 
3517                                     if (eOrient==SVX_ORIENTATION_STANDARD && !nAttrRotate)
3518                                     {
3519                                         if (eHorJust==SVX_HOR_JUSTIFY_RIGHT ||
3520                                             eHorJust==SVX_HOR_JUSTIFY_CENTER)
3521                                         {
3522                                             pEngine->SetUpdateMode( sal_False );
3523 
3524                                             SvxAdjust eSvxAdjust =
3525                                                 (eHorJust==SVX_HOR_JUSTIFY_RIGHT) ?
3526                                                     SVX_ADJUST_RIGHT : SVX_ADJUST_CENTER;
3527                                             pEngine->SetDefaultItem(
3528                                                 SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) );
3529 
3530                                             aPaperSize.Width() = nOutWidth;
3531                                             if (bPixelToLogic)
3532                                                 pEngine->SetPaperSize(pRefDevice->PixelToLogic(aPaperSize));
3533                                             else
3534                                                 pEngine->SetPaperSize(aPaperSize);
3535 
3536                                             pEngine->SetUpdateMode( sal_True );
3537                                         }
3538                                     }
3539                                     else
3540                                     {
3541                                         //  bei gedrehtem Text ist Standard zentriert
3542                                         if (eHorJust==SVX_HOR_JUSTIFY_RIGHT)
3543                                             aLogicStart.X() += nAvailWidth - nEngineWidth;
3544                                         else if (eHorJust==SVX_HOR_JUSTIFY_CENTER ||
3545                                                  eHorJust==SVX_HOR_JUSTIFY_STANDARD)
3546                                             aLogicStart.X() += (nAvailWidth - nEngineWidth) / 2;
3547                                     }
3548                                 }
3549 
3550                                 if ( bLayoutRTL )
3551                                 {
3552                                     if (bPixelToLogic)
3553                                         aLogicStart.X() -= pRefDevice->PixelToLogic(
3554                                                         Size( nCellWidth, 0 ) ).Width();
3555                                     else
3556                                         aLogicStart.X() -= nCellWidth;
3557                                 }
3558 
3559                                 if ( eOrient==SVX_ORIENTATION_STANDARD ||
3560                                      eOrient==SVX_ORIENTATION_STACKED || !bBreak )
3561                                 {
3562                                     if (eVerJust==SVX_VER_JUSTIFY_BOTTOM ||
3563                                         eVerJust==SVX_VER_JUSTIFY_STANDARD)
3564                                     {
3565                                         if (bPixelToLogic)
3566                                             aLogicStart.Y() += pRefDevice->PixelToLogic( Size(0,
3567                                                             pRefDevice->LogicToPixel(aCellSize).Height() -
3568                                                             pRefDevice->LogicToPixel(Size(0,nEngineHeight)).Height()
3569                                                             )).Height();
3570                                         else
3571                                             aLogicStart.Y() += aCellSize.Height() - nEngineHeight;
3572                                     }
3573 
3574                                     else if (eVerJust==SVX_VER_JUSTIFY_CENTER)
3575                                     {
3576                                         if (bPixelToLogic)
3577                                             aLogicStart.Y() += pRefDevice->PixelToLogic( Size(0,(
3578                                                             pRefDevice->LogicToPixel(aCellSize).Height() -
3579                                                             pRefDevice->LogicToPixel(Size(0,nEngineHeight)).Height())
3580                                                             / 2)).Height();
3581                                         else
3582                                             aLogicStart.Y() += (aCellSize.Height() - nEngineHeight) / 2;
3583                                     }
3584                                 }
3585 
3586                                 // TOPBOTTON and BOTTOMTOP are handled in DrawStrings/DrawEdit
3587                                 DBG_ASSERT( eOrient == SVX_ORIENTATION_STANDARD && nAttrRotate,
3588                                             "DrawRotated: no rotation" );
3589 
3590                                 long nOriVal = 0;
3591                                 if ( nAttrRotate )
3592                                 {
3593                                     // Attribut ist 1/100, Font 1/10 Grad
3594                                     nOriVal = nAttrRotate / 10;
3595 
3596                                     double nAddX = 0.0;
3597                                     double nAddY = 0.0;
3598                                     if ( nCos > 0.0 && eRotMode != SVX_ROTATE_MODE_STANDARD )
3599                                     {
3600                                         //! begrenzen !!!
3601                                         double nH = nRealHeight * nCos;
3602                                         nAddX += nH * ( nCos / fabs(nSin) );
3603                                     }
3604                                     if ( nCos < 0.0 && eRotMode == SVX_ROTATE_MODE_STANDARD )
3605                                         nAddX -= nRealWidth * nCos;
3606                                     if ( nSin < 0.0 )
3607                                         nAddX -= nRealHeight * nSin;
3608                                     if ( nSin > 0.0 )
3609                                         nAddY += nRealWidth * nSin;
3610                                     if ( nCos < 0.0 )
3611                                         nAddY -= nRealHeight * nCos;
3612 
3613                                     if ( eRotMode != SVX_ROTATE_MODE_STANDARD )
3614                                     {
3615                                         //! begrenzen !!!
3616                                         double nSkew = nTotalHeight * nCos / fabs(nSin);
3617                                         if ( eRotMode == SVX_ROTATE_MODE_CENTER )
3618                                             nAddX -= nSkew * 0.5;
3619                                         if ( ( eRotMode == SVX_ROTATE_MODE_TOP && nSin > 0.0 ) ||
3620                                              ( eRotMode == SVX_ROTATE_MODE_BOTTOM && nSin < 0.0 ) )
3621                                             nAddX -= nSkew;
3622 
3623                                         long nUp = 0;
3624                                         if ( eVerJust == SVX_VER_JUSTIFY_CENTER )
3625                                             nUp = ( aCellSize.Height() - nEngineHeight ) / 2;
3626                                         else if ( eVerJust == SVX_VER_JUSTIFY_TOP )
3627                                         {
3628                                             if ( nSin > 0.0 )
3629                                                 nUp = aCellSize.Height() - nEngineHeight;
3630                                         }
3631                                         else    // BOTTOM / STANDARD
3632                                         {
3633                                             if ( nSin < 0.0 )
3634                                                 nUp = aCellSize.Height() - nEngineHeight;
3635                                         }
3636                                         if ( nUp )
3637                                             nAddX += ( nUp * nCos / fabs(nSin) );
3638                                     }
3639 
3640                                     aLogicStart.X() += (long) nAddX;
3641                                     aLogicStart.Y() += (long) nAddY;
3642                                 }
3643 
3644                                 //  bSimClip is not used here (because nOriVal is set)
3645 
3646                                 if ( pEngine->IsRightToLeft( 0 ) )
3647                                 {
3648                                     //  For right-to-left, EditEngine always calculates its lines
3649                                     //  beginning from the right edge, but EditLine::nStartPosX is
3650                                     //  of sal_uInt16 type, so the PaperSize must be limited to USHRT_MAX.
3651                                     Size aLogicPaper = pEngine->GetPaperSize();
3652                                     if ( aLogicPaper.Width() > USHRT_MAX )
3653                                     {
3654                                         aLogicPaper.Width() = USHRT_MAX;
3655                                         pEngine->SetPaperSize(aLogicPaper);
3656                                     }
3657                                 }
3658 
3659                                 pEngine->Draw( pDev, aLogicStart, (short)nOriVal );
3660 
3661                                 if (bClip)
3662                                 {
3663                                     if (bMetaFile)
3664                                         pDev->Pop();
3665                                     else
3666                                         pDev->SetClipRegion();
3667                                 }
3668                             }
3669                         }
3670                     }
3671                 }
3672                 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
3673             }
3674         }
3675         nRowPosY += pRowInfo[nArrY].nHeight;
3676     }
3677 
3678     delete pEngine;
3679 }
3680 
3681 
3682 
3683