LibreOffice Module sw (master)  1
chpfld.cxx
Go to the documentation of this file.
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 
20 #include <sal/config.h>
21 
22 #include <string_view>
23 
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>
36 
37 using namespace ::com::sun::star;
38 
39 namespace
40 {
41 
42 OUString removeControlChars(std::u16string_view sIn)
43 {
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)
48  {
49  if (aBuf[i] < ' ')
50  {
51  sal_Int32 j = i+1;
52  while (j<nLen && aBuf[j]<' ') ++j;
53  aBuf.remove(i, j-i);
54  nLen = aBuf.getLength();
55  }
56  }
57  return aBuf.makeStringAndClear();
58 }
59 
60 }
61 
64 {
65 }
66 
67 std::unique_ptr<SwFieldType> SwChapterFieldType::Copy() const
68 {
69  return std::make_unique<SwChapterFieldType>();
70 }
71 
72 // chapter field
73 
75  : SwField(pTyp, nFormat)
76 {
77 }
78 
80 {
81  State const& rState(pLayout && pLayout->IsHideRedlines() ? m_StateRLHidden : m_State);
82  return rState.nLevel;
83 }
84 
85 // this is called from UI or from import filters, so override both states
87 {
88  m_State.nLevel = nLev;
89  m_StateRLHidden.nLevel = nLev;
90 }
91 
92 const OUString& SwChapterField::GetNumber(SwRootFrame const*const pLayout) const
93 {
94  State const& rState(pLayout && pLayout->IsHideRedlines() ? m_StateRLHidden : m_State);
95  return rState.sNumber;
96 }
97 
98 const OUString& SwChapterField::GetTitle(SwRootFrame const*const pLayout) const
99 {
100  State const& rState(pLayout && pLayout->IsHideRedlines() ? m_StateRLHidden : m_State);
101  return rState.sTitle;
102 }
103 
104 OUString SwChapterField::ExpandImpl(SwRootFrame const*const pLayout) const
105 {
106  State const& rState(pLayout && pLayout->IsHideRedlines() ? m_StateRLHidden : m_State);
107  switch( GetFormat() )
108  {
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;
116  return rState.sNumber + rState.sLabelFollowedBy + rState.sTitle;
117  }
118  // CF_NUMBER_NOPREPST
119  return rState.sNumber;
120 }
121 
122 std::unique_ptr<SwField> SwChapterField::Copy() const
123 {
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;
128 
129  return std::unique_ptr<SwField>(pTmp.release());
130 }
131 
132 // #i53420#
134  const SwContentNode* pContentNode,
135  bool bSrchNum )
136 {
137  SwDoc& rDoc = const_cast<SwDoc&>(pContentNode->GetDoc());
138 
139  const SwTextNode* pTextNode = dynamic_cast<const SwTextNode*>(pContentNode);
140  if (!pTextNode || !rFrame.IsInDocBody())
141  {
142  SwPosition aDummyPos( rDoc.GetNodes().GetEndOfContent() );
143  pTextNode = GetBodyTextNode( rDoc, aDummyPos, rFrame );
144  }
145 
146  if ( pTextNode )
147  {
148  ChangeExpansion( *pTextNode, bSrchNum, rFrame.getRootFrame() );
149  }
150 }
151 
152 void SwChapterField::ChangeExpansion(const SwTextNode &rTextNd, bool bSrchNum,
153  SwRootFrame const*const pLayout)
154 {
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();
161 
162  SwDoc& rDoc = const_cast<SwDoc&>(rTextNd.GetDoc());
163  const SwTextNode *pTextNd = rTextNd.FindOutlineNodeOfLevel(rState.nLevel, pLayout);
164  if( !pTextNd )
165  return;
166 
167  if( bSrchNum )
168  {
169  const SwTextNode* pONd = pTextNd;
170  do {
171  if( pONd && pONd->GetTextColl() )
172  {
173  sal_uInt8 nPrevLvl = rState.nLevel;
174 
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());
178 
179  if (nPrevLvl < rState.nLevel)
180  rState.nLevel = nPrevLvl;
181  else if( SVX_NUM_NUMBER_NONE != rDoc.GetOutlineNumRule()
182  ->Get( rState.nLevel ).GetNumberingType() )
183  {
184  pTextNd = pONd;
185  break;
186  }
187 
188  if (!rState.nLevel--)
189  break;
190  pONd = pTextNd->FindOutlineNodeOfLevel(rState.nLevel, pLayout);
191  }
192  else
193  break;
194  } while( true );
195  }
196 
197  // get the number without Pre-/Post-fixstrings
198 
199  if ( pTextNd->IsOutline() )
200  {
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);
205 
206  SwNumRule* pRule( pTextNd->GetNumRule() );
207  if ( pTextNd->IsCountedInList() && pRule )
208  {
209  int nListLevel = pTextNd->GetActualListLevel();
210  if (nListLevel < 0)
211  nListLevel = 0;
212  if (nListLevel >= MAXLEVEL)
213  nListLevel = MAXLEVEL - 1;
214 
215  const SwNumFormat& rNFormat = pRule->Get(nListLevel);
216  rState.sPost = rNFormat.GetSuffix();
217  rState.sPre = rNFormat.GetPrefix();
218  rState.sLabelFollowedBy = removeControlChars(rNFormat.GetLabelFollowedByAsString());
219  }
220  }
221  else
222  {
223  rState.sNumber = "??";
224  }
225 
226  rState.sTitle = removeControlChars(sw::GetExpandTextMerged(pLayout,
227  *pTextNd, false, false, ExpandMode(0)));
228 }
229 
230 bool SwChapterField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
231 {
232  switch( nWhichId )
233  {
234  case FIELD_PROP_BYTE1:
235  rAny <<= static_cast<sal_Int8>(m_State.nLevel);
236  break;
237 
238  case FIELD_PROP_USHORT1:
239  {
240  sal_Int16 nRet;
241  switch( GetFormat() )
242  {
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;
249  nRet = text::ChapterFormat::NO_PREFIX_SUFFIX;
250  break;
251  case CF_NUM_TITLE:
252  default: nRet = text::ChapterFormat::NAME_NUMBER;
253  }
254  rAny <<= nRet;
255  }
256  break;
257 
258  default:
259  assert(false);
260  }
261  return true;
262 }
263 
264 bool SwChapterField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
265 {
266  bool bRet = true;
267  switch( nWhichId )
268  {
269  case FIELD_PROP_BYTE1:
270  {
271  sal_Int8 nTmp = 0;
272  rAny >>= nTmp;
273  if(nTmp >= 0 && nTmp < MAXLEVEL)
274  {
275  m_State.nLevel = nTmp;
276  m_StateRLHidden.nLevel = nTmp;
277  }
278  else
279  bRet = false;
280  break;
281  }
282 
283  case FIELD_PROP_USHORT1:
284  {
285  sal_Int16 nVal = 0;
286  rAny >>= nVal;
287  switch( nVal )
288  {
290  case text::ChapterFormat::NUMBER: SetFormat(CF_NUMBER); break;
291  case text::ChapterFormat::NO_PREFIX_SUFFIX:
293  break;
294  case text::ChapterFormat::DIGIT:
296  break;
297 
298  default: SetFormat(CF_NUM_TITLE);
299  }
300  }
301  break;
302 
303  default:
304  assert(false);
305  }
306  return bRet;
307 }
308 
309 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SvxNumType GetNumberingType() const
Instances of SwFields and those derived from it occur 0 to n times.
Definition: fldbas.hxx:242
Base class of the Writer layout elements.
Definition: frame.hxx:315
Marks a position in the document model.
Definition: pam.hxx:36
bool IsInDocBody() const
Definition: frame.hxx:944
bool IsOutline() const
Returns if this text node is an outline.
Definition: ndtxt.cxx:3953
sal_uInt32 GetFormat() const
Query parameters for dialog and for BASIC.
Definition: fldbas.hxx:401
signed char sal_Int8
const SwTextNode * GetBodyTextNode(const SwDoc &rDoc, SwPosition &rPos, const SwFrame &rFrame)
Forward declaration: get "BodyTextNode" for exp.fld in Fly's headers/footers/footnotes.
Definition: expfld.cxx:163
SVX_NUM_NUMBER_NONE
Base class of all fields.
Definition: fldbas.hxx:293
#define FIELD_PROP_USHORT1
Definition: unofldmid.h:31
Definition: doc.hxx:188
only chapter number without post-/prefix
Definition: chpfld.hxx:35
constexpr sal_uInt8 MAXLEVEL
Definition: swtypes.hxx:93
aBuf
void SetLevel(sal_uInt8)
Definition: chpfld.cxx:86
The root element of a Writer document layout.
Definition: rootfrm.hxx:82
int GetActualListLevel() const
Returns the actual list level of this text node, when it is a list item.
Definition: ndtxt.cxx:4063
int GetAttrOutlineLevel() const
Returns outline level of this text node.
Definition: ndtxt.cxx:3983
chapter number without post-/prefix and title
Definition: chpfld.hxx:36
virtual bool PutValue(const css::uno::Any &rVal, sal_uInt16 nWhich) override
Definition: chpfld.cxx:264
virtual OUString ExpandImpl(SwRootFrame const *pLayout) const override
Definition: chpfld.cxx:104
const OUString & GetTitle(SwRootFrame const *pLayout=nullptr) const
Definition: chpfld.cxx:98
const OUString & GetPrefix() const
const OUString & GetSuffix() const
SwNode & GetEndOfContent() const
Regular ContentSection (i.e. the BodyText).
Definition: ndarr.hxx:161
OUString GetExpandTextMerged(SwRootFrame const *const pLayout, SwTextNode const &rNode, bool const bWithNumber, bool const bWithSpacesForLevel, ExpandMode const i_mode)
number and title
Definition: chpfld.hxx:34
int i
SwDoc & GetDoc()
Definition: node.hxx:213
sal_uInt8 GetLevel(SwRootFrame const *pLayout=nullptr) const
Definition: chpfld.cxx:79
SwFieldIds
Definition: fldbas.hxx:46
SwNumRule * GetNumRule(bool bInParent=true) const
Returns numbering rule of this text node.
Definition: ndtxt.cxx:2777
void SetFormat(sal_uInt32 const nSet)
Definition: fldbas.hxx:307
#define FIELD_PROP_BYTE1
Definition: unofldmid.h:33
sal_uInt8 nLevel
Definition: chpfld.hxx:55
OUString GetLabelFollowedByAsString() const
SwFieldType * GetTyp() const
Definition: fldbas.hxx:396
only the chapter number
Definition: chpfld.hxx:32
const SwNumFormat & Get(sal_uInt16 i) const
Definition: number.cxx:86
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
virtual std::unique_ptr< SwFieldType > Copy() const override
Definition: chpfld.cxx:67
ExpandMode
Some helpers for converting model strings to view strings.
const SwTextNode * FindOutlineNodeOfLevel(sal_uInt8 nLvl, SwRootFrame const *pLayout=nullptr) const
Definition: node.cxx:773
void ChangeExpansion(const SwFrame &, const SwContentNode *, bool bSrchNum=false)
Definition: chpfld.cxx:133
unsigned char sal_uInt8
bool IsCountedInList() const
Definition: ndtxt.cxx:4201
SwNodes & GetNodes()
Definition: doc.hxx:409
virtual std::unique_ptr< SwField > Copy() const override
Definition: chpfld.cxx:122
bool IsHideRedlines() const
Replacement for sw::DocumentRedlineManager::GetRedlineFlags() (this is layout-level redline hiding)...
Definition: rootfrm.hxx:422
const OUString & GetNumber(SwRootFrame const *pLayout=nullptr) const
Definition: chpfld.cxx:92
State m_StateRLHidden
Definition: chpfld.hxx:64
OUString GetNumString(const bool _bInclPrefixAndSuffixStrings=true, const unsigned int _nRestrictToThisLevel=MAXLEVEL, SwRootFrame const *pLayout=nullptr) const
Returns outline of numbering string.
Definition: ndtxt.cxx:3083
virtual bool QueryValue(css::uno::Any &rVal, sal_uInt16 nWhich) const override
Definition: chpfld.cxx:230
SwChapterField(SwChapterFieldType *, sal_uInt32 nFormat=0)
Definition: chpfld.cxx:74
SwRootFrame * getRootFrame()
Definition: frame.hxx:680
State m_State
Definition: chpfld.hxx:63
SwNumRule * GetOutlineNumRule() const
Definition: doc.hxx:1024
only the title
Definition: chpfld.hxx:33
SwTextFormatColl * GetTextColl() const
Definition: ndtxt.hxx:850