tdf#149420 sw offapi xmloff: add hyphenation zone

Add hyphenation zone support, i.e. allow the specified
amount of extra space in lines instead of forcing hyphenation.
It's for limiting hyphenation, used especially with
not justified paragraph alignment.

Note: this is an OOXML interoperability feature,
used also in DTP software and CSS.

* Add checkbox to Text Flow in paragraph dialog
* Store property in paragraph model (com::sun::star::style::ParagraphProperties::ParaHyphenationZone)
* Add ODF import/export
* Add ODF unit test
* Add layout test

Note: extend SvxHyphenZoneItem::GetPresentation() with
missing No CAPS and No last word hyphenation options.

Note: fix OSL_ENSURE condition in SwTextFormatInfo::GetHyphValues().

Follow-up to commit 29359fc15c435cec17987fd6221ab6833d38746e
"tdf#149324 sw offapi xmloff: add option to not hyphenate short words".

Change-Id: Ib8eff6ea98a9aa5ca6cb9d17faa0bbb789687ce9
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135247
Tested-by: Jenkins
Reviewed-by: László Németh <nemeth@numbertext.org>
diff --git a/cui/source/inc/paragrph.hxx b/cui/source/inc/paragrph.hxx
index f0c5677..3947c14 100644
--- a/cui/source/inc/paragrph.hxx
+++ b/cui/source/inc/paragrph.hxx
@@ -233,6 +233,7 @@ private:
    std::unique_ptr<weld::Label> m_xMaxHyphenLabel;
    std::unique_ptr<weld::SpinButton> m_xMaxHyphenEdit;
    std::unique_ptr<weld::SpinButton> m_xMinWordLength;
    std::unique_ptr<SvxRelativeField> m_xHyphenZone;

    // pagebreak
    std::unique_ptr<weld::CheckButton> m_xPageBreakBox;
diff --git a/cui/source/tabpages/paragrph.cxx b/cui/source/tabpages/paragrph.cxx
index 2d651fe..3fa77d9 100644
--- a/cui/source/tabpages/paragrph.cxx
+++ b/cui/source/tabpages/paragrph.cxx
@@ -1356,7 +1356,8 @@ bool SvxExtParagraphTabPage::FillItemSet( SfxItemSet* rOutSet )
         m_xExtHyphenBeforeBox->get_value_changed_from_saved() ||
         m_xExtHyphenAfterBox->get_value_changed_from_saved() ||
         m_xMaxHyphenEdit->get_value_changed_from_saved() ||
         m_xMinWordLength->get_value_changed_from_saved() )
         m_xMinWordLength->get_value_changed_from_saved() ||
         m_xHyphenZone->get_value_changed_from_saved() )
    {
        SvxHyphenZoneItem aHyphen(
            static_cast<const SvxHyphenZoneItem&>(GetItemSet().Get( _nWhich )) );
@@ -1372,6 +1373,11 @@ bool SvxExtParagraphTabPage::FillItemSet( SfxItemSet* rOutSet )
        }
        aHyphen.GetMaxHyphens() = static_cast<sal_uInt8>(m_xMaxHyphenEdit->get_value());

        SfxItemPool* pPool = GetItemSet().GetPool();
        DBG_ASSERT( pPool, "Where is the pool?" );
        MapUnit eUnit = pPool->GetMetric( _nWhich );
        aHyphen.GetTextHyphenZone() = static_cast<sal_uInt16>(m_xHyphenZone->GetCoreValue(eUnit));

        if ( !pOld ||
            *static_cast<const SvxHyphenZoneItem*>(pOld) != aHyphen ||
                m_xHyphenBox->get_state_changed_from_saved())
@@ -1560,6 +1566,17 @@ bool SvxExtParagraphTabPage::FillItemSet( SfxItemSet* rOutSet )
}
void SvxExtParagraphTabPage::Reset( const SfxItemSet* rSet )
{
    SfxItemPool* pPool = rSet->GetPool();
    DBG_ASSERT( pPool, "Where is the pool?" );

    // adjust metric
    FieldUnit eFUnit = GetModuleFieldUnit( *rSet );

    bool bApplyCharUnit = GetApplyCharUnit( *rSet );

    if( SvtCJKOptions::IsAsianTypographyEnabled() && bApplyCharUnit )
        eFUnit = FieldUnit::CHAR;

    sal_uInt16 _nWhich = GetWhich( SID_ATTR_PARA_HYPHENZONE );
    SfxItemState eItemState = rSet->GetItemState( _nWhich );

@@ -1580,6 +1597,8 @@ void SvxExtParagraphTabPage::Reset( const SfxItemSet* rSet )
        m_xExtHyphenAfterBox->set_value(rHyphen.GetMinTrail());
        m_xMaxHyphenEdit->set_value(rHyphen.GetMaxHyphens());
        m_xMinWordLength->set_value(rHyphen.GetMinWordLength());
        m_xHyphenZone->SetFieldUnit(eFUnit);
        m_xHyphenZone->SetMetricValue(rHyphen.GetTextHyphenZone(), MapUnit::MapTwip);
    }
    else
    {
@@ -1597,6 +1616,7 @@ void SvxExtParagraphTabPage::Reset( const SfxItemSet* rSet )
    m_xMaxHyphenLabel->set_sensitive(bEnable);
    m_xMaxHyphenEdit->set_sensitive(bEnable);
    m_xMinWordLength->set_sensitive(bEnable);
    m_xHyphenZone->set_sensitive(bEnable);

    switch (rSet->GetItemState(SID_ATTR_PARA_PAGENUM))
    {
@@ -1857,6 +1877,11 @@ void SvxExtParagraphTabPage::ChangesApplied()
    m_xExtHyphenAfterBox->set_value(m_xExtHyphenAfterBox->get_value());
    m_xMaxHyphenEdit->set_value(m_xMaxHyphenEdit->get_value());
    m_xMinWordLength->set_value(m_xMinWordLength->get_value());
    SfxItemPool* pPool = GetItemSet().GetPool();
    DBG_ASSERT( pPool, "Where is the pool?" );
    FieldUnit eUnit =
           MapToFieldUnit( pPool->GetMetric( GetWhich( SID_ATTR_PARA_HYPHENZONE ) ) );
    m_xHyphenZone->set_value(m_xHyphenZone->get_value(eUnit), eUnit);
    m_xPageBreakBox->save_state();
    m_xBreakPositionLB->save_value();
    m_xBreakTypeLB->save_value();
@@ -1908,6 +1933,7 @@ SvxExtParagraphTabPage::SvxExtParagraphTabPage(weld::Container* pPage, weld::Dia
    , m_xMaxHyphenLabel(m_xBuilder->weld_label("labelMaxNum"))
    , m_xMaxHyphenEdit(m_xBuilder->weld_spin_button("spinMaxNum"))
    , m_xMinWordLength(m_xBuilder->weld_spin_button("spinMinLen"))
    , m_xHyphenZone(new SvxRelativeField(m_xBuilder->weld_metric_spin_button("spinHyphenZone", FieldUnit::CM)))
    //Page break
    , m_xPageBreakBox(m_xBuilder->weld_check_button("checkInsert"))
    , m_xBreakTypeFT(m_xBuilder->weld_label("labelType"))
diff --git a/cui/uiconfig/ui/textflowpage.ui b/cui/uiconfig/ui/textflowpage.ui
index 89ac8a3..496f22f 100644
--- a/cui/uiconfig/ui/textflowpage.ui
+++ b/cui/uiconfig/ui/textflowpage.ui
@@ -48,6 +48,11 @@
    <property name="step_increment">1</property>
    <property name="page_increment">10</property>
  </object>
  <object class="GtkAdjustment" id="adjustment8">
    <property name="upper">55.88</property>
    <property name="step_increment">1</property>
    <property name="page_increment">10</property>
  </object>
  <!-- n-columns=1 n-rows=1 -->
  <object class="GtkGrid" id="TextFlowPage">
    <property name="visible">True</property>
@@ -258,6 +263,49 @@
                <property name="width">2</property>
              </packing>
            </child>
            <child>
              <!-- n-columns=1 n-rows=1 -->
              <object class="GtkGrid" id="gridHyphenZone">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="row_spacing">6</property>
                <property name="column_spacing">12</property>
                <property name="margin-start">12</property>
                <property name="margin-top">6</property>
                <child>
                  <object class="GtkSpinButton" id="spinHyphenZone">
                    <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">adjustment8</property>
                  </object>
                  <packing>
                    <property name="left_attach">1</property>
                    <property name="top_attach">0</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkLabel" id="labelHyphenZone">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="label" translatable="yes" context="textflowpage|labelHyphenZone">Hyphenation _zone:</property>
                    <property name="use_underline">True</property>
                    <property name="mnemonic_widget">spinHyphenZone</property>
                    <property name="xalign">0</property>
                  </object>
                  <packing>
                    <property name="left_attach">0</property>
                    <property name="top_attach">0</property>
                  </packing>
                </child>
              </object>
              <packing>
                <property name="left_attach">0</property>
                <property name="top_attach">7</property>
                <property name="width">2</property>
              </packing>
            </child>
          </object>
        </child>
        <child type="label">
diff --git a/editeng/source/items/paraitem.cxx b/editeng/source/items/paraitem.cxx
index 202341ca..9368dfd 100644
--- a/editeng/source/items/paraitem.cxx
+++ b/editeng/source/items/paraitem.cxx
@@ -559,7 +559,8 @@ SvxHyphenZoneItem::SvxHyphenZoneItem( const bool bHyph, const sal_uInt16 nId ) :
    nMinLead(0),
    nMinTrail(0),
    nMaxHyphens(255),
    nMinWordLength(0)
    nMinWordLength(0),
    nTextHyphenZone(0)
{
}

@@ -590,6 +591,9 @@ bool    SvxHyphenZoneItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) con
        case MID_HYPHEN_MIN_WORD_LENGTH:
            rVal <<= static_cast<sal_Int16>(nMinWordLength);
        break;
        case MID_HYPHEN_ZONE:
            rVal <<= static_cast<sal_Int16>(nTextHyphenZone);
        break;
    }
    return true;
}
@@ -629,6 +633,9 @@ bool SvxHyphenZoneItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
        case MID_HYPHEN_MIN_WORD_LENGTH:
            nMinWordLength = static_cast<sal_uInt8>(nNewVal);
        break;
        case MID_HYPHEN_ZONE:
            nTextHyphenZone = nNewVal;
        break;
    }
    return true;
}
@@ -646,7 +653,8 @@ bool SvxHyphenZoneItem::operator==( const SfxPoolItem& rAttr ) const
            && rItem.nMinLead == nMinLead
            && rItem.nMinTrail == nMinTrail
            && rItem.nMaxHyphens == nMaxHyphens
            && rItem.nMinWordLength == nMinWordLength );
            && rItem.nMinWordLength == nMinWordLength
            && rItem.nTextHyphenZone == nTextHyphenZone );
}

SvxHyphenZoneItem* SvxHyphenZoneItem::Clone( SfxItemPool * ) const
@@ -657,9 +665,9 @@ SvxHyphenZoneItem* SvxHyphenZoneItem::Clone( SfxItemPool * ) const
bool SvxHyphenZoneItem::GetPresentation
(
    SfxItemPresentation ePres,
    MapUnit             /*eCoreUnit*/,
    MapUnit             /*ePresUnit*/,
    OUString&           rText, const IntlWrapper&
    MapUnit             eCoreUnit,
    MapUnit             ePresUnit,
    OUString&           rText, const IntlWrapper& rIntl
)   const
{
    OUString cpDelimTmp(cpDelim);
@@ -680,7 +688,16 @@ bool SvxHyphenZoneItem::GetPresentation
                    OUString::number( nMinLead ) + cpDelimTmp +
                    OUString::number( nMinTrail ) + cpDelimTmp +
                    OUString::number( nMaxHyphens ) + cpDelimTmp +
                    OUString::number( nMinWordLength );
                    OUString::number( nMinWordLength ) + cpDelimTmp +
                    GetMetricText( nTextHyphenZone, eCoreUnit, ePresUnit, &rIntl ) +
                        " " + EditResId(GetMetricId(ePresUnit));

            if ( bNoCapsHyphenation )
                rText += cpDelimTmp + EditResId(RID_SVXITEMS_HYPHEN_NO_CAPS_TRUE);

            if ( bNoLastWordHyphenation )
                rText += cpDelimTmp + EditResId(RID_SVXITEMS_HYPHEN_LAST_WORD_TRUE);

            return true;
        }
        case SfxItemPresentation::Complete:
@@ -703,6 +720,20 @@ bool SvxHyphenZoneItem::GetPresentation
                    EditResId(RID_SVXITEMS_HYPHEN_MAX).replaceAll("%1", OUString::number(nMaxHyphens)) +
                    cpDelimTmp +
                    EditResId(RID_SVXITEMS_HYPHEN_MINWORDLEN).replaceAll("%1", OUString::number(nMinWordLength));

            if ( nTextHyphenZone > 0 )
            {
                rText += cpDelimTmp + EditResId(RID_SVXITEMS_HYPHEN_ZONE) +
                        GetMetricText( nTextHyphenZone, eCoreUnit, ePresUnit, &rIntl ) +
                        " " + EditResId(GetMetricId(ePresUnit));
            }

            if ( bNoCapsHyphenation )
                rText += cpDelimTmp + EditResId(RID_SVXITEMS_HYPHEN_NO_CAPS_TRUE);

            if ( bNoLastWordHyphenation )
                rText += cpDelimTmp + EditResId(RID_SVXITEMS_HYPHEN_LAST_WORD_TRUE);

            return true;
        }
        default: ;//prevent warning
diff --git a/include/editeng/editrids.hrc b/include/editeng/editrids.hrc
index 57342e7..31ac07a 100644
--- a/include/editeng/editrids.hrc
+++ b/include/editeng/editrids.hrc
@@ -230,7 +230,10 @@
#define RID_SVXITEMS_HYPHEN_MINLEAD             NC_("RID_SVXITEMS_HYPHEN_MINLEAD", "%1 characters at end of line")
#define RID_SVXITEMS_HYPHEN_MINTRAIL            NC_("RID_SVXITEMS_HYPHEN_MINTRAIL", "%1 characters at beginning of line")
#define RID_SVXITEMS_HYPHEN_MAX                 NC_("RID_SVXITEMS_HYPHEN_MAX", "%1 hyphens")
#define RID_SVXITEMS_HYPHEN_MINWORDLEN          NC_("RID_SVXITEMS_HYPHEN_MINWORDLEN", "Words with at least %1 characters")
#define RID_SVXITEMS_HYPHEN_NO_CAPS_TRUE        NC_("RID_SVXITEMS_HYPHEN_NO_CAPS_TRUE", "Not hyphenated CAPS")
#define RID_SVXITEMS_HYPHEN_LAST_WORD_TRUE      NC_("RID_SVXITEMS_HYPHEN_NO_CAPS_FALSE", "Not hyphenated last word")
#define RID_SVXITEMS_HYPHEN_MINWORDLEN          NC_("RID_SVXITEMS_HYPHEN_MINWORDLEN", "%1 characters in words")
#define RID_SVXITEMS_HYPHEN_ZONE                NC_("RID_SVXITEMS_HYPHEN_ZONE", "Hyphenation zone ")
#define RID_SVXITEMS_PAGEMODEL_COMPLETE         NC_("RID_SVXITEMS_PAGEMODEL_COMPLETE", "Page Style: ")
#define RID_SVXITEMS_KERNING_COMPLETE           NC_("RID_SVXITEMS_KERNING_COMPLETE", "Kerning ")
#define RID_SVXITEMS_KERNING_EXPANDED           NC_("RID_SVXITEMS_KERNING_EXPANDED", "locked ")
diff --git a/include/editeng/hyphenzoneitem.hxx b/include/editeng/hyphenzoneitem.hxx
index b1ec7cb..7104d2d 100644
--- a/include/editeng/hyphenzoneitem.hxx
+++ b/include/editeng/hyphenzoneitem.hxx
@@ -38,8 +38,9 @@ class EDITENG_DLLPUBLIC SvxHyphenZoneItem final : public SfxPoolItem
    bool      bNoLastWordHyphenation : 1;
    sal_uInt8 nMinLead;
    sal_uInt8 nMinTrail;
    sal_uInt8 nMaxHyphens;
    sal_uInt8 nMinWordLength;
    sal_uInt8 nMaxHyphens;      // max. consecutive lines with hyphenation
    sal_uInt8 nMinWordLength;   // hyphenate only words with at least nMinWordLength characters
    sal_uInt16 nTextHyphenZone; // don't force hyphenation at line end, allow this extra white space

public:
    static SfxPoolItem* CreateDefault();
@@ -81,6 +82,9 @@ public:

    sal_uInt8 &GetMinWordLength() { return nMinWordLength; }
    sal_uInt8 GetMinWordLength() const { return nMinWordLength; }

    sal_uInt16 &GetTextHyphenZone() { return nTextHyphenZone; }
    sal_uInt16 GetTextHyphenZone() const { return nTextHyphenZone; }
};

#endif
diff --git a/include/editeng/memberids.h b/include/editeng/memberids.h
index 4ec470f3..9b89eba 100644
--- a/include/editeng/memberids.h
+++ b/include/editeng/memberids.h
@@ -49,6 +49,7 @@
#define MID_HYPHEN_NO_CAPS      4
#define MID_HYPHEN_NO_LAST_WORD 5
#define MID_HYPHEN_MIN_WORD_LENGTH 6
#define MID_HYPHEN_ZONE         7

// SvxBoxInfoItem
#define MID_HORIZONTAL          1
diff --git a/include/unotools/linguprops.hxx b/include/unotools/linguprops.hxx
index adede0b..971c028 100644
--- a/include/unotools/linguprops.hxx
+++ b/include/unotools/linguprops.hxx
@@ -42,6 +42,7 @@ inline constexpr OUStringLiteral UPN_HYPH_MIN_TRAILING               = u"HyphMin
inline constexpr OUStringLiteral UPN_HYPH_MIN_WORD_LENGTH            = u"HyphMinWordLength";
inline constexpr OUStringLiteral UPN_HYPH_NO_CAPS                    = u"HyphNoCaps";
inline constexpr OUStringLiteral UPN_HYPH_NO_LAST_WORD               = u"HyphNoLastWord";
inline constexpr OUStringLiteral UPN_HYPH_ZONE                       = u"HyphZone";

// UNO property names for Lingu
// (those not covered by the SpellChecker and Hyphenator
@@ -109,6 +110,7 @@ inline constexpr OUStringLiteral UPN_IS_GRAMMAR_INTERACTIVE          = u"IsInter
#define UPH_IS_GRAMMAR_INTERACTIVE          35
#define UPH_HYPH_NO_CAPS                    36
#define UPH_HYPH_NO_LAST_WORD               37
#define UPH_HYPH_ZONE                       38

#ifdef __GNUC__
#pragma GCC diagnostic pop
diff --git a/include/xmloff/xmltoken.hxx b/include/xmloff/xmltoken.hxx
index 4592c01..69a4956 100644
--- a/include/xmloff/xmltoken.hxx
+++ b/include/xmloff/xmltoken.hxx
@@ -1053,6 +1053,7 @@ namespace xmloff::token {
        XML_HYPHENATION_NO_CAPS,
        XML_HYPHENATION_NO_LAST_WORD,
        XML_HYPHENATION_WORD_CHAR_COUNT,
        XML_HYPHENATION_ZONE,
        XML_I,
        XML_ICON,
        XML_ICON_SET,
diff --git a/offapi/com/sun/star/style/ParagraphProperties.idl b/offapi/com/sun/star/style/ParagraphProperties.idl
index e9522d77..32a6328 100644
--- a/offapi/com/sun/star/style/ParagraphProperties.idl
+++ b/offapi/com/sun/star/style/ParagraphProperties.idl
@@ -428,6 +428,13 @@ published service ParagraphProperties
            @since LibreOffice 7.4
         */
        [optional, property] short ParaHyphenationMinWordLength;

        /** specifies the hyphenation zone, i.e. allowed extra white space
            in the line before applying hyphenation.

            @since LibreOffice 7.4
         */
        [optional, property] long ParaHyphenationZone;
};


diff --git a/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng b/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng
index d5857c1..293e40d 100644
--- a/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng
+++ b/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng
@@ -2727,6 +2727,18 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.
  </rng:define>

  <!-- TODO no proposal -->
  <rng:define name="style-text-properties-attlist" combine="interleave">
    <rng:optional>
      <rng:attribute name="loext:hyphenation-zone">
        <rng:choice>
          <rng:value>no-limit</rng:value>
          <rng:ref name="positiveInteger"/>
        </rng:choice>
      </rng:attribute>
    </rng:optional>
  </rng:define>

  <!-- TODO no proposal -->
  <rng:define name="chart-data-point-attlist" combine="interleave">
    <rng:optional>
      <rng:attribute name="loext:custom-label-pos-x">
diff --git a/svx/sdi/svxitems.sdi b/svx/sdi/svxitems.sdi
index 00e4b74..df38999 100644
--- a/svx/sdi/svxitems.sdi
+++ b/svx/sdi/svxitems.sdi
@@ -260,6 +260,7 @@ struct SvxHyphenZone
    INT16       MinTrail      MID_HYPHEN_MIN_TRAIL;
    INT16       MaxHyphens    MID_HYPHEN_MAX_HYPHENS;
    INT16       MinWordLength MID_HYPHEN_MIN_WORD_LENGTH;
    INT16       HyphenZone    MID_HYPHEN_ZONE;
};
item SvxHyphenZone SvxHyphenZoneItem;

diff --git a/sw/inc/inspectorproperties.hrc b/sw/inc/inspectorproperties.hrc
index f1327ec..c2fd2a1 100644
--- a/sw/inc/inspectorproperties.hrc
+++ b/sw/inc/inspectorproperties.hrc
@@ -208,6 +208,7 @@
#define RID_PARA_HYPHENATION_NO_CAPS                        NC_("RID_ATTRIBUTE_NAMES_MAP", "Para Hyphenation No Caps")
#define RID_PARA_HYPHENATION_NO_LAST_WORD                   NC_("RID_ATTRIBUTE_NAMES_MAP", "Para Hyphenation No Last Word")
#define RID_PARA_HYPHENATION_MIN_WORD_LENGTH                NC_("RID_ATTRIBUTE_NAMES_MAP", "Para Hyphenation Min Word Length")
#define RID_PARA_HYPHENATION_ZONE                           NC_("RID_ATTRIBUTE_NAMES_MAP", "Para Hyphenation Zone")
#define RID_PARA_INTEROP_GRAB_BAG                           NC_("RID_ATTRIBUTE_NAMES_MAP", "Para Interop Grab Bag")
#define RID_PARA_IS_AUTO_FIRST_LINE_INDENT                  NC_("RID_ATTRIBUTE_NAMES_MAP", "Para is Auto First Line Indent")
#define RID_PARA_IS_CHARACTER_DISTANCE                      NC_("RID_ATTRIBUTE_NAMES_MAP", "Para is Character Distance")
diff --git a/sw/inc/unoprnms.hxx b/sw/inc/unoprnms.hxx
index 14da263..c3a7d97 100644
--- a/sw/inc/unoprnms.hxx
+++ b/sw/inc/unoprnms.hxx
@@ -65,6 +65,7 @@
#define UNO_NAME_PARA_HYPHENATION_MAX_TRAILING_CHARS "ParaHyphenationMaxTrailingChars"
#define UNO_NAME_PARA_HYPHENATION_MAX_HYPHENS "ParaHyphenationMaxHyphens"
#define UNO_NAME_PARA_HYPHENATION_MIN_WORD_LENGTH "ParaHyphenationMinWordLength"
#define UNO_NAME_PARA_HYPHENATION_ZONE "ParaHyphenationZone"
#define UNO_NAME_PARA_HYPHENATION_NO_CAPS "ParaHyphenationNoCaps"
#define UNO_NAME_PARA_HYPHENATION_NO_LAST_WORD "ParaHyphenationNoLastWord"
#define UNO_NAME_LEFT_MARGIN "LeftMargin"
diff --git a/sw/qa/extras/layout/data/tdf149420.odt b/sw/qa/extras/layout/data/tdf149420.odt
new file mode 100644
index 0000000..249d726
--- /dev/null
+++ b/sw/qa/extras/layout/data/tdf149420.odt
Binary files differ
diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx
index e42f5c2..2a6b2ca 100644
--- a/sw/qa/extras/layout/layout.cxx
+++ b/sw/qa/extras/layout/layout.cxx
@@ -4379,6 +4379,21 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf121658)
    assertXPath(pXmlDoc, "//Special[@nType='PortionType::Hyphen']", 2);
}

CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf149420)
{
    uno::Reference<linguistic2::XHyphenator> xHyphenator = LinguMgr::GetHyphenator();
    if (!xHyphenator->hasLocale(lang::Locale("en", "US", OUString())))
        return;

    createSwDoc(DATA_DIRECTORY, "tdf149420.odt");
    xmlDocUniquePtr pXmlDoc = parseLayoutDump();

    // Only 3 hyphenated words should appear in the document (last paragraph
    // has got a 1 cm hyphenation zone, removing two hyphenations, which visible
    // in the second paragraph).
    assertXPath(pXmlDoc, "//Special[@nType='PortionType::Hyphen']", 8);
}

CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf149324)
{
    uno::Reference<linguistic2::XHyphenator> xHyphenator = LinguMgr::GetHyphenator();
diff --git a/sw/qa/extras/odfexport/data/tdf149420.odt b/sw/qa/extras/odfexport/data/tdf149420.odt
new file mode 100644
index 0000000..249d726
--- /dev/null
+++ b/sw/qa/extras/odfexport/data/tdf149420.odt
Binary files differ
diff --git a/sw/qa/extras/odfexport/odfexport.cxx b/sw/qa/extras/odfexport/odfexport.cxx
index 6f85db1..e58b772 100644
--- a/sw/qa/extras/odfexport/odfexport.cxx
+++ b/sw/qa/extras/odfexport/odfexport.cxx
@@ -3052,6 +3052,13 @@ DECLARE_ODFEXPORT_TEST(tdf149324, "tdf149324.odt")
    CPPUNIT_ASSERT_EQUAL(sal_uInt16(7), getProperty<sal_uInt16>(getParagraph(4), "ParaHyphenationMinWordLength"));
}

DECLARE_ODFEXPORT_TEST(tdf149420, "tdf149420.odt")
{
    CPPUNIT_ASSERT_EQUAL(1, getPages());
    CPPUNIT_ASSERT_EQUAL(sal_uInt16(0), getProperty<sal_uInt16>(getParagraph(2), "ParaHyphenationZone"));
    CPPUNIT_ASSERT_EQUAL(sal_uInt16(567), getProperty<sal_uInt16>(getParagraph(4), "ParaHyphenationZone"));
}

DECLARE_ODFEXPORT_TEST(testArabicZeroNumbering, "arabic-zero-numbering.odt")
{
    CPPUNIT_ASSERT_EQUAL(1, getPages());
diff --git a/sw/qa/uitest/styleInspector/styleInspector.py b/sw/qa/uitest/styleInspector/styleInspector.py
index 29300f6..f5ce2cd 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\t", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
            self.assertEqual(139, len(xListBox.getChild('0').getChild('0').getChildren()))
            self.assertEqual(140, 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\t", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
            self.assertEqual(139, len(xListBox.getChild('0').getChild('0').getChildren()))
            self.assertEqual(140, 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\t", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
            self.assertEqual(139, len(xListBox.getChild('0').getChild('0').getChildren()))
            self.assertEqual(140, len(xListBox.getChild('0').getChild('0').getChildren()))

            xParDirFormatting = xListBox.getChild('1')
            self.assertEqual(7, len(xParDirFormatting.getChildren()))
@@ -75,7 +75,7 @@ class styleNavigator(UITestCase):
            xParStyle = xListBox.getChild('0')
            self.assertEqual(3, len(xParStyle.getChildren()))
            self.assertEqual("Default Paragraph Style\t", get_state_as_dict(xParStyle.getChild('0'))['Text'])
            self.assertEqual(139, len(xParStyle.getChild('0').getChildren()))
            self.assertEqual(140, len(xParStyle.getChild('0').getChildren()))
            self.assertEqual("Heading\t", get_state_as_dict(xParStyle.getChild('1'))['Text'])
            self.assertEqual(28, len(xParStyle.getChild('1').getChildren()))

@@ -109,7 +109,7 @@ class styleNavigator(UITestCase):
            xParStyle = xListBox.getChild('0')
            self.assertEqual(3, len(xParStyle.getChildren()))
            self.assertEqual("Default Paragraph Style\t", get_state_as_dict(xParStyle.getChild('0'))['Text'])
            self.assertEqual(139, len(xParStyle.getChild('0').getChildren()))
            self.assertEqual(140, len(xParStyle.getChild('0').getChildren()))
            self.assertEqual("Text Body\t", get_state_as_dict(xParStyle.getChild('1'))['Text'])
            self.assertEqual(6, len(xParStyle.getChild('1').getChildren()))

@@ -144,7 +144,7 @@ class styleNavigator(UITestCase):
            # The cursor is on text without metadata
            self.assertEqual(1, len(xListBox.getChild('0').getChildren()))
            self.assertEqual("Default Paragraph Style\t", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
            self.assertEqual(139, len(xListBox.getChild('0').getChild('0').getChildren()))
            self.assertEqual(140, 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()))
@@ -154,7 +154,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\t", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
            self.assertEqual(139, len(xListBox.getChild('0').getChild('0').getChildren()))
            self.assertEqual(140, len(xListBox.getChild('0').getChild('0').getChildren()))

            xParDirFormatting = xListBox.getChild('1')
            self.assertEqual(1, len(xParDirFormatting.getChildren()))
@@ -207,7 +207,7 @@ class styleNavigator(UITestCase):
            # The cursor is on text without metadata
            self.assertEqual(1, len(xListBox.getChild('0').getChildren()))
            self.assertEqual("Default Paragraph Style\t", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
            self.assertEqual(139, len(xListBox.getChild('0').getChild('0').getChildren()))
            self.assertEqual(140, 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()))
@@ -217,7 +217,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\t", get_state_as_dict(xListBox.getChild('1').getChild('0'))['Text'])
            self.assertEqual(139, len(xListBox.getChild('1').getChild('0').getChildren()))
            self.assertEqual(140, len(xListBox.getChild('1').getChild('0').getChildren()))

            # Outer bookmark
            xBookmarkFormatting = xListBox.getChild('0')
@@ -264,7 +264,7 @@ class styleNavigator(UITestCase):
            # The cursor is on text without metadata
            self.assertEqual(1, len(xListBox.getChild('0').getChildren()))
            self.assertEqual("Default Paragraph Style\t", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
            self.assertEqual(139, len(xListBox.getChild('0').getChild('0').getChildren()))
            self.assertEqual(140, 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 8dfc592..a0c9dda 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\t", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
            self.assertEqual("Table Contents\t", get_state_as_dict(xListBox.getChild('0').getChild('1'))['Text'])
            self.assertEqual(139, len(xListBox.getChild('0').getChild('0').getChildren()))
            self.assertEqual(140, 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 d2711d4..3055c69 100644
--- a/sw/source/core/text/guess.cxx
+++ b/sw/source/core/text/guess.cxx
@@ -196,29 +196,69 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, SwTextFormatInfo &rInf,
    // considering an additional "-" for hyphenation
    if( bHyph )
    {
        // search start of the last word, if needed
        sal_Int32 nLastWord = rInf.GetText().getLength() - 1;
        bool bHyphenationNoLastWord = false;
        // nHyphZone is the first character not fitting in the hyphenation zone,
        // or 0, if the whole line in the hyphenation zone,
        // or -1, if no hyphenation zone defined (i.e. it is 0)
        sal_Int32 nHyphZone = -1;
        const css::beans::PropertyValues & rHyphValues = rInf.GetHyphValues();
        assert( rHyphValues.getLength() > 3 && rHyphValues[3].Name == UPN_HYPH_NO_LAST_WORD );
        if ( rHyphValues[3].Value >>= bHyphenationNoLastWord )
        {
            bool bCutBlank = false;
            for (; sal_Int32(rInf.GetIdx()) <= nLastWord; --nLastWord )
            {
                sal_Unicode cChar = rInf.GetText()[nLastWord];
                if ( cChar != CH_BLANK && cChar != CH_FULL_BLANK && cChar != CH_SIX_PER_EM )
                    bCutBlank = true;
                else if ( bCutBlank )
                    break;
            }
        }
        assert( rHyphValues.getLength() > 5 && rHyphValues[5].Name == UPN_HYPH_ZONE );
        // hyphenation zone (distance from the line end in twips)
        sal_uInt16 nTextHyphenZone;
        if ( rHyphValues[5].Value >>= nTextHyphenZone )
            nHyphZone = nTextHyphenZone >= nLineWidth
                ? 0
                : sal_Int32(rInf.GetTextBreak( nLineWidth - nTextHyphenZone,
                                        nMaxLen, nMaxComp, rInf.GetCachedVclData().get() ));

        m_nCutPos = rInf.GetTextBreak( nLineWidth, nMaxLen, nMaxComp, nHyphPos, rInf.GetCachedVclData().get() );

        // don't hyphenate last word of the paragraph
        if ( bHyphenationNoLastWord && sal_Int32(m_nCutPos) > nLastWord )
            m_nCutPos = TextFrameIndex(nLastWord);
        // don't try to hyphenate in the hyphenation zone
        if ( nHyphZone != -1 && TextFrameIndex(COMPLETE_STRING) != m_nCutPos )
        {
            sal_Int32 nZonePos = sal_Int32(m_nCutPos);
            // disable hyphenation, if there is a space within the hyphenation zone
            // Note: for better interoperability, not fitting space character at
            // rInf.GetIdx()[nHyphZone] always disables the hyphenation, don't need to calculate
            // with its fitting part. Moreover, do not check double or more spaces there, they
            // are accepted outside of the hyphenation zone, too.
            for (; sal_Int32(rInf.GetIdx()) <= nZonePos && nHyphZone <= nZonePos; --nZonePos )
            {
                sal_Unicode cChar = rInf.GetText()[nZonePos];
                if ( cChar == CH_BLANK || cChar == CH_FULL_BLANK || cChar == CH_SIX_PER_EM )
                {
                    bHyph = false;
                }
            }
        }

        // search start of the last word, if needed
        if ( bHyph )
        {
            // nLastWord is the space character before the last word
            sal_Int32 nLastWord = rInf.GetText().getLength() - 1;
            bool bHyphenationNoLastWord = false;
            assert( rHyphValues.getLength() > 3 && rHyphValues[3].Name == UPN_HYPH_NO_LAST_WORD );
            if ( rHyphValues[3].Value >>= bHyphenationNoLastWord )
            {
                // skip spaces after the last word
                bool bCutBlank = false;
                for (; sal_Int32(rInf.GetIdx()) <= nLastWord; --nLastWord )
                {
                    sal_Unicode cChar = rInf.GetText()[nLastWord];
                    if ( cChar != CH_BLANK && cChar != CH_FULL_BLANK && cChar != CH_SIX_PER_EM )
                        bCutBlank = true;
                    else if ( bCutBlank )
                        break;
                }
            }

            // don't hyphenate the last word of the paragraph
            if ( bHyphenationNoLastWord && sal_Int32(m_nCutPos) > nLastWord &&
                            TextFrameIndex(COMPLETE_STRING) != m_nCutPos )
            {
                m_nCutPos = TextFrameIndex(nLastWord);
            }
        }

        if ( !nHyphPos && rInf.GetIdx() )
            nHyphPos = rInf.GetIdx() - TextFrameIndex(1);
diff --git a/sw/source/core/text/inftxt.cxx b/sw/source/core/text/inftxt.cxx
index 5a79437..c3a5068 100644
--- a/sw/source/core/text/inftxt.cxx
+++ b/sw/source/core/text/inftxt.cxx
@@ -1361,13 +1361,14 @@ void SwTextPaintInfo::DrawViewOpt( const SwLinePortion &rPor,

static void lcl_InitHyphValues( PropertyValues &rVals,
            sal_Int16 nMinLeading, sal_Int16 nMinTrailing,
            bool bNoCapsHyphenation, bool bNoLastWordHyphenation, sal_Int16 nMinWordLength )
            bool bNoCapsHyphenation, bool bNoLastWordHyphenation,
            sal_Int16 nMinWordLength, sal_Int16 nTextHyphZone )
{
    sal_Int32 nLen = rVals.getLength();

    if (0 == nLen)  // yet to be initialized?
    {
        rVals.realloc( 5 );
        rVals.realloc( 6 );
        PropertyValue *pVal = rVals.getArray();

        pVal[0].Name    = UPN_HYPH_MIN_LEADING;
@@ -1389,8 +1390,12 @@ static void lcl_InitHyphValues( PropertyValues &rVals,
        pVal[4].Name    = UPN_HYPH_MIN_WORD_LENGTH;
        pVal[4].Handle  = UPH_HYPH_MIN_WORD_LENGTH;
        pVal[4].Value   <<= nMinWordLength;

        pVal[5].Name    = UPN_HYPH_ZONE;
        pVal[5].Handle  = UPH_HYPH_ZONE;
        pVal[5].Value   <<= nTextHyphZone;
    }
    else if (5 == nLen) // already initialized once?
    else if (6 == nLen) // already initialized once?
    {
        PropertyValue *pVal = rVals.getArray();
        pVal[0].Value <<= nMinLeading;
@@ -1398,6 +1403,7 @@ static void lcl_InitHyphValues( PropertyValues &rVals,
        pVal[2].Value <<= bNoCapsHyphenation;
        pVal[3].Value <<= bNoLastWordHyphenation;
        pVal[4].Value <<= nMinWordLength;
        pVal[5].Value <<= nTextHyphZone;
    }
    else {
        OSL_FAIL( "unexpected size of sequence" );
@@ -1406,7 +1412,7 @@ static void lcl_InitHyphValues( PropertyValues &rVals,

const PropertyValues & SwTextFormatInfo::GetHyphValues() const
{
    OSL_ENSURE( 4 == m_aHyphVals.getLength(),
    OSL_ENSURE( 6 == m_aHyphVals.getLength(),
            "hyphenation values not yet initialized" );
    return m_aHyphVals;
}
@@ -1427,8 +1433,10 @@ bool SwTextFormatInfo::InitHyph( const bool bAutoHyphen )
        const sal_Int16 nMinimalWordLength = rAttr.GetMinWordLength();
        const bool bNoCapsHyphenation = rAttr.IsNoCapsHyphenation();
        const bool bNoLastWordHyphenation = rAttr.IsNoLastWordHyphenation();
        const sal_Int16 nTextHyphZone = rAttr.GetTextHyphenZone();
        lcl_InitHyphValues( m_aHyphVals, nMinimalLeading, nMinimalTrailing,
                 bNoCapsHyphenation, bNoLastWordHyphenation, nMinimalWordLength );
                 bNoCapsHyphenation, bNoLastWordHyphenation,
                 nMinimalWordLength, nTextHyphZone );
    }
    return bAuto;
}
diff --git a/sw/source/core/unocore/unomapproperties.hxx b/sw/source/core/unocore/unomapproperties.hxx
index 1f679b2..da2d4d9 100644
--- a/sw/source/core/unocore/unomapproperties.hxx
+++ b/sw/source/core/unocore/unomapproperties.hxx
@@ -118,6 +118,7 @@
        { u"" UNO_NAME_PARA_HYPHENATION_MAX_TRAILING_CHARS, RES_PARATR_HYPHENZONE,         cppu::UnoType<sal_Int16>::get(),         PropertyAttribute::MAYBEVOID, MID_HYPHEN_MIN_TRAIL                   }, \
        { u"" UNO_NAME_PARA_HYPHENATION_MAX_HYPHENS,        RES_PARATR_HYPHENZONE,         cppu::UnoType<sal_Int16>::get(),         PropertyAttribute::MAYBEVOID, MID_HYPHEN_MAX_HYPHENS                 }, \
        { u"" UNO_NAME_PARA_HYPHENATION_MIN_WORD_LENGTH,    RES_PARATR_HYPHENZONE,         cppu::UnoType<sal_Int16>::get(),         PropertyAttribute::MAYBEVOID, MID_HYPHEN_MIN_WORD_LENGTH             }, \
        { u"" UNO_NAME_PARA_HYPHENATION_ZONE,               RES_PARATR_HYPHENZONE,         cppu::UnoType<sal_Int16>::get(),         PropertyAttribute::MAYBEVOID, MID_HYPHEN_ZONE}, \
        { u"" UNO_NAME_CHAR_AUTO_KERNING,                   RES_CHRATR_AUTOKERN,           cppu::UnoType<bool>::get(),       PropertyAttribute::MAYBEVOID, 0                                      }, \
        { u"" UNO_NAME_CHAR_BACK_COLOR,                     RES_CHRATR_BACKGROUND,         cppu::UnoType<sal_Int32>::get(),         PropertyAttribute::MAYBEVOID, MID_BACK_COLOR                         }, \
        { u"" UNO_NAME_CHAR_HIGHLIGHT,                      RES_CHRATR_HIGHLIGHT,          cppu::UnoType<sal_Int32>::get(), PropertyAttribute::MAYBEVOID, MID_BACK_COLOR                         }, \
@@ -442,6 +443,7 @@
                    { u"" UNO_NAME_PARA_HYPHENATION_MAX_TRAILING_CHARS, RES_PARATR_HYPHENZONE,        cppu::UnoType<sal_Int16>::get(),   PropertyAttribute::MAYBEVOID, MID_HYPHEN_MIN_TRAIL  },\
                    { u"" UNO_NAME_PARA_HYPHENATION_MAX_HYPHENS, RES_PARATR_HYPHENZONE,       cppu::UnoType<sal_Int16>::get(),   PropertyAttribute::MAYBEVOID, MID_HYPHEN_MAX_HYPHENS},\
                    { u"" UNO_NAME_PARA_HYPHENATION_MIN_WORD_LENGTH, RES_PARATR_HYPHENZONE,       cppu::UnoType<sal_Int16>::get(),   PropertyAttribute::MAYBEVOID, MID_HYPHEN_MIN_WORD_LENGTH},\
                    { u"" UNO_NAME_PARA_HYPHENATION_ZONE, RES_PARATR_HYPHENZONE,                      cppu::UnoType<sal_Int16>::get(),   PropertyAttribute::MAYBEVOID, MID_HYPHEN_ZONE},\
                    { u"" UNO_NAME_NUMBERING_STYLE_NAME, RES_PARATR_NUMRULE,  cppu::UnoType<OUString>::get(),         PropertyAttribute::MAYBEVOID,   0},\
                    { UNO_NAME_NUMBERING_LEVEL, RES_PARATR_LIST_LEVEL,    cppu::UnoType<sal_Int16>::get(),        PropertyAttribute::MAYBEVOID,   0},\
                    { u"" UNO_NAME_PARA_USER_DEFINED_ATTRIBUTES, RES_UNKNOWNATR_CONTAINER, cppu::UnoType<css::container::XNameContainer>::get(), PropertyAttribute::MAYBEVOID, 0 },\
diff --git a/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx b/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx
index 530f72c..9137033 100644
--- a/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx
+++ b/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx
@@ -258,6 +258,7 @@ static OUString PropertyNametoRID(const OUString& rName)
        { "ParaHyphenationNoCaps", RID_PARA_HYPHENATION_NO_CAPS },
        { "ParaHyphenationNoLastWord", RID_PARA_HYPHENATION_NO_LAST_WORD },
        { "ParaHyphenationMinWordLength", RID_PARA_HYPHENATION_MIN_WORD_LENGTH },
        { "ParaHyphenationZone", RID_PARA_HYPHENATION_ZONE },
        { "ParaInteropGrabBag", RID_PARA_INTEROP_GRAB_BAG },
        { "ParaIsAutoFirstLineIndent", RID_PARA_IS_AUTO_FIRST_LINE_INDENT },
        { "ParaIsCharacterDistance", RID_PARA_IS_CHARACTER_DISTANCE },
diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx
index 356b980..efdd8a9 100644
--- a/xmloff/source/core/xmltoken.cxx
+++ b/xmloff/source/core/xmltoken.cxx
@@ -1066,6 +1066,7 @@ namespace xmloff::token {
        TOKEN( "hyphenation-no-caps",             XML_HYPHENATION_NO_CAPS ),
        TOKEN( "hyphenation-no-last-word",        XML_HYPHENATION_NO_LAST_WORD ),
        TOKEN( "hyphenation-word-char-count",     XML_HYPHENATION_WORD_CHAR_COUNT ),
        TOKEN( "hyphenation-zone",                XML_HYPHENATION_ZONE ),
        TOKEN( "i",                               XML_I ),
        TOKEN( "icon",                            XML_ICON ),
        TOKEN( "icon-set",                        XML_ICON_SET ),
diff --git a/xmloff/source/text/txtprmap.cxx b/xmloff/source/text/txtprmap.cxx
index a2e110e..66bda55 100644
--- a/xmloff/source/text/txtprmap.cxx
+++ b/xmloff/source/text/txtprmap.cxx
@@ -345,6 +345,7 @@ XMLPropertyMapEntry const aXMLParaPropMap[] =
    MAP_EXT( "ParaHyphenationNoCaps",  XML_NAMESPACE_LO_EXT, XML_HYPHENATION_NO_CAPS, XML_TYPE_BOOL|XML_TYPE_PROP_TEXT, 0 ),
    MAP_EXT( "ParaHyphenationNoLastWord",  XML_NAMESPACE_LO_EXT, XML_HYPHENATION_NO_LAST_WORD, XML_TYPE_BOOL|XML_TYPE_PROP_TEXT, 0 ),
    MAP_EXT( "ParaHyphenationMinWordLength",  XML_NAMESPACE_LO_EXT, XML_HYPHENATION_WORD_CHAR_COUNT, XML_TYPE_NUMBER16_NONE|XML_TYPE_PROP_TEXT, 0 ),
    MAP_EXT( "ParaHyphenationZone",  XML_NAMESPACE_LO_EXT, XML_HYPHENATION_ZONE, XML_TYPE_NUMBER16_NONE|XML_TYPE_PROP_TEXT, 0 ),
    // RES_PARATR_DROP
    MP_E( "DropCapWholeWord",   STYLE,  LENGTH,     MID_FLAG_SPECIAL_ITEM|XML_TYPE_BOOL, CTF_DROPCAPWHOLEWORD ),
    MP_E( "DropCapCharStyleName",   STYLE,  STYLE_NAME, MID_FLAG_SPECIAL_ITEM|XML_TYPE_STRING, CTF_DROPCAPCHARSTYLE ),
diff --git a/xmloff/source/token/tokens.txt b/xmloff/source/token/tokens.txt
index ee0adc3..aaf1442 100644
--- a/xmloff/source/token/tokens.txt
+++ b/xmloff/source/token/tokens.txt
@@ -966,6 +966,7 @@ hyphenation-remain-char-count
hyphenation-no-caps
hyphenation-no-last-word
hyphenation-word-char-count
hyphenation-zone
i
icon
icon-set