Avoid potential negative array index access to cached text.
[LibreOffice.git] / sc / source / core / data / stlsheet.cxx
blob7679f1936a6b893acf1e05cffe90fe040b667f5b
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 <document.hxx>
21 #include <stlsheet.hxx>
22 #include <stlpool.hxx>
24 #include <scitems.hxx>
25 #include <editeng/boxitem.hxx>
26 #include <editeng/frmdiritem.hxx>
27 #include <editeng/lrspitem.hxx>
28 #include <svx/pageitem.hxx>
29 #include <svx/svddef.hxx>
30 #include <svx/svdpool.hxx>
31 #include <svx/xdef.hxx>
32 #include <editeng/eeitem.hxx>
33 #include <editeng/paperinf.hxx>
34 #include <editeng/shaditem.hxx>
35 #include <editeng/sizeitem.hxx>
36 #include <editeng/ulspitem.hxx>
37 #include <editeng/xmlcnitm.hxx>
38 #include <svl/itempool.hxx>
39 #include <svl/itemset.hxx>
40 #include <svl/numformat.hxx>
41 #include <svl/hint.hxx>
42 #include <o3tl/unit_conversion.hxx>
43 #include <attrib.hxx>
45 #include <globstr.hrc>
46 #include <scresid.hxx>
47 #include <sc.hrc>
49 constexpr auto TWO_CM = o3tl::convert(2, o3tl::Length::cm, o3tl::Length::twip); // 1134
50 constexpr auto HFDIST_CM = o3tl::convert(250, o3tl::Length::mm100, o3tl::Length::twip); // 142
52 ScStyleSheet::ScStyleSheet( const OUString& rName,
53 const ScStyleSheetPool& rPoolP,
54 SfxStyleFamily eFamily,
55 SfxStyleSearchBits nMaskP )
57 : SfxStyleSheet ( rName, rPoolP, eFamily, nMaskP )
58 , eUsage( Usage::UNKNOWN )
62 ScStyleSheet::ScStyleSheet( const ScStyleSheet& rStyle )
63 : SfxStyleSheet ( rStyle )
64 , eUsage( Usage::UNKNOWN )
68 ScStyleSheet::~ScStyleSheet()
72 bool ScStyleSheet::HasFollowSupport() const
74 return false;
77 bool ScStyleSheet::HasParentSupport () const
79 bool bHasParentSupport = false;
81 switch ( GetFamily() )
83 case SfxStyleFamily::Para: bHasParentSupport = true; break;
84 case SfxStyleFamily::Frame: bHasParentSupport = true; break;
85 case SfxStyleFamily::Page: bHasParentSupport = false; break;
86 default:
88 // added to avoid warnings
92 return bHasParentSupport;
95 bool ScStyleSheet::SetParent( const OUString& rParentName )
97 bool bResult = false;
98 OUString aEffName = rParentName;
99 SfxStyleSheetBase* pStyle = m_pPool->Find( aEffName, nFamily );
100 if (!pStyle)
102 std::unique_ptr<SfxStyleSheetIterator> pIter = m_pPool->CreateIterator(nFamily);
103 pStyle = pIter->First();
104 if (pStyle)
105 aEffName = pStyle->GetName();
108 if ( pStyle && aEffName != GetName() )
110 bResult = SfxStyleSheet::SetParent( aEffName );
111 if (bResult)
113 SfxItemSet& rParentSet = pStyle->GetItemSet();
114 GetItemSet().SetParent( &rParentSet );
116 // #i113491# Drag&Drop in the stylist's hierarchical view doesn't execute a slot,
117 // so the repaint has to come from here (after modifying the ItemSet).
118 // RepaintRange checks the document's IsVisible flag and locked repaints.
119 ScDocument* pDoc = static_cast<ScStyleSheetPool*>(GetPool())->GetDocument();
120 if (pDoc)
121 pDoc->RepaintRange( ScRange( 0,0,0, pDoc->MaxCol(),pDoc->MaxRow(),MAXTAB ) );
125 return bResult;
128 void ScStyleSheet::ResetParent()
130 GetItemSet().SetParent(nullptr);
133 SfxItemSet& ScStyleSheet::GetItemSet()
135 if ( !pSet )
137 switch ( GetFamily() )
139 case SfxStyleFamily::Page:
141 // Page templates should not be derivable,
142 // therefore suitable values are set at this point.
143 // (== Standard page template)
145 SfxItemPool& rItemPool = GetPool()->GetPool();
146 pSet = new SfxItemSetFixed<
147 ATTR_USERDEF, ATTR_USERDEF,
148 ATTR_WRITINGDIR, ATTR_WRITINGDIR,
149 ATTR_BACKGROUND, ATTR_BACKGROUND,
150 ATTR_BORDER, ATTR_SHADOW,
151 ATTR_LRSPACE, ATTR_PAGE_SCALETO>(rItemPool);
153 // If being loaded also the set is then filled in from the file,
154 // so the defaults do not need to be set.
155 // GetPrinter would then also create a new printer,
156 // because the stored Printer is not loaded yet!
158 ScDocument* pDoc = static_cast<ScStyleSheetPool*>(GetPool())->GetDocument();
159 if ( pDoc )
161 // Setting reasonable default values:
162 SvxPageItem aPageItem( ATTR_PAGE );
163 SvxSizeItem aPaperSizeItem( ATTR_PAGE_SIZE, SvxPaperInfo::GetDefaultPaperSize() );
165 SvxSetItem aHFSetItem(
166 rItemPool.GetDefaultItem(ATTR_PAGE_HEADERSET) );
168 SfxItemSet& rHFSet = aHFSetItem.GetItemSet();
169 SvxSizeItem aHFSizeItem( // 0,5 cm + distance
170 ATTR_PAGE_SIZE,
171 Size( 0, o3tl::convert(500, o3tl::Length::mm100, o3tl::Length::twip) + HFDIST_CM ) );
173 SvxULSpaceItem aHFDistItem ( HFDIST_CM,// nUp
174 HFDIST_CM,// nLow
175 ATTR_ULSPACE );
177 SvxLRSpaceItem aLRSpaceItem( TWO_CM, // nLeft
178 TWO_CM, // nRight
179 0, // nFirstLineOffset
180 ATTR_LRSPACE );
181 SvxULSpaceItem aULSpaceItem( TWO_CM, // nUp
182 TWO_CM, // nLow
183 ATTR_ULSPACE );
184 SvxBoxInfoItem aBoxInfoItem( ATTR_BORDER_INNER );
186 aBoxInfoItem.SetTable( false );
187 aBoxInfoItem.SetDist( true );
188 aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::DISTANCE );
190 aPageItem.SetLandscape( false );
192 rHFSet.Put( aBoxInfoItem );
193 rHFSet.Put( aHFSizeItem );
194 rHFSet.Put( aHFDistItem );
195 rHFSet.Put( SvxLRSpaceItem(0, 0, 0, ATTR_LRSPACE) ); // Set border to Null
197 aHFSetItem.SetWhich(ATTR_PAGE_HEADERSET);
198 pSet->Put( aHFSetItem );
199 aHFSetItem.SetWhich(ATTR_PAGE_FOOTERSET);
200 pSet->Put( aHFSetItem );
201 pSet->Put( aBoxInfoItem ); // Do not overwrite PoolDefault
202 // due to format templates
205 // Writing direction: not as pool default because the default for cells
206 // must remain SvxFrameDirection::Environment, and each page style's setting is
207 // supposed to be saved in the file format.
208 // The page default depends on the system language.
209 SvxFrameDirection eDirection = ScGlobal::IsSystemRTL() ?
210 SvxFrameDirection::Horizontal_RL_TB : SvxFrameDirection::Horizontal_LR_TB;
211 pSet->Put( SvxFrameDirectionItem( eDirection, ATTR_WRITINGDIR ) );
213 rItemPool.SetPoolDefaultItem( aPageItem );
214 rItemPool.SetPoolDefaultItem( aPaperSizeItem );
215 rItemPool.SetPoolDefaultItem( aLRSpaceItem );
216 rItemPool.SetPoolDefaultItem( aULSpaceItem );
217 rItemPool.SetPoolDefaultItem( SfxUInt16Item( ATTR_PAGE_SCALE, 100 ) );
218 ScPageScaleToItem aScaleToItem;
219 rItemPool.SetPoolDefaultItem( aScaleToItem );
220 rItemPool.SetPoolDefaultItem( SfxUInt16Item( ATTR_PAGE_SCALETOPAGES, 0 ) );
223 break;
225 case SfxStyleFamily::Frame:
227 SfxItemPool* pItemPool = &GetPool()->GetPool();
228 if (dynamic_cast<SdrItemPool*>(pItemPool) == nullptr)
229 pItemPool = pItemPool->GetSecondaryPool();
230 assert(pItemPool);
232 pSet = new SfxItemSetFixed<
233 XATTR_LINE_FIRST, XATTR_LINE_LAST,
234 XATTR_FILL_FIRST, XATTR_FILL_LAST,
235 SDRATTR_SHADOW_FIRST, SDRATTR_SHADOW_LAST,
236 SDRATTR_TEXT_MINFRAMEHEIGHT, SDRATTR_TEXT_WORDWRAP,
237 SDRATTR_EDGE_FIRST, SDRATTR_MEASURE_LAST,
238 SDRATTR_3D_FIRST, SDRATTR_3D_LAST,
239 EE_PARA_START, EE_CHAR_END>(*pItemPool);
241 break;
243 case SfxStyleFamily::Para:
244 default:
245 pSet = new SfxItemSetFixed<ATTR_PATTERN_START, ATTR_PATTERN_END>( GetPool()->GetPool() );
246 break;
248 bMySet = true;
250 if ( nHelpId == HID_SC_SHEET_CELL_ERG1 )
252 if ( !pSet->Count() )
254 // Hack to work around that when this code is called from
255 // ~ScStyleSheetPool -> ~SfxStyleSheetPool, GetPool() is no longer
256 // an ScStyleSheetPool:
257 ScStyleSheetPool * pool = dynamic_cast<ScStyleSheetPool *>(
258 GetPool());
259 if (pool != nullptr) {
260 ScDocument* pDoc = pool->GetDocument();
261 if ( pDoc )
263 sal_uInt32 nNumFmt = pDoc->GetFormatTable()->GetStandardFormat( SvNumFormatType::CURRENCY,ScGlobal::eLnge );
264 pSet->Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNumFmt ) );
270 return *pSet;
273 bool ScStyleSheet::IsUsed() const
275 switch (GetFamily())
277 case SfxStyleFamily::Para:
279 // Always query the document to let it decide if a rescan is necessary,
280 // and store the state.
281 ScDocument* pDoc = static_cast<ScStyleSheetPool*>(m_pPool)->GetDocument();
282 if ( pDoc && pDoc->IsStyleSheetUsed( *this ) )
283 eUsage = Usage::USED;
284 else
285 eUsage = Usage::NOTUSED;
286 return eUsage == Usage::USED;
288 case SfxStyleFamily::Page:
290 // tdf#108188 - verify that the page style is actually used
291 ScDocument* pDoc = static_cast<ScStyleSheetPool*>(m_pPool)->GetDocument();
292 if (pDoc && pDoc->IsPageStyleInUse(GetName(), nullptr))
293 eUsage = Usage::USED;
294 else
295 eUsage = Usage::NOTUSED;
296 return eUsage == Usage::USED;
298 case SfxStyleFamily::Frame:
300 ForAllListeners([this] (SfxListener* pListener)
302 auto pUser(dynamic_cast<svl::StyleSheetUser*>(pListener));
303 if (pUser && pUser->isUsedByModel())
305 eUsage = Usage::USED;
306 return true; // break loop
308 else
309 eUsage = Usage::NOTUSED;
310 return false;
312 return eUsage == Usage::USED;
314 default:
315 return true;
319 void ScStyleSheet::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
321 if ( rHint.GetId() == SfxHintId::Dying )
322 GetItemSet().SetParent( nullptr );
323 if (GetFamily() == SfxStyleFamily::Frame)
324 SfxStyleSheet::Notify(rBC, rHint);
327 // Avoid creating a Style "Standard" if this is not the Standard-Name;
328 // otherwise two styles would have the same name when storing.
329 // (on loading the style is created directly per Make with the name; making this query
330 // not applicable)
331 //TODO: If at any time during loading SetName is called, a flag has to be set/checked for loading
332 //TODO: The whole check has to be removed if for a new file version the name transformation is dropped.
334 bool ScStyleSheet::SetName(const OUString& rNew, bool bReindexNow)
336 OUString aFileStdName = STRING_STANDARD;
337 if ( rNew == aFileStdName && aFileStdName != ScResId(STR_STYLENAME_STANDARD) )
338 return false;
339 else
340 return SfxStyleSheet::SetName(rNew, bReindexNow);
343 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */