1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
28 #include <rootfrm.hxx>
34 #include <unofldmid.h>
35 #include <numrule.hxx>
37 using namespace ::com::sun::star
;
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
)
52 while (j
<nLen
&& aBuf
[j
]<' ') ++j
;
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
>();
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
);
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() )
110 return rState
.sTitle
;
112 return rState
.sPre
+ rState
.sNumber
+ rState
.sPost
;
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());
133 void SwChapterField::ChangeExpansion(const SwFrame
& rFrame
,
134 const SwContentNode
* pContentNode
,
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
);
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();
162 SwDoc
& rDoc
= const_cast<SwDoc
&>(rTextNd
.GetDoc());
163 const SwTextNode
*pTextNd
= rTextNd
.FindOutlineNodeOfLevel(rState
.nLevel
, pLayout
);
169 const SwTextNode
* pONd
= pTextNd
;
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() )
188 if (!rState
.nLevel
--)
190 pONd
= pTextNd
->FindOutlineNodeOfLevel(rState
.nLevel
, pLayout
);
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();
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());
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
234 case FIELD_PROP_BYTE1
:
235 rAny
<<= static_cast<sal_Int8
>(m_State
.nLevel
);
238 case FIELD_PROP_USHORT1
:
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
;
248 case CF_NUM_NOPREPST_TITLE
:
249 nRet
= text::ChapterFormat::NO_PREFIX_SUFFIX
;
252 default: nRet
= text::ChapterFormat::NAME_NUMBER
;
264 bool SwChapterField::PutValue( const uno::Any
& rAny
, sal_uInt16 nWhichId
)
269 case FIELD_PROP_BYTE1
:
273 if(nTmp
>= 0 && nTmp
< MAXLEVEL
)
275 m_State
.nLevel
= nTmp
;
276 m_StateRLHidden
.nLevel
= nTmp
;
283 case FIELD_PROP_USHORT1
:
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
);
294 case text::ChapterFormat::DIGIT
:
295 SetFormat(CF_NUMBER_NOPREPST
);
298 default: SetFormat(CF_NUM_TITLE
);
309 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */