include/xmloff/xmltoken.hxx                                         |    1 
 offapi/com/sun/star/text/textfield/PageCountRange.idl               |   40 ++++
 officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu |    8 
 schema/libreoffice/OpenDocument-v1.4+libreoffice-schema.rng         |   11 +
 sw/inc/cmdid.h                                                      |    1 
 sw/inc/docufld.hxx                                                  |   13 +
 sw/inc/strings.hrc                                                  |    1 
 sw/inc/swabstdlg.hxx                                                |    1 
 sw/inc/unocoll.hxx                                                  |    2 
 sw/inc/unoprnms.hxx                                                 |    1 
 sw/qa/extras/odfexport/data/tdf71583.odt                            |binary
 sw/qa/extras/odfexport/odfexport2.cxx                               |    9 +
 sw/qa/extras/uiwriter/uiwriter9.cxx                                 |   83 
++++++++++
 sw/sdi/_textsh.sdi                                                  |    8 
 sw/sdi/swriter.sdi                                                  |   17 ++
 sw/source/core/doc/DocumentFieldsManager.cxx                        |   11 +
 sw/source/core/fields/docufld.cxx                                   |   66 
+++++++
 sw/source/core/inc/frame.hxx                                        |    1 
 sw/source/core/layout/trvlfrm.cxx                                   |   66 
++++++-
 sw/source/core/text/txtfld.cxx                                      |    6 
 sw/source/core/unocore/unocoll.cxx                                  |    4 
 sw/source/core/unocore/unofield.cxx                                 |    7 
 sw/source/ui/dialog/swdlgfact.cxx                                   |    1 
 sw/source/ui/misc/pagenumberdlg.cxx                                 |   19 ++
 sw/source/uibase/docvw/HeaderFooterWin.cxx                          |    5 
 sw/source/uibase/fldui/fldmgr.cxx                                   |    1 
 sw/source/uibase/inc/pagenumberdlg.hxx                              |    3 
 sw/source/uibase/shells/textfld.cxx                                 |   12 -
 sw/uiconfig/sglobal/popupmenu/insertfield.xml                       |    1 
 sw/uiconfig/swform/popupmenu/insertfield.xml                        |    1 
 sw/uiconfig/swreport/popupmenu/insertfield.xml                      |    1 
 sw/uiconfig/swriter/popupmenu/insertfield.xml                       |    1 
 sw/uiconfig/swriter/ui/hfmenubutton.ui                              |    8 
 sw/uiconfig/swriter/ui/pagenumberdlg.ui                             |   28 +++
 sw/uiconfig/swxform/popupmenu/insertfield.xml                       |    1 
 xmloff/inc/txtflde.hxx                                              |    5 
 xmloff/source/core/xmltoken.cxx                                     |    1 
 xmloff/source/text/txtflde.cxx                                      |   30 +++
 xmloff/source/text/txtfldi.cxx                                      |    4 
 xmloff/source/token/tokens.txt                                      |    1 
 40 files changed, 437 insertions(+), 43 deletions(-)

New commits:
commit 554d2769d1c8c5b2fa03d2c72e91c92a94fb3cd8
Author:     Oliver Specht <oliver.spe...@cib.de>
AuthorDate: Mon Dec 9 13:10:22 2024 +0100
Commit:     Thorsten Behrens <thorsten.behr...@allotropia.de>
CommitDate: Sat Mar 8 14:59:16 2025 +0100

    tdf#71583 Add page count of ranges with consecutive page numbering
    
    Adds a field that counts the pages in ranges defined by page number restarts
    
    Change-Id: Ie0727ab20c81464918ad5fb9aa42046bf00aa63c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/178141
    Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de>
    Tested-by: Gabor Kelemen <gabor.kelemen.ext...@allotropia.de>
    Tested-by: Jenkins

diff --git a/include/xmloff/xmltoken.hxx b/include/xmloff/xmltoken.hxx
index e6a82d4021c2..3dadf9fa10fe 100644
--- a/include/xmloff/xmltoken.hxx
+++ b/include/xmloff/xmltoken.hxx
@@ -1489,6 +1489,7 @@ namespace xmloff::token {
         XML_PAGE_CONTENT,
         XML_PAGE_CONTINUATION_STRING,
         XML_PAGE_COUNT,
+        XML_PAGE_COUNT_RANGE,
         XML_PAGE_END_MARGIN,
         XML_PAGE_HEIGHT,
         XML_PAGE_MASTER,
diff --git a/offapi/com/sun/star/text/textfield/PageCountRange.idl 
b/offapi/com/sun/star/text/textfield/PageCountRange.idl
new file mode 100755
index 000000000000..0a74540082c6
--- /dev/null
+++ b/offapi/com/sun/star/text/textfield/PageCountRange.idl
@@ -0,0 +1,40 @@
+/* -*- 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 .
+ */
+
+
+module com { module sun { module star { module text { module textfield {
+
+/** specifies service of a text field that displays the number of pages
+ in the current range of pages with consecutive page numbering
+    @see com::sun::star::text::TextField
+*/
+published service PageCountRange
+{
+    service  com::sun::star::text::TextField;
+
+    /** specifies the type of the numbering as
+        com::sun::star::style::NumberingType
+     */
+    [property]short NumberingType;
+};
+
+
+}; }; }; }; };
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git 
a/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu 
b/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu
index bcacf991e058..9686cdb09823 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu
@@ -1188,6 +1188,14 @@
           <value>1</value>
         </prop>
       </node>
+      <node oor:name=".uno:InsertPageCountInRangeField" oor:op="replace">
+        <prop oor:name="Label" oor:type="xs:string">
+          <value xml:lang="en-US">Page Count In ~Range</value>
+        </prop>
+        <prop oor:name="Properties" oor:type="xs:int">
+          <value>1</value>
+        </prop>
+      </node>
       <node oor:name=".uno:InsertTopicField" oor:op="replace">
         <prop oor:name="Label" oor:type="xs:string">
           <value xml:lang="en-US">~Subject</value>
diff --git a/schema/libreoffice/OpenDocument-v1.4+libreoffice-schema.rng 
b/schema/libreoffice/OpenDocument-v1.4+libreoffice-schema.rng
index 50a5fa96e5b3..dfc2bba4af45 100644
--- a/schema/libreoffice/OpenDocument-v1.4+libreoffice-schema.rng
+++ b/schema/libreoffice/OpenDocument-v1.4+libreoffice-schema.rng
@@ -4033,7 +4033,6 @@ 
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.
       </rng:attribute>
     </rng:optional>
   </rng:define>
-
   <!-- TODO no proposal for page number on multipage formats -->
   <rng:define name="draw-image-attlist" combine="interleave">
     <rng:optional>
@@ -4042,4 +4041,14 @@ 
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.
       </rng:attribute>
       </rng:optional>
   </rng:define>
+  <!-- tdf#71583 -->
+  <rng:define name="paragraph-content" combine="choice">
+    <rng:element>
+        <rng:choice>
+            <rng:name>loext:page-count-range</rng:name>
+        </rng:choice>
+        <rng:ref name="common-field-num-format-attlist"/>
+        <rng:text/>
+    </rng:element>
+  </rng:define>
 </rng:grammar>
diff --git a/sw/inc/cmdid.h b/sw/inc/cmdid.h
index 5c7cda8f44af..abfe12fa9e78 100644
--- a/sw/inc/cmdid.h
+++ b/sw/inc/cmdid.h
@@ -341,6 +341,7 @@ class SwUINumRuleItem;
 #define FN_DELETE_FIELDS (FN_INSERT2 + 40)
 #define FN_DELETE_SECTIONS (FN_INSERT2 + 41)
 #define FN_DELETE_CONTENT_CONTROL (FN_INSERT2 + 42) /* Delete content control 
formatting */
+#define FN_INSERT_FLD_RANGE_PGCOUNT (FN_INSERT2 + 43) /*insert field page 
count in range*/
 
 // Region: Format
 #define FN_AUTOFORMAT_APPLY     (FN_FORMAT + 1 ) /* apply autoformat options */
diff --git a/sw/inc/docufld.hxx b/sw/inc/docufld.hxx
index 83986b735ae3..2e762987b01a 100644
--- a/sw/inc/docufld.hxx
+++ b/sw/inc/docufld.hxx
@@ -51,12 +51,14 @@ enum SwDocStatSubType
 {
     DS_BEGIN,
     DS_PAGE = DS_BEGIN,
+    // page count in current section
+    DS_PAGE_RANGE,
     DS_PARA,
     DS_WORD,
     DS_CHAR,
     DS_TBL,
     DS_GRF,
-    DS_OLE,
+    DS_OLE
 };
 
 typedef sal_uInt16  SwDocInfoSubType;
@@ -255,21 +257,24 @@ class SAL_DLLPUBLIC_RTTI SwDocStatFieldType final : 
public SwFieldType
 
 public:
     SwDocStatFieldType(SwDoc&);
-    OUString                Expand(sal_uInt16 nSubType, SvxNumType nFormat) 
const;
+    OUString                Expand(sal_uInt16 nSubType, SvxNumType nFormat,
+        sal_uInt16 nVirtPageCount) const;
     virtual std::unique_ptr<SwFieldType> Copy() const override;
 
     void             SetNumFormat( SvxNumType eFormat )  { m_nNumberingType = 
eFormat; }
+    void             UpdateRangeFields(SwRootFrame const*const pLayout);
 };
 
 class SW_DLLPUBLIC SwDocStatField final : public SwField
 {
     sal_uInt16 m_nSubType;
+    sal_uInt16 m_nVirtPageCount;
 
 public:
     SwDocStatField( SwDocStatFieldType*,
-                    sal_uInt16 nSubType, sal_uInt32 nFormat);
+                    sal_uInt16 nSubType, sal_uInt32 nFormat, sal_uInt16 
nVirtPageCount = 0);
 
-    void ChangeExpansion( const SwFrame* pFrame );
+    void ChangeExpansion( const SwFrame* pFrame, sal_uInt16 nVirtPageCount);
 
     virtual OUString    ExpandImpl(SwRootFrame const* pLayout) const override;
     virtual std::unique_ptr<SwField> Copy() const override;
diff --git a/sw/inc/strings.hrc b/sw/inc/strings.hrc
index 18a66de7b251..526c1f3ab8f6 100644
--- a/sw/inc/strings.hrc
+++ b/sw/inc/strings.hrc
@@ -1012,6 +1012,7 @@
 #define FLD_STAT_GRF                            NC_("FLD_STAT_GRF", "Image")
 #define FLD_STAT_OBJ                            NC_("FLD_STAT_OBJ", "OLE 
objects")
 #define FLD_STAT_PAGE                           NC_("FLD_STAT_PAGE", "Pages")
+#define FLD_STAT_PAGE_RANGE                     NC_("FLD_STAT_PAGE", "Pages in 
range")
 //  SubCmd DDETypes
 #define FMT_DDE_HOT                             NC_("FMT_DDE_HOT", "DDE 
automatic")
 #define FMT_DDE_NORMAL                          NC_("FMT_DDE_NORMAL", "DDE 
manual")
diff --git a/sw/inc/swabstdlg.hxx b/sw/inc/swabstdlg.hxx
index 59768a69aa55..3f4e1cd5b10d 100644
--- a/sw/inc/swabstdlg.hxx
+++ b/sw/inc/swabstdlg.hxx
@@ -241,6 +241,7 @@ public:
     virtual int GetPageNumberAlignment() const = 0;
     virtual bool GetMirrorOnEvenPages() const = 0;
     virtual bool GetIncludePageTotal() const = 0;
+    virtual bool GetIncludePageRangeTotal() const = 0;
     virtual bool GetFitIntoExistingMargins() const = 0;
     virtual SvxNumType GetPageNumberType() const = 0;
     virtual void SetPageNumberType(SvxNumType nSet) = 0;
diff --git a/sw/inc/unocoll.hxx b/sw/inc/unocoll.hxx
index b190f3e4ca1f..5bc0f5c0726a 100644
--- a/sw/inc/unocoll.hxx
+++ b/sw/inc/unocoll.hxx
@@ -126,6 +126,7 @@ enum class SwServiceType {
     FieldTypeDocInfoDescription     =  59,
     FieldTypeDocInfoCreateAuthor    =  60,
     FieldTypeDocInfoCreateDateTime  =  61,
+    FieldTypePageCountRange         =  62,
     FieldTypeDummy1                 =  63,
     FieldTypeDummy2                 =  64,
     FieldTypeDummy3                 =  65,
@@ -215,6 +216,7 @@ enum class SwServiceType {
 #define CSS_TEXT_TEXTFIELD_DATABASE_NAME                
"com.sun.star.text.textfield.DatabaseName"
 #define CSS_TEXT_TEXTFIELD_TABLE_FORMULA                
"com.sun.star.text.textfield.TableFormula"
 #define CSS_TEXT_TEXTFIELD_PAGE_COUNT                   
"com.sun.star.text.textfield.PageCount"
+#define CSS_TEXT_TEXTFIELD_PAGE_COUNT_RANGE             
"com.sun.star.text.textfield.PageCountRange"
 #define CSS_TEXT_TEXTFIELD_PARAGRAPH_COUNT              
"com.sun.star.text.textfield.ParagraphCount"
 #define CSS_TEXT_TEXTFIELD_WORD_COUNT                   
"com.sun.star.text.textfield.WordCount"
 #define CSS_TEXT_TEXTFIELD_CHARACTER_COUNT              
"com.sun.star.text.textfield.CharacterCount"
diff --git a/sw/inc/unoprnms.hxx b/sw/inc/unoprnms.hxx
index 8408c0f13fd7..82bd0b806c93 100644
--- a/sw/inc/unoprnms.hxx
+++ b/sw/inc/unoprnms.hxx
@@ -310,6 +310,7 @@ inline constexpr OUString UNO_NAME_NUMBERING_TYPE = 
u"NumberingType"_ustr;
 inline constexpr OUString UNO_NAME_OFFSET = u"Offset"_ustr;
 inline constexpr OUString UNO_NAME_ON = u"On"_ustr;
 inline constexpr OUString UNO_NAME_OPAQUE = u"Opaque"_ustr;
+inline constexpr OUString UNO_NAME_PAGE_COUNT_RANGE = u"PageCountRange"_ustr;
 inline constexpr OUString UNO_NAME_PAGE_TOGGLE = u"PageToggle"_ustr;
 inline constexpr OUString UNO_NAME_PAGE_DESC_NAME = u"PageDescName"_ustr;
 inline constexpr OUString UNO_NAME_PAGE_NUMBER_OFFSET = 
u"PageNumberOffset"_ustr;
diff --git a/sw/qa/extras/odfexport/data/tdf71583.odt 
b/sw/qa/extras/odfexport/data/tdf71583.odt
new file mode 100644
index 000000000000..034d4fa536c8
Binary files /dev/null and b/sw/qa/extras/odfexport/data/tdf71583.odt differ
diff --git a/sw/qa/extras/odfexport/odfexport2.cxx 
b/sw/qa/extras/odfexport/odfexport2.cxx
index f43067922976..41a95a022b10 100644
--- a/sw/qa/extras/odfexport/odfexport2.cxx
+++ b/sw/qa/extras/odfexport/odfexport2.cxx
@@ -2044,6 +2044,15 @@ CPPUNIT_TEST_FIXTURE(Test, testMsWordUlTrailSpace)
     }
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testTdf71583)
+{
+    // Verifies that loext:text-indent correctly round-trips
+    loadAndReload("tdf71583.odt");
+    xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
+    assertXPathNodeName(pXmlDoc, "//office:body/office:text/text:p/*[1]",
+                        "page-count-range");
+}
+
 } // end of anonymous namespace
 CPPUNIT_PLUGIN_IMPLEMENT();
 
diff --git a/sw/qa/extras/uiwriter/uiwriter9.cxx 
b/sw/qa/extras/uiwriter/uiwriter9.cxx
index 8e92bcc8d67c..d42c7fc06ee7 100644
--- a/sw/qa/extras/uiwriter/uiwriter9.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter9.cxx
@@ -19,11 +19,13 @@
 #include <com/sun/star/awt/FontSlant.hpp>
 #include <com/sun/star/table/TableBorder2.hpp>
 #include <com/sun/star/text/XDocumentIndex.hpp>
+#include <com/sun/star/text/XTextField.hpp>
 #include <com/sun/star/text/XTextFrame.hpp>
 #include <com/sun/star/text/XTextTable.hpp>
 #include <com/sun/star/text/XTextViewCursorSupplier.hpp>
 #include <com/sun/star/text/XPageCursor.hpp>
 #include <com/sun/star/text/XParagraphCursor.hpp>
+
 #include <com/sun/star/view/XSelectionSupplier.hpp>
 
 #include <comphelper/lok.hxx>
@@ -1184,6 +1186,87 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf164140)
     CPPUNIT_ASSERT_EQUAL(size_t(0), stAfterKashida.size());
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf71583)
+{
+    //create a document, multiple pages, some restart page counting
+    // insert page count in section fields and check the calculated
+    // values
+
+    auto insertParagraphAndBreak = [](sal_Int32& nParagraph, SwWrtShell& 
rWrtSh,
+                                      uno::Reference<lang::XComponent> 
xComponent,
+                                      const sal_uInt16 nPages) {
+        for (sal_uInt16 nPage = 0; nPage < nPages; ++nPage)
+        {
+            rWrtSh.Insert(u"Paragraph "_ustr);
+            rWrtSh.Insert(OUString::number(nParagraph));
+            ++nParagraph;
+            auto xModel(xComponent.queryThrow<frame::XModel>());
+            auto xFactory(xComponent.queryThrow<lang::XMultiServiceFactory>());
+            auto xTextViewCursorSupplier(
+                
xModel->getCurrentController().queryThrow<text::XTextViewCursorSupplier>());
+            auto xTextRangeCursor(
+                
xTextViewCursorSupplier->getViewCursor().queryThrow<text::XTextRange>());
+
+            uno::Reference<text::XTextField> xTextField(
+                
xFactory->createInstance(u"com.sun.star.text.TextField.PageCountRange"_ustr),
+                uno::UNO_QUERY);
+            xTextRangeCursor->getText()->insertTextContent(xTextRangeCursor, 
xTextField, false);
+
+            rWrtSh.SttEndDoc(false);
+            rWrtSh.SplitNode();
+            if (nPage < nPages - 1)
+                rWrtSh.InsertPageBreak();
+            else
+            {
+                std::optional<sal_uInt16> oPageNumber = 1;
+                OUString sPageStyle(u"Default Page Style"_ustr);
+                rWrtSh.InsertPageBreak(&sPageStyle, oPageNumber);
+            }
+        }
+    };
+
+    auto checkDocument = [this]() {
+        auto checkFieldContent = [this](uno::Reference<text::XText>& 
xBodyText, sal_uInt16 nPara,
+                                        rtl::OUString sSymbol) {
+            uno::Reference<text::XTextRange> xPara(getParagraphOfText(nPara, 
xBodyText));
+            const uno::Reference<text::XTextRange> xRun = getRun(xPara, 2);
+            uno::Reference<text::XTextField> xTextField
+                = getProperty<uno::Reference<text::XTextField>>(xRun, 
u"TextField"_ustr);
+            OUString sPresentation = xTextField->getPresentation(false);
+            CPPUNIT_ASSERT_EQUAL(sSymbol, sPresentation);
+        };
+
+        auto xModel(mxComponent.queryThrow<text::XTextDocument>());
+        uno::Reference<text::XText> xBodyText = xModel->getText();
+        OUString sCompare = u"B"_ustr;
+
+        for (sal_uInt16 nPara = 1; nPara < 25; nPara += 2)
+        {
+            if (nPara == 5)
+                sCompare = u"D"_ustr;
+            if (nPara == 13)
+                sCompare = u"F"_ustr;
+            checkFieldContent(xBodyText, nPara, sCompare);
+        }
+    };
+    createSwDoc();
+    SwWrtShell* pWrtShell = nullptr;
+    {
+        pWrtShell = getSwDocShell()->GetWrtShell();
+        CPPUNIT_ASSERT(pWrtShell);
+
+        sal_Int32 nParagraph = 0;
+        for (int i = 1; i <= 3; ++i)
+            insertParagraphAndBreak(nParagraph, *pWrtShell, mxComponent, i * 
2);
+        checkDocument();
+    }
+
+    {
+        saveAndReload(u"writer8"_ustr);
+        checkDocument();
+    }
+}
+
 } // end of anonymous namespace
 CPPUNIT_PLUGIN_IMPLEMENT();
 
diff --git a/sw/sdi/_textsh.sdi b/sw/sdi/_textsh.sdi
index a0f257d916a3..b385e798ad9b 100644
--- a/sw/sdi/_textsh.sdi
+++ b/sw/sdi/_textsh.sdi
@@ -960,6 +960,14 @@ interface BaseText
         ReadOnlyDoc = FALSE ;
     ]
 
+    FN_INSERT_FLD_RANGE_PGCOUNT
+    [
+        ExecMethod = ExecField ;
+        StateMethod = StateField ;
+        DisableFlags="SfxDisableFlags::SwOnProtectedCursor";
+        ReadOnlyDoc = FALSE ;
+    ]
+
     FN_INSERT_FLD_TITLE
     [
         ExecMethod = ExecField ;
diff --git a/sw/sdi/swriter.sdi b/sw/sdi/swriter.sdi
index b2856ba521c0..2268643f4575 100644
--- a/sw/sdi/swriter.sdi
+++ b/sw/sdi/swriter.sdi
@@ -3478,6 +3478,23 @@ SfxVoidItem InsertPageCountField FN_INSERT_FLD_PGCOUNT
     GroupId = SfxGroupId::Insert;
 ]
 
+SfxVoidItem InsertPageCountInRangeField FN_INSERT_FLD_RANGE_PGCOUNT
+()
+[
+    AutoUpdate = FALSE,
+    FastCall = FALSE,
+    ReadOnlyDoc = FALSE,
+    Toggle = FALSE,
+    Container = FALSE,
+    RecordAbsolute = FALSE,
+    RecordPerSet;
+
+    AccelConfig = TRUE,
+    MenuConfig = TRUE,
+    ToolBoxConfig = TRUE,
+    GroupId = SfxGroupId::Insert;
+]
+
 SfxObjectShellItem InsertPageFooter FN_INSERT_PAGEFOOTER
 (SfxStringItem PageStyle FN_INSERT_PAGEFOOTER,SfxBoolItem On FN_PARAM_1)
 [
diff --git a/sw/source/core/doc/DocumentFieldsManager.cxx 
b/sw/source/core/doc/DocumentFieldsManager.cxx
index 9180ca187767..1af75789e2af 100644
--- a/sw/source/core/doc/DocumentFieldsManager.cxx
+++ b/sw/source/core/doc/DocumentFieldsManager.cxx
@@ -1281,8 +1281,17 @@ void DocumentFieldsManager::UpdatePageFields(const 
SwTwips nDocPos)
             pFieldType->UpdateDocPos(nDocPos);
             break;
         case SwFieldIds::DocStat:
+        {
             pFieldType->CallSwClientNotify(sw::LegacyModifyHint(nullptr, 
nullptr));
-            break;
+            SwRootFrame const* pLayout(nullptr);
+            for (SwRootFrame const*const pLay : m_rDoc.GetAllLayouts())
+            {
+                if (!pLay->IsHideRedlines())
+                    pLayout = pLay;
+            }
+            
static_cast<SwDocStatFieldType*>(pFieldType)->UpdateRangeFields(pLayout);
+        }
+        break;
         case SwFieldIds::GetRef:
             
static_cast<SwGetRefFieldType*>(pFieldType)->UpdateStyleReferences();
             // Style references can vary across different pages (e.g. in 
header/footer)
diff --git a/sw/source/core/fields/docufld.cxx 
b/sw/source/core/fields/docufld.cxx
index fc9141f67f03..68576689f1ac 100644
--- a/sw/source/core/fields/docufld.cxx
+++ b/sw/source/core/fields/docufld.cxx
@@ -740,7 +740,8 @@ SwDocStatFieldType::SwDocStatFieldType(SwDoc& rDocument)
 {
 }
 
-OUString SwDocStatFieldType::Expand(sal_uInt16 nSubType, SvxNumType nFormat) 
const
+OUString SwDocStatFieldType::Expand(sal_uInt16 nSubType,
+    SvxNumType nFormat, sal_uInt16 nVirtPageCount) const
 {
     sal_uInt32 nVal = 0;
     const SwDocStat& rDStat = m_rDoc.getIDocumentStatistics().GetDocStat();
@@ -759,6 +760,11 @@ OUString SwDocStatFieldType::Expand(sal_uInt16 nSubType, 
SvxNumType nFormat) con
             if( SVX_NUM_PAGEDESC == nFormat )
                 nFormat = m_nNumberingType;
             break;
+        case DS_PAGE_RANGE:
+            nVal = nVirtPageCount;
+            if( SVX_NUM_PAGEDESC == nFormat )
+                nFormat = m_nNumberingType;
+            break;
         default:
             OSL_FAIL( "SwDocStatFieldType::Expand: unknown SubType" );
     }
@@ -773,26 +779,56 @@ std::unique_ptr<SwFieldType> SwDocStatFieldType::Copy() 
const
 {
     return std::make_unique<SwDocStatFieldType>(m_rDoc);
 }
+void SwDocStatFieldType::UpdateRangeFields(SwRootFrame const*const pLayout)
+{
+    std::vector<SwFormatField*> vFields;
+    GatherFields(vFields);
+    for(auto pFormatField: vFields)
+    {
+        SwDocStatField* pDocStatField = 
static_cast<SwDocStatField*>(pFormatField->GetField());
+        if (pDocStatField->GetSubType() == DS_PAGE_RANGE)
+        {
+            SwTextField* pTField = pFormatField->GetTextField();
+            const SwTextNode& rTextNd = pTField->GetTextNode();
 
+            // Always the first! (in Tab-Headline, header/footer )
+            Point aPt;
+            std::pair<Point, bool> const tmp(aPt, false);
+            const SwContentFrame *const pFrame = rTextNd.getLayoutFrame(
+                pLayout, nullptr, &tmp);
+
+            if (pFrame &&
+                pFrame->IsInDocBody() &&
+                pFrame->FindPageFrame())
+            {
+                pDocStatField->ChangeExpansion(pFrame, 
pFrame->GetVirtPageCount());
+            }
+        }
+    }
+}
 /**
  * @param pTyp
  * @param nSub SubType
  * @param nFormat
  */
-SwDocStatField::SwDocStatField(SwDocStatFieldType* pTyp, sal_uInt16 nSub, 
sal_uInt32 nFormat)
+SwDocStatField::SwDocStatField(SwDocStatFieldType* pTyp, sal_uInt16 nSub,
+    sal_uInt32 nFormat, sal_uInt16 nVirtPageCount)
     : SwField(pTyp, nFormat),
