Avoid potential negative array index access to cached text.
[LibreOffice.git] / sc / source / core / data / patattr.cxx
blob32905201def9b7871fc2a0c3c87aa6687307db89
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <memory>
21 #include <utility>
22 #include <scitems.hxx>
23 #include <editeng/adjustitem.hxx>
24 #include <editeng/boxitem.hxx>
25 #include <editeng/lineitem.hxx>
26 #include <editeng/brushitem.hxx>
27 #include <editeng/charreliefitem.hxx>
28 #include <editeng/contouritem.hxx>
29 #include <svtools/colorcfg.hxx>
30 #include <editeng/colritem.hxx>
31 #include <editeng/crossedoutitem.hxx>
32 #include <editeng/eeitem.hxx>
33 #include <editeng/emphasismarkitem.hxx>
34 #include <editeng/fhgtitem.hxx>
35 #include <editeng/fontitem.hxx>
36 #include <editeng/forbiddenruleitem.hxx>
37 #include <editeng/frmdiritem.hxx>
38 #include <editeng/langitem.hxx>
39 #include <editeng/postitem.hxx>
40 #include <svx/rotmodit.hxx>
41 #include <editeng/scriptspaceitem.hxx>
42 #include <editeng/shaditem.hxx>
43 #include <editeng/shdditem.hxx>
44 #include <editeng/udlnitem.hxx>
45 #include <editeng/wghtitem.hxx>
46 #include <editeng/wrlmitem.hxx>
47 #include <editeng/justifyitem.hxx>
48 #include <svl/intitem.hxx>
49 #include <svl/numformat.hxx>
50 #include <svl/whiter.hxx>
51 #include <svl/zforlist.hxx>
52 #include <vcl/outdev.hxx>
53 #include <tools/fract.hxx>
54 #include <tools/UnitConversion.hxx>
55 #include <osl/diagnose.h>
57 #include <attrib.hxx>
58 #include <patattr.hxx>
59 #include <docpool.hxx>
60 #include <stlsheet.hxx>
61 #include <stlpool.hxx>
62 #include <document.hxx>
63 #include <globstr.hrc>
64 #include <scresid.hxx>
65 #include <validat.hxx>
66 #include <scmod.hxx>
67 #include <fillinfo.hxx>
68 #include <comphelper/lok.hxx>
69 #include <tabvwsh.hxx>
71 const WhichRangesContainer aScPatternAttrSchema(svl::Items<ATTR_PATTERN_START, ATTR_PATTERN_END>);
73 ScPatternAttr::ScPatternAttr( SfxItemSet&& pItemSet, const OUString& rStyleName )
74 : SfxSetItem ( ATTR_PATTERN, std::move(pItemSet) ),
75 pName ( rStyleName ),
76 pStyle ( nullptr ),
77 mnPAKey(0)
79 setExceptionalSCItem();
81 // We need to ensure that ScPatternAttr is using the correct WhichRange,
82 // see comments in commit message. This does transfers the items with
83 // minimized overhead, too
84 if (GetItemSet().GetRanges() != aScPatternAttrSchema)
85 GetItemSet().SetRanges(aScPatternAttrSchema);
88 ScPatternAttr::ScPatternAttr( SfxItemSet&& pItemSet )
89 : SfxSetItem ( ATTR_PATTERN, std::move(pItemSet) ),
90 pStyle ( nullptr ),
91 mnPAKey(0)
93 setExceptionalSCItem();
95 // We need to ensure that ScPatternAttr is using the correct WhichRange,
96 // see comments in commit message. This does transfers the items with
97 // minimized overhead, too
98 if (GetItemSet().GetRanges() != aScPatternAttrSchema)
99 GetItemSet().SetRanges(aScPatternAttrSchema);
102 ScPatternAttr::ScPatternAttr( SfxItemPool* pItemPool )
103 : SfxSetItem ( ATTR_PATTERN, SfxItemSetFixed<ATTR_PATTERN_START, ATTR_PATTERN_END>( *pItemPool ) ),
104 pStyle ( nullptr ),
105 mnPAKey(0)
107 setExceptionalSCItem();
110 ScPatternAttr::ScPatternAttr( const ScPatternAttr& rPatternAttr )
111 : SfxSetItem ( rPatternAttr ),
112 pName ( rPatternAttr.pName ),
113 pStyle ( rPatternAttr.pStyle ),
114 mnPAKey(rPatternAttr.mnPAKey)
116 setExceptionalSCItem();
119 ScPatternAttr* ScPatternAttr::Clone( SfxItemPool *pPool ) const
121 ScPatternAttr* pPattern = new ScPatternAttr( GetItemSet().CloneAsValue(true, pPool) );
123 pPattern->pStyle = pStyle;
124 pPattern->pName = pName;
126 return pPattern;
129 static bool StrCmp( const OUString* pStr1, const OUString* pStr2 )
131 if (pStr1 == pStr2)
132 return true;
133 if (pStr1 && !pStr2)
134 return false;
135 if (!pStr1 && pStr2)
136 return false;
137 return *pStr1 == *pStr2;
140 constexpr size_t compareSize = ATTR_PATTERN_END - ATTR_PATTERN_START + 1;
142 bool ScPatternAttr::operator==( const SfxPoolItem& rCmp ) const
144 // check if same incarnation
145 if (this == &rCmp)
146 return true;
148 // check SfxPoolItem base class
149 if (!SfxPoolItem::operator==(rCmp) )
150 return false;
152 // check everything except the SfxItemSet from base class SfxSetItem
153 const ScPatternAttr& rOther(static_cast<const ScPatternAttr&>(rCmp));
154 if (!StrCmp(GetStyleName(), rOther.GetStyleName()))
155 return false;
157 // here we need to compare the SfxItemSet. We *know* that these are
158 // all simple (one range, same range)
159 const SfxItemSet& rSet1(GetItemSet());
160 const SfxItemSet& rSet2(rOther.GetItemSet());
162 // the former method 'FastEqualPatternSets' mentioned:
163 // "Actually test_tdf133629 from UITest_calc_tests9 somehow manages to have
164 // a different range (and I don't understand enough why), so better be safe and compare fully."
165 // in that case the hash code above would already fail, too
166 if (rSet1.TotalCount() != compareSize || rSet2.TotalCount() != compareSize)
168 // assert this for now, should not happen. If it does, look for it and evtl.
169 // enable SfxItemSet::operator== below
170 assert(false);
171 return rSet1 == rSet2;
174 // check pools, do not accept different pools
175 if (rSet1.GetPool() != rSet2.GetPool())
176 return false;
178 // check count of set items, has to be equal
179 if (rSet1.Count() != rSet2.Count())
180 return false;
182 // compare each item separately
183 const SfxPoolItem **ppItem1(rSet1.GetItems_Impl());
184 const SfxPoolItem **ppItem2(rSet2.GetItems_Impl());
186 // are all pointers the same?
187 if (0 == memcmp(ppItem1, ppItem2, compareSize * sizeof(ppItem1[0])))
188 return true;
190 for (sal_uInt16 nPos(0); nPos < compareSize; nPos++)
192 if (!SfxPoolItem::areSame(*ppItem1, *ppItem2))
193 return false;
194 ++ppItem1;
195 ++ppItem2;
198 return true;
201 SvxCellOrientation ScPatternAttr::GetCellOrientation( const SfxItemSet& rItemSet, const SfxItemSet* pCondSet )
203 SvxCellOrientation eOrient = SvxCellOrientation::Standard;
205 if( GetItem( ATTR_STACKED, rItemSet, pCondSet ).GetValue() )
207 eOrient = SvxCellOrientation::Stacked;
209 else
211 Degree100 nAngle = GetItem( ATTR_ROTATE_VALUE, rItemSet, pCondSet ).GetValue();
212 if( nAngle == 9000_deg100 )
213 eOrient = SvxCellOrientation::BottomUp;
214 else if( nAngle == 27000_deg100 )
215 eOrient = SvxCellOrientation::TopBottom;
218 return eOrient;
221 SvxCellOrientation ScPatternAttr::GetCellOrientation( const SfxItemSet* pCondSet ) const
223 return GetCellOrientation( GetItemSet(), pCondSet );
226 namespace {
228 void getFontIDsByScriptType(SvtScriptType nScript,
229 TypedWhichId<SvxFontItem>& nFontId,
230 TypedWhichId<SvxFontHeightItem>& nHeightId,
231 TypedWhichId<SvxWeightItem>& nWeightId,
232 TypedWhichId<SvxPostureItem>& nPostureId,
233 TypedWhichId<SvxLanguageItem>& nLangId)
235 if ( nScript == SvtScriptType::ASIAN )
237 nFontId = ATTR_CJK_FONT;
238 nHeightId = ATTR_CJK_FONT_HEIGHT;
239 nWeightId = ATTR_CJK_FONT_WEIGHT;
240 nPostureId = ATTR_CJK_FONT_POSTURE;
241 nLangId = ATTR_CJK_FONT_LANGUAGE;
243 else if ( nScript == SvtScriptType::COMPLEX )
245 nFontId = ATTR_CTL_FONT;
246 nHeightId = ATTR_CTL_FONT_HEIGHT;
247 nWeightId = ATTR_CTL_FONT_WEIGHT;
248 nPostureId = ATTR_CTL_FONT_POSTURE;
249 nLangId = ATTR_CTL_FONT_LANGUAGE;
251 else
253 nFontId = ATTR_FONT;
254 nHeightId = ATTR_FONT_HEIGHT;
255 nWeightId = ATTR_FONT_WEIGHT;
256 nPostureId = ATTR_FONT_POSTURE;
257 nLangId = ATTR_FONT_LANGUAGE;
263 void ScPatternAttr::fillFont(
264 vcl::Font& rFont, const SfxItemSet& rItemSet, ScAutoFontColorMode eAutoMode,
265 const OutputDevice* pOutDev, const Fraction* pScale,
266 const SfxItemSet* pCondSet, SvtScriptType nScript,
267 const Color* pBackConfigColor, const Color* pTextConfigColor)
269 model::ComplexColor aComplexColor;
271 // determine effective font color
272 ScPatternAttr::fillFontOnly(rFont, rItemSet, pOutDev, pScale, pCondSet, nScript);
273 ScPatternAttr::fillColor(aComplexColor, rItemSet, eAutoMode, pCondSet, pBackConfigColor, pTextConfigColor);
275 // set font effects
276 rFont.SetColor(aComplexColor.getFinalColor());
279 void ScPatternAttr::fillFontOnly(
280 vcl::Font& rFont, const SfxItemSet& rItemSet,
281 const OutputDevice* pOutDev, const Fraction* pScale,
282 const SfxItemSet* pCondSet, SvtScriptType nScript)
284 // Read items
286 const SvxFontItem* pFontAttr;
287 sal_uInt32 nFontHeight;
288 FontWeight eWeight;
289 FontItalic eItalic;
290 FontLineStyle eUnder;
291 FontLineStyle eOver;
292 bool bWordLine;
293 FontStrikeout eStrike;
294 bool bOutline;
295 bool bShadow;
296 FontEmphasisMark eEmphasis;
297 FontRelief eRelief;
298 LanguageType eLang;
300 TypedWhichId<SvxFontItem> nFontId(0);
301 TypedWhichId<SvxFontHeightItem> nHeightId(0);
302 TypedWhichId<SvxWeightItem> nWeightId(0);
303 TypedWhichId<SvxPostureItem> nPostureId(0);
304 TypedWhichId<SvxLanguageItem> nLangId(0);
305 getFontIDsByScriptType(nScript, nFontId, nHeightId, nWeightId, nPostureId, nLangId);
307 if (pCondSet)
309 pFontAttr = pCondSet->GetItemIfSet( nFontId );
310 if ( !pFontAttr )
311 pFontAttr = &rItemSet.Get( nFontId );
313 const SvxFontHeightItem* pFontHeightItem = pCondSet->GetItemIfSet( nHeightId );
314 if ( !pFontHeightItem )
315 pFontHeightItem = &rItemSet.Get( nHeightId );
316 nFontHeight = pFontHeightItem->GetHeight();
318 const SvxWeightItem* pFontHWeightItem = pCondSet->GetItemIfSet( nWeightId );
319 if ( !pFontHWeightItem )
320 pFontHWeightItem = &rItemSet.Get( nWeightId );
321 eWeight = pFontHWeightItem->GetValue();
323 const SvxPostureItem* pPostureItem = pCondSet->GetItemIfSet( nPostureId );
324 if ( !pPostureItem )
325 pPostureItem = &rItemSet.Get( nPostureId );
326 eItalic = pPostureItem->GetValue();
328 const SvxUnderlineItem* pUnderlineItem = pCondSet->GetItemIfSet( ATTR_FONT_UNDERLINE );
329 if ( !pUnderlineItem )
330 pUnderlineItem = &rItemSet.Get( ATTR_FONT_UNDERLINE );
331 eUnder = pUnderlineItem->GetValue();
333 const SvxOverlineItem* pOverlineItem = pCondSet->GetItemIfSet( ATTR_FONT_OVERLINE );
334 if ( !pOverlineItem )
335 pOverlineItem = &rItemSet.Get( ATTR_FONT_OVERLINE );
336 eOver = pOverlineItem->GetValue();
338 const SvxWordLineModeItem* pWordlineItem = pCondSet->GetItemIfSet( ATTR_FONT_WORDLINE );
339 if ( !pWordlineItem )
340 pWordlineItem = &rItemSet.Get( ATTR_FONT_WORDLINE );
341 bWordLine = pWordlineItem->GetValue();
343 const SvxCrossedOutItem* pCrossedOutItem = pCondSet->GetItemIfSet( ATTR_FONT_CROSSEDOUT );
344 if ( !pCrossedOutItem )
345 pCrossedOutItem = &rItemSet.Get( ATTR_FONT_CROSSEDOUT );
346 eStrike = pCrossedOutItem->GetValue();
348 const SvxContourItem* pContourItem = pCondSet->GetItemIfSet( ATTR_FONT_CONTOUR );
349 if ( !pContourItem )
350 pContourItem = &rItemSet.Get( ATTR_FONT_CONTOUR );
351 bOutline = pContourItem->GetValue();
353 const SvxShadowedItem* pShadowedItem = pCondSet->GetItemIfSet( ATTR_FONT_SHADOWED );
354 if ( !pShadowedItem )
355 pShadowedItem = &rItemSet.Get( ATTR_FONT_SHADOWED );
356 bShadow = pShadowedItem->GetValue();
358 const SvxEmphasisMarkItem* pEmphasisMarkItem = pCondSet->GetItemIfSet( ATTR_FONT_EMPHASISMARK );
359 if ( !pEmphasisMarkItem )
360 pEmphasisMarkItem = &rItemSet.Get( ATTR_FONT_EMPHASISMARK );
361 eEmphasis = pEmphasisMarkItem->GetEmphasisMark();
363 const SvxCharReliefItem* pCharReliefItem = pCondSet->GetItemIfSet( ATTR_FONT_RELIEF );
364 if ( !pCharReliefItem )
365 pCharReliefItem = &rItemSet.Get( ATTR_FONT_RELIEF );
366 eRelief = pCharReliefItem->GetValue();
368 const SvxLanguageItem* pLanguageItem = pCondSet->GetItemIfSet( nLangId );
369 if ( !pLanguageItem )
370 pLanguageItem = &rItemSet.Get( nLangId );
371 eLang = pLanguageItem->GetLanguage();
373 else // Everything from rItemSet
375 pFontAttr = &rItemSet.Get( nFontId );
376 nFontHeight = rItemSet.Get( nHeightId ).GetHeight();
377 eWeight = rItemSet.Get( nWeightId ).GetValue();
378 eItalic = rItemSet.Get( nPostureId ).GetValue();
379 eUnder = rItemSet.Get( ATTR_FONT_UNDERLINE ).GetValue();
380 eOver = rItemSet.Get( ATTR_FONT_OVERLINE ).GetValue();
381 bWordLine = rItemSet.Get( ATTR_FONT_WORDLINE ).GetValue();
382 eStrike = rItemSet.Get( ATTR_FONT_CROSSEDOUT ).GetValue();
383 bOutline = rItemSet.Get( ATTR_FONT_CONTOUR ).GetValue();
384 bShadow = rItemSet.Get( ATTR_FONT_SHADOWED ).GetValue();
385 eEmphasis = rItemSet.Get( ATTR_FONT_EMPHASISMARK ).GetEmphasisMark();
386 eRelief = rItemSet.Get( ATTR_FONT_RELIEF ).GetValue();
387 // for graphite language features
388 eLang = rItemSet.Get( nLangId ).GetLanguage();
390 OSL_ENSURE(pFontAttr,"Oops?");
392 // Evaluate
394 // FontItem:
396 if (rFont.GetFamilyName() != pFontAttr->GetFamilyName())
397 rFont.SetFamilyName( pFontAttr->GetFamilyName() );
398 if (rFont.GetStyleName() != pFontAttr->GetStyleName())
399 rFont.SetStyleName( pFontAttr->GetStyleName() );
401 rFont.SetFamily( pFontAttr->GetFamily() );
402 rFont.SetCharSet( pFontAttr->GetCharSet() );
403 rFont.SetPitch( pFontAttr->GetPitch() );
405 rFont.SetLanguage(eLang);
407 // Size
409 if ( pOutDev != nullptr )
411 Size aEffSize;
412 Fraction aFraction( 1,1 );
413 if (pScale)
414 aFraction = *pScale;
415 Size aSize( 0, static_cast<tools::Long>(nFontHeight) );
416 MapMode aDestMode = pOutDev->GetMapMode();
417 MapMode aSrcMode( MapUnit::MapTwip, Point(), aFraction, aFraction );
418 if (aDestMode.GetMapUnit() == MapUnit::MapPixel && pOutDev->GetDPIX() > 0)
419 aEffSize = pOutDev->LogicToPixel( aSize, aSrcMode );
420 else
422 Fraction aFractOne(1,1);
423 aDestMode.SetScaleX( aFractOne );
424 aDestMode.SetScaleY( aFractOne );
425 aEffSize = OutputDevice::LogicToLogic( aSize, aSrcMode, aDestMode );
427 rFont.SetFontSize( aEffSize );
429 else /* if pOutDev != NULL */
431 rFont.SetFontSize( Size( 0, static_cast<tools::Long>(nFontHeight) ) );
434 // set font effects
435 rFont.SetWeight( eWeight );
436 rFont.SetItalic( eItalic );
437 rFont.SetUnderline( eUnder );
438 rFont.SetOverline( eOver );
439 rFont.SetWordLineMode( bWordLine );
440 rFont.SetStrikeout( eStrike );
441 rFont.SetOutline( bOutline );
442 rFont.SetShadow( bShadow );
443 rFont.SetEmphasisMark( eEmphasis );
444 rFont.SetRelief( eRelief );
445 rFont.SetTransparent( true );
448 void ScPatternAttr::fillColor(model::ComplexColor& rComplexColor, const SfxItemSet& rItemSet, ScAutoFontColorMode eAutoMode, const SfxItemSet* pCondSet, const Color* pBackConfigColor, const Color* pTextConfigColor)
450 model::ComplexColor aComplexColor;
452 Color aColor;
454 SvxColorItem const* pColorItem = nullptr;
456 if (pCondSet)
457 pColorItem = pCondSet->GetItemIfSet(ATTR_FONT_COLOR);
459 if (!pColorItem)
460 pColorItem = &rItemSet.Get(ATTR_FONT_COLOR);
462 if (pColorItem)
464 aComplexColor = pColorItem->getComplexColor();
465 aColor = pColorItem->GetValue();
468 if (aComplexColor.getType() == model::ColorType::Unused)
470 aComplexColor.setColor(aColor);
473 if ((aColor == COL_AUTO && eAutoMode != ScAutoFontColorMode::Raw)
474 || eAutoMode == ScAutoFontColorMode::IgnoreFont
475 || eAutoMode == ScAutoFontColorMode::IgnoreAll)
477 // get background color from conditional or own set
478 Color aBackColor;
479 if ( pCondSet )
481 const SvxBrushItem* pItem = pCondSet->GetItemIfSet(ATTR_BACKGROUND);
482 if (!pItem)
483 pItem = &rItemSet.Get(ATTR_BACKGROUND);
484 aBackColor = pItem->GetColor();
486 else
488 aBackColor = rItemSet.Get(ATTR_BACKGROUND).GetColor();
491 // if background color attribute is transparent, use window color for brightness comparisons
492 if (aBackColor == COL_TRANSPARENT
493 || eAutoMode == ScAutoFontColorMode::IgnoreBack
494 || eAutoMode == ScAutoFontColorMode::IgnoreAll)
496 if (!comphelper::LibreOfficeKit::isActive())
498 if ( eAutoMode == ScAutoFontColorMode::Print )
499 aBackColor = COL_WHITE;
500 else if ( pBackConfigColor )
502 // pBackConfigColor can be used to avoid repeated lookup of the configured color
503 aBackColor = *pBackConfigColor;
505 else
506 aBackColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor;
508 else
510 // Get document color from current view instead
511 SfxViewShell* pSfxViewShell = SfxViewShell::Current();
512 ScTabViewShell* pViewShell = dynamic_cast<ScTabViewShell*>(pSfxViewShell);
513 if (pViewShell)
515 const ScViewRenderingOptions& rViewRenderingOptions = pViewShell->GetViewRenderingData();
516 aBackColor = eAutoMode == ScAutoFontColorMode::Print ? COL_WHITE :
517 rViewRenderingOptions.GetDocColor();
522 // get system text color for comparison
523 Color aSysTextColor;
524 if (eAutoMode == ScAutoFontColorMode::Print)
526 aSysTextColor = COL_BLACK;
528 else if (pTextConfigColor)
530 // pTextConfigColor can be used to avoid repeated lookup of the configured color
531 aSysTextColor = *pTextConfigColor;
533 else
535 aSysTextColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor;
538 // select the resulting color
539 if ( aBackColor.IsDark() && aSysTextColor.IsDark() )
541 // use white instead of dark on dark
542 aColor = COL_WHITE;
544 else if ( aBackColor.IsBright() && aSysTextColor.IsBright() )
546 // use black instead of bright on bright
547 aColor = COL_BLACK;
549 else
551 // use aSysTextColor (black for ScAutoFontColorMode::Print, from style settings otherwise)
552 aColor = aSysTextColor;
555 aComplexColor.setFinalColor(aColor);
556 rComplexColor = aComplexColor;
559 ScDxfFont ScPatternAttr::GetDxfFont(const SfxItemSet& rItemSet, SvtScriptType nScript)
561 TypedWhichId<SvxFontItem> nFontId(0);
562 TypedWhichId<SvxFontHeightItem> nHeightId(0);
563 TypedWhichId<SvxWeightItem> nWeightId(0);
564 TypedWhichId<SvxPostureItem> nPostureId(0);
565 TypedWhichId<SvxLanguageItem> nLangId(0);
566 getFontIDsByScriptType(nScript, nFontId, nHeightId, nWeightId, nPostureId, nLangId);
568 ScDxfFont aReturn;
570 if ( const SvxFontItem* pItem = rItemSet.GetItemIfSet( nFontId ) )
572 aReturn.pFontAttr = pItem;
575 if ( const SvxFontHeightItem* pItem = rItemSet.GetItemIfSet( nHeightId ) )
577 aReturn.nFontHeight = pItem->GetHeight();
580 if ( const SvxWeightItem* pItem = rItemSet.GetItemIfSet( nWeightId ) )
582 aReturn.eWeight = pItem->GetValue();
585 if ( const SvxPostureItem* pItem = rItemSet.GetItemIfSet( nPostureId ) )
587 aReturn.eItalic = pItem->GetValue();
590 if ( const SvxUnderlineItem* pItem = rItemSet.GetItemIfSet( ATTR_FONT_UNDERLINE ) )
592 pItem = &rItemSet.Get( ATTR_FONT_UNDERLINE );
593 aReturn.eUnder = pItem->GetValue();
596 if ( const SvxOverlineItem* pItem = rItemSet.GetItemIfSet( ATTR_FONT_OVERLINE ) )
598 aReturn.eOver = pItem->GetValue();
601 if ( const SvxWordLineModeItem* pItem = rItemSet.GetItemIfSet( ATTR_FONT_WORDLINE ) )
603 aReturn.bWordLine = pItem->GetValue();
606 if ( const SvxCrossedOutItem* pItem = rItemSet.GetItemIfSet( ATTR_FONT_CROSSEDOUT ) )
608 pItem = &rItemSet.Get( ATTR_FONT_CROSSEDOUT );
609 aReturn.eStrike = pItem->GetValue();
612 if ( const SvxContourItem* pItem = rItemSet.GetItemIfSet( ATTR_FONT_CONTOUR ) )
614 aReturn.bOutline = pItem->GetValue();
617 if ( const SvxShadowedItem* pItem = rItemSet.GetItemIfSet( ATTR_FONT_SHADOWED ) )
619 pItem = &rItemSet.Get( ATTR_FONT_SHADOWED );
620 aReturn.bShadow = pItem->GetValue();
623 if ( const SvxEmphasisMarkItem* pItem = rItemSet.GetItemIfSet( ATTR_FONT_EMPHASISMARK ) )
625 aReturn.eEmphasis = pItem->GetEmphasisMark();
628 if ( const SvxCharReliefItem* pItem = rItemSet.GetItemIfSet( ATTR_FONT_RELIEF ) )
630 aReturn.eRelief = pItem->GetValue();
633 if ( const SvxColorItem* pItem = rItemSet.GetItemIfSet( ATTR_FONT_COLOR ) )
635 aReturn.aColor = pItem->GetValue();
638 if ( const SvxLanguageItem* pItem = rItemSet.GetItemIfSet( nLangId ) )
640 aReturn.eLang = pItem->GetLanguage();
643 return aReturn;
646 template <class T>
647 static void lcl_populate( std::unique_ptr<T>& rxItem, TypedWhichId<T> nWhich, const SfxItemSet& rSrcSet, const SfxItemSet* pCondSet )
649 const T* pItem = pCondSet->GetItemIfSet( nWhich );
650 if ( !pItem )
651 pItem = &rSrcSet.Get( nWhich );
652 rxItem.reset(pItem->Clone());
655 void ScPatternAttr::FillToEditItemSet( SfxItemSet& rEditSet, const SfxItemSet& rSrcSet, const SfxItemSet* pCondSet )
657 // Read Items
659 std::unique_ptr<SvxColorItem> aColorItem(std::make_unique<SvxColorItem>(EE_CHAR_COLOR)); // use item as-is
660 std::unique_ptr<SvxFontItem> aFontItem(std::make_unique<SvxFontItem>(EE_CHAR_FONTINFO)); // use item as-is
661 std::unique_ptr<SvxFontItem> aCjkFontItem(std::make_unique<SvxFontItem>(EE_CHAR_FONTINFO_CJK)); // use item as-is
662 std::unique_ptr<SvxFontItem> aCtlFontItem(std::make_unique<SvxFontItem>(EE_CHAR_FONTINFO_CTL)); // use item as-is
663 tools::Long nTHeight, nCjkTHeight, nCtlTHeight; // Twips
664 FontWeight eWeight, eCjkWeight, eCtlWeight;
665 std::unique_ptr<SvxUnderlineItem> aUnderlineItem(std::make_unique<SvxUnderlineItem>(LINESTYLE_NONE, EE_CHAR_UNDERLINE));
666 std::unique_ptr<SvxOverlineItem> aOverlineItem(std::make_unique<SvxOverlineItem>(LINESTYLE_NONE, EE_CHAR_OVERLINE));
667 bool bWordLine;
668 FontStrikeout eStrike;
669 FontItalic eItalic, eCjkItalic, eCtlItalic;
670 bool bOutline;
671 bool bShadow;
672 bool bForbidden;
673 FontEmphasisMark eEmphasis;
674 FontRelief eRelief;
675 LanguageType eLang, eCjkLang, eCtlLang;
676 bool bHyphenate;
677 SvxFrameDirection eDirection;
679 //TODO: additional parameter to control if language is needed?
681 if ( pCondSet )
683 lcl_populate(aColorItem, ATTR_FONT_COLOR, rSrcSet, pCondSet);
684 lcl_populate(aFontItem, ATTR_FONT, rSrcSet, pCondSet);
685 lcl_populate(aCjkFontItem, ATTR_CJK_FONT, rSrcSet, pCondSet);
686 lcl_populate(aCtlFontItem, ATTR_CTL_FONT, rSrcSet, pCondSet);
688 const SvxFontHeightItem* pFontHeightItem = pCondSet->GetItemIfSet( ATTR_FONT_HEIGHT );
689 if (!pFontHeightItem)
690 pFontHeightItem = &rSrcSet.Get( ATTR_FONT_HEIGHT );
691 nTHeight = pFontHeightItem->GetHeight();
692 pFontHeightItem = pCondSet->GetItemIfSet( ATTR_CJK_FONT_HEIGHT );
693 if ( !pFontHeightItem )
694 pFontHeightItem = &rSrcSet.Get( ATTR_CJK_FONT_HEIGHT );
695 nCjkTHeight = pFontHeightItem->GetHeight();
696 pFontHeightItem = pCondSet->GetItemIfSet( ATTR_CTL_FONT_HEIGHT );
697 if ( !pFontHeightItem )
698 pFontHeightItem = &rSrcSet.Get( ATTR_CTL_FONT_HEIGHT );
699 nCtlTHeight = pFontHeightItem->GetHeight();
701 const SvxWeightItem* pWeightItem = pCondSet->GetItemIfSet( ATTR_FONT_WEIGHT );
702 if ( !pWeightItem )
703 pWeightItem = &rSrcSet.Get( ATTR_FONT_WEIGHT );
704 eWeight = pWeightItem->GetValue();
705 pWeightItem = pCondSet->GetItemIfSet( ATTR_CJK_FONT_WEIGHT );
706 if ( !pWeightItem )
707 pWeightItem = &rSrcSet.Get( ATTR_CJK_FONT_WEIGHT );
708 eCjkWeight = pWeightItem->GetValue();
709 pWeightItem = pCondSet->GetItemIfSet( ATTR_CTL_FONT_WEIGHT );
710 if ( !pWeightItem )
711 pWeightItem = &rSrcSet.Get( ATTR_CTL_FONT_WEIGHT );
712 eCtlWeight = pWeightItem->GetValue();
714 const SvxPostureItem* pPostureItem = pCondSet->GetItemIfSet( ATTR_FONT_POSTURE );
715 if ( !pPostureItem )
716 pPostureItem = &rSrcSet.Get( ATTR_FONT_POSTURE );
717 eItalic = pPostureItem->GetValue();
718 pPostureItem = pCondSet->GetItemIfSet( ATTR_CJK_FONT_POSTURE );
719 if ( !pPostureItem )
720 pPostureItem = &rSrcSet.Get( ATTR_CJK_FONT_POSTURE );
721 eCjkItalic = pPostureItem->GetValue();
722 pPostureItem = pCondSet->GetItemIfSet( ATTR_CTL_FONT_POSTURE );
723 if ( !pPostureItem )
724 pPostureItem = &rSrcSet.Get( ATTR_CTL_FONT_POSTURE );
725 eCtlItalic = pPostureItem->GetValue();
727 lcl_populate(aUnderlineItem, ATTR_FONT_UNDERLINE, rSrcSet, pCondSet);
728 lcl_populate(aOverlineItem, ATTR_FONT_OVERLINE, rSrcSet, pCondSet);
730 const SvxWordLineModeItem* pWordLineModeItem = pCondSet->GetItemIfSet( ATTR_FONT_WORDLINE );
731 if ( !pWordLineModeItem )
732 pWordLineModeItem = &rSrcSet.Get( ATTR_FONT_WORDLINE );
733 bWordLine = pWordLineModeItem->GetValue();
735 const SvxCrossedOutItem* pCrossedOutItem = pCondSet->GetItemIfSet( ATTR_FONT_CROSSEDOUT );
736 if ( !pCrossedOutItem )
737 pCrossedOutItem = &rSrcSet.Get( ATTR_FONT_CROSSEDOUT );
738 eStrike = pCrossedOutItem->GetValue();
740 const SvxContourItem* pContourItem = pCondSet->GetItemIfSet( ATTR_FONT_CONTOUR );
741 if ( !pContourItem )
742 pContourItem = &rSrcSet.Get( ATTR_FONT_CONTOUR );
743 bOutline = pContourItem->GetValue();
745 const SvxShadowedItem* pShadowedItem = pCondSet->GetItemIfSet( ATTR_FONT_SHADOWED );
746 if ( !pShadowedItem )
747 pShadowedItem = &rSrcSet.Get( ATTR_FONT_SHADOWED );
748 bShadow = pShadowedItem->GetValue();
750 const SvxForbiddenRuleItem* pForbiddenRuleItem = pCondSet->GetItemIfSet( ATTR_FORBIDDEN_RULES );
751 if ( !pForbiddenRuleItem )
752 pForbiddenRuleItem = &rSrcSet.Get( ATTR_FORBIDDEN_RULES );
753 bForbidden = pForbiddenRuleItem->GetValue();
755 const SvxEmphasisMarkItem* pEmphasisMarkItem = pCondSet->GetItemIfSet( ATTR_FONT_EMPHASISMARK );
756 if ( !pEmphasisMarkItem )
757 pEmphasisMarkItem = &rSrcSet.Get( ATTR_FONT_EMPHASISMARK );
758 eEmphasis = pEmphasisMarkItem->GetEmphasisMark();
759 const SvxCharReliefItem* pCharReliefItem = pCondSet->GetItemIfSet( ATTR_FONT_RELIEF );
760 if ( !pCharReliefItem )
761 pCharReliefItem = &rSrcSet.Get( ATTR_FONT_RELIEF );
762 eRelief = pCharReliefItem->GetValue();
764 const SvxLanguageItem* pLanguageItem = pCondSet->GetItemIfSet( ATTR_FONT_LANGUAGE );
765 if ( !pLanguageItem )
766 pLanguageItem = &rSrcSet.Get( ATTR_FONT_LANGUAGE );
767 eLang = pLanguageItem->GetLanguage();
768 pLanguageItem = pCondSet->GetItemIfSet( ATTR_CJK_FONT_LANGUAGE );
769 if ( !pLanguageItem )
770 pLanguageItem = &rSrcSet.Get( ATTR_CJK_FONT_LANGUAGE );
771 eCjkLang = pLanguageItem->GetLanguage();
772 pLanguageItem = pCondSet->GetItemIfSet( ATTR_CTL_FONT_LANGUAGE );
773 if ( !pLanguageItem )
774 pLanguageItem = &rSrcSet.Get( ATTR_CTL_FONT_LANGUAGE );
775 eCtlLang = pLanguageItem->GetLanguage();
777 const ScHyphenateCell* pHyphenateCell = pCondSet->GetItemIfSet( ATTR_HYPHENATE );
778 if ( !pHyphenateCell )
779 pHyphenateCell = &rSrcSet.Get( ATTR_HYPHENATE );
780 bHyphenate = pHyphenateCell->GetValue();
782 const SvxFrameDirectionItem* pFrameDirectionItem = pCondSet->GetItemIfSet( ATTR_WRITINGDIR );
783 if ( !pFrameDirectionItem )
784 pFrameDirectionItem = &rSrcSet.Get( ATTR_WRITINGDIR );
785 eDirection = pFrameDirectionItem->GetValue();
787 else // Everything directly from Pattern
789 aColorItem.reset(rSrcSet.Get(ATTR_FONT_COLOR).Clone());
790 aFontItem.reset(rSrcSet.Get(ATTR_FONT).Clone());
791 aCjkFontItem.reset(rSrcSet.Get(ATTR_CJK_FONT).Clone());
792 aCtlFontItem.reset(rSrcSet.Get(ATTR_CTL_FONT).Clone());
793 nTHeight = rSrcSet.Get( ATTR_FONT_HEIGHT ).GetHeight();
794 nCjkTHeight = rSrcSet.Get( ATTR_CJK_FONT_HEIGHT ).GetHeight();
795 nCtlTHeight = rSrcSet.Get( ATTR_CTL_FONT_HEIGHT ).GetHeight();
796 eWeight = rSrcSet.Get( ATTR_FONT_WEIGHT ).GetValue();
797 eCjkWeight = rSrcSet.Get( ATTR_CJK_FONT_WEIGHT ).GetValue();
798 eCtlWeight = rSrcSet.Get( ATTR_CTL_FONT_WEIGHT ).GetValue();
799 eItalic = rSrcSet.Get( ATTR_FONT_POSTURE ).GetValue();
800 eCjkItalic = rSrcSet.Get( ATTR_CJK_FONT_POSTURE ).GetValue();
801 eCtlItalic = rSrcSet.Get( ATTR_CTL_FONT_POSTURE ).GetValue();
802 aUnderlineItem.reset(rSrcSet.Get(ATTR_FONT_UNDERLINE).Clone());
803 aOverlineItem.reset(rSrcSet.Get(ATTR_FONT_OVERLINE).Clone());
804 bWordLine = rSrcSet.Get( ATTR_FONT_WORDLINE ).GetValue();
805 eStrike = rSrcSet.Get( ATTR_FONT_CROSSEDOUT ).GetValue();
806 bOutline = rSrcSet.Get( ATTR_FONT_CONTOUR ).GetValue();
807 bShadow = rSrcSet.Get( ATTR_FONT_SHADOWED ).GetValue();
808 bForbidden = rSrcSet.Get( ATTR_FORBIDDEN_RULES ).GetValue();
809 eEmphasis = rSrcSet.Get( ATTR_FONT_EMPHASISMARK ).GetEmphasisMark();
810 eRelief = rSrcSet.Get( ATTR_FONT_RELIEF ).GetValue();
811 eLang = rSrcSet.Get( ATTR_FONT_LANGUAGE ).GetLanguage();
812 eCjkLang = rSrcSet.Get( ATTR_CJK_FONT_LANGUAGE ).GetLanguage();
813 eCtlLang = rSrcSet.Get( ATTR_CTL_FONT_LANGUAGE ).GetLanguage();
814 bHyphenate = rSrcSet.Get( ATTR_HYPHENATE ).GetValue();
815 eDirection = rSrcSet.Get( ATTR_WRITINGDIR ).GetValue();
818 // Expect to be compatible to LogicToLogic, ie. 2540/1440 = 127/72, and round
820 tools::Long nHeight = convertTwipToMm100(nTHeight);
821 tools::Long nCjkHeight = convertTwipToMm100(nCjkTHeight);
822 tools::Long nCtlHeight = convertTwipToMm100(nCtlTHeight);
824 // put items into EditEngine ItemSet
826 if ( aColorItem->GetValue() == COL_AUTO )
828 // When cell attributes are converted to EditEngine paragraph attributes,
829 // don't create a hard item for automatic color, because that would be converted
830 // to black when the item's Store method is used in CreateTransferable/WriteBin.
831 // COL_AUTO is the EditEngine's pool default, so ClearItem will result in automatic
832 // color, too, without having to store the item.
833 rEditSet.ClearItem( EE_CHAR_COLOR );
835 else
837 // tdf#125054 adapt WhichID
838 rEditSet.Put( std::move(aColorItem), EE_CHAR_COLOR );
841 // tdf#125054 adapt WhichID
842 rEditSet.Put( std::move(aFontItem), EE_CHAR_FONTINFO );
843 rEditSet.Put( std::move(aCjkFontItem), EE_CHAR_FONTINFO_CJK );
844 rEditSet.Put( std::move(aCtlFontItem), EE_CHAR_FONTINFO_CTL );
846 rEditSet.Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) );
847 rEditSet.Put( SvxFontHeightItem( nCjkHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) );
848 rEditSet.Put( SvxFontHeightItem( nCtlHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) );
849 rEditSet.Put( SvxWeightItem ( eWeight, EE_CHAR_WEIGHT ) );
850 rEditSet.Put( SvxWeightItem ( eCjkWeight, EE_CHAR_WEIGHT_CJK ) );
851 rEditSet.Put( SvxWeightItem ( eCtlWeight, EE_CHAR_WEIGHT_CTL ) );
853 // tdf#125054 adapt WhichID
854 rEditSet.Put( std::move(aUnderlineItem), EE_CHAR_UNDERLINE );
855 rEditSet.Put( std::move(aOverlineItem), EE_CHAR_OVERLINE );
857 rEditSet.Put( SvxWordLineModeItem( bWordLine, EE_CHAR_WLM ) );
858 rEditSet.Put( SvxCrossedOutItem( eStrike, EE_CHAR_STRIKEOUT ) );
859 rEditSet.Put( SvxPostureItem ( eItalic, EE_CHAR_ITALIC ) );
860 rEditSet.Put( SvxPostureItem ( eCjkItalic, EE_CHAR_ITALIC_CJK ) );
861 rEditSet.Put( SvxPostureItem ( eCtlItalic, EE_CHAR_ITALIC_CTL ) );
862 rEditSet.Put( SvxContourItem ( bOutline, EE_CHAR_OUTLINE ) );
863 rEditSet.Put( SvxShadowedItem ( bShadow, EE_CHAR_SHADOW ) );
864 rEditSet.Put( SvxForbiddenRuleItem(bForbidden, EE_PARA_FORBIDDENRULES) );
865 rEditSet.Put( SvxEmphasisMarkItem( eEmphasis, EE_CHAR_EMPHASISMARK ) );
866 rEditSet.Put( SvxCharReliefItem( eRelief, EE_CHAR_RELIEF ) );
867 rEditSet.Put( SvxLanguageItem ( eLang, EE_CHAR_LANGUAGE ) );
868 rEditSet.Put( SvxLanguageItem ( eCjkLang, EE_CHAR_LANGUAGE_CJK ) );
869 rEditSet.Put( SvxLanguageItem ( eCtlLang, EE_CHAR_LANGUAGE_CTL ) );
870 rEditSet.Put( SfxBoolItem ( EE_PARA_HYPHENATE, bHyphenate ) );
871 rEditSet.Put( SvxFrameDirectionItem( eDirection, EE_PARA_WRITINGDIR ) );
873 // Script spacing is always off.
874 // The cell attribute isn't used here as long as there is no UI to set it
875 // (don't evaluate attributes that can't be changed).
876 // If a locale-dependent default is needed, it has to go into the cell
877 // style, like the fonts.
878 rEditSet.Put( SvxScriptSpaceItem( false, EE_PARA_ASIANCJKSPACING ) );
881 void ScPatternAttr::FillEditItemSet( SfxItemSet* pEditSet, const SfxItemSet* pCondSet ) const
883 if( pEditSet )
884 FillToEditItemSet( *pEditSet, GetItemSet(), pCondSet );
887 void ScPatternAttr::GetFromEditItemSet( SfxItemSet& rDestSet, const SfxItemSet& rEditSet )
889 if (const SvxColorItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_COLOR))
890 rDestSet.Put( *pItem, ATTR_FONT_COLOR );
892 if (const SvxFontItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_FONTINFO))
893 rDestSet.Put( *pItem, ATTR_FONT );
894 if (const SvxFontItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_FONTINFO_CJK))
895 rDestSet.Put( *pItem, ATTR_CJK_FONT );
896 if (const SvxFontItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_FONTINFO_CTL))
897 rDestSet.Put( *pItem, ATTR_CTL_FONT );
899 if (const SvxFontHeightItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_FONTHEIGHT))
900 rDestSet.Put( SvxFontHeightItem(o3tl::toTwips(pItem->GetHeight(), o3tl::Length::mm100),
901 100, ATTR_FONT_HEIGHT ) );
902 if (const SvxFontHeightItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_FONTHEIGHT_CJK))
903 rDestSet.Put( SvxFontHeightItem(o3tl::toTwips(pItem->GetHeight(), o3tl::Length::mm100),
904 100, ATTR_CJK_FONT_HEIGHT ) );
905 if (const SvxFontHeightItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_FONTHEIGHT_CTL))
906 rDestSet.Put( SvxFontHeightItem(o3tl::toTwips(pItem->GetHeight(), o3tl::Length::mm100),
907 100, ATTR_CTL_FONT_HEIGHT ) );
909 if (const SvxWeightItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_WEIGHT))
910 rDestSet.Put( SvxWeightItem( pItem->GetValue(),
911 ATTR_FONT_WEIGHT) );
912 if (const SvxWeightItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_WEIGHT_CJK))
913 rDestSet.Put( SvxWeightItem( pItem->GetValue(),
914 ATTR_CJK_FONT_WEIGHT) );
915 if (const SvxWeightItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_WEIGHT_CTL))
916 rDestSet.Put( SvxWeightItem( pItem->GetValue(),
917 ATTR_CTL_FONT_WEIGHT) );
919 // SvxTextLineItem contains enum and color
920 if (const SvxUnderlineItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_UNDERLINE))
921 rDestSet.Put( *pItem, ATTR_FONT_UNDERLINE );
922 if (const SvxOverlineItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_OVERLINE))
923 rDestSet.Put( *pItem, ATTR_FONT_OVERLINE );
924 if (const SvxWordLineModeItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_WLM))
925 rDestSet.Put( SvxWordLineModeItem( pItem->GetValue(),
926 ATTR_FONT_WORDLINE) );
928 if (const SvxCrossedOutItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_STRIKEOUT))
929 rDestSet.Put( SvxCrossedOutItem( pItem->GetValue(),
930 ATTR_FONT_CROSSEDOUT) );
932 if (const SvxPostureItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_ITALIC))
933 rDestSet.Put( SvxPostureItem( pItem->GetValue(),
934 ATTR_FONT_POSTURE) );
935 if (const SvxPostureItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_ITALIC_CJK))
936 rDestSet.Put( SvxPostureItem( pItem->GetValue(),
937 ATTR_CJK_FONT_POSTURE) );
938 if (const SvxPostureItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_ITALIC_CTL))
939 rDestSet.Put( SvxPostureItem( pItem->GetValue(),
940 ATTR_CTL_FONT_POSTURE) );
942 if (const SvxContourItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_OUTLINE))
943 rDestSet.Put( SvxContourItem( pItem->GetValue(),
944 ATTR_FONT_CONTOUR) );
945 if (const SvxShadowedItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_SHADOW))
946 rDestSet.Put( SvxShadowedItem( pItem->GetValue(),
947 ATTR_FONT_SHADOWED) );
948 if (const SvxEmphasisMarkItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_EMPHASISMARK))
949 rDestSet.Put( SvxEmphasisMarkItem( pItem->GetEmphasisMark(),
950 ATTR_FONT_EMPHASISMARK) );
951 if (const SvxCharReliefItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_RELIEF))
952 rDestSet.Put( SvxCharReliefItem( pItem->GetValue(),
953 ATTR_FONT_RELIEF) );
955 if (const SvxLanguageItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_LANGUAGE))
956 rDestSet.Put( SvxLanguageItem(pItem->GetValue(), ATTR_FONT_LANGUAGE) );
957 if (const SvxLanguageItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_LANGUAGE_CJK))
958 rDestSet.Put( SvxLanguageItem(pItem->GetValue(), ATTR_CJK_FONT_LANGUAGE) );
959 if (const SvxLanguageItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_LANGUAGE_CTL))
960 rDestSet.Put( SvxLanguageItem(pItem->GetValue(), ATTR_CTL_FONT_LANGUAGE) );
962 const SvxAdjustItem* pAdjustItem = rEditSet.GetItemIfSet(EE_PARA_JUST);
964 if (!pAdjustItem)
965 return;
967 SvxCellHorJustify eVal;
968 switch ( pAdjustItem->GetAdjust() )
970 case SvxAdjust::Left:
971 // EditEngine Default is always set in the GetAttribs() ItemSet !
972 // whether left or right, is decided in text / number
973 eVal = SvxCellHorJustify::Standard;
974 break;
975 case SvxAdjust::Right:
976 eVal = SvxCellHorJustify::Right;
977 break;
978 case SvxAdjust::Block:
979 eVal = SvxCellHorJustify::Block;
980 break;
981 case SvxAdjust::Center:
982 eVal = SvxCellHorJustify::Center;
983 break;
984 case SvxAdjust::BlockLine:
985 eVal = SvxCellHorJustify::Block;
986 break;
987 case SvxAdjust::End:
988 eVal = SvxCellHorJustify::Right;
989 break;
990 default:
991 eVal = SvxCellHorJustify::Standard;
993 if ( eVal != SvxCellHorJustify::Standard )
994 rDestSet.Put( SvxHorJustifyItem( eVal, ATTR_HOR_JUSTIFY) );
997 void ScPatternAttr::GetFromEditItemSet( const SfxItemSet* pEditSet )
999 if( !pEditSet )
1000 return;
1001 GetFromEditItemSet( GetItemSet(), *pEditSet );
1002 mxVisible.reset();
1005 void ScPatternAttr::FillEditParaItems( SfxItemSet* pEditSet ) const
1007 // already there in GetFromEditItemSet, but not in FillEditItemSet
1008 // Default horizontal alignment is always implemented as left
1010 const SfxItemSet& rMySet = GetItemSet();
1012 SvxCellHorJustify eHorJust = rMySet.Get(ATTR_HOR_JUSTIFY).GetValue();
1014 SvxAdjust eSvxAdjust;
1015 switch (eHorJust)
1017 case SvxCellHorJustify::Right: eSvxAdjust = SvxAdjust::Right; break;
1018 case SvxCellHorJustify::Center: eSvxAdjust = SvxAdjust::Center; break;
1019 case SvxCellHorJustify::Block: eSvxAdjust = SvxAdjust::Block; break;
1020 default: eSvxAdjust = SvxAdjust::Left; break;
1022 pEditSet->Put( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) );
1025 void ScPatternAttr::DeleteUnchanged( const ScPatternAttr* pOldAttrs )
1027 SfxItemSet& rThisSet = GetItemSet();
1028 const SfxItemSet& rOldSet = pOldAttrs->GetItemSet();
1030 const SfxPoolItem* pThisItem;
1031 const SfxPoolItem* pOldItem;
1033 for ( sal_uInt16 nSubWhich=ATTR_PATTERN_START; nSubWhich<=ATTR_PATTERN_END; nSubWhich++ )
1035 // only items that are set are interesting
1036 if ( rThisSet.GetItemState( nSubWhich, false, &pThisItem ) == SfxItemState::SET )
1038 SfxItemState eOldState = rOldSet.GetItemState( nSubWhich, true, &pOldItem );
1039 if ( eOldState == SfxItemState::SET )
1041 // item is set in OldAttrs (or its parent) -> compare pointers
1042 if (SfxPoolItem::areSame( pThisItem, pOldItem ))
1044 rThisSet.ClearItem( nSubWhich );
1045 mxVisible.reset();
1048 else if ( eOldState != SfxItemState::DONTCARE )
1050 // not set in OldAttrs -> compare item value to default item
1051 if ( *pThisItem == rThisSet.GetPool()->GetDefaultItem( nSubWhich ) )
1053 rThisSet.ClearItem( nSubWhich );
1054 mxVisible.reset();
1061 bool ScPatternAttr::HasItemsSet( const sal_uInt16* pWhich ) const
1063 const SfxItemSet& rSet = GetItemSet();
1064 for (sal_uInt16 i=0; pWhich[i]; i++)
1065 if ( rSet.GetItemState( pWhich[i], false ) == SfxItemState::SET )
1066 return true;
1067 return false;
1070 void ScPatternAttr::ClearItems( const sal_uInt16* pWhich )
1072 SfxItemSet& rSet = GetItemSet();
1073 for (sal_uInt16 i=0; pWhich[i]; i++)
1074 rSet.ClearItem(pWhich[i]);
1075 mxVisible.reset();
1078 static SfxStyleSheetBase* lcl_CopyStyleToPool
1080 SfxStyleSheetBase* pSrcStyle,
1081 SfxStyleSheetBasePool* pSrcPool,
1082 SfxStyleSheetBasePool* pDestPool,
1083 const SvNumberFormatterIndexTable* pFormatExchangeList
1086 if ( !pSrcStyle || !pDestPool || !pSrcPool )
1088 OSL_FAIL( "CopyStyleToPool: Invalid Arguments :-/" );
1089 return nullptr;
1092 const OUString aStrSrcStyle = pSrcStyle->GetName();
1093 const SfxStyleFamily eFamily = pSrcStyle->GetFamily();
1094 SfxStyleSheetBase* pDestStyle = pDestPool->Find( aStrSrcStyle, eFamily );
1096 if ( !pDestStyle )
1098 const OUString aStrParent = pSrcStyle->GetParent();
1099 const SfxItemSet& rSrcSet = pSrcStyle->GetItemSet();
1101 pDestStyle = &pDestPool->Make( aStrSrcStyle, eFamily, SfxStyleSearchBits::UserDefined );
1102 SfxItemSet& rDestSet = pDestStyle->GetItemSet();
1103 rDestSet.Put( rSrcSet );
1105 // number format exchange list has to be handled here, too
1106 // (only called for cell styles)
1108 const SfxUInt32Item* pSrcItem;
1109 if ( pFormatExchangeList &&
1110 (pSrcItem = rSrcSet.GetItemIfSet( ATTR_VALUE_FORMAT, false )) )
1112 sal_uInt32 nOldFormat = pSrcItem->GetValue();
1113 SvNumberFormatterIndexTable::const_iterator it = pFormatExchangeList->find(nOldFormat);
1114 if (it != pFormatExchangeList->end())
1116 sal_uInt32 nNewFormat = it->second;
1117 rDestSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat ) );
1121 // if necessary create derivative Styles, if not available:
1123 if ( ScResId(STR_STYLENAME_STANDARD) != aStrParent &&
1124 aStrSrcStyle != aStrParent &&
1125 !pDestPool->Find( aStrParent, eFamily ) )
1127 lcl_CopyStyleToPool( pSrcPool->Find( aStrParent, eFamily ),
1128 pSrcPool, pDestPool, pFormatExchangeList );
1131 pDestStyle->SetParent( aStrParent );
1134 return pDestStyle;
1137 ScPatternAttr* ScPatternAttr::PutInPool( ScDocument* pDestDoc, ScDocument* pSrcDoc ) const
1139 const SfxItemSet* pSrcSet = &GetItemSet();
1141 ScPatternAttr aDestPattern( pDestDoc->GetPool() );
1142 SfxItemSet* pDestSet = &aDestPattern.GetItemSet();
1144 // Copy cell pattern style to other document:
1146 if ( pDestDoc != pSrcDoc )
1148 OSL_ENSURE( pStyle, "Missing Pattern-Style! :-/" );
1150 // if pattern in DestDoc is available, use this, otherwise copy
1151 // parent style to style or create if necessary and attach DestDoc
1153 SfxStyleSheetBase* pStyleCpy = lcl_CopyStyleToPool( pStyle,
1154 pSrcDoc->GetStyleSheetPool(),
1155 pDestDoc->GetStyleSheetPool(),
1156 pDestDoc->GetFormatExchangeList() );
1158 aDestPattern.SetStyleSheet( static_cast<ScStyleSheet*>(pStyleCpy) );
1161 for ( sal_uInt16 nAttrId = ATTR_PATTERN_START; nAttrId <= ATTR_PATTERN_END; nAttrId++ )
1163 const SfxPoolItem* pSrcItem;
1164 SfxItemState eItemState = pSrcSet->GetItemState( nAttrId, false, &pSrcItem );
1165 if (eItemState==SfxItemState::SET)
1167 std::unique_ptr<SfxPoolItem> pNewItem;
1169 if ( nAttrId == ATTR_VALIDDATA )
1171 // Copy validity to the new document
1173 sal_uInt32 nNewIndex = 0;
1174 ScValidationDataList* pSrcList = pSrcDoc->GetValidationList();
1175 if ( pSrcList )
1177 sal_uInt32 nOldIndex = static_cast<const SfxUInt32Item*>(pSrcItem)->GetValue();
1178 const ScValidationData* pOldData = pSrcList->GetData( nOldIndex );
1179 if ( pOldData )
1180 nNewIndex = pDestDoc->AddValidationEntry( *pOldData );
1182 pNewItem.reset(new SfxUInt32Item( ATTR_VALIDDATA, nNewIndex ));
1184 else if ( nAttrId == ATTR_VALUE_FORMAT && pDestDoc->GetFormatExchangeList() )
1186 // Number format to Exchange List
1188 sal_uInt32 nOldFormat = static_cast<const SfxUInt32Item*>(pSrcItem)->GetValue();
1189 SvNumberFormatterIndexTable::const_iterator it = pDestDoc->GetFormatExchangeList()->find(nOldFormat);
1190 if (it != pDestDoc->GetFormatExchangeList()->end())
1192 sal_uInt32 nNewFormat = it->second;
1193 pNewItem.reset(new SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat ));
1197 if ( pNewItem )
1199 pDestSet->Put(std::move(pNewItem));
1201 else
1202 pDestSet->Put(*pSrcItem);
1206 ScPatternAttr* pPatternAttr = const_cast<ScPatternAttr*>( &pDestDoc->GetPool()->DirectPutItemInPool(aDestPattern) );
1207 return pPatternAttr;
1210 bool ScPatternAttr::IsVisible() const
1212 if (!mxVisible.has_value())
1213 mxVisible = CalcVisible();
1214 return *mxVisible;
1217 bool ScPatternAttr::CalcVisible() const
1219 const SfxItemSet& rSet = GetItemSet();
1221 if ( const SvxBrushItem* pItem = rSet.GetItemIfSet( ATTR_BACKGROUND ) )
1222 if ( pItem->GetColor() != COL_TRANSPARENT )
1223 return true;
1225 if ( const SvxBoxItem* pBoxItem = rSet.GetItemIfSet( ATTR_BORDER ) )
1227 if ( pBoxItem->GetTop() || pBoxItem->GetBottom() ||
1228 pBoxItem->GetLeft() || pBoxItem->GetRight() )
1229 return true;
1232 if ( const SvxLineItem* pItem = rSet.GetItemIfSet( ATTR_BORDER_TLBR ) )
1233 if( pItem->GetLine() )
1234 return true;
1236 if ( const SvxLineItem* pItem = rSet.GetItemIfSet( ATTR_BORDER_BLTR ) )
1237 if( pItem->GetLine() )
1238 return true;
1240 if ( const SvxShadowItem* pItem = rSet.GetItemIfSet( ATTR_SHADOW ) )
1241 if ( pItem->GetLocation() != SvxShadowLocation::NONE )
1242 return true;
1244 return false;
1247 bool ScPatternAttr::IsVisibleEqual( const ScPatternAttr& rOther ) const
1249 // This method is hot, so we do an optimised comparison here, by
1250 // walking the two itemsets in parallel, avoiding doing repeated searches.
1251 auto IsInterestingWhich = [](sal_uInt16 n)
1253 return n == ATTR_BORDER_TLBR || n == ATTR_BORDER_BLTR || n == ATTR_BACKGROUND
1254 || n == ATTR_BORDER || n == ATTR_SHADOW;
1256 SfxWhichIter aIter1(GetItemSet());
1257 SfxWhichIter aIter2(rOther.GetItemSet());
1258 sal_uInt16 nWhich1 = aIter1.FirstWhich();
1259 sal_uInt16 nWhich2 = aIter2.FirstWhich();
1260 for (;;)
1262 while (nWhich1 != nWhich2)
1264 SfxWhichIter* pIterToIncrement;
1265 sal_uInt16* pSmallerWhich;
1266 if (nWhich1 == 0 || nWhich1 > nWhich2)
1268 pSmallerWhich = &nWhich2;
1269 pIterToIncrement = &aIter2;
1271 else
1273 pSmallerWhich = &nWhich1;
1274 pIterToIncrement = &aIter1;
1277 if (IsInterestingWhich(*pSmallerWhich))
1279 // the iter with larger which has already passed this point, and has no interesting
1280 // item available in the other - so indeed these are unequal
1281 return false;
1284 *pSmallerWhich = pIterToIncrement->NextWhich();
1287 // Here nWhich1 == nWhich2
1289 if (!nWhich1 /* && !nWhich2*/)
1290 return true;
1292 if (IsInterestingWhich(nWhich1))
1294 const SfxPoolItem* pItem1 = nullptr;
1295 const SfxPoolItem* pItem2 = nullptr;
1296 SfxItemState state1 = aIter1.GetItemState(true, &pItem1);
1297 SfxItemState state2 = aIter2.GetItemState(true, &pItem2);
1298 if (state1 != state2
1299 && (state1 < SfxItemState::DEFAULT || state2 < SfxItemState::DEFAULT))
1300 return false;
1301 if (!SfxPoolItem::areSame(pItem1, pItem2))
1302 return false;
1304 nWhich1 = aIter1.NextWhich();
1305 nWhich2 = aIter2.NextWhich();
1307 //TODO: also here only check really visible values !!!
1310 const OUString* ScPatternAttr::GetStyleName() const
1312 return pName ? &*pName : ( pStyle ? &pStyle->GetName() : nullptr );
1315 void ScPatternAttr::SetStyleSheet( ScStyleSheet* pNewStyle, bool bClearDirectFormat )
1317 if (pNewStyle)
1319 SfxItemSet& rPatternSet = GetItemSet();
1320 const SfxItemSet& rStyleSet = pNewStyle->GetItemSet();
1322 if (bClearDirectFormat)
1324 for (sal_uInt16 i=ATTR_PATTERN_START; i<=ATTR_PATTERN_END; i++)
1326 if (rStyleSet.GetItemState(i) == SfxItemState::SET)
1327 rPatternSet.ClearItem(i);
1330 rPatternSet.SetParent(&pNewStyle->GetItemSet());
1331 pStyle = pNewStyle;
1332 pName.reset();
1334 else
1336 OSL_FAIL( "ScPatternAttr::SetStyleSheet( NULL ) :-|" );
1337 GetItemSet().SetParent(nullptr);
1338 pStyle = nullptr;
1340 mxVisible.reset();
1343 void ScPatternAttr::UpdateStyleSheet(const ScDocument& rDoc)
1345 if (pName)
1347 pStyle = static_cast<ScStyleSheet*>(rDoc.GetStyleSheetPool()->Find(*pName, SfxStyleFamily::Para));
1349 // use Standard if Style is not found,
1350 // to avoid empty display in Toolbox-Controller
1351 // Assumes that "Standard" is always the 1st entry!
1352 if (!pStyle)
1354 std::unique_ptr<SfxStyleSheetIterator> pIter = rDoc.GetStyleSheetPool()->CreateIterator(SfxStyleFamily::Para);
1355 pStyle = dynamic_cast< ScStyleSheet* >(pIter->First());
1358 if (pStyle)
1360 GetItemSet().SetParent(&pStyle->GetItemSet());
1361 pName.reset();
1364 else
1365 pStyle = nullptr;
1366 mxVisible.reset();
1369 void ScPatternAttr::StyleToName()
1371 // Style was deleted, remember name:
1373 if ( pStyle )
1375 pName = pStyle->GetName();
1376 pStyle = nullptr;
1377 GetItemSet().SetParent( nullptr );
1378 mxVisible.reset();
1382 bool ScPatternAttr::IsSymbolFont() const
1384 if( const SvxFontItem* pItem = GetItemSet().GetItemIfSet( ATTR_FONT ) )
1385 return pItem->GetCharSet() == RTL_TEXTENCODING_SYMBOL;
1386 else
1387 return false;
1390 namespace {
1392 sal_uInt32 getNumberFormatKey(const SfxItemSet& rSet)
1394 return rSet.Get(ATTR_VALUE_FORMAT).GetValue();
1397 LanguageType getLanguageType(const SfxItemSet& rSet)
1399 return rSet.Get(ATTR_LANGUAGE_FORMAT).GetLanguage();
1404 sal_uInt32 ScPatternAttr::GetNumberFormat( SvNumberFormatter* pFormatter ) const
1406 sal_uInt32 nFormat = getNumberFormatKey(GetItemSet());
1407 LanguageType eLang = getLanguageType(GetItemSet());
1408 if ( nFormat < SV_COUNTRY_LANGUAGE_OFFSET && eLang == LANGUAGE_SYSTEM )
1409 ; // it remains as it is
1410 else if ( pFormatter )
1411 nFormat = pFormatter->GetFormatForLanguageIfBuiltIn( nFormat, eLang );
1412 return nFormat;
1415 sal_uInt32 ScPatternAttr::GetNumberFormat( const ScInterpreterContext& rContext ) const
1417 sal_uInt32 nFormat = getNumberFormatKey(GetItemSet());
1418 LanguageType eLang = getLanguageType(GetItemSet());
1419 if ( nFormat < SV_COUNTRY_LANGUAGE_OFFSET && eLang == LANGUAGE_SYSTEM )
1420 ; // it remains as it is
1421 else
1422 nFormat = rContext.GetFormatForLanguageIfBuiltIn( nFormat, eLang );
1423 return nFormat;
1426 // the same if conditional formatting is in play:
1428 sal_uInt32 ScPatternAttr::GetNumberFormat( SvNumberFormatter* pFormatter,
1429 const SfxItemSet* pCondSet ) const
1431 assert(pFormatter);
1432 if (!pCondSet)
1433 return GetNumberFormat(pFormatter);
1435 // Conditional format takes precedence over style and even hard format.
1437 sal_uInt32 nFormat;
1438 LanguageType eLang;
1439 if (pCondSet->GetItemState(ATTR_VALUE_FORMAT) == SfxItemState::SET )
1441 nFormat = getNumberFormatKey(*pCondSet);
1442 if (pCondSet->GetItemState(ATTR_LANGUAGE_FORMAT) == SfxItemState::SET)
1443 eLang = getLanguageType(*pCondSet);
1444 else
1445 eLang = getLanguageType(GetItemSet());
1447 else
1449 nFormat = getNumberFormatKey(GetItemSet());
1450 eLang = getLanguageType(GetItemSet());
1453 return pFormatter->GetFormatForLanguageIfBuiltIn(nFormat, eLang);
1456 const SfxPoolItem& ScPatternAttr::GetItem( sal_uInt16 nWhich, const SfxItemSet& rItemSet, const SfxItemSet* pCondSet )
1458 const SfxPoolItem* pCondItem;
1459 if ( pCondSet && pCondSet->GetItemState( nWhich, true, &pCondItem ) == SfxItemState::SET )
1460 return *pCondItem;
1461 return rItemSet.Get(nWhich);
1464 const SfxPoolItem& ScPatternAttr::GetItem( sal_uInt16 nSubWhich, const SfxItemSet* pCondSet ) const
1466 return GetItem( nSubWhich, GetItemSet(), pCondSet );
1469 // GetRotateVal is tested before ATTR_ORIENTATION
1471 Degree100 ScPatternAttr::GetRotateVal( const SfxItemSet* pCondSet ) const
1473 Degree100 nAttrRotate(0);
1474 if ( GetCellOrientation() == SvxCellOrientation::Standard )
1476 bool bRepeat = ( GetItem(ATTR_HOR_JUSTIFY, pCondSet).
1477 GetValue() == SvxCellHorJustify::Repeat );
1478 // ignore orientation/rotation if "repeat" is active
1479 if ( !bRepeat )
1480 nAttrRotate = GetItem( ATTR_ROTATE_VALUE, pCondSet ).GetValue();
1482 return nAttrRotate;
1485 ScRotateDir ScPatternAttr::GetRotateDir( const SfxItemSet* pCondSet ) const
1487 ScRotateDir nRet = ScRotateDir::NONE;
1489 Degree100 nAttrRotate = GetRotateVal( pCondSet );
1490 if ( nAttrRotate )
1492 SvxRotateMode eRotMode = GetItem(ATTR_ROTATE_MODE, pCondSet).GetValue();
1494 if ( eRotMode == SVX_ROTATE_MODE_STANDARD || nAttrRotate == 18000_deg100 )
1495 nRet = ScRotateDir::Standard;
1496 else if ( eRotMode == SVX_ROTATE_MODE_CENTER )
1497 nRet = ScRotateDir::Center;
1498 else if ( eRotMode == SVX_ROTATE_MODE_TOP || eRotMode == SVX_ROTATE_MODE_BOTTOM )
1500 Degree100 nRot180 = nAttrRotate % 18000_deg100; // 1/100 degrees
1501 if ( nRot180 == 9000_deg100 )
1502 nRet = ScRotateDir::Center;
1503 else if ( ( eRotMode == SVX_ROTATE_MODE_TOP && nRot180 < 9000_deg100 ) ||
1504 ( eRotMode == SVX_ROTATE_MODE_BOTTOM && nRot180 > 9000_deg100 ) )
1505 nRet = ScRotateDir::Left;
1506 else
1507 nRet = ScRotateDir::Right;
1511 return nRet;
1514 void ScPatternAttr::SetPAKey(sal_uInt64 nKey)
1516 mnPAKey = nKey;
1519 sal_uInt64 ScPatternAttr::GetPAKey() const
1521 return mnPAKey;
1524 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */