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