-    m_nSubType(nSub)
-{}
+    m_nSubType(nSub),
+    m_nVirtPageCount(nVirtPageCount)
+{
+}
 
 OUString SwDocStatField::ExpandImpl(SwRootFrame const*const) const
 {
-    return static_cast<SwDocStatFieldType*>(GetTyp())->Expand(m_nSubType, 
static_cast<SvxNumType>(GetFormat()));
+    return static_cast<SwDocStatFieldType*>(GetTyp())
+        ->Expand(m_nSubType, static_cast<SvxNumType>(GetFormat()), 
m_nVirtPageCount);
 }
 
 std::unique_ptr<SwField> SwDocStatField::Copy() const
 {
     return std::make_unique<SwDocStatField>(
-                    static_cast<SwDocStatFieldType*>(GetTyp()), m_nSubType, 
GetFormat() );
+        static_cast<SwDocStatFieldType*>(GetTyp()), m_nSubType, GetFormat(), 
m_nVirtPageCount );
 }
 
 sal_uInt16 SwDocStatField::GetSubType() const
@@ -805,11 +841,13 @@ void SwDocStatField::SetSubType(sal_uInt16 nSub)
     m_nSubType = nSub;
 }
 
-void SwDocStatField::ChangeExpansion( const SwFrame* pFrame )
+void SwDocStatField::ChangeExpansion(const SwFrame* pFrame, sal_uInt16 
nVirtPageCount)
 {
     if( DS_PAGE == m_nSubType && SVX_NUM_PAGEDESC == GetFormat() )
         static_cast<SwDocStatFieldType*>(GetTyp())->SetNumFormat(
                 
pFrame->FindPageFrame()->GetPageDesc()->GetNumType().GetNumberingType() );
+    else if (nVirtPageCount && DS_PAGE_RANGE == m_nSubType)
+        m_nVirtPageCount = nVirtPageCount;
 }
 
 bool SwDocStatField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
@@ -819,6 +857,9 @@ bool SwDocStatField::QueryValue( uno::Any& rAny, sal_uInt16 
nWhichId ) const
     case FIELD_PROP_USHORT2:
         rAny <<= static_cast<sal_Int16>(GetFormat());
         break;
+    case FIELD_PROP_USHORT1:
+        rAny <<= static_cast<sal_Int32>(m_nVirtPageCount);
+        break;
 
     default:
         assert(false);
@@ -844,6 +885,17 @@ bool SwDocStatField::PutValue( const uno::Any& rAny, 
sal_uInt16 nWhichId )
             }
         }
         break;
+    case FIELD_PROP_USHORT1:
+        {
+            sal_Int32 nSet = 0;
+            rAny >>= nSet;
+            if (nSet >= 0 && nSet < USHRT_MAX)
+            {
+                m_nVirtPageCount = static_cast<sal_uInt16>(nSet);
+                bRet = true;
+            }
+        }
+        break;
 
     default:
         assert(false);
diff --git a/sw/source/core/inc/frame.hxx b/sw/source/core/inc/frame.hxx
index 3ef9f4c15901..df6adf0a5e38 100644
--- a/sw/source/core/inc/frame.hxx
+++ b/sw/source/core/inc/frame.hxx
@@ -755,6 +755,7 @@ public:
 
     sal_uInt16 GetPhyPageNum() const;   // page number without offset
     SW_DLLPUBLIC sal_uInt16 GetVirtPageNum() const;  // page number with offset
+    SW_DLLPUBLIC sal_uInt16 GetVirtPageCount() const;  // page count between 
offsets
     bool OnRightPage() const { return 0 != GetPhyPageNum() % 2; };
     bool WannaRightPage() const;
     bool OnFirstPage() const;
diff --git a/sw/source/core/layout/trvlfrm.cxx 
b/sw/source/core/layout/trvlfrm.cxx
index 0b4f2d2a8eb0..865878b51822 100644
--- a/sw/source/core/layout/trvlfrm.cxx
+++ b/sw/source/core/layout/trvlfrm.cxx
@@ -1866,20 +1866,8 @@ Point SwFrame::GetRelPos() const
     return aRet;
 }
 
-/** @return the virtual page number with the offset. */
-sal_uInt16 SwFrame::GetVirtPageNum() const
+static const SwFrame* lcl_FindStartOfVirtualPages(const SwPageFrame *pPage)
 {
-    const SwPageFrame *pPage = FindPageFrame();
-    if ( !pPage || !pPage->GetUpper() )
-        return 0;
-
-    sal_uInt16 nPhyPage = pPage->GetPhyPageNum();
-    const SwRootFrame* pRootFrame = static_cast<const 
SwRootFrame*>(pPage->GetUpper());
-    if ( !pRootFrame->IsVirtPageNum() )
-        return nPhyPage;
-
-    //Search the nearest section using the virtual page number.
-    const SwFrame *pFoundFrame = nullptr;
     const SwPageFrame* pPageFrameIter = pPage;
     while (pPageFrameIter)
     {
@@ -1895,13 +1883,28 @@ sal_uInt16 SwFrame::GetVirtPageNum() const
                 pMod->CallSwClientNotify(aHint);
                 if(aHint.GetPage())
                 {
-                    pFoundFrame = aHint.GetFrame();
-                    break;
+                    return aHint.GetFrame();
                 }
             }
         }
         pPageFrameIter = static_cast<const 
SwPageFrame*>(pPageFrameIter->GetPrev());
     }
+    return nullptr;
+}
+/** @return the virtual page number with the offset. */
+sal_uInt16 SwFrame::GetVirtPageNum() const
+{
+    const SwPageFrame *pPage = FindPageFrame();
+    if ( !pPage || !pPage->GetUpper() )
+        return 0;
+
+    sal_uInt16 nPhyPage = pPage->GetPhyPageNum();
+    const SwRootFrame* pRootFrame = static_cast<const 
SwRootFrame*>(pPage->GetUpper());
+    if ( !pRootFrame->IsVirtPageNum() )
+        return nPhyPage;
+
+    //Search the nearest section using the virtual page number.
+    const SwFrame *pFoundFrame = lcl_FindStartOfVirtualPages(pPage);
     if ( pFoundFrame )
     {
         ::std::optional<sal_uInt16> oNumOffset = 
pFoundFrame->GetPageDescItem().GetNumOffset();
@@ -1917,6 +1920,39 @@ sal_uInt16 SwFrame::GetVirtPageNum() const
     return nPhyPage;
 }
 
+sal_uInt16 SwFrame::GetVirtPageCount() const
+{
+    const SwPageFrame *pPage = FindPageFrame();
+    if ( !pPage || !pPage->GetUpper() )
+        return 0;
+
+    const SwRootFrame* pRootFrame = static_cast<const 
SwRootFrame*>(pPage->GetUpper());
+    if ( !pRootFrame->IsVirtPageNum() )
+        return pRootFrame->GetPageNum();
+
+    //Search the nearest section using the virtual page number and the nearest
+    //follower without a virtual page number.
+    const SwFrame *pFoundFrame = lcl_FindStartOfVirtualPages(pPage);
+    const SwPageFrame* pEndPage = pPage;
+    const SwPageFrame* pPageFrameIter = static_cast<const 
SwPageFrame*>(pPage->GetNext());;
+    while (pPageFrameIter)
+    {
+        const SwContentFrame* pContentFrame = 
pPageFrameIter->FindFirstBodyContent();
+        if (pContentFrame)
+        {
+            const SwFormatPageDesc& rFormatPageDesc = 
pContentFrame->GetPageDescItem();
+
+            if ( rFormatPageDesc.GetNumOffset() && 
rFormatPageDesc.GetDefinedIn() )
+                break;
+            else
+                pEndPage = pPageFrameIter;
+        }
+        pPageFrameIter = static_cast<const 
SwPageFrame*>(pPageFrameIter->GetNext());
+    }
+    sal_uInt16 nStartPage = pFoundFrame ? pFoundFrame->GetPhyPageNum() : 1;
+    return pEndPage->GetPhyPageNum() - nStartPage + 1;
+}
+
 /** Determines and sets those cells which are enclosed by the selection. */
 bool SwRootFrame::MakeTableCursors( SwTableCursor& rTableCursor )
 {
diff --git a/sw/source/core/text/txtfld.cxx b/sw/source/core/text/txtfld.cxx
index 77abcff7e344..18d102f40319 100644
--- a/sw/source/core/text/txtfld.cxx
+++ b/sw/source/core/text/txtfld.cxx
@@ -117,7 +117,11 @@ SwExpandPortion *SwTextFormatter::NewFieldPortion( 
SwTextFormatInfo &rInf,
         case SwFieldIds::DocStat:
             if (!bName && pSh && !pSh->Imp()->IsUpdateExpFields())
             {
-                
static_cast<SwDocStatField*>(pField)->ChangeExpansion(m_pFrame);
+                SwDocStatField* pDocStatField = 
static_cast<SwDocStatField*>(pField);
+                sal_uInt16 nVirtPageCount = 0;
+                if (pDocStatField->GetSubType() == 
SwDocStatSubType::DS_PAGE_RANGE)
+                    nVirtPageCount = m_pFrame->GetVirtPageCount();
+                pDocStatField->ChangeExpansion(m_pFrame, nVirtPageCount);
             }
             break;
         case SwFieldIds::PageNumber:
diff --git a/sw/source/core/unocore/unocoll.cxx 
b/sw/source/core/unocore/unocoll.cxx
index 342d2913f74a..8d12d8aea92c 100644
--- a/sw/source/core/unocore/unocoll.cxx
+++ b/sw/source/core/unocore/unocoll.cxx
@@ -346,7 +346,7 @@ const ProvNamesId_Type aProvNamesId[] =
     { "com.sun.star.text.TextField.DocInfo.Description",      
SwServiceType::FieldTypeDocInfoDescription },
     { "com.sun.star.text.TextField.DocInfo.CreateAuthor",     
SwServiceType::FieldTypeDocInfoCreateAuthor },
     { "com.sun.star.text.TextField.DocInfo.CreateDateTime",   
SwServiceType::FieldTypeDocInfoCreateDateTime },
-    { "",                                                     
SwServiceType::FieldTypeDummy0 },
+    { "com.sun.star.text.TextField.PageCountRange",           
SwServiceType::FieldTypePageCountRange },
     { "",                                                     
SwServiceType::FieldTypeDummy1 },
     { "",                                                     
SwServiceType::FieldTypeDummy2 },
     { "",                                                     
SwServiceType::FieldTypeDummy3 },
@@ -428,6 +428,7 @@ const ProvNamesId_Type aProvNamesId[] =
     { CSS_TEXT_TEXTFIELD_DATABASE_NAME,               
SwServiceType::FieldTypeDatabaseName },
     { CSS_TEXT_TEXTFIELD_TABLE_FORMULA,               
SwServiceType::FieldTypeTableFormula },
     { CSS_TEXT_TEXTFIELD_PAGE_COUNT,                  
SwServiceType::FieldTypePageCount },
+    { CSS_TEXT_TEXTFIELD_PAGE_COUNT_RANGE,            
SwServiceType::FieldTypePageCountRange },
     { CSS_TEXT_TEXTFIELD_PARAGRAPH_COUNT,             
SwServiceType::FieldTypeParagraphCount },
     { CSS_TEXT_TEXTFIELD_WORD_COUNT,                  
SwServiceType::FieldTypeWordCount },
     { CSS_TEXT_TEXTFIELD_CHARACTER_COUNT,             
SwServiceType::FieldTypeCharacterCount },
@@ -734,6 +735,7 @@ SwXServiceProvider::MakeInstance(SwServiceType nObjectType, 
SwDoc & rDoc)
         case SwServiceType::FieldTypeDatabase:
         case SwServiceType::FieldTypeDatabaseName:
         case SwServiceType::FieldTypePageCount:
+        case SwServiceType::FieldTypePageCountRange:
         case SwServiceType::FieldTypeParagraphCount:
         case SwServiceType::FieldTypeWordCount:
         case SwServiceType::FieldTypeCharacterCount:
diff --git a/sw/source/core/unocore/unofield.cxx 
b/sw/source/core/unocore/unofield.cxx
index da961728d8cc..57c4d881472d 100644
--- a/sw/source/core/unocore/unofield.cxx
+++ b/sw/source/core/unocore/unofield.cxx
@@ -157,6 +157,7 @@ const ServiceIdResId aServiceToRes[] =
     {SwFieldIds::Database,           SwServiceType::FieldTypeDatabase          
    },
     {SwFieldIds::DatabaseName,       SwServiceType::FieldTypeDatabaseName      
    },
     {SwFieldIds::DocStat,            SwServiceType::FieldTypePageCount         
    },
+    {SwFieldIds::DocStat,            SwServiceType::FieldTypePageCountRange    
    },
     {SwFieldIds::DocStat,            SwServiceType::FieldTypeParagraphCount    
    },
     {SwFieldIds::DocStat,            SwServiceType::FieldTypeWordCount         
    },
     {SwFieldIds::DocStat,            SwServiceType::FieldTypeCharacterCount    
    },
@@ -247,6 +248,7 @@ static SwServiceType lcl_GetServiceForField( const SwField& 
rField )
         {
             switch( rField.GetSubType() )
             {
+            case DS_PAGE_RANGE:nSrvId = 
SwServiceType::FieldTypePageCountRange; break;
             case DS_PAGE: nSrvId = SwServiceType::FieldTypePageCount; break;
             case DS_PARA: nSrvId = SwServiceType::FieldTypeParagraphCount; 
break;
             case DS_WORD: nSrvId = SwServiceType::FieldTypeWordCount     ; 
break;
@@ -357,6 +359,7 @@ static sal_uInt16 lcl_GetPropertyMapOfService( 
SwServiceType nServiceId )
     case SwServiceType::FieldTypeDatabase: nRet = 
PROPERTY_MAP_FLDTYP_DATABASE; break;
     case SwServiceType::FieldTypeDatabaseName: nRet = 
PROPERTY_MAP_FLDTYP_DATABASE_NAME; break;
     case SwServiceType::FieldTypeTableFormula: nRet = 
PROPERTY_MAP_FLDTYP_TABLE_FORMULA; break;
+    case SwServiceType::FieldTypePageCountRange:
     case SwServiceType::FieldTypePageCount:
     case SwServiceType::FieldTypeParagraphCount:
     case SwServiceType::FieldTypeWordCount:
@@ -1856,6 +1859,7 @@ void SAL_CALL SwXTextField::attach(
             }
             break;
             case SwServiceType::FieldTypePageCount:
+            case SwServiceType::FieldTypePageCountRange:
             case SwServiceType::FieldTypeParagraphCount:
             case SwServiceType::FieldTypeWordCount:
             case SwServiceType::FieldTypeCharacterCount:
@@ -1872,12 +1876,13 @@ void SAL_CALL SwXTextField::attach(
                     case SwServiceType::FieldTypeTableCount           : 
nSubType = DS_TBL;  break;
                     case SwServiceType::FieldTypeGraphicObjectCount  : 
nSubType = DS_GRF;  break;
                     case SwServiceType::FieldTypeEmbeddedObjectCount : 
nSubType = DS_OLE;  break;
+                    case SwServiceType::FieldTypePageCountRange  :     
nSubType = DS_PAGE_RANGE; break;
                     default: break;
                 }
                 SwFieldType* pFieldType = 
pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::DocStat);
                 xField.reset(new SwDocStatField(
                         static_cast<SwDocStatFieldType*>(pFieldType),
-                        nSubType, m_pImpl->m_pProps->nUSHORT2));
+                        nSubType, m_pImpl->m_pProps->nUSHORT2, 
m_pImpl->m_pProps->nUSHORT1));
             }
             break;
             case SwServiceType::FieldTypeBibliography:
diff --git a/sw/source/ui/dialog/swdlgfact.cxx 
b/sw/source/ui/dialog/swdlgfact.cxx
index ea4e0ffa3daa..66608b9427b1 100644
--- a/sw/source/ui/dialog/swdlgfact.cxx
+++ b/sw/source/ui/dialog/swdlgfact.cxx
@@ -788,6 +788,7 @@ public:
     int GetPageNumberAlignment() const override { return 
m_pDlg->GetPageNumberAlignment(); }
     bool GetMirrorOnEvenPages() const override { return 
m_pDlg->GetMirrorOnEvenPages(); }
     bool GetIncludePageTotal() const override { return 
m_pDlg->GetIncludePageTotal(); }
+    bool GetIncludePageRangeTotal() const override { return 
m_pDlg->GetIncludePageRangeTotal(); }
     bool GetFitIntoExistingMargins() const override { return 
m_pDlg->GetFitIntoExistingMargins(); }
     SvxNumType GetPageNumberType() const override { return 
m_pDlg->GetPageNumberType(); }
     void SetPageNumberType(SvxNumType nSet) override { 
m_pDlg->SetPageNumberType(nSet); }
diff --git a/sw/source/ui/misc/pagenumberdlg.cxx 
b/sw/source/ui/misc/pagenumberdlg.cxx
index bc3cadb701e8..812ef0bdcc1a 100644
--- a/sw/source/ui/misc/pagenumberdlg.cxx
+++ b/sw/source/ui/misc/pagenumberdlg.cxx
@@ -34,6 +34,7 @@ SwPageNumberDlg::SwPageNumberDlg(weld::Window* pParent)
     , 
m_xPageNumberAlignment(m_xBuilder->weld_combo_box(u"alignmentCombo"_ustr))
     , 
m_xMirrorOnEvenPages(m_xBuilder->weld_check_button(u"mirrorCheckbox"_ustr))
     , 
m_xIncludePageTotal(m_xBuilder->weld_check_button(u"pagetotalCheckbox"_ustr))
+    , 
m_xIncludePageRangeTotal(m_xBuilder->weld_check_button(u"pagerangetotalCheckbox"_ustr))
     , m_xFitIntoExistingMargins(
           
m_xBuilder->weld_check_button(u"fitintoexistingmarginsCheckbox"_ustr))
     , m_xPageNumberTypeLB(new 
SvxPageNumberListBox(m_xBuilder->weld_combo_box(u"numfmtlb"_ustr)))
@@ -50,11 +51,14 @@ SwPageNumberDlg::SwPageNumberDlg(weld::Window* pParent)
     m_xMirrorOnEvenPages->set_sensitive(false);
     m_xMirrorOnEvenPages->set_state(TRISTATE_TRUE);
     m_xIncludePageTotal->set_state(TRISTATE_FALSE);
+    m_xIncludePageRangeTotal->set_state(TRISTATE_FALSE);
     m_xFitIntoExistingMargins->set_state(TRISTATE_FALSE);
     
SvxNumOptionsTabPageHelper::GetI18nNumbering(m_xPageNumberTypeLB->get_widget(),
                                                  
::std::numeric_limits<sal_uInt16>::max());
     m_xPageNumberTypeLB->connect_changed(LINK(this, SwPageNumberDlg, 
NumberTypeSelectHdl));
     m_xIncludePageTotal->connect_toggled(LINK(this, SwPageNumberDlg, 
IncludePageTotalChangeHdl));
+    m_xIncludePageRangeTotal->connect_toggled(
+        LINK(this, SwPageNumberDlg, IncludePageRangeTotalChangeHdl));
     updateImage();
 }
 
@@ -84,6 +88,13 @@ IMPL_LINK_NOARG(SwPageNumberDlg, NumberTypeSelectHdl, 
weld::ComboBox&, void)
 
 IMPL_LINK_NOARG(SwPageNumberDlg, IncludePageTotalChangeHdl, weld::Toggleable&, 
void)
 {
+    m_xIncludePageRangeTotal->set_sensitive(m_xIncludePageTotal->get_state() 
!= TRISTATE_TRUE);
+    updateImage();
+}
+
+IMPL_LINK_NOARG(SwPageNumberDlg, IncludePageRangeTotalChangeHdl, 
weld::Toggleable&, void)
+{
+    m_xIncludePageTotal->set_sensitive(m_xIncludePageRangeTotal->get_state() 
!= TRISTATE_TRUE);
     updateImage();
 }
 
@@ -98,6 +109,11 @@ bool SwPageNumberDlg::GetIncludePageTotal() const
     return m_xIncludePageTotal->get_state() == TRISTATE_TRUE;
 }
 
+bool SwPageNumberDlg::GetIncludePageRangeTotal() const
+{
+    return m_xIncludePageRangeTotal->get_state() == TRISTATE_TRUE;
+}
+
 bool SwPageNumberDlg::GetFitIntoExistingMargins() const
 {
     return m_xFitIntoExistingMargins->get_state() == TRISTATE_TRUE;
@@ -124,7 +140,8 @@ void SwPageNumberDlg::updateImage()
 
     OUString sText = u"#"_ustr;
 
-    if (m_xIncludePageTotal->get_state() == TRISTATE_TRUE)
+    if (m_xIncludePageTotal->get_state() == TRISTATE_TRUE
+        || m_xIncludePageRangeTotal->get_state() == TRISTATE_TRUE)
     {
         sText += " / #";
     }
diff --git a/sw/source/uibase/docvw/HeaderFooterWin.cxx 
b/sw/source/uibase/docvw/HeaderFooterWin.cxx
index c20c39dcb6e4..b96e31880e76 100644
--- a/sw/source/uibase/docvw/HeaderFooterWin.cxx
+++ b/sw/source/uibase/docvw/HeaderFooterWin.cxx
@@ -537,6 +537,11 @@ void SwHeaderFooterWin::ExecuteCommand(std::u16string_view 
rIdent)
         SfxViewFrame& rVFrame = rSh.GetView().GetViewFrame();
         rVFrame.GetBindings().Execute(FN_INSERT_FLD_PGCOUNT);
     }
+    else if (rIdent == u"insert_pagecount_in_range")
+    {
+        SfxViewFrame& rVFrame = rSh.GetView().GetViewFrame();
+        rVFrame.GetBindings().Execute(FN_INSERT_FLD_RANGE_PGCOUNT);
+    }
 }
 
 IMPL_LINK_NOARG(SwHeaderFooterWin, ClickHdl, weld::Button&, void)
