cui/source/inc/paragrph.hxx                                 |    8 
 cui/source/tabpages/paragrph.cxx                            |   70 +++
 cui/uiconfig/ui/paragalignpage.ui                           |   90 ++++
 editeng/source/items/paraitem.cxx                           |   24 +
 include/editeng/adjustitem.hxx                              |   27 +
 include/editeng/memberids.h                                 |    2 
 include/editeng/unotext.hxx                                 |    2 
 include/xmloff/xmltoken.hxx                                 |    2 
 offapi/com/sun/star/style/ParagraphProperties.idl           |   26 +
 schema/libreoffice/OpenDocument-v1.4+libreoffice-schema.rng |   24 +
 svx/sdi/svxitems.sdi                                        |    2 
 sw/inc/inspectorproperties.hrc                              |    2 
 sw/inc/unoprnms.hxx                                         |    2 
 sw/qa/extras/layout/data/tdf126154.fodt                     |  245 ++++++++++++
 sw/qa/extras/layout/layout3.cxx                             |   89 ++++
 sw/qa/uitest/styleInspector/styleInspector.py               |   24 -
 sw/qa/uitest/styleInspector/tdf137513.py                    |    2 
 sw/source/core/text/guess.cxx                               |   35 +
 sw/source/core/text/guess.hxx                               |    3 
 sw/source/core/text/portxt.cxx                              |   53 ++
 sw/source/core/unocore/unomapproperties.hxx                 |    4 
 sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx       |    2 
 xmloff/inc/xmlprop.hxx                                      |    2 
 xmloff/source/core/xmltoken.cxx                             |    2 
 xmloff/source/style/xmlexppr.cxx                            |    4 
 xmloff/source/text/txtprmap.cxx                             |    2 
 xmloff/source/token/tokens.txt                              |    2 
 27 files changed, 715 insertions(+), 35 deletions(-)

New commits:
commit 5a48070f5904c51dc9e7bbad4213d802fd4bc89b
Author:     László Németh <nem...@numbertext.org>
AuthorDate: Wed Apr 16 13:51:28 2025 +0200
Commit:     László Németh <nem...@numbertext.org>
CommitDate: Fri Apr 25 09:54:28 2025 +0200

    tdf#126154 sw offapi xmloff cui: add min/max word spacing
    
    To avoid of rivers and too much hyphenation, add minimum
    and maximum word spacing options, similar to XSL-FO/CSS
    and DTP software.
    
    Only limiting hyphenation was implemented: hyphenation
    of the words are disabled, if it's possible to expand
    or shrink the spaces of the line within the values specified
    by the maximum and minimum word spacing. First try to apply
    the minimum word spacing, and if not possible, then the
    maximum word spacing.
    
    Note: maximum allowed shrinking has been applied for the
    hyphenated lines instead of the minimum to remove the
    hyphenation, yet. With the suggested default word spacing
    values, this results no or minimal differences.
    
    New UNO paragraph properties:
    
      com::sun::star::text::ParaWordSpacingMinimum
    
      com::sun::star::text::ParaWordSpacingMaximum
    
    New ODF paragraph attributes:
    
      loext:word-spacing-minimum
    
      loext:word-spacing-maximum
    
    New paragraph settings on Text Align pane:
    
      Minimum word spacing
    
      Maximum word spacing
    
    While the desired word spacing got "Desired" label.
    
    Note: suggested values of minimum, desired and
    maximum word spacing are 80%, 100% and 133% (default
    values e.g. in Adobe InDesign), in narrow columns e.g.
    60%, 100% and 150%.
    
    Follow-up to commit 7d6696757dcdfa3cee481ac7795a91b2b47da363
    "tdf#159923 sw cui offapi xmloff: add custom word spacing".
    
    Change-Id: I7f2a07f7fdb634cb16cdd8c2c937ca911b968405
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184595
    Reviewed-by: László Németh <nem...@numbertext.org>
    Tested-by: Jenkins

diff --git a/cui/source/inc/paragrph.hxx b/cui/source/inc/paragrph.hxx
index 14916178d752..4975027f0857 100644
--- a/cui/source/inc/paragrph.hxx
+++ b/cui/source/inc/paragrph.hxx
@@ -152,11 +152,19 @@ class SvxParaAlignTabPage : public SfxTabPage
 
     /// word spacing
     std::unique_ptr<weld::Label> m_xLabelWordSpacing;
+    std::unique_ptr<weld::Label> m_xLabelMinimum;
+    std::unique_ptr<weld::Label> m_xLabelDesired;
+    std::unique_ptr<weld::Label> m_xLabelMaximum;
     std::unique_ptr<weld::MetricSpinButton> m_xWordSpacing;
+    std::unique_ptr<weld::MetricSpinButton> m_xWordSpacingMinimum;
+    std::unique_ptr<weld::MetricSpinButton> m_xWordSpacingMaximum;
 
     DECL_LINK(AlignHdl_Impl, weld::Toggleable&, void);
     DECL_LINK(LastLineHdl_Impl, weld::ComboBox&, void);
     DECL_LINK(TextDirectionHdl_Impl, weld::ComboBox&, void);
+    DECL_LINK(WordSpacingHdl_Impl, weld::MetricSpinButton&, void);
+    DECL_LINK(WordSpacingMinimumHdl_Impl, weld::MetricSpinButton&, void);
+    DECL_LINK(WordSpacingMaximumHdl_Impl, weld::MetricSpinButton&, void);
 
     void                    UpdateExample_Impl();
 
diff --git a/cui/source/tabpages/paragrph.cxx b/cui/source/tabpages/paragrph.cxx
index eefd2f9119c5..212b523d6ebb 100644
--- a/cui/source/tabpages/paragrph.cxx
+++ b/cui/source/tabpages/paragrph.cxx
@@ -1280,7 +1280,12 @@ 
SvxParaAlignTabPage::SvxParaAlignTabPage(weld::Container* pPage, weld::DialogCon
     , m_xVertAlignSdr(m_xBuilder->weld_label(u"labelST_VERTALIGN_SDR"_ustr))
     , m_xTextDirectionLB(new 
svx::FrameDirectionListBox(m_xBuilder->weld_combo_box(u"comboLB_TEXTDIRECTION"_ustr)))
     , m_xLabelWordSpacing(m_xBuilder->weld_label(u"labelWordSpacing"_ustr))
+    , m_xLabelMinimum(m_xBuilder->weld_label(u"labelMinimum"_ustr))
+    , m_xLabelDesired(m_xBuilder->weld_label(u"labelDesired"_ustr))
+    , m_xLabelMaximum(m_xBuilder->weld_label(u"labelMaximum"_ustr))
     , 
m_xWordSpacing(m_xBuilder->weld_metric_spin_button(u"spin_WORD_SPACING"_ustr, 
FieldUnit::PERCENT))
+    , 
m_xWordSpacingMinimum(m_xBuilder->weld_metric_spin_button(u"spin_WORD_SPACING_MIN"_ustr,
 FieldUnit::PERCENT))
+    , 
m_xWordSpacingMaximum(m_xBuilder->weld_metric_spin_button(u"spin_WORD_SPACING_MAX"_ustr,
 FieldUnit::PERCENT))
 {
     SetExchangeSupport();
 
@@ -1318,6 +1323,12 @@ 
SvxParaAlignTabPage::SvxParaAlignTabPage(weld::Container* pPage, weld::DialogCon
     m_xTextDirectionLB->append(SvxFrameDirection::Environment, 
SvxResId(RID_SVXSTR_FRAMEDIR_SUPER));
     m_xTextDirectionLB->append(SvxFrameDirection::Horizontal_LR_TB, 
SvxResId(RID_SVXSTR_FRAMEDIR_LTR));
     m_xTextDirectionLB->append(SvxFrameDirection::Horizontal_RL_TB, 
SvxResId(RID_SVXSTR_FRAMEDIR_RTL));
+
+    // Minimum <= Desired <= Maximum word spacing
+    // apply these modifying the other values, if needed
+    m_xWordSpacing->connect_value_changed(LINK(this, SvxParaAlignTabPage, 
WordSpacingHdl_Impl));
+    m_xWordSpacingMinimum->connect_value_changed(LINK(this, 
SvxParaAlignTabPage, WordSpacingMinimumHdl_Impl));
+    m_xWordSpacingMaximum->connect_value_changed(LINK(this, 
SvxParaAlignTabPage, WordSpacingMaximumHdl_Impl));
 }
 
 SvxParaAlignTabPage::~SvxParaAlignTabPage()
@@ -1364,7 +1375,9 @@ bool SvxParaAlignTabPage::FillItemSet( SfxItemSet* 
rOutSet )
         bAdj = m_xJustify->get_saved_state() == TRISTATE_FALSE ||
             m_xExpandCB->get_state_changed_from_saved() ||
             m_xLastLineLB->get_value_changed_from_saved() ||
-            m_xWordSpacing->get_value_changed_from_saved();
+            m_xWordSpacing->get_value_changed_from_saved() ||
+            m_xWordSpacingMinimum->get_value_changed_from_saved() ||
+            m_xWordSpacingMaximum->get_value_changed_from_saved();
     }
 
     sal_uInt16 _nWhich = GetWhich( SID_ATTR_PARA_ADJUST );
@@ -1385,6 +1398,8 @@ bool SvxParaAlignTabPage::FillItemSet( SfxItemSet* 
rOutSet )
         aAdj.SetOneWord( eOneWord );
         aAdj.SetLastBlock( eLastBlock );
         aAdj.SetPropWordSpacing( m_xWordSpacing->get_value(FieldUnit::PERCENT) 
);
+        aAdj.SetPropWordSpacingMinimum( 
m_xWordSpacingMinimum->get_value(FieldUnit::PERCENT) );
+        aAdj.SetPropWordSpacingMaximum( 
m_xWordSpacingMaximum->get_value(FieldUnit::PERCENT) );
         rOutSet->Put( aAdj );
         bModified = true;
     }
@@ -1462,13 +1477,25 @@ void SvxParaAlignTabPage::Reset( const SfxItemSet* rSet 
)
         if (m_xJustify->get_active())
         {
             m_xLabelWordSpacing->set_sensitive(true);
+            m_xLabelMinimum->set_sensitive(true);
+            m_xLabelDesired->set_sensitive(true);
+            m_xLabelMaximum->set_sensitive(true);
             m_xWordSpacing->set_sensitive(true);
+            m_xWordSpacingMinimum->set_sensitive(true);
+            m_xWordSpacingMaximum->set_sensitive(true);
             m_xWordSpacing->set_value(rAdj.GetPropWordSpacing(), 
FieldUnit::PERCENT);
+            m_xWordSpacingMinimum->set_value(rAdj.GetPropWordSpacingMinimum(), 
FieldUnit::PERCENT);
+            m_xWordSpacingMaximum->set_value(rAdj.GetPropWordSpacingMaximum(), 
FieldUnit::PERCENT);
         }
         else
         {
             m_xLabelWordSpacing->set_sensitive(false);
+            m_xLabelMinimum->set_sensitive(false);
+            m_xLabelDesired->set_sensitive(false);
+            m_xLabelMaximum->set_sensitive(false);
             m_xWordSpacing->set_sensitive(false);
+            m_xWordSpacingMinimum->set_sensitive(false);
+            m_xWordSpacingMaximum->set_sensitive(false);
         }
     }
     else
@@ -1478,7 +1505,12 @@ void SvxParaAlignTabPage::Reset( const SfxItemSet* rSet )
         m_xCenter->set_active(false);
         m_xJustify->set_active(false);
         m_xLabelWordSpacing->set_sensitive(false);
+        m_xLabelMinimum->set_sensitive(false);
+        m_xLabelDesired->set_sensitive(false);
+        m_xLabelMaximum->set_sensitive(false);
         m_xWordSpacing->set_sensitive(false);
+        m_xWordSpacingMinimum->set_sensitive(false);
+        m_xWordSpacingMaximum->set_sensitive(false);
     }
     m_xLastLineLB->set_active(nLBSelect);
 
@@ -1537,6 +1569,8 @@ void SvxParaAlignTabPage::Reset( const SfxItemSet* rSet )
     m_xLastLineLB->save_value();
     m_xExpandCB->save_state();
     m_xWordSpacing->save_value();
+    m_xWordSpacingMinimum->save_value();
+    m_xWordSpacingMaximum->save_value();
 
     UpdateExample_Impl();
 }
@@ -1553,6 +1587,8 @@ void SvxParaAlignTabPage::ChangesApplied()
     m_xLastLineLB->save_value();
     m_xExpandCB->save_state();
     m_xWordSpacing->save_value();
+    m_xWordSpacingMinimum->save_value();
+    m_xWordSpacingMaximum->save_value();
 }
 
 IMPL_LINK_NOARG(SvxParaAlignTabPage, AlignHdl_Impl, weld::Toggleable&, void)
@@ -1561,7 +1597,12 @@ IMPL_LINK_NOARG(SvxParaAlignTabPage, AlignHdl_Impl, 
weld::Toggleable&, void)
     m_xLastLineFT->set_sensitive(bJustify);
     m_xLastLineLB->set_sensitive(bJustify);
     m_xLabelWordSpacing->set_sensitive(bJustify);
+    m_xLabelMinimum->set_sensitive(bJustify);
+    m_xLabelDesired->set_sensitive(bJustify);
+    m_xLabelMaximum->set_sensitive(bJustify);
     m_xWordSpacing->set_sensitive(bJustify);
+    m_xWordSpacingMinimum->set_sensitive(bJustify);
+    m_xWordSpacingMaximum->set_sensitive(bJustify);
     bool bLastLineIsBlock = m_xLastLineLB->get_active() == 2;
     m_xExpandCB->set_sensitive(bJustify && bLastLineIsBlock);
     //set last line listbox to entry position 0 if not enabled
@@ -1589,6 +1630,33 @@ IMPL_LINK_NOARG(SvxParaAlignTabPage, 
TextDirectionHdl_Impl, weld::ComboBox&, voi
     UpdateExample_Impl();
 }
 
+IMPL_LINK_NOARG(SvxParaAlignTabPage, WordSpacingHdl_Impl, 
weld::MetricSpinButton&, void)
+{
+    sal_Int16 nDesired = m_xWordSpacing->get_value(FieldUnit::PERCENT);
+    if (nDesired < m_xWordSpacingMinimum->get_value(FieldUnit::PERCENT))
+        m_xWordSpacingMinimum->set_value(nDesired, FieldUnit::PERCENT);
+    if (nDesired > m_xWordSpacingMaximum->get_value(FieldUnit::PERCENT))
+        m_xWordSpacingMaximum->set_value(nDesired, FieldUnit::PERCENT);
+}
+
+IMPL_LINK_NOARG(SvxParaAlignTabPage, WordSpacingMinimumHdl_Impl, 
weld::MetricSpinButton&, void)
+{
+    sal_Int16 nMinimum = m_xWordSpacingMinimum->get_value(FieldUnit::PERCENT);
+    if (nMinimum > m_xWordSpacing->get_value(FieldUnit::PERCENT))
+        m_xWordSpacing->set_value(nMinimum, FieldUnit::PERCENT);
+    if (nMinimum > m_xWordSpacingMaximum->get_value(FieldUnit::PERCENT))
+        m_xWordSpacingMaximum->set_value(nMinimum, FieldUnit::PERCENT);
+}
+
+IMPL_LINK_NOARG(SvxParaAlignTabPage, WordSpacingMaximumHdl_Impl, 
weld::MetricSpinButton&, void)
+{
+    sal_Int16 nMaximum = m_xWordSpacingMaximum->get_value(FieldUnit::PERCENT);
+    if (nMaximum < m_xWordSpacingMinimum->get_value(FieldUnit::PERCENT))
+        m_xWordSpacingMinimum->set_value(nMaximum, FieldUnit::PERCENT);
+    if (nMaximum < m_xWordSpacing->get_value(FieldUnit::PERCENT))
+        m_xWordSpacing->set_value(nMaximum, FieldUnit::PERCENT);
+}
+
 void SvxParaAlignTabPage::UpdateExample_Impl()
 {
     if (m_xLeft->get_active())
diff --git a/cui/uiconfig/ui/paragalignpage.ui 
b/cui/uiconfig/ui/paragalignpage.ui
index 7fb8bbeb6321..06609b18b329 100644
--- a/cui/uiconfig/ui/paragalignpage.ui
+++ b/cui/uiconfig/ui/paragalignpage.ui
@@ -6,16 +6,19 @@
     <property name="upper">1000</property>
     <property name="step-increment">1</property>
     <property name="page-increment">10</property>
+    <property name="value">100</property>
   </object>
   <object class="GtkAdjustment" id="adjustmentPercent2">
     <property name="upper">1000</property>
     <property name="step-increment">1</property>
     <property name="page-increment">10</property>
+    <property name="value">100</property>
   </object>
   <object class="GtkAdjustment" id="adjustmentPercent3">
     <property name="upper">1000</property>
     <property name="step-increment">1</property>
     <property name="page-increment">10</property>
+    <property name="value">100</property>
   </object>
   <!-- n-columns=2 n-rows=1 -->
   <object class="GtkGrid" id="ParaAlignPage">
@@ -422,6 +425,51 @@
                 <property name="margin-top">6</property>
                 <property name="row-spacing">6</property>
                 <property name="column-spacing">12</property>
+                <child>
+                  <object class="GtkLabel" id="labelMinimum">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="label" translatable="yes" 
context="paragalignpage|labelMinimum">Minimum</property>
+                    <property name="use-underline">True</property>
+                    <property name="xalign">0</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="left-attach">1</property>
+                    <property name="top-attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="labelDesired">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="label" translatable="yes" 
context="paragalignpage|labelDesired">Desired</property>
+                    <property name="use-underline">True</property>
+                    <property name="xalign">0</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="left-attach">2</property>
+                    <property name="top-attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="labelMaximum">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="label" translatable="yes" 
context="paragalignpage|labelMaximum">Maximum</property>
+                    <property name="use-underline">True</property>
+                    <property name="xalign">0</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="left-attach">3</property>
+                    <property name="top-attach">0</property>
+                  </packing>
+                </child>
                 <child>
                   <object class="GtkLabel" id="labelWordSpacing">
                     <property name="visible">True</property>
@@ -434,7 +482,25 @@
                     <property name="expand">False</property>
                     <property name="fill">True</property>
                     <property name="left-attach">0</property>
-                    <property name="top-attach">0</property>
+                    <property name="top-attach">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkSpinButton" id="spin_WORD_SPACING_MIN">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="activates-default">True</property>
+                    <property name="truncate-multiline">True</property>
+                    <property name="adjustment">adjustmentPercent</property>
+                    <child internal-child="accessible">
+                       <object class="AtkObject" 
id="JUSTIFICATION-MIN-atkobject">
+                         <property name="AtkObject::accessible-description" 
translatable="yes" 
context="paralignpage|extended_tip|JUSTIFICATION-MIN">Adjusts the minimum word 
spacing. Enter a number between 0% (no word spacing) and 250% (two and a half 
times the width of the space character).</property>
+                       </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left-attach">1</property>
+                    <property name="top-attach">1</property>
                   </packing>
                 </child>
                 <child>
@@ -451,8 +517,26 @@
                     </child>
                   </object>
                   <packing>
-                    <property name="left-attach">1</property>
-                    <property name="top-attach">0</property>
+                    <property name="left-attach">2</property>
+                    <property name="top-attach">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkSpinButton" id="spin_WORD_SPACING_MAX">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="activates-default">True</property>
+                    <property name="truncate-multiline">True</property>
+                    <property name="adjustment">adjustmentPercent3</property>
+                    <child internal-child="accessible">
+                      <object class="AtkObject" 
id="JUSTIFICATION-MAX-atkobject">
+                        <property name="AtkObject::accessible-description" 
translatable="yes" 
context="paralignpage|extended_tip|JUSTIFICATION-MAX">Adjusts the maximum word 
spacing. Enter a number between 0% (no word spacing) and 250% (two and a half 
times the width of the space character).</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left-attach">3</property>
+                    <property name="top-attach">1</property>
                   </packing>
                 </child>
               </object>
diff --git a/editeng/source/items/paraitem.cxx 
b/editeng/source/items/paraitem.cxx
index 382552b230c8..d23776f43159 100644
--- a/editeng/source/items/paraitem.cxx
+++ b/editeng/source/items/paraitem.cxx
@@ -362,7 +362,9 @@ ItemInstanceManager* 
SvxAdjustItem::getItemInstanceManager() const
 SvxAdjustItem::SvxAdjustItem(const SvxAdjust eAdjst, const sal_uInt16 nId )
     : SfxEnumItemInterface( nId ),
     bOneBlock( false ), bLastCenter( false ), bLastBlock( false ),
-    nPropWordSpacing(100)
+    nPropWordSpacing(100),
+    nPropWordSpacingMinimum(100),
+    nPropWordSpacingMaximum(100)
 {
     SetAdjust( eAdjst );
 }
@@ -376,6 +378,8 @@ bool SvxAdjustItem::operator==( const SfxPoolItem& rAttr ) 
const
            bOneBlock == rItem.bOneBlock &&
            bLastCenter == rItem.bLastCenter &&
            bLastBlock == rItem.bLastBlock &&
+           nPropWordSpacingMinimum == rItem.nPropWordSpacingMinimum &&
+           nPropWordSpacingMaximum == rItem.nPropWordSpacingMaximum &&
            nPropWordSpacing == rItem.nPropWordSpacing;
 }
 
@@ -387,6 +391,8 @@ size_t SvxAdjustItem::hashCode() const
     o3tl::hash_combine(seed, bLastCenter);
     o3tl::hash_combine(seed, bLastBlock);
     o3tl::hash_combine(seed, nPropWordSpacing);
+    o3tl::hash_combine(seed, nPropWordSpacingMinimum);
+    o3tl::hash_combine(seed, nPropWordSpacingMaximum);
     return seed;
 }
 
@@ -398,6 +404,8 @@ bool SvxAdjustItem::QueryValue( uno::Any& rVal, sal_uInt8 
nMemberId ) const
         case MID_PARA_ADJUST      : rVal <<= 
static_cast<sal_Int16>(GetAdjust()); break;
         case MID_LAST_LINE_ADJUST : rVal <<= 
static_cast<sal_Int16>(GetLastBlock()); break;
         case MID_WORD_SPACING     : rVal <<= 
static_cast<sal_Int16>(GetPropWordSpacing()); break;
+        case MID_WORD_SPACING_MIN : rVal <<= 
static_cast<sal_Int16>(GetPropWordSpacingMinimum()); break;
+        case MID_WORD_SPACING_MAX : rVal <<= 
static_cast<sal_Int16>(GetPropWordSpacingMaximum()); break;
         case MID_EXPAND_SINGLE    :
         {
             rVal <<= bOneBlock;
@@ -438,6 +446,20 @@ bool SvxAdjustItem::PutValue( const uno::Any& rVal, 
sal_uInt8 nMemberId )
             SetPropWordSpacing(nVal);
         }
         break;
+        case MID_WORD_SPACING_MIN :
+        {
+            sal_Int16 nVal = -1;
+            rVal >>= nVal;
+            SetPropWordSpacingMinimum(nVal);
+        }
+        break;
+        case MID_WORD_SPACING_MAX :
+        {
+            sal_Int16 nVal = -1;
+            rVal >>= nVal;
+            SetPropWordSpacingMaximum(nVal);
+        }
+        break;
         case MID_EXPAND_SINGLE :
             ASSERT_CHANGE_REFCOUNTED_ITEM;
             bOneBlock = Any2Bool(rVal);
diff --git a/include/editeng/adjustitem.hxx b/include/editeng/adjustitem.hxx
index 61d8836ae235..27d29757bb41 100644
--- a/include/editeng/adjustitem.hxx
+++ b/include/editeng/adjustitem.hxx
@@ -44,8 +44,11 @@ class EDITENG_DLLPUBLIC SvxAdjustItem final : public 
SfxEnumItemInterface
     bool    bLastCenter : 1;
     bool    bLastBlock : 1;
 
-    // desired word spacing in percent of the width of space character in 
justified text
+    // desired, minimum and maximum word spacing values in percent of
+    // the width of space character in justified text
     sal_uInt16 nPropWordSpacing;
+    sal_uInt16 nPropWordSpacingMinimum;
+    sal_uInt16 nPropWordSpacingMaximum;
 
 protected:
     virtual ItemInstanceManager* getItemInstanceManager() const override;
@@ -160,6 +163,28 @@ public:
         nPropWordSpacing = nVal;
     }
 
+
+    sal_uInt16 GetPropWordSpacingMinimum() const
+    {
+        return nPropWordSpacingMinimum;
+    }
+
+    void SetPropWordSpacingMinimum( sal_uInt16 nVal )
+    {
+        nPropWordSpacingMinimum = nVal;
+    }
+
+
+    sal_uInt16 GetPropWordSpacingMaximum() const
+    {
+        return nPropWordSpacingMaximum;
+    }
+
+    void SetPropWordSpacingMaximum( sal_uInt16 nVal )
+    {
+        nPropWordSpacingMaximum = nVal;
+    }
+
 };
 
 #endif
diff --git a/include/editeng/memberids.h b/include/editeng/memberids.h
index 9d6cd26c036c..7748e8167750 100644
--- a/include/editeng/memberids.h
+++ b/include/editeng/memberids.h
@@ -70,6 +70,8 @@
 #define MID_LAST_LINE_ADJUST    1
 #define MID_EXPAND_SINGLE       2
 #define MID_WORD_SPACING        3
+#define MID_WORD_SPACING_MIN    4
+#define MID_WORD_SPACING_MAX    5
 
 //SvxFontItem
 // Don't use 0 as it used for the whole struct
diff --git a/include/editeng/unotext.hxx b/include/editeng/unotext.hxx
index 1d63f76ce060..b411867c5b0a 100644
--- a/include/editeng/unotext.hxx
+++ b/include/editeng/unotext.hxx
@@ -161,6 +161,8 @@ struct SfxItemPropertyMapEntry;
     { UNO_NAME_EDIT_PARA_IS_CHARACTER_DISTANCE, EE_PARA_ASIANCJKSPACING,   
cppu::UnoType<bool>::get(),                0 ,0 }, \
     { UNO_NAME_EDIT_PARA_IS_FORBIDDEN_RULES,    EE_PARA_FORBIDDENRULES,     
cppu::UnoType<bool>::get(),                0 ,0 },\
     {u"ParaWordSpacing"_ustr,          EE_PARA_JUST,               
::cppu::UnoType<sal_Int16>::get(),            0, MID_WORD_SPACING }, \
+    {u"ParaWordSpacingMinimum"_ustr,   EE_PARA_JUST,               
::cppu::UnoType<sal_Int16>::get(),            0, MID_WORD_SPACING_MIN }, \
+    {u"ParaWordSpacingMaximum"_ustr,   EE_PARA_JUST,               
::cppu::UnoType<sal_Int16>::get(),            0, MID_WORD_SPACING_MAX }, \
     {u"WritingMode"_ustr,              EE_PARA_WRITINGDIR, 
::cppu::UnoType<sal_Int16>::get(),            0, 0 }
 
 class SvxFieldData;
diff --git a/include/xmloff/xmltoken.hxx b/include/xmloff/xmltoken.hxx
index f37f1e4466d7..8212be5d8f74 100644
--- a/include/xmloff/xmltoken.hxx
+++ b/include/xmloff/xmltoken.hxx
@@ -2201,6 +2201,8 @@ namespace xmloff::token {
         XML_WORD,
         XML_WORD_COUNT,
         XML_WORD_SPACING,
+        XML_WORD_SPACING_MAXIMUM,
+        XML_WORD_SPACING_MINIMUM,
         XML_WRAP,
         XML_WRAP_CONTOUR,
         XML_WRAP_CONTOUR_MODE,
diff --git a/offapi/com/sun/star/style/ParagraphProperties.idl 
b/offapi/com/sun/star/style/ParagraphProperties.idl
index 5d4fb7cbd648..d6cb14ab6c6c 100644
--- a/offapi/com/sun/star/style/ParagraphProperties.idl
+++ b/offapi/com/sun/star/style/ParagraphProperties.idl
@@ -514,9 +514,35 @@ published service ParagraphProperties
         /** specifies the desired word spacing as percentage value relative
             to the width of the space character.
 
+            @see ParaWordSpacingMininum
+
+            @see ParaWordSpacingMaximum
+
             @since LibreOffice 25.8
          */
         [optional, property] long ParaWordSpacing;
+
+        /** specifies the minimum word spacing as percentage value relative
+            to the width of the space character.
+
+            @see ParaWordSpacing
+
+            @see ParaWordSpacingMaximum
+
+            @since LibreOffice 25.8
+         */
+        [optional, property] long ParaWordSpacingMinimum;
+
+        /** specifies the maximum word spacing as percentage value relative
+            to the width of the space character.
+
+            @see ParaWordSpacing
+
+            @see ParaWordSpacingMininum
+
+            @since LibreOffice 25.8
+         */
+        [optional, property] long ParaWordSpacingMaximum;
 };
 
 
diff --git a/schema/libreoffice/OpenDocument-v1.4+libreoffice-schema.rng 
b/schema/libreoffice/OpenDocument-v1.4+libreoffice-schema.rng
index 19a8e6e8838a..a4f057d8d1e6 100644
--- a/schema/libreoffice/OpenDocument-v1.4+libreoffice-schema.rng
+++ b/schema/libreoffice/OpenDocument-v1.4+libreoffice-schema.rng
@@ -3172,6 +3172,30 @@ 
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.
     </rng:optional>
   </rng:define>
 
+  <!-- TODO no proposal -->
+  <rng:define name="style-paragraph-properties-attlist" combine="interleave">
+    <rng:optional>
+      <rng:attribute name="loext:word-spacing-minimum">
+        <rng:choice>
+          <rng:ref name="positiveLength"/>
+          <rng:ref name="percent"/>
+        </rng:choice>
+      </rng:attribute>
+    </rng:optional>
+  </rng:define>
+
+  <!-- TODO no proposal -->
+  <rng:define name="style-paragraph-properties-attlist" combine="interleave">
+    <rng:optional>
+      <rng:attribute name="loext:word-spacing-maximum">
+        <rng:choice>
+          <rng:ref name="positiveLength"/>
+          <rng:ref name="percent"/>
+        </rng:choice>
+      </rng:attribute>
+    </rng:optional>
+  </rng:define>
+
   <!-- TODO no proposal -->
   <rng:define name="style-text-properties-attlist" combine="interleave">
     <rng:optional>
diff --git a/svx/sdi/svxitems.sdi b/svx/sdi/svxitems.sdi
index d14ad2776988..2db7f4016a53 100644
--- a/svx/sdi/svxitems.sdi
+++ b/svx/sdi/svxitems.sdi
@@ -58,6 +58,8 @@ struct SvxAdjustStruct
     SvxAdjust   LastLineAdjustment  MID_LAST_LINE_ADJUST;
     BOOL        ExpandSingleWord    MID_EXPAND_SINGLE;
     INT16       WordSpacing         MID_WORD_SPACING;
+    INT16       WordSpacingMinimum  MID_WORD_SPACING_MIN;
+    INT16       WordSpacingMaximum  MID_WORD_SPACING_MAX;
 };
 item SvxAdjustStruct SvxAdjustItem;
 
diff --git a/sw/inc/inspectorproperties.hrc b/sw/inc/inspectorproperties.hrc
index 970e724bb2c9..b218cb946ca1 100644
--- a/sw/inc/inspectorproperties.hrc
+++ b/sw/inc/inspectorproperties.hrc
@@ -245,7 +245,9 @@
 #define RID_PARA_USER_DEFINED_ATTRIBUTES                    
NC_("RID_ATTRIBUTE_NAMES_MAP", "Para User Defined Attributes")
 #define RID_PARA_VERT_ALIGNMENT                             
NC_("RID_ATTRIBUTE_NAMES_MAP", "Para Vertical Alignment")
 #define RID_PARA_WIDOWS                                     
NC_("RID_ATTRIBUTE_NAMES_MAP", "Para Widows")
+#define RID_PARA_WORD_SPACING_MIN                           
NC_("RID_ATTRIBUTE_NAMES_MAP", "Para Word Spacing Minimum")
 #define RID_PARA_WORD_SPACING                               
NC_("RID_ATTRIBUTE_NAMES_MAP", "Para Word Spacing")
+#define RID_PARA_WORD_SPACING_MAX                           
NC_("RID_ATTRIBUTE_NAMES_MAP", "Para Word Spacing Maximum")
 #define RID_REFERENCE_MARK                                  
NC_("RID_ATTRIBUTE_NAMES_MAP", "Reference Mark")
 #define RID_RIGHT_BORDER                                    
NC_("RID_ATTRIBUTE_NAMES_MAP", "Right Border")
 #define RID_RIGHT_BORDER_DISTANCE                           
NC_("RID_ATTRIBUTE_NAMES_MAP", "Right Border Distance")
diff --git a/sw/inc/unoprnms.hxx b/sw/inc/unoprnms.hxx
index a83ae8c90409..192120f4eefa 100644
--- a/sw/inc/unoprnms.hxx
+++ b/sw/inc/unoprnms.hxx
@@ -203,6 +203,8 @@ inline constexpr OUString 
UNO_NAME_PARA_REGISTER_MODE_ACTIVE = u"ParaRegisterMod
 inline constexpr OUString UNO_NAME_PARA_STYLE_NAME = u"ParaStyleName"_ustr;
 inline constexpr OUString UNO_NAME_PARA_LAST_LINE_ADJUST = 
u"ParaLastLineAdjust"_ustr;
 inline constexpr OUString UNO_NAME_PARA_WORD_SPACING = u"ParaWordSpacing"_ustr;
+inline constexpr OUString UNO_NAME_PARA_WORD_SPACING_MIN = 
u"ParaWordSpacingMinimum"_ustr;
+inline constexpr OUString UNO_NAME_PARA_WORD_SPACING_MAX = 
u"ParaWordSpacingMaximum"_ustr;
 inline constexpr OUString UNO_NAME_PARA_LINE_NUMBER_COUNT = 
u"ParaLineNumberCount"_ustr;
 inline constexpr OUString UNO_NAME_PARA_LINE_NUMBER_START_VALUE = 
u"ParaLineNumberStartValue"_ustr;
 inline constexpr OUString UNO_NAME_BACK_COLOR = u"BackColor"_ustr;
