summaryrefslogtreecommitdiffstats
path: root/sw/source/core/fields/chpfld.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/fields/chpfld.cxx')
-rw-r--r--sw/source/core/fields/chpfld.cxx309
1 files changed, 309 insertions, 0 deletions
diff --git a/sw/source/core/fields/chpfld.cxx b/sw/source/core/fields/chpfld.cxx
new file mode 100644
index 000000000..fe591d11a
--- /dev/null
+++ b/sw/source/core/fields/chpfld.cxx
@@ -0,0 +1,309 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <com/sun/star/text/ChapterFormat.hpp>
+#include <osl/diagnose.h>
+#include <doc.hxx>
+#include <frame.hxx>
+#include <rootfrm.hxx>
+#include <txtfrm.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <chpfld.hxx>
+#include <expfld.hxx>
+#include <unofldmid.h>
+#include <numrule.hxx>
+
+using namespace ::com::sun::star;
+
+namespace
+{
+
+OUString removeControlChars(std::u16string_view sIn)
+{
+ OUStringBuffer aBuf(sIn);
+ aBuf = aBuf.replace('\n', ' ').replace('\t', ' ');
+ sal_Int32 nLen = aBuf.getLength();
+ for (sal_Int32 i = 0; i < nLen; ++i)
+ {
+ if (aBuf[i] < ' ')
+ {
+ sal_Int32 j = i+1;
+ while (j<nLen && aBuf[j]<' ') ++j;
+ aBuf.remove(i, j-i);
+ nLen = aBuf.getLength();
+ }
+ }
+ return aBuf.makeStringAndClear();
+}
+
+}
+
+SwChapterFieldType::SwChapterFieldType()
+ : SwFieldType( SwFieldIds::Chapter )
+{
+}
+
+std::unique_ptr<SwFieldType> SwChapterFieldType::Copy() const
+{
+ return std::make_unique<SwChapterFieldType>();
+}
+
+// chapter field
+
+SwChapterField::SwChapterField(SwChapterFieldType* pTyp, sal_uInt32 nFormat)
+ : SwField(pTyp, nFormat)
+{
+}
+
+sal_uInt8 SwChapterField::GetLevel(SwRootFrame const*const pLayout) const
+{
+ State const& rState(pLayout && pLayout->IsHideRedlines() ? m_StateRLHidden : m_State);
+ return rState.nLevel;
+}
+
+// this is called from UI or from import filters, so override both states
+void SwChapterField::SetLevel(sal_uInt8 nLev)
+{
+ m_State.nLevel = nLev;
+ m_StateRLHidden.nLevel = nLev;
+}
+
+const OUString& SwChapterField::GetNumber(SwRootFrame const*const pLayout) const
+{
+ State const& rState(pLayout && pLayout->IsHideRedlines() ? m_StateRLHidden : m_State);
+ return rState.sNumber;
+}
+
+const OUString& SwChapterField::GetTitle(SwRootFrame const*const pLayout) const
+{
+ State const& rState(pLayout && pLayout->IsHideRedlines() ? m_StateRLHidden : m_State);
+ return rState.sTitle;
+}
+
+OUString SwChapterField::ExpandImpl(SwRootFrame const*const pLayout) const
+{
+ State const& rState(pLayout && pLayout->IsHideRedlines() ? m_StateRLHidden : m_State);
+ switch( GetFormat() )
+ {
+ case CF_TITLE:
+ return rState.sTitle;
+ case CF_NUMBER:
+ return rState.sPre + rState.sNumber + rState.sPost;
+ case CF_NUM_TITLE:
+ return rState.sPre + rState.sNumber + rState.sPost + rState.sLabelFollowedBy + rState.sTitle;
+ case CF_NUM_NOPREPST_TITLE:
+ return rState.sNumber + rState.sLabelFollowedBy + rState.sTitle;
+ }
+ // CF_NUMBER_NOPREPST
+ return rState.sNumber;
+}
+
+std::unique_ptr<SwField> SwChapterField::Copy() const
+{
+ std::unique_ptr<SwChapterField> pTmp(
+ new SwChapterField(static_cast<SwChapterFieldType*>(GetTyp()), GetFormat()));
+ pTmp->m_State = m_State;
+ pTmp->m_StateRLHidden = m_StateRLHidden;
+
+ return std::unique_ptr<SwField>(pTmp.release());
+}
+
+// #i53420#
+void SwChapterField::ChangeExpansion(const SwFrame & rFrame,
+ const SwContentNode* pContentNode,
+ bool bSrchNum )
+{
+ SwDoc& rDoc = const_cast<SwDoc&>(pContentNode->GetDoc());
+
+ const SwTextNode* pTextNode = dynamic_cast<const SwTextNode*>(pContentNode);
+ if (!pTextNode || !rFrame.IsInDocBody())
+ {
+ SwPosition aDummyPos( rDoc.GetNodes().GetEndOfContent() );
+ pTextNode = GetBodyTextNode( rDoc, aDummyPos, rFrame );
+ }
+
+ if ( pTextNode )
+ {
+ ChangeExpansion( *pTextNode, bSrchNum, rFrame.getRootFrame() );
+ }
+}
+
+void SwChapterField::ChangeExpansion(const SwTextNode &rTextNd, bool bSrchNum,
+ SwRootFrame const*const pLayout)
+{
+ State & rState(pLayout && pLayout->IsHideRedlines() ? m_StateRLHidden : m_State);
+ rState.sNumber.clear();
+ rState.sLabelFollowedBy.clear();
+ rState.sTitle.clear();
+ rState.sPost.clear();
+ rState.sPre.clear();
+
+ SwDoc& rDoc = const_cast<SwDoc&>(rTextNd.GetDoc());
+ const SwTextNode *pTextNd = rTextNd.FindOutlineNodeOfLevel(rState.nLevel, pLayout);
+ if( !pTextNd )
+ return;
+
+ if( bSrchNum )
+ {
+ const SwTextNode* pONd = pTextNd;
+ do {
+ if( pONd && pONd->GetTextColl() )
+ {
+ sal_uInt8 nPrevLvl = rState.nLevel;
+
+ OSL_ENSURE( pONd->GetAttrOutlineLevel() >= 0 && pONd->GetAttrOutlineLevel() <= MAXLEVEL,
+ "<SwChapterField::ChangeExpansion(..)> - outline node with inconsistent outline level. Serious defect." );
+ rState.nLevel = static_cast<sal_uInt8>(pONd->GetAttrOutlineLevel());
+
+ if (nPrevLvl < rState.nLevel)
+ rState.nLevel = nPrevLvl;
+ else if( SVX_NUM_NUMBER_NONE != rDoc.GetOutlineNumRule()
+ ->Get( rState.nLevel ).GetNumberingType() )
+ {
+ pTextNd = pONd;
+ break;
+ }
+
+ if (!rState.nLevel--)
+ break;
+ pONd = pTextNd->FindOutlineNodeOfLevel(rState.nLevel, pLayout);
+ }
+ else
+ break;
+ } while( true );
+ }
+
+ // get the number without Pre-/Post-fixstrings
+
+ if ( pTextNd->IsOutline() )
+ {
+ // correction of refactoring done by cws swnumtree:
+ // retrieve numbering string without prefix and suffix strings
+ // as stated in the above german comment.
+ rState.sNumber = pTextNd->GetNumString(false, MAXLEVEL, pLayout);
+
+ SwNumRule* pRule( pTextNd->GetNumRule() );
+ if ( pTextNd->IsCountedInList() && pRule )
+ {
+ int nListLevel = pTextNd->GetActualListLevel();
+ if (nListLevel < 0)
+ nListLevel = 0;
+ if (nListLevel >= MAXLEVEL)
+ nListLevel = MAXLEVEL - 1;
+
+ const SwNumFormat& rNFormat = pRule->Get(nListLevel);
+ rState.sPost = rNFormat.GetSuffix();
+ rState.sPre = rNFormat.GetPrefix();
+ rState.sLabelFollowedBy = removeControlChars(rNFormat.GetLabelFollowedByAsString());
+ }
+ }
+ else
+ {
+ rState.sNumber = "??";
+ }
+
+ rState.sTitle = removeControlChars(sw::GetExpandTextMerged(pLayout,
+ *pTextNd, false, false, ExpandMode(0)));
+}
+
+bool SwChapterField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_BYTE1:
+ rAny <<= static_cast<sal_Int8>(m_State.nLevel);
+ break;
+
+ case FIELD_PROP_USHORT1:
+ {
+ sal_Int16 nRet;
+ switch( GetFormat() )
+ {
+ case CF_NUMBER: nRet = text::ChapterFormat::NUMBER; break;
+ case CF_TITLE: nRet = text::ChapterFormat::NAME; break;
+ case CF_NUMBER_NOPREPST:
+ nRet = text::ChapterFormat::DIGIT;
+ break;
+ case CF_NUM_NOPREPST_TITLE:
+ nRet = text::ChapterFormat::NO_PREFIX_SUFFIX;
+ break;
+ case CF_NUM_TITLE:
+ default: nRet = text::ChapterFormat::NAME_NUMBER;
+ }
+ rAny <<= nRet;
+ }
+ break;
+
+ default:
+ assert(false);
+ }
+ return true;
+}
+
+bool SwChapterField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ bool bRet = true;
+ switch( nWhichId )
+ {
+ case FIELD_PROP_BYTE1:
+ {
+ sal_Int8 nTmp = 0;
+ rAny >>= nTmp;
+ if(nTmp >= 0 && nTmp < MAXLEVEL)
+ {
+ m_State.nLevel = nTmp;
+ m_StateRLHidden.nLevel = nTmp;
+ }
+ else
+ bRet = false;
+ break;
+ }
+
+ case FIELD_PROP_USHORT1:
+ {
+ sal_Int16 nVal = 0;
+ rAny >>= nVal;
+ switch( nVal )
+ {
+ case text::ChapterFormat::NAME: SetFormat(CF_TITLE); break;
+ case text::ChapterFormat::NUMBER: SetFormat(CF_NUMBER); break;
+ case text::ChapterFormat::NO_PREFIX_SUFFIX:
+ SetFormat(CF_NUM_NOPREPST_TITLE);
+ break;
+ case text::ChapterFormat::DIGIT:
+ SetFormat(CF_NUMBER_NOPREPST);
+ break;
+
+ default: SetFormat(CF_NUM_TITLE);
+ }
+ }
+ break;
+
+ default:
+ assert(false);
+ }
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */