1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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>
70 #include "document.hxx"
73 #include "patattr.hxx"
74 #include "cellform.hxx"
75 #include "editutil.hxx"
76 #include "progress.hxx"
78 #include "fillinfo.hxx"
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
103 long nAscentPixel
; // always pixels
104 SvxCellOrientation eAttrOrient
;
105 SvxCellHorJustify eAttrHorJust
;
106 SvxCellVerJustify eAttrVerJust
;
107 const SvxMarginItem
* pMargin
;
111 String aString
; // Inhalte
115 ScBaseCell
* pLastCell
;
124 Color aBackConfigColor
; // used for ScPatternAttr::GetFont calls
125 Color aTextConfigColor
;
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
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
) :
175 eAttrOrient ( SVX_ORIENTATION_STANDARD
),
176 eAttrHorJust( SVX_HOR_JUSTIFY_STANDARD
),
177 eAttrVerJust( SVX_VER_JUSTIFY_BOTTOM
),
184 bLineBreak ( 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
;
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();
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
)
251 // pPattern auswerten
253 OutputDevice
* pDev
= pOutput
->pDev
;
254 OutputDevice
* pRefDevice
= pOutput
->pRefDevice
;
255 OutputDevice
* pFmtDevice
= pOutput
->pFmtDevice
;
259 ScAutoFontColorMode eColorMode
;
260 if ( pOutput
->bUseStyleColor
)
262 if ( pOutput
->bForceAutoColor
)
263 eColorMode
= bCellContrast
? SC_AUTOCOL_IGNOREALL
: SC_AUTOCOL_IGNOREFONT
;
265 eColorMode
= bCellContrast
? SC_AUTOCOL_IGNOREBACK
: SC_AUTOCOL_DISPLAY
;
268 eColorMode
= SC_AUTOCOL_PRINT
;
271 pPattern
->GetFont( aFont
, eColorMode
, pFmtDevice
, NULL
, pCondSet
, nScript
,
272 &aBackConfigColor
, &aTextConfigColor
);
274 pPattern
->GetFont( aFont
, eColorMode
, pFmtDevice
, &pOutput
->aZoomY
, pCondSet
, nScript
,
275 &aBackConfigColor
, &aTextConfigColor
);
276 aFont
.SetAlign(ALIGN_BASELINE
);
280 eAttrOrient
= pPattern
->GetCellOrientation( pCondSet
);
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
;
292 bLineBreak
= ((const SfxBoolItem
&)pPattern
->GetItem( ATTR_LINEBREAK
, pCondSet
)).GetValue();
294 // handle "repeat" alignment
296 bRepeat
= ( eAttrHorJust
== SVX_HOR_JUSTIFY_REPEAT
);
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)
304 eAttrHorJust
= SVX_HOR_JUSTIFY_STANDARD
;
310 case SVX_ORIENTATION_STANDARD
:
312 bRotated
= (((const SfxInt32Item
&)pPattern
->GetItem( ATTR_ROTATE_VALUE
, pCondSet
)).GetValue() != 0) &&
315 case SVX_ORIENTATION_STACKED
:
319 case SVX_ORIENTATION_TOPBOTTOM
:
323 case SVX_ORIENTATION_BOTTOMTOP
:
328 DBG_ERROR("Falscher SvxCellOrientation Wert");
333 aFont
.SetOrientation( nRot
);
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();
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
);
372 // ULONG nOld = nValueFormat;
373 nValueFormat
= pPattern
->GetNumberFormat( pOutput
->pDoc
->GetFormatTable(), pCondSet
);
376 if (nValueFormat != nOld)
377 pLastCell = NULL; // immer neu formatieren
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();
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?
397 void ScDrawStringsVars::SetPatternSimple( const ScPatternAttr
* pNew
, const SfxItemSet
* pSet
)
399 // wird gerufen, wenn sich die Font-Variablen nicht aendern (!StringDiffer)
402 pCondSet
= pSet
; //! noetig ???
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
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();
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
;
448 if ( !SameValue( pCell
, pLastCell
) )
450 pLastCell
= pCell
; // Zelle merken
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
460 ScCellFormat::GetInputString( pCell
,
462 *pOutput
->pDoc
->GetFormatTable(),
465 ScCellFormat::GetString( pCell
,
466 nFormat
, aString
, &pColor
,
467 *pOutput
->pDoc
->GetFormatTable(),
468 pOutput
->bShowNullValues
,
469 pOutput
->bShowFormulas
,
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
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();
505 aTextSize
= pRefDevice
->LogicToPixel( aTextSize
);
507 // sonst String/Groesse behalten
513 aTextSize
= Size(0,0);
520 void ScDrawStringsVars::SetHashText()
522 SetAutoText( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("###")) );
525 void ScDrawStringsVars::SetAutoText( const String
& 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();
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.
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
);
587 // when formatting for printer, device map mode has already been taken care of
588 return ((double)aZoomY
) / ((double)aZoomX
);
592 //==================================================================
598 void lcl_DoHyperlinkResult( OutputDevice
* pDev
, const Rectangle
& rRect
, ScBaseCell
* pCell
)
600 vcl::PDFExtOutDevData
* pPDFData
= PTR_CAST( vcl::PDFExtOutDevData
, pDev
->GetExtOutDevData() );
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
)
625 switch (pCell
->GetCellType())
628 pFont
->SetColor( *pValueColor
);
630 case CELLTYPE_STRING
:
631 pFont
->SetColor( *pTextColor
);
633 case CELLTYPE_FORMULA
:
634 pFont
->SetColor( *pFormulaColor
);
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
)
658 switch (pCell
->GetCellType())
661 aColor
= *pValueColor
;
663 case CELLTYPE_STRING
:
664 aColor
= *pTextColor
;
666 case CELLTYPE_FORMULA
:
667 aColor
= *pFormulaColor
;
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
)
691 else if ( pInfo
->bVOverlapped
)
694 // weiter solange versteckt
701 BOOL bHOver
= pInfo
->bHOverlapped
;
702 BOOL bVOver
= pInfo
->bVOverlapped
;
705 while (bHOver
) // nY konstant
708 bHidden
= pDoc
->ColHidden(rOverX
, nTab
);
709 if ( !bDoMerge
&& !bHidden
)
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
;
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);
732 bHidden
= pDoc
->RowHidden(rOverY
, nTab
);
733 if ( !bDoMerge
&& !bHidden
)
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
;
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);
762 inline BOOL
StringDiffer( const ScPatternAttr
*& rpOldPattern
, const ScPatternAttr
*& rpNewPattern
)
764 DBG_ASSERT( rpNewPattern
, "pNewPattern" );
766 if ( rpNewPattern
== rpOldPattern
)
768 else if ( !rpOldPattern
)
770 else if ( &rpNewPattern
->GetItem( ATTR_FONT
) != &rpOldPattern
->GetItem( ATTR_FONT
) )
772 else if ( &rpNewPattern
->GetItem( ATTR_CJK_FONT
) != &rpOldPattern
->GetItem( ATTR_CJK_FONT
) )
774 else if ( &rpNewPattern
->GetItem( ATTR_CTL_FONT
) != &rpOldPattern
->GetItem( ATTR_CTL_FONT
) )
776 else if ( &rpNewPattern
->GetItem( ATTR_FONT_HEIGHT
) != &rpOldPattern
->GetItem( ATTR_FONT_HEIGHT
) )
778 else if ( &rpNewPattern
->GetItem( ATTR_CJK_FONT_HEIGHT
) != &rpOldPattern
->GetItem( ATTR_CJK_FONT_HEIGHT
) )
780 else if ( &rpNewPattern
->GetItem( ATTR_CTL_FONT_HEIGHT
) != &rpOldPattern
->GetItem( ATTR_CTL_FONT_HEIGHT
) )
782 else if ( &rpNewPattern
->GetItem( ATTR_FONT_WEIGHT
) != &rpOldPattern
->GetItem( ATTR_FONT_WEIGHT
) )
784 else if ( &rpNewPattern
->GetItem( ATTR_CJK_FONT_WEIGHT
) != &rpOldPattern
->GetItem( ATTR_CJK_FONT_WEIGHT
) )
786 else if ( &rpNewPattern
->GetItem( ATTR_CTL_FONT_WEIGHT
) != &rpOldPattern
->GetItem( ATTR_CTL_FONT_WEIGHT
) )
788 else if ( &rpNewPattern
->GetItem( ATTR_FONT_POSTURE
) != &rpOldPattern
->GetItem( ATTR_FONT_POSTURE
) )
790 else if ( &rpNewPattern
->GetItem( ATTR_CJK_FONT_POSTURE
) != &rpOldPattern
->GetItem( ATTR_CJK_FONT_POSTURE
) )
792 else if ( &rpNewPattern
->GetItem( ATTR_CTL_FONT_POSTURE
) != &rpOldPattern
->GetItem( ATTR_CTL_FONT_POSTURE
) )
794 else if ( &rpNewPattern
->GetItem( ATTR_FONT_UNDERLINE
) != &rpOldPattern
->GetItem( ATTR_FONT_UNDERLINE
) )
796 else if ( &rpNewPattern
->GetItem( ATTR_FONT_OVERLINE
) != &rpOldPattern
->GetItem( ATTR_FONT_OVERLINE
) )
798 else if ( &rpNewPattern
->GetItem( ATTR_FONT_WORDLINE
) != &rpOldPattern
->GetItem( ATTR_FONT_WORDLINE
) )
800 else if ( &rpNewPattern
->GetItem( ATTR_FONT_CROSSEDOUT
) != &rpOldPattern
->GetItem( ATTR_FONT_CROSSEDOUT
) )
802 else if ( &rpNewPattern
->GetItem( ATTR_FONT_CONTOUR
) != &rpOldPattern
->GetItem( ATTR_FONT_CONTOUR
) )
804 else if ( &rpNewPattern
->GetItem( ATTR_FONT_SHADOWED
) != &rpOldPattern
->GetItem( ATTR_FONT_SHADOWED
) )
806 else if ( &rpNewPattern
->GetItem( ATTR_FONT_COLOR
) != &rpOldPattern
->GetItem( ATTR_FONT_COLOR
) )
808 else if ( &rpNewPattern
->GetItem( ATTR_HOR_JUSTIFY
) != &rpOldPattern
->GetItem( ATTR_HOR_JUSTIFY
) )
810 else if ( &rpNewPattern
->GetItem( ATTR_VER_JUSTIFY
) != &rpOldPattern
->GetItem( ATTR_VER_JUSTIFY
) )
812 else if ( &rpNewPattern
->GetItem( ATTR_STACKED
) != &rpOldPattern
->GetItem( ATTR_STACKED
) )
814 else if ( &rpNewPattern
->GetItem( ATTR_LINEBREAK
) != &rpOldPattern
->GetItem( ATTR_LINEBREAK
) )
816 else if ( &rpNewPattern
->GetItem( ATTR_MARGIN
) != &rpOldPattern
->GetItem( ATTR_MARGIN
) )
818 else if ( &rpNewPattern
->GetItem( ATTR_ROTATE_VALUE
) != &rpOldPattern
->GetItem( ATTR_ROTATE_VALUE
) )
820 else if ( &rpNewPattern
->GetItem( ATTR_FORBIDDEN_RULES
) != &rpOldPattern
->GetItem( ATTR_FORBIDDEN_RULES
) )
822 else if ( &rpNewPattern
->GetItem( ATTR_FONT_EMPHASISMARK
) != &rpOldPattern
->GetItem( ATTR_FONT_EMPHASISMARK
) )
824 else if ( &rpNewPattern
->GetItem( ATTR_FONT_RELIEF
) != &rpOldPattern
->GetItem( ATTR_FONT_RELIEF
) )
826 else if ( &rpNewPattern
->GetItem( ATTR_BACKGROUND
) != &rpOldPattern
->GetItem( ATTR_BACKGROUND
) )
827 return TRUE
; // needed with automatic text color
830 rpOldPattern
= rpNewPattern
;
835 inline void lcl_CreateInterpretProgress( BOOL
& bProgress
, ScDocument
* pDoc
,
836 ScFormulaCell
* pFCell
)
838 if ( !bProgress
&& pFCell
->GetDirty() )
840 ScProgress::CreateInterpretProgress( pDoc
, 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
864 if ( pThisRowInfo
&& nX
<= nX2
)
865 bEmpty
= pThisRowInfo
->pCellInfo
[nX
+1].bEmptyCellText
;
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() )
882 else if ( bTabProtected
)
884 if ( pAttr
->GetHideCell() )
886 else if ( bShowFormulas
&& pAttr
->GetHideFormula() )
888 ScBaseCell
* pCell
= pDoc
->GetCell( ScAddress( nX
, nY
, nTab
) );
889 if ( pCell
&& pCell
->GetCellType() == CELLTYPE_FORMULA
)
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
) )
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
) )
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() )
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
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
;
965 while ( nCellX
< 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
;
983 nCompRow
= pRowInfo
[nCompArr
].nRowNo
;
987 USHORT nDocHeight
= pDoc
->GetRowHeight( nCompRow
, nTab
);
989 nCellPosY
+= (long) ( nDocHeight
* nPPTY
);
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 )
1000 long nMergeRows
= pMerge
->GetRowMerge();
1001 if ( nMergeRows
== 0 )
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;
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;
1050 case SVX_HOR_JUSTIFY_LEFT
:
1051 nRightMissing
= nMissing
;
1053 case SVX_HOR_JUSTIFY_RIGHT
:
1054 nLeftMissing
= nMissing
;
1056 case SVX_HOR_JUSTIFY_CENTER
:
1057 nLeftMissing
= nMissing
/ 2;
1058 nRightMissing
= nMissing
- nLeftMissing
;
1062 // added to avoid warnings
1066 // nLeftMissing, nRightMissing are logical, eHorJust values are visual
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
) ) )
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
;
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
;
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
;
1112 long nMarkPixel
= (long)( SC_CLIPMARK_SIZE
* nPPTX
);
1113 rClipRect
.Left() += nMarkPixel
* nLayoutSign
;
1116 rLeftClip
= ( nLeftMissing
> 0 );
1117 rRightClip
= ( nRightMissing
> 0 );
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)
1144 rLeftClip
= rRightClip
= TRUE
;
1149 // justify both rectangles for alignment calculation, use with DrawText etc.
1151 rAlignRect
.Justify();
1152 rClipRect
.Justify();
1157 pDev
->SetLineColor();
1158 pDev
->SetFillColor( COL_LIGHTGREEN
);
1159 pDev
->DrawRect( pDev
->PixelToLogic(rClipRect
) );
1160 pDev
->DrawRect( rClipRect
); // print preview
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
;
1189 nInitPosX
+= nMirrorW
- 1; // pixels
1190 long nLayoutSign
= bLayoutRTL
? -1 : 1;
1192 SCCOL nLastContentCol
= 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
;
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
;
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
1230 BOOL bDoCell
= FALSE
;
1231 BOOL bNeedEdit
= FALSE
;
1234 // Part of a merged cell?
1237 BOOL bOverlapped
= ( pInfo
->bHOverlapped
|| pInfo
->bVOverlapped
);
1242 SCCOL nOverX
; // start of the merged cells
1244 BOOL bVisChanged
= !pRowInfo
[nArrY
-1].bChanged
;
1245 if (GetMergeOrigin( nX
,nY
, nArrY
, nOverX
,nOverY
, bVisChanged
))
1256 // Rest of a long text further to the left?
1259 if ( bEmpty
&& !bMergeEmpty
&& nX
< nX1
&& !bOverlapped
)
1262 while (nTempX
> 0 && IsEmptyCellText( pThisRowInfo
, nTempX
, nY
))
1265 if ( nTempX
< nX1
&&
1266 !IsEmptyCellText( pThisRowInfo
, nTempX
, nY
) &&
1267 !pDoc
->HasAttrib( nTempX
,nY
,nTab
, nX1
,nY
,nTab
, HASATTR_MERGED
| HASATTR_OVERLAPPED
) )
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
1283 while (nTempX
< nLastContentCol
&& IsEmptyCellText( pThisRowInfo
, nTempX
, nY
))
1287 !IsEmptyCellText( pThisRowInfo
, nTempX
, nY
) &&
1288 !pDoc
->HasAttrib( nTempX
,nY
,nTab
, nX
,nY
,nTab
, HASATTR_MERGED
| HASATTR_OVERLAPPED
) )
1296 // normal visible cell
1303 // don't output the cell that's being edited
1306 if ( bDoCell
&& bEditMode
&& nCellX
== nEditCol
&& nCellY
== nEditRow
)
1310 // output the cell text
1313 ScBaseCell
* pCell
= NULL
;
1316 if ( nCellY
== nY
&& nCellX
== nX
&& nCellX
>= nX1
&& nCellX
<= nX2
)
1317 pCell
= pThisRowInfo
->pCellInfo
[nCellX
+1].pCell
;
1319 GetVisibleCell( nCellX
, nCellY
, nTab
, pCell
); // get from document
1322 else if ( pCell
->GetCellType() == CELLTYPE_EDIT
)
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
;
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
);
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
) )
1367 if (bDoCell
&& !bNeedEdit
)
1369 BOOL bFormulaCell
= (pCell
->GetCellType() == CELLTYPE_FORMULA
);
1371 lcl_CreateInterpretProgress( bProgress
, pDoc
, (ScFormulaCell
*)pCell
);
1372 if ( aVars
.SetText(pCell
) )
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
);
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.
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();
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
;
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
)
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
1473 if ( aVars
.GetOrient() == SVX_ORIENTATION_STANDARD
)
1474 bNeedEdit
= ( bLeftClip
|| bRightClip
);
1477 long nHeight
= aVars
.GetTextSize().Height() +
1478 (long)(aVars
.GetMargin()->GetTopMargin()*nPPTY
) +
1479 (long)(aVars
.GetMargin()->GetBottomMargin()*nPPTY
);
1480 bNeedEdit
= ( nHeight
> aClipRect
.GetHeight() );
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
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
;
1521 if ( aClipRect
.Right() > nScrX
+ nScrW
)
1523 aClipRect
.Right() = nScrX
+ nScrW
; //! minus one?
1527 BOOL bHClip
= bLeftClip
|| bRightClip
;
1528 BOOL bVClip
= FALSE
;
1530 if ( aClipRect
.Top() < nScrY
)
1532 aClipRect
.Top() = nScrY
;
1535 if ( aClipRect
.Bottom() > nScrY
+ nScrH
)
1537 aClipRect
.Bottom() = nScrY
+ nScrH
; //! minus one?
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
);
1554 case SVX_HOR_JUSTIFY_RIGHT
:
1555 nJustPosX
+= nAvailWidth
- aVars
.GetTextSize().Width() -
1556 (long) ( aVars
.GetMargin()->GetRightMargin() * nPPTX
);
1557 bRightAdjusted
= TRUE
;
1559 case SVX_HOR_JUSTIFY_CENTER
:
1560 nJustPosX
+= ( nAvailWidth
- aVars
.GetTextSize().Width() +
1561 (long) ( aVars
.GetLeftTotal() * nPPTX
) -
1562 (long) ( aVars
.GetMargin()->GetRightMargin() * nPPTX
) ) / 2;
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
);
1577 nTestClipHeight
+= nTop
;
1580 case SVX_VER_JUSTIFY_BOTTOM
:
1582 long nBot
= (long)( aVars
.GetMargin()->GetBottomMargin() * nPPTY
);
1583 nJustPosY
+= nOutHeight
- aVars
.GetTextSize().Height() - nBot
;
1584 nTestClipHeight
+= nBot
;
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
);
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() ) )
1612 if ( bHClip
|| bVClip
)
1614 // nur die betroffene Dimension clippen,
1615 // damit bei nicht-proportionalem Resize nicht alle
1616 // rechtsbuendigen Zahlen abgeschnitten werden:
1620 aClipRect
.Left() = nScrX
;
1621 aClipRect
.Right() = nScrX
+nScrW
;
1625 aClipRect
.Top() = nScrY
;
1626 aClipRect
.Bottom() = nScrY
+nScrH
;
1629 // aClipRect is not used after SetClipRegion/IntersectClipRegion,
1630 // so it can be modified here
1632 aClipRect
= pRefDevice
->PixelToLogic( aClipRect
);
1637 pDev
->IntersectClipRegion( aClipRect
);
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();
1650 case SVX_ORIENTATION_TOPBOTTOM
:
1651 nJustPosX
+= aVars
.GetTextSize().Width() - aVars
.GetAscent();
1653 case SVX_ORIENTATION_BOTTOMTOP
:
1654 nJustPosY
+= aVars
.GetTextSize().Height();
1655 nJustPosX
+= aVars
.GetAscent();
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
1671 aDrawTextPos
.X() += aVars
.GetTextSize().Width();
1673 aDrawTextPos
= pRefDevice
->PixelToLogic( aDrawTextPos
);
1675 // redo text width adjustment in logic units
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
);
1702 pDev
->DrawText( aDrawTextPos
, aString
);
1704 if ( bHClip
|| bVClip
)
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();
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
;
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);
1742 rEngine
.SetParaAttribs( 0,
1743 SfxItemSet( *rPara
.GetPool(), rPara
.GetRanges() ) );
1746 BOOL
lcl_SafeIsValue( ScBaseCell
* pCell
)
1752 switch ( pCell
->GetCellType() )
1754 case CELLTYPE_VALUE
:
1757 case CELLTYPE_FORMULA
:
1759 ScFormulaCell
* pFCell
= (ScFormulaCell
*)pCell
;
1760 if ( pFCell
->IsRunning() || pFCell
->IsValue() )
1766 // added to avoid warnings
1772 void lcl_ScaleFonts( EditEngine
& rEngine
, long nPercent
)
1774 BOOL bUpdateMode
= rEngine
.GetUpdateMode();
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();
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?
1811 rEngine
.SetUpdateMode( TRUE
);
1814 long lcl_GetEditSize( EditEngine
& rEngine
, BOOL bWidth
, BOOL bSwap
, long 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
) );
1830 return (long) ( nRealWidth
* nAbsCos
+ nRealHeight
* nAbsSin
);
1832 return (long) ( nRealHeight
* nAbsCos
+ nRealWidth
* nAbsSin
);
1835 return (long) rEngine
.CalcTextWidth();
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
)
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() )
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
;
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
)
1888 long nAvailable
= rAlignRect
.GetWidth() - nLeftM
- nRightM
;
1889 long nScaleSize
= rNeededPixel
- nLeftM
- nRightM
; // without margin
1891 if ( nScaleSize
<= nAvailable
)
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
;
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
;
1945 Size aOnePixel
= pDev
->PixelToLogic(Size(1,1));
1946 long nOneX
= aOnePixel
.Width();
1947 nInitPosX
+= nMirrorW
- nOneX
;
1949 nInitPosX
+= nMirrorW
- 1;
1951 long nLayoutSign
= bLayoutRTL
? -1 : 1;
1953 //! store nLastContentCol as member!
1954 SCCOL nLastContentCol
= 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 )
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
1980 BOOL bDoCell
= FALSE
;
1982 long nPosY
= nRowPosY
;
1986 nY
= pRowInfo
[1].nRowNo
;
1987 SCCOL nOverX
; // start of the merged cells
1989 if (GetMergeOrigin( nX
,nY
, 1, nOverX
,nOverY
, TRUE
))
1996 else if ( nX
== nX2
&& !pThisRowInfo
->pCellInfo
[nX
+1].pCell
)
1998 // Rest of a long text further to the right?
2001 while (nTempX
< nLastContentCol
&& IsEmptyCellText( pThisRowInfo
, nTempX
, nY
))
2005 !IsEmptyCellText( pThisRowInfo
, nTempX
, nY
) &&
2006 !pDoc
->HasAttrib( nTempX
,nY
,nTab
, nX
,nY
,nTab
, HASATTR_MERGED
| HASATTR_OVERLAPPED
) )
2017 if ( bDoCell
&& bEditMode
&& nCellX
== nEditCol
&& nCellY
== nEditRow
)
2020 const ScPatternAttr
* pPattern
= NULL
;
2021 const SfxItemSet
* pCondSet
= NULL
;
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
);
2043 BOOL bHidden
= FALSE
;
2046 // Create EditEngine
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
) );
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
;
2091 // #i31843# "repeat" with "line breaks" is treated as default alignment
2092 // (but rotation is still disabled)
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 )
2129 //! Point aPos( nStartX, nStartY );
2130 //! pDev->DrawPixel( aPos,
2131 //! ((const SvxColorItem&)pPattern->
2132 //! GetItem( ATTR_FONT_COLOR )).GetValue() );
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
);
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
)
2159 SCSIZE nArrYForPos
= nArrY
;
2160 if ( nArrYForPos
< 1 )
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
;
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
;
2204 pEngine
->SetPaperSize(pRefDevice
->PixelToLogic(aPaperSize
));
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
;
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
;
2261 if (eOrient
==SVX_ORIENTATION_STANDARD
&& !bAsianVertical
)
2264 case SVX_HOR_JUSTIFY_STANDARD
:
2265 eSvxAdjust
= bCellIsValue
? SVX_ADJUST_RIGHT
: SVX_ADJUST_LEFT
;
2267 case SVX_HOR_JUSTIFY_LEFT
:
2268 case SVX_HOR_JUSTIFY_REPEAT
: // nicht implementiert
2269 eSvxAdjust
= SVX_ADJUST_LEFT
;
2271 case SVX_HOR_JUSTIFY_RIGHT
:
2272 eSvxAdjust
= SVX_ADJUST_RIGHT
;
2274 case SVX_HOR_JUSTIFY_CENTER
:
2275 eSvxAdjust
= SVX_ADJUST_CENTER
;
2277 case SVX_HOR_JUSTIFY_BLOCK
:
2278 eSvxAdjust
= SVX_ADJUST_BLOCK
;
2284 case SVX_VER_JUSTIFY_TOP
:
2285 eSvxAdjust
= (eOrient
==SVX_ORIENTATION_TOPBOTTOM
|| bAsianVertical
) ?
2286 SVX_ADJUST_LEFT
: SVX_ADJUST_RIGHT
;
2288 case SVX_VER_JUSTIFY_CENTER
:
2289 eSvxAdjust
= SVX_ADJUST_CENTER
;
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
;
2298 pEngine
->SetDefaultItem( SvxAdjustItem( eSvxAdjust
, EE_PARA_JUST
) );
2300 // Read content from cell
2302 BOOL bWrapFields
= FALSE
;
2305 if (pCell
->GetCellType() == CELLTYPE_EDIT
)
2307 const EditTextObject
* pData
;
2308 ((ScEditCell
*)pCell
)->GetData(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
2324 DBG_ERROR("pData == 0");
2329 ULONG nFormat
= pPattern
->GetNumberFormat(
2330 pDoc
->GetFormatTable(), pCondSet
);
2333 ScCellFormat::GetString( pCell
,
2334 nFormat
,aString
, &pColor
,
2335 *pDoc
->GetFormatTable(),
2340 pEngine
->SetText(aString
);
2341 if ( pColor
&& !bSyntaxMode
&& !( bUseStyleColor
&& bForceAutoColor
) )
2342 lcl_SetEditColor( *pEngine
, *pColor
);
2346 SetEditSyntaxColor( *pEngine
, pCell
);
2347 else if ( bUseStyleColor
&& bForceAutoColor
)
2348 lcl_SetEditColor( *pEngine
, COL_AUTO
); //! or have a flag at EditEngine
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
2363 if ( bBreak
&& eOrient
!= SVX_ORIENTATION_STACKED
&& !bAsianVertical
)
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
;
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
);
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();
2417 nRepeatSize
= pRefDevice
->LogicToPixel(Size(nRepeatSize
,0)).Width();
2418 if ( pFmtDevice
!= pRefDevice
)
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();
2433 nNeededPixel
= pRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
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();
2447 nNeededPixel
= pRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
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;
2459 pEngine
->SetPaperSize(pRefDevice
->PixelToLogic(aPaperSize
));
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
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;
2489 BOOL bOutside
= ( aClipRect
.Right() < nScrX
|| aClipRect
.Left() >= nScrX
+ nScrW
);
2490 if ( aClipRect
.Left() < nScrX
)
2492 aClipRect
.Left() = nScrX
;
2495 if ( aClipRect
.Right() > nScrX
+ nScrW
)
2497 aClipRect
.Right() = nScrX
+ nScrW
; //! minus one?
2501 if ( !bHidden
&& !bOutside
)
2503 BOOL bClip
= bLeftClip
|| bRightClip
;
2504 BOOL bSimClip
= FALSE
;
2508 // Fields in a cell with automatic breaks: clip to cell width
2512 if ( aClipRect
.Top() < nScrY
)
2514 aClipRect
.Top() = nScrY
;
2517 if ( aClipRect
.Bottom() > nScrY
+ nScrH
)
2519 aClipRect
.Bottom() = nScrY
+ nScrH
; //! minus one?
2523 Size aCellSize
; // output area, excluding margins, in logical units
2525 aCellSize
= pRefDevice
->PixelToLogic( Size( nOutWidth
, nOutHeight
) );
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
) ) )
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
;
2560 // anywhere in the merged area...
2561 SCCOL nClipX
= ( nX
< nX1
) ? nX1
: nX
;
2562 pClipMarkCell
= &pRowInfo
[(nArrY
!= 0) ? nArrY
: 1].pCellInfo
[nClipX
+1];
2565 pClipMarkCell
= &pThisRowInfo
->pCellInfo
[nX
+1];
2567 pClipMarkCell
->nClipMark
|= SC_CLIPMARK_RIGHT
; //! also allow left?
2570 long nMarkPixel
= (long)( SC_CLIPMARK_SIZE
* nPPTX
);
2571 if ( aClipRect
.Right() - nMarkPixel
> aClipRect
.Left() )
2572 aClipRect
.Right() -= nMarkPixel
;
2577 long nClipStartY
= nStartY
;
2578 if (nArrY
==0 || bVisChanged
)
2580 if ( nClipStartY
< nRowPosY
)
2582 long nDif
= nRowPosY
- nClipStartY
;
2584 nClipStartY
= nRowPosY
;
2585 aClipSize
.Height() -= nDif
;
2590 Rectangle aLogicClip
;
2591 if (bClip
|| bSimClip
)
2593 // Clip marks are already handled in GetOutputArea
2596 aLogicClip
= pRefDevice
->PixelToLogic( aClipRect
);
2598 aLogicClip
= aClipRect
;
2600 if (bClip
) // bei bSimClip nur aClipRect initialisieren
2605 pDev
->IntersectClipRegion( aLogicClip
);
2608 pDev
->SetClipRegion( Region( aLogicClip
) );
2614 aLogicStart
= pRefDevice
->PixelToLogic( Point(nStartX
,nStartY
) );
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
2641 pEngine
->SetUpdateMode( TRUE
);
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
2664 aLogicStart
.Y() += pRefDevice
->PixelToLogic(Size(0,nTopM
)).Height();
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?
2679 aLogicStart
.Y() += pRefDevice
->PixelToLogic( Size(0, nTopM
+
2680 pRefDevice
->LogicToPixel(aCellSize
).Height() -
2681 pRefDevice
->LogicToPixel(Size(0,nEngineHeight
)).Height()
2684 aLogicStart
.Y() += nTopM
+ aCellSize
.Height() - nEngineHeight
;
2686 else if (eVerJust
==SVX_VER_JUSTIFY_CENTER
)
2689 aLogicStart
.Y() += pRefDevice
->PixelToLogic( Size(0, nTopM
+ (
2690 pRefDevice
->LogicToPixel(aCellSize
).Height() -
2691 pRefDevice
->LogicToPixel(Size(0,nEngineHeight
)).Height() )
2694 aLogicStart
.Y() += nTopM
+ (aCellSize
.Height() - nEngineHeight
) / 2;
2699 aLogicStart
.Y() += pRefDevice
->PixelToLogic(Size(0,nTopM
)).Height();
2701 aLogicStart
.Y() += nTopM
;
2705 Point aURLStart
= aLogicStart
; // copy before modifying for orientation
2708 if (eOrient
==SVX_ORIENTATION_TOPBOTTOM
)
2712 aLogicStart
.X() += nEngineWidth
;
2714 else if (eOrient
==SVX_ORIENTATION_BOTTOMTOP
)
2717 aLogicStart
.Y() += bBreak
? pEngine
->GetPaperSize().Width() :
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
2748 Point aDocStart
= aLogicClip
.TopLeft();
2749 aDocStart
-= aLogicStart
;
2750 pEngine
->Draw( pDev
, aLogicClip
, aDocStart
, FALSE
);
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
);
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();
2776 long nURLWidth
= (long) pEngine
->CalcTextWidth();
2777 long nURLHeight
= pEngine
->GetTextHeight();
2780 Size aPaper
= pEngine
->GetPaperSize();
2781 if ( bAsianVertical
)
2782 nURLHeight
= aPaper
.Height();
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
;
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
;
2839 Size aOnePixel
= pDev
->PixelToLogic(Size(1,1));
2840 long nOneX
= aOnePixel
.Width();
2841 nInitPosX
+= nMirrorW
- nOneX
;
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
)
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
;
2868 if ( nX
== nEditCol
&& nY
== nEditRow
)
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
) );
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
;
2906 pPattern
= pDoc
->GetPattern( nX
, nY
, nTab
);
2909 pCell
= pInfo
->pCell
;
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
;
2938 if ((bBreak
|| eOrient
!=SVX_ORIENTATION_STANDARD
) && !bMerged
)
2942 nStartX
= nInitPosX
;
2947 nStartX
-= nLayoutSign
* (long) pRowInfo
[0].pCellInfo
[nCol
+1].nWidth
;
2951 long nCellStartX
= nStartX
;
2953 // Ersatzdarstellung fuer zu kleinen Text weggelassen
2957 long nOutWidth
= nCellWidth
- 1;
2960 nOutHeight
= nCellHeight
;
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
;
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
);
3019 //! Position und Papersize auf EditUtil umstellen !!!
3021 const SvxMarginItem
* pMargin
= (const SvxMarginItem
*)
3022 &pPattern
->GetItem(ATTR_MARGIN
, pCondSet
);
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
);
3038 nOutWidth
-= nLeftM
+ nRightM
;
3039 nOutHeight
-= nTopM
+ nBottomM
;
3041 // Rotation schon hier, um bei Umbruch auch PaperSize anzupassen
3042 long nAttrRotate
= 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();
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
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
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
;
3083 aPaperSize
.Width() = nOutHeight
- 1;
3086 pEngine
->SetPaperSize(pRefDevice
->PixelToLogic(aPaperSize
));
3088 pEngine
->SetPaperSize(aPaperSize
); // Scale ist immer 1
3090 // Daten aus Zelle lesen
3094 if (pCell
->GetCellType() == CELLTYPE_EDIT
)
3096 const EditTextObject
* pData
;
3097 ((ScEditCell
*)pCell
)->GetData(pData
);
3100 pEngine
->SetText(*pData
);
3103 DBG_ERROR("pData == 0");
3108 ULONG nFormat
= pPattern
->GetNumberFormat(
3109 pDoc
->GetFormatTable(), pCondSet
);
3112 ScCellFormat::GetString( pCell
,
3113 nFormat
,aString
, &pColor
,
3114 *pDoc
->GetFormatTable(),
3119 pEngine
->SetText(aString
);
3120 if ( pColor
&& !bSyntaxMode
&& !( bUseStyleColor
&& bForceAutoColor
) )
3121 lcl_SetEditColor( *pEngine
, *pColor
);
3125 SetEditSyntaxColor( *pEngine
, pCell
);
3126 else if ( bUseStyleColor
&& bForceAutoColor
)
3127 lcl_SetEditColor( *pEngine
, COL_AUTO
); //! or have a flag at EditEngine
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
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() );
3158 if ( nNewWidth
< 4 )
3160 // can't fit -> fall back to using half height
3161 nEffHeight
= nOutHeight
/ 2;
3162 nNewWidth
= (long)(nEffHeight
/ nAbsSin
) + 2;
3168 // set paper width and get new text height
3169 aPaperSize
.Width() = nNewWidth
;
3171 pEngine
->SetPaperSize(pRefDevice
->PixelToLogic(aPaperSize
));
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
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
);
3194 nEngineWidth
= (long) ( nRealHeight
/ nAbsSin
);
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
3209 Size aClipSize
= Size( nScrX
+nScrW
-nStartX
, nScrY
+nScrH
-nStartY
);
3215 aCellSize
= pRefDevice
->PixelToLogic( Size( nOutWidth
, nOutHeight
) );
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
);
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
;
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
),
3249 aAlignRect
, aClipRect
, bLeftClip
, bRightClip
);
3253 long nPixelWidth
= bPixelToLogic
?
3254 pRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width() : nEngineWidth
;
3255 long nNeededPixel
= nPixelWidth
+ nLeftM
+ nRightM
;
3257 bLeftClip
= bRightClip
= TRUE
;
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
;
3286 //! Clipping unnoetig, wenn links am Fenster
3288 bClip
= TRUE
; // nur Rest ausgeben!
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
;
3304 nClipStartY
= nRowPosY
;
3305 aClipSize
.Height() -= nDif
;
3309 bClip
= TRUE
; // always clip at the window/page border
3311 //Rectangle aClipRect;
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
;
3323 aClipRect
= pRefDevice
->PixelToLogic( Rectangle(
3324 Point(nClipStartX
,nClipStartY
), aClipSize
) );
3326 aClipRect
= Rectangle(Point(nClipStartX
, nClipStartY
),
3327 aClipSize
); // Scale = 1
3332 pDev
->IntersectClipRegion( aClipRect
);
3335 pDev
->SetClipRegion( Region( aClipRect
) );
3340 aLogicStart
= pRefDevice
->PixelToLogic( Point(nStartX
,nStartY
) );
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
)
3353 nAvailWidth
-= pRefDevice
->PixelToLogic(Size(0,pRowInfo
[nArrY
].nHeight
)).Height();
3355 nAvailWidth
-= pRowInfo
[nArrY
].nHeight
;
3360 nAvailWidth
-= pRefDevice
->PixelToLogic(Size(0,DROPDOWN_BITMAP_SIZE
)).Height();
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
;
3385 pEngine
->SetPaperSize(pRefDevice
->PixelToLogic(aPaperSize
));
3387 pEngine
->SetPaperSize(aPaperSize
);
3389 pEngine
->SetUpdateMode( TRUE
);
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;
3406 aLogicStart
.X() -= pRefDevice
->PixelToLogic(
3407 Size( nCellWidth
, 0 ) ).Width();
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
)
3419 aLogicStart
.Y() += pRefDevice
->PixelToLogic( Size(0,
3420 pRefDevice
->LogicToPixel(aCellSize
).Height() -
3421 pRefDevice
->LogicToPixel(Size(0,nEngineHeight
)).Height()
3424 aLogicStart
.Y() += aCellSize
.Height() - nEngineHeight
;
3427 else if (eVerJust
==SVX_VER_JUSTIFY_CENTER
)
3430 aLogicStart
.Y() += pRefDevice
->PixelToLogic( Size(0,(
3431 pRefDevice
->LogicToPixel(aCellSize
).Height() -
3432 pRefDevice
->LogicToPixel(Size(0,nEngineHeight
)).Height())
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" );
3446 // Attribut ist 1/100, Font 1/10 Grad
3447 nOriVal
= nAttrRotate
/ 10;
3451 if ( nCos
> 0.0 && eRotMode
!= SVX_ROTATE_MODE_STANDARD
)
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
;
3460 nAddX
-= nRealHeight
* nSin
;
3462 nAddY
+= nRealWidth
* nSin
;
3464 nAddY
-= nRealHeight
* nCos
;
3466 if ( eRotMode
!= SVX_ROTATE_MODE_STANDARD
)
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 ) )
3477 if ( eVerJust
== SVX_VER_JUSTIFY_CENTER
)
3478 nUp
= ( aCellSize
.Height() - nEngineHeight
) / 2;
3479 else if ( eVerJust
== SVX_VER_JUSTIFY_TOP
)
3482 nUp
= aCellSize
.Height() - nEngineHeight
;
3484 else // BOTTOM / STANDARD
3487 nUp
= aCellSize
.Height() - nEngineHeight
;
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
);
3519 pDev
->SetClipRegion();
3525 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
3528 nRowPosY
+= pRowInfo
[nArrY
].nHeight
;