diff --git a/sw/source/uibase/fldui/fldmgr.cxx 
b/sw/source/uibase/fldui/fldmgr.cxx
index 7d4d4e251b67..cfef4e3e7bf5 100644
--- a/sw/source/uibase/fldui/fldmgr.cxx
+++ b/sw/source/uibase/fldui/fldmgr.cxx
@@ -196,6 +196,7 @@ const TranslateId FMT_FF_ARY[] =
 const TranslateId FLD_STAT_ARY[] =
 {
     FLD_STAT_PAGE,
+    FLD_STAT_PAGE_RANGE,
     FLD_STAT_PARA,
     FLD_STAT_WORD,
     FLD_STAT_CHAR,
diff --git a/sw/source/uibase/inc/pagenumberdlg.hxx 
b/sw/source/uibase/inc/pagenumberdlg.hxx
index f097509b5a68..c5371fa01f1a 100644
--- a/sw/source/uibase/inc/pagenumberdlg.hxx
+++ b/sw/source/uibase/inc/pagenumberdlg.hxx
@@ -33,6 +33,7 @@ class SwPageNumberDlg final : public SfxDialogController
     std::unique_ptr<weld::ComboBox> m_xPageNumberAlignment;
     std::unique_ptr<weld::CheckButton> m_xMirrorOnEvenPages;
     std::unique_ptr<weld::CheckButton> m_xIncludePageTotal;
+    std::unique_ptr<weld::CheckButton> m_xIncludePageRangeTotal;
     std::unique_ptr<weld::CheckButton> m_xFitIntoExistingMargins;
     std::unique_ptr<SvxPageNumberListBox> m_xPageNumberTypeLB;
 
@@ -44,6 +45,7 @@ class SwPageNumberDlg final : public SfxDialogController
 
     DECL_LINK(OkHdl, weld::Button&, void);
     DECL_LINK(IncludePageTotalChangeHdl, weld::Toggleable&, void);
+    DECL_LINK(IncludePageRangeTotalChangeHdl, weld::Toggleable&, void);
     DECL_LINK(PositionSelectHdl, weld::ComboBox&, void);
     DECL_LINK(AlignmentSelectHdl, weld::ComboBox&, void);
     DECL_LINK(NumberTypeSelectHdl, weld::ComboBox&, void);
@@ -56,6 +58,7 @@ public:
     int GetPageNumberAlignment() const { return m_aPageNumberAlignment; }
     bool GetMirrorOnEvenPages() const;
     bool GetIncludePageTotal() const;
+    bool GetIncludePageRangeTotal() const;
     bool GetFitIntoExistingMargins() const;
     SvxNumType GetPageNumberType() const { return m_nPageNumberType; }
     void SetPageNumberType(SvxNumType nSet);
diff --git a/sw/source/uibase/shells/textfld.cxx 
b/sw/source/uibase/shells/textfld.cxx
index ea69fe7e8064..4a9a11eba7f2 100644
--- a/sw/source/uibase/shells/textfld.cxx
+++ b/sw/source/uibase/shells/textfld.cxx
@@ -790,8 +790,9 @@ void SwTextShell::ExecField(SfxRequest &rReq)
             bIsText = false;
             goto FIELD_INSERT;
         case FN_INSERT_FLD_PGCOUNT :
+        case FN_INSERT_FLD_RANGE_PGCOUNT:
             nInsertType = SwFieldTypesEnum::DocumentStatistics;
-            nInsertSubType = 0;
+            nInsertSubType = FN_INSERT_FLD_RANGE_PGCOUNT == nSlot ? 1 : 0;
             bIsText = false;
             nInsertFormat = SVX_NUM_PAGEDESC;
             goto FIELD_INSERT;
@@ -1401,11 +1402,13 @@ FIELD_INSERT:
                 SwInsertField_Data aData(SwFieldTypesEnum::PageNumber, 0,
                             OUString(), OUString(), SVX_NUM_PAGEDESC);
                 aMgr.InsertField(aData);
-                if (pDlg->GetIncludePageTotal())
+                if (pDlg->GetIncludePageTotal() ||
+                    pDlg->GetIncludePageRangeTotal())
                 {
                     
rDoc.getIDocumentContentOperations().InsertString(*rSh.GetCursor(), u" / 
"_ustr);
-                    SwInsertField_Data 
aPageTotalData(SwFieldTypesEnum::DocumentStatistics, DS_PAGE,
-                                                      OUString(), OUString(), 
SVX_NUM_PAGEDESC);
+                    SwInsertField_Data 
aPageTotalData(SwFieldTypesEnum::DocumentStatistics,
+                        pDlg->GetIncludePageTotal() ? DS_PAGE : DS_PAGE_RANGE,
+                        OUString(), OUString(), SVX_NUM_PAGEDESC);
                     aMgr.InsertField(aPageTotalData);
                 }
 
@@ -1731,6 +1734,7 @@ void SwTextShell::StateField( SfxItemSet &rSet )
         case FN_INSERT_FLD_AUTHOR:
         case FN_INSERT_FLD_DATE:
         case FN_INSERT_FLD_PGCOUNT:
+        case FN_INSERT_FLD_RANGE_PGCOUNT:
         case FN_INSERT_FLD_PGNUMBER:
         case FN_INSERT_FLD_TIME:
         case FN_INSERT_FLD_TITLE:
diff --git a/sw/uiconfig/sglobal/popupmenu/insertfield.xml 
b/sw/uiconfig/sglobal/popupmenu/insertfield.xml
index 48e9ae5370d3..f063065ff96c 100644
--- a/sw/uiconfig/sglobal/popupmenu/insertfield.xml
+++ b/sw/uiconfig/sglobal/popupmenu/insertfield.xml
@@ -10,6 +10,7 @@
 <menu:menupopup xmlns:menu="http://openoffice.org/2001/menu";>
   <menu:menuitem menu:id=".uno:InsertPageNumberField"/>
   <menu:menuitem menu:id=".uno:InsertPageCountField"/>
+  <menu:menuitem menu:id=".uno:InsertPageCountInRangeField"/>
   <menu:menuitem menu:id=".uno:InsertDateField"/>
   <menu:menuitem menu:id=".uno:InsertDateFieldVar"/>
   <menu:menuitem menu:id=".uno:InsertTimeField"/>
diff --git a/sw/uiconfig/swform/popupmenu/insertfield.xml 
b/sw/uiconfig/swform/popupmenu/insertfield.xml
index 48e9ae5370d3..f063065ff96c 100644
--- a/sw/uiconfig/swform/popupmenu/insertfield.xml
+++ b/sw/uiconfig/swform/popupmenu/insertfield.xml
@@ -10,6 +10,7 @@
 <menu:menupopup xmlns:menu="http://openoffice.org/2001/menu";>
   <menu:menuitem menu:id=".uno:InsertPageNumberField"/>
   <menu:menuitem menu:id=".uno:InsertPageCountField"/>
+  <menu:menuitem menu:id=".uno:InsertPageCountInRangeField"/>
   <menu:menuitem menu:id=".uno:InsertDateField"/>
   <menu:menuitem menu:id=".uno:InsertDateFieldVar"/>
   <menu:menuitem menu:id=".uno:InsertTimeField"/>
diff --git a/sw/uiconfig/swreport/popupmenu/insertfield.xml 
b/sw/uiconfig/swreport/popupmenu/insertfield.xml
index 48e9ae5370d3..f063065ff96c 100644
--- a/sw/uiconfig/swreport/popupmenu/insertfield.xml
+++ b/sw/uiconfig/swreport/popupmenu/insertfield.xml
@@ -10,6 +10,7 @@
 <menu:menupopup xmlns:menu="http://openoffice.org/2001/menu";>
   <menu:menuitem menu:id=".uno:InsertPageNumberField"/>
   <menu:menuitem menu:id=".uno:InsertPageCountField"/>
+  <menu:menuitem menu:id=".uno:InsertPageCountInRangeField"/>
   <menu:menuitem menu:id=".uno:InsertDateField"/>
   <menu:menuitem menu:id=".uno:InsertDateFieldVar"/>
   <menu:menuitem menu:id=".uno:InsertTimeField"/>
diff --git a/sw/uiconfig/swriter/popupmenu/insertfield.xml 
b/sw/uiconfig/swriter/popupmenu/insertfield.xml
index 48e9ae5370d3..f063065ff96c 100644
--- a/sw/uiconfig/swriter/popupmenu/insertfield.xml
+++ b/sw/uiconfig/swriter/popupmenu/insertfield.xml
@@ -10,6 +10,7 @@
 <menu:menupopup xmlns:menu="http://openoffice.org/2001/menu";>
   <menu:menuitem menu:id=".uno:InsertPageNumberField"/>
   <menu:menuitem menu:id=".uno:InsertPageCountField"/>
+  <menu:menuitem menu:id=".uno:InsertPageCountInRangeField"/>
   <menu:menuitem menu:id=".uno:InsertDateField"/>
   <menu:menuitem menu:id=".uno:InsertDateFieldVar"/>
   <menu:menuitem menu:id=".uno:InsertTimeField"/>
diff --git a/sw/uiconfig/swriter/ui/hfmenubutton.ui 
b/sw/uiconfig/swriter/ui/hfmenubutton.ui
index a41efba005ec..ce4e22de1e87 100644
--- a/sw/uiconfig/swriter/ui/hfmenubutton.ui
+++ b/sw/uiconfig/swriter/ui/hfmenubutton.ui
@@ -48,6 +48,14 @@
         <property name="use-underline">True</property>
       </object>
     </child>
+    <child>
+        <object class="GtkMenuItem" id="insert_pagecount_in_range">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="label" translatable="yes" 
context="headerfootermenu|insert_pagecount_in_range">Insert Page Count In 
Range</property>
+            <property name="use-underline">True</property>
+        </object>
+    </child>
   </object>
   <object class="GtkBox" id="HFMenuButton">
     <property name="visible">True</property>
diff --git a/sw/uiconfig/swriter/ui/pagenumberdlg.ui 
b/sw/uiconfig/swriter/ui/pagenumberdlg.ui
index e876594c05c5..e5ef0d86e9bf 100644
--- a/sw/uiconfig/swriter/ui/pagenumberdlg.ui
+++ b/sw/uiconfig/swriter/ui/pagenumberdlg.ui
@@ -212,6 +212,28 @@
                   </packing>
                 </child>
                 <child>
+                  <object class="GtkCheckButton" id="pagerangetotalCheckbox">
+                    <property name="label" translatable="yes" 
context="pagenumberdlg|pagerangetotalCheckbox">Include page total in 
range</property>
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">False</property>
+                    <property name="margin-start">18</property>
+                    <property name="margin-top">3</property>
+                    <property name="use-underline">True</property>
+                    <property name="draw-indicator">True</property>
+                    <child internal-child="accessible">
+                      <object class="AtkObject" 
id="pagerangetotalCheckbox-atkobject">
+                        <property name="AtkObject::accessible-description" 
translatable="yes" 
context="pagenumberdlg|extended_tip|pagerangetotalCheckbox">Also insert the 
total number of pages in range</property>
+                      </object>
+                    </child>
+                    </object>
+                    <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">6</property>
+                    </packing>
+                  </child>
+                  <child>
                   <object class="GtkCheckButton" 
id="fitintoexistingmarginsCheckbox">
                     <property name="label" translatable="yes" 
context="pagenumberdlg|fitintoexistingmarginsCheckbox">Fit into existing 
margins</property>
                     <property name="visible">True</property>
@@ -230,7 +252,7 @@
                   <packing>
                     <property name="expand">False</property>
                     <property name="fill">True</property>
-                    <property name="position">6</property>
+                    <property name="position">7</property>
                   </packing>
                 </child>
                 <child>
@@ -254,7 +276,7 @@
                   <packing>
                     <property name="expand">False</property>
                     <property name="fill">True</property>
-                    <property name="position">7</property>
+                    <property name="position">8</property>
                   </packing>
                 </child>
                 <child>
@@ -273,7 +295,7 @@
                   <packing>
                     <property name="expand">False</property>
                     <property name="fill">True</property>
-                    <property name="position">8</property>
+                    <property name="position">9</property>
                   </packing>
                 </child>
               </object>
diff --git a/sw/uiconfig/swxform/popupmenu/insertfield.xml 
b/sw/uiconfig/swxform/popupmenu/insertfield.xml
index 48e9ae5370d3..f063065ff96c 100644
--- a/sw/uiconfig/swxform/popupmenu/insertfield.xml
+++ b/sw/uiconfig/swxform/popupmenu/insertfield.xml
@@ -10,6 +10,7 @@
 <menu:menupopup xmlns:menu="http://openoffice.org/2001/menu";>
   <menu:menuitem menu:id=".uno:InsertPageNumberField"/>
   <menu:menuitem menu:id=".uno:InsertPageCountField"/>
+  <menu:menuitem menu:id=".uno:InsertPageCountInRangeField"/>
   <menu:menuitem menu:id=".uno:InsertDateField"/>
   <menu:menuitem menu:id=".uno:InsertDateFieldVar"/>
   <menu:menuitem menu:id=".uno:InsertTimeField"/>
diff --git a/xmloff/inc/txtflde.hxx b/xmloff/inc/txtflde.hxx
index 60065d90095b..30ed2d6ae71e 100644
--- a/xmloff/inc/txtflde.hxx
+++ b/xmloff/inc/txtflde.hxx
@@ -108,6 +108,8 @@ enum FieldIdEnum {
     FIELD_ID_COUNT_WORDS,           //                    - words
     FIELD_ID_COUNT_CHARACTERS,      //                    - chars
     FIELD_ID_COUNT_PAGES,           //                    - pages
+    FIELD_ID_COUNT_PAGES_RANGE,     //                    - pages in 
section/range
+
     FIELD_ID_COUNT_TABLES,          //                    - tables
     FIELD_ID_COUNT_GRAPHICS,        //                    - graphics
     FIELD_ID_COUNT_OBJECTS,         //                    - objects
@@ -227,7 +229,8 @@ private:
 
     /// export an element with string content
     void ExportElement(enum ::xmloff::token::XMLTokenEnum eElement, /// 
element token
-                       const OUString& sContent); /// element content
+                       const OUString& sContent,
+                       sal_uInt16 nNamespace = XML_NAMESPACE_TEXT); /// 
element content
 
     /// export a macro (as used in the macro field)
     void ExportMacro( const css::uno::Reference< css::beans::XPropertySet> & 
rPropSet,
diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx
index b0fc6e028c2f..aa5b24961ba8 100644
--- a/xmloff/source/core/xmltoken.cxx
+++ b/xmloff/source/core/xmltoken.cxx
@@ -1502,6 +1502,7 @@ namespace xmloff::token {
         TOKEN( "page-content",                    XML_PAGE_CONTENT ),
         TOKEN( "page-continuation-string",        XML_PAGE_CONTINUATION_STRING 
),
         TOKEN( "page-count",                      XML_PAGE_COUNT ),
+        TOKEN( "page-count-range",                XML_PAGE_COUNT_RANGE ),
         TOKEN( "page-end-margin",                 XML_PAGE_END_MARGIN ),
         TOKEN( "page-height",                     XML_PAGE_HEIGHT ),
         TOKEN( "page-master",                     XML_PAGE_MASTER ),
diff --git a/xmloff/source/text/txtflde.cxx b/xmloff/source/text/txtflde.cxx
index 3f2ac6b452f3..c0fb7aaac850 100644
--- a/xmloff/source/text/txtflde.cxx
+++ b/xmloff/source/text/txtflde.cxx
@@ -130,6 +130,7 @@ char const FIELD_SERVICE_FILE_NAME[] = "FileName";
 char const FIELD_SERVICE_CHAPTER[] = "Chapter";
 char const FIELD_SERVICE_TEMPLATE_NAME[] = "TemplateName";
 char const FIELD_SERVICE_PAGE_COUNT[] = "PageCount";
+char const FIELD_SERVICE_PAGE_COUNT_RANGE[] = "PageCountRange";
 char const FIELD_SERVICE_PARAGRAPH_COUNT[] = "ParagraphCount";
 char const FIELD_SERVICE_WORD_COUNT[] = "WordCount";
 char const FIELD_SERVICE_CHARACTER_COUNT[] = "CharacterCount";
@@ -249,6 +250,7 @@ SvXMLEnumStringMapEntry<FieldIdEnum> const 
aFieldServiceNameMapping[] =
     ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_TEMPLATE_NAME, FIELD_ID_TEMPLATE_NAME 
),
 
     ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_PAGE_COUNT, FIELD_ID_COUNT_PAGES ),
+    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_PAGE_COUNT_RANGE, 
FIELD_ID_COUNT_PAGES_RANGE ),
     ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_PARAGRAPH_COUNT, 
FIELD_ID_COUNT_PARAGRAPHS ),
     ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_WORD_COUNT, FIELD_ID_COUNT_WORDS ),
     ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_CHARACTER_COUNT, 
FIELD_ID_COUNT_CHARACTERS ),
@@ -592,6 +594,7 @@ enum FieldIdEnum XMLTextFieldExport::MapFieldName(
         case FIELD_ID_REFPAGE_SET:
         case FIELD_ID_REFPAGE_GET:
         case FIELD_ID_COUNT_PAGES:
+        case FIELD_ID_COUNT_PAGES_RANGE:
         case FIELD_ID_COUNT_PARAGRAPHS:
         case FIELD_ID_COUNT_WORDS:
         case FIELD_ID_COUNT_CHARACTERS:
@@ -683,6 +686,7 @@ bool XMLTextFieldExport::IsStringField(
         return false;
 
     case FIELD_ID_COUNT_PAGES:
+    case FIELD_ID_COUNT_PAGES_RANGE:
     case FIELD_ID_COUNT_PARAGRAPHS:
     case FIELD_ID_COUNT_WORDS:
     case FIELD_ID_COUNT_CHARACTERS:
@@ -929,6 +933,7 @@ void XMLTextFieldExport::ExportFieldAutoStyle(
     case FIELD_ID_REFPAGE_SET:
     case FIELD_ID_REFPAGE_GET:
     case FIELD_ID_COUNT_PAGES:
+    case FIELD_ID_COUNT_PAGES_RANGE:
     case FIELD_ID_COUNT_PARAGRAPHS:
     case FIELD_ID_COUNT_WORDS:
     case FIELD_ID_COUNT_CHARACTERS:
@@ -1494,9 +1499,24 @@ void XMLTextFieldExport::ExportFieldHelper(
             ProcessNumberingType(GetInt16Property(gsPropertyNumberingType,
                                                   rPropSet));
         }
-        ExportElement(MapCountFieldName(nToken), sPresentation);
+        ExportElement(MapCountFieldName(nToken), sPresentation, 
XML_NAMESPACE_TEXT);
         break;
 
+    case FIELD_ID_COUNT_PAGES_RANGE:
+        if (GetExport().getSaneDefaultVersion() & 
SvtSaveOptions::ODFSVER_EXTENDED)
+        {
+            if (xPropSetInfo->hasPropertyByName(gsPropertyNumberingType))
+            {
+                ProcessNumberingType(GetInt16Property(gsPropertyNumberingType,
+                                                      rPropSet));
+            }
+            ExportElement(MapCountFieldName(nToken), sPresentation, 
XML_NAMESPACE_LO_EXT);
+        }
+        else
+        {
+              GetExport().Characters(sPresentation);
+        }
+        break;
     case FIELD_ID_CONDITIONAL_TEXT:
         ProcessString(XML_CONDITION, XML_NAMESPACE_OOOW,
                       GetStringProperty(gsPropertyCondition, rPropSet));
@@ -2271,13 +2291,14 @@ void XMLTextFieldExport::ExportElement(enum 
XMLTokenEnum eElementName,
 }
 
 void XMLTextFieldExport::ExportElement(enum XMLTokenEnum eElementName,
-                                       const OUString& sContent)
+                                       const OUString& sContent,
+                                       sal_uInt16 nNamespace)
 {
     DBG_ASSERT(eElementName != XML_TOKEN_INVALID, "invalid element name!");
     if (eElementName != XML_TOKEN_INVALID)
     {
         // Element
-        SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
+        SvXMLElementExport aElem( GetExport(), nNamespace,
                 eElementName, false, false );
         // export content
         GetExport().Characters(sContent);
@@ -3050,6 +3071,9 @@ enum XMLTokenEnum 
XMLTextFieldExport::MapCountFieldName(FieldIdEnum nToken)
         case FIELD_ID_COUNT_PAGES:
             eElement = XML_PAGE_COUNT;
             break;
+        case FIELD_ID_COUNT_PAGES_RANGE:
+            eElement = XML_PAGE_COUNT_RANGE;
+            break;
         case FIELD_ID_COUNT_PARAGRAPHS:
             eElement = XML_PARAGRAPH_COUNT;
             break;
diff --git a/xmloff/source/text/txtfldi.cxx b/xmloff/source/text/txtfldi.cxx
index fcaf900b8f41..ed14e1edb1a8 100644
--- a/xmloff/source/text/txtfldi.cxx
+++ b/xmloff/source/text/txtfldi.cxx
@@ -383,6 +383,7 @@ XMLTextFieldImportContext::CreateTextFieldImportContext(
         case XML_ELEMENT(TEXT, XML_IMAGE_COUNT):
         case XML_ELEMENT(TEXT, XML_OBJECT_COUNT):
         case XML_ELEMENT(TEXT, XML_PAGE_COUNT):
+        case XML_ELEMENT(LO_EXT, XML_PAGE_COUNT_RANGE):
             pContext = new XMLCountFieldImportContext( rImport, rHlp, nToken);
             break;
 
@@ -2238,6 +2239,9 @@ OUString 
XMLCountFieldImportContext::MapTokenToServiceName(
         case XML_ELEMENT(TEXT, XML_PAGE_COUNT):
             pServiceName = "PageCount";
             break;
+        case XML_ELEMENT(LO_EXT, XML_PAGE_COUNT_RANGE):
+            pServiceName = "PageCountRange";
+            break;
         default:
             XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
             assert(false);
diff --git a/xmloff/source/token/tokens.txt b/xmloff/source/token/tokens.txt
index 004243725964..d11a6d02e77c 100644
--- a/xmloff/source/token/tokens.txt
+++ b/xmloff/source/token/tokens.txt
@@ -1402,6 +1402,7 @@ page-breaks-on-group-change
 page-content
 page-continuation-string
 page-count
+page-count-range
 page-end-margin
 page-height
 page-master

Reply via email to