offapi/com/sun/star/style/CharacterProperties.idl |    8 +
 sw/inc/ndtxt.hxx                                  |    2 
 sw/qa/uitest/data/tdf106733.fodt                  |   66 ++++++++++++
 sw/qa/uitest/writer_tests8/tdf106733.py           |  112 ++++++++++++++++++++++
 sw/qa/uitest/writer_tests8/tdf159102.py           |   42 +++++---
 sw/source/core/inc/txtfrm.hxx                     |    2 
 sw/source/core/text/guess.cxx                     |    7 +
 sw/source/core/text/txtfrm.cxx                    |    4 
 sw/source/core/txtnode/thints.cxx                 |   23 +++-
 xmloff/source/text/txtprmap.cxx                   |    2 
 10 files changed, 243 insertions(+), 25 deletions(-)

New commits:
commit b5e275f47a54bd7fee39dad516a433fde5be872d
Author:     László Németh <nem...@numbertext.org>
AuthorDate: Fri Jan 19 01:29:34 2024 +0100
Commit:     László Németh <nem...@numbertext.org>
CommitDate: Fri Jan 19 17:37:41 2024 +0100

    tdf#106733 sw: implement CharNoHyphenation
    
    Implement CharNoHyphenation character property to
    disable automatic hyphenation of words in paragraphs
    with enabled hyphenation.
    
    Fix also fo:hyphenate mapping to CharNoHyphenation
    using automatic inversion of their boolean values
    defined by xmloff's XML_TYPE_NBOOL, as suggested by
    Michael Stahl.
    
    Update also the test for tdf#159102 to check the available
    hyphenation dictionary (also custom hyphenation patterns
    work only with supported locales of the hyphenator).
    
    Note: patch of thints.cxx contains also partial revert
    of commit 53b289eabb3d265b47bc7fb6cc430291c97f0c0b
    "use more TypedWhichId".
    
    Follow-up to commit 73bd04a71e741788a2f2f3b26cc46ddb6a361372
    "tdf#106733 xmloff: keep fo:hyphenate in character formatting".
    
    Change-Id: If99b94ddcd44a5c2426e646be149078a3b9773b6
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162300
    Tested-by: László Németh <nem...@numbertext.org>
    Reviewed-by: László Németh <nem...@numbertext.org>

diff --git a/offapi/com/sun/star/style/CharacterProperties.idl 
b/offapi/com/sun/star/style/CharacterProperties.idl
index 6502a47b2886..aaff4a569455 100644
--- a/offapi/com/sun/star/style/CharacterProperties.idl
+++ b/offapi/com/sun/star/style/CharacterProperties.idl
@@ -325,7 +325,13 @@ published service CharacterProperties
 
 
     /** This optional property determines if the word can be hyphenated at the
-        character.
+        character by automatic hyphenation.
+
+        <p>Setting to `true` will disable hyphenation enabled by 
ParaIsHyphenation.</p>
+
+        <p>Note: implemented since LibreOffice 24.2.</p>
+
+        @see ParaIsHyphenation
      */
     [optional, property] boolean CharNoHyphenation;
 
diff --git a/sw/inc/ndtxt.hxx b/sw/inc/ndtxt.hxx
index 3f99919f77b2..352dad71c247 100644
--- a/sw/inc/ndtxt.hxx
+++ b/sw/inc/ndtxt.hxx
@@ -720,7 +720,7 @@ public:
     void fillSoftPageBreakList( SwSoftPageBreakList& rBreak ) const;
 
     LanguageType GetLang( const sal_Int32 nBegin, const sal_Int32 nLen = 0,
-                    sal_uInt16 nScript = 0 ) const;
+                    sal_uInt16 nScript = 0, bool bNoneIfNoHyphenation = false 
) const;
 
     /// in ndcopy.cxx
     bool IsSymbolAt(sal_Int32 nBegin) const; // In itratr.cxx.
