xref: /core/svx/source/sidebar/nbdtmg.cxx (revision c4e3658169d08180f74d56788c6b53d13a90ba07)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 #include <svx/nbdtmg.hxx>
20 #include <svx/svxids.hrc>
21 #include <vcl/svapp.hxx>
22 #include <svl/itemset.hxx>
23 #include <sfx2/request.hxx>
24 #include <svl/stritem.hxx>
25 #include <svtools/ctrltool.hxx>
26 #include <sfx2/objsh.hxx>
27 #include <editeng/flstitem.hxx>
28 #include <svl/itempool.hxx>
29 #include <vcl/outdev.hxx>
30 #include <editeng/brushitem.hxx>
31 #include <svx/dialmgr.hxx>
32 #include <svx/strings.hrc>
33 #include <vcl/graph.hxx>
34 #include <vcl/settings.hxx>
35 
36 #include <i18nlangtag/languagetag.hxx>
37 #include <o3tl/temporary.hxx>
38 #include <tools/debug.hxx>
39 #include <tools/urlobj.hxx>
40 #include <unotools/ucbstreamhelper.hxx>
41 #include <unotools/pathoptions.hxx>
42 #include <editeng/eeitem.hxx>
43 #include <officecfg/Office/Common.hxx>
44 
45 #include <com/sun/star/text/VertOrientation.hpp>
46 #include <com/sun/star/style/NumberingType.hpp>
47 #include <com/sun/star/container/XIndexAccess.hpp>
48 #include <com/sun/star/text/DefaultNumberingProvider.hpp>
49 #include <com/sun/star/beans/PropertyValue.hpp>
50 #include <comphelper/processfactory.hxx>
51 #include <memory>
52 
53 using namespace com::sun::star;
54 using namespace com::sun::star::uno;
55 using namespace com::sun::star::beans;
56 using namespace com::sun::star::lang;
57 using namespace com::sun::star::text;
58 using namespace com::sun::star::container;
59 
60 namespace svx::sidebar {
61 
62 namespace {
63 
lcl_GetDefaultBulletFont()64 vcl::Font& lcl_GetDefaultBulletFont()
65 {
66     static vcl::Font aDefBulletFont = []()
67     {
68         static vcl::Font tmp(u"OpenSymbol"_ustr, u""_ustr, Size(0, 14));
69         tmp.SetCharSet( RTL_TEXTENCODING_SYMBOL );
70         tmp.SetFamily( FAMILY_DONTKNOW );
71         tmp.SetPitch( PITCH_DONTKNOW );
72         tmp.SetWeight( WEIGHT_DONTKNOW );
73         tmp.SetTransparent( true );
74         return tmp;
75     }();
76     return aDefBulletFont;
77 }
78 
lcl_CreateNumberingSettingsPtr(const Sequence<PropertyValue> & rLevelProps)79 NumSettings_Impl* lcl_CreateNumberingSettingsPtr(const Sequence<PropertyValue>& rLevelProps)
80 {
81     NumSettings_Impl* pNew = new NumSettings_Impl;
82     for(const PropertyValue& rValue : rLevelProps)
83     {
84         if(rValue.Name == "NumberingType")
85         {
86             sal_Int16 nTmp;
87             if (rValue.Value >>= nTmp)
88                 pNew->nNumberType = static_cast<SvxNumType>(nTmp);
89         }
90         else if(rValue.Name == "Prefix")
91             rValue.Value >>= pNew->sPrefix;
92         else if(rValue.Name == "Suffix")
93             rValue.Value >>= pNew->sSuffix;
94         else if (rValue.Name == "Adjust")
95         {
96             sal_Int16 nTmp;
97             if (rValue.Value >>= nTmp)
98                 pNew->eNumAlign = static_cast<SvxAdjust>(nTmp);
99         }
100         else if(rValue.Name == "ParentNumbering")
101             rValue.Value >>= pNew->nParentNumbering;
102         else if(rValue.Name == "BulletChar")
103             rValue.Value >>= pNew->sBulletChar;
104         else if(rValue.Name == "BulletFontName")
105             rValue.Value >>= pNew->sBulletFont;
106     }
107     const sal_Unicode cLocalPrefix = pNew->sPrefix.getLength() ? pNew->sPrefix[0] : 0;
108     const sal_Unicode cLocalSuffix = pNew->sSuffix.getLength() ? pNew->sSuffix[0] : 0;
109     if( cLocalPrefix == ' ') pNew->sPrefix.clear();
110     if( cLocalSuffix == ' ') pNew->sSuffix.clear();
111     return pNew;
112 }
113 
114 }
115 
IsSingleLevel(sal_uInt16 nCurLevel)116 sal_uInt16 NBOTypeMgrBase:: IsSingleLevel(sal_uInt16 nCurLevel)
117 {
118     sal_uInt16 nLv = sal_uInt16(0xFFFF);
119     sal_uInt16 nCount = 0;
120     sal_uInt16 nMask = 1;
121     for( sal_uInt16 i = 0; i < SVX_MAX_NUM; i++ )
122     {
123         if(nCurLevel & nMask)
124         {
125             nCount++;
126             nLv=i;
127         }
128         nMask <<= 1 ;
129     }
130 
131     if ( nCount == 1)
132         return nLv;
133     else
134         return sal_uInt16(0xFFFF);
135 }
136 
SetItems(const SfxItemSet * pArg)137 void NBOTypeMgrBase::SetItems(const SfxItemSet* pArg) {
138     pSet = pArg;
139     if ( !pSet )
140         return;
141 
142     SfxAllItemSet aSet(*pSet);
143 
144     const SfxStringItem* pBulletCharFmt = aSet.GetItem<SfxStringItem>(SID_BULLET_CHAR_FMT, false);
145     if (pBulletCharFmt)
146         aBulletCharFmtName = pBulletCharFmt->GetValue();
147 
148     const SfxStringItem* pNumCharFmt = aSet.GetItem<SfxStringItem>(SID_NUM_CHAR_FMT, false);
149     if (pNumCharFmt)
150         aNumCharFmtName = pNumCharFmt->GetValue();
151 
152     const SfxPoolItem* pItem;
153     SfxItemState eState = pSet->GetItemState(SID_ATTR_NUMBERING_RULE, false, &pItem);
154     if(eState == SfxItemState::SET)
155     {
156         eCoreUnit = pSet->GetPool()->GetMetric(pSet->GetPool()->GetWhichIDFromSlotID(SID_ATTR_NUMBERING_RULE));
157     } else {
158         //sd use different sid for numbering rule
159         eState = pSet->GetItemState(EE_PARA_NUMBULLET, false, &pItem);
160         if(eState == SfxItemState::SET)
161         {
162             eCoreUnit = pSet->GetPool()->GetMetric(pSet->GetPool()->GetWhichIDFromSlotID(EE_PARA_NUMBULLET));
163         }
164     }
165 }
166 
ImplLoad(std::u16string_view filename)167 void NBOTypeMgrBase::ImplLoad(std::u16string_view filename)
168 {
169     bIsLoading = true;
170     MapUnit      eOldCoreUnit=eCoreUnit;
171     eCoreUnit = MapUnit::Map100thMM;
172     INetURLObject aFile( SvtPathOptions().GetUserConfigPath() );
173     aFile.Append( filename);
174     std::unique_ptr<SvStream> xIStm(::utl::UcbStreamHelper::CreateStream( aFile.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::READ ));
175     if( xIStm ) {
176         sal_uInt32                  nVersion = 0;
177         sal_Int32                   nNumIndex = 0;
178         xIStm->ReadUInt32( nVersion );
179         if (nVersion==DEFAULT_NUMBERING_CACHE_FORMAT_VERSION) //first version
180         {
181             xIStm->ReadInt32( nNumIndex );
182             while (nNumIndex>=0 && nNumIndex<DEFAULT_NUM_VALUSET_COUNT) {
183                 SvxNumRule aNum(*xIStm);
184                 //bullet color in font properties is not stored correctly. Need set transparency bits manually
185                 for(sal_uInt16 i = 0; i < aNum.GetLevelCount(); i++)
186                 {
187                     SvxNumberFormat aFmt(aNum.GetLevel(i));
188                     if (aFmt.GetBulletFont()) {
189                         vcl::Font aFont(*aFmt.GetBulletFont());
190                         Color c=aFont.GetColor();
191                         c.SetAlpha(0);
192                         aFont.SetColor(c);
193                         aFmt.SetBulletFont(&aFont);
194                         aNum.SetLevel(i, aFmt);
195                     }
196                 }
197                 ReplaceNumRule(aNum,nNumIndex,0x1/*nLevel*/);
198                 xIStm->ReadInt32( nNumIndex );
199             }
200         }
201     }
202     eCoreUnit = eOldCoreUnit;
203     bIsLoading = false;
204 }
ImplStore(std::u16string_view filename)205 void NBOTypeMgrBase::ImplStore(std::u16string_view filename)
206 {
207     if (bIsLoading) return;
208     MapUnit      eOldCoreUnit=eCoreUnit;
209     eCoreUnit = MapUnit::Map100thMM;
210     INetURLObject aFile( SvtPathOptions().GetUserConfigPath() );
211     aFile.Append( filename);
212     std::unique_ptr<SvStream> xOStm(::utl::UcbStreamHelper::CreateStream( aFile.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::WRITE ));
213     if( xOStm ) {
214         sal_uInt32                      nVersion;
215         sal_Int32                       nNumIndex;
216         nVersion = DEFAULT_NUMBERING_CACHE_FORMAT_VERSION;
217         xOStm->WriteUInt32( nVersion );
218         for(sal_Int32 nItem = 0; nItem < DEFAULT_NUM_VALUSET_COUNT; nItem++ ) {
219             if (IsCustomized(nItem)) {
220                 SvxNumRule aDefNumRule( SvxNumRuleFlags::BULLET_REL_SIZE | SvxNumRuleFlags::CONTINUOUS | SvxNumRuleFlags::BULLET_COLOR,
221                     10, false,
222                     SvxNumRuleType::NUMBERING, SvxNumberFormat::LABEL_ALIGNMENT);
223                 xOStm->WriteInt32( nItem );
224                 ApplyNumRule(aDefNumRule,nItem,0x1/*nLevel*/,false,true);
225                 aDefNumRule.Store(*xOStm);
226             }
227         }
228         nNumIndex = -1;
229         xOStm->WriteInt32( nNumIndex );  //write end flag
230     }
231     eCoreUnit = eOldCoreUnit;
232 }
233 
234 // Character Bullet Type lib
235 BulletsSettings* BulletsTypeMgr::pActualBullets[] ={nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr};
236 const sal_Unicode BulletsTypeMgr::aDynamicBulletTypes[]={' ',' ',' ',' ',' ',' ',' ',' '};
237 const sal_Unicode BulletsTypeMgr::aDynamicRTLBulletTypes[]={' ',' ',' ',' ',' ',' ',' ',' '};
238 
BulletsTypeMgr()239 BulletsTypeMgr::BulletsTypeMgr()
240 {
241     Init();
242 }
243 
GetInstance()244 BulletsTypeMgr& BulletsTypeMgr::GetInstance()
245 {
246     static BulletsTypeMgr theBulletsTypeMgr;
247     return theBulletsTypeMgr;
248 }
249 
Init()250 void BulletsTypeMgr::Init()
251 {
252     css::uno::Sequence< OUString > aBulletSymbols(officecfg::Office::Common::BulletsNumbering::DefaultBullets::get());
253     css::uno::Sequence< OUString > aBulletSymbolsFonts(officecfg::Office::Common::BulletsNumbering::DefaultBulletsFonts::get());
254 
255     vcl::Font& rActBulletFont = lcl_GetDefaultBulletFont();
256 
257     for (sal_uInt16 i=0;i<DEFAULT_BULLET_TYPES;i++)
258     {
259         pActualBullets[i] = new BulletsSettings;
260         pActualBullets[i]->cBulletChar = aBulletSymbols[i].toChar();
261         rActBulletFont.SetFamilyName(aBulletSymbolsFonts[i]);
262         pActualBullets[i]->aFont = rActBulletFont;
263     }
264 }
265 
GetNBOIndexForNumRule(SvxNumRule & aNum,sal_uInt16 mLevel,sal_uInt16 nFromIndex)266 sal_uInt16 BulletsTypeMgr::GetNBOIndexForNumRule(SvxNumRule& aNum,sal_uInt16 mLevel,sal_uInt16 nFromIndex)
267 {
268     if ( mLevel == sal_uInt16(0xFFFF) || mLevel == 0)
269         return sal_uInt16(0xFFFF);
270     //if ( !lcl_IsNumFmtSet(pNR, mLevel) ) return (sal_uInt16)0xFFFF;
271 
272     sal_uInt16 nActLv = IsSingleLevel(mLevel);
273 
274     if ( nActLv == sal_uInt16(0xFFFF) )
275         return sal_uInt16(0xFFFF);
276 
277     const SvxNumberFormat& aFmt(aNum.GetLevel(nActLv));
278     sal_UCS4 cChar = aFmt.GetBulletChar();
279 
280     css::uno::Sequence<OUString> aBulletSymbols(officecfg::Office::Common::BulletsNumbering::DefaultBullets::get());
281     for(sal_uInt16 i = nFromIndex; i < DEFAULT_BULLET_TYPES; i++)
282     {
283         if ( (cChar == aBulletSymbols[i].toChar()) ||
284              (cChar == 9830 && 57356 == pActualBullets[i]->cBulletChar) ||
285              (cChar == 9632 && 57354 == pActualBullets[i]->cBulletChar)   )
286         {
287             return i+1;
288         }
289     }
290 
291     return sal_uInt16(0xFFFF);
292 }
293 
ReplaceNumRule(SvxNumRule & aNum,sal_uInt16 nIndex,sal_uInt16 mLevel)294 void BulletsTypeMgr::ReplaceNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_uInt16 mLevel)
295 {
296     if ( nIndex >= DEFAULT_BULLET_TYPES )
297         return;
298 
299     if ( mLevel == sal_uInt16(0xFFFF) || mLevel == 0)
300         return;
301 
302     if ( GetNBOIndexForNumRule(aNum,mLevel) != sal_uInt16(0xFFFF) )
303         return;
304 
305     sal_uInt16 nActLv = IsSingleLevel(mLevel);
306 
307     if ( nActLv == sal_uInt16(0xFFFF) )
308         return;
309 
310     SvxNumberFormat aFmt(aNum.GetLevel(nActLv));
311     sal_UCS4 cChar = aFmt.GetBulletChar();
312     const std::optional<vcl::Font>& pFont = aFmt.GetBulletFont();
313 
314     pActualBullets[nIndex]->cBulletChar = cChar;
315     if ( pFont )
316         pActualBullets[nIndex]->aFont = *pFont;
317     pActualBullets[nIndex]->bIsCustomized = true;
318 }
319 
ApplyNumRule(SvxNumRule & aNum,sal_uInt16 nIndex,sal_uInt16 mLevel,bool,bool isResetSize)320 void BulletsTypeMgr::ApplyNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_uInt16 mLevel, bool /*isDefault*/, bool isResetSize)
321 {
322     if ( nIndex >= DEFAULT_BULLET_TYPES )
323         return;
324 
325     css::uno::Sequence<OUString> aBulletSymbols(officecfg::Office::Common::BulletsNumbering::DefaultBullets::get());
326     css::uno::Sequence<OUString> aBulletFontSymbols(officecfg::Office::Common::BulletsNumbering::DefaultBulletsFonts::get());
327 
328     sal_UCS4 cChar = aBulletSymbols[nIndex].toChar();
329     vcl::Font& rActBulletFont = pActualBullets[nIndex]->aFont;
330     rActBulletFont.SetFamilyName(aBulletFontSymbols[nIndex]);
331 
332     sal_uInt16 nMask = 1;
333     OUString sBulletCharFormatName = GetBulletCharFmtName();
334     for(sal_uInt16 i = 0; i < aNum.GetLevelCount(); i++)
335     {
336         if(mLevel & nMask)
337         {
338             SvxNumberFormat aFmt(aNum.GetLevel(i));
339             aFmt.SetNumberingType( SVX_NUM_CHAR_SPECIAL );
340             aFmt.SetBulletFont(&rActBulletFont);
341             aFmt.SetBulletChar(cChar);
342             aFmt.SetCharFormatName(sBulletCharFormatName);
343             aFmt.SetListFormat( "" );
344             if (isResetSize) aFmt.SetBulletRelSize(45);
345             aNum.SetLevel(i, aFmt);
346         }
347         nMask <<= 1;
348     }
349 }
350 
ApplyCustomRule(SvxNumRule & aNum,std::u16string_view sBullet,const OUString & sFont,sal_uInt16 mLevel)351 void BulletsTypeMgr::ApplyCustomRule(SvxNumRule& aNum, std::u16string_view sBullet,
352                                      const OUString& sFont, sal_uInt16 mLevel)
353 {
354     sal_uInt16 nMask = 1;
355     OUString sBulletCharFormatName = GetBulletCharFmtName();
356     const vcl::Font aFont(sFont, Size(1, 1));
357     for (sal_uInt16 i = 0; i < aNum.GetLevelCount(); i++)
358     {
359         if (mLevel & nMask)
360         {
361             SvxNumberFormat aFmt(aNum.GetLevel(i));
362             aFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
363             aFmt.SetBulletFont(&aFont);
364             aFmt.SetBulletChar(sBullet[0]);
365             aFmt.SetCharFormatName(sBulletCharFormatName);
366             aFmt.SetListFormat("");
367             aNum.SetLevel(i, aFmt);
368         }
369         nMask <<= 1;
370     }
371 }
372 
GetDescription(sal_uInt16,bool)373 OUString BulletsTypeMgr::GetDescription(sal_uInt16 /*nIndex*/, bool /*isDefault*/)
374 {
375     return OUString();
376 }
377 
IsCustomized(sal_uInt16 nIndex)378 bool BulletsTypeMgr::IsCustomized(sal_uInt16 nIndex)
379 {
380     bool bRet = false;
381 
382     if ( nIndex >= DEFAULT_BULLET_TYPES )
383         bRet = false;
384     else
385         bRet = pActualBullets[nIndex]->bIsCustomized;
386 
387     return bRet;
388 }
389 
390 // Numbering Type lib
NumberingTypeMgr()391 NumberingTypeMgr::NumberingTypeMgr()
392 {
393     Init();
394     maDefaultNumberSettingsArr = maNumberSettingsArr;
395     ImplLoad(u"standard.syb");
396 }
397 
~NumberingTypeMgr()398 NumberingTypeMgr::~NumberingTypeMgr()
399 {
400 }
401 
402 const TranslateId RID_SVXSTR_SINGLENUM_DESCRIPTIONS[] =
403 {
404     RID_SVXSTR_SINGLENUM_DESCRIPTION_0,
405     RID_SVXSTR_SINGLENUM_DESCRIPTION_1,
406     RID_SVXSTR_SINGLENUM_DESCRIPTION_2,
407     RID_SVXSTR_SINGLENUM_DESCRIPTION_3,
408     RID_SVXSTR_SINGLENUM_DESCRIPTION_4,
409     RID_SVXSTR_SINGLENUM_DESCRIPTION_5,
410     RID_SVXSTR_SINGLENUM_DESCRIPTION_6,
411     RID_SVXSTR_SINGLENUM_DESCRIPTION_7
412 };
413 
GetInstance()414 NumberingTypeMgr& NumberingTypeMgr::GetInstance()
415 {
416     static NumberingTypeMgr theNumberingTypeMgr;
417     return theNumberingTypeMgr;
418 }
419 
Init()420 void NumberingTypeMgr::Init()
421 {
422     const Reference< XComponentContext >& xContext = ::comphelper::getProcessComponentContext();
423     Reference<XDefaultNumberingProvider> xDefNum = DefaultNumberingProvider::create( xContext );
424 
425     Sequence< Sequence< PropertyValue > > aNumberings;
426     Locale aLocale(Application::GetSettings().GetLanguageTag().getLocale());
427     try
428     {
429         aNumberings = xDefNum->getDefaultContinuousNumberingLevels( aLocale );
430 
431         sal_Int32 nLength = aNumberings.getLength();
432 
433         const Sequence<PropertyValue>* pValuesArr = aNumberings.getConstArray();
434         for(sal_Int32 i = 0; i < nLength; i++)
435         {
436             NumSettings_Impl* pNew = lcl_CreateNumberingSettingsPtr(pValuesArr[i]);
437             std::shared_ptr<NumberSettings_Impl> pNumEntry = std::make_shared<NumberSettings_Impl>();
438             pNumEntry->pNumSetting = pNew;
439             if ( i < 8 )
440                 pNumEntry->sDescription = SvxResId(RID_SVXSTR_SINGLENUM_DESCRIPTIONS[i]);
441             maNumberSettingsArr.push_back(std::move(pNumEntry));
442         }
443     }
444     catch(Exception&)
445     {
446     }
447 }
448 
GetNBOIndexForNumRule(SvxNumRule & aNum,sal_uInt16 mLevel,sal_uInt16 nFromIndex)449 sal_uInt16 NumberingTypeMgr::GetNBOIndexForNumRule(SvxNumRule& aNum,sal_uInt16 mLevel,sal_uInt16 nFromIndex)
450 {
451     if ( mLevel == sal_uInt16(0xFFFF) || mLevel > aNum.GetLevelCount() || mLevel == 0)
452         return sal_uInt16(0xFFFF);
453 
454     sal_uInt16 nActLv = IsSingleLevel(mLevel);
455 
456     if ( nActLv == sal_uInt16(0xFFFF) )
457         return sal_uInt16(0xFFFF);
458 
459     const SvxNumberFormat& aFmt(aNum.GetLevel(nActLv));
460     //sal_Unicode cPrefix = OUString(aFmt.GetPrefix())[0];
461     //sal_Unicode cSuffix = :OUString(aFmt.GetSuffix())[0];
462     const OUString& sPrefix = aFmt.GetPrefix();
463     const OUString& sLclSuffix = aFmt.GetSuffix();
464     sal_Int16 eNumType = aFmt.GetNumberingType();
465 
466     sal_uInt16 nCount = maNumberSettingsArr.size();
467     for(sal_uInt16 i = nFromIndex; i < nCount; ++i)
468     {
469         NumberSettings_Impl* _pSet = maNumberSettingsArr[i].get();
470         sal_Int16 eNType = _pSet->pNumSetting->nNumberType;
471         OUString sLocalPrefix = _pSet->pNumSetting->sPrefix;
472         OUString sLocalSuffix = _pSet->pNumSetting->sSuffix;
473         if (sPrefix == sLocalPrefix &&
474             sLclSuffix == sLocalSuffix &&
475             eNumType == eNType )
476         {
477             return i+1;
478         }
479     }
480 
481 
482     return sal_uInt16(0xFFFF);
483 }
484 
ReplaceNumRule(SvxNumRule & aNum,sal_uInt16 nIndex,sal_uInt16 mLevel)485 void NumberingTypeMgr::ReplaceNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_uInt16 mLevel)
486 {
487     sal_uInt16 nActLv = IsSingleLevel(mLevel);
488 
489     if ( nActLv == sal_uInt16(0xFFFF) )
490         return;
491 
492     const SvxNumberFormat& aFmt(aNum.GetLevel(nActLv));
493     SvxNumType eNumType = aFmt.GetNumberingType();
494 
495     sal_uInt16 nCount = maNumberSettingsArr.size();
496     if ( nIndex >= nCount )
497         return;
498 
499     NumberSettings_Impl* _pSet = maNumberSettingsArr[nIndex].get();
500 
501     _pSet->pNumSetting->sPrefix = aFmt.GetPrefix();
502     _pSet->pNumSetting->sSuffix = aFmt.GetSuffix();
503     _pSet->pNumSetting->nNumberType = eNumType;
504     _pSet->bIsCustomized = true;
505 
506     SvxNumRule aTmpRule1(aNum);
507     SvxNumRule aTmpRule2(aNum);
508     ApplyNumRule(aTmpRule1,nIndex,mLevel,true);
509     ApplyNumRule(aTmpRule2,nIndex,mLevel);
510     if (aTmpRule1==aTmpRule2) _pSet->bIsCustomized=false;
511     if (!_pSet->bIsCustomized) {
512         _pSet->sDescription = GetDescription(nIndex,true);
513     }
514     ImplStore(u"standard.syb");
515 }
516 
ApplyNumRule(SvxNumRule & aNum,sal_uInt16 nIndex,sal_uInt16 mLevel,bool isDefault,bool isResetSize)517 void NumberingTypeMgr::ApplyNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_uInt16 mLevel, bool isDefault, bool isResetSize)
518 {
519     if(maNumberSettingsArr.size() <= nIndex)
520         return;
521     NumberSettingsArr_Impl*     pCurrentNumberSettingsArr = &maNumberSettingsArr;
522     if (isDefault) pCurrentNumberSettingsArr = &maDefaultNumberSettingsArr;
523     NumberSettings_Impl* _pSet = (*pCurrentNumberSettingsArr)[nIndex].get();
524     SvxNumType eNewType = _pSet->pNumSetting->nNumberType;
525 
526     sal_uInt16 nMask = 1;
527     OUString sNumCharFmtName = GetNumCharFmtName();
528     for(sal_uInt16 i = 0; i < aNum.GetLevelCount(); i++)
529     {
530         if(mLevel & nMask)
531         {
532             SvxNumberFormat aFmt(aNum.GetLevel(i));
533             if (eNewType!=aFmt.GetNumberingType()) isResetSize=true;
534             aFmt.SetNumberingType(eNewType);
535             aFmt.SetListFormat(_pSet->pNumSetting->sPrefix, _pSet->pNumSetting->sSuffix, i);
536             aFmt.SetCharFormatName(sNumCharFmtName);
537             if (isResetSize) aFmt.SetBulletRelSize(100);
538             aNum.SetLevel(i, aFmt);
539         }
540         nMask <<= 1 ;
541     }
542 }
543 
GetDescription(sal_uInt16 nIndex,bool isDefault)544 OUString NumberingTypeMgr::GetDescription(sal_uInt16 nIndex, bool isDefault)
545 {
546     OUString sRet;
547     sal_uInt16 nLength = maNumberSettingsArr.size();
548 
549     if ( nIndex >= nLength )
550         return sRet;
551     else
552         sRet = maNumberSettingsArr[nIndex]->sDescription;
553     if (isDefault) sRet = maDefaultNumberSettingsArr[nIndex]->sDescription;
554 
555     return sRet;
556 }
557 
IsCustomized(sal_uInt16 nIndex)558 bool NumberingTypeMgr::IsCustomized(sal_uInt16 nIndex)
559 {
560     bool bRet = false;
561     sal_uInt16 nLength = maNumberSettingsArr.size();
562 
563     if ( nIndex >= nLength )
564         bRet = false;
565     else
566         bRet = maNumberSettingsArr[nIndex]->bIsCustomized;
567 
568     return bRet;
569 }
570 // Multi-level /Outline Type lib
OutlineTypeMgr()571 OutlineTypeMgr::OutlineTypeMgr()
572 {
573     Init();
574     for(sal_Int32 nItem = 0; nItem < DEFAULT_NUM_VALUSET_COUNT; nItem++ )
575     {
576         pDefaultOutlineSettingsArrs[nItem] = pOutlineSettingsArrs[nItem];
577     }
578     //Initial the first time to store the default value. Then do it again for customized value
579     Init();
580     ImplLoad(u"standard.syc");
581 }
582 
GetInstance()583 OutlineTypeMgr& OutlineTypeMgr::GetInstance()
584 {
585     static OutlineTypeMgr theOutlineTypeMgr;
586     return theOutlineTypeMgr;
587 }
588 
Init()589 void OutlineTypeMgr::Init()
590 {
591     const Reference< XComponentContext >& xContext = ::comphelper::getProcessComponentContext();
592     Reference<XDefaultNumberingProvider> xDefNum = DefaultNumberingProvider::create( xContext );
593 
594     Sequence<Reference<XIndexAccess> > aOutlineAccess;
595     Locale aLocale(Application::GetSettings().GetLanguageTag().getLocale());
596     try
597     {
598         aOutlineAccess = xDefNum->getDefaultOutlineNumberings( aLocale );
599 
600         SvxNumRule aDefNumRule( SvxNumRuleFlags::BULLET_REL_SIZE | SvxNumRuleFlags::CONTINUOUS | SvxNumRuleFlags::BULLET_COLOR,
601             10, false,
602             SvxNumRuleType::NUMBERING, SvxNumberFormat::LABEL_ALIGNMENT);
603 
604         auto nSize = std::min<sal_Int32>(aOutlineAccess.getLength(), DEFAULT_NUM_VALUSET_COUNT);
605         for(sal_Int32 nItem = 0; nItem < nSize; nItem++ )
606         {
607             pOutlineSettingsArrs[ nItem ] = new OutlineSettings_Impl;
608             OutlineSettings_Impl* pItemArr = pOutlineSettingsArrs[ nItem ];
609             OString id = OString::Concat(RID_SVXSTR_OUTLINENUM_DESCRIPTION_0.getId()) + OString::number(nItem);
610             pItemArr->sDescription = SvxResId( TranslateId(RID_SVXSTR_OUTLINENUM_DESCRIPTION_0.mpContext, id.getStr()) );
611             pItemArr->pNumSettingsArr = new NumSettingsArr_Impl;
612             Reference<XIndexAccess> xLevel = aOutlineAccess.getConstArray()[nItem];
613             for(sal_Int32 nLevel = 0; nLevel < SVX_MAX_NUM; nLevel++)
614             {
615                 // use the last locale-defined level for all remaining levels.
616                 sal_Int32 nLocaleLevel = std::min(nLevel, xLevel->getCount() - 1);
617                 Sequence<PropertyValue> aLevelProps;
618                 if (nLocaleLevel >= 0)
619                     xLevel->getByIndex(nLocaleLevel) >>= aLevelProps;
620 
621                 NumSettings_Impl* pNew = lcl_CreateNumberingSettingsPtr(aLevelProps);
622                 const SvxNumberFormat& aNumFmt( aDefNumRule.GetLevel( nLevel) );
623                 assert(aNumFmt.GetNumAdjust() == SvxAdjust::Left && "new entry was previously defined by default, now defaults to Left");
624                 pNew->eLabelFollowedBy = aNumFmt.GetLabelFollowedBy();
625                 pNew->nTabValue = aNumFmt.GetListtabPos();
626                 if (pNew->eNumAlign == SvxAdjust::Right)
627                     pNew->nNumAlignAt = -174; // number borrowed from RES_POOLNUMRULE_NUM4
628                 else
629                     pNew->nNumAlignAt = aNumFmt.GetFirstLineIndent();
630                 pNew->nNumIndentAt = aNumFmt.GetIndentAt();
631                 pItemArr->pNumSettingsArr->push_back(std::shared_ptr<NumSettings_Impl>(pNew));
632             }
633         }
634     }
635     catch(Exception&)
636     {
637     }
638 }
639 
GetNBOIndexForNumRule(SvxNumRule & aNum,sal_uInt16,sal_uInt16 nFromIndex)640 sal_uInt16 OutlineTypeMgr::GetNBOIndexForNumRule(SvxNumRule& aNum,sal_uInt16 /*mLevel*/,sal_uInt16 nFromIndex)
641 {
642     sal_uInt16 const nLength = SAL_N_ELEMENTS(pOutlineSettingsArrs);
643     for(sal_uInt16 iDex = nFromIndex; iDex < nLength; iDex++)
644     {
645         bool bNotMatch = false;
646         OutlineSettings_Impl* pItemArr = pOutlineSettingsArrs[iDex];
647         sal_uInt16 nCount = pItemArr ? pItemArr->pNumSettingsArr->size() : 0;
648         for (sal_uInt16 iLevel=0;iLevel < nCount;iLevel++)
649         {
650             NumSettings_Impl* _pSet = (*pItemArr->pNumSettingsArr)[iLevel].get();
651             sal_Int16 eNType = _pSet->nNumberType;
652 
653             const SvxNumberFormat& aFmt(aNum.GetLevel(iLevel));
654             const OUString& sPrefix = aFmt.GetPrefix();
655             const OUString& sLclSuffix = aFmt.GetSuffix();
656             sal_Int16 eNumType = aFmt.GetNumberingType();
657             if( eNumType == SVX_NUM_CHAR_SPECIAL)
658             {
659                 sal_UCS4 cChar = aFmt.GetBulletChar();
660 
661                 sal_UCS4 ccChar
662                     = _pSet->sBulletChar.isEmpty()
663                           ? 0
664                           : _pSet->sBulletChar.iterateCodePoints(&o3tl::temporary(sal_Int32(0)));
665 
666                 if ( !((cChar == ccChar) &&
667                     _pSet->eLabelFollowedBy == aFmt.GetLabelFollowedBy() &&
668                     _pSet->nTabValue == aFmt.GetListtabPos() &&
669                     _pSet->eNumAlign == aFmt.GetNumAdjust() &&
670                     _pSet->nNumAlignAt == aFmt.GetFirstLineIndent() &&
671                     _pSet->nNumIndentAt == aFmt.GetIndentAt()))
672                 {
673                     bNotMatch = true;
674                     break;
675                 }
676             }
677             else if ((eNumType&(~LINK_TOKEN)) == SVX_NUM_BITMAP )
678             {
679                 const SvxBrushItem* pBrsh1 = aFmt.GetBrush();
680                 const SvxBrushItem* pBrsh2 = _pSet->pBrushItem;
681                 bool bIsMatch = false;
682                 if (SfxPoolItem::areSame(pBrsh1,pBrsh2)) bIsMatch = true;
683                 if (pBrsh1 && pBrsh2) {
684                     const Graphic* pGrf1 = pBrsh1->GetGraphic();
685                     const Graphic* pGrf2 = pBrsh2->GetGraphic();
686                     if (pGrf1==pGrf2) bIsMatch = true;
687                     if (pGrf1 && pGrf2) {
688                         if ( pGrf1->GetBitmap() == pGrf2->GetBitmap() &&
689                                 _pSet->aSize == aFmt.GetGraphicSize())
690                             bIsMatch = true;
691                     }
692                 }
693                 if (!bIsMatch) {
694                     bNotMatch = true;
695                     break;
696                 }
697             }
698             else
699             {
700                 if (!(sPrefix == _pSet->sPrefix &&
701                       sLclSuffix == _pSet->sSuffix &&
702                       eNumType == eNType &&
703                       _pSet->eLabelFollowedBy == aFmt.GetLabelFollowedBy() &&
704                       _pSet->nTabValue == aFmt.GetListtabPos() &&
705                       _pSet->eNumAlign == aFmt.GetNumAdjust() &&
706                       _pSet->nNumAlignAt == aFmt.GetFirstLineIndent() &&
707                       _pSet->nNumIndentAt == aFmt.GetIndentAt()))
708                 {
709                     bNotMatch = true;
710                     break;
711                 }
712             }
713         }
714         if ( !bNotMatch )
715             return iDex+1;
716     }
717 
718 
719     return sal_uInt16(0xFFFF);
720 }
721 
ReplaceNumRule(SvxNumRule & aNum,sal_uInt16 nIndex,sal_uInt16 mLevel)722 void OutlineTypeMgr::ReplaceNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_uInt16 mLevel)
723 {
724     sal_uInt16 const nLength = SAL_N_ELEMENTS(pOutlineSettingsArrs);
725     if ( nIndex >= nLength )
726         return;
727 
728     OutlineSettings_Impl* pItemArr = pOutlineSettingsArrs[nIndex];
729     sal_uInt16 nCount = pItemArr->pNumSettingsArr->size();
730     for (sal_uInt16 iLevel=0;iLevel < nCount;iLevel++)
731     {
732         const SvxNumberFormat& aFmt(aNum.GetLevel(iLevel));
733         SvxNumType eNumType = aFmt.GetNumberingType();
734 
735         NumSettings_Impl* _pSet = (*pItemArr->pNumSettingsArr)[iLevel].get();
736 
737         _pSet->eLabelFollowedBy = aFmt.GetLabelFollowedBy();
738         _pSet->nTabValue = aFmt.GetListtabPos();
739         _pSet->eNumAlign = aFmt.GetNumAdjust();
740         _pSet->nNumAlignAt = aFmt.GetFirstLineIndent();
741         _pSet->nNumIndentAt = aFmt.GetIndentAt();
742 
743         if( eNumType == SVX_NUM_CHAR_SPECIAL)
744         {
745             sal_UCS4 cChar = aFmt.GetBulletChar();
746             _pSet->sBulletChar = OUString(&cChar, 1);
747             if ( aFmt.GetBulletFont() )
748                 _pSet->sBulletFont = aFmt.GetBulletFont()->GetFamilyName();
749             _pSet->nNumberType = eNumType;
750             pItemArr->bIsCustomized = true;
751         }else if ((eNumType&(~LINK_TOKEN)) == SVX_NUM_BITMAP ) {
752             if (_pSet->pBrushItem) {
753                 delete _pSet->pBrushItem;
754                 _pSet->pBrushItem=nullptr;
755             }
756             if (aFmt.GetBrush())
757                 _pSet->pBrushItem = new SvxBrushItem(*aFmt.GetBrush());
758             _pSet->aSize = aFmt.GetGraphicSize();
759             _pSet->nNumberType = eNumType;
760         } else
761         {
762             _pSet->sPrefix = aFmt.GetPrefix();
763             _pSet->sSuffix = aFmt.GetSuffix();
764             _pSet->nNumberType = eNumType;
765             if ( aFmt.GetBulletFont() )
766                 _pSet->sBulletFont = aFmt.GetBulletFont()->GetFamilyName();
767             pItemArr->bIsCustomized = true;
768          }
769     }
770     SvxNumRule aTmpRule1(aNum);
771     SvxNumRule aTmpRule2(aNum);
772     ApplyNumRule(aTmpRule1,nIndex,mLevel,true);
773     ApplyNumRule(aTmpRule2,nIndex,mLevel);
774     if (aTmpRule1==aTmpRule2) pItemArr->bIsCustomized=false;
775     if (!pItemArr->bIsCustomized) {
776         pItemArr->sDescription = GetDescription(nIndex,true);
777     }
778     ImplStore(u"standard.syc");
779 }
780 
ApplyNumRule(SvxNumRule & aNum,sal_uInt16 nIndex,sal_uInt16,bool isDefault,bool isResetSize)781 void OutlineTypeMgr::ApplyNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_uInt16 /*mLevel*/, bool isDefault, bool isResetSize)
782 {
783     DBG_ASSERT(DEFAULT_NUM_VALUSET_COUNT > nIndex, "wrong index");
784     if(DEFAULT_NUM_VALUSET_COUNT <= nIndex)
785         return;
786 
787     const FontList* pList = nullptr;
788 
789     OutlineSettings_Impl* pItemArr = pOutlineSettingsArrs[nIndex];
790     if (isDefault) pItemArr=pDefaultOutlineSettingsArrs[nIndex];
791 
792     NumSettingsArr_Impl *pNumSettingsArr=pItemArr->pNumSettingsArr;
793 
794     NumSettings_Impl* pLevelSettings = nullptr;
795     for(sal_uInt16 i = 0; i < aNum.GetLevelCount(); i++)
796     {
797         if(pNumSettingsArr->size() > i)
798             pLevelSettings = (*pNumSettingsArr)[i].get();
799 
800         if(!pLevelSettings)
801             break;
802 
803         SvxNumberFormat aFmt(aNum.GetLevel(i));
804         const vcl::Font& rActBulletFont = lcl_GetDefaultBulletFont();
805         if (pLevelSettings->nNumberType !=aFmt.GetNumberingType()) isResetSize=true;
806         aFmt.SetNumberingType( pLevelSettings->nNumberType );
807         sal_uInt16 nUpperLevelOrChar = static_cast<sal_uInt16>(pLevelSettings->nParentNumbering);
808         if(aFmt.GetNumberingType() == SVX_NUM_CHAR_SPECIAL)
809         {
810             if( pLevelSettings->sBulletFont.getLength() &&
811                 pLevelSettings->sBulletFont != rActBulletFont.GetFamilyName() )
812             {
813                 //search for the font
814                 if(!pList)
815                 {
816                     if (SfxObjectShell* pCurDocShell = SfxObjectShell::Current())
817                     {
818                         const SvxFontListItem* pFontListItem = static_cast<const SvxFontListItem*>(pCurDocShell->GetItem(SID_ATTR_CHAR_FONTLIST));
819                         pList = pFontListItem ? pFontListItem->GetFontList() : nullptr;
820                     }
821                 }
822                 if(pList && pList->IsAvailable( pLevelSettings->sBulletFont ) )
823                 {
824                     vcl::Font aFont(pList->Get(pLevelSettings->sBulletFont,WEIGHT_NORMAL, ITALIC_NONE));
825                     aFmt.SetBulletFont(&aFont);
826                 }
827                 else
828                 {
829                     //if it cannot be found then create a new one
830                     vcl::Font aCreateFont( pLevelSettings->sBulletFont, OUString(), Size( 0, 14 ) );
831                     aCreateFont.SetCharSet( RTL_TEXTENCODING_DONTKNOW );
832                     aCreateFont.SetFamily( FAMILY_DONTKNOW );
833                     aCreateFont.SetPitch( PITCH_DONTKNOW );
834                     aCreateFont.SetWeight( WEIGHT_DONTKNOW );
835                     aCreateFont.SetTransparent( true );
836                     aFmt.SetBulletFont( &aCreateFont );
837                 }
838             }else
839                 aFmt.SetBulletFont( &rActBulletFont );
840 
841             sal_UCS4 cChar = 0;
842             if( !pLevelSettings->sBulletChar.isEmpty() )
843             {
844                 cChar
845                     = pLevelSettings->sBulletChar.iterateCodePoints(&o3tl::temporary(sal_Int32(0)));
846             }
847             if( AllSettings::GetLayoutRTL() )
848             {
849                 if( 0 == i && cChar == BulletsTypeMgr::aDynamicBulletTypes[5] )
850                     cChar = BulletsTypeMgr::aDynamicRTLBulletTypes[5];
851                 else if( 1 == i )
852                 {
853                     const SvxNumberFormat& numberFmt = aNum.GetLevel(0);
854                     if( numberFmt.GetBulletChar() == BulletsTypeMgr::aDynamicRTLBulletTypes[5] )
855                         cChar = BulletsTypeMgr::aDynamicRTLBulletTypes[4];
856                 }
857             }
858 
859             aFmt.SetBulletChar(cChar);
860             aFmt.SetCharFormatName( GetBulletCharFmtName() );
861             if (isResetSize) aFmt.SetBulletRelSize(45);
862         }else if ((aFmt.GetNumberingType()&(~LINK_TOKEN)) == SVX_NUM_BITMAP ) {
863             if (pLevelSettings->pBrushItem) {
864                     const Graphic* pGrf = pLevelSettings->pBrushItem->GetGraphic();
865                     Size aSize = pLevelSettings->aSize;
866                     sal_Int16 eOrient = text::VertOrientation::LINE_CENTER;
867                     if (!isResetSize  && aFmt.GetGraphicSize()!=Size(0,0))
868                         aSize = aFmt.GetGraphicSize();
869                     else if (aSize.IsEmpty() && pGrf)
870                         aSize = SvxNumberFormat::GetGraphicSizeMM100( pGrf );
871                     aSize = OutputDevice::LogicToLogic(aSize, MapMode(MapUnit::Map100thMM), MapMode(GetMapUnit()));
872                     aFmt.SetGraphicBrush( pLevelSettings->pBrushItem, &aSize, &eOrient );
873             }
874         } else
875         {
876             aFmt.SetIncludeUpperLevels(sal::static_int_cast< sal_uInt8 >(0 != nUpperLevelOrChar ? aNum.GetLevelCount() : 1));
877             aFmt.SetCharFormatName(GetNumCharFmtName());
878             if (isResetSize) aFmt.SetBulletRelSize(100);
879         }
880         if(pNumSettingsArr->size() > i) {
881             aFmt.SetLabelFollowedBy(pLevelSettings->eLabelFollowedBy);
882             aFmt.SetListtabPos(pLevelSettings->nTabValue);
883             aFmt.SetNumAdjust(pLevelSettings->eNumAlign);
884             aFmt.SetFirstLineIndent(pLevelSettings->nNumAlignAt);
885             aFmt.SetIndentAt(pLevelSettings->nNumIndentAt);
886         }
887         aFmt.SetListFormat(pLevelSettings->sPrefix, pLevelSettings->sSuffix, i);
888         aNum.SetLevel(i, aFmt);
889     }
890 }
891 
GetDescription(sal_uInt16 nIndex,bool isDefault)892 OUString OutlineTypeMgr::GetDescription(sal_uInt16 nIndex, bool isDefault)
893 {
894     OUString sRet;
895 
896     if ( nIndex >= SAL_N_ELEMENTS(pOutlineSettingsArrs) )
897         return sRet;
898     else
899     {
900         OutlineSettings_Impl* pItemArr = pOutlineSettingsArrs[nIndex];
901         if (isDefault) pItemArr = pDefaultOutlineSettingsArrs[nIndex];
902         if ( pItemArr )
903         {
904             sRet = pItemArr->sDescription;
905         }
906     }
907     return sRet;
908 }
909 
IsCustomized(sal_uInt16 nIndex)910 bool OutlineTypeMgr::IsCustomized(sal_uInt16 nIndex)
911 {
912     bool bRet = false;
913 
914     if ( nIndex >= SAL_N_ELEMENTS(pOutlineSettingsArrs) )
915         return bRet;
916     else
917     {
918         OutlineSettings_Impl* pItemArr = pOutlineSettingsArrs[nIndex];
919         if ( pItemArr )
920         {
921             bRet = pItemArr->bIsCustomized;
922         }
923     }
924 
925     return bRet;
926 }
927 
928 
929 }
930 
931 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
932