diff --git a/sw/qa/extras/layout/data/tdf126154.fodt 
b/sw/qa/extras/layout/data/tdf126154.fodt
new file mode 100644
index 000000000000..ad4d775baa72
--- /dev/null
+++ b/sw/qa/extras/layout/data/tdf126154.fodt
@@ -0,0 +1,245 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:css3t="http://www.w3.org/TR/css3-text/"; 
xmlns:grddl="http://www.w3.org/2003/g/data-view#"; 
xmlns:xhtml="http://www.w3.org/1999/xhtml"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"; 
xmlns:xforms="http://www.w3.org/2002/xforms"; 
xmlns:dom="http://www.w3.org/2001/xml-events"; 
xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" 
xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" 
xmlns:math="http://www.w3.org/1998/Math/MathML"; 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:ooo="http://openoffice.org/2004/office"; 
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" 
xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" 
xmlns:ooow="http://openoffice.org/2004/writer"; 
xmlns:xlink="http://www.w3.org/1999/xlink"; 
xmlns:drawooo="http://openoffice.org/2010/draw"; 
xmlns:oooc="http://openoffice.org/2004/calc"; 
xmlns:dc="http://purl.org/dc/elements/1.1/"; xmlns:c
 alcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" 
xmlns:tableooo="http://openoffice.org/2009/table"; 
xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" 
xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" 
xmlns:rpt="http://openoffice.org/2005/report"; 
xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0"
 xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" 
xmlns:officeooo="http://openoffice.org/2009/office"; 
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" 
xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" 
xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" 
xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:
 meta:1.0" 
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
 office:version="1.4" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:settings>
+  <config:config-item-set config:name="ooo:view-settings">
+   <config:config-item config:name="ViewAreaTop" 
config:type="long">9246</config:config-item>
+   <config:config-item config:name="ViewAreaLeft" 
config:type="long">0</config:config-item>
+   <config:config-item config:name="ViewAreaWidth" 
config:type="long">22368</config:config-item>
+   <config:config-item config:name="ViewAreaHeight" 
config:type="long">12661</config:config-item>
+   <config:config-item config:name="ShowRedlineChanges" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="InBrowseMode" 
config:type="boolean">false</config:config-item>
+   <config:config-item-map-indexed config:name="Views">
+    <config:config-item-map-entry>
+     <config:config-item config:name="ViewId" 
config:type="string">view2</config:config-item>
+     <config:config-item config:name="ViewLeft" 
config:type="long">8156</config:config-item>
+     <config:config-item config:name="ViewTop" 
config:type="long">7959</config:config-item>
+     <config:config-item config:name="VisibleLeft" 
config:type="long">0</config:config-item>
+     <config:config-item config:name="VisibleTop" 
config:type="long">9246</config:config-item>
+     <config:config-item config:name="VisibleRight" 
config:type="long">22366</config:config-item>
+     <config:config-item config:name="VisibleBottom" 
config:type="long">21906</config:config-item>
+     <config:config-item config:name="ZoomType" 
config:type="short">0</config:config-item>
+     <config:config-item config:name="ViewLayoutColumns" 
config:type="short">0</config:config-item>
+     <config:config-item config:name="ViewLayoutBookMode" 
config:type="boolean">false</config:config-item>
+     <config:config-item config:name="ZoomFactor" 
config:type="short">172</config:config-item>
+     <config:config-item config:name="IsSelectedFrame" 
config:type="boolean">false</config:config-item>
+     <config:config-item config:name="KeepRatio" 
config:type="boolean">false</config:config-item>
+     <config:config-item config:name="AnchoredTextOverflowLegacy" 
config:type="boolean">true</config:config-item>
+     <config:config-item config:name="LegacySingleLineFontwork" 
config:type="boolean">true</config:config-item>
+     <config:config-item config:name="ConnectorUseSnapRect" 
config:type="boolean">false</config:config-item>
+     <config:config-item config:name="IgnoreBreakAfterMultilineField" 
config:type="boolean">false</config:config-item>
+    </config:config-item-map-entry>
+   </config:config-item-map-indexed>
+  </config:config-item-set>
+  <config:config-item-set config:name="ooo:configuration-settings">
+   <config:config-item config:name="PrintProspectRTL" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="PrintPageBackground" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="PrintDrawings" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="PrintFaxName" config:type="string"/>
+   <config:config-item config:name="PrintReversed" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="PrintAnnotationMode" 
config:type="short">0</config:config-item>
+   <config:config-item config:name="PrintHiddenText" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="PrintEmptyPages" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="BalanceSpacesAndIdeographicSpaces" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="MsWordCompGridMetrics" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="PaintHellOverHeaderFooter" 
config:type="boolean">false</config:config-item>
+   <config:config-item 
config:name="ApplyParagraphMarkFormatToEmptyLineAtEndOfParagraph" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="PrintGraphics" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="NoNumberingShowFollowBy" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="MinRowHeightInclBorder" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="HyphenateURLs" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="ImagePreferredDPI" 
config:type="int">0</config:config-item>
+   <config:config-item config:name="FootnoteInColumnToPageEnd" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="GutterAtTop" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="ContinuousEndnotes" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="MsWordUlTrailSpace" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="FrameAutowidthWithMorePara" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="SubtractFlysAnchoredAtFlys" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="SurroundTextWrapSmall" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="PrintControls" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="TreatSingleColumnBreakAsPageBreak" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="TabOverSpacing" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="AutoFirstLineIndentDisregardLineSpace" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="TabOverMargin" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="EmbedComplexScriptFonts" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="EmbedAsianScriptFonts" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="PrintTextPlaceholder" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="ApplyTextAttrToEmptyLineAtEndOfParagraph" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="EmbedSystemFonts" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="EmbedFonts" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="NoClippingWithWrapPolygon" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="DisableOffPagePositioning" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="BackgroundParaOverDrawings" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="TabOverflow" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="SmallCapsPercentage66" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="AllowPrintJobCancel" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="AddVerticalFrameOffsets" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="ProtectBookmarks" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="AddFrameOffsets" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="PrintBlackFonts" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="TableRowKeep" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="ApplyParagraphMarkFormatToNumbering" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="PrinterIndependentLayout" 
config:type="string">high-resolution</config:config-item>
+   <config:config-item config:name="JustifyLinesWithShrinking" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="RsidRoot" 
config:type="int">585804</config:config-item>
+   <config:config-item config:name="PrintProspect" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="CollapseEmptyCellPara" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="PrintPaperFromSetup" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="CurrentDatabaseCommand" 
config:type="string"/>
+   <config:config-item config:name="CurrentDatabaseDataSource" 
config:type="string"/>
+   <config:config-item config:name="SaveThumbnail" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="EmbeddedDatabaseName" 
config:type="string"/>
+   <config:config-item config:name="UnbreakableNumberings" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="SaveGlobalDocumentLinks" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="MsWordCompTrailingBlanks" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="PrintTables" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="PrintLeftPages" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="AddParaTableSpacing" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="PrinterPaperFromSetup" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="CurrentDatabaseCommandType" 
config:type="int">0</config:config-item>
+   <config:config-item config:name="ChartAutoUpdate" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="OutlineLevelYieldsNumbering" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="UseOldNumbering" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="AddParaSpacingToTableCells" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="FieldAutoUpdate" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="PropLineSpacingShrinksFirstLine" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="TabAtLeftIndentForParagraphsInList" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="PrintRightPages" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="DoNotCaptureDrawObjsOnPage" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="LoadReadonly" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="HeaderSpacingBelowLastPara" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="SaveVersionOnClose" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="UseFormerLineSpacing" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="PrinterName" config:type="string"/>
+   <config:config-item config:name="AddParaLineSpacingToTableCells" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="IsKernAsianPunctuation" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="DoNotJustifyLinesWithManualBreak" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="CharacterCompressionType" 
config:type="short">0</config:config-item>
+   <config:config-item config:name="IsLabelDocument" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="EmbedLatinScriptFonts" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="PrinterSetup" config:type="base64Binary"/>
+   <config:config-item config:name="UseVariableWidthNBSP" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="EmbedOnlyUsedFonts" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="ApplyUserData" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="AddParaTableSpacingAtStart" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="InvertBorderSpacing" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="ProtectFields" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="AddExternalLeading" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="LinkUpdateMode" 
config:type="short">1</config:config-item>
+   <config:config-item config:name="UseFormerObjectPositioning" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="UnxForceZeroExtLeading" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="UseFormerTextWrapping" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="ConsiderTextWrapOnObjPos" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="StylesNoDefault" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="IgnoreFirstLineIndentInNumbering" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="NoGapAfterNoteNumber" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="EmptyDbFieldHidesPara" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="DoNotResetParaAttrsForNumFont" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="IgnoreTabsAndBlanksForLineCalculation" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="ClippedPictures" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="MathBaselineAlignment" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="AlignTabStopPosition" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="IgnoreHiddenCharsForLineCalculation" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="ClipAsCharacterAnchoredWriterFlyFrames" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="DropCapPunctuation" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="UseOldPrinterMetrics" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="RedlineProtectionKey" 
config:type="base64Binary"/>
+   <config:config-item config:name="TabsRelativeToIndent" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="Rsid" 
config:type="int">1072074</config:config-item>
+   <config:config-item config:name="UpdateFromTemplate" 
config:type="boolean">true</config:config-item>
+   <config:config-item config:name="ProtectForm" 
config:type="boolean">false</config:config-item>
+   <config:config-item config:name="MsWordCompMinLineHeightByFly" 
config:type="boolean">false</config:config-item>
+  </config:config-item-set>
+ </office:settings>
+ <office:font-face-decls>
+  <style:font-face style:name="Arial" svg:font-family="Arial"/>
+  <style:font-face style:name="Arial1" svg:font-family="Arial" 
style:font-adornments="Bold" style:font-family-generic="swiss" 
style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+  <style:default-style style:family="graphic">
+   <style:graphic-properties svg:stroke-color="#3465a4" 
draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="8.5pt" 
draw:shadow-offset-y="8.5pt" draw:start-line-spacing-horizontal="8.02pt" 
draw:start-line-spacing-vertical="8.02pt" 
draw:end-line-spacing-horizontal="8.02pt" 
draw:end-line-spacing-vertical="8.02pt" style:writing-mode="lr-tb" 
style:flow-with-text="false"/>
+   <style:paragraph-properties style:text-autospace="ideograph-alpha" 
style:line-break="strict" loext:tab-stop-distance="0pt" 
style:writing-mode="lr-tb" style:font-independent-line-spacing="false">
+    <style:tab-stops/>
+   </style:paragraph-properties>
+   <style:text-properties style:use-window-font-color="true" 
loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="10pt" 
fo:language="en" fo:country="US" style:letter-kerning="false"        />
+  </style:default-style>
+  <style:default-style style:family="paragraph">
+   <style:paragraph-properties fo:hyphenation-ladder-count="no-limit" 
fo:hyphenation-keep="auto" loext:hyphenation-keep-type="column" 
loext:hyphenation-keep-line="false" style:text-autospace="ideograph-alpha" 
style:punctuation-wrap="hanging" style:line-break="strict" 
style:tab-stop-distance="36pt" style:writing-mode="page"/>
+   <style:text-properties style:use-window-font-color="true" 
loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="10pt" 
fo:language="en" fo:country="US" style:letter-kerning="false"         
fo:hyphenate="false" fo:hyphenation-remain-char-count="2" 
fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false" 
loext:hyphenation-no-last-word="false" 
loext:hyphenation-word-char-count="no-limit" loext:hyphenation-zone="no-limit"/>
+  </style:default-style>
+  <style:default-style style:family="table">
+   <style:table-properties table:border-model="collapsing"/>
+  </style:default-style>
+  <style:default-style style:family="table-row">
+   <style:table-row-properties fo:keep-together="auto"/>
+  </style:default-style>
+  <style:style style:name="Standard" style:family="paragraph" 
style:class="text">
+   <style:paragraph-properties fo:margin-top="0pt" fo:margin-bottom="0pt" 
style:contextual-spacing="false" fo:text-align="start" 
style:justify-single-word="false" fo:orphans="2" fo:widows="2" 
style:writing-mode="lr-tb"/>
+   <style:text-properties style:font-name="Arial" fo:font-family="Arial" 
fo:font-size="10pt" fo:language="en" fo:country="GB"/>
+  </style:style>
+  <style:style style:name="Text_20_body" style:display-name="Text body" 
style:family="paragraph" style:parent-style-name="Standard" style:class="text">
+   <style:paragraph-properties fo:margin-top="0pt" fo:margin-bottom="7pt" 
style:contextual-spacing="false" fo:line-height="115%"/>
+  </style:style>
+ </office:styles>
+ <office:automatic-styles>
+  <style:style style:name="P1" style:family="paragraph" 
style:parent-style-name="Heading_20_5">
+   <style:text-properties style:font-name="Arial1" fo:font-family="Arial" 
style:font-style-name="Bold" style:font-family-generic="swiss" 
style:font-pitch="variable" fo:font-size="12pt" fo:font-weight="bold"    />
+  </style:style>
+  <style:style style:name="P2" style:family="paragraph" 
style:parent-style-name="Standard">
+   <style:paragraph-properties fo:text-align="justify" 
style:justify-single-word="false" fo:hyphenation-ladder-count="no-limit" 
fo:hyphenation-keep="auto" loext:hyphenation-keep-type="column" 
loext:hyphenation-keep-line="true"/>
+   <style:text-properties officeooo:rsid="000f3b24" 
officeooo:paragraph-rsid="00105bca" fo:hyphenate="true" 
fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" 
loext:hyphenation-no-caps="false" loext:hyphenation-no-last-word="false" 
loext:hyphenation-word-char-count="4" loext:hyphenation-zone="no-limit" 
loext:hyphenation-compound-remain-char-count="2"/>
+  </style:style>
+  <style:style style:name="P3" style:family="paragraph" 
style:parent-style-name="Standard">
+   <style:paragraph-properties fo:text-align="justify" 
style:justify-single-word="false" fo:hyphenation-ladder-count="no-limit" 
fo:hyphenation-keep="auto" loext:hyphenation-keep-type="column" 
loext:hyphenation-keep-line="true" loext:word-spacing-minimum="80%"/>
+   <style:text-properties officeooo:rsid="000f3b24" 
officeooo:paragraph-rsid="00105bca" fo:hyphenate="true" 
fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" 
loext:hyphenation-no-caps="false" loext:hyphenation-no-last-word="false" 
loext:hyphenation-word-char-count="4" loext:hyphenation-zone="no-limit" 
loext:hyphenation-compound-remain-char-count="2"/>
+  </style:style>
+  <style:style style:name="P4" style:family="paragraph" 
style:parent-style-name="Standard">
+   <style:paragraph-properties fo:text-align="justify" 
style:justify-single-word="false" fo:hyphenation-ladder-count="no-limit" 
fo:hyphenation-keep="auto" loext:hyphenation-keep-type="column" 
loext:hyphenation-keep-line="true" loext:word-spacing-minimum="80%" 
loext:word-spacing-maximum="133%"/>
+   <style:text-properties officeooo:rsid="000f3b24" 
officeooo:paragraph-rsid="00105bca" fo:hyphenate="true" 
fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" 
loext:hyphenation-no-caps="false" loext:hyphenation-no-last-word="false" 
loext:hyphenation-word-char-count="4" loext:hyphenation-zone="no-limit" 
loext:hyphenation-compound-remain-char-count="2"/>
+  </style:style>
+  <style:style style:name="T1" style:family="text">
+   <style:text-properties officeooo:rsid="00105bca"/>
+  </style:style>
+  <style:page-layout style:name="pm1">
+   <style:page-layout-properties fo:page-width="419.56pt" 
fo:page-height="595.3pt" style:num-format="1" 
style:print-orientation="portrait" fo:margin-top="21.6pt" 
fo:margin-bottom="14.4pt" fo:margin-left="36pt" fo:margin-right="36pt" 
style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" 
style:layout-grid-lines="31" style:layout-grid-base-height="18pt" 
style:layout-grid-ruby-height="0pt" style:layout-grid-mode="none" 
style:layout-grid-ruby-below="false" style:layout-grid-print="false" 
style:layout-grid-display="false" style:footnote-max-height="0pt" 
loext:margin-gutter="0pt">
+    <style:footnote-sep style:width="0.51pt" 
style:distance-before-sep="2.86pt" style:distance-after-sep="2.86pt" 
style:line-style="solid" style:adjustment="left" style:rel-width="25%" 
style:color="#000000"/>
+   </style:page-layout-properties>
+   <style:header-style/>
+   <style:footer-style/>
+  </style:page-layout>
+  <style:style style:name="dp1" style:family="drawing-page">
+   <style:drawing-page-properties draw:background-size="full"/>
+  </style:style>
+ </office:automatic-styles>
+ <office:master-styles>
+  <style:master-page style:name="Standard" style:page-layout-name="pm1" 
draw:style-name="dp1"/>
+ </office:master-styles>
+ <office:body>
+  <office:text>
+   <text:p text:style-name="P1">Only desired word spacing (100%, 100%, 
100%)</text:p>
+   <text:p text:style-name="P2">,, , , , , , , , Lorem ipsum dolor sit amet, 
consectetur adipiscing elit. Vesti bulum con sequat mi quis pretium 
semper.</text:p>
+   <text:p text:style-name="P2">,,, , , , , , , , Lorem ipsum dolor sit amet, 
consectetur adipiscing elit. Vesti bulum con sequat mi quis pretium 
semper.</text:p>
+   <text:p text:style-name="P2">,,,, , , , , , , , Lorem ipsum dolor sit amet, 
consectetur adipiscing elit. Vesti bulum con sequat mi quis pretium 
semper.</text:p>
+   <text:p text:style-name="P2">,,,,, , , , , , , , Lorem ipsum dolor sit 
amet, consectetur adipiscing elit. Vesti bulum con sequat mi quis pretium 
semper.</text:p>
+   <text:p text:style-name="P2">,,,,,, , , , , , , , Lorem ipsum dolor sit 
amet, consectetur adipiscing elit. Vesti bulum con sequat mi quis pretium 
semper.</text:p>
+   <text:p text:style-name="P2">,,,,,,, , , , , , , , Lorem ipsum dolor sit 
amet, consectetur adipiscing elit. Vesti bulum con sequat mi quis pretium 
semper.</text:p>
+   <text:p text:style-name="P2">,,,,,,,, , , , , , , , Lorem ipsum dolor sit 
amet, consectetur adipiscing elit. Vesti bulum con sequat mi quis pretium 
semper.</text:p>
+   <text:p text:style-name="P1">Minimum word spacing (80%, 100%, 100%)</text:p>
+   <text:p text:style-name="P3">,, , , , , , , , Lorem ipsum dolor sit amet, 
consectetur adipiscing elit. Vesti bulum con sequat mi quis pretium 
semper.</text:p>
+   <text:p text:style-name="P3">,,, , , , , , , , Lorem ipsum dolor sit amet, 
consectetur adipiscing elit. Vesti bulum con sequat mi quis pretium 
semper.</text:p>
+   <text:p text:style-name="P3">,,,, , , , , , , , Lorem ipsum dolor sit amet, 
consectetur adipiscing elit. Vesti bulum con sequat mi quis pretium 
semper.</text:p>
+   <text:p text:style-name="P3">,,,,, , , , , , , , Lorem ipsum dolor sit 
amet, consectetur adipiscing elit. Vesti bulum con sequat mi quis pretium 
semper.</text:p>
+   <text:p text:style-name="P3">,,,,,, , , , , , , , Lorem ipsum dolor sit 
amet, consectetur adipiscing elit. Vesti bulum con sequat mi quis pretium 
semper.</text:p>
+   <text:p text:style-name="P3">,,,,,,, , , , , , , , Lorem ipsum dolor sit 
amet, consectetur adipiscing elit. Vesti bulum con sequat mi quis pretium 
semper.</text:p>
+   <text:p text:style-name="P3">,,,,,,,, , , , , , , , Lorem ipsum dolor sit 
amet, consectetur adipiscing elit. Vesti bulum con sequat mi quis pretium 
semper.</text:p>
+   <text:p text:style-name="P1">Minimum and maximum word spacing (80%, 100%, 
133%)</text:p>
+   <text:p text:style-name="P4">,, , , , , , , , Lorem ipsum dolor sit amet, 
consectetur adipiscing elit. Vesti bulum con sequat mi quis pretium 
semper.</text:p>
+   <text:p text:style-name="P4">,,, , , , , , , , Lorem ipsum dolor sit amet, 
consectetur adipiscing elit. Vesti bulum con sequat mi quis pretium 
semper.</text:p>
+   <text:p text:style-name="P4">,,,, , , , , , , , Lorem ipsum dolor sit amet, 
consectetur adipiscing elit. Vesti bulum con sequat mi quis pretium 
semper.</text:p>
+   <text:p text:style-name="P4">,,,,, , , , , , , , Lorem ipsum dolor sit 
amet, consectetur adipiscing elit. Vesti bulum con sequat mi quis pretium 
semper.</text:p>
+   <text:p text:style-name="P4">,,,,,, , , , , , , , Lorem ipsum dolor sit 
amet, consectetur adipiscing elit. Vesti bulum con sequat mi quis pretium 
semper.</text:p>
+   <text:p text:style-name="P4">,,,,,,, , , , , , , , Lorem ipsum dolor sit 
amet, consectetur adipiscing elit. Vesti bulum con sequat mi quis pretium 
semper.</text:p>
+   <text:p text:style-name="P4">,,,,,,,, , , , , , , , Lorem ipsum dolor sit 
amet, consectetur adipiscing elit. Vesti bulum con sequat mi quis pretium 
semper.</text:p>
+  </office:text>
+ </office:body>
+</office:document>
diff --git a/sw/qa/extras/layout/layout3.cxx b/sw/qa/extras/layout/layout3.cxx
index 9189590f6804..1920c4a78360 100644
--- a/sw/qa/extras/layout/layout3.cxx
+++ b/sw/qa/extras/layout/layout3.cxx
@@ -1012,6 +1012,95 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf165984)
                 u"of the Earth is space ");
 }
 
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf126154)
+{
+    // minimum, desired and maximum word spacing
+    uno::Reference<linguistic2::XHyphenator> xHyphenator = 
LinguMgr::GetHyphenator();
+    if (!xHyphenator->hasLocale(lang::Locale(u"en"_ustr, u"US"_ustr, 
OUString())))
+        return;
+
+    createSwDoc("tdf126154.fodt");
+    // Ensure that all text portions are calculated before testing.
+    SwViewShell* pViewShell = 
getSwDoc()->getIDocumentLayoutAccess().GetCurrentViewShell();
+    CPPUNIT_ASSERT(pViewShell);
+    pViewShell->Reformat();
+
+    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+
+    // only desired word space: 100%, 100%, 100%
+    // 5 lines are hyphenated
+    assertXPath(
+        pXmlDoc, "/root/page[1]/body/txt[2]/SwParaPortion/SwLineLayout[1]", 
"portion",
+        u",, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing 
elit. Vesti bulum ");
+    assertXPath(
+        pXmlDoc, "/root/page[1]/body/txt[3]/SwParaPortion/SwLineLayout[1]", 
"portion",
+        u",,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing 
elit. Vesti bu");
+    assertXPath(
+        pXmlDoc, "/root/page[1]/body/txt[4]/SwParaPortion/SwLineLayout[1]", 
"portion",
+        u",,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur 
adipiscing elit. Vesti bu");
+    assertXPath(
+        pXmlDoc, "/root/page[1]/body/txt[5]/SwParaPortion/SwLineLayout[1]", 
"portion",
+        u",,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur 
adipiscing elit. Vesti bu");
+    assertXPath(
+        pXmlDoc, "/root/page[1]/body/txt[6]/SwParaPortion/SwLineLayout[1]", 
"portion",
+        u",,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur 
adipiscing elit. Vesti bu");
+    assertXPath(
+        pXmlDoc, "/root/page[1]/body/txt[7]/SwParaPortion/SwLineLayout[1]", 
"portion",
+        u",,,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur 
adipiscing elit. Vesti bu");
+    assertXPath(
+        pXmlDoc, "/root/page[1]/body/txt[8]/SwParaPortion/SwLineLayout[1]", 
"portion",
+        u",,,,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur 
adipiscing elit. Vesti ");
+
+    // also minimum word space: 80%, 100%, 100%
+    // only a single line is hyphenated from the previous ones
+    assertXPath(
+        pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout[1]", 
"portion",
+        u",, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing 
elit. Vesti bulum ");
+    assertXPath(
+        pXmlDoc, "/root/page[1]/body/txt[11]/SwParaPortion/SwLineLayout[1]", 
"portion",
+        u",,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing 
elit. Vesti bulum ");
+    assertXPath(pXmlDoc, 
"/root/page[1]/body/txt[12]/SwParaPortion/SwLineLayout[1]", "portion",
+                u",,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur 
adipiscing elit. "
+                u"Vesti bulum ");
+    assertXPath(pXmlDoc, 
"/root/page[1]/body/txt[13]/SwParaPortion/SwLineLayout[1]", "portion",
+                u",,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur 
adipiscing elit. "
+                u"Vesti bulum ");
+    assertXPath(pXmlDoc, 
"/root/page[1]/body/txt[14]/SwParaPortion/SwLineLayout[1]", "portion",
+                u",,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur 
adipiscing elit. "
+                u"Vesti bulum ");
+    assertXPath(
+        pXmlDoc, "/root/page[1]/body/txt[15]/SwParaPortion/SwLineLayout[1]", 
"portion",
+        u",,,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur 
adipiscing elit. Vesti bu");
+    assertXPath(
+        pXmlDoc, "/root/page[1]/body/txt[16]/SwParaPortion/SwLineLayout[1]", 
"portion",
+        u",,,,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur 
adipiscing elit. Vesti ");
+
+    // minimum, desired and maximum word spacing: 80%, 100%, 133%
+    // no hyphenation in the same text: hyphenation of all the short words are 
limited
+    // by the minimum and maximum word spacing settings
+    assertXPath(
+        pXmlDoc, "/root/page[1]/body/txt[18]/SwParaPortion/SwLineLayout[1]", 
"portion",
+        u",, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing 
elit. Vesti bulum ");
+    assertXPath(
+        pXmlDoc, "/root/page[1]/body/txt[19]/SwParaPortion/SwLineLayout[1]", 
"portion",
+        u",,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing 
elit. Vesti bulum ");
+    assertXPath(pXmlDoc, 
"/root/page[1]/body/txt[20]/SwParaPortion/SwLineLayout[1]", "portion",
+                u",,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur 
adipiscing elit. "
+                u"Vesti bulum ");
+    assertXPath(pXmlDoc, 
"/root/page[1]/body/txt[21]/SwParaPortion/SwLineLayout[1]", "portion",
+                u",,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur 
adipiscing elit. "
+                u"Vesti bulum ");
+    assertXPath(pXmlDoc, 
"/root/page[1]/body/txt[22]/SwParaPortion/SwLineLayout[1]", "portion",
+                u",,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur 
adipiscing elit. "
+                u"Vesti bulum ");
+    assertXPath(
+        pXmlDoc, "/root/page[1]/body/txt[23]/SwParaPortion/SwLineLayout[1]", 
"portion",
+        u",,,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur 
adipiscing elit. Vesti ");
+    assertXPath(
+        pXmlDoc, "/root/page[1]/body/txt[24]/SwParaPortion/SwLineLayout[1]", 
"portion",
+        u",,,,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur 
adipiscing elit. Vesti ");
+}
+
 CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf106234)
 {
     createSwDoc("tdf106234.fodt");
diff --git a/sw/qa/uitest/styleInspector/styleInspector.py 
b/sw/qa/uitest/styleInspector/styleInspector.py
index 5e3a5ea7c91a..301b6ee09ced 100644
--- a/sw/qa/uitest/styleInspector/styleInspector.py
+++ b/sw/qa/uitest/styleInspector/styleInspector.py
@@ -26,7 +26,7 @@ class styleNavigator(UITestCase):
             # The cursor is on text without formatting and default style
             self.assertEqual(1, len(xListBox.getChild('0').getChildren()))
             self.assertEqual("Default Paragraph Style  ", 
get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
-            self.assertEqual(149, 
len(xListBox.getChild('0').getChild('0').getChildren()))
+            self.assertEqual(151, 
len(xListBox.getChild('0').getChild('0').getChildren()))
             self.assertEqual(0, len(xListBox.getChild('1').getChildren()))
             self.assertEqual(0, len(xListBox.getChild('2').getChildren()))
             self.assertEqual(0, len(xListBox.getChild('3').getChildren()))
@@ -36,7 +36,7 @@ class styleNavigator(UITestCase):
             # The cursor is on text with direct formatting
             self.assertEqual(1, len(xListBox.getChild('0').getChildren()))
             self.assertEqual("Default Paragraph Style  ", 
get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
-            self.assertEqual(149, 
len(xListBox.getChild('0').getChild('0').getChildren()))
+            self.assertEqual(151, 
len(xListBox.getChild('0').getChild('0').getChildren()))
             self.assertEqual(0, len(xListBox.getChild('1').getChildren()))
             self.assertEqual(0, len(xListBox.getChild('2').getChildren()))
 
@@ -54,7 +54,7 @@ class styleNavigator(UITestCase):
             # The cursor is on text with paragraph direct formatting
             self.assertEqual(1, len(xListBox.getChild('0').getChildren()))
             self.assertEqual("Default Paragraph Style  ", 
get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
-            self.assertEqual(149, 
len(xListBox.getChild('0').getChild('0').getChildren()))
+            self.assertEqual(151, 
len(xListBox.getChild('0').getChild('0').getChildren()))
 
             xParDirFormatting = xListBox.getChild('1')
             self.assertEqual(7, len(xParDirFormatting.getChildren()))
@@ -75,13 +75,13 @@ class styleNavigator(UITestCase):
             xParStyle = xListBox.getChild('0')
             self.assertEqual(3, len(xParStyle.getChildren()))
             self.assertEqual("Default Paragraph Style  ", 
get_state_as_dict(xParStyle.getChild('0'))['Text'])
-            self.assertEqual(149, len(xParStyle.getChild('0').getChildren()))
+            self.assertEqual(151, len(xParStyle.getChild('0').getChildren()))
             self.assertEqual("Heading  ", 
get_state_as_dict(xParStyle.getChild('1'))['Text'])
             self.assertEqual(28, len(xParStyle.getChild('1').getChildren()))
 
             xTitleStyle = xParStyle.getChild('2')
             self.assertEqual("Title    ", 
get_state_as_dict(xTitleStyle)['Text'])
-            self.assertEqual(17, len(xTitleStyle.getChildren()))
+            self.assertEqual(19, len(xTitleStyle.getChildren()))
             self.assertEqual("Char Difference Height   0", 
get_state_as_dict(xTitleStyle.getChild('0'))['Text'])
             self.assertEqual("Char Difference Height Asian     0", 
get_state_as_dict(xTitleStyle.getChild('1'))['Text'])
             self.assertEqual("Char Difference Height Complex   0", 
get_state_as_dict(xTitleStyle.getChild('2'))['Text'])
@@ -99,6 +99,8 @@ class styleNavigator(UITestCase):
             self.assertEqual("Para Expand Single Word  False", 
get_state_as_dict(xTitleStyle.getChild('14'))['Text'])
             self.assertEqual("Para Last Line Adjust    0", 
get_state_as_dict(xTitleStyle.getChild('15'))['Text'])
             self.assertEqual("Para Word Spacing        100", 
get_state_as_dict(xTitleStyle.getChild('16'))['Text'])
+            self.assertEqual("Para Word Spacing Maximum        100", 
get_state_as_dict(xTitleStyle.getChild('17'))['Text'])
+            self.assertEqual("Para Word Spacing Minimum        100", 
get_state_as_dict(xTitleStyle.getChild('18'))['Text'])
 
             self.assertEqual(0, len(xListBox.getChild('1').getChildren()))
             self.assertEqual(0, len(xListBox.getChild('2').getChildren()))
@@ -110,7 +112,7 @@ class styleNavigator(UITestCase):
             xParStyle = xListBox.getChild('0')
             self.assertEqual(3, len(xParStyle.getChildren()))
             self.assertEqual("Default Paragraph Style  ", 
get_state_as_dict(xParStyle.getChild('0'))['Text'])
-            self.assertEqual(149, len(xParStyle.getChild('0').getChildren()))
+            self.assertEqual(151, len(xParStyle.getChild('0').getChildren()))
             self.assertEqual("Body Text        ", 
get_state_as_dict(xParStyle.getChild('1'))['Text'])
             self.assertEqual(6, len(xParStyle.getChild('1').getChildren()))
 
@@ -145,7 +147,7 @@ class styleNavigator(UITestCase):
             # The cursor is on text without metadata
             self.assertEqual(1, len(xListBox.getChild('0').getChildren()))
             self.assertEqual("Default Paragraph Style  ", 
get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
-            self.assertEqual(149, 
len(xListBox.getChild('0').getChild('0').getChildren()))
+            self.assertEqual(151, 
len(xListBox.getChild('0').getChild('0').getChildren()))
             self.assertEqual(0, len(xListBox.getChild('1').getChildren()))
             self.assertEqual(0, len(xListBox.getChild('2').getChildren()))
             self.assertEqual(0, len(xListBox.getChild('3').getChildren()))
@@ -155,7 +157,7 @@ class styleNavigator(UITestCase):
             # The cursor is on text with paragraph metadata showed under 
direct paragraph formatting
             self.assertEqual(1, len(xListBox.getChild('0').getChildren()))
             self.assertEqual("Default Paragraph Style  ", 
get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
-            self.assertEqual(149, 
len(xListBox.getChild('0').getChild('0').getChildren()))
+            self.assertEqual(151, 
len(xListBox.getChild('0').getChild('0').getChildren()))
 
             xParDirFormatting = xListBox.getChild('1')
             self.assertEqual(1, len(xParDirFormatting.getChildren()))
@@ -208,7 +210,7 @@ class styleNavigator(UITestCase):
             # The cursor is on text without metadata
             self.assertEqual(1, len(xListBox.getChild('0').getChildren()))
             self.assertEqual("Default Paragraph Style  ", 
get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
-            self.assertEqual(149, 
len(xListBox.getChild('0').getChild('0').getChildren()))
+            self.assertEqual(151, 
len(xListBox.getChild('0').getChild('0').getChildren()))
             self.assertEqual(0, len(xListBox.getChild('1').getChildren()))
             self.assertEqual(0, len(xListBox.getChild('2').getChildren()))
             self.assertEqual(0, len(xListBox.getChild('3').getChildren()))
@@ -218,7 +220,7 @@ class styleNavigator(UITestCase):
             # The cursor is on text with paragraph metadata showed under 
direct paragraph formatting
             self.assertEqual(1, len(xListBox.getChild('1').getChildren()))
             self.assertEqual("Default Paragraph Style  ", 
get_state_as_dict(xListBox.getChild('1').getChild('0'))['Text'])
-            self.assertEqual(149, 
len(xListBox.getChild('1').getChild('0').getChildren()))
+            self.assertEqual(151, 
len(xListBox.getChild('1').getChild('0').getChildren()))
 
             # Outer bookmark
             xBookmarkFormatting = xListBox.getChild('0')
@@ -265,7 +267,7 @@ class styleNavigator(UITestCase):
             # The cursor is on text without metadata
             self.assertEqual(1, len(xListBox.getChild('0').getChildren()))
             self.assertEqual("Default Paragraph Style  ", 
get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
-            self.assertEqual(149, 
len(xListBox.getChild('0').getChild('0').getChildren()))
+            self.assertEqual(151, 
len(xListBox.getChild('0').getChild('0').getChildren()))
             self.assertEqual(0, len(xListBox.getChild('1').getChildren()))
             self.assertEqual(0, len(xListBox.getChild('2').getChildren()))
 
diff --git a/sw/qa/uitest/styleInspector/tdf137513.py 
b/sw/qa/uitest/styleInspector/tdf137513.py
index c27646779743..cf7f62c59f85 100644
--- a/sw/qa/uitest/styleInspector/tdf137513.py
+++ b/sw/qa/uitest/styleInspector/tdf137513.py
@@ -35,7 +35,7 @@ class tdf137513(UITestCase):
             self.assertEqual(2, len(xListBox.getChild('0').getChildren()))
             self.assertEqual("Default Paragraph Style  ", 
get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
             self.assertEqual("Table Contents   ", 
get_state_as_dict(xListBox.getChild('0').getChild('1'))['Text'])
-            self.assertEqual(149, 
len(xListBox.getChild('0').getChild('0').getChildren()))
+            self.assertEqual(151, 
len(xListBox.getChild('0').getChild('0').getChildren()))
 
             xTableContent = xListBox.getChild('0').getChild('1')
             self.assertEqual(5, len(xTableContent.getChildren()))
diff --git a/sw/source/core/text/guess.cxx b/sw/source/core/text/guess.cxx
index 6057fd6f45d8..4740244139b7 100644
--- a/sw/source/core/text/guess.cxx
+++ b/sw/source/core/text/guess.cxx
@@ -157,7 +157,8 @@ bool 
SwTextGuess::maybeAdjustPositionsForBlockAdjust(tools::Long& rMaxSizeDiff,
 // returns true if no line break has to be performed
 // otherwise possible break or hyphenation position is determined
 bool SwTextGuess::Guess( const SwTextPortion& rPor, SwTextFormatInfo &rInf,
-                            const sal_uInt16 nPorHeight, sal_Int32 
nSpacesInLine )
+                            const sal_uInt16 nPorHeight, sal_Int32 
nSpacesInLine,
+                            sal_uInt16 nPropWordSpacing )
 {
     m_nCutPos = rInf.GetIdx();
 
@@ -183,17 +184,28 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, 
SwTextFormatInfo &rInf,
 
     SvxAdjustItem aAdjustItem = 
rInf.GetTextFrame()->GetTextNodeForParaProps()->GetSwAttrSet().GetAdjust();
     const SvxAdjust aAdjust = aAdjustItem.GetAdjust();
+    // Maximum word spacing allows bigger spaces to limit hyphenation,
+    // implement it based on the hyphenation zone: calculate a hyphenation zone
+    // from maximum word spacing and space count of the line
+    SwTwips nWordSpacingMaximumZone = 0;
 
-    // allow up to 20% shrinking of the spaces
     if ( nSpacesInLine )
     {
         static constexpr OUStringLiteral STR_BLANK = u" ";
         sal_Int16 nSpaceWidth = rInf.GetTextSize(STR_BLANK).Width();
-        float fWordSpacingOptimum = aAdjustItem.GetPropWordSpacing() == 100
+        float fWordSpacing = nPropWordSpacing == SAL_MAX_UINT16
                 ? 0.75 // MSO interoperability value
-                : aAdjustItem.GetPropWordSpacing() / 100.0;
-        SwTwips nExtraSpace = nSpacesInLine * nSpaceWidth * (1.0 - 
fWordSpacingOptimum);
+                       // allow up to 25% shrinking of the spaces
+                : nPropWordSpacing / 100.0;
+        SwTwips nExtraSpace = nSpacesInLine * nSpaceWidth * (1.0 - 
fWordSpacing);
         nLineWidth += nExtraSpace;
+        // convert maximum word spacing to hyphenation zone, if defined
+        if ( nPropWordSpacing == aAdjustItem.GetPropWordSpacing() )
+        {
+            SwTwips nMaxDif = aAdjustItem.GetPropWordSpacingMaximum() - 
nPropWordSpacing;
+            nWordSpacingMaximumZone = nSpacesInLine * nSpaceWidth * nMaxDif / 
100.0;
+        }
+
         rInf.SetExtraSpace(nExtraSpace);
     }
 
@@ -284,12 +296,15 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, 
SwTextFormatInfo &rInf,
         }
     }
 
-    bool bHyph = rInf.IsHyphenate() && !rInf.IsHyphForbud();
+    bool bHyph = rInf.IsHyphenate() && !rInf.IsHyphForbud() &&
+            // disable hyphenation at minimum word spacing
+            !( nPropWordSpacing < aAdjustItem.GetPropWordSpacing() );
+
     // disable hyphenation according to hyphenation-keep and 
hyphenation-keep-type,
     // or modify hyphenation according to hyphenation-zone-column/page/spread 
(see widorp.cxx)
     sal_Int16 nEndZone = 0;
     if ( bHyph &&
-          rInf.GetTextFrame()->GetNoHyphOffset() != 
TextFrameIndex(COMPLETE_STRING) &&
+          rInf.GetTextFrame()->GetNoHyphOffset() != 
TextFrameIndex(COMPLETE_STRING) && // ) // &&
           // when there is a portion in the last line, rInf.GetIdx() > 
GetNoHyphOffset()
           rInf.GetTextFrame()->GetNoHyphOffset() <= rInf.GetIdx() )
     {
@@ -318,6 +333,12 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, 
SwTextFormatInfo &rInf,
         sal_Int16 nTextHyphenZone = 0;
         sal_Int16 nTextHyphenZoneAlways = 0;
         rHyphValues[5].Value >>= nTextHyphenZone;
+
+        // maximum word spacing can result bigger hyphenation zone,
+        // if there are enough spaces in the line: apply that
+        if ( nWordSpacingMaximumZone > nTextHyphenZone )
+            nTextHyphenZone = nWordSpacingMaximumZone;
+
         rHyphValues[10].Value >>= nTextHyphenZoneAlways;
         if ( nTextHyphenZone || nTextHyphenZoneAlways || nEndZone )
         {
diff --git a/sw/source/core/text/guess.hxx b/sw/source/core/text/guess.hxx
index 6db8b107e971..54f38c7f1e90 100644
--- a/sw/source/core/text/guess.hxx
+++ b/sw/source/core/text/guess.hxx
@@ -44,7 +44,8 @@ public:
 
     // true, if current portion still fits to current line
     bool Guess( const SwTextPortion& rPor, SwTextFormatInfo &rInf,
-                    const sal_uInt16 nHeight, sal_Int32 nSpacesInLine = 0 );
+                    const sal_uInt16 nHeight, sal_Int32 nSpacesInLine = 0,
+                    sal_uInt16 nPropWordSpacing = 100 );
     bool AlternativeSpelling( const SwTextFormatInfo &rInf, const 
TextFrameIndex nPos );
 
     SwHangingPortion* GetHangingPortion() const { return m_pHanging.get(); }
diff --git a/sw/source/core/text/portxt.cxx b/sw/source/core/text/portxt.cxx
index eb1b538936c5..661e0ae883b4 100644
--- a/sw/source/core/text/portxt.cxx
+++ b/sw/source/core/text/portxt.cxx
@@ -365,11 +365,19 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf )
     // adjusted line by shrinking spaces using the know space count from the 
first Guess() call
     SvxAdjustItem aAdjustItem = 
rInf.GetTextFrame()->GetTextNodeForParaProps()->GetSwAttrSet().GetAdjust();
     const SvxAdjust aAdjust = aAdjustItem.GetAdjust();
-    if ( bFull && aAdjust == SvxAdjust::Block &&
-         pGuess->BreakPos() != TextFrameIndex(COMPLETE_STRING) &&
-         ( rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(
-                    DocumentSettingId::JUSTIFY_LINES_WITH_SHRINKING) ||
-           aAdjustItem.GetPropWordSpacing() != 100 ) &&
+    bool bFullJustified = bFull && aAdjust == SvxAdjust::Block &&
+         pGuess->BreakPos() != TextFrameIndex(COMPLETE_STRING);
+    bool bInteropSmartJustify = bFullJustified &&
+            rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(
+                    DocumentSettingId::JUSTIFY_LINES_WITH_SHRINKING);
+    bool bWordSpacing = bFullJustified && !bInteropSmartJustify &&
+           aAdjustItem.GetPropWordSpacing() != 100;
+    bool bWordSpacingMaximum = bFullJustified && !bInteropSmartJustify &&
+           aAdjustItem.GetPropWordSpacingMaximum() > 
aAdjustItem.GetPropWordSpacing();
+    bool bWordSpacingMinimum = bFullJustified && !bInteropSmartJustify &&
+           aAdjustItem.GetPropWordSpacingMinimum() < 
aAdjustItem.GetPropWordSpacing();
+
+    if ( ( bInteropSmartJustify || bWordSpacing || bWordSpacingMaximum || 
bWordSpacingMinimum ) &&
          // tdf#164499 no shrinking in tabulated line
          ( !rInf.GetLast() || !rInf.GetLast()->InTabGrp() ) &&
          // tdf#158436 avoid shrinking at underflow, e.g. no-break space after 
a
@@ -401,10 +409,39 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf )
         if ( nSpacesInLine > 0 )
         {
             SwTwips nOldWidth = pGuess->BreakWidth();
-            pGuess.emplace();
-            bFull = !pGuess->Guess( *this, rInf, Height(), nSpacesInLine );
+            if ( bInteropSmartJustify )
+            {
+                pGuess.emplace();
+                bFull = !pGuess->Guess( *this, rInf, Height(), nSpacesInLine, 
SAL_MAX_UINT16 );
+            }
+            else
+            {
+                if ( bWordSpacing || bWordSpacingMaximum )
+                {
+                    pGuess.emplace();
+                    bFull = !pGuess->Guess( *this, rInf, Height(), 
nSpacesInLine, aAdjustItem.GetPropWordSpacing() );
+                }
+                if ( bWordSpacingMinimum )
+                {
+                    std::optional<SwTextGuess> pGuess2(std::in_place);
+                    SwTwips nOldExtraSpace = rInf.GetExtraSpace();
+                    // break the line after the hyphenated word, if it's 
possible
+                    // (hyphenation is disabled in Guess(), when called with 
GetPropWordSpacingMinimum())
+                    // FIXME: if there are multiple possible break points 
allowed by minimum
+                    // word spacing, choose the nearest to the desired word 
spacing, not the opposite
+                    bool bFull2 = !pGuess2->Guess( *this, rInf, Height(), 
nSpacesInLine, aAdjustItem.GetPropWordSpacingMinimum() );
+                    if ( pGuess2->BreakWidth() > nOldWidth )
+                    {
+                        pGuess = std::move(pGuess2);
+                        bFull = bFull2;
+                    }
+                    else
+                        // minimum word spacing is not applicable
+                        rInf.SetExtraSpace(nOldExtraSpace);
+                }
+            }
 
-            if ( pGuess->BreakWidth() > nOldWidth )
+            if ( pGuess->BreakWidth() != nOldWidth )
                 ExtraShrunkWidth( pGuess->BreakWidth() );
         }
     }
diff --git a/sw/source/core/unocore/unomapproperties.hxx 
b/sw/source/core/unocore/unomapproperties.hxx
index 61e8163dbcba..40f97515f5ff 100644
--- a/sw/source/core/unocore/unomapproperties.hxx
+++ b/sw/source/core/unocore/unomapproperties.hxx
@@ -185,6 +185,8 @@
         { UNO_NAME_PARA_EXPAND_SINGLE_WORD,             RES_PARATR_ADJUST,     
        cppu::UnoType<bool>::get(),       PropertyAttribute::MAYBEVOID, 
MID_EXPAND_SINGLE                      }, \
         { UNO_NAME_PARA_LAST_LINE_ADJUST,               RES_PARATR_ADJUST,     
        cppu::UnoType<sal_Int16>::get(),         PropertyAttribute::MAYBEVOID, 
MID_LAST_LINE_ADJUST                   }, \
         { UNO_NAME_PARA_WORD_SPACING,                   RES_PARATR_ADJUST,     
        cppu::UnoType<sal_Int16>::get(),         PropertyAttribute::MAYBEVOID, 
MID_WORD_SPACING                       }, \
+        { UNO_NAME_PARA_WORD_SPACING_MIN,               RES_PARATR_ADJUST,     
        cppu::UnoType<sal_Int16>::get(),         PropertyAttribute::MAYBEVOID, 
MID_WORD_SPACING_MIN                   }, \
+        { UNO_NAME_PARA_WORD_SPACING_MAX,               RES_PARATR_ADJUST,     
        cppu::UnoType<sal_Int16>::get(),         PropertyAttribute::MAYBEVOID, 
MID_WORD_SPACING_MAX                   }, \
         { UNO_NAME_PARA_LINE_NUMBER_COUNT,              RES_LINENUMBER,        
        cppu::UnoType<bool>::get(),       PropertyAttribute::MAYBEVOID, 
MID_LINENUMBER_COUNT                   }, \
         { UNO_NAME_PARA_LINE_NUMBER_START_VALUE,        RES_LINENUMBER,        
        cppu::UnoType<sal_Int32>::get(),         PropertyAttribute::MAYBEVOID, 
MID_LINENUMBER_STARTVALUE              }, \
         { UNO_NAME_PARA_LINE_SPACING,                   
RES_PARATR_LINESPACING,        cppu::UnoType<css::style::LineSpacing>::get(),   
  PropertyAttribute::MAYBEVOID, CONVERT_TWIPS                          }, \
@@ -449,6 +451,8 @@
                     { UNO_NAME_PARA_EXPAND_SINGLE_WORD, RES_PARATR_ADJUST,     
 cppu::UnoType<bool>::get()  ,         PROPERTY_NONE, MID_EXPAND_SINGLE   },\
                     { UNO_NAME_PARA_LAST_LINE_ADJUST, RES_PARATR_ADJUST,      
cppu::UnoType<sal_Int16>::get(),       PROPERTY_NONE, MID_LAST_LINE_ADJUST},\
                     { UNO_NAME_PARA_WORD_SPACING, RES_PARATR_ADJUST,          
cppu::UnoType<sal_Int16>::get(),       PROPERTY_NONE, MID_WORD_SPACING    },\
+                    { UNO_NAME_PARA_WORD_SPACING_MIN, RES_PARATR_ADJUST,      
cppu::UnoType<sal_Int16>::get(),       PROPERTY_NONE, MID_WORD_SPACING_MIN},\
+                    { UNO_NAME_PARA_WORD_SPACING_MAX, RES_PARATR_ADJUST,      
cppu::UnoType<sal_Int16>::get(),       PROPERTY_NONE, MID_WORD_SPACING_MAX},\
                     { UNO_NAME_PARA_LINE_NUMBER_COUNT, RES_LINENUMBER,        
cppu::UnoType<bool>::get(),         PROPERTY_NONE ,MID_LINENUMBER_COUNT     },\
                     { UNO_NAME_PARA_LINE_NUMBER_START_VALUE, RES_LINENUMBER,   
   cppu::UnoType<sal_Int32>::get(),           PROPERTY_NONE 
,MID_LINENUMBER_STARTVALUE},\
                     { UNO_NAME_PARA_LINE_SPACING, RES_PARATR_LINESPACING, 
cppu::UnoType<css::style::LineSpacing>::get(),PROPERTY_NONE,     
CONVERT_TWIPS},\
diff --git a/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx 
b/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx
index 10f861246381..bf6600f9a0c4 100644
--- a/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx
+++ b/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx
@@ -309,7 +309,9 @@ static OUString PropertyNametoRID(const OUString& rName)
         { "ParaUserDefinedAttributes", RID_PARA_USER_DEFINED_ATTRIBUTES },
         { "ParaVertAlignment", RID_PARA_VERT_ALIGNMENT },
         { "ParaWidows", RID_PARA_WIDOWS },
+        { "ParaWordSpacingMinimum", RID_PARA_WORD_SPACING_MIN },
         { "ParaWordSpacing", RID_PARA_WORD_SPACING },
+        { "ParaWordSpacingMaximum", RID_PARA_WORD_SPACING_MAX },
         { "ReferenceMark", RID_REFERENCE_MARK },
         { "RightBorder", RID_RIGHT_BORDER },
         { "RightBorderDistance", RID_RIGHT_BORDER_DISTANCE },
diff --git a/xmloff/inc/xmlprop.hxx b/xmloff/inc/xmlprop.hxx
index 3224dc5653f5..df8c76673a2a 100644
--- a/xmloff/inc/xmlprop.hxx
+++ b/xmloff/inc/xmlprop.hxx
@@ -524,6 +524,8 @@ inline constexpr OUString PROP_ParaLineNumberStartValue = 
u"ParaLineNumberStartV
 inline constexpr OUString PROP_ParaLineSpacing = u"ParaLineSpacing"_ustr;
 inline constexpr OUString PROP_ParaOrphans = u"ParaOrphans"_ustr;
 inline constexpr OUString PROP_ParaWordSpacing = u"ParaWordSpacing"_ustr;
+inline constexpr OUString PROP_ParaWordSpacingMinimum = 
u"ParaWordSpacingMinimum"_ustr;
+inline constexpr OUString PROP_ParaWordSpacingMaximum = 
u"ParaWordSpacingMaximum"_ustr;
 inline constexpr OUString PROP_ParaRegisterModeActive = 
u"ParaRegisterModeActive"_ustr;
 inline constexpr OUString PROP_ParaRightMargin = u"ParaRightMargin"_ustr;
 inline constexpr OUString PROP_ParaRightMarginRelative = 
u"ParaRightMarginRelative"_ustr;
diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx
index 686865a3bc9c..c58ddd5eda26 100644
--- a/xmloff/source/core/xmltoken.cxx
+++ b/xmloff/source/core/xmltoken.cxx
@@ -2214,6 +2214,8 @@ namespace xmloff::token {
         TOKEN( "word",                            XML_WORD ),
         TOKEN( "word-count",                      XML_WORD_COUNT ),
         TOKEN( "word-spacing",                    XML_WORD_SPACING ),
+        TOKEN( "word-spacing-maximum",            XML_WORD_SPACING_MAXIMUM ),
+        TOKEN( "word-spacing-minimum",            XML_WORD_SPACING_MINIMUM ),
         TOKEN( "wrap",                            XML_WRAP ),
         TOKEN( "wrap-contour",                    XML_WRAP_CONTOUR ),
         TOKEN( "wrap-contour-mode",               XML_WRAP_CONTOUR_MODE ),
diff --git a/xmloff/source/style/xmlexppr.cxx b/xmloff/source/style/xmlexppr.cxx
index 543cd7381474..16626e6629e6 100644
--- a/xmloff/source/style/xmlexppr.cxx
+++ b/xmloff/source/style/xmlexppr.cxx
@@ -947,7 +947,9 @@ sal_Int8 CheckExtendedNamespace(std::u16string_view 
sXMLAttributeName, std::u16s
         || IsXMLToken(sXMLAttributeName, XML_HYPHENATION_ZONE_PAGE)
         || IsXMLToken(sXMLAttributeName, XML_HYPHENATION_ZONE_SPREAD))
         return IsXMLToken(sValue, XML_NO_LIMIT) ? -1 : 1;
-    else if (IsXMLToken(sXMLAttributeName, XML_WORD_SPACING))
+    else if (IsXMLToken(sXMLAttributeName, XML_WORD_SPACING)
+        || IsXMLToken(sXMLAttributeName, XML_WORD_SPACING_MINIMUM)
+        || IsXMLToken(sXMLAttributeName, XML_WORD_SPACING_MAXIMUM))
     {
         static constexpr OUString s100PercentCompare( u"100%"_ustr );
         size_t nBegin = sValue.find( s100PercentCompare );
diff --git a/xmloff/source/text/txtprmap.cxx b/xmloff/source/text/txtprmap.cxx
index d04a037bb18d..b95a77f0906f 100644
--- a/xmloff/source/text/txtprmap.cxx
+++ b/xmloff/source/text/txtprmap.cxx
@@ -483,6 +483,8 @@ XMLPropertyMapEntry constexpr aXMLParaPropMap[] =
     MAP_EXT_I( PROP_ParaFirstLineIndent, XML_NAMESPACE_LO_EXT, 
XML_TEXT_INDENT, 
XML_TYPE_PROP_PARAGRAPH|XML_TYPE_MEASURE|MID_FLAG_MULTI_PROPERTY, 
CTF_PARAFIRSTLINE ),
     MAP_EXT_I( PROP_ParaFirstLineIndentRelative, XML_NAMESPACE_LO_EXT, 
XML_TEXT_INDENT, XML_TYPE_PROP_PARAGRAPH|XML_TYPE_PERCENT, 
CTF_PARAFIRSTLINE_REL ),
     MAP_EXT( PROP_ParaWordSpacing, XML_NAMESPACE_LO_EXT, XML_WORD_SPACING, 
XML_TYPE_PROP_PARAGRAPH|XML_TYPE_PERCENT16, 0 ),
+    MAP_EXT( PROP_ParaWordSpacingMinimum, XML_NAMESPACE_LO_EXT, 
XML_WORD_SPACING_MINIMUM, XML_TYPE_PROP_PARAGRAPH|XML_TYPE_PERCENT16, 0 ),
+    MAP_EXT( PROP_ParaWordSpacingMaximum, XML_NAMESPACE_LO_EXT, 
XML_WORD_SPACING_MAXIMUM, XML_TYPE_PROP_PARAGRAPH|XML_TYPE_PERCENT16, 0 ),
 
     M_END()
 };
diff --git a/xmloff/source/token/tokens.txt b/xmloff/source/token/tokens.txt
index ad37fe87e600..6c7c02eb2aac 100644
--- a/xmloff/source/token/tokens.txt
+++ b/xmloff/source/token/tokens.txt
@@ -2114,6 +2114,8 @@ window-font-color
 word
 word-count
 word-spacing
+word-spacing-maximum
+word-spacing-minimum
 wrap
 wrap-contour
 wrap-contour-mode

Reply via email to