diff --git a/sw/qa/uitest/data/tdf106733.fodt b/sw/qa/uitest/data/tdf106733.fodt
new file mode 100644
index 000000000000..fa9a02440573
--- /dev/null
+++ b/sw/qa/uitest/data/tdf106733.fodt
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:css3t="http://www.w3.org/TR/css3-text/"; 
xmlns:grddl="http://www.w3.org/2003/g/data-view#"; 
xmlns:xhtml="http://www.w3.org/1999/xhtml"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"; 
xmlns:xforms="http://www.w3.org/2002/xforms"; 
xmlns:dom="http://www.w3.org/2001/xml-events"; 
xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" 
xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" 
xmlns:math="http://www.w3.org/1998/Math/MathML"; 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:ooo="http://openoffice.org/2004/office"; 
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" 
xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" 
xmlns:ooow="http://openoffice.org/2004/writer"; 
xmlns:xlink="http://www.w3.org/1999/xlink"; 
xmlns:drawooo="http://openoffice.org/2010/draw"; 
xmlns:oooc="http://openoffice.org/2004/calc"; 
xmlns:dc="http://purl.org/dc/elements/1.1/"; xmlns:c
 alcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" 
xmlns:tableooo="http://openoffice.org/2009/table"; 
xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" 
xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" 
xmlns:rpt="http://openoffice.org/2005/report"; 
xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0"
 xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" 
xmlns:officeooo="http://openoffice.org/2009/office"; 
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" 
xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" 
xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" 
xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:
 meta:1.0" 
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
 office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:font-face-decls>
+  <style:font-face style:name="DejaVu Sans" svg:font-family="&apos;DejaVu 
Sans&apos;" style:font-family-generic="swiss"/>
+ </office:font-face-decls>
+ <office:styles>
+  <style:default-style style:family="paragraph">
+   <style:paragraph-properties fo:orphans="2" fo:widows="2" 
fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" 
style:punctuation-wrap="hanging" style:line-break="strict" 
style:tab-stop-distance="35.46pt" style:writing-mode="page"/>
+   <style:text-properties style:use-window-font-color="true" 
loext:opacity="0%" style:font-name="DejaVu Sans" fo:font-size="12pt" 
fo:language="hu" fo:country="HU" style:letter-kerning="true" 
style:font-name-asian="Noto Serif CJK SC" style:font-size-asian="10.5pt" 
style:language-asian="zh" style:country-asian="CN" 
style:font-name-complex="Lohit Devanagari1" style:font-size-complex="12pt" 
style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" 
fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" 
loext:hyphenation-no-caps="false" loext:hyphenation-no-last-word="false" 
loext:hyphenation-word-char-count="5" loext:hyphenation-zone="no-limit"/>
+  </style:default-style>
+  <style:style style:name="Standard" style:family="paragraph" 
style:class="text"/>
+  <style:style style:name="Text_20_body" style:display-name="Text body" 
style:family="paragraph" style:parent-style-name="Standard" style:class="text">
+   <style:paragraph-properties fo:margin-top="0pt" fo:margin-bottom="7pt" 
style:contextual-spacing="false" fo:line-height="115%"/>
+  </style:style>
+  <style:style style:name="Heading_20_3" style:display-name="Heading 3" 
style:family="paragraph" style:parent-style-name="Heading" 
style:next-style-name="Text_20_body" style:default-outline-level="3" 
style:class="text">
+   <style:paragraph-properties fo:margin-top="7pt" fo:margin-bottom="6.01pt" 
style:contextual-spacing="false"/>
+   <style:text-properties fo:font-size="14pt" fo:font-weight="bold" 
style:font-size-asian="14pt" style:font-weight-asian="bold" 
style:font-size-complex="14pt" style:font-weight-complex="bold"/>
+  </style:style>
+  <style:style style:name="Strong_20_Emphasis" style:display-name="Strong 
Emphasis" style:family="text">
+   <style:text-properties fo:font-weight="bold" fo:hyphenate="false" 
style:font-weight-asian="bold" style:font-weight-complex="bold"/>
+  </style:style>
+ </office:styles>
+ <office:automatic-styles>
+  <style:style style:name="P1" style:family="paragraph" 
style:parent-style-name="Text_20_body">
+   <loext:graphic-properties draw:fill="none"/>
+   <style:paragraph-properties fo:margin-left="0pt" fo:margin-right="257.95pt" 
fo:margin-top="0pt" fo:margin-bottom="7pt" style:contextual-spacing="false" 
fo:line-height="115%" fo:text-align="justify" style:justify-single-word="false" 
fo:hyphenation-ladder-count="no-limit" fo:text-indent="0pt" 
style:auto-text-indent="false" fo:background-color="transparent"/>
+   <style:text-properties fo:language="en" fo:country="US" 
officeooo:rsid="1d851e57" officeooo:paragraph-rsid="0007570c" 
style:language-complex="ar" style:country-complex="SA" fo:hyphenate="true" 
fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" 
loext:hyphenation-no-caps="false" loext:hyphenation-no-last-word="false" 
loext:hyphenation-word-char-count="no-limit" loext:hyphenation-zone="no-limit"/>
+  </style:style>
+  <style:style style:name="P3" style:family="paragraph" 
style:parent-style-name="Text_20_body">
+   <loext:graphic-properties draw:fill="none"/>
+   <style:paragraph-properties fo:margin-left="0pt" fo:margin-right="257.95pt" 
fo:margin-top="0pt" fo:margin-bottom="7pt" style:contextual-spacing="false" 
fo:line-height="115%" fo:text-align="justify" style:justify-single-word="false" 
fo:hyphenation-ladder-count="no-limit" fo:text-indent="0pt" 
style:auto-text-indent="false" fo:background-color="transparent"/>
+   <style:text-properties fo:language="en" fo:country="US" 
officeooo:paragraph-rsid="0007570c" style:language-complex="ar" 
style:country-complex="SA" fo:hyphenate="true" 
fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" 
loext:hyphenation-no-caps="false" loext:hyphenation-no-last-word="false" 
loext:hyphenation-word-char-count="no-limit" loext:hyphenation-zone="no-limit"/>
+  </style:style>
+  <style:style style:name="P4" style:family="paragraph" 
style:parent-style-name="Heading_20_3">
+   <style:text-properties officeooo:paragraph-rsid="0007570c"/>
+  </style:style>
+  <style:style style:name="T6" style:family="text">
+   <style:text-properties fo:language="en" fo:country="US" 
fo:font-style="italic" fo:font-weight="bold" officeooo:rsid="1d851e57" 
fo:hyphenate="false" style:font-style-asian="italic" 
style:font-weight-asian="bold" style:language-complex="ar" 
style:country-complex="SA" style:font-style-complex="italic" 
style:font-weight-complex="bold"/>
+  </style:style>
+  <style:style style:name="T8" style:family="text">
+   <style:text-properties fo:font-weight="bold" officeooo:rsid="1d851e57" 
style:font-weight-asian="bold" style:font-weight-complex="bold"/>
+  </style:style>
+  <style:page-layout style:name="pm1">
+   <style:page-layout-properties fo:page-width="595.3pt" 
fo:page-height="841.89pt" style:num-format="1" 
style:print-orientation="portrait" fo:margin-top="56.69pt" 
fo:margin-bottom="56.69pt" fo:margin-left="56.69pt" fo:margin-right="56.69pt" 
style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" 
style:layout-grid-lines="20" style:layout-grid-base-height="20.01pt" 
style:layout-grid-ruby-height="10.01pt" style:layout-grid-mode="none" 
style:layout-grid-ruby-below="false" style:layout-grid-print="false" 
style:layout-grid-display="false" style:footnote-max-height="0pt" 
loext:margin-gutter="0pt">
+    <style:footnote-sep style:width="0.51pt" 
style:distance-before-sep="2.86pt" style:distance-after-sep="2.86pt" 
style:line-style="solid" style:adjustment="left" style:rel-width="25%" 
style:color="#000000"/>
+   </style:page-layout-properties>
+   <style:header-style/>
+   <style:footer-style/>
+  </style:page-layout>
+ </office:automatic-styles>
+ <office:master-styles>
+  <style:master-page style:name="Standard" style:page-layout-name="pm1" 
draw:style-name="dp1"/>
+ </office:master-styles>
+ <office:body>
+  <office:text>
+   <text:h text:style-name="P4" text:outline-level="3">Hyphenate</text:h>
+   <text:p text:style-name="P3">The Earth is no different to any other 
celestial body out there in space. It merely moves along in space inertially. 
Even just one inch above the surface of the Earth is space, <text:span 
text:style-name="T8">except</text:span> that it has an atmosphere.</text:p>
+   <text:h text:style-name="P4" text:outline-level="3">Don’t hyphenate (direct 
formatting)</text:h>
+   <text:p text:style-name="P3">The Earth is no different to any other 
celestial body out there in space. It merely moves along in space inertially. 
Even just one inch above the surface of the Earth is space, <text:span 
text:style-name="T6">except</text:span> that it has an atmosphere.</text:p>
+   <text:h text:style-name="P4" text:outline-level="3">Don’t hyphenate 
(character style)</text:h>
+   <text:p text:style-name="P3">The Earth is no different to any other 
celestial body out there in space. It merely moves along in space inertially. 
Even just one inch above the surface of the Earth is space, <text:span 
text:style-name="Strong_20_Emphasis">except</text:span> that it has an 
atmosphere.</text:p>
+   <text:p text:style-name="P3"/>
+  </office:text>
+ </office:body>
+</office:document>
diff --git a/sw/qa/uitest/writer_tests8/tdf106733.py 
b/sw/qa/uitest/writer_tests8/tdf106733.py
new file mode 100644
index 000000000000..201bba1c56ff
--- /dev/null
+++ b/sw/qa/uitest/writer_tests8/tdf106733.py
@@ -0,0 +1,112 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+from uitest.framework import UITestCase
+from uitest.uihelper.common import get_state_as_dict, get_url_for_data_file
+from libreoffice.uno.propertyvalue import mkPropertyValues
+from libreoffice.linguistic.linguservice import get_lingu_service_manager
+from com.sun.star.lang import Locale
+
+# handle tdf#106733 hyphenation of words disabled by character formatting
+
+class tdf106733(UITestCase):
+    def is_supported_locale(self, language, country):
+        xLinguServiceManager = 
get_lingu_service_manager(self.ui_test._xContext)
+        xHyphenator = xLinguServiceManager.getHyphenator()
+        locales = xHyphenator.getLocales()
+        for locale in locales:
+            if language != None:
+                if locale.Language != language:
+                    continue
+
+            if country != None:
+                if locale.Country != country:
+                    continue
+
+            # we found the correct combination
+            return True
+
+    def set_custom_hyphenation(self):
+        with 
self.ui_test.execute_dialog_through_command(".uno:OptionsTreeDialog") as 
xDialog:
+
+            xPages = xDialog.getChild("pages")
+            xLanguageEntry = xPages.getChild('2')                 # Language 
Settings
+            xLanguageEntry.executeAction("EXPAND", tuple())
+            xxLanguageEntryWritingAidsEntry = xLanguageEntry.getChild('1')
+            xxLanguageEntryWritingAidsEntry.executeAction("SELECT", tuple())   
       # Writing Aids
+
+            # add hyphenations to the custom dictionary to solve the 
non-accessible
+            # hyphenation patterns for the test
+
+            # Select an editable dictionary (list of Ignored words)
+            dictionaries = xDialog.getChild("lingudicts")
+            hasEditableDictionary = False
+            for i in dictionaries.getChildren():
+                entry = dictionaries.getChild(i)
+                entry_label = get_state_as_dict(entry)["Text"]
+                if entry_label == "List of Ignored Words [All]":
+                    hasEditableDictionary = True
+                    entry.executeAction("SELECT", tuple())          # an 
editable user dictionary
+                    break
+
+            self.assertEqual(True, hasEditableDictionary)
+
+            # open Edit dialog window
+            edit = xDialog.getChild("lingudictsedit")
+            with self.ui_test.execute_blocking_action(edit.executeAction, 
args=('CLICK', ()), close_button="close") as xEdit:
+                # add in=ertially and ex=cept to the custom hyphenations
+                inputbox = xEdit.getChild("word")
+                inputbox.executeAction("TYPE", mkPropertyValues({"TEXT": 
"ex=cept"}))
+                add = xEdit.getChild("newreplace")
+                add.executeAction("CLICK", tuple())
+                inputbox.executeAction("TYPE", mkPropertyValues({"TEXT": 
"in=ertially"}))
+                add.executeAction("CLICK", tuple())
+
+    def test_tdf106733_disable_hyphenation(self):
+        supported_locale = self.is_supported_locale("en", "US")
+        if not supported_locale:
+            self.skipTest("no hyphenation patterns for en_US available")
+
+        with self.ui_test.load_file(get_url_for_data_file("tdf106733.fodt")) 
as writer_doc:
+            # we must not depend on the installed hyphenation patterns,
+            # so extend user dictionary temporarily with the requested 
hyphenations
+            self.set_custom_hyphenation()
+
+            # delete the text of the first line
+            for i in range(5):
+                self.xUITest.executeCommand(".uno:GoDown")
+            self.xUITest.executeCommand(".uno:GoToEndOfLine")
+            self.xUITest.executeCommand('.uno:StartOfDocumentSel')
+            self.xUITest.executeCommand('.uno:Delete')
+            paragraphs = writer_doc.Text.createEnumeration()
+            para1 = paragraphs.nextElement()
+            # check default "ex=cept" hyphenation
+            self.assertEqual(True, para1.String.startswith("cept"))
+
+            # check disabled hyphenations (by direct character formatting)
+            for i in range(6):
+                self.xUITest.executeCommand(".uno:GoDown")
+            self.xUITest.executeCommand(".uno:GoToEndOfLine")
+            self.xUITest.executeCommand('.uno:StartOfDocumentSel')
+            self.xUITest.executeCommand('.uno:Delete')
+            paragraphs = writer_doc.Text.createEnumeration()
+            para1 = paragraphs.nextElement()
+            # This was False (the line started with "cept", because of the 
enabled hyphenation)
+            self.assertEqual(True, para1.String.startswith(" except"))
+
+            # check disabled hyphenations (by character style)
+            for i in range(6):
+                self.xUITest.executeCommand(".uno:GoDown")
+            self.xUITest.executeCommand(".uno:GoToEndOfLine")
+            self.xUITest.executeCommand('.uno:StartOfDocumentSel')
+            self.xUITest.executeCommand('.uno:Delete')
+            paragraphs = writer_doc.Text.createEnumeration()
+            para1 = paragraphs.nextElement()
+            # This was False (the line started with "cept", because of the 
enabled hyphenation)
+            self.assertEqual(True, para1.String.startswith(" except"))
+
diff --git a/sw/qa/uitest/writer_tests8/tdf159102.py 
b/sw/qa/uitest/writer_tests8/tdf159102.py
index 07152ada3999..b1daffabfe63 100644
--- a/sw/qa/uitest/writer_tests8/tdf159102.py
+++ b/sw/qa/uitest/writer_tests8/tdf159102.py
@@ -9,10 +9,27 @@
 from uitest.framework import UITestCase
 from uitest.uihelper.common import get_state_as_dict, get_url_for_data_file
 from libreoffice.uno.propertyvalue import mkPropertyValues
+from libreoffice.linguistic.linguservice import get_lingu_service_manager
+from com.sun.star.lang import Locale
 
 # handle tdf#119908 smart justify with automatic hyphenation
 
 class tdf159102(UITestCase):
+    def is_supported_locale(self, language, country):
+        xLinguServiceManager = 
get_lingu_service_manager(self.ui_test._xContext)
+        xHyphenator = xLinguServiceManager.getHyphenator()
+        locales = xHyphenator.getLocales()
+        for locale in locales:
+            if language != None:
+                if locale.Language != language:
+                    continue
+
+            if country != None:
+                if locale.Country != country:
+                    continue
+
+            # we found the correct combination
+            return True
 
     def set_custom_hyphenation(self):
         with 
self.ui_test.execute_dialog_through_command(".uno:OptionsTreeDialog") as 
xDialog:
@@ -23,8 +40,8 @@ class tdf159102(UITestCase):
             xxLanguageEntryWritingAidsEntry = xLanguageEntry.getChild('1')
             xxLanguageEntryWritingAidsEntry.executeAction("SELECT", tuple())   
       # Writing Aids
 
-            # add hyphenation "cur=sus" to the custom dictionary to solve the 
non-accessible
-            # hyphenation patterns for the test
+            # add hyphenation "cur=sus" and "ege=stas" to the custom dictionary
+            # to solve the non-accessible hyphenation patterns for the test
 
             # Select an editable dictionary (list of Ignored words)
             dictionaries = xDialog.getChild("lingudicts")
@@ -47,12 +64,18 @@ class tdf159102(UITestCase):
                 inputbox.executeAction("TYPE", mkPropertyValues({"TEXT": 
"cur=sus"}))
                 add = xEdit.getChild("newreplace")
                 add.executeAction("CLICK", tuple())
+                inputbox.executeAction("TYPE", mkPropertyValues({"TEXT": 
"ege=stas"}))
+                add.executeAction("CLICK", tuple())
 
     def test_tdf159102_smart_justify_with_automatic_hyphenation(self):
+        supported_locale = self.is_supported_locale("en", "US")
+        if not supported_locale:
+            self.skipTest("no hyphenation patterns for en_US available")
+
         xToolkit = 
self.xContext.ServiceManager.createInstance('com.sun.star.awt.Toolkit')
         with self.ui_test.load_file(get_url_for_data_file("tdf159102.fodt")) 
as writer_doc:
             # we must not depend on the installed hyphenation patterns,
-            # so extend user dictionary temporarily with the hyphenation 
cur=sus
+            # so extend user dictionary temporarily with the hyphenation 
cur=sus and ege=stas
             self.set_custom_hyphenation()
             xToolkit.processEventsToIdle()
             # delete the text of the first line
@@ -61,12 +84,8 @@ class tdf159102(UITestCase):
             self.xUITest.executeCommand('.uno:Delete')
             paragraphs = writer_doc.Text.createEnumeration()
             para1 = paragraphs.nextElement()
-            # This was "stas.", i.e. too much shrinking (accept also " cursus 
egestas." in the
-            # case of missing hyphenation patterns on some test platforms).
-            try:
-                self.assertEqual("sus egestas.", para1.String)
-            except AssertionError:
-                self.assertEqual(" cursus egestas.", para1.String)
+            # This was "stas.", i.e. too much shrinking
+            self.assertEqual("sus egestas.", para1.String)
 
             # check next paragraph (containing different text portions)
             self.xUITest.executeCommand(".uno:GoDown")
@@ -75,7 +94,4 @@ class tdf159102(UITestCase):
             self.xUITest.executeCommand('.uno:Delete')
             paragraphs = writer_doc.Text.createEnumeration()
             para1 = paragraphs.nextElement()
-            try:
-                self.assertEqual("sus egestas.", para1.String)
-            except AssertionError:
-                self.assertEqual(" cursus egestas.", para1.String)
+            self.assertEqual("sus egestas.", para1.String)
diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index 4b06ba0164c1..a906571487f2 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -587,7 +587,7 @@ public:
     TextFrameIndex GetDropLen(TextFrameIndex nWishLen) const;
 
     LanguageType GetLangOfChar(TextFrameIndex nIndex, sal_uInt16 nScript,
-            bool bNoChar = false) const;
+            bool bNoChar = false, bool bNoneIfNoHyphenation = false ) const;
 
     virtual void Format( vcl::RenderContext* pRenderContext, const 
SwBorderAttrs *pAttrs = nullptr ) override;
     virtual void CheckDirection( bool bVert ) override;
diff --git a/sw/source/core/text/guess.cxx b/sw/source/core/text/guess.cxx
index 3346fe345acc..c3a94187a7ea 100644
--- a/sw/source/core/text/guess.cxx
+++ b/sw/source/core/text/guess.cxx
@@ -585,7 +585,12 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, 
SwTextFormatInfo &rInf,
 
         m_nBreakStart = m_nBreakPos;
 
-        bHyph = BreakType::HYPHENATION == aResult.breakType;
+        bHyph = BreakType::HYPHENATION == aResult.breakType &&
+                // allow hyphenation of the word only if it's not disabled by 
character formatting
+                LANGUAGE_NONE != rInf.GetTextFrame()->GetLangOfChar(
+                        TextFrameIndex( sal_Int32(m_nBreakPos) +
+                                aResult.rHyphenatedWord->getHyphenationPos() ),
+                        1, true, /*bNoneIfNoHyphenation=*/true );
 
         if (bHyph && m_nBreakPos != TextFrameIndex(COMPLETE_STRING))
         {
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index 2f2136133fa3..86375e1e412f 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -1459,11 +1459,11 @@ SwDoc const& SwTextFrame::GetDoc() const
 }
 
 LanguageType SwTextFrame::GetLangOfChar(TextFrameIndex const nIndex,
-        sal_uInt16 const nScript, bool const bNoChar) const
+        sal_uInt16 const nScript, bool const bNoChar, bool const 
bNoneIfNoHyphenation) const
 {
     // a single character can be mapped uniquely!
     std::pair<SwTextNode const*, sal_Int32> const pos(MapViewToModel(nIndex));
-    return pos.first->GetLang(pos.second, bNoChar ? 0 : 1, nScript);
+    return pos.first->GetLang(pos.second, bNoChar ? 0 : 1, nScript, 
bNoneIfNoHyphenation);
 }
 
 void SwTextFrame::ResetPreps()
diff --git a/sw/source/core/txtnode/thints.cxx 
b/sw/source/core/txtnode/thints.cxx
index 0220fa9d8b2a..184866daf3e0 100644
--- a/sw/source/core/txtnode/thints.cxx
+++ b/sw/source/core/txtnode/thints.cxx
@@ -23,6 +23,7 @@
 #include <DocumentContentOperationsManager.hxx>
 #include <hintids.hxx>
 #include <editeng/rsiditem.hxx>
+#include <editeng/nhypitem.hxx>
 #include <osl/diagnose.h>
 #include <svl/whiter.hxx>
 #include <svl/itemiter.hxx>
@@ -3487,7 +3488,7 @@ void SwTextNode::ClearSwpHintsArr( bool bDelFields )
 }
 
 LanguageType SwTextNode::GetLang( const sal_Int32 nBegin, const sal_Int32 nLen,
-                           sal_uInt16 nScript ) const
+                           sal_uInt16 nScript, bool const bNoneIfNoHyphenation 
) const
 {
     LanguageType nRet = LANGUAGE_DONTKNOW;
 
@@ -3497,7 +3498,9 @@ LanguageType SwTextNode::GetLang( const sal_Int32 nBegin, 
const sal_Int32 nLen,
     }
 
     // #i91465# Consider nScript if pSwpHints == 0
-    const TypedWhichId<SvxLanguageItem> nWhichId = GetWhichOfScript( 
RES_CHRATR_LANGUAGE, nScript );
+    const sal_uInt16 nWhichId = bNoneIfNoHyphenation
+            ? RES_CHRATR_NOHYPHEN
+            : GetWhichOfScript( RES_CHRATR_LANGUAGE, nScript );
 
     if ( HasHints() )
     {
@@ -3531,8 +3534,18 @@ LanguageType SwTextNode::GetLang( const sal_Int32 
nBegin, const sal_Int32 nLen,
                     if( pHt->DontExpand() ? nBegin >= *pEndIdx : nBegin > 
*pEndIdx)
                         continue;
                 }
-                const SvxLanguageItem* pItem = CharFormat::GetItem( *pHt, 
nWhichId );
-                const LanguageType nLng = pItem->GetLanguage();
+                const SfxPoolItem* pItem = CharFormat::GetItem( *pHt, nWhichId 
);
+
+                if ( RES_CHRATR_NOHYPHEN == nWhichId )
+                {
+                   // bNoneIfNoHyphenation = true: return with LANGUAGE_NONE,
+                   // if the hyphenation is disabled by character formatting
+                   if  ( static_cast<const 
SvxNoHyphenItem*>(pItem)->GetValue() )
+                       return LANGUAGE_NONE;
+                   continue;
+                }
+
+                const LanguageType nLng = static_cast<const 
SvxLanguageItem*>(pItem)->GetLanguage();
 
                 // does the attribute completely cover the range?
                 if( nAttrStart <= nBegin && nEnd <= *pEndIdx )
@@ -3544,7 +3557,7 @@ LanguageType SwTextNode::GetLang( const sal_Int32 nBegin, 
const sal_Int32 nLen,
     }
     if( LANGUAGE_DONTKNOW == nRet )
     {
-        nRet = GetSwAttrSet().Get( nWhichId ).GetLanguage();
+        nRet = static_cast<const SvxLanguageItem&>(GetSwAttrSet().Get( 
nWhichId )).GetLanguage();
         if( LANGUAGE_DONTKNOW == nRet )
             nRet = GetAppLanguage();
     }
diff --git a/xmloff/source/text/txtprmap.cxx b/xmloff/source/text/txtprmap.cxx
index faa8150a3b6a..98d347d9edbe 100644
--- a/xmloff/source/text/txtprmap.cxx
+++ b/xmloff/source/text/txtprmap.cxx
@@ -546,7 +546,7 @@ XMLPropertyMapEntry constexpr aXMLTextPropMap[] =
     // RES_CHRATR_BLINK
     MT_E( PROP_CharFlash, XML_NAMESPACE_STYLE, XML_TEXT_BLINKING, 
XML_TYPE_BOOL, 0 ),
     // RES_CHRATR_NOHYPHEN
-    MT_E( PROP_CharNoHyphenation, XML_NAMESPACE_FO, XML_HYPHENATE, 
XML_TYPE_BOOL, 0 ),
+    MT_E( PROP_CharNoHyphenation, XML_NAMESPACE_FO, XML_HYPHENATE, 
XML_TYPE_NBOOL, 0 ),
     // RES_CHRATR_UNUSED2
     // RES_CHRATR_BACKGROUND
     MT_E( PROP_CharBackColor,       XML_NAMESPACE_FO,     
XML_BACKGROUND_COLOR,      XML_TYPE_COLORTRANSPARENT|MID_FLAG_MULTI_PROPERTY, 
CTF_CHAR_BACKGROUND ),

Reply via email to