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