merge the formfield patch from ooo-build
[ooovba.git] / sc / source / ui / view / output2.cxx
blob7eb59e2b2b85208b1a3fb0260cb28a2aa1633a3e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: output2.cxx,v $
10 * $Revision: 1.56.142.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
37 // INCLUDE ---------------------------------------------------------------
39 #include "scitems.hxx"
40 #include <svx/eeitem.hxx>
43 #include <svx/adjitem.hxx>
44 #include <svx/algitem.hxx>
45 #include <svx/brshitem.hxx>
46 #include <svtools/colorcfg.hxx>
47 #include <svx/colritem.hxx>
48 #include <svx/editobj.hxx>
49 #include <svx/editstat.hxx>
50 #include <svx/fhgtitem.hxx>
51 #include <svx/forbiddencharacterstable.hxx>
52 #include <svx/frmdiritem.hxx>
53 #include <svx/langitem.hxx>
54 #include <svx/rotmodit.hxx>
55 #include <svx/scripttypeitem.hxx>
56 #include <svx/udlnitem.hxx>
57 #include <svx/unolingu.hxx>
58 #include <svtools/zforlist.hxx>
59 #include <vcl/svapp.hxx>
60 #include <vcl/metric.hxx>
61 #include <vcl/outdev.hxx>
62 #include <vcl/pdfextoutdevdata.hxx>
64 #ifndef _SVSTDARR_USHORTS
65 #define _SVSTDARR_USHORTS
66 #include <svtools/svstdarr.hxx>
67 #endif
69 #include "output.hxx"
70 #include "document.hxx"
71 #include "cell.hxx"
72 #include "attrib.hxx"
73 #include "patattr.hxx"
74 #include "cellform.hxx"
75 #include "editutil.hxx"
76 #include "progress.hxx"
77 #include "scmod.hxx"
78 #include "fillinfo.hxx"
80 #include <math.h>
82 //! Autofilter-Breite mit column.cxx zusammenfassen
83 #define DROPDOWN_BITMAP_SIZE 17
85 #define DRAWTEXT_MAX 32767
87 const USHORT SC_SHRINKAGAIN_MAX = 7;
89 // STATIC DATA -----------------------------------------------------------
92 // -----------------------------------------------------------------------
94 class ScDrawStringsVars
96 ScOutputData* pOutput; // Verbindung
98 const ScPatternAttr* pPattern; // Attribute
99 const SfxItemSet* pCondSet; // aus bedingter Formatierung
101 Font aFont; // aus Attributen erzeugt
102 FontMetric aMetric;
103 long nAscentPixel; // always pixels
104 SvxCellOrientation eAttrOrient;
105 SvxCellHorJustify eAttrHorJust;
106 SvxCellVerJustify eAttrVerJust;
107 const SvxMarginItem* pMargin;
108 USHORT nIndent;
109 BOOL bRotated;
111 String aString; // Inhalte
112 Size aTextSize;
113 long nOriginalWidth;
115 ScBaseCell* pLastCell;
116 ULONG nValueFormat;
117 BOOL bLineBreak;
118 BOOL bRepeat;
119 BOOL bShrink;
121 BOOL bPixelToLogic;
122 BOOL bCellContrast;
124 Color aBackConfigColor; // used for ScPatternAttr::GetFont calls
125 Color aTextConfigColor;
127 public:
128 ScDrawStringsVars(ScOutputData* pData, BOOL bPTL);
129 ~ScDrawStringsVars();
131 // SetPattern = ex-SetVars
132 // SetPatternSimple: ohne Font
134 void SetPattern( const ScPatternAttr* pNew, const SfxItemSet* pSet, ScBaseCell* pCell, BYTE nScript );
135 void SetPatternSimple( const ScPatternAttr* pNew, const SfxItemSet* pSet );
137 BOOL SetText( ScBaseCell* pCell ); // TRUE -> pOldPattern vergessen
138 void SetHashText();
139 void SetAutoText( const String& rAutoText );
141 const ScPatternAttr* GetPattern() const { return pPattern; }
142 SvxCellOrientation GetOrient() const { return eAttrOrient; }
143 SvxCellHorJustify GetHorJust() const { return eAttrHorJust; }
144 SvxCellVerJustify GetVerJust() const { return eAttrVerJust; }
145 const SvxMarginItem* GetMargin() const { return pMargin; }
147 USHORT GetLeftTotal() const { return pMargin->GetLeftMargin() + nIndent; }
149 const String& GetString() const { return aString; }
150 const Size& GetTextSize() const { return aTextSize; }
151 long GetOriginalWidth() const { return nOriginalWidth; }
153 ULONG GetValueFormat() const { return nValueFormat; }
154 BOOL GetLineBreak() const { return bLineBreak; }
155 BOOL IsRepeat() const { return bRepeat; }
156 BOOL IsShrink() const { return bShrink; }
158 long GetAscent() const { return nAscentPixel; }
159 BOOL IsRotated() const { return bRotated; }
161 void SetShrinkScale( long nScale, BYTE nScript );
163 BOOL HasCondHeight() const { return pCondSet && SFX_ITEM_SET ==
164 pCondSet->GetItemState( ATTR_FONT_HEIGHT, TRUE ); }
166 BOOL HasEditCharacters() const;
169 //==================================================================
171 ScDrawStringsVars::ScDrawStringsVars(ScOutputData* pData, BOOL bPTL) :
172 pOutput ( pData ),
173 pPattern ( NULL ),
174 pCondSet ( NULL ),
175 eAttrOrient ( SVX_ORIENTATION_STANDARD ),
176 eAttrHorJust( SVX_HOR_JUSTIFY_STANDARD ),
177 eAttrVerJust( SVX_VER_JUSTIFY_BOTTOM ),
178 pMargin ( NULL ),
179 nIndent ( 0 ),
180 bRotated ( FALSE ),
181 nOriginalWidth( 0 ),
182 pLastCell ( NULL ),
183 nValueFormat( 0 ),
184 bLineBreak ( FALSE ),
185 bRepeat ( FALSE ),
186 bShrink ( FALSE ),
187 bPixelToLogic( bPTL )
189 ScModule* pScMod = SC_MOD();
190 // #105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed TRUE)
191 bCellContrast = pOutput->bUseStyleColor &&
192 Application::GetSettings().GetStyleSettings().GetHighContrastMode();
194 const svtools::ColorConfig& rColorConfig = pScMod->GetColorConfig();
195 aBackConfigColor.SetColor( rColorConfig.GetColorValue(svtools::DOCCOLOR).nColor );
196 aTextConfigColor.SetColor( rColorConfig.GetColorValue(svtools::FONTCOLOR).nColor );
199 ScDrawStringsVars::~ScDrawStringsVars()
203 void ScDrawStringsVars::SetShrinkScale( long nScale, BYTE nScript )
205 // text remains valid, size is updated
207 OutputDevice* pDev = pOutput->pDev;
208 OutputDevice* pRefDevice = pOutput->pRefDevice;
209 OutputDevice* pFmtDevice = pOutput->pFmtDevice;
211 // call GetFont with a modified fraction, use only the height
213 Fraction aFraction( nScale, 100 );
214 if ( !bPixelToLogic )
215 aFraction *= pOutput->aZoomY;
216 Font aTmpFont;
217 pPattern->GetFont( aTmpFont, SC_AUTOCOL_RAW, pFmtDevice, &aFraction, pCondSet, nScript );
218 long nNewHeight = aTmpFont.GetHeight();
219 if ( nNewHeight > 0 )
220 aFont.SetHeight( nNewHeight );
222 // set font and dependent variables as in SetPattern
224 pDev->SetFont( aFont );
225 if ( pFmtDevice != pDev )
226 pFmtDevice->SetFont( aFont );
228 aMetric = pFmtDevice->GetFontMetric();
229 if ( pFmtDevice->GetOutDevType() == OUTDEV_PRINTER && aMetric.GetIntLeading() == 0 )
231 OutputDevice* pDefaultDev = Application::GetDefaultDevice();
232 MapMode aOld = pDefaultDev->GetMapMode();
233 pDefaultDev->SetMapMode( pFmtDevice->GetMapMode() );
234 aMetric = pDefaultDev->GetFontMetric( aFont );
235 pDefaultDev->SetMapMode( aOld );
238 nAscentPixel = aMetric.GetAscent();
239 if ( bPixelToLogic )
240 nAscentPixel = pRefDevice->LogicToPixel( Size( 0, nAscentPixel ) ).Height();
242 SetAutoText( aString ); // same text again, to get text size
245 void ScDrawStringsVars::SetPattern( const ScPatternAttr* pNew, const SfxItemSet* pSet,
246 ScBaseCell* pCell, BYTE nScript )
248 pPattern = pNew;
249 pCondSet = pSet;
251 // pPattern auswerten
253 OutputDevice* pDev = pOutput->pDev;
254 OutputDevice* pRefDevice = pOutput->pRefDevice;
255 OutputDevice* pFmtDevice = pOutput->pFmtDevice;
257 // Font
259 ScAutoFontColorMode eColorMode;
260 if ( pOutput->bUseStyleColor )
262 if ( pOutput->bForceAutoColor )
263 eColorMode = bCellContrast ? SC_AUTOCOL_IGNOREALL : SC_AUTOCOL_IGNOREFONT;
264 else
265 eColorMode = bCellContrast ? SC_AUTOCOL_IGNOREBACK : SC_AUTOCOL_DISPLAY;
267 else
268 eColorMode = SC_AUTOCOL_PRINT;
270 if ( bPixelToLogic )
271 pPattern->GetFont( aFont, eColorMode, pFmtDevice, NULL, pCondSet, nScript,
272 &aBackConfigColor, &aTextConfigColor );
273 else
274 pPattern->GetFont( aFont, eColorMode, pFmtDevice, &pOutput->aZoomY, pCondSet, nScript,
275 &aBackConfigColor, &aTextConfigColor );
276 aFont.SetAlign(ALIGN_BASELINE);
278 // Orientierung
280 eAttrOrient = pPattern->GetCellOrientation( pCondSet );
282 // alignment
284 eAttrHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern->GetItem( ATTR_HOR_JUSTIFY, pCondSet )).GetValue();
286 eAttrVerJust = (SvxCellVerJustify)((const SvxVerJustifyItem&)pPattern->GetItem( ATTR_VER_JUSTIFY, pCondSet )).GetValue();
287 if ( eAttrVerJust == SVX_VER_JUSTIFY_STANDARD )
288 eAttrVerJust = SVX_VER_JUSTIFY_BOTTOM;
290 // line break
292 bLineBreak = ((const SfxBoolItem&)pPattern->GetItem( ATTR_LINEBREAK, pCondSet )).GetValue();
294 // handle "repeat" alignment
296 bRepeat = ( eAttrHorJust == SVX_HOR_JUSTIFY_REPEAT );
297 if ( bRepeat )
299 // "repeat" disables rotation (before constructing the font)
300 eAttrOrient = SVX_ORIENTATION_STANDARD;
302 // #i31843# "repeat" with "line breaks" is treated as default alignment (but rotation is still disabled)
303 if ( bLineBreak )
304 eAttrHorJust = SVX_HOR_JUSTIFY_STANDARD;
307 short nRot;
308 switch (eAttrOrient)
310 case SVX_ORIENTATION_STANDARD:
311 nRot = 0;
312 bRotated = (((const SfxInt32Item&)pPattern->GetItem( ATTR_ROTATE_VALUE, pCondSet )).GetValue() != 0) &&
313 !bRepeat;
314 break;
315 case SVX_ORIENTATION_STACKED:
316 nRot = 0;
317 bRotated = FALSE;
318 break;
319 case SVX_ORIENTATION_TOPBOTTOM:
320 nRot = 2700;
321 bRotated = FALSE;
322 break;
323 case SVX_ORIENTATION_BOTTOMTOP:
324 nRot = 900;
325 bRotated = FALSE;
326 break;
327 default:
328 DBG_ERROR("Falscher SvxCellOrientation Wert");
329 nRot = 0;
330 bRotated = FALSE;
331 break;
333 aFont.SetOrientation( nRot );
335 // Syntax-Modus
337 if (pOutput->bSyntaxMode)
338 pOutput->SetSyntaxColor( &aFont, pCell );
340 pDev->SetFont( aFont );
341 if ( pFmtDevice != pDev )
342 pFmtDevice->SetFont( aFont );
344 aMetric = pFmtDevice->GetFontMetric();
347 // Wenn auf dem Drucker das Leading 0 ist, gibt es Probleme
348 // -> Metric vom Bildschirm nehmen (wie EditEngine!)
351 if ( pFmtDevice->GetOutDevType() == OUTDEV_PRINTER && aMetric.GetIntLeading() == 0 )
353 OutputDevice* pDefaultDev = Application::GetDefaultDevice();
354 MapMode aOld = pDefaultDev->GetMapMode();
355 pDefaultDev->SetMapMode( pFmtDevice->GetMapMode() );
356 aMetric = pDefaultDev->GetFontMetric( aFont );
357 pDefaultDev->SetMapMode( aOld );
360 nAscentPixel = aMetric.GetAscent();
361 if ( bPixelToLogic )
362 nAscentPixel = pRefDevice->LogicToPixel( Size( 0, nAscentPixel ) ).Height();
364 Color aULineColor( ((const SvxUnderlineItem&)pPattern->GetItem( ATTR_FONT_UNDERLINE, pCondSet )).GetColor() );
365 pDev->SetTextLineColor( aULineColor );
367 Color aOLineColor( ((const SvxOverlineItem&)pPattern->GetItem( ATTR_FONT_OVERLINE, pCondSet )).GetColor() );
368 pDev->SetOverlineColor( aOLineColor );
370 // Zahlenformat
372 // ULONG nOld = nValueFormat;
373 nValueFormat = pPattern->GetNumberFormat( pOutput->pDoc->GetFormatTable(), pCondSet );
375 /* s.u.
376 if (nValueFormat != nOld)
377 pLastCell = NULL; // immer neu formatieren
379 // Raender
381 pMargin = (const SvxMarginItem*)&pPattern->GetItem( ATTR_MARGIN, pCondSet );
382 if ( eAttrHorJust == SVX_HOR_JUSTIFY_LEFT )
383 nIndent = ((const SfxUInt16Item&)pPattern->GetItem( ATTR_INDENT, pCondSet )).GetValue();
384 else
385 nIndent = 0;
387 // "Shrink to fit"
389 bShrink = static_cast<const SfxBoolItem&>(pPattern->GetItem( ATTR_SHRINKTOFIT, pCondSet )).GetValue();
391 // zumindest die Text-Groesse muss neu geholt werden
392 //! unterscheiden, und den Text nicht neu vom Numberformatter holen?
394 pLastCell = NULL;
397 void ScDrawStringsVars::SetPatternSimple( const ScPatternAttr* pNew, const SfxItemSet* pSet )
399 // wird gerufen, wenn sich die Font-Variablen nicht aendern (!StringDiffer)
401 pPattern = pNew;
402 pCondSet = pSet; //! noetig ???
404 // Zahlenformat
406 ULONG nOld = nValueFormat;
407 // nValueFormat = pPattern->GetNumberFormat( pFormatter );
408 const SfxPoolItem* pFormItem;
409 if ( !pCondSet || pCondSet->GetItemState(ATTR_VALUE_FORMAT,TRUE,&pFormItem) != SFX_ITEM_SET )
410 pFormItem = &pPattern->GetItem(ATTR_VALUE_FORMAT);
411 const SfxPoolItem* pLangItem;
412 if ( !pCondSet || pCondSet->GetItemState(ATTR_LANGUAGE_FORMAT,TRUE,&pLangItem) != SFX_ITEM_SET )
413 pLangItem = &pPattern->GetItem(ATTR_LANGUAGE_FORMAT);
414 nValueFormat = pOutput->pDoc->GetFormatTable()->GetFormatForLanguageIfBuiltIn(
415 ((SfxUInt32Item*)pFormItem)->GetValue(),
416 ((SvxLanguageItem*)pLangItem)->GetLanguage() );
418 if (nValueFormat != nOld)
419 pLastCell = NULL; // immer neu formatieren
421 // Raender
423 pMargin = (const SvxMarginItem*)&pPattern->GetItem( ATTR_MARGIN, pCondSet );
425 if ( eAttrHorJust == SVX_HOR_JUSTIFY_LEFT )
426 nIndent = ((const SfxUInt16Item&)pPattern->GetItem( ATTR_INDENT, pCondSet )).GetValue();
427 else
428 nIndent = 0;
430 // "Shrink to fit"
432 bShrink = static_cast<const SfxBoolItem&>(pPattern->GetItem( ATTR_SHRINKTOFIT, pCondSet )).GetValue();
435 inline BOOL SameValue( ScBaseCell* pCell, ScBaseCell* pOldCell ) // pCell ist != 0
437 return pOldCell && pOldCell->GetCellType() == CELLTYPE_VALUE &&
438 pCell->GetCellType() == CELLTYPE_VALUE &&
439 ((ScValueCell*)pCell)->GetValue() == ((ScValueCell*)pOldCell)->GetValue();
442 BOOL ScDrawStringsVars::SetText( ScBaseCell* pCell )
444 BOOL bChanged = FALSE;
446 if (pCell)
448 if ( !SameValue( pCell, pLastCell ) )
450 pLastCell = pCell; // Zelle merken
452 Color* pColor;
453 ULONG nFormat = GetValueFormat();
455 if (static_cast<NfIndexTableOffset>(nFormat) == NF_NUMBER_STANDARD)
456 // For 'General' format type, display the value the same way it
457 // is displayed in the edit window, which automatically
458 // adjusts the number of decimal places based on the value of
459 // the cell.
460 ScCellFormat::GetInputString( pCell,
461 nFormat, aString,
462 *pOutput->pDoc->GetFormatTable(),
463 &pColor );
464 else
465 ScCellFormat::GetString( pCell,
466 nFormat, aString, &pColor,
467 *pOutput->pDoc->GetFormatTable(),
468 pOutput->bShowNullValues,
469 pOutput->bShowFormulas,
470 ftCheck );
472 if (aString.Len() > DRAWTEXT_MAX)
473 aString.Erase(DRAWTEXT_MAX);
475 if ( pColor && !pOutput->bSyntaxMode && !( pOutput->bUseStyleColor && pOutput->bForceAutoColor ) )
477 OutputDevice* pDev = pOutput->pDev;
478 aFont.SetColor(*pColor);
479 pDev->SetFont( aFont ); // nur fuer Ausgabe
480 bChanged = TRUE;
481 pLastCell = NULL; // naechstes Mal wieder hierherkommen
484 OutputDevice* pRefDevice = pOutput->pRefDevice;
485 OutputDevice* pFmtDevice = pOutput->pFmtDevice;
486 aTextSize.Width() = pFmtDevice->GetTextWidth( aString );
487 aTextSize.Height() = pFmtDevice->GetTextHeight();
489 if ( !pRefDevice->GetConnectMetaFile() || pRefDevice->GetOutDevType() == OUTDEV_PRINTER )
491 double fMul = pOutput->GetStretch();
492 aTextSize.Width() = (long)(aTextSize.Width() / fMul + 0.5);
495 aTextSize.Height() = aMetric.GetAscent() + aMetric.GetDescent();
496 if ( GetOrient() != SVX_ORIENTATION_STANDARD )
498 long nTemp = aTextSize.Height();
499 aTextSize.Height() = aTextSize.Width();
500 aTextSize.Width() = nTemp;
503 nOriginalWidth = aTextSize.Width();
504 if ( bPixelToLogic )
505 aTextSize = pRefDevice->LogicToPixel( aTextSize );
507 // sonst String/Groesse behalten
509 else
511 aString.Erase();
512 pLastCell = NULL;
513 aTextSize = Size(0,0);
514 nOriginalWidth = 0;
517 return bChanged;
520 void ScDrawStringsVars::SetHashText()
522 SetAutoText( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("###")) );
525 void ScDrawStringsVars::SetAutoText( const String& rAutoText )
527 aString = rAutoText;
529 OutputDevice* pRefDevice = pOutput->pRefDevice;
530 OutputDevice* pFmtDevice = pOutput->pFmtDevice;
531 aTextSize.Width() = pFmtDevice->GetTextWidth( aString );
532 aTextSize.Height() = pFmtDevice->GetTextHeight();
534 if ( !pRefDevice->GetConnectMetaFile() || pRefDevice->GetOutDevType() == OUTDEV_PRINTER )
536 double fMul = pOutput->GetStretch();
537 aTextSize.Width() = (long)(aTextSize.Width() / fMul + 0.5);
540 aTextSize.Height() = aMetric.GetAscent() + aMetric.GetDescent();
541 if ( GetOrient() != SVX_ORIENTATION_STANDARD )
543 long nTemp = aTextSize.Height();
544 aTextSize.Height() = aTextSize.Width();
545 aTextSize.Width() = nTemp;
548 nOriginalWidth = aTextSize.Width();
549 if ( bPixelToLogic )
550 aTextSize = pRefDevice->LogicToPixel( aTextSize );
552 pLastCell = NULL; // derselbe Text kann in der naechsten Zelle wieder passen
555 BOOL ScDrawStringsVars::HasEditCharacters() const
557 static const sal_Unicode pChars[] =
559 CHAR_NBSP, CHAR_SHY, CHAR_ZWSP, CHAR_LRM, CHAR_RLM, CHAR_NBHY, CHAR_ZWNBSP, 0
561 return aString.SearchChar( pChars ) != STRING_NOTFOUND;
564 //==================================================================
566 double ScOutputData::GetStretch()
568 if ( pRefDevice->IsMapMode() )
570 // #95920# If a non-trivial MapMode is set, its scale is now already
571 // taken into account in the OutputDevice's font handling
572 // (OutputDevice::ImplNewFont, see #95414#).
573 // The old handling below is only needed for pixel output.
574 return 1.0;
577 // calculation in double is faster than Fraction multiplication
578 // and doesn't overflow
580 if ( pRefDevice == pFmtDevice )
582 MapMode aOld = pRefDevice->GetMapMode();
583 return ((double)aOld.GetScaleY()) / ((double)aOld.GetScaleX()) * ((double)aZoomY) / ((double)aZoomX);
585 else
587 // when formatting for printer, device map mode has already been taken care of
588 return ((double)aZoomY) / ((double)aZoomX);
592 //==================================================================
595 // output strings
598 void lcl_DoHyperlinkResult( OutputDevice* pDev, const Rectangle& rRect, ScBaseCell* pCell )
600 vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, pDev->GetExtOutDevData() );
602 String aCellText;
603 String aURL;
604 if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA )
606 ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
607 if ( pFCell->IsHyperLinkCell() )
608 pFCell->GetURLResult( aURL, aCellText );
611 if ( aURL.Len() && pPDFData )
613 vcl::PDFExtOutDevBookmarkEntry aBookmark;
614 aBookmark.nLinkId = pPDFData->CreateLink( rRect );
615 aBookmark.aBookmark = aURL;
616 std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFData->GetBookmarks();
617 rBookmarks.push_back( aBookmark );
621 void ScOutputData::SetSyntaxColor( Font* pFont, ScBaseCell* pCell )
623 if (pCell)
625 switch (pCell->GetCellType())
627 case CELLTYPE_VALUE:
628 pFont->SetColor( *pValueColor );
629 break;
630 case CELLTYPE_STRING:
631 pFont->SetColor( *pTextColor );
632 break;
633 case CELLTYPE_FORMULA:
634 pFont->SetColor( *pFormulaColor );
635 break;
636 default:
638 // added to avoid warnings
644 void lcl_SetEditColor( EditEngine& rEngine, const Color& rColor )
646 ESelection aSel( 0, 0, rEngine.GetParagraphCount(), 0 );
647 SfxItemSet aSet( rEngine.GetEmptyItemSet() );
648 aSet.Put( SvxColorItem( rColor, EE_CHAR_COLOR ) );
649 rEngine.QuickSetAttribs( aSet, aSel );
650 // function is called with update mode set to FALSE
653 void ScOutputData::SetEditSyntaxColor( EditEngine& rEngine, ScBaseCell* pCell )
655 if (pCell)
657 Color aColor;
658 switch (pCell->GetCellType())
660 case CELLTYPE_VALUE:
661 aColor = *pValueColor;
662 break;
663 case CELLTYPE_STRING:
664 aColor = *pTextColor;
665 break;
666 case CELLTYPE_FORMULA:
667 aColor = *pFormulaColor;
668 break;
669 default:
671 // added to avoid warnings
674 lcl_SetEditColor( rEngine, aColor );
678 BOOL ScOutputData::GetMergeOrigin( SCCOL nX, SCROW nY, SCSIZE nArrY,
679 SCCOL& rOverX, SCROW& rOverY,
680 BOOL bVisRowChanged )
682 BOOL bDoMerge = FALSE;
683 BOOL bIsLeft = ( nX == nVisX1 );
684 BOOL bIsTop = ( nY == nVisY1 ) || bVisRowChanged;
686 CellInfo* pInfo = &pRowInfo[nArrY].pCellInfo[nX+1];
687 if ( pInfo->bHOverlapped && pInfo->bVOverlapped )
688 bDoMerge = bIsLeft && bIsTop;
689 else if ( pInfo->bHOverlapped )
690 bDoMerge = bIsLeft;
691 else if ( pInfo->bVOverlapped )
692 bDoMerge = bIsTop;
694 // weiter solange versteckt
695 /* if (!bDoMerge)
696 return FALSE;
699 rOverX = nX;
700 rOverY = nY;
701 BOOL bHOver = pInfo->bHOverlapped;
702 BOOL bVOver = pInfo->bVOverlapped;
703 BOOL bHidden;
705 while (bHOver) // nY konstant
707 --rOverX;
708 bHidden = pDoc->ColHidden(rOverX, nTab);
709 if ( !bDoMerge && !bHidden )
710 return FALSE;
712 if (rOverX >= nX1 && !bHidden)
714 // rVirtPosX -= pRowInfo[0].pCellInfo[rOverX+1].nWidth;
715 bHOver = pRowInfo[nArrY].pCellInfo[rOverX+1].bHOverlapped;
716 bVOver = pRowInfo[nArrY].pCellInfo[rOverX+1].bVOverlapped;
718 else
720 // if (!bClipVirt)
721 // rVirtPosX -= (long) (pDoc->GetColWidth( rOverX, nTab ) * nPPTX);
722 USHORT nOverlap = ((ScMergeFlagAttr*)pDoc->GetAttr(
723 rOverX, rOverY, nTab, ATTR_MERGE_FLAG ))->GetValue();
724 bHOver = ((nOverlap & SC_MF_HOR) != 0);
725 bVOver = ((nOverlap & SC_MF_VER) != 0);
729 while (bVOver)
731 --rOverY;
732 bHidden = pDoc->RowHidden(rOverY, nTab);
733 if ( !bDoMerge && !bHidden )
734 return FALSE;
736 if (nArrY>0)
737 --nArrY; // lokale Kopie !
739 if (rOverX >= nX1 && rOverY >= nY1 &&
740 !pDoc->ColHidden(rOverX, nTab) &&
741 !pDoc->RowHidden(rOverY, nTab) &&
742 pRowInfo[nArrY].nRowNo == rOverY)
744 // rVirtPosY -= pRowInfo[nArrY].nHeight;
745 bHOver = pRowInfo[nArrY].pCellInfo[rOverX+1].bHOverlapped;
746 bVOver = pRowInfo[nArrY].pCellInfo[rOverX+1].bVOverlapped;
748 else
750 // if (!bClipVirt)
751 // rVirtPosY -= (long) (pDoc->GetRowHeight( rOverY, nTab ) * nPPTY);
752 USHORT nOverlap = ((ScMergeFlagAttr*)pDoc->GetAttr(
753 rOverX, rOverY, nTab, ATTR_MERGE_FLAG ))->GetValue();
754 bHOver = ((nOverlap & SC_MF_HOR) != 0);
755 bVOver = ((nOverlap & SC_MF_VER) != 0);
759 return TRUE;
762 inline BOOL StringDiffer( const ScPatternAttr*& rpOldPattern, const ScPatternAttr*& rpNewPattern )
764 DBG_ASSERT( rpNewPattern, "pNewPattern" );
766 if ( rpNewPattern == rpOldPattern )
767 return FALSE;
768 else if ( !rpOldPattern )
769 return TRUE;
770 else if ( &rpNewPattern->GetItem( ATTR_FONT ) != &rpOldPattern->GetItem( ATTR_FONT ) )
771 return TRUE;
772 else if ( &rpNewPattern->GetItem( ATTR_CJK_FONT ) != &rpOldPattern->GetItem( ATTR_CJK_FONT ) )
773 return TRUE;
774 else if ( &rpNewPattern->GetItem( ATTR_CTL_FONT ) != &rpOldPattern->GetItem( ATTR_CTL_FONT ) )
775 return TRUE;
776 else if ( &rpNewPattern->GetItem( ATTR_FONT_HEIGHT ) != &rpOldPattern->GetItem( ATTR_FONT_HEIGHT ) )
777 return TRUE;
778 else if ( &rpNewPattern->GetItem( ATTR_CJK_FONT_HEIGHT ) != &rpOldPattern->GetItem( ATTR_CJK_FONT_HEIGHT ) )
779 return TRUE;
780 else if ( &rpNewPattern->GetItem( ATTR_CTL_FONT_HEIGHT ) != &rpOldPattern->GetItem( ATTR_CTL_FONT_HEIGHT ) )
781 return TRUE;
782 else if ( &rpNewPattern->GetItem( ATTR_FONT_WEIGHT ) != &rpOldPattern->GetItem( ATTR_FONT_WEIGHT ) )
783 return TRUE;
784 else if ( &rpNewPattern->GetItem( ATTR_CJK_FONT_WEIGHT ) != &rpOldPattern->GetItem( ATTR_CJK_FONT_WEIGHT ) )
785 return TRUE;
786 else if ( &rpNewPattern->GetItem( ATTR_CTL_FONT_WEIGHT ) != &rpOldPattern->GetItem( ATTR_CTL_FONT_WEIGHT ) )
787 return TRUE;
788 else if ( &rpNewPattern->GetItem( ATTR_FONT_POSTURE ) != &rpOldPattern->GetItem( ATTR_FONT_POSTURE ) )
789 return TRUE;
790 else if ( &rpNewPattern->GetItem( ATTR_CJK_FONT_POSTURE ) != &rpOldPattern->GetItem( ATTR_CJK_FONT_POSTURE ) )
791 return TRUE;
792 else if ( &rpNewPattern->GetItem( ATTR_CTL_FONT_POSTURE ) != &rpOldPattern->GetItem( ATTR_CTL_FONT_POSTURE ) )
793 return TRUE;
794 else if ( &rpNewPattern->GetItem( ATTR_FONT_UNDERLINE ) != &rpOldPattern->GetItem( ATTR_FONT_UNDERLINE ) )
795 return TRUE;
796 else if ( &rpNewPattern->GetItem( ATTR_FONT_OVERLINE ) != &rpOldPattern->GetItem( ATTR_FONT_OVERLINE ) )
797 return TRUE;
798 else if ( &rpNewPattern->GetItem( ATTR_FONT_WORDLINE ) != &rpOldPattern->GetItem( ATTR_FONT_WORDLINE ) )
799 return TRUE;
800 else if ( &rpNewPattern->GetItem( ATTR_FONT_CROSSEDOUT ) != &rpOldPattern->GetItem( ATTR_FONT_CROSSEDOUT ) )
801 return TRUE;
802 else if ( &rpNewPattern->GetItem( ATTR_FONT_CONTOUR ) != &rpOldPattern->GetItem( ATTR_FONT_CONTOUR ) )
803 return TRUE;
804 else if ( &rpNewPattern->GetItem( ATTR_FONT_SHADOWED ) != &rpOldPattern->GetItem( ATTR_FONT_SHADOWED ) )
805 return TRUE;
806 else if ( &rpNewPattern->GetItem( ATTR_FONT_COLOR ) != &rpOldPattern->GetItem( ATTR_FONT_COLOR ) )
807 return TRUE;
808 else if ( &rpNewPattern->GetItem( ATTR_HOR_JUSTIFY ) != &rpOldPattern->GetItem( ATTR_HOR_JUSTIFY ) )
809 return TRUE;
810 else if ( &rpNewPattern->GetItem( ATTR_VER_JUSTIFY ) != &rpOldPattern->GetItem( ATTR_VER_JUSTIFY ) )
811 return TRUE;
812 else if ( &rpNewPattern->GetItem( ATTR_STACKED ) != &rpOldPattern->GetItem( ATTR_STACKED ) )
813 return TRUE;
814 else if ( &rpNewPattern->GetItem( ATTR_LINEBREAK ) != &rpOldPattern->GetItem( ATTR_LINEBREAK ) )
815 return TRUE;
816 else if ( &rpNewPattern->GetItem( ATTR_MARGIN ) != &rpOldPattern->GetItem( ATTR_MARGIN ) )
817 return TRUE;
818 else if ( &rpNewPattern->GetItem( ATTR_ROTATE_VALUE ) != &rpOldPattern->GetItem( ATTR_ROTATE_VALUE ) )
819 return TRUE;
820 else if ( &rpNewPattern->GetItem( ATTR_FORBIDDEN_RULES ) != &rpOldPattern->GetItem( ATTR_FORBIDDEN_RULES ) )
821 return TRUE;
822 else if ( &rpNewPattern->GetItem( ATTR_FONT_EMPHASISMARK ) != &rpOldPattern->GetItem( ATTR_FONT_EMPHASISMARK ) )
823 return TRUE;
824 else if ( &rpNewPattern->GetItem( ATTR_FONT_RELIEF ) != &rpOldPattern->GetItem( ATTR_FONT_RELIEF ) )
825 return TRUE;
826 else if ( &rpNewPattern->GetItem( ATTR_BACKGROUND ) != &rpOldPattern->GetItem( ATTR_BACKGROUND ) )
827 return TRUE; // needed with automatic text color
828 else
830 rpOldPattern = rpNewPattern;
831 return FALSE;
835 inline void lcl_CreateInterpretProgress( BOOL& bProgress, ScDocument* pDoc,
836 ScFormulaCell* pFCell )
838 if ( !bProgress && pFCell->GetDirty() )
840 ScProgress::CreateInterpretProgress( pDoc, TRUE );
841 bProgress = TRUE;
845 inline BYTE GetScriptType( ScDocument* pDoc, ScBaseCell* pCell,
846 const ScPatternAttr* pPattern,
847 const SfxItemSet* pCondSet )
849 return pDoc->GetCellScriptType( pCell, pPattern->GetNumberFormat( pDoc->GetFormatTable(), pCondSet ) );
852 inline BOOL IsAmbiguousScript( BYTE nScript )
854 return ( nScript != SCRIPTTYPE_LATIN &&
855 nScript != SCRIPTTYPE_ASIAN &&
856 nScript != SCRIPTTYPE_COMPLEX );
859 BOOL ScOutputData::IsEmptyCellText( RowInfo* pThisRowInfo, SCCOL nX, SCROW nY )
861 // pThisRowInfo may be NULL
863 BOOL bEmpty;
864 if ( pThisRowInfo && nX <= nX2 )
865 bEmpty = pThisRowInfo->pCellInfo[nX+1].bEmptyCellText;
866 else
867 bEmpty = ( pDoc->GetCell( ScAddress( nX, nY, nTab ) ) == NULL );
869 if ( !bEmpty && ( nX < nX1 || nX > nX2 || !pThisRowInfo ) )
871 // for the range nX1..nX2 in RowInfo, cell protection attribute is already evaluated
872 // into bEmptyCellText in ScDocument::FillInfo / lcl_HidePrint (printfun)
874 BOOL bIsPrint = ( eType == OUTTYPE_PRINTER );
876 if ( bIsPrint || bTabProtected )
878 const ScProtectionAttr* pAttr = (const ScProtectionAttr*)
879 pDoc->GetEffItem( nX, nY, nTab, ATTR_PROTECTION );
880 if ( bIsPrint && pAttr->GetHidePrint() )
881 bEmpty = TRUE;
882 else if ( bTabProtected )
884 if ( pAttr->GetHideCell() )
885 bEmpty = TRUE;
886 else if ( bShowFormulas && pAttr->GetHideFormula() )
888 ScBaseCell* pCell = pDoc->GetCell( ScAddress( nX, nY, nTab ) );
889 if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA )
890 bEmpty = TRUE;
895 return bEmpty;
898 void ScOutputData::GetVisibleCell( SCCOL nCol, SCROW nRow, SCTAB nTabP, ScBaseCell*& rpCell )
900 pDoc->GetCell( nCol, nRow, nTabP, rpCell );
901 if ( rpCell && IsEmptyCellText( NULL, nCol, nRow ) )
902 rpCell = NULL;
905 BOOL ScOutputData::IsAvailable( SCCOL nX, SCROW nY )
907 // apply the same logic here as in DrawStrings/DrawEdit:
908 // Stop at non-empty or merged or overlapped cell,
909 // where a note is empty as well as a cell that's hidden by protection settings
911 const ScBaseCell* pCell = pDoc->GetCell( ScAddress( nX, nY, nTab ) );
912 if ( pCell && pCell->GetCellType() != CELLTYPE_NOTE && !IsEmptyCellText( NULL, nX, nY ) )
914 return FALSE;
917 const ScPatternAttr* pPattern = pDoc->GetPattern( nX, nY, nTab );
918 if ( ((const ScMergeAttr&)pPattern->GetItem(ATTR_MERGE)).IsMerged() ||
919 ((const ScMergeFlagAttr&)pPattern->GetItem(ATTR_MERGE_FLAG)).IsOverlapped() )
921 return FALSE;
924 return TRUE;
927 // nX, nArrY: loop variables from DrawStrings / DrawEdit
928 // nPosX, nPosY: corresponding positions for nX, nArrY
929 // nCellX, nCellY: position of the cell that contains the text
930 // nNeeded: Text width, including margin
931 // rPattern: cell format at nCellX, nCellY
932 // nHorJustify: horizontal alignment (visual) to determine which cells to use for long strings
933 // bCellIsValue: if set, don't extend into empty cells
934 // bBreak: if set, don't extend, and don't set clip marks (but rLeftClip/rRightClip is set)
935 // bOverwrite: if set, also extend into non-empty cells (for rotated text)
936 // rAlignRect: output: single or merged cell, used for alignment (visual rectangle)
937 // rClipRect: output: total output area, for clipping (visual)
938 // rLeftClip: output: need to clip at rClipRect left (visual) edge
939 // rRightClip: output: same for right
941 void ScOutputData::GetOutputArea( SCCOL nX, SCSIZE nArrY, long nPosX, long nPosY,
942 SCCOL nCellX, SCROW nCellY, long nNeeded,
943 const ScPatternAttr& rPattern,
944 USHORT nHorJustify, BOOL bCellIsValue,
945 BOOL bBreak, BOOL bOverwrite,
946 Rectangle& rAlignRect, Rectangle& rClipRect,
947 BOOL& rLeftClip, BOOL& rRightClip )
949 // rThisRowInfo may be for a different row than nCellY, is still used for clip marks
950 RowInfo& rThisRowInfo = pRowInfo[nArrY];
952 long nLayoutSign = bLayoutRTL ? -1 : 1;
954 long nCellPosX = nPosX; // find nCellX position, starting at nX/nPosX
955 SCCOL nCompCol = nX;
956 while ( nCellX > nCompCol )
958 //! extra member function for width?
959 long nColWidth = ( nCompCol <= nX2 ) ?
960 pRowInfo[0].pCellInfo[nCompCol+1].nWidth :
961 (long) ( pDoc->GetColWidth( nCompCol, nTab ) * nPPTX );
962 nCellPosX += nColWidth * nLayoutSign;
963 ++nCompCol;
965 while ( nCellX < nCompCol )
967 --nCompCol;
968 long nColWidth = ( nCompCol <= nX2 ) ?
969 pRowInfo[0].pCellInfo[nCompCol+1].nWidth :
970 (long) ( pDoc->GetColWidth( nCompCol, nTab ) * nPPTX );
971 nCellPosX -= nColWidth * nLayoutSign;
974 long nCellPosY = nPosY; // find nCellY position, starting at nArrY/nPosY
975 SCSIZE nCompArr = nArrY;
976 SCROW nCompRow = pRowInfo[nCompArr].nRowNo;
977 while ( nCellY > nCompRow )
979 if ( nCompArr + 1 < nArrCount )
981 nCellPosY += pRowInfo[nCompArr].nHeight;
982 ++nCompArr;
983 nCompRow = pRowInfo[nCompArr].nRowNo;
985 else
987 USHORT nDocHeight = pDoc->GetRowHeight( nCompRow, nTab );
988 if ( nDocHeight )
989 nCellPosY += (long) ( nDocHeight * nPPTY );
990 ++nCompRow;
993 nCellPosY -= (long) pDoc->GetScaledRowHeight( nCellY, nCompRow-1, nTab, nPPTY );
995 const ScMergeAttr* pMerge = (const ScMergeAttr*)&rPattern.GetItem( ATTR_MERGE );
996 BOOL bMerged = pMerge->IsMerged();
997 long nMergeCols = pMerge->GetColMerge();
998 if ( nMergeCols == 0 )
999 nMergeCols = 1;
1000 long nMergeRows = pMerge->GetRowMerge();
1001 if ( nMergeRows == 0 )
1002 nMergeRows = 1;
1004 long i;
1005 long nMergeSizeX = 0;
1006 for ( i=0; i<nMergeCols; i++ )
1008 long nColWidth = ( nCellX+i <= nX2 ) ?
1009 pRowInfo[0].pCellInfo[nCellX+i+1].nWidth :
1010 (long) ( pDoc->GetColWidth( sal::static_int_cast<SCCOL>(nCellX+i), nTab ) * nPPTX );
1011 nMergeSizeX += nColWidth;
1013 long nMergeSizeY = 0;
1014 short nDirect = 0;
1015 if ( rThisRowInfo.nRowNo == nCellY )
1017 // take first row's height from row info
1018 nMergeSizeY += rThisRowInfo.nHeight;
1019 nDirect = 1; // skip in loop
1021 // following rows always from document
1022 nMergeSizeY += (long) pDoc->GetScaledRowHeight( nCellY+nDirect, nCellY+nMergeRows-1, nTab, nPPTY);
1024 --nMergeSizeX; // leave out the grid horizontally, also for alignment (align between grid lines)
1027 // construct the rectangles using logical left/right values (justify is called at the end)
1030 // rAlignRect is the single cell or merged area, used for alignment.
1032 rAlignRect.Left() = nCellPosX;
1033 rAlignRect.Right() = nCellPosX + ( nMergeSizeX - 1 ) * nLayoutSign;
1034 rAlignRect.Top() = nCellPosY;
1035 rAlignRect.Bottom() = nCellPosY + nMergeSizeY - 1;
1037 // rClipRect is all cells that are used for output.
1038 // For merged cells this is the same as rAlignRect, otherwise neighboring cells can also be used.
1040 rClipRect = rAlignRect;
1041 if ( nNeeded > nMergeSizeX )
1043 SvxCellHorJustify eHorJust = (SvxCellHorJustify)nHorJustify;
1045 long nMissing = nNeeded - nMergeSizeX;
1046 long nLeftMissing = 0;
1047 long nRightMissing = 0;
1048 switch ( eHorJust )
1050 case SVX_HOR_JUSTIFY_LEFT:
1051 nRightMissing = nMissing;
1052 break;
1053 case SVX_HOR_JUSTIFY_RIGHT:
1054 nLeftMissing = nMissing;
1055 break;
1056 case SVX_HOR_JUSTIFY_CENTER:
1057 nLeftMissing = nMissing / 2;
1058 nRightMissing = nMissing - nLeftMissing;
1059 break;
1060 default:
1062 // added to avoid warnings
1066 // nLeftMissing, nRightMissing are logical, eHorJust values are visual
1067 if ( bLayoutRTL )
1068 ::std::swap( nLeftMissing, nRightMissing );
1070 SCCOL nRightX = nCellX;
1071 SCCOL nLeftX = nCellX;
1072 if ( !bMerged && !bCellIsValue && !bBreak )
1074 // look for empty cells into which the text can be extended
1076 while ( nRightMissing > 0 && nRightX < MAXCOL && ( bOverwrite || IsAvailable( nRightX+1, nCellY ) ) )
1078 ++nRightX;
1079 long nAdd = (long) ( pDoc->GetColWidth( nRightX, nTab ) * nPPTX );
1080 nRightMissing -= nAdd;
1081 rClipRect.Right() += nAdd * nLayoutSign;
1083 if ( rThisRowInfo.nRowNo == nCellY && nRightX >= nX1 && nRightX <= nX2 )
1084 rThisRowInfo.pCellInfo[nRightX].bHideGrid = TRUE;
1087 while ( nLeftMissing > 0 && nLeftX > 0 && ( bOverwrite || IsAvailable( nLeftX-1, nCellY ) ) )
1089 if ( rThisRowInfo.nRowNo == nCellY && nLeftX >= nX1 && nLeftX <= nX2 )
1090 rThisRowInfo.pCellInfo[nLeftX].bHideGrid = TRUE;
1092 --nLeftX;
1093 long nAdd = (long) ( pDoc->GetColWidth( nLeftX, nTab ) * nPPTX );
1094 nLeftMissing -= nAdd;
1095 rClipRect.Left() -= nAdd * nLayoutSign;
1099 // Set flag and reserve space for clipping mark triangle,
1100 // even if rThisRowInfo isn't for nCellY (merged cells).
1101 if ( nRightMissing > 0 && bMarkClipped && nRightX >= nX1 && nRightX <= nX2 && !bBreak && !bCellIsValue )
1103 rThisRowInfo.pCellInfo[nRightX+1].nClipMark |= SC_CLIPMARK_RIGHT;
1104 bAnyClipped = TRUE;
1105 long nMarkPixel = (long)( SC_CLIPMARK_SIZE * nPPTX );
1106 rClipRect.Right() -= nMarkPixel * nLayoutSign;
1108 if ( nLeftMissing > 0 && bMarkClipped && nLeftX >= nX1 && nLeftX <= nX2 && !bBreak && !bCellIsValue )
1110 rThisRowInfo.pCellInfo[nLeftX+1].nClipMark |= SC_CLIPMARK_LEFT;
1111 bAnyClipped = TRUE;
1112 long nMarkPixel = (long)( SC_CLIPMARK_SIZE * nPPTX );
1113 rClipRect.Left() += nMarkPixel * nLayoutSign;
1116 rLeftClip = ( nLeftMissing > 0 );
1117 rRightClip = ( nRightMissing > 0 );
1119 else
1121 rLeftClip = rRightClip = FALSE;
1123 // leave space for AutoFilter on screen
1124 // (for automatic line break: only if not formatting for printer, as in ScColumn::GetNeededSize)
1126 if ( eType==OUTTYPE_WINDOW &&
1127 ( static_cast<const ScMergeFlagAttr&>(rPattern.GetItem(ATTR_MERGE_FLAG)).GetValue() & SC_MF_AUTO ) &&
1128 ( !bBreak || pRefDevice == pFmtDevice ) )
1130 long nFilter = Min( nMergeSizeY, (long) DROPDOWN_BITMAP_SIZE );
1131 BOOL bFit = ( nNeeded + nFilter <= nMergeSizeX );
1132 if ( bFit || bCellIsValue )
1134 // content fits even in the remaining area without the filter button
1135 // -> align within that remaining area
1137 rAlignRect.Right() -= nFilter * nLayoutSign;
1138 rClipRect.Right() -= nFilter * nLayoutSign;
1140 // if a number doesn't fit, don't hide part of the number behind the button
1141 // -> set clip flags, so "###" replacement is used (but also within the smaller area)
1143 if ( !bFit )
1144 rLeftClip = rRightClip = TRUE;
1149 // justify both rectangles for alignment calculation, use with DrawText etc.
1151 rAlignRect.Justify();
1152 rClipRect.Justify();
1154 #if 0
1155 //! Test !!!
1156 pDev->Push();
1157 pDev->SetLineColor();
1158 pDev->SetFillColor( COL_LIGHTGREEN );
1159 pDev->DrawRect( pDev->PixelToLogic(rClipRect) );
1160 pDev->DrawRect( rClipRect ); // print preview
1161 pDev->Pop();
1162 //! Test !!!
1163 #endif
1166 void ScOutputData::DrawStrings( BOOL bPixelToLogic )
1168 DBG_ASSERT( pDev == pRefDevice ||
1169 pDev->GetMapMode().GetMapUnit() == pRefDevice->GetMapMode().GetMapUnit(),
1170 "DrawStrings: unterschiedliche MapUnits ?!?!" );
1172 vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, pDev->GetExtOutDevData() );
1174 BOOL bWasIdleDisabled = pDoc->IsIdleDisabled();
1175 pDoc->DisableIdle( TRUE );
1176 Size aMinSize = pRefDevice->PixelToLogic(Size(0,100)); // erst darueber wird ausgegeben
1177 // UINT32 nMinHeight = aMinSize.Height() / 200; // 1/2 Pixel
1179 ScDrawStringsVars aVars( this, bPixelToLogic );
1181 const ScPatternAttr* pOldPattern = NULL;
1182 const SfxItemSet* pOldCondSet = NULL;
1183 BYTE nOldScript = 0;
1185 BOOL bProgress = FALSE;
1187 long nInitPosX = nScrX;
1188 if ( bLayoutRTL )
1189 nInitPosX += nMirrorW - 1; // pixels
1190 long nLayoutSign = bLayoutRTL ? -1 : 1;
1192 SCCOL nLastContentCol = MAXCOL;
1193 if ( nX2 < MAXCOL )
1194 nLastContentCol = sal::static_int_cast<SCCOL>(
1195 nLastContentCol - pDoc->GetEmptyLinesInBlock( nX2+1, nY1, nTab, MAXCOL, nY2, nTab, DIR_RIGHT ) );
1196 SCCOL nLoopStartX = nX1;
1197 if ( nX1 > 0 )
1198 --nLoopStartX; // start before nX1 for rest of long text to the left
1200 // variables for GetOutputArea
1201 BOOL bCellIsValue = FALSE;
1202 BOOL bLeftClip = FALSE;
1203 BOOL bRightClip = FALSE;
1204 long nNeededWidth = 0;
1205 Rectangle aAlignRect;
1206 Rectangle aClipRect;
1207 SvxCellHorJustify eOutHorJust = SVX_HOR_JUSTIFY_STANDARD;
1208 const ScPatternAttr* pPattern = NULL;
1209 const SfxItemSet* pCondSet = NULL;
1211 long nPosY = nScrY;
1212 for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
1214 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1215 if ( pThisRowInfo->bChanged )
1217 SCROW nY = pThisRowInfo->nRowNo;
1218 // long nCellHeight = (long) pThisRowInfo->nHeight;
1219 long nPosX = nInitPosX;
1220 if ( nLoopStartX < nX1 )
1221 nPosX -= pRowInfo[0].pCellInfo[nLoopStartX+1].nWidth * nLayoutSign;
1222 for (SCCOL nX=nLoopStartX; nX<=nX2; nX++)
1224 BOOL bMergeEmpty = FALSE;
1225 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
1226 BOOL bEmpty = nX < nX1 || pInfo->bEmptyCellText;
1228 SCCOL nCellX = nX; // position where the cell really starts
1229 SCROW nCellY = nY;
1230 BOOL bDoCell = FALSE;
1231 BOOL bNeedEdit = FALSE;
1234 // Part of a merged cell?
1237 BOOL bOverlapped = ( pInfo->bHOverlapped || pInfo->bVOverlapped );
1238 if ( bOverlapped )
1240 bEmpty = TRUE;
1242 SCCOL nOverX; // start of the merged cells
1243 SCROW nOverY;
1244 BOOL bVisChanged = !pRowInfo[nArrY-1].bChanged;
1245 if (GetMergeOrigin( nX,nY, nArrY, nOverX,nOverY, bVisChanged ))
1247 nCellX = nOverX;
1248 nCellY = nOverY;
1249 bDoCell = TRUE;
1251 else
1252 bMergeEmpty = TRUE;
1256 // Rest of a long text further to the left?
1259 if ( bEmpty && !bMergeEmpty && nX < nX1 && !bOverlapped )
1261 SCCOL nTempX=nX1;
1262 while (nTempX > 0 && IsEmptyCellText( pThisRowInfo, nTempX, nY ))
1263 --nTempX;
1265 if ( nTempX < nX1 &&
1266 !IsEmptyCellText( pThisRowInfo, nTempX, nY ) &&
1267 !pDoc->HasAttrib( nTempX,nY,nTab, nX1,nY,nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ) )
1269 nCellX = nTempX;
1270 bDoCell = TRUE;
1275 // Rest of a long text further to the right?
1278 if ( bEmpty && !bMergeEmpty && nX == nX2 && !bOverlapped )
1280 // don't have to look further than nLastContentCol
1282 SCCOL nTempX=nX;
1283 while (nTempX < nLastContentCol && IsEmptyCellText( pThisRowInfo, nTempX, nY ))
1284 ++nTempX;
1286 if ( nTempX > nX &&
1287 !IsEmptyCellText( pThisRowInfo, nTempX, nY ) &&
1288 !pDoc->HasAttrib( nTempX,nY,nTab, nX,nY,nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ) )
1290 nCellX = nTempX;
1291 bDoCell = TRUE;
1296 // normal visible cell
1299 if (!bEmpty)
1300 bDoCell = TRUE;
1303 // don't output the cell that's being edited
1306 if ( bDoCell && bEditMode && nCellX == nEditCol && nCellY == nEditRow )
1307 bDoCell = FALSE;
1310 // output the cell text
1313 ScBaseCell* pCell = NULL;
1314 if (bDoCell)
1316 if ( nCellY == nY && nCellX == nX && nCellX >= nX1 && nCellX <= nX2 )
1317 pCell = pThisRowInfo->pCellInfo[nCellX+1].pCell;
1318 else
1319 GetVisibleCell( nCellX, nCellY, nTab, pCell ); // get from document
1320 if ( !pCell )
1321 bDoCell = FALSE;
1322 else if ( pCell->GetCellType() == CELLTYPE_EDIT )
1323 bNeedEdit = TRUE;
1325 if (bDoCell && !bNeedEdit)
1327 if ( nCellY == nY && nCellX >= nX1 && nCellX <= nX2 )
1329 CellInfo& rCellInfo = pThisRowInfo->pCellInfo[nCellX+1];
1330 pPattern = rCellInfo.pPatternAttr;
1331 pCondSet = rCellInfo.pConditionSet;
1333 if ( !pPattern )
1335 // #i68085# pattern from cell info for hidden columns is null,
1336 // test for null is quicker than using column flags
1337 pPattern = pDoc->GetPattern( nCellX, nCellY, nTab );
1338 pCondSet = pDoc->GetCondResult( nCellX, nCellY, nTab );
1341 else // get from document
1343 pPattern = pDoc->GetPattern( nCellX, nCellY, nTab );
1344 pCondSet = pDoc->GetCondResult( nCellX, nCellY, nTab );
1347 BYTE nScript = GetScriptType( pDoc, pCell, pPattern, pCondSet );
1348 if (nScript == 0) nScript = ScGlobal::GetDefaultScriptType();
1349 if ( pPattern != pOldPattern || pCondSet != pOldCondSet ||
1350 nScript != nOldScript || bSyntaxMode )
1352 if ( StringDiffer(pOldPattern,pPattern) ||
1353 pCondSet != pOldCondSet || nScript != nOldScript || bSyntaxMode )
1354 aVars.SetPattern( pPattern, pCondSet, pCell, nScript );
1355 else
1356 aVars.SetPatternSimple( pPattern, pCondSet );
1357 pOldPattern = pPattern;
1358 pOldCondSet = pCondSet;
1359 nOldScript = nScript;
1362 // use edit engine for rotated, stacked or mixed-script text
1363 if ( aVars.GetOrient() == SVX_ORIENTATION_STACKED ||
1364 aVars.IsRotated() || IsAmbiguousScript(nScript) )
1365 bNeedEdit = TRUE;
1367 if (bDoCell && !bNeedEdit)
1369 BOOL bFormulaCell = (pCell->GetCellType() == CELLTYPE_FORMULA );
1370 if ( bFormulaCell )
1371 lcl_CreateInterpretProgress( bProgress, pDoc, (ScFormulaCell*)pCell );
1372 if ( aVars.SetText(pCell) )
1373 pOldPattern = NULL;
1374 bNeedEdit = aVars.HasEditCharacters() ||
1375 (bFormulaCell && ((ScFormulaCell*)pCell)->IsMultilineResult());
1377 if (bDoCell && !bNeedEdit)
1379 CellType eCellType = pCell->GetCellType();
1380 bCellIsValue = ( eCellType == CELLTYPE_VALUE );
1381 if ( eCellType == CELLTYPE_FORMULA )
1383 ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
1384 bCellIsValue = pFCell->IsRunning() || pFCell->IsValue();
1387 eOutHorJust = ( aVars.GetHorJust() != SVX_HOR_JUSTIFY_STANDARD ) ?
1388 aVars.GetHorJust() :
1389 ( bCellIsValue ? SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_LEFT );
1391 if ( eOutHorJust == SVX_HOR_JUSTIFY_BLOCK || eOutHorJust == SVX_HOR_JUSTIFY_REPEAT )
1392 eOutHorJust = SVX_HOR_JUSTIFY_LEFT; // repeat is not yet implemented
1394 BOOL bBreak = ( aVars.GetLineBreak() || aVars.GetHorJust() == SVX_HOR_JUSTIFY_BLOCK );
1395 BOOL bRepeat = aVars.IsRepeat() && !bBreak;
1396 BOOL bShrink = aVars.IsShrink() && !bBreak && !bRepeat;
1398 long nTotalMargin = (long) ( aVars.GetLeftTotal() * nPPTX ) +
1399 (long) ( aVars.GetMargin()->GetRightMargin() * nPPTX );
1400 nNeededWidth = aVars.GetTextSize().Width() + nTotalMargin;
1401 // GetOutputArea gives justfied rectangles
1402 GetOutputArea( nX, nArrY, nPosX, nPosY, nCellX, nCellY, nNeededWidth,
1403 *pPattern, sal::static_int_cast<USHORT>(eOutHorJust),
1404 bCellIsValue || bRepeat || bShrink, bBreak, FALSE,
1405 aAlignRect, aClipRect, bLeftClip, bRightClip );
1407 if ( bShrink )
1409 if ( aVars.GetOrient() != SVX_ORIENTATION_STANDARD )
1411 // Only horizontal scaling is handled here.
1412 // DrawEdit is used to vertically scale 90 deg rotated text.
1413 bNeedEdit = TRUE;
1415 else if ( bLeftClip || bRightClip ) // horizontal
1417 long nAvailable = aAlignRect.GetWidth() - nTotalMargin;
1418 long nScaleSize = aVars.GetTextSize().Width(); // without margin
1420 if ( nScaleSize > 0 ) // 0 if the text is empty (formulas, number formats)
1422 long nScale = ( nAvailable * 100 ) / nScaleSize;
1424 aVars.SetShrinkScale( nScale, nOldScript );
1425 long nNewSize = aVars.GetTextSize().Width();
1427 USHORT nShrinkAgain = 0;
1428 while ( nNewSize > nAvailable && nShrinkAgain < SC_SHRINKAGAIN_MAX )
1430 // If the text is still too large, reduce the scale again by 10%, until it fits,
1431 // at most 7 times (it's less than 50% of the calculated scale then).
1433 nScale = ( nScale * 9 ) / 10;
1434 aVars.SetShrinkScale( nScale, nOldScript );
1435 nNewSize = aVars.GetTextSize().Width();
1436 ++nShrinkAgain;
1438 // If even at half the size the font still isn't rendered smaller,
1439 // fall back to normal clipping (showing ### for numbers).
1440 if ( nNewSize <= nAvailable )
1441 bLeftClip = bRightClip = FALSE;
1443 pOldPattern = NULL;
1448 if ( bRepeat && !bLeftClip && !bRightClip )
1450 long nAvailable = aAlignRect.GetWidth() - nTotalMargin;
1451 long nRepeatSize = aVars.GetTextSize().Width(); // without margin
1452 // When formatting for the printer, the text sizes don't always add up.
1453 // Round down (too few repetitions) rather than exceeding the cell size then:
1454 if ( pFmtDevice != pRefDevice )
1455 ++nRepeatSize;
1456 if ( nRepeatSize > 0 )
1458 long nRepeatCount = nAvailable / nRepeatSize;
1459 if ( nRepeatCount > 1 )
1461 String aCellStr = aVars.GetString();
1462 String aRepeated = aCellStr;
1463 for ( long nRepeat = 1; nRepeat < nRepeatCount; nRepeat++ )
1464 aRepeated.Append( aCellStr );
1465 aVars.SetAutoText( aRepeated );
1470 // use edit engine if automatic line breaks are needed
1471 if ( bBreak )
1473 if ( aVars.GetOrient() == SVX_ORIENTATION_STANDARD )
1474 bNeedEdit = ( bLeftClip || bRightClip );
1475 else
1477 long nHeight = aVars.GetTextSize().Height() +
1478 (long)(aVars.GetMargin()->GetTopMargin()*nPPTY) +
1479 (long)(aVars.GetMargin()->GetBottomMargin()*nPPTY);
1480 bNeedEdit = ( nHeight > aClipRect.GetHeight() );
1484 if (bNeedEdit)
1486 // mark the cell in CellInfo to be drawn in DrawEdit:
1487 // Cells to the left are marked directly, cells to the
1488 // right are handled by the flag for nX2
1489 SCCOL nMarkX = ( nCellX <= nX2 ) ? nCellX : nX2;
1490 RowInfo* pMarkRowInfo = ( nCellY == nY ) ? pThisRowInfo : &pRowInfo[0];
1491 pMarkRowInfo->pCellInfo[nMarkX+1].bEditEngine = TRUE;
1492 bDoCell = FALSE; // don't draw here
1494 if ( bDoCell )
1496 if ( bCellIsValue && ( bLeftClip || bRightClip ) )
1498 aVars.SetHashText();
1499 nNeededWidth = aVars.GetTextSize().Width() +
1500 (long) ( aVars.GetLeftTotal() * nPPTX ) +
1501 (long) ( aVars.GetMargin()->GetRightMargin() * nPPTX );
1502 if ( nNeededWidth <= aClipRect.GetWidth() )
1503 bLeftClip = bRightClip = FALSE;
1505 // If the "###" replacement doesn't fit into the cells, no clip marks
1506 // are shown, as the "###" already denotes too little space.
1507 // The rectangles from the first GetOutputArea call remain valid.
1510 long nJustPosX = aAlignRect.Left(); // "justified" - effect of alignment will be added
1511 long nJustPosY = aAlignRect.Top();
1512 long nAvailWidth = aAlignRect.GetWidth();
1513 long nOutHeight = aAlignRect.GetHeight();
1515 BOOL bOutside = ( aClipRect.Right() < nScrX || aClipRect.Left() >= nScrX + nScrW );
1516 if ( aClipRect.Left() < nScrX )
1518 aClipRect.Left() = nScrX;
1519 bLeftClip = TRUE;
1521 if ( aClipRect.Right() > nScrX + nScrW )
1523 aClipRect.Right() = nScrX + nScrW; //! minus one?
1524 bRightClip = TRUE;
1527 BOOL bHClip = bLeftClip || bRightClip;
1528 BOOL bVClip = FALSE;
1530 if ( aClipRect.Top() < nScrY )
1532 aClipRect.Top() = nScrY;
1533 bVClip = TRUE;
1535 if ( aClipRect.Bottom() > nScrY + nScrH )
1537 aClipRect.Bottom() = nScrY + nScrH; //! minus one?
1538 bVClip = TRUE;
1542 // horizontalen Platz testen
1545 BOOL bRightAdjusted = FALSE; // to correct text width calculation later
1546 BOOL bNeedEditEngine = FALSE;
1547 if ( !bNeedEditEngine && !bOutside )
1549 switch (eOutHorJust)
1551 case SVX_HOR_JUSTIFY_LEFT:
1552 nJustPosX += (long) ( aVars.GetLeftTotal() * nPPTX );
1553 break;
1554 case SVX_HOR_JUSTIFY_RIGHT:
1555 nJustPosX += nAvailWidth - aVars.GetTextSize().Width() -
1556 (long) ( aVars.GetMargin()->GetRightMargin() * nPPTX );
1557 bRightAdjusted = TRUE;
1558 break;
1559 case SVX_HOR_JUSTIFY_CENTER:
1560 nJustPosX += ( nAvailWidth - aVars.GetTextSize().Width() +
1561 (long) ( aVars.GetLeftTotal() * nPPTX ) -
1562 (long) ( aVars.GetMargin()->GetRightMargin() * nPPTX ) ) / 2;
1563 break;
1564 default:
1566 // added to avoid warnings
1570 long nTestClipHeight = aVars.GetTextSize().Height();
1571 switch (aVars.GetVerJust())
1573 case SVX_VER_JUSTIFY_TOP:
1575 long nTop = (long)( aVars.GetMargin()->GetTopMargin() * nPPTY );
1576 nJustPosY += nTop;
1577 nTestClipHeight += nTop;
1579 break;
1580 case SVX_VER_JUSTIFY_BOTTOM:
1582 long nBot = (long)( aVars.GetMargin()->GetBottomMargin() * nPPTY );
1583 nJustPosY += nOutHeight - aVars.GetTextSize().Height() - nBot;
1584 nTestClipHeight += nBot;
1586 break;
1587 case SVX_VER_JUSTIFY_CENTER:
1589 long nTop = (long)( aVars.GetMargin()->GetTopMargin() * nPPTY );
1590 long nBot = (long)( aVars.GetMargin()->GetBottomMargin() * nPPTY );
1591 nJustPosY += ( nOutHeight + nTop -
1592 aVars.GetTextSize().Height() - nBot ) / 2;
1593 nTestClipHeight += Abs( nTop - nBot );
1595 break;
1596 default:
1598 // added to avoid warnings
1602 if ( nTestClipHeight > nOutHeight )
1604 // kein vertikales Clipping beim Drucken von Zellen mit
1605 // optimaler Hoehe, ausser bei Groesse in bedingter Formatierung
1606 if ( eType != OUTTYPE_PRINTER ||
1607 ( pDoc->GetRowFlags( nCellY, nTab ) & CR_MANUALSIZE ) ||
1608 ( aVars.HasCondHeight() ) )
1609 bVClip = TRUE;
1612 if ( bHClip || bVClip )
1614 // nur die betroffene Dimension clippen,
1615 // damit bei nicht-proportionalem Resize nicht alle
1616 // rechtsbuendigen Zahlen abgeschnitten werden:
1618 if (!bHClip)
1620 aClipRect.Left() = nScrX;
1621 aClipRect.Right() = nScrX+nScrW;
1623 if (!bVClip)
1625 aClipRect.Top() = nScrY;
1626 aClipRect.Bottom() = nScrY+nScrH;
1629 // aClipRect is not used after SetClipRegion/IntersectClipRegion,
1630 // so it can be modified here
1631 if (bPixelToLogic)
1632 aClipRect = pRefDevice->PixelToLogic( aClipRect );
1634 if (bMetaFile)
1636 pDev->Push();
1637 pDev->IntersectClipRegion( aClipRect );
1639 else
1640 pDev->SetClipRegion( Region( aClipRect ) );
1643 Point aURLStart( nJustPosX, nJustPosY ); // copy before modifying for orientation
1645 switch (aVars.GetOrient())
1647 case SVX_ORIENTATION_STANDARD:
1648 nJustPosY += aVars.GetAscent();
1649 break;
1650 case SVX_ORIENTATION_TOPBOTTOM:
1651 nJustPosX += aVars.GetTextSize().Width() - aVars.GetAscent();
1652 break;
1653 case SVX_ORIENTATION_BOTTOMTOP:
1654 nJustPosY += aVars.GetTextSize().Height();
1655 nJustPosX += aVars.GetAscent();
1656 break;
1657 default:
1659 // added to avoid warnings
1663 // When clipping, the visible part is now completely defined by the alignment,
1664 // there's no more special handling to show the right part of RTL text.
1666 Point aDrawTextPos( nJustPosX, nJustPosY );
1667 if ( bPixelToLogic )
1669 // undo text width adjustment in pixels
1670 if (bRightAdjusted)
1671 aDrawTextPos.X() += aVars.GetTextSize().Width();
1673 aDrawTextPos = pRefDevice->PixelToLogic( aDrawTextPos );
1675 // redo text width adjustment in logic units
1676 if (bRightAdjusted)
1677 aDrawTextPos.X() -= aVars.GetOriginalWidth();
1680 // in Metafiles immer DrawTextArray, damit die Positionen mit
1681 // aufgezeichnet werden (fuer nicht-proportionales Resize):
1683 String aString = aVars.GetString();
1684 if (bMetaFile || pFmtDevice != pDev || aZoomX != aZoomY)
1686 sal_Int32* pDX = new sal_Int32[aString.Len()];
1687 pFmtDevice->GetTextArray( aString, pDX );
1689 if ( !pRefDevice->GetConnectMetaFile() ||
1690 pRefDevice->GetOutDevType() == OUTDEV_PRINTER )
1692 double fMul = GetStretch();
1693 xub_StrLen nLen = aString.Len();
1694 for (xub_StrLen i=0; i<nLen; i++)
1695 pDX[i] = (long)(pDX[i] / fMul + 0.5);
1698 pDev->DrawTextArray( aDrawTextPos, aString, pDX );
1699 delete[] pDX;
1701 else
1702 pDev->DrawText( aDrawTextPos, aString );
1704 if ( bHClip || bVClip )
1706 if (bMetaFile)
1707 pDev->Pop();
1708 else
1709 pDev->SetClipRegion();
1712 // PDF: whole-cell hyperlink from formula?
1713 BOOL bHasURL = pPDFData && pCell && pCell->GetCellType() == CELLTYPE_FORMULA &&
1714 static_cast<ScFormulaCell*>(pCell)->IsHyperLinkCell();
1715 if ( bHasURL )
1717 Rectangle aURLRect( aURLStart, aVars.GetTextSize() );
1718 lcl_DoHyperlinkResult( pDev, aURLRect, pCell );
1722 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
1725 nPosY += pRowInfo[nArrY].nHeight;
1727 if ( bProgress )
1728 ScProgress::DeleteInterpretProgress();
1729 pDoc->DisableIdle( bWasIdleDisabled );
1732 // -------------------------------------------------------------------------------
1734 void lcl_ClearEdit( EditEngine& rEngine ) // Text und Attribute
1736 rEngine.SetUpdateMode( FALSE );
1738 rEngine.SetText(EMPTY_STRING);
1739 // keine Para-Attribute uebrigbehalten...
1740 const SfxItemSet& rPara = rEngine.GetParaAttribs(0);
1741 if (rPara.Count())
1742 rEngine.SetParaAttribs( 0,
1743 SfxItemSet( *rPara.GetPool(), rPara.GetRanges() ) );
1746 BOOL lcl_SafeIsValue( ScBaseCell* pCell )
1748 if (!pCell)
1749 return FALSE;
1751 BOOL bRet = FALSE;
1752 switch ( pCell->GetCellType() )
1754 case CELLTYPE_VALUE:
1755 bRet = TRUE;
1756 break;
1757 case CELLTYPE_FORMULA:
1759 ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
1760 if ( pFCell->IsRunning() || pFCell->IsValue() )
1761 bRet = TRUE;
1763 break;
1764 default:
1766 // added to avoid warnings
1769 return bRet;
1772 void lcl_ScaleFonts( EditEngine& rEngine, long nPercent )
1774 BOOL bUpdateMode = rEngine.GetUpdateMode();
1775 if ( bUpdateMode )
1776 rEngine.SetUpdateMode( FALSE );
1778 USHORT nParCount = rEngine.GetParagraphCount();
1779 for (USHORT nPar=0; nPar<nParCount; nPar++)
1781 SvUShorts aPortions;
1782 rEngine.GetPortions( nPar, aPortions );
1784 USHORT nPCount = aPortions.Count();
1785 USHORT nStart = 0;
1786 for ( USHORT nPos=0; nPos<nPCount; nPos++ )
1788 USHORT nEnd = aPortions.GetObject( nPos );
1789 ESelection aSel( nPar, nStart, nPar, nEnd );
1790 SfxItemSet aAttribs = rEngine.GetAttribs( aSel );
1792 long nWestern = static_cast<const SvxFontHeightItem&>(aAttribs.Get(EE_CHAR_FONTHEIGHT)).GetHeight();
1793 long nCJK = static_cast<const SvxFontHeightItem&>(aAttribs.Get(EE_CHAR_FONTHEIGHT_CJK)).GetHeight();
1794 long nCTL = static_cast<const SvxFontHeightItem&>(aAttribs.Get(EE_CHAR_FONTHEIGHT_CTL)).GetHeight();
1796 nWestern = ( nWestern * nPercent ) / 100;
1797 nCJK = ( nCJK * nPercent ) / 100;
1798 nCTL = ( nCTL * nPercent ) / 100;
1800 aAttribs.Put( SvxFontHeightItem( nWestern, 100, EE_CHAR_FONTHEIGHT ) );
1801 aAttribs.Put( SvxFontHeightItem( nCJK, 100, EE_CHAR_FONTHEIGHT_CJK ) );
1802 aAttribs.Put( SvxFontHeightItem( nCTL, 100, EE_CHAR_FONTHEIGHT_CTL ) );
1804 rEngine.QuickSetAttribs( aAttribs, aSel ); //! remove paragraph attributes from aAttribs?
1806 nStart = nEnd;
1810 if ( bUpdateMode )
1811 rEngine.SetUpdateMode( TRUE );
1814 long lcl_GetEditSize( EditEngine& rEngine, BOOL bWidth, BOOL bSwap, long nAttrRotate )
1816 if ( bSwap )
1817 bWidth = !bWidth;
1819 if ( nAttrRotate )
1821 long nRealWidth = (long) rEngine.CalcTextWidth();
1822 long nRealHeight = rEngine.GetTextHeight();
1824 // assuming standard mode, otherwise width isn't used
1826 double nRealOrient = nAttrRotate * F_PI18000; // 1/100th degrees
1827 double nAbsCos = fabs( cos( nRealOrient ) );
1828 double nAbsSin = fabs( sin( nRealOrient ) );
1829 if ( bWidth )
1830 return (long) ( nRealWidth * nAbsCos + nRealHeight * nAbsSin );
1831 else
1832 return (long) ( nRealHeight * nAbsCos + nRealWidth * nAbsSin );
1834 else if ( bWidth )
1835 return (long) rEngine.CalcTextWidth();
1836 else
1837 return rEngine.GetTextHeight();
1841 void ScOutputData::ShrinkEditEngine( EditEngine& rEngine, const Rectangle& rAlignRect,
1842 long nLeftM, long nTopM, long nRightM, long nBottomM,
1843 BOOL bWidth, USHORT nOrient, long nAttrRotate, BOOL bPixelToLogic,
1844 long& rEngineWidth, long& rEngineHeight, long& rNeededPixel, BOOL& rLeftClip, BOOL& rRightClip )
1846 if ( !bWidth )
1848 // vertical
1850 long nScaleSize = bPixelToLogic ?
1851 pRefDevice->LogicToPixel(Size(0,rEngineHeight)).Height() : rEngineHeight;
1853 // Don't scale if it fits already.
1854 // Allowing to extend into the margin, to avoid scaling at optimal height.
1855 if ( nScaleSize <= rAlignRect.GetHeight() )
1856 return;
1858 BOOL bSwap = ( nOrient == SVX_ORIENTATION_TOPBOTTOM || nOrient == SVX_ORIENTATION_BOTTOMTOP );
1859 long nAvailable = rAlignRect.GetHeight() - nTopM - nBottomM;
1860 long nScale = ( nAvailable * 100 ) / nScaleSize;
1862 lcl_ScaleFonts( rEngine, nScale );
1863 rEngineHeight = lcl_GetEditSize( rEngine, FALSE, bSwap, nAttrRotate );
1864 long nNewSize = bPixelToLogic ?
1865 pRefDevice->LogicToPixel(Size(0,rEngineHeight)).Height() : rEngineHeight;
1867 USHORT nShrinkAgain = 0;
1868 while ( nNewSize > nAvailable && nShrinkAgain < SC_SHRINKAGAIN_MAX )
1870 // further reduce, like in DrawStrings
1871 lcl_ScaleFonts( rEngine, 90 ); // reduce by 10%
1872 rEngineHeight = lcl_GetEditSize( rEngine, FALSE, bSwap, nAttrRotate );
1873 nNewSize = bPixelToLogic ?
1874 pRefDevice->LogicToPixel(Size(0,rEngineHeight)).Height() : rEngineHeight;
1875 ++nShrinkAgain;
1878 // sizes for further processing (alignment etc):
1879 rEngineWidth = lcl_GetEditSize( rEngine, TRUE, bSwap, nAttrRotate );
1880 long nPixelWidth = bPixelToLogic ?
1881 pRefDevice->LogicToPixel(Size(rEngineWidth,0)).Width() : rEngineWidth;
1882 rNeededPixel = nPixelWidth + nLeftM + nRightM;
1884 else if ( rLeftClip || rRightClip )
1886 // horizontal
1888 long nAvailable = rAlignRect.GetWidth() - nLeftM - nRightM;
1889 long nScaleSize = rNeededPixel - nLeftM - nRightM; // without margin
1891 if ( nScaleSize <= nAvailable )
1892 return;
1894 long nScale = ( nAvailable * 100 ) / nScaleSize;
1896 lcl_ScaleFonts( rEngine, nScale );
1897 rEngineWidth = lcl_GetEditSize( rEngine, TRUE, FALSE, nAttrRotate );
1898 long nNewSize = bPixelToLogic ?
1899 pRefDevice->LogicToPixel(Size(rEngineWidth,0)).Width() : rEngineWidth;
1901 USHORT nShrinkAgain = 0;
1902 while ( nNewSize > nAvailable && nShrinkAgain < SC_SHRINKAGAIN_MAX )
1904 // further reduce, like in DrawStrings
1905 lcl_ScaleFonts( rEngine, 90 ); // reduce by 10%
1906 rEngineWidth = lcl_GetEditSize( rEngine, TRUE, FALSE, nAttrRotate );
1907 nNewSize = bPixelToLogic ?
1908 pRefDevice->LogicToPixel(Size(rEngineWidth,0)).Width() : rEngineWidth;
1909 ++nShrinkAgain;
1911 if ( nNewSize <= nAvailable )
1912 rLeftClip = rRightClip = FALSE;
1914 // sizes for further processing (alignment etc):
1915 rNeededPixel = nNewSize + nLeftM + nRightM;
1916 rEngineHeight = lcl_GetEditSize( rEngine, FALSE, FALSE, nAttrRotate );
1920 void ScOutputData::DrawEdit(BOOL bPixelToLogic)
1922 vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, pDev->GetExtOutDevData() );
1924 Size aMinSize = pRefDevice->PixelToLogic(Size(0,100)); // erst darueber wird ausgegeben
1925 // UINT32 nMinHeight = aMinSize.Height() / 200; // 1/2 Pixel
1927 ScModule* pScMod = SC_MOD();
1928 sal_Int32 nConfBackColor = pScMod->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor;
1929 // #105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed TRUE)
1930 BOOL bCellContrast = bUseStyleColor &&
1931 Application::GetSettings().GetStyleSettings().GetHighContrastMode();
1933 ScFieldEditEngine* pEngine = NULL;
1934 BOOL bHyphenatorSet = FALSE;
1935 const ScPatternAttr* pOldPattern = NULL;
1936 const SfxItemSet* pOldCondSet = NULL;
1937 ScBaseCell* pCell = NULL;
1939 Size aRefOne = pRefDevice->PixelToLogic(Size(1,1));
1941 long nInitPosX = nScrX;
1942 if ( bLayoutRTL )
1944 #if 0
1945 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1946 long nOneX = aOnePixel.Width();
1947 nInitPosX += nMirrorW - nOneX;
1948 #endif
1949 nInitPosX += nMirrorW - 1;
1951 long nLayoutSign = bLayoutRTL ? -1 : 1;
1953 //! store nLastContentCol as member!
1954 SCCOL nLastContentCol = MAXCOL;
1955 if ( nX2 < MAXCOL )
1956 nLastContentCol = sal::static_int_cast<SCCOL>(
1957 nLastContentCol - pDoc->GetEmptyLinesInBlock( nX2+1, nY1, nTab, MAXCOL, nY2, nTab, DIR_RIGHT ) );
1959 long nRowPosY = nScrY;
1960 for (SCSIZE nArrY=0; nArrY+1<nArrCount; nArrY++) // 0 fuer Reste von zusammengefassten
1962 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1963 // long nCellHeight = (long) pThisRowInfo->nHeight;
1964 if (nArrY==1) nRowPosY = nScrY; // vorher wird einzeln berechnet
1966 if ( pThisRowInfo->bChanged || nArrY==0 )
1968 long nPosX = 0;
1969 for (SCCOL nX=0; nX<=nX2; nX++) // wegen Ueberhaengen
1971 if (nX==nX1) nPosX = nInitPosX; // positions before nX1 are calculated individually
1973 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
1974 if (pInfo->bEditEngine)
1976 SCROW nY = pThisRowInfo->nRowNo;
1978 SCCOL nCellX = nX; // position where the cell really starts
1979 SCROW nCellY = nY;
1980 BOOL bDoCell = FALSE;
1982 long nPosY = nRowPosY;
1983 if ( nArrY == 0 )
1985 nPosY = nScrY;
1986 nY = pRowInfo[1].nRowNo;
1987 SCCOL nOverX; // start of the merged cells
1988 SCROW nOverY;
1989 if (GetMergeOrigin( nX,nY, 1, nOverX,nOverY, TRUE ))
1991 nCellX = nOverX;
1992 nCellY = nOverY;
1993 bDoCell = TRUE;
1996 else if ( nX == nX2 && !pThisRowInfo->pCellInfo[nX+1].pCell )
1998 // Rest of a long text further to the right?
2000 SCCOL nTempX=nX;
2001 while (nTempX < nLastContentCol && IsEmptyCellText( pThisRowInfo, nTempX, nY ))
2002 ++nTempX;
2004 if ( nTempX > nX &&
2005 !IsEmptyCellText( pThisRowInfo, nTempX, nY ) &&
2006 !pDoc->HasAttrib( nTempX,nY,nTab, nX,nY,nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ) )
2008 nCellX = nTempX;
2009 bDoCell = TRUE;
2012 else
2014 bDoCell = TRUE;
2017 if ( bDoCell && bEditMode && nCellX == nEditCol && nCellY == nEditRow )
2018 bDoCell = FALSE;
2020 const ScPatternAttr* pPattern = NULL;
2021 const SfxItemSet* pCondSet = NULL;
2022 if (bDoCell)
2024 if ( nCellY == nY && nCellX >= nX1 && nCellX <= nX2 &&
2025 !pDoc->ColHidden(nCellX, nTab) )
2027 CellInfo& rCellInfo = pThisRowInfo->pCellInfo[nCellX+1];
2028 pPattern = rCellInfo.pPatternAttr;
2029 pCondSet = rCellInfo.pConditionSet;
2030 pCell = rCellInfo.pCell;
2032 else // get from document
2034 pPattern = pDoc->GetPattern( nCellX, nCellY, nTab );
2035 pCondSet = pDoc->GetCondResult( nCellX, nCellY, nTab );
2036 GetVisibleCell( nCellX, nCellY, nTab, pCell );
2038 if ( !pCell )
2039 bDoCell = FALSE;
2041 if (bDoCell)
2043 BOOL bHidden = FALSE;
2046 // Create EditEngine
2049 if (!pEngine)
2051 // Ein RefDevice muss auf jeden Fall gesetzt werden,
2052 // sonst legt sich die EditEngine ein VirtualDevice an!
2053 pEngine = new ScFieldEditEngine( pDoc->GetEnginePool() );
2054 pEngine->SetUpdateMode( FALSE );
2055 pEngine->SetRefDevice( pFmtDevice ); // always set
2056 ULONG nCtrl = pEngine->GetControlWord();
2057 if ( bShowSpellErrors )
2058 nCtrl |= EE_CNTRL_ONLINESPELLING;
2059 if ( eType == OUTTYPE_PRINTER )
2060 nCtrl &= ~EE_CNTRL_MARKFIELDS;
2061 pEngine->SetControlWord( nCtrl );
2062 pEngine->SetForbiddenCharsTable( pDoc->GetForbiddenCharacters() );
2063 pEngine->SetAsianCompressionMode( pDoc->GetAsianCompression() );
2064 pEngine->SetKernAsianPunctuation( pDoc->GetAsianKerning() );
2065 pEngine->EnableAutoColor( bUseStyleColor );
2066 pEngine->SetDefaultHorizontalTextDirection(
2067 (EEHorizontalTextDirection)pDoc->GetEditTextDirection( nTab ) );
2069 else
2070 lcl_ClearEdit( *pEngine ); // also calls SetUpdateMode(FALSE)
2073 BOOL bCellIsValue = lcl_SafeIsValue(pCell);
2075 SvxCellHorJustify eHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem&)
2076 pPattern->GetItem(ATTR_HOR_JUSTIFY, pCondSet)).GetValue();
2077 BOOL bBreak = ( eHorJust == SVX_HOR_JUSTIFY_BLOCK ) ||
2078 ((const SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK, pCondSet)).GetValue();
2079 BOOL bRepeat = ( eHorJust == SVX_HOR_JUSTIFY_REPEAT && !bBreak );
2080 BOOL bShrink = !bBreak && !bRepeat && static_cast<const SfxBoolItem&>
2081 (pPattern->GetItem( ATTR_SHRINKTOFIT, pCondSet )).GetValue();
2082 SvxCellOrientation eOrient = pPattern->GetCellOrientation( pCondSet );
2083 long nAttrRotate = ((const SfxInt32Item&)pPattern->
2084 GetItem(ATTR_ROTATE_VALUE, pCondSet)).GetValue();
2085 if ( eHorJust == SVX_HOR_JUSTIFY_REPEAT )
2087 // ignore orientation/rotation if "repeat" is active
2088 eOrient = SVX_ORIENTATION_STANDARD;
2089 nAttrRotate = 0;
2091 // #i31843# "repeat" with "line breaks" is treated as default alignment
2092 // (but rotation is still disabled)
2093 if ( bBreak )
2094 eHorJust = SVX_HOR_JUSTIFY_STANDARD;
2096 if ( eOrient==SVX_ORIENTATION_STANDARD && nAttrRotate )
2098 //! Flag setzen, um die Zelle in DrawRotated wiederzufinden ?
2099 //! (oder Flag schon bei DrawBackground, dann hier keine Abfrage)
2100 bHidden = TRUE; // gedreht wird getrennt ausgegeben
2103 BOOL bAsianVertical = ( eOrient == SVX_ORIENTATION_STACKED &&
2104 ((const SfxBoolItem&)pPattern->GetItem( ATTR_VERTICAL_ASIAN, pCondSet )).GetValue() );
2105 if ( bAsianVertical )
2107 // in asian mode, use EditEngine::SetVertical instead of EE_CNTRL_ONECHARPERLINE
2108 eOrient = SVX_ORIENTATION_STANDARD;
2109 // default alignment for asian vertical mode is top-right
2110 if ( eHorJust == SVX_HOR_JUSTIFY_STANDARD )
2111 eHorJust = SVX_HOR_JUSTIFY_RIGHT;
2116 SvxCellHorJustify eOutHorJust =
2117 ( eHorJust != SVX_HOR_JUSTIFY_STANDARD ) ? eHorJust :
2118 ( bCellIsValue ? SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_LEFT );
2120 if ( eOutHorJust == SVX_HOR_JUSTIFY_BLOCK || eOutHorJust == SVX_HOR_JUSTIFY_REPEAT )
2121 eOutHorJust = SVX_HOR_JUSTIFY_LEFT; // repeat is not yet implemented
2124 //! if ( !bHidden && eType == OUTTYPE_PRINTER &&
2125 //! pDev->GetOutDevType() == OUTDEV_WINDOW &&
2126 //! ((const SvxFontHeightItem&)pPattern->
2127 //! GetItem(ATTR_FONT_HEIGHT)).GetHeight() <= nMinHeight )
2128 //! {
2129 //! Point aPos( nStartX, nStartY );
2130 //! pDev->DrawPixel( aPos,
2131 //! ((const SvxColorItem&)pPattern->
2132 //! GetItem( ATTR_FONT_COLOR )).GetValue() );
2133 //! bHidden = TRUE;
2134 //! }
2136 if (!bHidden)
2138 //! mirror margin values for RTL?
2139 //! move margin down to after final GetOutputArea call
2141 const SvxMarginItem* pMargin = (const SvxMarginItem*)
2142 &pPattern->GetItem(ATTR_MARGIN, pCondSet);
2143 USHORT nIndent = 0;
2144 if ( eHorJust == SVX_HOR_JUSTIFY_LEFT )
2145 nIndent = ((const SfxUInt16Item&)pPattern->
2146 GetItem(ATTR_INDENT, pCondSet)).GetValue();
2148 long nLeftM = (long) ( (pMargin->GetLeftMargin() + nIndent) * nPPTX );
2149 long nTopM = (long) ( pMargin->GetTopMargin() * nPPTY );
2150 long nRightM = (long) ( pMargin->GetRightMargin() * nPPTX );
2151 long nBottomM = (long) ( pMargin->GetBottomMargin() * nPPTY );
2153 SCCOL nXForPos = nX;
2154 if ( nXForPos < nX1 )
2156 nXForPos = nX1;
2157 nPosX = nInitPosX;
2159 SCSIZE nArrYForPos = nArrY;
2160 if ( nArrYForPos < 1 )
2162 nArrYForPos = 1;
2163 nPosY = nScrY;
2166 Rectangle aAlignRect;
2167 Rectangle aClipRect;
2168 BOOL bLeftClip = FALSE;
2169 BOOL bRightClip = FALSE;
2172 // Initial page size - large for normal text, cell size for automatic line breaks
2175 Size aPaperSize = Size( 1000000, 1000000 );
2176 if ( bBreak || eOrient == SVX_ORIENTATION_STACKED || bAsianVertical )
2178 //! also stacked, AsianVertical
2180 // call GetOutputArea with nNeeded=0, to get only the cell width
2182 //! handle nArrY == 0
2183 GetOutputArea( nXForPos, nArrYForPos, nPosX, nPosY, nCellX, nCellY, 0,
2184 *pPattern, sal::static_int_cast<USHORT>(eOutHorJust),
2185 bCellIsValue, TRUE, FALSE,
2186 aAlignRect, aClipRect, bLeftClip, bRightClip );
2188 //! special ScEditUtil handling if formatting for printer
2190 if ( eOrient == SVX_ORIENTATION_TOPBOTTOM || eOrient == SVX_ORIENTATION_BOTTOMTOP )
2191 aPaperSize.Width() = aAlignRect.GetHeight() - nTopM - nBottomM;
2192 else
2193 aPaperSize.Width() = aAlignRect.GetWidth() - nLeftM - nRightM;
2195 if (bAsianVertical && bBreak)
2197 // add some extra height (default margin value) for safety
2198 // as long as GetEditArea isn't used below
2199 long nExtraHeight = (long)( 20 * nPPTY );
2200 aPaperSize.Height() = aAlignRect.GetHeight() - nTopM - nBottomM + nExtraHeight;
2203 if (bPixelToLogic)
2204 pEngine->SetPaperSize(pRefDevice->PixelToLogic(aPaperSize));
2205 else
2206 pEngine->SetPaperSize(aPaperSize);
2209 // Fill the EditEngine (cell attributes and text)
2212 SvxCellVerJustify eVerJust = (SvxCellVerJustify)((const SvxVerJustifyItem&)
2213 pPattern->GetItem(ATTR_VER_JUSTIFY, pCondSet)).GetValue();
2215 // default alignment for asian vertical mode is top-right
2216 if ( bAsianVertical && eVerJust == SVX_VER_JUSTIFY_STANDARD )
2217 eVerJust = SVX_VER_JUSTIFY_TOP;
2219 // syntax highlighting mode is ignored here
2220 // StringDiffer doesn't look at hyphenate, language items
2221 if ( pPattern != pOldPattern || pCondSet != pOldCondSet )
2223 SfxItemSet* pSet = new SfxItemSet( pEngine->GetEmptyItemSet() );
2224 pPattern->FillEditItemSet( pSet, pCondSet );
2226 pEngine->SetDefaults( pSet );
2227 pOldPattern = pPattern;
2228 pOldCondSet = pCondSet;
2230 ULONG nControl = pEngine->GetControlWord();
2231 if (eOrient==SVX_ORIENTATION_STACKED)
2232 nControl |= EE_CNTRL_ONECHARPERLINE;
2233 else
2234 nControl &= ~EE_CNTRL_ONECHARPERLINE;
2235 pEngine->SetControlWord( nControl );
2237 if ( !bHyphenatorSet && ((const SfxBoolItem&)pSet->Get(EE_PARA_HYPHENATE)).GetValue() )
2239 // set hyphenator the first time it is needed
2240 com::sun::star::uno::Reference<com::sun::star::linguistic2::XHyphenator> xXHyphenator( LinguMgr::GetHyphenator() );
2241 pEngine->SetHyphenator( xXHyphenator );
2242 bHyphenatorSet = TRUE;
2245 Color aBackCol = ((const SvxBrushItem&)
2246 pPattern->GetItem( ATTR_BACKGROUND, pCondSet )).GetColor();
2247 if ( bUseStyleColor && ( aBackCol.GetTransparency() > 0 || bCellContrast ) )
2248 aBackCol.SetColor( nConfBackColor );
2249 pEngine->SetBackgroundColor( aBackCol );
2252 // horizontal alignment now may depend on cell content
2253 // (for values with number formats with mixed script types)
2254 // -> always set adjustment
2256 SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT;
2257 if (eOrient==SVX_ORIENTATION_STACKED)
2258 eSvxAdjust = SVX_ADJUST_CENTER;
2259 else if (bBreak)
2261 if (eOrient==SVX_ORIENTATION_STANDARD && !bAsianVertical)
2262 switch (eHorJust)
2264 case SVX_HOR_JUSTIFY_STANDARD:
2265 eSvxAdjust = bCellIsValue ? SVX_ADJUST_RIGHT : SVX_ADJUST_LEFT;
2266 break;
2267 case SVX_HOR_JUSTIFY_LEFT:
2268 case SVX_HOR_JUSTIFY_REPEAT: // nicht implementiert
2269 eSvxAdjust = SVX_ADJUST_LEFT;
2270 break;
2271 case SVX_HOR_JUSTIFY_RIGHT:
2272 eSvxAdjust = SVX_ADJUST_RIGHT;
2273 break;
2274 case SVX_HOR_JUSTIFY_CENTER:
2275 eSvxAdjust = SVX_ADJUST_CENTER;
2276 break;
2277 case SVX_HOR_JUSTIFY_BLOCK:
2278 eSvxAdjust = SVX_ADJUST_BLOCK;
2279 break;
2281 else
2282 switch (eVerJust)
2284 case SVX_VER_JUSTIFY_TOP:
2285 eSvxAdjust = (eOrient==SVX_ORIENTATION_TOPBOTTOM || bAsianVertical) ?
2286 SVX_ADJUST_LEFT : SVX_ADJUST_RIGHT;
2287 break;
2288 case SVX_VER_JUSTIFY_CENTER:
2289 eSvxAdjust = SVX_ADJUST_CENTER;
2290 break;
2291 case SVX_VER_JUSTIFY_BOTTOM:
2292 case SVX_HOR_JUSTIFY_STANDARD:
2293 eSvxAdjust = (eOrient==SVX_ORIENTATION_TOPBOTTOM || bAsianVertical) ?
2294 SVX_ADJUST_RIGHT : SVX_ADJUST_LEFT;
2295 break;
2298 pEngine->SetDefaultItem( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) );
2300 // Read content from cell
2302 BOOL bWrapFields = FALSE;
2303 if (pCell)
2305 if (pCell->GetCellType() == CELLTYPE_EDIT)
2307 const EditTextObject* pData;
2308 ((ScEditCell*)pCell)->GetData(pData);
2310 if (pData)
2312 pEngine->SetText(*pData);
2314 if ( bBreak && !bAsianVertical && pData->HasField() )
2316 // Fields aren't wrapped, so clipping is enabled to prevent
2317 // a field from being drawn beyond the cell size
2319 bWrapFields = TRUE;
2322 else
2324 DBG_ERROR("pData == 0");
2327 else
2329 ULONG nFormat = pPattern->GetNumberFormat(
2330 pDoc->GetFormatTable(), pCondSet );
2331 String aString;
2332 Color* pColor;
2333 ScCellFormat::GetString( pCell,
2334 nFormat,aString, &pColor,
2335 *pDoc->GetFormatTable(),
2336 bShowNullValues,
2337 bShowFormulas,
2338 ftCheck );
2340 pEngine->SetText(aString);
2341 if ( pColor && !bSyntaxMode && !( bUseStyleColor && bForceAutoColor ) )
2342 lcl_SetEditColor( *pEngine, *pColor );
2345 if ( bSyntaxMode )
2346 SetEditSyntaxColor( *pEngine, pCell );
2347 else if ( bUseStyleColor && bForceAutoColor )
2348 lcl_SetEditColor( *pEngine, COL_AUTO ); //! or have a flag at EditEngine
2350 else
2352 DBG_ERROR("pCell == NULL");
2355 pEngine->SetVertical( bAsianVertical );
2356 pEngine->SetUpdateMode( TRUE ); // after SetText, before CalcTextWidth/GetTextHeight
2359 // Get final output area using the calculated width
2362 long nEngineWidth;
2363 if ( bBreak && eOrient != SVX_ORIENTATION_STACKED && !bAsianVertical )
2364 nEngineWidth = 0;
2365 else
2366 nEngineWidth = (long) pEngine->CalcTextWidth();
2367 long nEngineHeight = pEngine->GetTextHeight();
2369 if (eOrient != SVX_ORIENTATION_STANDARD &&
2370 eOrient != SVX_ORIENTATION_STACKED)
2372 long nTemp = nEngineWidth;
2373 nEngineWidth = nEngineHeight;
2374 nEngineHeight = nTemp;
2377 if (eOrient == SVX_ORIENTATION_STACKED)
2378 nEngineWidth = nEngineWidth * 11 / 10;
2380 long nNeededPixel = nEngineWidth;
2381 if (bPixelToLogic)
2382 nNeededPixel = pRefDevice->LogicToPixel(Size(nNeededPixel,0)).Width();
2383 nNeededPixel += nLeftM + nRightM;
2385 if ( ( !bBreak && eOrient != SVX_ORIENTATION_STACKED ) || bAsianVertical || bShrink )
2387 // for break, the first GetOutputArea call is sufficient
2388 GetOutputArea( nXForPos, nArrYForPos, nPosX, nPosY, nCellX, nCellY, nNeededPixel,
2389 *pPattern, sal::static_int_cast<USHORT>(eOutHorJust),
2390 bCellIsValue || bRepeat || bShrink, FALSE, FALSE,
2391 aAlignRect, aClipRect, bLeftClip, bRightClip );
2393 if ( bShrink )
2395 BOOL bWidth = ( eOrient == SVX_ORIENTATION_STANDARD && !bAsianVertical );
2396 ShrinkEditEngine( *pEngine, aAlignRect,
2397 nLeftM, nTopM, nRightM, nBottomM, bWidth,
2398 sal::static_int_cast<USHORT>(eOrient), 0, bPixelToLogic,
2399 nEngineWidth, nEngineHeight, nNeededPixel, bLeftClip, bRightClip );
2402 if ( bRepeat && !bLeftClip && !bRightClip && pEngine->GetParagraphCount() == 1 )
2404 // First check if twice the space for the formatted text is available
2405 // (otherwise just keep it unchanged).
2407 long nFormatted = nNeededPixel - nLeftM - nRightM; // without margin
2408 long nAvailable = aAlignRect.GetWidth() - nLeftM - nRightM;
2409 if ( nAvailable >= 2 * nFormatted )
2411 // "repeat" is handled with unformatted text (for performance reasons)
2412 String aCellStr = pEngine->GetText();
2413 pEngine->SetText( aCellStr );
2415 long nRepeatSize = (long) pEngine->CalcTextWidth();
2416 if (bPixelToLogic)
2417 nRepeatSize = pRefDevice->LogicToPixel(Size(nRepeatSize,0)).Width();
2418 if ( pFmtDevice != pRefDevice )
2419 ++nRepeatSize;
2420 if ( nRepeatSize > 0 )
2422 long nRepeatCount = nAvailable / nRepeatSize;
2423 if ( nRepeatCount > 1 )
2425 String aRepeated = aCellStr;
2426 for ( long nRepeat = 1; nRepeat < nRepeatCount; nRepeat++ )
2427 aRepeated.Append( aCellStr );
2428 pEngine->SetText( aRepeated );
2430 nEngineHeight = pEngine->GetTextHeight();
2431 nEngineWidth = (long) pEngine->CalcTextWidth();
2432 if (bPixelToLogic)
2433 nNeededPixel = pRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
2434 else
2435 nNeededPixel = nEngineWidth;
2436 nNeededPixel += nLeftM + nRightM;
2442 if ( bCellIsValue && ( bLeftClip || bRightClip ) )
2444 pEngine->SetText( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("###")) );
2445 nEngineWidth = (long) pEngine->CalcTextWidth();
2446 if (bPixelToLogic)
2447 nNeededPixel = pRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
2448 else
2449 nNeededPixel = nEngineWidth;
2450 nNeededPixel += nLeftM + nRightM;
2452 // No clip marks if "###" doesn't fit (same as in DrawStrings)
2455 if ( eOutHorJust != SVX_HOR_JUSTIFY_LEFT && eOrient == SVX_ORIENTATION_STANDARD )
2457 aPaperSize.Width() = nNeededPixel + 1;
2458 if (bPixelToLogic)
2459 pEngine->SetPaperSize(pRefDevice->PixelToLogic(aPaperSize));
2460 else
2461 pEngine->SetPaperSize(aPaperSize);
2465 long nStartX = aAlignRect.Left();
2466 long nStartY = aAlignRect.Top();
2467 long nCellWidth = aAlignRect.GetWidth();
2468 long nOutWidth = nCellWidth - 1 - nLeftM - nRightM;
2469 long nOutHeight = aAlignRect.GetHeight() - nTopM - nBottomM;
2471 if ( bBreak || eOrient != SVX_ORIENTATION_STANDARD || bAsianVertical )
2473 // text with automatic breaks is aligned only within the
2474 // edit engine's paper size, the output of the whole area
2475 // is always left-aligned
2477 nStartX += nLeftM;
2479 else
2481 if ( eOutHorJust == SVX_HOR_JUSTIFY_RIGHT )
2482 nStartX -= nNeededPixel - nCellWidth + nRightM + 1;
2483 else if ( eOutHorJust == SVX_HOR_JUSTIFY_CENTER )
2484 nStartX -= ( nNeededPixel - nCellWidth + nRightM + 1 - nLeftM ) / 2;
2485 else
2486 nStartX += nLeftM;
2489 BOOL bOutside = ( aClipRect.Right() < nScrX || aClipRect.Left() >= nScrX + nScrW );
2490 if ( aClipRect.Left() < nScrX )
2492 aClipRect.Left() = nScrX;
2493 bLeftClip = TRUE;
2495 if ( aClipRect.Right() > nScrX + nScrW )
2497 aClipRect.Right() = nScrX + nScrW; //! minus one?
2498 bRightClip = TRUE;
2501 if ( !bHidden && !bOutside )
2503 BOOL bClip = bLeftClip || bRightClip;
2504 BOOL bSimClip = FALSE;
2506 if ( bWrapFields )
2508 // Fields in a cell with automatic breaks: clip to cell width
2509 bClip = TRUE;
2512 if ( aClipRect.Top() < nScrY )
2514 aClipRect.Top() = nScrY;
2515 bClip = TRUE;
2517 if ( aClipRect.Bottom() > nScrY + nScrH )
2519 aClipRect.Bottom() = nScrY + nScrH; //! minus one?
2520 bClip = TRUE;
2523 Size aCellSize; // output area, excluding margins, in logical units
2524 if (bPixelToLogic)
2525 aCellSize = pRefDevice->PixelToLogic( Size( nOutWidth, nOutHeight ) );
2526 else
2527 aCellSize = Size( nOutWidth, nOutHeight );
2529 if ( nEngineHeight >= aCellSize.Height() + aRefOne.Height() )
2531 const ScMergeAttr* pMerge =
2532 (ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE);
2533 BOOL bMerged = pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1;
2535 // Don't clip for text height when printing rows with optimal height,
2536 // except when font size is from conditional formatting.
2537 //! Allow clipping when vertically merged?
2538 if ( eType != OUTTYPE_PRINTER ||
2539 ( pDoc->GetRowFlags( nCellY, nTab ) & CR_MANUALSIZE ) ||
2540 ( pCondSet && SFX_ITEM_SET ==
2541 pCondSet->GetItemState(ATTR_FONT_HEIGHT, TRUE) ) )
2542 bClip = TRUE;
2543 else
2544 bSimClip = TRUE;
2546 // Show clip marks if height is at least 5pt too small and
2547 // there are several lines of text.
2548 // Not for asian vertical text, because that would interfere
2549 // with the default right position of the text.
2550 // Only with automatic line breaks, to avoid having to find
2551 // the cells with the horizontal end of the text again.
2552 if ( nEngineHeight - aCellSize.Height() > 100 &&
2553 ( bBreak || eOrient == SVX_ORIENTATION_STACKED ) &&
2554 !bAsianVertical && bMarkClipped &&
2555 ( pEngine->GetParagraphCount() > 1 || pEngine->GetLineCount(0) > 1 ) )
2557 CellInfo* pClipMarkCell = NULL;
2558 if ( bMerged )
2560 // anywhere in the merged area...
2561 SCCOL nClipX = ( nX < nX1 ) ? nX1 : nX;
2562 pClipMarkCell = &pRowInfo[(nArrY != 0) ? nArrY : 1].pCellInfo[nClipX+1];
2564 else
2565 pClipMarkCell = &pThisRowInfo->pCellInfo[nX+1];
2567 pClipMarkCell->nClipMark |= SC_CLIPMARK_RIGHT; //! also allow left?
2568 bAnyClipped = TRUE;
2570 long nMarkPixel = (long)( SC_CLIPMARK_SIZE * nPPTX );
2571 if ( aClipRect.Right() - nMarkPixel > aClipRect.Left() )
2572 aClipRect.Right() -= nMarkPixel;
2576 #if 0
2577 long nClipStartY = nStartY;
2578 if (nArrY==0 || bVisChanged)
2580 if ( nClipStartY < nRowPosY )
2582 long nDif = nRowPosY - nClipStartY;
2583 bClip = TRUE;
2584 nClipStartY = nRowPosY;
2585 aClipSize.Height() -= nDif;
2588 #endif
2590 Rectangle aLogicClip;
2591 if (bClip || bSimClip)
2593 // Clip marks are already handled in GetOutputArea
2595 if (bPixelToLogic)
2596 aLogicClip = pRefDevice->PixelToLogic( aClipRect );
2597 else
2598 aLogicClip = aClipRect;
2600 if (bClip) // bei bSimClip nur aClipRect initialisieren
2602 if (bMetaFile)
2604 pDev->Push();
2605 pDev->IntersectClipRegion( aLogicClip );
2607 else
2608 pDev->SetClipRegion( Region( aLogicClip ) );
2612 Point aLogicStart;
2613 if (bPixelToLogic)
2614 aLogicStart = pRefDevice->PixelToLogic( Point(nStartX,nStartY) );
2615 else
2616 aLogicStart = Point(nStartX, nStartY);
2617 if ( eOrient!=SVX_ORIENTATION_STANDARD || bAsianVertical || !bBreak )
2619 long nAvailWidth = aCellSize.Width();
2620 // space for AutoFilter is already handled in GetOutputArea
2622 // horizontal alignment
2624 if (eOrient==SVX_ORIENTATION_STANDARD && !bAsianVertical)
2626 if (eHorJust==SVX_HOR_JUSTIFY_RIGHT ||
2627 eHorJust==SVX_HOR_JUSTIFY_CENTER ||
2628 (eHorJust==SVX_HOR_JUSTIFY_STANDARD && bCellIsValue) )
2630 pEngine->SetUpdateMode( FALSE );
2632 SvxAdjust eEditAdjust =
2633 (eHorJust==SVX_HOR_JUSTIFY_CENTER) ?
2634 SVX_ADJUST_CENTER : SVX_ADJUST_RIGHT;
2635 pEngine->SetDefaultItem(
2636 SvxAdjustItem( eEditAdjust, EE_PARA_JUST ) );
2638 // #55142# reset adjustment for the next cell
2639 pOldPattern = NULL;
2641 pEngine->SetUpdateMode( TRUE );
2644 else
2646 if (eHorJust==SVX_HOR_JUSTIFY_RIGHT)
2647 aLogicStart.X() += nAvailWidth - nEngineWidth;
2648 else if (eHorJust==SVX_HOR_JUSTIFY_CENTER)
2649 aLogicStart.X() += (nAvailWidth - nEngineWidth) / 2;
2653 if ( bAsianVertical )
2655 // paper size is subtracted below
2656 aLogicStart.X() += nEngineWidth;
2659 if ( ( bAsianVertical || eOrient == SVX_ORIENTATION_TOPBOTTOM ||
2660 eOrient == SVX_ORIENTATION_BOTTOMTOP ) && bBreak )
2662 // vertical adjustment is within the EditEngine
2663 if (bPixelToLogic)
2664 aLogicStart.Y() += pRefDevice->PixelToLogic(Size(0,nTopM)).Height();
2665 else
2666 aLogicStart.Y() += nTopM;
2669 if ( ( eOrient==SVX_ORIENTATION_STANDARD && !bAsianVertical ) ||
2670 eOrient==SVX_ORIENTATION_STACKED || !bBreak )
2672 if (eVerJust==SVX_VER_JUSTIFY_BOTTOM ||
2673 eVerJust==SVX_VER_JUSTIFY_STANDARD)
2675 //! if pRefDevice != pFmtDevice, keep heights in logic units,
2676 //! only converting margin?
2678 if (bPixelToLogic)
2679 aLogicStart.Y() += pRefDevice->PixelToLogic( Size(0, nTopM +
2680 pRefDevice->LogicToPixel(aCellSize).Height() -
2681 pRefDevice->LogicToPixel(Size(0,nEngineHeight)).Height()
2682 )).Height();
2683 else
2684 aLogicStart.Y() += nTopM + aCellSize.Height() - nEngineHeight;
2686 else if (eVerJust==SVX_VER_JUSTIFY_CENTER)
2688 if (bPixelToLogic)
2689 aLogicStart.Y() += pRefDevice->PixelToLogic( Size(0, nTopM + (
2690 pRefDevice->LogicToPixel(aCellSize).Height() -
2691 pRefDevice->LogicToPixel(Size(0,nEngineHeight)).Height() )
2692 / 2)).Height();
2693 else
2694 aLogicStart.Y() += nTopM + (aCellSize.Height() - nEngineHeight) / 2;
2696 else // top
2698 if (bPixelToLogic)
2699 aLogicStart.Y() += pRefDevice->PixelToLogic(Size(0,nTopM)).Height();
2700 else
2701 aLogicStart.Y() += nTopM;
2705 Point aURLStart = aLogicStart; // copy before modifying for orientation
2707 short nOriVal = 0;
2708 if (eOrient==SVX_ORIENTATION_TOPBOTTOM)
2710 // nOriVal = -900;
2711 nOriVal = 2700;
2712 aLogicStart.X() += nEngineWidth;
2714 else if (eOrient==SVX_ORIENTATION_BOTTOMTOP)
2716 nOriVal = 900;
2717 aLogicStart.Y() += bBreak ? pEngine->GetPaperSize().Width() :
2718 nEngineHeight;
2720 else if (eOrient==SVX_ORIENTATION_STACKED)
2722 Size aPaperLogic = pEngine->GetPaperSize();
2723 aPaperLogic.Width() = nEngineWidth;
2724 pEngine->SetPaperSize(aPaperLogic);
2727 if ( pEngine->IsRightToLeft( 0 ) )
2729 // For right-to-left, EditEngine always calculates its lines
2730 // beginning from the right edge, but EditLine::nStartPosX is
2731 // of USHORT type, so the PaperSize must be limited to USHRT_MAX.
2732 Size aLogicPaper = pEngine->GetPaperSize();
2733 if ( aLogicPaper.Width() > USHRT_MAX )
2735 aLogicPaper.Width() = USHRT_MAX;
2736 pEngine->SetPaperSize(aLogicPaper);
2740 // bMoveClipped handling has been replaced by complete alignment
2741 // handling (also extending to the left).
2743 if ( bSimClip && !nOriVal && !bAsianVertical )
2745 // kein hartes Clipping, aber nur die betroffenen
2746 // Zeilen ausgeben
2748 Point aDocStart = aLogicClip.TopLeft();
2749 aDocStart -= aLogicStart;
2750 pEngine->Draw( pDev, aLogicClip, aDocStart, FALSE );
2752 else
2754 if (bAsianVertical)
2756 // with SetVertical, the start position is top left of
2757 // the whole output area, not the text itself
2758 aLogicStart.X() -= pEngine->GetPaperSize().Width();
2760 pEngine->Draw( pDev, aLogicStart, nOriVal );
2763 if (bClip)
2765 if (bMetaFile)
2766 pDev->Pop();
2767 else
2768 pDev->SetClipRegion();
2771 // PDF: whole-cell hyperlink from formula?
2772 BOOL bHasURL = pPDFData && pCell && pCell->GetCellType() == CELLTYPE_FORMULA &&
2773 static_cast<ScFormulaCell*>(pCell)->IsHyperLinkCell();
2774 if ( bHasURL )
2776 long nURLWidth = (long) pEngine->CalcTextWidth();
2777 long nURLHeight = pEngine->GetTextHeight();
2778 if ( bBreak )
2780 Size aPaper = pEngine->GetPaperSize();
2781 if ( bAsianVertical )
2782 nURLHeight = aPaper.Height();
2783 else
2784 nURLWidth = aPaper.Width();
2786 if ( eOrient == SVX_ORIENTATION_TOPBOTTOM || eOrient == SVX_ORIENTATION_BOTTOMTOP )
2787 std::swap( nURLWidth, nURLHeight );
2788 else if ( bAsianVertical )
2789 aURLStart.X() -= nURLWidth;
2791 Rectangle aURLRect( aURLStart, Size( nURLWidth, nURLHeight ) );
2792 lcl_DoHyperlinkResult( pDev, aURLRect, pCell );
2798 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2801 nRowPosY += pRowInfo[nArrY].nHeight;
2804 delete pEngine;
2806 if (bAnyRotated)
2807 DrawRotated(bPixelToLogic); //! von aussen rufen ?
2810 // -------------------------------------------------------------------------------
2812 void ScOutputData::DrawRotated(BOOL bPixelToLogic)
2814 //! nRotMax speichern
2815 SCCOL nRotMax = nX2;
2816 for (SCSIZE nRotY=0; nRotY<nArrCount; nRotY++)
2817 if (pRowInfo[nRotY].nRotMaxCol != SC_ROTMAX_NONE && pRowInfo[nRotY].nRotMaxCol > nRotMax)
2818 nRotMax = pRowInfo[nRotY].nRotMaxCol;
2821 ScModule* pScMod = SC_MOD();
2822 sal_Int32 nConfBackColor = pScMod->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor;
2823 // #105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed TRUE)
2824 BOOL bCellContrast = bUseStyleColor &&
2825 Application::GetSettings().GetStyleSettings().GetHighContrastMode();
2827 ScFieldEditEngine* pEngine = NULL;
2828 BOOL bHyphenatorSet = FALSE;
2829 const ScPatternAttr* pPattern;
2830 const SfxItemSet* pCondSet;
2831 const ScPatternAttr* pOldPattern = NULL;
2832 const SfxItemSet* pOldCondSet = NULL;
2833 ScBaseCell* pCell = NULL;
2835 long nInitPosX = nScrX;
2836 if ( bLayoutRTL )
2838 #if 0
2839 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
2840 long nOneX = aOnePixel.Width();
2841 nInitPosX += nMirrorW - nOneX;
2842 #endif
2843 nInitPosX += nMirrorW - 1;
2845 long nLayoutSign = bLayoutRTL ? -1 : 1;
2847 long nRowPosY = nScrY;
2848 for (SCSIZE nArrY=0; nArrY+1<nArrCount; nArrY++) // 0 fuer Reste von zusammengefassten
2850 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
2851 long nCellHeight = (long) pThisRowInfo->nHeight;
2852 if (nArrY==1) nRowPosY = nScrY; // vorher wird einzeln berechnet
2854 if ( ( pThisRowInfo->bChanged || nArrY==0 ) && pThisRowInfo->nRotMaxCol != SC_ROTMAX_NONE )
2856 long nPosX = 0;
2857 for (SCCOL nX=0; nX<=nRotMax; nX++)
2859 if (nX==nX1) nPosX = nInitPosX; // positions before nX1 are calculated individually
2861 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
2862 if ( pInfo->nRotateDir != SC_ROTDIR_NONE )
2864 SCROW nY = pThisRowInfo->nRowNo;
2866 BOOL bHidden = FALSE;
2867 if (bEditMode)
2868 if ( nX == nEditCol && nY == nEditRow )
2869 bHidden = TRUE;
2871 if (!bHidden)
2873 if (!pEngine)
2875 // Ein RefDevice muss auf jeden Fall gesetzt werden,
2876 // sonst legt sich die EditEngine ein VirtualDevice an!
2877 pEngine = new ScFieldEditEngine( pDoc->GetEnginePool() );
2878 pEngine->SetUpdateMode( FALSE );
2879 pEngine->SetRefDevice( pFmtDevice ); // always set
2880 ULONG nCtrl = pEngine->GetControlWord();
2881 if ( bShowSpellErrors )
2882 nCtrl |= EE_CNTRL_ONLINESPELLING;
2883 if ( eType == OUTTYPE_PRINTER )
2884 nCtrl &= ~EE_CNTRL_MARKFIELDS;
2885 pEngine->SetControlWord( nCtrl );
2886 pEngine->SetForbiddenCharsTable( pDoc->GetForbiddenCharacters() );
2887 pEngine->SetAsianCompressionMode( pDoc->GetAsianCompression() );
2888 pEngine->SetKernAsianPunctuation( pDoc->GetAsianKerning() );
2889 pEngine->EnableAutoColor( bUseStyleColor );
2890 pEngine->SetDefaultHorizontalTextDirection(
2891 (EEHorizontalTextDirection)pDoc->GetEditTextDirection( nTab ) );
2893 else
2894 lcl_ClearEdit( *pEngine ); // also calls SetUpdateMode(FALSE)
2896 long nPosY = nRowPosY;
2897 BOOL bVisChanged = FALSE;
2899 //! Rest von zusammengefasster Zelle weiter oben funktioniert nicht!
2901 BOOL bFromDoc = FALSE;
2902 pPattern = pInfo->pPatternAttr;
2903 pCondSet = pInfo->pConditionSet;
2904 if (!pPattern)
2906 pPattern = pDoc->GetPattern( nX, nY, nTab );
2907 bFromDoc = TRUE;
2909 pCell = pInfo->pCell;
2910 if (bFromDoc)
2911 pCondSet = pDoc->GetCondResult( nX, nY, nTab );
2913 if (!pCell && nX>nX2)
2914 GetVisibleCell( nX, nY, nTab, pCell );
2916 if ( !pCell || IsEmptyCellText( pThisRowInfo, nX, nY ) )
2917 bHidden = TRUE; // nRotateDir is also set without a cell
2919 long nCellWidth = (long) pRowInfo[0].pCellInfo[nX+1].nWidth;
2921 SvxCellHorJustify eHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem&)
2922 pPattern->GetItem(ATTR_HOR_JUSTIFY, pCondSet)).GetValue();
2923 BOOL bBreak = ( eHorJust == SVX_HOR_JUSTIFY_BLOCK ) ||
2924 ((const SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK, pCondSet)).GetValue();
2925 BOOL bRepeat = ( eHorJust == SVX_HOR_JUSTIFY_REPEAT && !bBreak );
2926 BOOL bShrink = !bBreak && !bRepeat && static_cast<const SfxBoolItem&>
2927 (pPattern->GetItem( ATTR_SHRINKTOFIT, pCondSet )).GetValue();
2928 SvxCellOrientation eOrient = pPattern->GetCellOrientation( pCondSet );
2930 const ScMergeAttr* pMerge =
2931 (ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE);
2932 BOOL bMerged = pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1;
2934 long nStartX = nPosX;
2935 long nStartY = nPosY;
2936 if (nX<nX1)
2938 if ((bBreak || eOrient!=SVX_ORIENTATION_STANDARD) && !bMerged)
2939 bHidden = TRUE;
2940 else
2942 nStartX = nInitPosX;
2943 SCCOL nCol = nX1;
2944 while (nCol > nX)
2946 --nCol;
2947 nStartX -= nLayoutSign * (long) pRowInfo[0].pCellInfo[nCol+1].nWidth;
2951 long nCellStartX = nStartX;
2953 // Ersatzdarstellung fuer zu kleinen Text weggelassen
2955 if (!bHidden)
2957 long nOutWidth = nCellWidth - 1;
2958 long nOutHeight;
2959 if (pInfo)
2960 nOutHeight = nCellHeight;
2961 else
2962 nOutHeight = (long) ( pDoc->GetRowHeight(nY,nTab) * nPPTY );
2964 if ( bMerged ) // Zusammengefasst
2966 SCCOL nCountX = pMerge->GetColMerge();
2967 for (SCCOL i=1; i<nCountX; i++)
2968 nOutWidth += (long) ( pDoc->GetColWidth(nX+i,nTab) * nPPTX );
2969 SCROW nCountY = pMerge->GetRowMerge();
2970 nOutHeight += (long) pDoc->GetScaledRowHeight( nY+1, nY+nCountY-1, nTab, nPPTY);
2973 SvxCellVerJustify eVerJust = (SvxCellVerJustify)((const SvxVerJustifyItem&)
2974 pPattern->GetItem(ATTR_VER_JUSTIFY, pCondSet)).GetValue();
2976 // Syntax-Modus wird hier ignoriert...
2978 // StringDiffer doesn't look at hyphenate, language items
2979 if ( pPattern != pOldPattern || pCondSet != pOldCondSet )
2981 SfxItemSet* pSet = new SfxItemSet( pEngine->GetEmptyItemSet() );
2982 pPattern->FillEditItemSet( pSet, pCondSet );
2984 // Ausrichtung fuer EditEngine
2985 SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT;
2986 if (eOrient==SVX_ORIENTATION_STACKED)
2987 eSvxAdjust = SVX_ADJUST_CENTER;
2988 // Adjustment fuer bBreak ist hier weggelassen
2989 pSet->Put( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) );
2991 pEngine->SetDefaults( pSet );
2992 pOldPattern = pPattern;
2993 pOldCondSet = pCondSet;
2995 ULONG nControl = pEngine->GetControlWord();
2996 if (eOrient==SVX_ORIENTATION_STACKED)
2997 nControl |= EE_CNTRL_ONECHARPERLINE;
2998 else
2999 nControl &= ~EE_CNTRL_ONECHARPERLINE;
3000 pEngine->SetControlWord( nControl );
3002 if ( !bHyphenatorSet && ((const SfxBoolItem&)pSet->Get(EE_PARA_HYPHENATE)).GetValue() )
3004 // set hyphenator the first time it is needed
3005 com::sun::star::uno::Reference<com::sun::star::linguistic2::XHyphenator> xXHyphenator( LinguMgr::GetHyphenator() );
3006 pEngine->SetHyphenator( xXHyphenator );
3007 bHyphenatorSet = TRUE;
3010 Color aBackCol = ((const SvxBrushItem&)
3011 pPattern->GetItem( ATTR_BACKGROUND, pCondSet )).GetColor();
3012 if ( bUseStyleColor && ( aBackCol.GetTransparency() > 0 || bCellContrast ) )
3013 aBackCol.SetColor( nConfBackColor );
3014 pEngine->SetBackgroundColor( aBackCol );
3017 // Raender
3019 //! Position und Papersize auf EditUtil umstellen !!!
3021 const SvxMarginItem* pMargin = (const SvxMarginItem*)
3022 &pPattern->GetItem(ATTR_MARGIN, pCondSet);
3023 USHORT nIndent = 0;
3024 if ( eHorJust == SVX_HOR_JUSTIFY_LEFT )
3025 nIndent = ((const SfxUInt16Item&)pPattern->
3026 GetItem(ATTR_INDENT, pCondSet)).GetValue();
3028 long nTotalHeight = nOutHeight; // ohne Rand abzuziehen
3029 if ( bPixelToLogic )
3030 nTotalHeight = pRefDevice->PixelToLogic(Size(0,nTotalHeight)).Height();
3032 long nLeftM = (long) ( (pMargin->GetLeftMargin() + nIndent) * nPPTX );
3033 long nTopM = (long) ( pMargin->GetTopMargin() * nPPTY );
3034 long nRightM = (long) ( pMargin->GetRightMargin() * nPPTX );
3035 long nBottomM = (long) ( pMargin->GetBottomMargin() * nPPTY );
3036 nStartX += nLeftM;
3037 nStartY += nTopM;
3038 nOutWidth -= nLeftM + nRightM;
3039 nOutHeight -= nTopM + nBottomM;
3041 // Rotation schon hier, um bei Umbruch auch PaperSize anzupassen
3042 long nAttrRotate = 0;
3043 double nSin = 0.0;
3044 double nCos = 1.0;
3045 SvxRotateMode eRotMode = SVX_ROTATE_MODE_STANDARD;
3046 if ( eOrient == SVX_ORIENTATION_STANDARD )
3048 nAttrRotate = ((const SfxInt32Item&)pPattern->
3049 GetItem(ATTR_ROTATE_VALUE, pCondSet)).GetValue();
3050 if ( nAttrRotate )
3052 eRotMode = (SvxRotateMode)((const SvxRotateModeItem&)
3053 pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet)).GetValue();
3055 if ( nAttrRotate == 18000 )
3056 eRotMode = SVX_ROTATE_MODE_STANDARD; // keinen Ueberlauf
3058 if ( bLayoutRTL )
3059 nAttrRotate = -nAttrRotate;
3061 double nRealOrient = nAttrRotate * F_PI18000; // 1/100 Grad
3062 nCos = cos( nRealOrient );
3063 nSin = sin( nRealOrient );
3067 Size aPaperSize = Size( 1000000, 1000000 );
3068 if (eOrient==SVX_ORIENTATION_STACKED)
3069 aPaperSize.Width() = nOutWidth; // zum Zentrieren
3070 else if (bBreak)
3072 if (nAttrRotate)
3074 //! richtige PaperSize fuer Umbruch haengt von der Zeilenzahl
3075 //! ab, solange die Zeilen nicht einzeln versetzt ausgegeben
3076 //! werden koennen -> darum unbegrenzt, also kein Umbruch.
3077 //! Mit versetzten Zeilen waere das folgende richtig:
3078 aPaperSize.Width() = (long)(nOutHeight / fabs(nSin));
3080 else if (eOrient == SVX_ORIENTATION_STANDARD)
3081 aPaperSize.Width() = nOutWidth;
3082 else
3083 aPaperSize.Width() = nOutHeight - 1;
3085 if (bPixelToLogic)
3086 pEngine->SetPaperSize(pRefDevice->PixelToLogic(aPaperSize));
3087 else
3088 pEngine->SetPaperSize(aPaperSize); // Scale ist immer 1
3090 // Daten aus Zelle lesen
3092 if (pCell)
3094 if (pCell->GetCellType() == CELLTYPE_EDIT)
3096 const EditTextObject* pData;
3097 ((ScEditCell*)pCell)->GetData(pData);
3099 if (pData)
3100 pEngine->SetText(*pData);
3101 else
3103 DBG_ERROR("pData == 0");
3106 else
3108 ULONG nFormat = pPattern->GetNumberFormat(
3109 pDoc->GetFormatTable(), pCondSet );
3110 String aString;
3111 Color* pColor;
3112 ScCellFormat::GetString( pCell,
3113 nFormat,aString, &pColor,
3114 *pDoc->GetFormatTable(),
3115 bShowNullValues,
3116 bShowFormulas,
3117 ftCheck );
3119 pEngine->SetText(aString);
3120 if ( pColor && !bSyntaxMode && !( bUseStyleColor && bForceAutoColor ) )
3121 lcl_SetEditColor( *pEngine, *pColor );
3124 if ( bSyntaxMode )
3125 SetEditSyntaxColor( *pEngine, pCell );
3126 else if ( bUseStyleColor && bForceAutoColor )
3127 lcl_SetEditColor( *pEngine, COL_AUTO ); //! or have a flag at EditEngine
3129 else
3131 DBG_ERROR("pCell == NULL");
3134 pEngine->SetUpdateMode( TRUE ); // after SetText, before CalcTextWidth/GetTextHeight
3136 long nEngineWidth = (long) pEngine->CalcTextWidth();
3137 long nEngineHeight = pEngine->GetTextHeight();
3139 if (nAttrRotate && bBreak)
3141 double nAbsCos = fabs( nCos );
3142 double nAbsSin = fabs( nSin );
3144 // #47740# adjust witdh of papersize for height of text
3145 int nSteps = 5;
3146 while (nSteps > 0)
3148 // everything is in pixels
3149 long nEnginePixel = pRefDevice->LogicToPixel(
3150 Size(0,nEngineHeight)).Height();
3151 long nEffHeight = nOutHeight - (long)(nEnginePixel * nAbsCos) + 2;
3152 long nNewWidth = (long)(nEffHeight / nAbsSin) + 2;
3153 BOOL bFits = ( nNewWidth >= aPaperSize.Width() );
3154 if ( bFits )
3155 nSteps = 0;
3156 else
3158 if ( nNewWidth < 4 )
3160 // can't fit -> fall back to using half height
3161 nEffHeight = nOutHeight / 2;
3162 nNewWidth = (long)(nEffHeight / nAbsSin) + 2;
3163 nSteps = 0;
3165 else
3166 --nSteps;
3168 // set paper width and get new text height
3169 aPaperSize.Width() = nNewWidth;
3170 if (bPixelToLogic)
3171 pEngine->SetPaperSize(pRefDevice->PixelToLogic(aPaperSize));
3172 else
3173 pEngine->SetPaperSize(aPaperSize); // Scale ist immer 1
3174 //pEngine->QuickFormatDoc( TRUE );
3175 nEngineWidth = (long) pEngine->CalcTextWidth();
3176 nEngineHeight = pEngine->GetTextHeight();
3181 long nRealWidth = nEngineWidth;
3182 long nRealHeight = nEngineHeight;
3184 // wenn gedreht, Groesse anpassen
3185 if (nAttrRotate)
3187 double nAbsCos = fabs( nCos );
3188 double nAbsSin = fabs( nSin );
3190 if ( eRotMode == SVX_ROTATE_MODE_STANDARD )
3191 nEngineWidth = (long) ( nRealWidth * nAbsCos +
3192 nRealHeight * nAbsSin );
3193 else
3194 nEngineWidth = (long) ( nRealHeight / nAbsSin );
3195 //! begrenzen !!!
3197 nEngineHeight = (long) ( nRealHeight * nAbsCos +
3198 nRealWidth * nAbsSin );
3201 if (!nAttrRotate) // hier nur gedrehter Text
3202 bHidden = TRUE; //! vorher abfragen !!!
3204 //! weglassen, was nicht hereinragt
3206 if (!bHidden)
3208 BOOL bClip = FALSE;
3209 Size aClipSize = Size( nScrX+nScrW-nStartX, nScrY+nScrH-nStartY );
3211 // weiterschreiben
3213 Size aCellSize;
3214 if (bPixelToLogic)
3215 aCellSize = pRefDevice->PixelToLogic( Size( nOutWidth, nOutHeight ) );
3216 else
3217 aCellSize = Size( nOutWidth, nOutHeight ); // Scale ist 1
3219 long nGridWidth = nEngineWidth;
3220 BOOL bNegative = FALSE;
3221 if ( eRotMode != SVX_ROTATE_MODE_STANDARD )
3223 nGridWidth = aCellSize.Width() +
3224 Abs((long) ( aCellSize.Height() * nCos / nSin ));
3225 bNegative = ( pInfo->nRotateDir == SC_ROTDIR_LEFT );
3226 if ( bLayoutRTL )
3227 bNegative = !bNegative;
3230 // use GetOutputArea to hide the grid
3231 // (clip region is done manually below)
3232 BOOL bLeftClip = FALSE;
3233 BOOL bRightClip = FALSE;
3234 Rectangle aAlignRect;
3235 Rectangle aClipRect;
3237 SCCOL nCellX = nX;
3238 SCROW nCellY = nY;
3239 SvxCellHorJustify eOutHorJust = eHorJust;
3240 if ( eRotMode != SVX_ROTATE_MODE_STANDARD )
3241 eOutHorJust = bNegative ? SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_LEFT;
3242 long nNeededWidth = nGridWidth; // in pixel for GetOutputArea
3243 if ( bPixelToLogic )
3244 nNeededWidth = pRefDevice->LogicToPixel(Size(nNeededWidth,0)).Width();
3246 GetOutputArea( nX, nArrY, nCellStartX, nPosY, nCellX, nCellY, nNeededWidth,
3247 *pPattern, sal::static_int_cast<USHORT>(eOutHorJust),
3248 FALSE, FALSE, TRUE,
3249 aAlignRect, aClipRect, bLeftClip, bRightClip );
3251 if ( bShrink )
3253 long nPixelWidth = bPixelToLogic ?
3254 pRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width() : nEngineWidth;
3255 long nNeededPixel = nPixelWidth + nLeftM + nRightM;
3257 bLeftClip = bRightClip = TRUE;
3259 // always do height
3260 ShrinkEditEngine( *pEngine, aAlignRect, nLeftM, nTopM, nRightM, nBottomM,
3261 FALSE, sal::static_int_cast<USHORT>(eOrient), nAttrRotate, bPixelToLogic,
3262 nEngineWidth, nEngineHeight, nNeededPixel, bLeftClip, bRightClip );
3264 if ( eRotMode == SVX_ROTATE_MODE_STANDARD )
3266 // do width only if rotating within the cell (standard mode)
3267 ShrinkEditEngine( *pEngine, aAlignRect, nLeftM, nTopM, nRightM, nBottomM,
3268 TRUE, sal::static_int_cast<USHORT>(eOrient), nAttrRotate, bPixelToLogic,
3269 nEngineWidth, nEngineHeight, nNeededPixel, bLeftClip, bRightClip );
3272 // nEngineWidth/nEngineHeight is updated in ShrinkEditEngine
3273 // (but width is only valid for standard mode)
3274 nRealWidth = (long) pEngine->CalcTextWidth();
3275 nRealHeight = pEngine->GetTextHeight();
3277 if ( eRotMode != SVX_ROTATE_MODE_STANDARD )
3278 nEngineWidth = (long) ( nRealHeight / fabs( nSin ) );
3281 // BOOL bVClip = ( nEngineHeight > aCellSize.Height() );
3283 long nClipStartX = nStartX;
3284 if (nX<nX1)
3286 //! Clipping unnoetig, wenn links am Fenster
3288 bClip = TRUE; // nur Rest ausgeben!
3289 if (nStartX<nScrX)
3291 long nDif = nScrX - nStartX;
3292 nClipStartX = nScrX;
3293 aClipSize.Width() -= nDif;
3297 long nClipStartY = nStartY;
3298 if (nArrY==0 || bVisChanged)
3300 if ( nClipStartY < nRowPosY )
3302 long nDif = nRowPosY - nClipStartY;
3303 bClip = TRUE;
3304 nClipStartY = nRowPosY;
3305 aClipSize.Height() -= nDif;
3309 bClip = TRUE; // always clip at the window/page border
3311 //Rectangle aClipRect;
3312 if (bClip)
3314 if ( nAttrRotate /* && eRotMode != SVX_ROTATE_MODE_STANDARD */ )
3316 // gedrehten, ausgerichteten Text nur an den
3317 // Seitengrenzen clippen
3318 nClipStartX = nScrX;
3319 aClipSize.Width() = nScrW;
3322 if (bPixelToLogic)
3323 aClipRect = pRefDevice->PixelToLogic( Rectangle(
3324 Point(nClipStartX,nClipStartY), aClipSize ) );
3325 else
3326 aClipRect = Rectangle(Point(nClipStartX, nClipStartY),
3327 aClipSize ); // Scale = 1
3329 if (bMetaFile)
3331 pDev->Push();
3332 pDev->IntersectClipRegion( aClipRect );
3334 else
3335 pDev->SetClipRegion( Region( aClipRect ) );
3338 Point aLogicStart;
3339 if (bPixelToLogic)
3340 aLogicStart = pRefDevice->PixelToLogic( Point(nStartX,nStartY) );
3341 else
3342 aLogicStart = Point(nStartX, nStartY);
3343 if ( eOrient!=SVX_ORIENTATION_STANDARD || !bBreak )
3345 long nAvailWidth = aCellSize.Width();
3346 if (eType==OUTTYPE_WINDOW &&
3347 eOrient!=SVX_ORIENTATION_STACKED &&
3348 pInfo && pInfo->bAutoFilter)
3350 if (pRowInfo[nArrY].nHeight < DROPDOWN_BITMAP_SIZE)
3352 if (bPixelToLogic)
3353 nAvailWidth -= pRefDevice->PixelToLogic(Size(0,pRowInfo[nArrY].nHeight)).Height();
3354 else
3355 nAvailWidth -= pRowInfo[nArrY].nHeight;
3357 else
3359 if (bPixelToLogic)
3360 nAvailWidth -= pRefDevice->PixelToLogic(Size(0,DROPDOWN_BITMAP_SIZE)).Height();
3361 else
3362 nAvailWidth -= DROPDOWN_BITMAP_SIZE;
3364 long nComp = nEngineWidth;
3365 if (nAvailWidth<nComp) nAvailWidth=nComp;
3368 // horizontale Ausrichtung
3370 if (eOrient==SVX_ORIENTATION_STANDARD && !nAttrRotate)
3372 if (eHorJust==SVX_HOR_JUSTIFY_RIGHT ||
3373 eHorJust==SVX_HOR_JUSTIFY_CENTER)
3375 pEngine->SetUpdateMode( FALSE );
3377 SvxAdjust eSvxAdjust =
3378 (eHorJust==SVX_HOR_JUSTIFY_RIGHT) ?
3379 SVX_ADJUST_RIGHT : SVX_ADJUST_CENTER;
3380 pEngine->SetDefaultItem(
3381 SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) );
3383 aPaperSize.Width() = nOutWidth;
3384 if (bPixelToLogic)
3385 pEngine->SetPaperSize(pRefDevice->PixelToLogic(aPaperSize));
3386 else
3387 pEngine->SetPaperSize(aPaperSize);
3389 pEngine->SetUpdateMode( TRUE );
3392 else
3394 // bei gedrehtem Text ist Standard zentriert
3395 if (eHorJust==SVX_HOR_JUSTIFY_RIGHT)
3396 aLogicStart.X() += nAvailWidth - nEngineWidth;
3397 else if (eHorJust==SVX_HOR_JUSTIFY_CENTER ||
3398 eHorJust==SVX_HOR_JUSTIFY_STANDARD)
3399 aLogicStart.X() += (nAvailWidth - nEngineWidth) / 2;
3403 if ( bLayoutRTL )
3405 if (bPixelToLogic)
3406 aLogicStart.X() -= pRefDevice->PixelToLogic(
3407 Size( nCellWidth, 0 ) ).Width();
3408 else
3409 aLogicStart.X() -= nCellWidth;
3412 if ( eOrient==SVX_ORIENTATION_STANDARD ||
3413 eOrient==SVX_ORIENTATION_STACKED || !bBreak )
3415 if (eVerJust==SVX_VER_JUSTIFY_BOTTOM ||
3416 eVerJust==SVX_VER_JUSTIFY_STANDARD)
3418 if (bPixelToLogic)
3419 aLogicStart.Y() += pRefDevice->PixelToLogic( Size(0,
3420 pRefDevice->LogicToPixel(aCellSize).Height() -
3421 pRefDevice->LogicToPixel(Size(0,nEngineHeight)).Height()
3422 )).Height();
3423 else
3424 aLogicStart.Y() += aCellSize.Height() - nEngineHeight;
3427 else if (eVerJust==SVX_VER_JUSTIFY_CENTER)
3429 if (bPixelToLogic)
3430 aLogicStart.Y() += pRefDevice->PixelToLogic( Size(0,(
3431 pRefDevice->LogicToPixel(aCellSize).Height() -
3432 pRefDevice->LogicToPixel(Size(0,nEngineHeight)).Height())
3433 / 2)).Height();
3434 else
3435 aLogicStart.Y() += (aCellSize.Height() - nEngineHeight) / 2;
3439 // TOPBOTTON and BOTTOMTOP are handled in DrawStrings/DrawEdit
3440 DBG_ASSERT( eOrient == SVX_ORIENTATION_STANDARD && nAttrRotate,
3441 "DrawRotated: no rotation" );
3443 long nOriVal = 0;
3444 if ( nAttrRotate )
3446 // Attribut ist 1/100, Font 1/10 Grad
3447 nOriVal = nAttrRotate / 10;
3449 double nAddX = 0.0;
3450 double nAddY = 0.0;
3451 if ( nCos > 0.0 && eRotMode != SVX_ROTATE_MODE_STANDARD )
3453 //! begrenzen !!!
3454 double nH = nRealHeight * nCos;
3455 nAddX += nH * ( nCos / fabs(nSin) );
3457 if ( nCos < 0.0 && eRotMode == SVX_ROTATE_MODE_STANDARD )
3458 nAddX -= nRealWidth * nCos;
3459 if ( nSin < 0.0 )
3460 nAddX -= nRealHeight * nSin;
3461 if ( nSin > 0.0 )
3462 nAddY += nRealWidth * nSin;
3463 if ( nCos < 0.0 )
3464 nAddY -= nRealHeight * nCos;
3466 if ( eRotMode != SVX_ROTATE_MODE_STANDARD )
3468 //! begrenzen !!!
3469 double nSkew = nTotalHeight * nCos / fabs(nSin);
3470 if ( eRotMode == SVX_ROTATE_MODE_CENTER )
3471 nAddX -= nSkew * 0.5;
3472 if ( ( eRotMode == SVX_ROTATE_MODE_TOP && nSin > 0.0 ) ||
3473 ( eRotMode == SVX_ROTATE_MODE_BOTTOM && nSin < 0.0 ) )
3474 nAddX -= nSkew;
3476 long nUp = 0;
3477 if ( eVerJust == SVX_VER_JUSTIFY_CENTER )
3478 nUp = ( aCellSize.Height() - nEngineHeight ) / 2;
3479 else if ( eVerJust == SVX_VER_JUSTIFY_TOP )
3481 if ( nSin > 0.0 )
3482 nUp = aCellSize.Height() - nEngineHeight;
3484 else // BOTTOM / STANDARD
3486 if ( nSin < 0.0 )
3487 nUp = aCellSize.Height() - nEngineHeight;
3489 if ( nUp )
3490 nAddX += ( nUp * nCos / fabs(nSin) );
3493 aLogicStart.X() += (long) nAddX;
3494 aLogicStart.Y() += (long) nAddY;
3497 // bSimClip is not used here (because nOriVal is set)
3499 if ( pEngine->IsRightToLeft( 0 ) )
3501 // For right-to-left, EditEngine always calculates its lines
3502 // beginning from the right edge, but EditLine::nStartPosX is
3503 // of USHORT type, so the PaperSize must be limited to USHRT_MAX.
3504 Size aLogicPaper = pEngine->GetPaperSize();
3505 if ( aLogicPaper.Width() > USHRT_MAX )
3507 aLogicPaper.Width() = USHRT_MAX;
3508 pEngine->SetPaperSize(aLogicPaper);
3512 pEngine->Draw( pDev, aLogicStart, (short)nOriVal );
3514 if (bClip)
3516 if (bMetaFile)
3517 pDev->Pop();
3518 else
3519 pDev->SetClipRegion();
3525 nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
3528 nRowPosY += pRowInfo[nArrY].nHeight;
3531 delete pEngine;