xref: /trunk/main/sc/source/ui/view/output2.cxx (revision c2eaa082)
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_uInt32 nParCount = rEngine.GetParagraphCount();
1969     for (sal_uInt32 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