android: Update app-specific/MIME type icons
[LibreOffice.git] / sw / source / core / fields / chpfld.cxx
bloba56a779e8928c3642e001153d2029c3aaed988dd
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 <sal/config.h>
22 #include <string_view>
24 #include <com/sun/star/text/ChapterFormat.hpp>
25 #include <osl/diagnose.h>
26 #include <doc.hxx>
27 #include <frame.hxx>
28 #include <rootfrm.hxx>
29 #include <txtfrm.hxx>
30 #include <pam.hxx>
31 #include <ndtxt.hxx>
32 #include <chpfld.hxx>
33 #include <expfld.hxx>
34 #include <unofldmid.h>
35 #include <numrule.hxx>
37 using namespace ::com::sun::star;
39 namespace
42 OUString removeControlChars(std::u16string_view sIn)
44 OUStringBuffer aBuf(sIn);
45 aBuf = aBuf.replace('\n', ' ').replace('\t', ' ');
46 sal_Int32 nLen = aBuf.getLength();
47 for (sal_Int32 i = 0; i < nLen; ++i)
49 if (aBuf[i] < ' ')
51 sal_Int32 j = i+1;
52 while (j<nLen && aBuf[j]<' ') ++j;
53 aBuf.remove(i, j-i);
54 nLen = aBuf.getLength();
57 return aBuf.makeStringAndClear();
62 SwChapterFieldType::SwChapterFieldType()
63 : SwFieldType( SwFieldIds::Chapter )
67 std::unique_ptr<SwFieldType> SwChapterFieldType::Copy() const
69 return std::make_unique<SwChapterFieldType>();
72 // chapter field
74 SwChapterField::SwChapterField(SwChapterFieldType* pTyp, sal_uInt32 nFormat)
75 : SwField(pTyp, nFormat)
79 sal_uInt8 SwChapterField::GetLevel(SwRootFrame const*const pLayout) const
81 State const& rState(pLayout && pLayout->IsHideRedlines() ? m_StateRLHidden : m_State);
82 return rState.nLevel;
85 // this is called from UI or from import filters, so override both states
86 void SwChapterField::SetLevel(sal_uInt8 nLev)
88 m_State.nLevel = nLev;
89 m_StateRLHidden.nLevel = nLev;
92 const OUString& SwChapterField::GetNumber(SwRootFrame const*const pLayout) const
94 State const& rState(pLayout && pLayout->IsHideRedlines() ? m_StateRLHidden : m_State);
95 return rState.sNumber;
98 const OUString& SwChapterField::GetTitle(SwRootFrame const*const pLayout) const
100 State const& rState(pLayout && pLayout->IsHideRedlines() ? m_StateRLHidden : m_State);
101 return rState.sTitle;
104 OUString SwChapterField::ExpandImpl(SwRootFrame const*const pLayout) const
106 State const& rState(pLayout && pLayout->IsHideRedlines() ? m_StateRLHidden : m_State);
107 switch( GetFormat() )
109 case CF_TITLE:
110 return rState.sTitle;
111 case CF_NUMBER:
112 return rState.sPre + rState.sNumber + rState.sPost;
113 case CF_NUM_TITLE:
114 return rState.sPre + rState.sNumber + rState.sPost + rState.sLabelFollowedBy + rState.sTitle;
115 case CF_NUM_NOPREPST_TITLE:
116 return rState.sNumber + rState.sLabelFollowedBy + rState.sTitle;
118 // CF_NUMBER_NOPREPST
119 return rState.sNumber;
122 std::unique_ptr<SwField> SwChapterField::Copy() const
124 std::unique_ptr<SwChapterField> pTmp(
125 new SwChapterField(static_cast<SwChapterFieldType*>(GetTyp()), GetFormat()));
126 pTmp->m_State = m_State;
127 pTmp->m_StateRLHidden = m_StateRLHidden;
129 return std::unique_ptr<SwField>(pTmp.release());
132 // #i53420#
133 void SwChapterField::ChangeExpansion(const SwFrame & rFrame,
134 const SwContentNode* pContentNode,
135 bool bSrchNum )
137 SwDoc& rDoc = const_cast<SwDoc&>(pContentNode->GetDoc());
139 const SwTextNode* pTextNode = pContentNode->GetTextNode();
140 if (!pTextNode || !rFrame.IsInDocBody())
142 SwPosition aDummyPos( rDoc.GetNodes().GetEndOfContent() );
143 pTextNode = GetBodyTextNode( rDoc, aDummyPos, rFrame );
146 if ( pTextNode )
148 ChangeExpansion( *pTextNode, bSrchNum, rFrame.getRootFrame() );
152 void SwChapterField::ChangeExpansion(const SwTextNode &rTextNd, bool bSrchNum,
153 SwRootFrame const*const pLayout)
155 State & rState(pLayout && pLayout->IsHideRedlines() ? m_StateRLHidden : m_State);
156 rState.sNumber.clear();
157 rState.sLabelFollowedBy.clear();
158 rState.sTitle.clear();
159 rState.sPost.clear();
160 rState.sPre.clear();
162 SwDoc& rDoc = const_cast<SwDoc&>(rTextNd.GetDoc());
163 const SwTextNode *pTextNd = rTextNd.FindOutlineNodeOfLevel(rState.nLevel, pLayout);
164 if( !pTextNd )
165 return;
167 if( bSrchNum )
169 const SwTextNode* pONd = pTextNd;
170 do {
171 if( pONd && pONd->GetTextColl() )
173 sal_uInt8 nPrevLvl = rState.nLevel;
175 OSL_ENSURE( pONd->GetAttrOutlineLevel() >= 0 && pONd->GetAttrOutlineLevel() <= MAXLEVEL,
176 "<SwChapterField::ChangeExpansion(..)> - outline node with inconsistent outline level. Serious defect." );
177 rState.nLevel = static_cast<sal_uInt8>(pONd->GetAttrOutlineLevel());
179 if (nPrevLvl < rState.nLevel)
180 rState.nLevel = nPrevLvl;
181 else if( SVX_NUM_NUMBER_NONE != rDoc.GetOutlineNumRule()
182 ->Get( rState.nLevel ).GetNumberingType() )
184 pTextNd = pONd;
185 break;
188 if (!rState.nLevel--)
189 break;
190 pONd = pTextNd->FindOutlineNodeOfLevel(rState.nLevel, pLayout);
192 else
193 break;
194 } while( true );
197 // get the number without Pre-/Post-fixstrings
199 if ( pTextNd->IsOutline() )
201 // correction of refactoring done by cws swnumtree:
202 // retrieve numbering string without prefix and suffix strings
203 // as stated in the above german comment.
204 rState.sNumber = pTextNd->GetNumString(false, MAXLEVEL, pLayout);
206 SwNumRule* pRule( pTextNd->GetNumRule() );
207 if ( pTextNd->IsCountedInList() && pRule )
209 int nListLevel = pTextNd->GetActualListLevel();
210 if (nListLevel < 0)
211 nListLevel = 0;
212 if (nListLevel >= MAXLEVEL)
213 nListLevel = MAXLEVEL - 1;
215 const SwNumFormat& rNFormat = pRule->Get(nListLevel);
216 rState.sPost = rNFormat.GetSuffix();
217 rState.sPre = rNFormat.GetPrefix();
218 rState.sLabelFollowedBy = removeControlChars(rNFormat.GetLabelFollowedByAsString());
221 else
223 rState.sNumber = "??";
226 rState.sTitle = removeControlChars(sw::GetExpandTextMerged(pLayout,
227 *pTextNd, false, false, ExpandMode(0)));
230 bool SwChapterField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
232 switch( nWhichId )
234 case FIELD_PROP_BYTE1:
235 rAny <<= static_cast<sal_Int8>(m_State.nLevel);
236 break;
238 case FIELD_PROP_USHORT1:
240 sal_Int16 nRet;
241 switch( GetFormat() )
243 case CF_NUMBER: nRet = text::ChapterFormat::NUMBER; break;
244 case CF_TITLE: nRet = text::ChapterFormat::NAME; break;
245 case CF_NUMBER_NOPREPST:
246 nRet = text::ChapterFormat::DIGIT;
247 break;
248 case CF_NUM_NOPREPST_TITLE:
249 nRet = text::ChapterFormat::NO_PREFIX_SUFFIX;
250 break;
251 case CF_NUM_TITLE:
252 default: nRet = text::ChapterFormat::NAME_NUMBER;
254 rAny <<= nRet;
256 break;
258 default:
259 assert(false);
261 return true;
264 bool SwChapterField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
266 bool bRet = true;
267 switch( nWhichId )
269 case FIELD_PROP_BYTE1:
271 sal_Int8 nTmp = 0;
272 rAny >>= nTmp;
273 if(nTmp >= 0 && nTmp < MAXLEVEL)
275 m_State.nLevel = nTmp;
276 m_StateRLHidden.nLevel = nTmp;
278 else
279 bRet = false;
280 break;
283 case FIELD_PROP_USHORT1:
285 sal_Int16 nVal = 0;
286 rAny >>= nVal;
287 switch( nVal )
289 case text::ChapterFormat::NAME: SetFormat(CF_TITLE); break;
290 case text::ChapterFormat::NUMBER: SetFormat(CF_NUMBER); break;
291 case text::ChapterFormat::NO_PREFIX_SUFFIX:
292 SetFormat(CF_NUM_NOPREPST_TITLE);
293 break;
294 case text::ChapterFormat::DIGIT:
295 SetFormat(CF_NUMBER_NOPREPST);
296 break;
298 default: SetFormat(CF_NUM_TITLE);
301 break;
303 default:
304 assert(false);
306 return bRet;
309 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */