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