tdf#173389 cui offapi sw xmloff: add custom compound-based hyphenation

Add new paragraph justification option "Split compound words" for
custom compound-based "smart" hyphenation. Add compound-based "smart"
hyphenation support for Danish, Dutch, Esperanto, Estonian, German,
Norwegian, Swedish (and potentially, Icelandic, Finnish and
Latvian) languages by fixing Hunspell morphological analysis and the
associated lingucomponent code. (Previously compound-based "smart"
hyphenation was enabled only for Hungarian.)

With the new option it's possible to keep MSO/MS-DOCX interoperability,
also introducing a better hyphenation algorithm for several languages.

Details:

    * Add check box to Alignment in paragraph formatting dialog window;

    * Store properties in paragraph model:

      css::style::ParagraphProperties::ParaIsCompoundBased

    * Implement it by checking the new option in the previously
      added commit f9f694f5d9f39c5801bc5fec45867252c293bbcb;

    * Add ODF import/export (loext:compound-based);

    * Add ODF unit tests by the new tdf173389_smart_hyphenation_nl.odt
      and tdf173389_smart_hyphenation_hu.odt. Now use the previous
      tdf119908_smart_hyphenation_hu for disabled compound-based "smart"
      hyphenation, also the new tdf119908_smart_hyphenation_nl.odt.
      Note: the Dutch test document results better compound-based
      hyphenation in two positions.

    * Add Hunspell patch to fix Danish, Dutch, Esperanto, Estonian,
      German, Norwegian, Swedish (and future Icelandic, Latvian,
      Finnish) morphological analysis for compound word constituents;

    * hyphenimp.cxx hyphenate(): fix tokenization for consecutive
      pa: elements, like resulted in the fixed Hunspell dictionaries.

Follow-up to commit f9f694f5d9
"tdf#173389 sw: add compound-based “smart” hyphenation for readability".

Change-Id: I4414bd588646ecf6dc86b77642833ac9c7820a98
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/211341
Tested-by: Jenkins
Reviewed-by: László Németh <nemeth@numbertext.org>
This commit is contained in:
László Németh
2026-09-23 14:38:07 +02:00
parent 85d27f843c
commit e668dc84eb
30 changed files with 902 additions and 32 deletions
+3
View File
@@ -177,6 +177,9 @@ class SvxParaAlignTabPage : public SfxTabPage
std::unique_ptr<weld::MetricSpinButton> m_xLetterSpacingMinimum; std::unique_ptr<weld::MetricSpinButton> m_xLetterSpacingMinimum;
std::unique_ptr<weld::MetricSpinButton> m_xLetterSpacingMaximum; std::unique_ptr<weld::MetricSpinButton> m_xLetterSpacingMaximum;
/// compound-based hyphenation
std::unique_ptr<weld::CheckButton> m_xCompoundBased;
/// glyph scaling /// glyph scaling
std::unique_ptr<weld::Label> m_xLabelGlyphScaling; std::unique_ptr<weld::Label> m_xLabelGlyphScaling;
std::unique_ptr<weld::MetricSpinButton> m_xGlyphScalingMinimum; std::unique_ptr<weld::MetricSpinButton> m_xGlyphScalingMinimum;
+9 -1
View File
@@ -1299,6 +1299,7 @@ SvxParaAlignTabPage::SvxParaAlignTabPage(weld::Container* pPage, weld::DialogCon
, m_xLabelLetterSpacing(m_xBuilder->weld_label(u"labelLetterSpacing"_ustr)) , m_xLabelLetterSpacing(m_xBuilder->weld_label(u"labelLetterSpacing"_ustr))
, m_xLetterSpacingMinimum(m_xBuilder->weld_metric_spin_button(u"spin_LETTER_SPACING_MIN"_ustr, FieldUnit::PERCENT)) , m_xLetterSpacingMinimum(m_xBuilder->weld_metric_spin_button(u"spin_LETTER_SPACING_MIN"_ustr, FieldUnit::PERCENT))
, m_xLetterSpacingMaximum(m_xBuilder->weld_metric_spin_button(u"spin_LETTER_SPACING_MAX"_ustr, FieldUnit::PERCENT)) , m_xLetterSpacingMaximum(m_xBuilder->weld_metric_spin_button(u"spin_LETTER_SPACING_MAX"_ustr, FieldUnit::PERCENT))
, m_xCompoundBased(m_xBuilder->weld_check_button(u"checkCompoundBased"_ustr))
, m_xLabelGlyphScaling(m_xBuilder->weld_label(u"labelGlyphScaling"_ustr)) , m_xLabelGlyphScaling(m_xBuilder->weld_label(u"labelGlyphScaling"_ustr))
, m_xGlyphScalingMinimum(m_xBuilder->weld_metric_spin_button(u"spin_GLYPH_SCALING_MIN"_ustr, FieldUnit::PERCENT)) , m_xGlyphScalingMinimum(m_xBuilder->weld_metric_spin_button(u"spin_GLYPH_SCALING_MIN"_ustr, FieldUnit::PERCENT))
, m_xGlyphScalingMaximum(m_xBuilder->weld_metric_spin_button(u"spin_GLYPH_SCALING_MAX"_ustr, FieldUnit::PERCENT)) , m_xGlyphScalingMaximum(m_xBuilder->weld_metric_spin_button(u"spin_GLYPH_SCALING_MAX"_ustr, FieldUnit::PERCENT))
@@ -1409,6 +1410,7 @@ bool SvxParaAlignTabPage::FillItemSet( SfxItemSet* rOutSet )
m_xParagraphComposer->get_state_changed_from_saved() || m_xParagraphComposer->get_state_changed_from_saved() ||
m_xLetterSpacingMinimum->get_value_changed_from_saved() || m_xLetterSpacingMinimum->get_value_changed_from_saved() ||
m_xLetterSpacingMaximum->get_value_changed_from_saved() || m_xLetterSpacingMaximum->get_value_changed_from_saved() ||
m_xCompoundBased->get_state_changed_from_saved() ||
m_xGlyphScalingMinimum->get_value_changed_from_saved() || m_xGlyphScalingMinimum->get_value_changed_from_saved() ||
m_xGlyphScalingMaximum->get_value_changed_from_saved(); m_xGlyphScalingMaximum->get_value_changed_from_saved();
} }
@@ -1436,6 +1438,7 @@ bool SvxParaAlignTabPage::FillItemSet( SfxItemSet* rOutSet )
aAdj.SetParagraphComposer( m_xParagraphComposer->get_active() ); aAdj.SetParagraphComposer( m_xParagraphComposer->get_active() );
aAdj.SetPropLetterSpacingMinimum( m_xLetterSpacingMinimum->get_value(FieldUnit::PERCENT) ); aAdj.SetPropLetterSpacingMinimum( m_xLetterSpacingMinimum->get_value(FieldUnit::PERCENT) );
aAdj.SetPropLetterSpacingMaximum( m_xLetterSpacingMaximum->get_value(FieldUnit::PERCENT) ); aAdj.SetPropLetterSpacingMaximum( m_xLetterSpacingMaximum->get_value(FieldUnit::PERCENT) );
aAdj.SetCompoundBased( m_xCompoundBased->get_active() );
aAdj.SetPropScaleWidthMinimum( m_xGlyphScalingMinimum->get_value(FieldUnit::PERCENT) ); aAdj.SetPropScaleWidthMinimum( m_xGlyphScalingMinimum->get_value(FieldUnit::PERCENT) );
aAdj.SetPropScaleWidthMaximum( m_xGlyphScalingMaximum->get_value(FieldUnit::PERCENT) ); aAdj.SetPropScaleWidthMaximum( m_xGlyphScalingMaximum->get_value(FieldUnit::PERCENT) );
rOutSet->Put( aAdj ); rOutSet->Put( aAdj );
@@ -1543,6 +1546,8 @@ void SvxParaAlignTabPage::Reset( const SfxItemSet* rSet )
m_xLetterSpacingMinimum->set_sensitive(true); m_xLetterSpacingMinimum->set_sensitive(true);
m_xLetterSpacingMinimum->set_value(rAdj.GetPropLetterSpacingMinimum(), FieldUnit::PERCENT); m_xLetterSpacingMinimum->set_value(rAdj.GetPropLetterSpacingMinimum(), FieldUnit::PERCENT);
m_xLetterSpacingMaximum->set_value(rAdj.GetPropLetterSpacingMaximum(), FieldUnit::PERCENT); m_xLetterSpacingMaximum->set_value(rAdj.GetPropLetterSpacingMaximum(), FieldUnit::PERCENT);
m_xCompoundBased->set_sensitive(true);
m_xCompoundBased->set_active(rAdj.GetCompoundBased());
// TODO add GlyphScaling (CharScaleWidth) // TODO add GlyphScaling (CharScaleWidth)
m_xGlyphScalingMaximum->set_sensitive(true); m_xGlyphScalingMaximum->set_sensitive(true);
m_xGlyphScalingMinimum->set_sensitive(true); m_xGlyphScalingMinimum->set_sensitive(true);
@@ -1559,10 +1564,10 @@ void SvxParaAlignTabPage::Reset( const SfxItemSet* rSet )
m_xWordSpacingMinimum->set_sensitive(false); m_xWordSpacingMinimum->set_sensitive(false);
m_xWordSpacingMaximum->set_sensitive(false); m_xWordSpacingMaximum->set_sensitive(false);
m_xParagraphComposer->set_sensitive(false); m_xParagraphComposer->set_sensitive(false);
m_xParagraphComposer->set_sensitive(false);
m_xLabelLetterSpacing->set_sensitive(false); m_xLabelLetterSpacing->set_sensitive(false);
m_xLetterSpacingMinimum->set_sensitive(false); m_xLetterSpacingMinimum->set_sensitive(false);
m_xLetterSpacingMaximum->set_sensitive(false); m_xLetterSpacingMaximum->set_sensitive(false);
m_xCompoundBased->set_sensitive(false);
m_xLabelGlyphScaling->set_sensitive(false); m_xLabelGlyphScaling->set_sensitive(false);
m_xGlyphScalingMinimum->set_sensitive(false); m_xGlyphScalingMinimum->set_sensitive(false);
m_xGlyphScalingMaximum->set_sensitive(false); m_xGlyphScalingMaximum->set_sensitive(false);
@@ -1664,6 +1669,7 @@ void SvxParaAlignTabPage::Reset( const SfxItemSet* rSet )
m_xParagraphComposer->save_state(); m_xParagraphComposer->save_state();
m_xLetterSpacingMinimum->save_value(); m_xLetterSpacingMinimum->save_value();
m_xLetterSpacingMaximum->save_value(); m_xLetterSpacingMaximum->save_value();
m_xCompoundBased->save_state();
m_xGlyphScalingMinimum->save_value(); m_xGlyphScalingMinimum->save_value();
m_xGlyphScalingMaximum->save_value(); m_xGlyphScalingMaximum->save_value();
@@ -1690,6 +1696,7 @@ void SvxParaAlignTabPage::ChangesApplied()
m_xParagraphComposer->save_state(); m_xParagraphComposer->save_state();
m_xLetterSpacingMinimum->save_value(); m_xLetterSpacingMinimum->save_value();
m_xLetterSpacingMaximum->save_value(); m_xLetterSpacingMaximum->save_value();
m_xCompoundBased->save_state();
m_xGlyphScalingMinimum->save_value(); m_xGlyphScalingMinimum->save_value();
m_xGlyphScalingMaximum->save_value(); m_xGlyphScalingMaximum->save_value();
} }
@@ -1711,6 +1718,7 @@ IMPL_LINK_NOARG(SvxParaAlignTabPage, AlignHdl_Impl, weld::Toggleable&, void)
// TODO visualize CharKerning with percentage // TODO visualize CharKerning with percentage
m_xLetterSpacingMinimum->set_sensitive(bJustify); m_xLetterSpacingMinimum->set_sensitive(bJustify);
m_xLetterSpacingMaximum->set_sensitive(bJustify); m_xLetterSpacingMaximum->set_sensitive(bJustify);
m_xCompoundBased->set_sensitive(bJustify);
m_xLabelGlyphScaling->set_sensitive(bJustify); m_xLabelGlyphScaling->set_sensitive(bJustify);
// TODO visualize CharScaleWidth with percentage // TODO visualize CharScaleWidth with percentage
m_xGlyphScalingMinimum->set_sensitive(bJustify); m_xGlyphScalingMinimum->set_sensitive(bJustify);
+20
View File
@@ -740,6 +740,26 @@
<property name="top-attach">2</property> <property name="top-attach">2</property>
</packing> </packing>
</child> </child>
<child>
<object class="GtkCheckButton" id="checkCompoundBased">
<property name="label" translatable="yes" context="paralignpage|checkCompoundBased">Split compound words</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="use-underline">True</property>
<property name="inconsistent">True</property>
<property name="draw-indicator">True</property>
<child internal-child="accessible">
<object class="AtkObject" id="checkCompoundBased-atkobject">
<property name="AtkObject::accessible-description" translatable="yes" context="textflowpage|extended_tip|checkCompoundBased">Select this check box, if you want to prefer compound word splitting during justification.</property>
</object>
</child>
</object>
<packing>
<property name="left-attach">4</property>
<property name="top-attach">2</property>
</packing>
</child>
<child> <child>
<object class="GtkLabel" id="labelGlyphScaling"> <object class="GtkLabel" id="labelGlyphScaling">
<property name="visible">True</property> <property name="visible">True</property>
+15 -1
View File
@@ -322,7 +322,8 @@ SvxAdjustItem::SvxAdjustItem(const SvxAdjust eAdjst, const sal_uInt16 nId )
nPropLetterSpacingMaximum(0), nPropLetterSpacingMaximum(0),
nPropScaleWidthMinimum(100), nPropScaleWidthMinimum(100),
nPropScaleWidthMaximum(100), nPropScaleWidthMaximum(100),
bParagraphComposer(false) bParagraphComposer(false),
bCompoundBased(false)
{ {
SetAdjust( eAdjst ); SetAdjust( eAdjst );
} }
@@ -342,6 +343,7 @@ bool SvxAdjustItem::operator==( const SfxPoolItem& rAttr ) const
bParagraphComposer == rItem.bParagraphComposer && bParagraphComposer == rItem.bParagraphComposer &&
nPropLetterSpacingMinimum == rItem.nPropLetterSpacingMinimum && nPropLetterSpacingMinimum == rItem.nPropLetterSpacingMinimum &&
nPropLetterSpacingMaximum == rItem.nPropLetterSpacingMaximum && nPropLetterSpacingMaximum == rItem.nPropLetterSpacingMaximum &&
bCompoundBased == rItem.bCompoundBased &&
nPropScaleWidthMinimum == rItem.nPropScaleWidthMinimum && nPropScaleWidthMinimum == rItem.nPropScaleWidthMinimum &&
nPropScaleWidthMaximum == rItem.nPropScaleWidthMaximum; nPropScaleWidthMaximum == rItem.nPropScaleWidthMaximum;
} }
@@ -359,6 +361,7 @@ size_t SvxAdjustItem::hashCode() const
o3tl::hash_combine(seed, bParagraphComposer); o3tl::hash_combine(seed, bParagraphComposer);
o3tl::hash_combine(seed, nPropLetterSpacingMinimum); o3tl::hash_combine(seed, nPropLetterSpacingMinimum);
o3tl::hash_combine(seed, nPropLetterSpacingMaximum); o3tl::hash_combine(seed, nPropLetterSpacingMaximum);
o3tl::hash_combine(seed, bCompoundBased);
o3tl::hash_combine(seed, nPropScaleWidthMinimum); o3tl::hash_combine(seed, nPropScaleWidthMinimum);
o3tl::hash_combine(seed, nPropScaleWidthMaximum); o3tl::hash_combine(seed, nPropScaleWidthMaximum);
return seed; return seed;
@@ -388,6 +391,11 @@ bool SvxAdjustItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
rVal <<= bParagraphComposer; rVal <<= bParagraphComposer;
break; break;
} }
case MID_COMPOUND_BASED :
{
rVal <<= bCompoundBased;
break;
}
default: ;//prevent warning default: ;//prevent warning
} }
return true; return true;
@@ -471,6 +479,12 @@ bool SvxAdjustItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
bParagraphComposer = Any2Bool(rVal); bParagraphComposer = Any2Bool(rVal);
} }
break; break;
case MID_COMPOUND_BASED :
{
ASSERT_CHANGE_REFCOUNTED_ITEM;
bCompoundBased = Any2Bool(rVal);
}
break;
case MID_EXPAND_SINGLE : case MID_EXPAND_SINGLE :
ASSERT_CHANGE_REFCOUNTED_ITEM; ASSERT_CHANGE_REFCOUNTED_ITEM;
bOneBlock = Any2Bool(rVal); bOneBlock = Any2Bool(rVal);
+5
View File
@@ -19,4 +19,9 @@ $(eval $(call gb_UnpackedTarball_set_post_action,hunspell,\
)) ))
endif endif
$(eval $(call gb_UnpackedTarball_add_patches,hunspell, \
external/hunspell/fix_morphological_analysis_for_compound_words.patch \
))
# vim: set noet sw=4 ts=4: # vim: set noet sw=4 ts=4:
@@ -0,0 +1,25 @@
--- a/src/hunspell/affixmgr.cxx 2026-05-04 16:31:57.000000000 +0200
+++ b/src/hunspell/affixmgr.cxx 2026-09-16 00:10:58.854821764 +0200
@@ -2338,10 +2338,10 @@
p = affix_check_morph(st, 0, i, compoundmiddle);
}
}
+ presult.push_back(MSEP_FLD);
+ presult.append(MORPH_PART);
+ presult.append(st, 0, i);
if (!p.empty()) {
- presult.push_back(MSEP_FLD);
- presult.append(MORPH_PART);
- presult.append(st, 0, i);
line_uniq_app(p, MSEP_REC);
presult.append(p);
}
@@ -2540,7 +2540,7 @@
if (!rv && compoundend && !onlycpdrule) {
sfx = nullptr;
pfx = nullptr;
- rv = affix_check(word, i, word.size() - i, compoundend);
+ rv = affix_check(word, i, word.size() - i, compoundend, IN_CPD_END);
}
if (!rv && !defcpdtable.empty() && words) {
+16
View File
@@ -63,6 +63,9 @@ class EDITENG_DLLPUBLIC SvxAdjustItem final : public SfxPoolItem
// paragraph composer // paragraph composer
bool bParagraphComposer : 1; bool bParagraphComposer : 1;
// compound-based hyphenation
bool bCompoundBased : 1;
protected: protected:
virtual ItemInstanceManager* getItemInstanceManager() const override; virtual ItemInstanceManager* getItemInstanceManager() const override;
@@ -160,6 +163,19 @@ public:
bParagraphComposer = bValue; bParagraphComposer = bValue;
} }
bool GetCompoundBased() const
{
return bCompoundBased;
}
void SetCompoundBased( const bool bValue )
{
ASSERT_CHANGE_REFCOUNTED_ITEM;
bCompoundBased = bValue;
}
sal_uInt16 GetPropWordSpacing() const sal_uInt16 GetPropWordSpacing() const
{ {
return nPropWordSpacing; return nPropWordSpacing;
+1
View File
@@ -79,6 +79,7 @@
#define MID_SCALE_WIDTH_MIN 8 #define MID_SCALE_WIDTH_MIN 8
#define MID_SCALE_WIDTH_MAX 9 #define MID_SCALE_WIDTH_MAX 9
#define MID_PARAGRAPH_COMPOSER 10 #define MID_PARAGRAPH_COMPOSER 10
#define MID_COMPOUND_BASED 11
//SvxFontItem //SvxFontItem
// Don't use 0 as it used for the whole struct // Don't use 0 as it used for the whole struct
+1
View File
@@ -175,6 +175,7 @@ struct SfxItemPropertyMapEntry;
{u"ParaScaleWidthMinimum"_ustr, EE_PARA_JUST, ::cppu::UnoType<sal_Int16>::get(), 0, MID_SCALE_WIDTH_MIN }, \ {u"ParaScaleWidthMinimum"_ustr, EE_PARA_JUST, ::cppu::UnoType<sal_Int16>::get(), 0, MID_SCALE_WIDTH_MIN }, \
{u"ParaScaleWidthMaximum"_ustr, EE_PARA_JUST, ::cppu::UnoType<sal_Int16>::get(), 0, MID_SCALE_WIDTH_MAX }, \ {u"ParaScaleWidthMaximum"_ustr, EE_PARA_JUST, ::cppu::UnoType<sal_Int16>::get(), 0, MID_SCALE_WIDTH_MAX }, \
{u"ParaComposer"_ustr, EE_PARA_JUST, ::cppu::UnoType<bool>::get(), 0, MID_PARAGRAPH_COMPOSER }, \ {u"ParaComposer"_ustr, EE_PARA_JUST, ::cppu::UnoType<bool>::get(), 0, MID_PARAGRAPH_COMPOSER }, \
{u"ParaIsCompoundBased"_ustr, EE_PARA_JUST, ::cppu::UnoType<bool>::get(), 0, MID_COMPOUND_BASED }, \
{u"WritingMode"_ustr, EE_PARA_WRITINGDIR, ::cppu::UnoType<sal_Int16>::get(), 0, 0 }, \ {u"WritingMode"_ustr, EE_PARA_WRITINGDIR, ::cppu::UnoType<sal_Int16>::get(), 0, 0 }, \
{u"WritingModeAutomatic"_ustr, EE_PARA_AUTOWRITINGDIR, ::cppu::UnoType<bool>::get(), 0, 0 } {u"WritingModeAutomatic"_ustr, EE_PARA_AUTOWRITINGDIR, ::cppu::UnoType<bool>::get(), 0, 0 }
+1 -1
View File
@@ -140,7 +140,7 @@ SFX_DECL_TYPE(7);
SFX_DECL_TYPE(8); SFX_DECL_TYPE(8);
SFX_DECL_TYPE(10); // for SfxDocInfoItem SFX_DECL_TYPE(10); // for SfxDocInfoItem
SFX_DECL_TYPE(11); SFX_DECL_TYPE(11);
SFX_DECL_TYPE(12); // for SvxAdjustStruct
SFX_DECL_TYPE(13); // for SwAddPrinterItem, Sd... SFX_DECL_TYPE(13); // for SwAddPrinterItem, Sd...
SFX_DECL_TYPE(14); SFX_DECL_TYPE(14);
SFX_DECL_TYPE(16); // for SwDocDisplayItem SFX_DECL_TYPE(16); // for SwDocDisplayItem
+1
View File
@@ -490,6 +490,7 @@ namespace xmloff::token {
XML_COMMAND, XML_COMMAND,
XML_COMMENT, XML_COMMENT,
XML_COMPOSE, XML_COMPOSE,
XML_COMPOUND_BASED,
XML_COND_STYLE_NAME, XML_COND_STYLE_NAME,
XML_CONDITION, XML_CONDITION,
XML_CONDITION_SOURCE, XML_CONDITION_SOURCE,
@@ -517,6 +517,7 @@ Reference< XHyphenatedWord > SAL_CALL Hyphenator::hyphenate( const OUString& aWo
sal_Int32 nPa = -1; sal_Int32 nPa = -1;
while ( (nPa = morph.indexOf(u" pa:", nPa + 1)) > -1 ) while ( (nPa = morph.indexOf(u" pa:", nPa + 1)) > -1 )
{ {
sal_Int32 nPaTemp(nPa);
// use hy: field of the actual stem, if it exists // use hy: field of the actual stem, if it exists
// pa:stem1 hy:st|em1 pa:stem2 -> st|em1||stem2 // pa:stem1 hy:st|em1 pa:stem2 -> st|em1||stem2
sal_Int32 nHy = morph.indexOf(u" hy:", nPa + 3); sal_Int32 nHy = morph.indexOf(u" hy:", nPa + 3);
@@ -529,7 +530,7 @@ Reference< XHyphenatedWord > SAL_CALL Hyphenator::hyphenate( const OUString& aWo
sStems += sStems2+ u"||"; sStems += sStems2+ u"||";
else if ( sal_Int32 nBreak = o3tl::toInt32(sStems2) ) else if ( sal_Int32 nBreak = o3tl::toInt32(sStems2) )
{ {
OUString sPa(morph.getToken(1, ' ', nPa).copy(3)); OUString sPa(morph.getToken(1, ' ', nPaTemp).copy(3));
if ( nBreak < sPa.getLength() ) if ( nBreak < sPa.getLength() )
sStems += OUString::Concat(sPa.subView(0, nBreak)) + u"|" + sStems += OUString::Concat(sPa.subView(0, nBreak)) + u"|" +
sPa.subView(nBreak); sPa.subView(nBreak);
@@ -537,7 +538,7 @@ Reference< XHyphenatedWord > SAL_CALL Hyphenator::hyphenate( const OUString& aWo
} }
else else
{ {
OUString sPa(morph.getToken(1, ' ', nPa).copy(3)); OUString sPa(morph.getToken(1, ' ', nPaTemp).copy(3));
// handle special case: missing pa: in morphological analysis // handle special case: missing pa: in morphological analysis
// before in-word suffixes (German, Sweden etc. dictionaries) // before in-word suffixes (German, Sweden etc. dictionaries)
@@ -563,9 +564,6 @@ Reference< XHyphenatedWord > SAL_CALL Hyphenator::hyphenate( const OUString& aWo
nSuffixLen = sPa.getLength() - nStemLen; nSuffixLen = sPa.getLength() - nStemLen;
} }
} }
if ( nPa == -1 ) // getToken() can modify nPa
break;
} }
// handle verb and leg-, legesleg- prefixes (Hungarian-only) // handle verb and leg-, legesleg- prefixes (Hungarian-only)
@@ -644,6 +644,12 @@ published service ParagraphProperties
@since LibreOffice 27.2 @since LibreOffice 27.2
*/ */
[optional, property] long ParaHyphenationLevel; [optional, property] long ParaHyphenationLevel;
/** specifies if automatic compound-based "smart" hyphenation is applied.
@since LibreOffice 27.2
*/
[optional, property] boolean ParaIsCompoundBased;
}; };
@@ -3381,6 +3381,15 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.
</rng:optional> </rng:optional>
</rng:define> </rng:define>
<!-- TODO no proposal -->
<rng:define name="style-paragraph-properties-attlist" combine="interleave">
<rng:optional>
<rng:attribute name="loext:compound-based">
<rng:ref name="boolean"/>
</rng:attribute>
</rng:optional>
</rng:define>
<!-- TODO no proposal --> <!-- TODO no proposal -->
<rng:define name="style-paragraph-properties-attlist" combine="interleave"> <rng:define name="style-paragraph-properties-attlist" combine="interleave">
<rng:optional> <rng:optional>
+1
View File
@@ -65,6 +65,7 @@ struct SvxAdjustStruct
INT16 ScaleWidthMinimum MID_SCALE_WIDTH_MIN; INT16 ScaleWidthMinimum MID_SCALE_WIDTH_MIN;
INT16 ScaleWidthMaximum MID_SCALE_WIDTH_MAX; INT16 ScaleWidthMaximum MID_SCALE_WIDTH_MAX;
BOOL ParagraphComposer MID_PARAGRAPH_COMPOSER; BOOL ParagraphComposer MID_PARAGRAPH_COMPOSER;
BOOL CompoundBased MID_COMPOUND_BASED;
}; };
item SvxAdjustStruct SvxAdjustItem; item SvxAdjustStruct SvxAdjustItem;
+1
View File
@@ -199,6 +199,7 @@
#define RID_PARA_BOTTOM_MARGIN_RELATIVE NC_("RID_ATTRIBUTE_NAMES_MAP", "Para Bottom Margin Relative") #define RID_PARA_BOTTOM_MARGIN_RELATIVE NC_("RID_ATTRIBUTE_NAMES_MAP", "Para Bottom Margin Relative")
#define RID_PARA_CHAPTER_NUMBERING_LEVEL NC_("RID_ATTRIBUTE_NAMES_MAP", "Para Chapter Numbering Level") #define RID_PARA_CHAPTER_NUMBERING_LEVEL NC_("RID_ATTRIBUTE_NAMES_MAP", "Para Chapter Numbering Level")
#define RID_PARA_COMPOSER NC_("RID_ATTRIBUTE_NAMES_MAP", "Para Composer") #define RID_PARA_COMPOSER NC_("RID_ATTRIBUTE_NAMES_MAP", "Para Composer")
#define RID_PARA_COMPOUND_BASED_HYPHENATION NC_("RID_ATTRIBUTE_NAMES_MAP", "Para Compound-based Hyphenation")
#define RID_PARA_CONDITIONAL_STYLE_NAME NC_("RID_ATTRIBUTE_NAMES_MAP", "Para Conditional Style Name") #define RID_PARA_CONDITIONAL_STYLE_NAME NC_("RID_ATTRIBUTE_NAMES_MAP", "Para Conditional Style Name")
#define RID_PARA_CONTEXT_MARGIN NC_("RID_ATTRIBUTE_NAMES_MAP", "Para Context Margin") #define RID_PARA_CONTEXT_MARGIN NC_("RID_ATTRIBUTE_NAMES_MAP", "Para Context Margin")
#define RID_PARA_EXPAND_SINGLE_WORD NC_("RID_ATTRIBUTE_NAMES_MAP", "Para Expand Single Word") #define RID_PARA_EXPAND_SINGLE_WORD NC_("RID_ATTRIBUTE_NAMES_MAP", "Para Expand Single Word")
+1
View File
@@ -519,6 +519,7 @@ inline constexpr OUString UNO_NAME_TEXT_USER_DEFINED_ATTRIBUTES = u"TextUserDefi
inline constexpr OUString UNO_NAME_FILE_PATH = u"FilePath"_ustr; inline constexpr OUString UNO_NAME_FILE_PATH = u"FilePath"_ustr;
inline constexpr OUString UNO_NAME_PARA_CHAPTER_NUMBERING_LEVEL = u"ParaChapterNumberingLevel"_ustr; inline constexpr OUString UNO_NAME_PARA_CHAPTER_NUMBERING_LEVEL = u"ParaChapterNumberingLevel"_ustr;
inline constexpr OUString UNO_NAME_PARA_COMPOSER = u"ParaComposer"_ustr; inline constexpr OUString UNO_NAME_PARA_COMPOSER = u"ParaComposer"_ustr;
inline constexpr OUString UNO_NAME_PARA_IS_COMPOUND_BASED = u"ParaIsCompoundBased"_ustr;
inline constexpr OUString UNO_NAME_PARA_CONDITIONAL_STYLE_NAME = u"ParaConditionalStyleName"_ustr; inline constexpr OUString UNO_NAME_PARA_CONDITIONAL_STYLE_NAME = u"ParaConditionalStyleName"_ustr;
inline constexpr OUString UNO_NAME_CHAPTER_NUMBERING_LEVEL = u"ChapterNumberingLevel"_ustr; inline constexpr OUString UNO_NAME_CHAPTER_NUMBERING_LEVEL = u"ChapterNumberingLevel"_ustr;
inline constexpr OUString UNO_NAME_NUMBERING_SEPARATOR = u"NumberingSeparator"_ustr; inline constexpr OUString UNO_NAME_NUMBERING_SEPARATOR = u"NumberingSeparator"_ustr;
+725 -1
View File
@@ -851,7 +851,7 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf172674_less_hyphenation)
assertXPath(pXmlDoc, "/root/page[1]/body/txt/SwParaPortion/SwLineLayout/SwHyphPortion", 3); assertXPath(pXmlDoc, "/root/page[1]/body/txt/SwParaPortion/SwLineLayout/SwHyphPortion", 3);
} }
// check smart hyphenation and compound-based smart hyphenation // check smart hyphenation and disabled compound-based smart hyphenation
CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf119908_smart_hyphenation_hu) CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf119908_smart_hyphenation_hu)
{ {
uno::Reference<linguistic2::XHyphenator> xHyphenator = LinguMgr::GetHyphenator(); uno::Reference<linguistic2::XHyphenator> xHyphenator = LinguMgr::GetHyphenator();
@@ -1030,6 +1030,520 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf119908_smart_hyphenation_hu)
pViewShell->Reformat(); pViewShell->Reformat();
pXmlDoc = parseLayoutDump(); pXmlDoc = parseLayoutDump();
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[2]/SwParaPortion/SwLineLayout[1]", "portion",
u"Senkit sem lehet rabszolgaságban vagy szolgaságban tartani; a rabszolgaság és a rab");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[4]/SwParaPortion/SwLineLayout[1]", "portion",
u"Senkit sem lehet kínvallatásnak, avagy kegyetlen, embertelen vagy lealacsonyító bá");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[4]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[8]/SwParaPortion/SwLineLayout[1]", "portion",
u"A törvény előtt mindenki egyenlő, és minden megkülönböztetés nélkül joga van a tör");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[8]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[8]/SwParaPortion/SwLineLayout[3]", "portion",
u"sértő minden megkülönböztetéssel és minden ilyen megkülönböztetésre irányuló fel");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[8]/SwParaPortion/SwLineLayout[3]/SwHyphPortion",
1);
// no compound-based "smart" hyphenation of the compound "jog|orvoslat"
// This is hyphenated as "jogor-voslat", not "jog-orvoslat"
if (bHunspell && aTests[0])
{
assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout[2]", "portion",
u"alapvető jogokat sértő eljárások ellen az illetékes hazai bíróságokhoz "
u"tényleges jogor");
}
assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout[2]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[14]/SwParaPortion/SwLineLayout[2]", "portion",
u"bíróság méltányosan és nyilvánosan tárgyalja, s ez határozzon egyrészt jogai és köte");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[14]/SwParaPortion/SwLineLayout[2]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[16]/SwParaPortion/SwLineLayout[1]", "portion",
u"Minden büntetendő cselekménnyel vádolt személyt ártatlannak kell vélelmezni mind");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[16]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[16]/SwParaPortion/SwLineLayout[2]", "portion",
u"addig, amíg bűnösségét nyilvánosan lefolytatott perben, a védelméhez szükséges vala");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[16]/SwParaPortion/SwLineLayout[2]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[17]/SwParaPortion/SwLineLayout[1]", "portion",
u"Senkit sem szabad elítélni oly cselekményért vagy mulasztásért, amely elkövetése pil");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[17]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[17]/SwParaPortion/SwLineLayout[3]", "portion",
u"Ugyancsak nem szabad súlyosabb büntetést kiszabni, mint amely a büntetendő cselek");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[17]/SwParaPortion/SwLineLayout[3]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[19]/SwParaPortion/SwLineLayout[1]", "portion",
u"Senkinek magánéletébe, családi ügyeibe, otthonába vagy levelezésébe nem szabad ön");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[19]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
// "smart" hyphenation: disabled hyphenation of "minden" by shrinking
// This was "Min-den"
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[19]/SwParaPortion/SwLineLayout[2]", "portion",
u"kényesen beavatkozni, sem pedig becsületében vagy jó hírnevében megsérteni. Minden ");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[21]/SwParaPortion/SwLineLayout[1]", "portion",
u"Az államon belül minden személynek joga van szabadon mozogni és lakóhelyét sza");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[21]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
// no compound-based "smart" hyphenation of the compound "vala|mint"
// This is hyphenated as "va-lamint" without enabled compound-based "smart" hyphenation
if (bHunspell && aTests[1])
{
assertXPath(pXmlDoc, "/root/page[1]/body/txt[22]/SwParaPortion/SwLineLayout[1]", "portion",
u"Minden személynek joga van minden országot, ideértve saját hazáját is, "
u"elhagyni, va");
}
assertXPath(pXmlDoc, "/root/page[1]/body/txt[22]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
assertXPath(pXmlDoc, "/root/page[1]/body/txt/SwParaPortion/SwLineLayout/SwHyphPortion", 13);
// delete page 2 to update hyphenation on the next page
pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 2297, /*bBasicCall=*/false);
pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 2297, /*bBasicCall=*/false);
pWrtShell->Delete();
// 10 hyphenations on page 3
pViewShell->Reformat();
pXmlDoc = parseLayoutDump();
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[1]/SwParaPortion/SwLineLayout[1]", "portion",
u"Erre a jogra nem lehet hivatkozni közönséges bűncselekmény miatti, kellőképpen meg");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[1]/SwParaPortion/SwLineLayout[2]", "portion",
u"alapozott üldözés, sem pedig az Egyesült Nemzetek céljaival és elveivel ellentétes te");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/SwParaPortion/SwLineLayout[2]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[4]/SwParaPortion/SwLineLayout[1]", "portion",
u"Senkit sem lehet sem állampolgárságától, sem állampolgársága megváltoztatásának jo");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[4]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[6]/SwParaPortion/SwLineLayout[1]", "portion",
u"Mind a férfinak, mind a nőnek a nagykorúság elérésétől kezdve joga van fajon, nem");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[6]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[6]/SwParaPortion/SwLineLayout[2]", "portion",
u"zetiségen vagy valláson alapuló korlátozás nélkül házasságot kötni és családot alapí");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[6]/SwParaPortion/SwLineLayout[2]/SwHyphPortion",
1);
assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout[1]", "portion",
u"Minden személynek joga van a tulajdonhoz, mind egyénileg, mind másokkal együtte");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
// "smart" hyphenation: disabled hyphenation of "valamint" by shifting
// This was "va-lamint"
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[13]/SwParaPortion/SwLineLayout[2]", "portion",
u"a jog magában foglalja a vallás és a meggyőződés megváltoztatásának szabadságát, ");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[15]/SwParaPortion/SwLineLayout[1]", "portion",
u"Minden személynek joga van a vélemény és a kifejezés szabadságához, amely magá");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[15]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[15]/SwParaPortion/SwLineLayout[2]", "portion",
u"ban foglalja azt a jogot, hogy véleménye miatt ne szenvedjen zaklatást, és hogy hatá");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[15]/SwParaPortion/SwLineLayout[2]/SwHyphPortion",
1);
// "smart" hyphenation: disabled hyphenation of "információkat" by shrinking
// This was "információ-kat"
assertXPath(pXmlDoc, "/root/page[1]/body/txt[15]/SwParaPortion/SwLineLayout[3]", "portion",
u"rokra való tekintet nélkül kutathasson, tájékozódhasson és terjeszthessen "
u"információkat ");
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[22]/SwParaPortion/SwLineLayout[2]", "portion",
u"rendszeres, az általános és egyenlő szavazati jogot és a titkos szavazást biztosító vá");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[22]/SwParaPortion/SwLineLayout[2]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[24]/SwParaPortion/SwLineLayout[1]", "portion",
u"Minden személynek mint a társadalom tagjának joga van a szociális biztonsághoz, to");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[24]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
assertXPath(pXmlDoc, "/root/page[1]/body/txt/SwParaPortion/SwLineLayout/SwHyphPortion", 10);
// delete page 3 to update hyphenation on the next page
pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 2566, /*bBasicCall=*/false);
pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 2566, /*bBasicCall=*/false);
pWrtShell->Delete();
// 12 hyphenations on page 4
pViewShell->Reformat();
pXmlDoc = parseLayoutDump();
assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/SwParaPortion/SwLineLayout[1]", "portion",
u"Minden személynek joga van a munkához, a munka szabad megválasztásához, a mél");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
assertXPath(pXmlDoc, "/root/page[1]/body/txt[4]/SwParaPortion/SwLineLayout[1]", "portion",
u"Mindenkinek joga van egyenlő munkáért egyenlő bért kapni, bárminemű megkülön");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[4]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[8]/SwParaPortion/SwLineLayout[1]", "portion",
u"Minden személynek joga van a pihenéshez, a szabadidőhöz, beleértve a munkaidő ész");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[8]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout[1]", "portion",
u"Minden személynek joga van saját maga és családja egészségének és jólétének bizto");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout[3]", "portion",
u"ellátáshoz, valamint a szükséges szociális szolgáltatásokhoz, továbbá joga van a szoci");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout[3]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[11]/SwParaPortion/SwLineLayout[2]", "portion",
u"gyermek, akár házasságból, akár házasságon kívül született, azonos szociális védelem");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[11]/SwParaPortion/SwLineLayout[2]/SwHyphPortion",
1);
// no compound-based "smart" hyphenation of the compound "alap|fokon"
// This is hyphenated as "alapfo-kon", not "alap-fokon"
if (bHunspell && aTests[2])
{
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[13]/SwParaPortion/SwLineLayout[1]", "portion",
u"Minden személynek joga van az oktatáshoz. Az oktatásnak legalábbis elemi és alapfo");
}
assertXPath(pXmlDoc, "/root/page[1]/body/txt[13]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[14]/SwParaPortion/SwLineLayout[1]", "portion",
u"A nevelésnek az emberi személyiség teljes kibontakoztatására, valamint az emberi jo");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[14]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[14]/SwParaPortion/SwLineLayout[4]", "portion",
u"közötti megértést, türelmet és barátságot, valamint támogatnia kell az Egyesült Nem");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[14]/SwParaPortion/SwLineLayout[4]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[15]/SwParaPortion/SwLineLayout[1]", "portion",
u"A szülőket elsőbbségi jog illeti meg a gyermekeiknek adandó oktatás megválasztásá");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[15]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
// no compound-based "smart" hyphenation of the compound "jó|téteményekben"
// This is not hyphenated, when compound-based smart hyphenation is disabled
if (bHunspell && aTests[3])
{
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[17]/SwParaPortion/SwLineLayout[2]", "portion",
u"a művészetek élvezéséhez, valamint a tudomány haladásában és az abból származó ");
assertXPath(pXmlDoc,
"/root/page[1]/body/txt[4]/SwParaPortion/SwLineLayout[2]/SwHyphPortion", 0);
}
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[18]/SwParaPortion/SwLineLayout[1]", "portion",
u"Mindenkinek joga van minden általa alkotott tudományos, irodalmi és művészeti ter");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[18]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
assertXPath(pXmlDoc, "/root/page[1]/body/txt/SwParaPortion/SwLineLayout/SwHyphPortion", 12);
// delete page 4 to update hyphenation on the next page
pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 2766, /*bBasicCall=*/false);
pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 2766, /*bBasicCall=*/false);
pWrtShell->Delete();
// 5 hyphenations on page 5
pViewShell->Reformat();
pXmlDoc = parseLayoutDump();
assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/SwParaPortion/SwLineLayout[1]", "portion",
u"Minden személynek joga van ahhoz, hogy mind a társadalmi, mind a nemzetközi vi");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[1]/SwParaPortion/SwLineLayout[2]", "portion",
u"szonyok tekintetében olyan rendszer uralkodjék, amelyben a jelen Nyilatkozatban ki");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/SwParaPortion/SwLineLayout[2]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[4]/SwParaPortion/SwLineLayout[1]", "portion",
u"Jogainak gyakorlásában és szabadságainak élvezetében mindenki csak olyan korláto");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[4]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
// no compound-based "smart" hyphenation of the compound "el|ismerésének"
// This is not hyphenated by the plain, i.e. not compound-based "smart" hyphenation.
if (bHunspell && aTests[4])
{
assertXPath(pXmlDoc, "/root/page[1]/body/txt[4]/SwParaPortion/SwLineLayout[2]", "portion",
u"zásoknak lehet alávetve, amelyeket a törvény kizárólag mások jogai és "
u"szabadságai ");
assertXPath(pXmlDoc,
"/root/page[1]/body/txt[4]/SwParaPortion/SwLineLayout[2]/SwHyphPortion", 0);
}
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[5]/SwParaPortion/SwLineLayout[1]", "portion",
u"Ezeket a jogokat és szabadságokat semmi esetre sem lehet az Egyesült Nemzetek cél");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[5]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
// "smart" hyphenation: disabled hyphenation of "állam" by shifting
// This was "ál-lam"
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[7]/SwParaPortion/SwLineLayout[1]", "portion",
u"A jelen Nyilatkozat egyetlen rendelkezése sem értelmezhető úgy, hogy az valamely ");
if (bHunspell && aTests[4])
assertXPath(pXmlDoc, "/root/page[1]/body/txt/SwParaPortion/SwLineLayout/SwHyphPortion", 5);
}
// check smart hyphenation and compound-based smart hyphenation
CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf173389_smart_hyphenation_hu)
{
uno::Reference<linguistic2::XHyphenator> xHyphenator = LinguMgr::GetHyphenator();
if (!xHyphenator->hasLocale(lang::Locale(u"hu"_ustr, u"HU"_ustr, OUString())))
return;
// compound-based hyphenation needs Hunspell morphological analysis
// (and an up-to-date Hungarian dictionary for full testing, which
// contains compound splitting information. E.g. dictionary version 1.7
// didn't contain data for the words "valamint" and "elismerésének")
uno::Reference<linguistic2::XSpellChecker1> xSpell = LinguMgr::GetSpellChecker();
LanguageType eLang
= LanguageTag::convertToLanguageType(lang::Locale(u"hu"_ustr, u"HU"_ustr, OUString()));
if (!xSpell.is() || !xSpell->hasLanguage(static_cast<sal_uInt16>(eLang)))
return;
std::vector<std::pair<OUString, OUString>> aCompound = {
{ u"jogorvoslatért"_ustr, "hy:3" }, { u"valamint"_ustr, "hy:4" },
{ u"alapfokon"_ustr, "pa:fokon" }, { u"jótéteményekben"_ustr, "hy:2" },
{ u"elismerésének"_ustr, "hy:2" },
};
// tests supported by the actual spelling dictionary
bool aTests[5];
// check Hunspell-based morphological analysis & hyphenation
bool bHunspell = xSpell->isValid("<?xml?>", static_cast<sal_uInt16>(eLang),
uno::Sequence<beans::PropertyValue>());
if (bHunspell)
{
// check dictionary support of compound splitting
for (size_t i = 0; i < aCompound.size(); ++i)
{
aTests[i] = false;
// get morphological analysis of the test word
uno::Reference<css::linguistic2::XSpellAlternatives> xTmpRes = xSpell->spell(
"<?xml?><query type='analyze'><word>" + aCompound[i].first + "</word></query>",
static_cast<sal_uInt16>(eLang), uno::Sequence<beans::PropertyValue>());
if (xTmpRes.is())
{
uno::Sequence<OUString> seq = xTmpRes->getAlternatives();
if (seq.hasElements())
{
sal_Int32 nEndOfFirstAnalysis = seq[0].indexOf("</a>");
// use only the first analysis, like the lingucomponent implementation
OUString morph(seq[0].copy(0, nEndOfFirstAnalysis));
// check compound data
aTests[i] = morph.indexOf(aCompound[i].second) > -1;
}
}
}
}
createSwDoc("tdf173389_smart_hyphenation_hu.odt");
// Ensure that all text portions are calculated before testing.
SwViewShell* pViewShell = getSwDoc()->getIDocumentLayoutAccess().GetCurrentViewShell();
CPPUNIT_ASSERT(pViewShell);
pViewShell->Reformat();
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
// 53 hyphenations on 5 pages using compound-based smart hyphenation
// This was 67 without smart hyphenation and 53 without compound-based smart hyphenation
// (using only the plain or interoperable smart hyphenation).
// 13 hyphenations on page 1
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[3]/SwParaPortion/SwLineLayout[1]", "portion",
u"Tekintettel arra, hogy az emberiség családja minden egyes tagja méltóságának, vala");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
// "smart" hyphenation: disabled hyphenation of "emberiség" by shrinking
// This was "emberi-ség"
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[4]/SwParaPortion/SwLineLayout[1]", "portion",
u"Tekintettel arra, hogy az emberi jogok el nem ismerése és semmibevevése az emberiség ");
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[5]/SwParaPortion/SwLineLayout[1]", "portion",
u"Tekintettel annak fontosságára, hogy az emberi jogokat a jog uralma védelmezze, ne");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[5]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[5]/SwParaPortion/SwLineLayout[2]", "portion",
u"hogy az ember végső szükségében a zsarnokság és az elnyomás elleni lázadásra kény");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[5]/SwParaPortion/SwLineLayout[2]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[6]/SwParaPortion/SwLineLayout[1]", "portion",
u"Tekintettel arra, hogy igen lényeges a nemzetek közötti baráti kapcsolatok kifejlődésé");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[6]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
// "smart" hyphenation: disabled hyphenation of "tettek" by shrinking
// This was "tet-tek"
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[7]/SwParaPortion/SwLineLayout[1]", "portion",
u"Tekintettel arra, hogy az Alapokmányban az Egyesült Nemzetek népei újból hitet tettek ");
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[7]/SwParaPortion/SwLineLayout[3]", "portion",
u"egyenjogúsága mellett, valamint kinyilvánították azt az elhatározásukat, hogy elősegí");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[7]/SwParaPortion/SwLineLayout[3]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[8]/SwParaPortion/SwLineLayout[1]", "portion",
u"Tekintettel arra, hogy a tagállamok kötelezték magukat arra, hogy az Egyesült Nemze");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[8]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
assertXPath(pXmlDoc, "/root/page[1]/body/txt[9]/SwParaPortion/SwLineLayout[1]", "portion",
u"A KÖZGYŰLÉS kinyilvánítja az EMBERI JOGOK EGYETEMES NYILATKOZA");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[9]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
// "smart" hyphenation: disabled hyphenation of "törekednie" by shifting
// This was "tö-rekednie"
assertXPath(pXmlDoc, "/root/page[1]/body/txt[9]/SwParaPortion/SwLineLayout[2]", "portion",
u"TÁT, mint azt a közös eszményt, amelynek elérésére minden népnek és nemzetnek ");
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[11]/SwParaPortion/SwLineLayout[1]", "portion",
u"Minden emberi lény szabadnak születik, és egyenlő méltósága és joga van. Az embe");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[11]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[13]/SwParaPortion/SwLineLayout[2]", "portion",
u"nyelvre, vallásra, politikai vagy más véleményre, nemzeti vagy társadalmi szárma");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[13]/SwParaPortion/SwLineLayout[2]/SwHyphPortion",
1);
assertXPath(pXmlDoc, "/root/page[1]/body/txt[13]/SwParaPortion/SwLineLayout[3]", "portion",
u"zásra, vagyonra, születésre vagy más körülményre vonatkozó mindennemű megkülön");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[13]/SwParaPortion/SwLineLayout[3]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[13]/SwParaPortion/SwLineLayout[4]", "portion",
u"böztetés nélkül mindenkit megilletnek. Ezenfelül nem lehet semmiféle megkülönböz");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[13]/SwParaPortion/SwLineLayout[4]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[13]/SwParaPortion/SwLineLayout[5]", "portion",
u"tetést tenni annak az országnak vagy területnek a politikai, jogi vagy nemzetközi hely");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[13]/SwParaPortion/SwLineLayout[5]/SwHyphPortion",
1);
assertXPath(
pXmlDoc, "/root/page[1]/body/txt[13]/SwParaPortion/SwLineLayout[7]", "portion",
u"terület független, gyámság alatt áll, nem autonóm vagy szuverenitása bármely vonat");
assertXPath(pXmlDoc, "/root/page[1]/body/txt[13]/SwParaPortion/SwLineLayout[7]/SwHyphPortion",
1);
assertXPath(pXmlDoc, "/root/page[1]/body/txt/SwParaPortion/SwLineLayout/SwHyphPortion", 13);
// delete page 1 to update hyphenation on the next page
SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 2868, /*bBasicCall=*/false);
pWrtShell->Delete();
// 13 hyphenations on page 2
pViewShell->Reformat();
pXmlDoc = parseLayoutDump();
assertXPath( assertXPath(
pXmlDoc, "/root/page[1]/body/txt[2]/SwParaPortion/SwLineLayout[1]", "portion", pXmlDoc, "/root/page[1]/body/txt[2]/SwParaPortion/SwLineLayout[1]", "portion",
u"Senkit sem lehet rabszolgaságban vagy szolgaságban tartani; a rabszolgaság és a rab"); u"Senkit sem lehet rabszolgaságban vagy szolgaságban tartani; a rabszolgaság és a rab");
@@ -1365,6 +1879,216 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf119908_smart_hyphenation_hu)
assertXPath(pXmlDoc, "/root/page[1]/body/txt/SwParaPortion/SwLineLayout/SwHyphPortion", 5); assertXPath(pXmlDoc, "/root/page[1]/body/txt/SwParaPortion/SwLineLayout/SwHyphPortion", 5);
} }
// check smart hyphenation and disabled compound-based smart hyphenation
CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf119908_smart_hyphenation_nl)
{
uno::Reference<linguistic2::XHyphenator> xHyphenator = LinguMgr::GetHyphenator();
if (!xHyphenator->hasLocale(lang::Locale(u"nl"_ustr, u"NL"_ustr, OUString())))
return;
// compound-based hyphenation needs fixed Hunspell morphological analysis
uno::Reference<linguistic2::XSpellChecker1> xSpell = LinguMgr::GetSpellChecker();
LanguageType eLang
= LanguageTag::convertToLanguageType(lang::Locale(u"nl"_ustr, u"NL"_ustr, OUString()));
if (!xSpell.is() || !xSpell->hasLanguage(static_cast<sal_uInt16>(eLang)))
return;
std::vector<std::pair<OUString, OUString>> aCompound = {
{ u"arbeidsvoorwaarden"_ustr, "pa:arbeids" },
{ u"doeleinden"_ustr, "pa:doel" },
};
// tests supported by the actual spelling dictionary
bool aTests[2];
// check Hunspell-based morphological analysis & hyphenation
bool bHunspell = xSpell->isValid("<?xml?>", static_cast<sal_uInt16>(eLang),
uno::Sequence<beans::PropertyValue>());
if (bHunspell)
{
// check dictionary support of compound splitting
for (size_t i = 0; i < aCompound.size(); ++i)
{
aTests[i] = false;
// get morphological analysis of the test word
uno::Reference<css::linguistic2::XSpellAlternatives> xTmpRes = xSpell->spell(
"<?xml?><query type='analyze'><word>" + aCompound[i].first + "</word></query>",
static_cast<sal_uInt16>(eLang), uno::Sequence<beans::PropertyValue>());
if (xTmpRes.is())
{
uno::Sequence<OUString> seq = xTmpRes->getAlternatives();
if (seq.hasElements())
{
sal_Int32 nEndOfFirstAnalysis = seq[0].indexOf("</a>");
// use only the first analysis, like the lingucomponent implementation
OUString morph(seq[0].copy(0, nEndOfFirstAnalysis));
// check compound data
aTests[i] = morph.indexOf(aCompound[i].second) > -1;
}
}
}
}
createSwDoc("tdf119908_smart_hyphenation_ml.odt");
// Ensure that all text portions are calculated before testing.
SwViewShell* pViewShell = getSwDoc()->getIDocumentLayoutAccess().GetCurrentViewShell();
CPPUNIT_ASSERT(pViewShell);
pViewShell->Reformat();
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
// delete page 1-2 to update hyphenation on the next page
SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 6151, /*bBasicCall=*/false);
pWrtShell->Delete();
pViewShell->Reformat();
pXmlDoc = parseLayoutDump();
// no compound-based "smart" hyphenation of the compound "arbeids|voorwaarden"
// This is hyphenated as "ar-beidsvoorwaarden" previously, not "arbeids-voorwaarden"
if (bHunspell && aTests[0])
{
assertXPath(pXmlDoc, "/root/page[1]/body/txt[25]/SwParaPortion/SwLineLayout[1]", "portion",
u"Een ieder heeft recht op arbeid, op vrije keuze van beroep, op rechtmatige "
u"en gunstige ar");
}
assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout[2]/SwHyphPortion",
1);
// delete page 2 to update hyphenation on the next page
pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 6179, /*bBasicCall=*/false);
pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 6179, /*bBasicCall=*/false);
pWrtShell->Delete();
// 10 hyphenations on page 3
pViewShell->Reformat();
pXmlDoc = parseLayoutDump();
// compound-based "smart" hyphenation of the compound "doel|einden"
// This is hyphenated as "doelein-den" previously, not "doel-einden"
if (bHunspell && aTests[1])
{
assertXPath(pXmlDoc, "/root/page[1]/body/txt[13]/SwParaPortion/SwLineLayout[1]", "portion",
u"Deze rechten en vrijheden mogen in geen geval worden uitgeoefend in strijd "
u"met de doelein");
}
assertXPath(pXmlDoc, "/root/page[1]/body/txt[13]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
}
// check smart hyphenation and compound-based smart hyphenation
CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf173389_smart_hyphenation_nl)
{
uno::Reference<linguistic2::XHyphenator> xHyphenator = LinguMgr::GetHyphenator();
if (!xHyphenator->hasLocale(lang::Locale(u"nl"_ustr, u"NL"_ustr, OUString())))
return;
// compound-based hyphenation needs fixed Hunspell morphological analysis
uno::Reference<linguistic2::XSpellChecker1> xSpell = LinguMgr::GetSpellChecker();
LanguageType eLang
= LanguageTag::convertToLanguageType(lang::Locale(u"nl"_ustr, u"NL"_ustr, OUString()));
if (!xSpell.is() || !xSpell->hasLanguage(static_cast<sal_uInt16>(eLang)))
return;
std::vector<std::pair<OUString, OUString>> aCompound = {
{ u"arbeidsvoorwaarden"_ustr, "pa:arbeids" },
{ u"doeleinden"_ustr, "pa:doel" },
};
// tests supported by the actual spelling dictionary
bool aTests[2];
// check Hunspell-based morphological analysis & hyphenation
bool bHunspell = xSpell->isValid("<?xml?>", static_cast<sal_uInt16>(eLang),
uno::Sequence<beans::PropertyValue>());
if (bHunspell)
{
// check dictionary support of compound splitting
for (size_t i = 0; i < aCompound.size(); ++i)
{
aTests[i] = false;
// get morphological analysis of the test word
uno::Reference<css::linguistic2::XSpellAlternatives> xTmpRes = xSpell->spell(
"<?xml?><query type='analyze'><word>" + aCompound[i].first + "</word></query>",
static_cast<sal_uInt16>(eLang), uno::Sequence<beans::PropertyValue>());
if (xTmpRes.is())
{
uno::Sequence<OUString> seq = xTmpRes->getAlternatives();
if (seq.hasElements())
{
sal_Int32 nEndOfFirstAnalysis = seq[0].indexOf("</a>");
// use only the first analysis, like the lingucomponent implementation
OUString morph(seq[0].copy(0, nEndOfFirstAnalysis));
// check compound data
aTests[i] = morph.indexOf(aCompound[i].second) > -1;
}
}
}
}
createSwDoc("tdf173389_smart_hyphenation_ml.odt");
// Ensure that all text portions are calculated before testing.
SwViewShell* pViewShell = getSwDoc()->getIDocumentLayoutAccess().GetCurrentViewShell();
CPPUNIT_ASSERT(pViewShell);
pViewShell->Reformat();
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
// delete page 1-2 to update hyphenation on the next page
SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 6151, /*bBasicCall=*/false);
pWrtShell->Delete();
pViewShell->Reformat();
pXmlDoc = parseLayoutDump();
// compound-based "smart" hyphenation of the compound "arbeids|voorwaarden"
// This was hyphenated as "ar-beidsvoorwaarden" previously, now "arbeids-voorwaarden"
if (bHunspell && aTests[0])
{
assertXPath(pXmlDoc, "/root/page[1]/body/txt[25]/SwParaPortion/SwLineLayout[1]", "portion",
u"Een ieder heeft recht op arbeid, op vrije keuze van beroep, op rechtmatige "
u"en gunstige arbeids");
}
assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout[2]/SwHyphPortion",
1);
// delete page 2 to update hyphenation on the next page
pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 6179, /*bBasicCall=*/false);
pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 6179, /*bBasicCall=*/false);
pWrtShell->Delete();
// 10 hyphenations on page 3
pViewShell->Reformat();
pXmlDoc = parseLayoutDump();
// compound-based "smart" hyphenation of the compound "doel|einden"
// This was hyphenated as "doelein-den" previously, now "doel-einden"
if (bHunspell && aTests[1])
{
assertXPath(pXmlDoc, "/root/page[1]/body/txt[13]/SwParaPortion/SwLineLayout[1]", "portion",
u"Deze rechten en vrijheden mogen in geen geval worden uitgeoefend in strijd "
u"met de doel");
}
assertXPath(pXmlDoc, "/root/page[1]/body/txt[13]/SwParaPortion/SwLineLayout[1]/SwHyphPortion",
1);
}
CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf158333) CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf158333)
{ {
createSwDoc("tdf130088.docx"); createSwDoc("tdf130088.docx");
+21 -20
View File
@@ -26,7 +26,7 @@ class styleNavigator(UITestCase):
# The cursor is on text without formatting and default style # The cursor is on text without formatting and default style
self.assertEqual(1, len(xListBox.getChild('0').getChildren())) 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("Default Paragraph Style\t", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
self.assertEqual(160, len(xListBox.getChild('0').getChild('0').getChildren())) self.assertEqual(161, len(xListBox.getChild('0').getChild('0').getChildren()))
self.assertEqual(0, len(xListBox.getChild('1').getChildren())) self.assertEqual(0, len(xListBox.getChild('1').getChildren()))
self.assertEqual(0, len(xListBox.getChild('2').getChildren())) self.assertEqual(0, len(xListBox.getChild('2').getChildren()))
self.assertEqual(0, len(xListBox.getChild('3').getChildren())) self.assertEqual(0, len(xListBox.getChild('3').getChildren()))
@@ -36,7 +36,7 @@ class styleNavigator(UITestCase):
# The cursor is on text with direct formatting # The cursor is on text with direct formatting
self.assertEqual(1, len(xListBox.getChild('0').getChildren())) 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("Default Paragraph Style\t", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
self.assertEqual(160, len(xListBox.getChild('0').getChild('0').getChildren())) self.assertEqual(161, len(xListBox.getChild('0').getChild('0').getChildren()))
self.assertEqual(0, len(xListBox.getChild('1').getChildren())) self.assertEqual(0, len(xListBox.getChild('1').getChildren()))
self.assertEqual(0, len(xListBox.getChild('2').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 # The cursor is on text with paragraph direct formatting
self.assertEqual(1, len(xListBox.getChild('0').getChildren())) 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("Default Paragraph Style\t", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
self.assertEqual(160, len(xListBox.getChild('0').getChild('0').getChildren())) self.assertEqual(161, len(xListBox.getChild('0').getChild('0').getChildren()))
xParDirFormatting = xListBox.getChild('1') xParDirFormatting = xListBox.getChild('1')
self.assertEqual(7, len(xParDirFormatting.getChildren())) self.assertEqual(7, len(xParDirFormatting.getChildren()))
@@ -75,13 +75,13 @@ class styleNavigator(UITestCase):
xParStyle = xListBox.getChild('0') xParStyle = xListBox.getChild('0')
self.assertEqual(3, len(xParStyle.getChildren())) self.assertEqual(3, len(xParStyle.getChildren()))
self.assertEqual("Default Paragraph Style\t", get_state_as_dict(xParStyle.getChild('0'))['Text']) self.assertEqual("Default Paragraph Style\t", get_state_as_dict(xParStyle.getChild('0'))['Text'])
self.assertEqual(160, len(xParStyle.getChild('0').getChildren())) self.assertEqual(161, len(xParStyle.getChild('0').getChildren()))
self.assertEqual("Heading\t", get_state_as_dict(xParStyle.getChild('1'))['Text']) self.assertEqual("Heading\t", get_state_as_dict(xParStyle.getChild('1'))['Text'])
self.assertEqual(28, len(xParStyle.getChild('1').getChildren())) self.assertEqual(28, len(xParStyle.getChild('1').getChildren()))
xTitleStyle = xParStyle.getChild('2') xTitleStyle = xParStyle.getChild('2')
self.assertEqual("Title\t", get_state_as_dict(xTitleStyle)['Text']) self.assertEqual("Title\t", get_state_as_dict(xTitleStyle)['Text'])
self.assertEqual(24, len(xTitleStyle.getChildren())) self.assertEqual(25, len(xTitleStyle.getChildren()))
self.assertEqual("Char Difference Height\t0", get_state_as_dict(xTitleStyle.getChild('0'))['Text']) self.assertEqual("Char Difference Height\t0", get_state_as_dict(xTitleStyle.getChild('0'))['Text'])
self.assertEqual("Char Difference Height Asian\t0", get_state_as_dict(xTitleStyle.getChild('1'))['Text']) self.assertEqual("Char Difference Height Asian\t0", get_state_as_dict(xTitleStyle.getChild('1'))['Text'])
self.assertEqual("Char Difference Height Complex\t0", get_state_as_dict(xTitleStyle.getChild('2'))['Text']) self.assertEqual("Char Difference Height Complex\t0", get_state_as_dict(xTitleStyle.getChild('2'))['Text'])
@@ -97,15 +97,16 @@ class styleNavigator(UITestCase):
self.assertEqual("Follow Style\tText body", get_state_as_dict(xTitleStyle.getChild('12'))['Text']) self.assertEqual("Follow Style\tText body", get_state_as_dict(xTitleStyle.getChild('12'))['Text'])
self.assertEqual("Para Adjust\t3", get_state_as_dict(xTitleStyle.getChild('13'))['Text']) self.assertEqual("Para Adjust\t3", get_state_as_dict(xTitleStyle.getChild('13'))['Text'])
self.assertEqual("Para Composer\tFalse", get_state_as_dict(xTitleStyle.getChild('14'))['Text']) self.assertEqual("Para Composer\tFalse", get_state_as_dict(xTitleStyle.getChild('14'))['Text'])
self.assertEqual("Para Expand Single Word\tFalse", get_state_as_dict(xTitleStyle.getChild('15'))['Text']) self.assertEqual("Para Compound-based Hyphenation\tFalse", get_state_as_dict(xTitleStyle.getChild('15'))['Text'])
self.assertEqual("Para Last Line Adjust\t0", get_state_as_dict(xTitleStyle.getChild('16'))['Text']) self.assertEqual("Para Expand Single Word\tFalse", get_state_as_dict(xTitleStyle.getChild('16'))['Text'])
self.assertEqual("Para Letter Spacing Maximum\t0", get_state_as_dict(xTitleStyle.getChild('17'))['Text']) self.assertEqual("Para Last Line Adjust\t0", get_state_as_dict(xTitleStyle.getChild('17'))['Text'])
self.assertEqual("Para Letter Spacing Minimum\t0", get_state_as_dict(xTitleStyle.getChild('18'))['Text']) self.assertEqual("Para Letter Spacing Maximum\t0", get_state_as_dict(xTitleStyle.getChild('18'))['Text'])
self.assertEqual("Para Scale Width Maximum\t100", get_state_as_dict(xTitleStyle.getChild('19'))['Text']) self.assertEqual("Para Letter Spacing Minimum\t0", get_state_as_dict(xTitleStyle.getChild('19'))['Text'])
self.assertEqual("Para Scale Width Minimum\t100", get_state_as_dict(xTitleStyle.getChild('20'))['Text']) self.assertEqual("Para Scale Width Maximum\t100", get_state_as_dict(xTitleStyle.getChild('20'))['Text'])
self.assertEqual("Para Word Spacing\t100", get_state_as_dict(xTitleStyle.getChild('21'))['Text']) self.assertEqual("Para Scale Width Minimum\t100", get_state_as_dict(xTitleStyle.getChild('21'))['Text'])
self.assertEqual("Para Word Spacing Maximum\t100", get_state_as_dict(xTitleStyle.getChild('22'))['Text']) self.assertEqual("Para Word Spacing\t100", get_state_as_dict(xTitleStyle.getChild('22'))['Text'])
self.assertEqual("Para Word Spacing Minimum\t100", get_state_as_dict(xTitleStyle.getChild('23'))['Text']) self.assertEqual("Para Word Spacing Maximum\t100", get_state_as_dict(xTitleStyle.getChild('23'))['Text'])
self.assertEqual("Para Word Spacing Minimum\t100", get_state_as_dict(xTitleStyle.getChild('24'))['Text'])
self.assertEqual(0, len(xListBox.getChild('1').getChildren())) self.assertEqual(0, len(xListBox.getChild('1').getChildren()))
self.assertEqual(0, len(xListBox.getChild('2').getChildren())) self.assertEqual(0, len(xListBox.getChild('2').getChildren()))
@@ -117,7 +118,7 @@ class styleNavigator(UITestCase):
xParStyle = xListBox.getChild('0') xParStyle = xListBox.getChild('0')
self.assertEqual(3, len(xParStyle.getChildren())) self.assertEqual(3, len(xParStyle.getChildren()))
self.assertEqual("Default Paragraph Style\t", get_state_as_dict(xParStyle.getChild('0'))['Text']) self.assertEqual("Default Paragraph Style\t", get_state_as_dict(xParStyle.getChild('0'))['Text'])
self.assertEqual(160, len(xParStyle.getChild('0').getChildren())) self.assertEqual(161, len(xParStyle.getChild('0').getChildren()))
self.assertEqual("Body Text\t", get_state_as_dict(xParStyle.getChild('1'))['Text']) self.assertEqual("Body Text\t", get_state_as_dict(xParStyle.getChild('1'))['Text'])
self.assertEqual(6, len(xParStyle.getChild('1').getChildren())) self.assertEqual(6, len(xParStyle.getChild('1').getChildren()))
@@ -152,7 +153,7 @@ class styleNavigator(UITestCase):
# The cursor is on text without metadata # The cursor is on text without metadata
self.assertEqual(1, len(xListBox.getChild('0').getChildren())) 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("Default Paragraph Style\t", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
self.assertEqual(160, len(xListBox.getChild('0').getChild('0').getChildren())) self.assertEqual(161, len(xListBox.getChild('0').getChild('0').getChildren()))
self.assertEqual(0, len(xListBox.getChild('1').getChildren())) self.assertEqual(0, len(xListBox.getChild('1').getChildren()))
self.assertEqual(0, len(xListBox.getChild('2').getChildren())) self.assertEqual(0, len(xListBox.getChild('2').getChildren()))
self.assertEqual(0, len(xListBox.getChild('3').getChildren())) self.assertEqual(0, len(xListBox.getChild('3').getChildren()))
@@ -162,7 +163,7 @@ class styleNavigator(UITestCase):
# The cursor is on text with paragraph metadata showed under direct paragraph formatting # The cursor is on text with paragraph metadata showed under direct paragraph formatting
self.assertEqual(1, len(xListBox.getChild('0').getChildren())) 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("Default Paragraph Style\t", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
self.assertEqual(160, len(xListBox.getChild('0').getChild('0').getChildren())) self.assertEqual(161, len(xListBox.getChild('0').getChild('0').getChildren()))
xParDirFormatting = xListBox.getChild('1') xParDirFormatting = xListBox.getChild('1')
self.assertEqual(1, len(xParDirFormatting.getChildren())) self.assertEqual(1, len(xParDirFormatting.getChildren()))
@@ -215,7 +216,7 @@ class styleNavigator(UITestCase):
# The cursor is on text without metadata # The cursor is on text without metadata
self.assertEqual(1, len(xListBox.getChild('0').getChildren())) 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("Default Paragraph Style\t", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
self.assertEqual(160, len(xListBox.getChild('0').getChild('0').getChildren())) self.assertEqual(161, len(xListBox.getChild('0').getChild('0').getChildren()))
self.assertEqual(0, len(xListBox.getChild('1').getChildren())) self.assertEqual(0, len(xListBox.getChild('1').getChildren()))
self.assertEqual(0, len(xListBox.getChild('2').getChildren())) self.assertEqual(0, len(xListBox.getChild('2').getChildren()))
self.assertEqual(0, len(xListBox.getChild('3').getChildren())) self.assertEqual(0, len(xListBox.getChild('3').getChildren()))
@@ -225,7 +226,7 @@ class styleNavigator(UITestCase):
# The cursor is on text with paragraph metadata showed under direct paragraph formatting # The cursor is on text with paragraph metadata showed under direct paragraph formatting
self.assertEqual(1, len(xListBox.getChild('1').getChildren())) 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("Default Paragraph Style\t", get_state_as_dict(xListBox.getChild('1').getChild('0'))['Text'])
self.assertEqual(160, len(xListBox.getChild('1').getChild('0').getChildren())) self.assertEqual(161, len(xListBox.getChild('1').getChild('0').getChildren()))
# Outer bookmark # Outer bookmark
xBookmarkFormatting = xListBox.getChild('0') xBookmarkFormatting = xListBox.getChild('0')
@@ -272,7 +273,7 @@ class styleNavigator(UITestCase):
# The cursor is on text without metadata # The cursor is on text without metadata
self.assertEqual(1, len(xListBox.getChild('0').getChildren())) 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("Default Paragraph Style\t", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
self.assertEqual(160, len(xListBox.getChild('0').getChild('0').getChildren())) self.assertEqual(161, len(xListBox.getChild('0').getChild('0').getChildren()))
self.assertEqual(0, len(xListBox.getChild('1').getChildren())) self.assertEqual(0, len(xListBox.getChild('1').getChildren()))
self.assertEqual(0, len(xListBox.getChild('2').getChildren())) self.assertEqual(0, len(xListBox.getChild('2').getChildren()))
+1 -1
View File
@@ -35,7 +35,7 @@ class tdf137513(UITestCase):
self.assertEqual(2, len(xListBox.getChild('0').getChildren())) 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("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("Table Contents\t", get_state_as_dict(xListBox.getChild('0').getChild('1'))['Text'])
self.assertEqual(160, len(xListBox.getChild('0').getChild('0').getChildren())) self.assertEqual(161, len(xListBox.getChild('0').getChild('0').getChildren()))
xTableContent = xListBox.getChild('0').getChild('1') xTableContent = xListBox.getChild('0').getChild('1')
self.assertEqual(5, len(xTableContent.getChildren())) self.assertEqual(5, len(xTableContent.getChildren()))
+30 -2
View File
@@ -325,10 +325,37 @@ bool SwTextPortion::IsCompoundSplit( SwTextFormatInfo &rInf, const SwTextGuess &
LanguageType aLang = rInf.GetTextFrame()->GetLangOfChar(rInf.GetIdx(), 1, true); LanguageType aLang = rInf.GetTextFrame()->GetLangOfChar(rInf.GetIdx(), 1, true);
// Hungarian-only yet // is compound-based "smart" hyphenation enabled?
if ( LANGUAGE_HUNGARIAN != aLang ) SvxAdjustItem aAdjustItem =
rInf.GetTextFrame()->GetTextNodeForParaProps()->GetSwAttrSet().GetAdjust();
if ( !aAdjustItem.GetCompoundBased() )
return false; return false;
// need Hunspell dictionaries with compound-based heuristics
// TODO update the list according to the dictionary update
if ( LANGUAGE_ICELANDIC != aLang &&
LANGUAGE_DANISH != aLang &&
LANGUAGE_DUTCH != aLang &&
LANGUAGE_DUTCH_BELGIAN != aLang &&
LANGUAGE_ESTONIAN != aLang &&
LANGUAGE_FINNISH != aLang &&
LANGUAGE_LATVIAN != aLang &&
LANGUAGE_GERMAN != aLang &&
LANGUAGE_GERMAN_AUSTRIAN != aLang &&
LANGUAGE_GERMAN_LIECHTENSTEIN != aLang &&
LANGUAGE_GERMAN_LUXEMBOURG != aLang &&
LANGUAGE_GERMAN_SWISS != aLang &&
LANGUAGE_HUNGARIAN != aLang &&
LANGUAGE_MONGOLIAN_CYRILLIC_MONGOLIA != aLang &&
LANGUAGE_NORWEGIAN_BOKMAL != aLang &&
LANGUAGE_NORWEGIAN_NYNORSK != aLang &&
LANGUAGE_SWEDISH != aLang &&
LANGUAGE_SWEDISH_FINLAND != aLang &&
LANGUAGE_USER_ESPERANTO != aLang )
{
return false;
}
LanguageTag aLanguageTag(aLang); LanguageTag aLanguageTag(aLang);
uno::Reference< linguistic2::XHyphenator > xHyph; uno::Reference< linguistic2::XHyphenator > xHyph;
@@ -733,6 +760,7 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf )
// perhaps there is a compound splitting in the same word before the plain hyphenation // perhaps there is a compound splitting in the same word before the plain hyphenation
bool bPossibleCompoundSplit = bOrigHyphenated3 && bool bPossibleCompoundSplit = bOrigHyphenated3 &&
aAdjustItem.GetCompoundBased() &&
pGuess3->HyphWord()->getHyphenationPos() < pGuess2->HyphWord()->getHyphenationPos() && pGuess3->HyphWord()->getHyphenationPos() < pGuess2->HyphWord()->getHyphenationPos() &&
pGuess3->HyphWord()->getWord().equals(pGuess2->HyphWord()->getWord()); pGuess3->HyphWord()->getWord().equals(pGuess2->HyphWord()->getWord());
@@ -198,6 +198,7 @@
{ UNO_NAME_PARA_SCALE_WIDTH_MIN, RES_PARATR_ADJUST, cppu::UnoType<sal_Int16>::get(), PropertyAttribute::MAYBEVOID, MID_SCALE_WIDTH_MIN }, \ { UNO_NAME_PARA_SCALE_WIDTH_MIN, RES_PARATR_ADJUST, cppu::UnoType<sal_Int16>::get(), PropertyAttribute::MAYBEVOID, MID_SCALE_WIDTH_MIN }, \
{ UNO_NAME_PARA_SCALE_WIDTH_MAX, RES_PARATR_ADJUST, cppu::UnoType<sal_Int16>::get(), PropertyAttribute::MAYBEVOID, MID_SCALE_WIDTH_MAX }, \ { UNO_NAME_PARA_SCALE_WIDTH_MAX, RES_PARATR_ADJUST, cppu::UnoType<sal_Int16>::get(), PropertyAttribute::MAYBEVOID, MID_SCALE_WIDTH_MAX }, \
{ UNO_NAME_PARA_COMPOSER, RES_PARATR_ADJUST, cppu::UnoType<bool>::get(), PropertyAttribute::MAYBEVOID, MID_PARAGRAPH_COMPOSER }, \ { UNO_NAME_PARA_COMPOSER, RES_PARATR_ADJUST, cppu::UnoType<bool>::get(), PropertyAttribute::MAYBEVOID, MID_PARAGRAPH_COMPOSER }, \
{ UNO_NAME_PARA_IS_COMPOUND_BASED, RES_PARATR_ADJUST, cppu::UnoType<bool>::get(), PropertyAttribute::MAYBEVOID, MID_COMPOUND_BASED }, \
{ UNO_NAME_PARA_LINE_NUMBER_COUNT, RES_LINENUMBER, cppu::UnoType<bool>::get(), PropertyAttribute::MAYBEVOID, MID_LINENUMBER_COUNT }, \ { 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_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 }, \ { UNO_NAME_PARA_LINE_SPACING, RES_PARATR_LINESPACING, cppu::UnoType<css::style::LineSpacing>::get(), PropertyAttribute::MAYBEVOID, CONVERT_TWIPS }, \
@@ -475,6 +476,7 @@
{ UNO_NAME_PARA_SCALE_WIDTH_MIN, RES_PARATR_ADJUST, cppu::UnoType<sal_Int16>::get(), PROPERTY_NONE, MID_SCALE_WIDTH_MIN},\ { UNO_NAME_PARA_SCALE_WIDTH_MIN, RES_PARATR_ADJUST, cppu::UnoType<sal_Int16>::get(), PROPERTY_NONE, MID_SCALE_WIDTH_MIN},\
{ UNO_NAME_PARA_SCALE_WIDTH_MAX, RES_PARATR_ADJUST, cppu::UnoType<sal_Int16>::get(), PROPERTY_NONE, MID_SCALE_WIDTH_MAX},\ { UNO_NAME_PARA_SCALE_WIDTH_MAX, RES_PARATR_ADJUST, cppu::UnoType<sal_Int16>::get(), PROPERTY_NONE, MID_SCALE_WIDTH_MAX},\
{ UNO_NAME_PARA_COMPOSER, RES_PARATR_ADJUST, cppu::UnoType<bool>::get(), PROPERTY_NONE, MID_PARAGRAPH_COMPOSER},\ { UNO_NAME_PARA_COMPOSER, RES_PARATR_ADJUST, cppu::UnoType<bool>::get(), PROPERTY_NONE, MID_PARAGRAPH_COMPOSER},\
{ UNO_NAME_PARA_IS_COMPOUND_BASED, RES_PARATR_ADJUST, cppu::UnoType<bool>::get(), PROPERTY_NONE, MID_COMPOUND_BASED},\
{ UNO_NAME_PARA_LINE_NUMBER_COUNT, RES_LINENUMBER, cppu::UnoType<bool>::get(), PROPERTY_NONE ,MID_LINENUMBER_COUNT },\ { 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_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},\ { UNO_NAME_PARA_LINE_SPACING, RES_PARATR_LINESPACING, cppu::UnoType<css::style::LineSpacing>::get(),PROPERTY_NONE, CONVERT_TWIPS},\
@@ -267,6 +267,7 @@ static OUString PropertyNametoRID(const OUString& rName)
{ "ParaBottomMarginRelative", RID_PARA_BOTTOM_MARGIN_RELATIVE }, { "ParaBottomMarginRelative", RID_PARA_BOTTOM_MARGIN_RELATIVE },
{ "ParaChapterNumberingLevel", RID_PARA_CHAPTER_NUMBERING_LEVEL }, { "ParaChapterNumberingLevel", RID_PARA_CHAPTER_NUMBERING_LEVEL },
{ "ParaComposer", RID_PARA_COMPOSER }, { "ParaComposer", RID_PARA_COMPOSER },
{ "ParaIsCompoundBased", RID_PARA_COMPOUND_BASED_HYPHENATION },
{ "ParaConditionalStyleName", RID_PARA_CONDITIONAL_STYLE_NAME }, { "ParaConditionalStyleName", RID_PARA_CONDITIONAL_STYLE_NAME },
{ "ParaContextMargin", RID_PARA_CONTEXT_MARGIN }, { "ParaContextMargin", RID_PARA_CONTEXT_MARGIN },
{ "ParaExpandSingleWord", RID_PARA_EXPAND_SINGLE_WORD }, { "ParaExpandSingleWord", RID_PARA_EXPAND_SINGLE_WORD },
+1
View File
@@ -498,6 +498,7 @@ inline constexpr OUString PROP_ParaBackTransparent = u"ParaBackTransparent"_ustr
inline constexpr OUString PROP_ParaBottomMargin = u"ParaBottomMargin"_ustr; inline constexpr OUString PROP_ParaBottomMargin = u"ParaBottomMargin"_ustr;
inline constexpr OUString PROP_ParaBottomMarginRelative = u"ParaBottomMarginRelative"_ustr; inline constexpr OUString PROP_ParaBottomMarginRelative = u"ParaBottomMarginRelative"_ustr;
inline constexpr OUString PROP_ParaComposer = u"ParaComposer"_ustr; inline constexpr OUString PROP_ParaComposer = u"ParaComposer"_ustr;
inline constexpr OUString PROP_ParaIsCompoundBased = u"ParaIsCompoundBased"_ustr;
inline constexpr OUString PROP_ParaContextMargin = u"ParaContextMargin"_ustr; inline constexpr OUString PROP_ParaContextMargin = u"ParaContextMargin"_ustr;
inline constexpr OUString PROP_ParaExpandSingleWord = u"ParaExpandSingleWord"_ustr; inline constexpr OUString PROP_ParaExpandSingleWord = u"ParaExpandSingleWord"_ustr;
inline constexpr OUString PROP_ParaFirstLineIndent = u"ParaFirstLineIndent"_ustr; inline constexpr OUString PROP_ParaFirstLineIndent = u"ParaFirstLineIndent"_ustr;
+1
View File
@@ -501,6 +501,7 @@ namespace xmloff::token {
TOKEN( "command", XML_COMMAND ), TOKEN( "command", XML_COMMAND ),
TOKEN( "comment", XML_COMMENT ), TOKEN( "comment", XML_COMMENT ),
TOKEN( "compose", XML_COMPOSE ), TOKEN( "compose", XML_COMPOSE ),
TOKEN( "compound-based", XML_COMPOUND_BASED ),
TOKEN( "cond-style-name", XML_COND_STYLE_NAME ), TOKEN( "cond-style-name", XML_COND_STYLE_NAME ),
TOKEN( "condition", XML_CONDITION ), TOKEN( "condition", XML_CONDITION ),
TOKEN( "condition-source", XML_CONDITION_SOURCE ), TOKEN( "condition-source", XML_CONDITION_SOURCE ),
+1
View File
@@ -500,6 +500,7 @@ XMLPropertyMapEntry constexpr aXMLParaPropMap[] =
MAP_EXT( PROP_ParaScaleWidthMinimum, XML_NAMESPACE_LO_EXT, XML_TEXT_SCALE_MINIMUM, XML_TYPE_PROP_PARAGRAPH|XML_TYPE_PERCENT16, 0 ), MAP_EXT( PROP_ParaScaleWidthMinimum, XML_NAMESPACE_LO_EXT, XML_TEXT_SCALE_MINIMUM, XML_TYPE_PROP_PARAGRAPH|XML_TYPE_PERCENT16, 0 ),
MAP_EXT( PROP_ParaScaleWidthMaximum, XML_NAMESPACE_LO_EXT, XML_TEXT_SCALE_MAXIMUM, XML_TYPE_PROP_PARAGRAPH|XML_TYPE_PERCENT16, 0 ), MAP_EXT( PROP_ParaScaleWidthMaximum, XML_NAMESPACE_LO_EXT, XML_TEXT_SCALE_MAXIMUM, XML_TYPE_PROP_PARAGRAPH|XML_TYPE_PERCENT16, 0 ),
MAP_EXT( PROP_ParaComposer, XML_NAMESPACE_LO_EXT, XML_PARAGRAPH_COMPOSER, XML_TYPE_PROP_PARAGRAPH|XML_TYPE_BOOL, 0 ), MAP_EXT( PROP_ParaComposer, XML_NAMESPACE_LO_EXT, XML_PARAGRAPH_COMPOSER, XML_TYPE_PROP_PARAGRAPH|XML_TYPE_BOOL, 0 ),
MAP_EXT( PROP_ParaIsCompoundBased, XML_NAMESPACE_LO_EXT, XML_COMPOUND_BASED, XML_TYPE_PROP_PARAGRAPH|XML_TYPE_BOOL, 0 ),
MT_ED( PROP_CharScriptHint, XML_NAMESPACE_STYLE, XML_SCRIPT_TYPE, XML_TYPE_TEXT_SCRIPT_TYPE|MID_FLAG_MERGE_PROPERTY, 0 ), MT_ED( PROP_CharScriptHint, XML_NAMESPACE_STYLE, XML_SCRIPT_TYPE, XML_TYPE_TEXT_SCRIPT_TYPE|MID_FLAG_MERGE_PROPERTY, 0 ),
+1
View File
@@ -405,6 +405,7 @@ comma-separated
command command
comment comment
compose compose
compound-based
cond-style-name cond-style-name
condition condition
condition-source condition-source