tdf#164487: Introduce "Show underline" MS Word compatibility option
It corresponds to ulTrailSpace element in OOXML. This commit creates the option in officecfg, UI, ODF, and implements its initial support in layout. Unresolved problems (pre-existing, not created here): 1. Short lines show underline unconditionally. In the unit test doc, line 2 is such. In SwTextGuess::Guess, there is the "first check if everything fits to line" shortcut, that skips SwHolePortion creation, that causes the problem. 2. The first character of the trailing whitespace is underlined. It is caused by AdjustCutPos only stepping back until there is a single character left. But to fix that, we need to handle the "zero-length portion plus some extra" case. Change-Id: Icc84fcff3ae62ced198522a80b8ce6b0e12e3a3c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182188 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
This commit is contained in:
@@ -116,6 +116,12 @@
|
||||
</info>
|
||||
<value>false</value>
|
||||
</prop>
|
||||
<prop oor:name="MsWordUlTrailSpace" oor:type="xs:boolean" oor:nillable="false">
|
||||
<info>
|
||||
<desc>Show underline of Word-compatible trailing blanks</desc>
|
||||
</info>
|
||||
<value>false</value>
|
||||
</prop>
|
||||
<prop oor:name="SubtractFlysAnchoredAtFlys" oor:type="xs:boolean" oor:nillable="false">
|
||||
<info>
|
||||
<desc>Tolerate white lines of PDF page backgrounds for compatibility with old documents (Use LibreOffice 4.3 anchoring paint order)</desc>
|
||||
|
@@ -142,6 +142,7 @@ enum class DocumentSettingId
|
||||
MS_WORD_COMP_GRID_METRICS,
|
||||
// tdf#161233 pictures with wrap polygon should not be clipped
|
||||
NO_CLIPPING_WITH_WRAP_POLYGON,
|
||||
MS_WORD_UL_TRAIL_SPACE,
|
||||
};
|
||||
|
||||
/** Provides access to settings of a document
|
||||
|
@@ -1532,6 +1532,7 @@
|
||||
#define STR_COMPAT_OPT_CONTINUOUS_ENDNOTES NC_("STR_COMPAT_OPT_CONTINUOUS_ENDNOTES", "Render endnotes at the end of document inline, rather than on a separate page")
|
||||
#define STR_COMPAT_OPT_MSWORDCOMPGRIDMETRICS NC_("STR_COMPAT_OPT_MSWORDCOMPGRIDMETRICS", "Use Word-compatible font metrics for text grid")
|
||||
#define STR_COMPAT_OPT_IGNORETABSANDBLANKSFORLINECALCULATION NC_("STR_COMPAT_OPT_IGNORETABSANDBLANKSFORLINECALCULATION", "Make whitespace character height not affect line height")
|
||||
#define STR_COMPAT_OPT_UNDERLINETRAILINGSPACE NC_("STR_COMPAT_OPT_UNDERLINETRAILINGSPACE", "Underline Word-compatible trailing blanks")
|
||||
|
||||
#define STR_TABLE_PANEL_ALIGN_AUTO NC_("sidebartableedit|alignautolabel", "Automatic")
|
||||
#define STR_TABLE_PANEL_ALIGN_LEFT NC_("sidebartableedit|alignleftlabel", "Left")
|
||||
|
@@ -471,6 +471,8 @@ public:
|
||||
|
||||
SW_DLLPUBLIC void SetIgnoreTabsAndBlanksForLineCalculation(bool bIgnoreTabsAndBlanksForLineCalculation);
|
||||
|
||||
SW_DLLPUBLIC void SetMsWordUlTrailSpace(bool val);
|
||||
|
||||
// DOCUMENT COMPATIBILITY FLAGS END
|
||||
|
||||
// Calls Idle-formatter of Layout.
|
||||
|
55
sw/qa/extras/odfexport/data/UnderlineTrailingSpace.fodt
Normal file
55
sw/qa/extras/odfexport/data/UnderlineTrailingSpace.fodt
Normal file
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<office:document 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:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" office:version="1.4" office:mimetype="application/vnd.oasis.opendocument.text">
|
||||
<office:settings>
|
||||
<config:config-item-set config:name="ooo:configuration-settings">
|
||||
<config:config-item config:name="MsWordCompTrailingBlanks" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="MsWordUlTrailSpace" config:type="boolean">true</config:config-item>
|
||||
</config:config-item-set>
|
||||
</office:settings>
|
||||
<office:font-face-decls>
|
||||
<style:font-face style:name="Liberation Sans" svg:font-family="'Liberation Sans'" style:font-family-generic="swiss" style:font-pitch="variable"/>
|
||||
</office:font-face-decls>
|
||||
<office:styles>
|
||||
<style:default-style style:family="paragraph">
|
||||
<style:paragraph-properties fo:hyphenation-ladder-count="no-limit" fo:hyphenation-keep="auto" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:writing-mode="page"/>
|
||||
<style:text-properties style:use-window-font-color="true" style:font-name="Liberation Sans" fo:font-size="10.5pt" fo:language="zxx" fo:country="none" style:letter-kerning="true" style:font-name-asian="Liberation Sans" style:font-size-asian="10.5pt" style:language-asian="zxx" style:country-asian="none" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/>
|
||||
</style:default-style>
|
||||
<style:style style:name="Standard" style:family="paragraph" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0" fo:margin-bottom="0" style:contextual-spacing="false" fo:text-align="justify" style:justify-single-word="false" style:writing-mode="lr-tb"/>
|
||||
</style:style>
|
||||
<style:style style:name="MyListLabel" style:family="text">
|
||||
<style:text-properties style:font-name="Liberation Sans"/>
|
||||
</style:style>
|
||||
<text:list-style style:name="MyListStyle">
|
||||
<text:list-level-style-bullet text:level="1" text:style-name="MyListLabel" style:num-suffix="•" text:bullet-char="•">
|
||||
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
|
||||
<style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-7mm" fo:margin-left="7mm"/>
|
||||
</style:list-level-properties>
|
||||
<style:text-properties fo:font-name="Liberation Sans"/>
|
||||
</text:list-level-style-bullet>
|
||||
</text:list-style>
|
||||
</office:styles>
|
||||
<office:automatic-styles>
|
||||
<style:style style:name="T1" style:family="text">
|
||||
<style:text-properties style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color"/>
|
||||
</style:style>
|
||||
<style:page-layout style:name="pm1">
|
||||
<style:page-layout-properties fo:page-width="210mm" fo:page-height="297mm" fo:margin-top="1in" fo:margin-bottom="1in" fo:margin-left="1.25in" fo:margin-right="1.25in" style:writing-mode="lr-tb"/>
|
||||
</style:page-layout>
|
||||
</office:automatic-styles>
|
||||
<office:master-styles>
|
||||
<style:master-page style:name="Standard" style:page-layout-name="pm1"/>
|
||||
</office:master-styles>
|
||||
<office:body>
|
||||
<office:text>
|
||||
<text:list text:style-name="MyListStyle">
|
||||
<text:list-item>
|
||||
<text:p>下划线 <text:span text:style-name="T1"><text:s text:c="70"/></text:span></text:p>
|
||||
</text:list-item>
|
||||
</text:list>
|
||||
<text:p><text:span text:style-name="T1"><text:s text:c="10"/></text:span></text:p>
|
||||
<text:p><text:span text:style-name="T1"><text:s text:c="1000"/></text:span></text:p>
|
||||
</office:text>
|
||||
</office:body>
|
||||
</office:document>
|
@@ -42,6 +42,7 @@
|
||||
#include <unotxdoc.hxx>
|
||||
#include <docsh.hxx>
|
||||
#include <IDocumentFieldsAccess.hxx>
|
||||
#include <IDocumentLayoutAccess.hxx>
|
||||
#include <IDocumentLinksAdministration.hxx>
|
||||
#include <sfx2/linkmgr.hxx>
|
||||
|
||||
@@ -1919,6 +1920,110 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf163913)
|
||||
"margin-right", u"6em");
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_FIXTURE(Test, testMsWordUlTrailSpace)
|
||||
{
|
||||
// Testing MsWordUlTrailSpace compat option
|
||||
|
||||
// Given a document with both MsWordCompTrailingBlanks and MsWordUlTrailSpace set
|
||||
createSwDoc("UnderlineTrailingSpace.fodt");
|
||||
// 1. Make sure that the import sets MsWordUlTrailSpace option, and creates correct layout
|
||||
{
|
||||
uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY_THROW);
|
||||
uno::Reference<beans::XPropertySet> xSettings(
|
||||
xFactory->createInstance(u"com.sun.star.document.Settings"_ustr), uno::UNO_QUERY_THROW);
|
||||
CPPUNIT_ASSERT_EQUAL(uno::Any(true),
|
||||
xSettings->getPropertyValue(u"MsWordUlTrailSpace"_ustr));
|
||||
|
||||
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
||||
OUString val;
|
||||
// Line 1: one SwHolePortion, showing underline
|
||||
val = getXPath(pXmlDoc, "//body/txt[1]/SwParaPortion/SwLineLayout/SwHolePortion", "length");
|
||||
CPPUNIT_ASSERT_GREATEREQUAL(sal_Int32(69), val.toInt32()); // In truth, it should be 70
|
||||
val = getXPath(pXmlDoc, "//body/txt[1]/SwParaPortion/SwLineLayout/SwHolePortion",
|
||||
"show-underline");
|
||||
CPPUNIT_ASSERT_EQUAL(u"true"_ustr, val);
|
||||
// TODO: Line 2
|
||||
// Line 3: two SwHolePortion, one for shown underline, one for the rest
|
||||
val = getXPath(pXmlDoc, "//body/txt[3]/SwParaPortion/SwLineLayout/SwHolePortion[1]",
|
||||
"length");
|
||||
CPPUNIT_ASSERT_GREATEREQUAL(sal_Int32(140), val.toInt32());
|
||||
val = getXPath(pXmlDoc, "//body/txt[3]/SwParaPortion/SwLineLayout/SwHolePortion[1]",
|
||||
"show-underline");
|
||||
CPPUNIT_ASSERT_EQUAL(u"true"_ustr, val);
|
||||
val = getXPath(pXmlDoc, "//body/txt[3]/SwParaPortion/SwLineLayout/SwHolePortion[2]",
|
||||
"length");
|
||||
CPPUNIT_ASSERT_GREATEREQUAL(sal_Int32(850), val.toInt32());
|
||||
val = getXPath(pXmlDoc, "//body/txt[3]/SwParaPortion/SwLineLayout/SwHolePortion[2]",
|
||||
"show-underline");
|
||||
CPPUNIT_ASSERT_EQUAL(u"false"_ustr, val);
|
||||
}
|
||||
|
||||
saveAndReload(mpFilter);
|
||||
// 2. Make sure that exported document has MsWordUlTrailSpace option set
|
||||
{
|
||||
xmlDocUniquePtr pXmlDoc = parseExport(u"settings.xml"_ustr);
|
||||
assertXPathContent(pXmlDoc, "//config:config-item[@config:name='MsWordUlTrailSpace']",
|
||||
u"true");
|
||||
|
||||
uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY_THROW);
|
||||
uno::Reference<beans::XPropertySet> xSettings(
|
||||
xFactory->createInstance(u"com.sun.star.document.Settings"_ustr), uno::UNO_QUERY_THROW);
|
||||
CPPUNIT_ASSERT_EQUAL(uno::Any(true),
|
||||
xSettings->getPropertyValue(u"MsWordUlTrailSpace"_ustr));
|
||||
}
|
||||
|
||||
// 3. Disable the option, and check the layout
|
||||
{
|
||||
uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY_THROW);
|
||||
uno::Reference<beans::XPropertySet> xSettings(
|
||||
xFactory->createInstance(u"com.sun.star.document.Settings"_ustr), uno::UNO_QUERY_THROW);
|
||||
xSettings->setPropertyValue(u"MsWordUlTrailSpace"_ustr, uno::Any(false));
|
||||
CPPUNIT_ASSERT_EQUAL(uno::Any(false),
|
||||
xSettings->getPropertyValue(u"MsWordUlTrailSpace"_ustr));
|
||||
|
||||
getSwDoc()->getIDocumentLayoutAccess().GetCurrentViewShell()->Reformat();
|
||||
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
||||
OUString val;
|
||||
// Line 1: one SwHolePortion, not showing underline
|
||||
val = getXPath(pXmlDoc, "//body/txt[1]/SwParaPortion/SwLineLayout/SwHolePortion", "length");
|
||||
CPPUNIT_ASSERT_GREATEREQUAL(sal_Int32(69), val.toInt32()); // In truth, it should be 70
|
||||
val = getXPath(pXmlDoc, "//body/txt[1]/SwParaPortion/SwLineLayout/SwHolePortion",
|
||||
"show-underline");
|
||||
CPPUNIT_ASSERT_EQUAL(u"false"_ustr, val);
|
||||
// TODO: Line 2
|
||||
// Line 3: one SwHolePortion, not showing underline
|
||||
val = getXPath(pXmlDoc, "//body/txt[3]/SwParaPortion/SwLineLayout/SwHolePortion", "length");
|
||||
CPPUNIT_ASSERT_GREATEREQUAL(sal_Int32(999), val.toInt32());
|
||||
val = getXPath(pXmlDoc, "//body/txt[3]/SwParaPortion/SwLineLayout/SwHolePortion",
|
||||
"show-underline");
|
||||
CPPUNIT_ASSERT_EQUAL(u"false"_ustr, val);
|
||||
}
|
||||
|
||||
saveAndReload(mpFilter);
|
||||
// 4. Make sure that exported document has MsWordUlTrailSpace option not set
|
||||
{
|
||||
xmlDocUniquePtr pXmlDoc = parseExport(u"settings.xml"_ustr);
|
||||
assertXPathContent(pXmlDoc, "//config:config-item[@config:name='MsWordUlTrailSpace']",
|
||||
u"false");
|
||||
|
||||
uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY_THROW);
|
||||
uno::Reference<beans::XPropertySet> xSettings(
|
||||
xFactory->createInstance(u"com.sun.star.document.Settings"_ustr), uno::UNO_QUERY_THROW);
|
||||
CPPUNIT_ASSERT_EQUAL(uno::Any(false),
|
||||
xSettings->getPropertyValue(u"MsWordUlTrailSpace"_ustr));
|
||||
}
|
||||
|
||||
createSwDoc();
|
||||
// 5. Make sure that a new Writer document has this setting set to false
|
||||
{
|
||||
uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY_THROW);
|
||||
uno::Reference<beans::XPropertySet> xSettings(
|
||||
xFactory->createInstance(u"com.sun.star.document.Settings"_ustr), uno::UNO_QUERY_THROW);
|
||||
CPPUNIT_ASSERT_EQUAL(uno::Any(false),
|
||||
xSettings->getPropertyValue(u"MsWordUlTrailSpace"_ustr));
|
||||
}
|
||||
}
|
||||
|
||||
} // end of anonymous namespace
|
||||
CPPUNIT_PLUGIN_IMPLEMENT();
|
||||
|
||||
|
@@ -279,6 +279,7 @@ bool sw::DocumentSettingManager::get(/*[in]*/ DocumentSettingId id) const
|
||||
case DocumentSettingId::MIN_ROW_HEIGHT_INCL_BORDER: return mbMinRowHeightInclBorder;
|
||||
case DocumentSettingId::MS_WORD_COMP_GRID_METRICS: return mbMsWordCompGridMetrics;
|
||||
case DocumentSettingId::NO_CLIPPING_WITH_WRAP_POLYGON: return mbNoClippingWithWrapPolygon;
|
||||
case DocumentSettingId::MS_WORD_UL_TRAIL_SPACE: return mbMsWordUlTrailSpace;
|
||||
default:
|
||||
OSL_FAIL("Invalid setting id");
|
||||
}
|
||||
@@ -610,6 +611,9 @@ void sw::DocumentSettingManager::set(/*[in]*/ DocumentSettingId id, /*[in]*/ boo
|
||||
case DocumentSettingId::NO_CLIPPING_WITH_WRAP_POLYGON:
|
||||
mbNoClippingWithWrapPolygon = value;
|
||||
break;
|
||||
case DocumentSettingId::MS_WORD_UL_TRAIL_SPACE:
|
||||
mbMsWordUlTrailSpace = value;
|
||||
break;
|
||||
default:
|
||||
OSL_FAIL("Invalid setting id");
|
||||
}
|
||||
@@ -791,6 +795,7 @@ void sw::DocumentSettingManager::ReplaceCompatibilityOptions(const DocumentSetti
|
||||
mbUseVariableWidthNBSP = rSource.mbUseVariableWidthNBSP;
|
||||
mbMsWordCompGridMetrics = rSource.mbMsWordCompGridMetrics;
|
||||
mbNoClippingWithWrapPolygon = rSource.mbNoClippingWithWrapPolygon;
|
||||
mbMsWordUlTrailSpace = rSource.mbMsWordUlTrailSpace;
|
||||
}
|
||||
|
||||
sal_uInt32 sw::DocumentSettingManager::Getn32DummyCompatibilityOptions1() const
|
||||
@@ -1187,6 +1192,11 @@ void sw::DocumentSettingManager::dumpAsXml(xmlTextWriterPtr pWriter) const
|
||||
BAD_CAST(OString::boolean(mbNoClippingWithWrapPolygon).getStr()));
|
||||
(void)xmlTextWriterEndElement(pWriter);
|
||||
|
||||
(void)xmlTextWriterStartElement(pWriter, BAD_CAST("mbMsWordUlTrailSpace"));
|
||||
(void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"),
|
||||
BAD_CAST(OString::boolean(mbMsWordUlTrailSpace).getStr()));
|
||||
(void)xmlTextWriterEndElement(pWriter);
|
||||
|
||||
(void)xmlTextWriterEndElement(pWriter);
|
||||
}
|
||||
|
||||
|
@@ -190,6 +190,7 @@ class DocumentSettingManager final :
|
||||
bool mbMinRowHeightInclBorder : 1; // tdf#155229
|
||||
bool mbMsWordCompGridMetrics : 1; // tdf#129808
|
||||
bool mbNoClippingWithWrapPolygon : 1; // tdf#161233
|
||||
bool mbMsWordUlTrailSpace : 1 = false;
|
||||
|
||||
public:
|
||||
|
||||
|
@@ -176,13 +176,7 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, SwTextFormatInfo &rInf,
|
||||
|
||||
const SwScriptInfo& rSI = rInf.GetParaPortion()->GetScriptInfo();
|
||||
|
||||
sal_uInt16 nMaxComp = ( SwFontScript::CJK == rInf.GetFont()->GetActual() ) &&
|
||||
rSI.CountCompChg() &&
|
||||
! rInf.IsMulti() &&
|
||||
! rPor.InFieldGrp() &&
|
||||
! rPor.IsDropPortion() ?
|
||||
10000 :
|
||||
0 ;
|
||||
const sal_uInt16 nMaxComp = rPor.GetMaxComp(rInf);
|
||||
|
||||
SwTwips nLineWidth = rInf.GetLineWidth();
|
||||
TextFrameIndex nMaxLen = TextFrameIndex(rInf.GetText().getLength()) - rInf.GetIdx();
|
||||
|
@@ -36,6 +36,7 @@
|
||||
#include <IMark.hxx>
|
||||
#include <pam.hxx>
|
||||
#include <doc.hxx>
|
||||
#include <o3tl/temporary.hxx>
|
||||
#include <xmloff/odffields.hxx>
|
||||
#include <viewopt.hxx>
|
||||
|
||||
@@ -227,6 +228,35 @@ static TextFrameIndex lcl_AddSpace_Latin(const SwTextSizeInfo& rInf, const OUStr
|
||||
return nCnt;
|
||||
}
|
||||
|
||||
static void GetLimitedStringPart(const SwTextFormatInfo& rInf, TextFrameIndex nIndex,
|
||||
TextFrameIndex nLength, sal_uInt16 nComp, SwTwips nOriginalWidth,
|
||||
SwTwips nMaxWidth, TextFrameIndex& rOutLength, SwTwips& rOutWidth)
|
||||
{
|
||||
assert(nMaxWidth >= 0);
|
||||
assert(nLength >= TextFrameIndex(0));
|
||||
const SwScriptInfo& rSI = rInf.GetParaPortion()->GetScriptInfo();
|
||||
rOutLength = nLength;
|
||||
rOutWidth = nOriginalWidth;
|
||||
while (rOutWidth > nMaxWidth)
|
||||
{
|
||||
TextFrameIndex nNewOnLineLengthGuess(rOutLength.get() * nMaxWidth / rOutWidth);
|
||||
assert(nNewOnLineLengthGuess < rOutLength);
|
||||
if (nNewOnLineLengthGuess < (rOutLength - TextFrameIndex(1)))
|
||||
++nNewOnLineLengthGuess; // to avoid too aggressive decrease
|
||||
rOutLength = nNewOnLineLengthGuess;
|
||||
rInf.GetTextSize(&rSI, nIndex, rOutLength, std::nullopt, nComp, rOutWidth,
|
||||
o3tl::temporary(tools::Long()), o3tl::temporary(SwTwips()),
|
||||
o3tl::temporary(SwTwips()), rInf.GetCachedVclData().get());
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsMsWordUlTrailSpace(const SwTextFormatInfo& rInf)
|
||||
{
|
||||
const auto& settings = rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess();
|
||||
return settings.get(DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS)
|
||||
&& settings.get(DocumentSettingId::MS_WORD_UL_TRAIL_SPACE);
|
||||
}
|
||||
|
||||
SwTextPortion * SwTextPortion::CopyLinePortion(const SwLinePortion &rPortion)
|
||||
{
|
||||
SwTextPortion *const pNew(new SwTextPortion);
|
||||
@@ -298,6 +328,15 @@ static bool lcl_HasContent( const SwFieldPortion& rField, SwTextFormatInfo const
|
||||
return rField.GetExpText( rInf, aText ) && !aText.isEmpty();
|
||||
}
|
||||
|
||||
sal_uInt16 SwTextPortion::GetMaxComp(const SwTextFormatInfo& rInf) const
|
||||
{
|
||||
const SwScriptInfo& rSI = rInf.GetParaPortion()->GetScriptInfo();
|
||||
return (SwFontScript::CJK == rInf.GetFont()->GetActual()) && rSI.CountCompChg()
|
||||
&& !rInf.IsMulti() && !InFieldGrp() && !IsDropPortion()
|
||||
? 10000
|
||||
: 0;
|
||||
}
|
||||
|
||||
bool SwTextPortion::Format_( SwTextFormatInfo &rInf )
|
||||
{
|
||||
// 5744: If only the hyphen does not fit anymore, we still need to wrap
|
||||
@@ -477,12 +516,37 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf )
|
||||
TextFrameIndex const nRealStart = pGuess->BreakStart() - pGuess->FieldDiff();
|
||||
if( pGuess->BreakPos() < nRealStart && !InExpGrp() )
|
||||
{
|
||||
SwHolePortion *pNew = new SwHolePortion( *this );
|
||||
pNew->SetLen( nRealStart - pGuess->BreakPos() );
|
||||
pNew->Width(0);
|
||||
pNew->ExtraBlankWidth( pGuess->ExtraBlankWidth() );
|
||||
TextFrameIndex nTotalExtraLen(nRealStart - pGuess->BreakPos());
|
||||
TextFrameIndex nExtraLen(nTotalExtraLen);
|
||||
TextFrameIndex nExtraLenOutOfLine(0);
|
||||
SwTwips nTotalExtraWidth(pGuess->ExtraBlankWidth());
|
||||
SwTwips nExtraWidth(nTotalExtraWidth);
|
||||
SwTwips nExtraWidthOutOfLine(0);
|
||||
SwTwips nAvailableLineWidth(rInf.GetLineWidth() - Width());
|
||||
const bool bMsWordUlTrailSpace(IsMsWordUlTrailSpace(rInf));
|
||||
if (nExtraWidth > nAvailableLineWidth && bMsWordUlTrailSpace)
|
||||
{
|
||||
GetLimitedStringPart(rInf, pGuess->BreakPos(), nTotalExtraLen, GetMaxComp(rInf),
|
||||
nTotalExtraWidth, nAvailableLineWidth, nExtraLen,
|
||||
nExtraWidth);
|
||||
nExtraLenOutOfLine = nTotalExtraLen - nExtraLen;
|
||||
nExtraWidthOutOfLine = nTotalExtraWidth - nExtraWidth;
|
||||
}
|
||||
|
||||
SwHolePortion* pNew = new SwHolePortion(*this, bMsWordUlTrailSpace);
|
||||
pNew->SetLen(nExtraLen);
|
||||
pNew->ExtraBlankWidth(nExtraWidth);
|
||||
Insert( pNew );
|
||||
|
||||
if (nExtraWidthOutOfLine)
|
||||
{
|
||||
// Out-of-line hole portion - will not show underline
|
||||
SwHolePortion* pNewOutOfLine = new SwHolePortion(*this, false);
|
||||
pNewOutOfLine->SetLen(nExtraLenOutOfLine);
|
||||
pNewOutOfLine->ExtraBlankWidth(nExtraWidthOutOfLine);
|
||||
pNew->Insert(pNewOutOfLine);
|
||||
}
|
||||
|
||||
// UAX #14 Unicode Line Breaking Algorithm Non-tailorable Line breaking rule LB6:
|
||||
// https://www.unicode.org/reports/tr14/#LB6 Do not break before hard line breaks
|
||||
if (auto ch = rInf.GetChar(pGuess->BreakStart()); !ch || ch == CH_BREAK)
|
||||
@@ -828,8 +892,9 @@ SwPositiveSize SwTextInputFieldPortion::GetTextSize( const SwTextSizeInfo &rInf
|
||||
return rInf.GetTextSize();
|
||||
}
|
||||
|
||||
SwHolePortion::SwHolePortion( const SwTextPortion &rPor )
|
||||
SwHolePortion::SwHolePortion(const SwTextPortion& rPor, bool bShowUnderline)
|
||||
: m_nBlankWidth( 0 )
|
||||
, m_bShowUnderline(bShowUnderline)
|
||||
{
|
||||
SetLen( TextFrameIndex(1) );
|
||||
Height( rPor.Height() );
|
||||
@@ -871,12 +936,13 @@ void SwHolePortion::Paint( const SwTextPaintInfo &rInf ) const
|
||||
const SwFont* pOrigFont = rInf.GetFont();
|
||||
std::unique_ptr<SwFont> pHoleFont;
|
||||
std::optional<SwFontSave> oFontSave;
|
||||
if( pOrigFont->GetUnderline() != LINESTYLE_NONE
|
||||
if( (!m_bShowUnderline && pOrigFont->GetUnderline() != LINESTYLE_NONE)
|
||||
|| pOrigFont->GetOverline() != LINESTYLE_NONE
|
||||
|| pOrigFont->GetStrikeout() != STRIKEOUT_NONE )
|
||||
{
|
||||
pHoleFont.reset(new SwFont( *pOrigFont ));
|
||||
pHoleFont->SetUnderline( LINESTYLE_NONE );
|
||||
if (!m_bShowUnderline)
|
||||
pHoleFont->SetUnderline(LINESTYLE_NONE);
|
||||
pHoleFont->SetOverline( LINESTYLE_NONE );
|
||||
pHoleFont->SetStrikeout( STRIKEOUT_NONE );
|
||||
oFontSave.emplace( rInf, pHoleFont.get() );
|
||||
@@ -916,6 +982,9 @@ void SwHolePortion::dumpAsXml(xmlTextWriterPtr pWriter, const OUString& rText, T
|
||||
(void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("blank-width"),
|
||||
BAD_CAST(OString::number(m_nBlankWidth).getStr()));
|
||||
|
||||
(void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("show-underline"),
|
||||
BAD_CAST(OString::boolean(m_bShowUnderline).getStr()));
|
||||
|
||||
(void)xmlTextWriterEndElement(pWriter);
|
||||
}
|
||||
|
||||
|
@@ -47,6 +47,8 @@ public:
|
||||
|
||||
// Accessibility: pass information about this portion to the PortionHandler
|
||||
virtual void HandlePortion( SwPortionHandler& rPH ) const override;
|
||||
|
||||
sal_uInt16 GetMaxComp(const SwTextFormatInfo &rInf) const;
|
||||
};
|
||||
|
||||
class SwTextInputFieldPortion : public SwTextPortion
|
||||
@@ -63,8 +65,10 @@ public:
|
||||
class SwHolePortion : public SwLinePortion
|
||||
{
|
||||
SwTwips m_nBlankWidth;
|
||||
bool m_bShowUnderline;
|
||||
|
||||
public:
|
||||
explicit SwHolePortion( const SwTextPortion &rPor );
|
||||
explicit SwHolePortion(const SwTextPortion& rPor, bool bShowUnderline = false);
|
||||
SwTwips GetBlankWidth() const { return m_nBlankWidth; }
|
||||
void SetBlankWidth(const SwTwips nNew) { m_nBlankWidth = nNew; }
|
||||
virtual SwLinePortion *Compress() override;
|
||||
|
@@ -1154,6 +1154,18 @@ void SwViewShell::SetIgnoreTabsAndBlanksForLineCalculation(bool val)
|
||||
}
|
||||
}
|
||||
|
||||
void SwViewShell::SetMsWordUlTrailSpace(bool val)
|
||||
{
|
||||
IDocumentSettingAccess& rIDSA = getIDocumentSettingAccess();
|
||||
if (rIDSA.get(DocumentSettingId::MS_WORD_UL_TRAIL_SPACE) != val)
|
||||
{
|
||||
SwWait aWait(*GetDoc()->GetDocShell(), true);
|
||||
rIDSA.set(DocumentSettingId::MS_WORD_UL_TRAIL_SPACE, val);
|
||||
const SwInvalidateFlags nInv = SwInvalidateFlags::Size;
|
||||
lcl_InvalidateAllContent(*this, nInv);
|
||||
}
|
||||
}
|
||||
|
||||
void SwViewShell::Reformat()
|
||||
{
|
||||
SwWait aWait( *GetDoc()->GetDocShell(), true );
|
||||
|
@@ -66,6 +66,7 @@ constexpr std::pair<OUString, TranslateId> options_list[]{
|
||||
{ u"ContinuousEndnotes"_ustr, STR_COMPAT_OPT_CONTINUOUS_ENDNOTES },
|
||||
{ u"MsWordCompGridMetrics"_ustr, STR_COMPAT_OPT_MSWORDCOMPGRIDMETRICS },
|
||||
{ u"IgnoreTabsAndBlanksForLineCalculation"_ustr, STR_COMPAT_OPT_IGNORETABSANDBLANKSFORLINECALCULATION },
|
||||
{ u"MsWordUlTrailSpace"_ustr, STR_COMPAT_OPT_UNDERLINETRAILINGSPACE },
|
||||
};
|
||||
|
||||
// DocumentSettingId, negate?
|
||||
@@ -95,6 +96,7 @@ std::pair<DocumentSettingId, bool> DocumentSettingForOption(const OUString& opti
|
||||
// { u"AddTableLineSpacing"_ustr, { DocumentSettingId::ADD_PARA_LINE_SPACING_TO_TABLE_CELLS, false } },
|
||||
{ u"MsWordCompGridMetrics"_ustr, { DocumentSettingId::MS_WORD_COMP_GRID_METRICS, false } },
|
||||
{ u"IgnoreTabsAndBlanksForLineCalculation"_ustr, { DocumentSettingId::IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION, false } },
|
||||
{ u"MsWordUlTrailSpace"_ustr, { DocumentSettingId::MS_WORD_UL_TRAIL_SPACE, false } },
|
||||
};
|
||||
return map.at(option);
|
||||
}
|
||||
@@ -342,6 +344,10 @@ bool SwCompatibilityOptPage::FillItemSet( SfxItemSet* )
|
||||
m_pWrtShell->SetIgnoreTabsAndBlanksForLineCalculation(bChecked);
|
||||
break;
|
||||
|
||||
case DocumentSettingId::MS_WORD_UL_TRAIL_SPACE:
|
||||
m_pWrtShell->SetMsWordUlTrailSpace(bChecked);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@@ -167,6 +167,7 @@ enum SwDocumentSettingsPropertyHandles
|
||||
HANDLE_MIN_ROW_HEIGHT_INCL_BORDER,
|
||||
HANDLE_MS_WORD_COMP_GRID_METRICS,
|
||||
HANDLE_NO_CLIPPING_WITH_WRAP_POLYGON,
|
||||
HANDLE_MS_WORD_UL_TRAIL_SPACE,
|
||||
};
|
||||
|
||||
}
|
||||
@@ -280,6 +281,7 @@ static rtl::Reference<MasterPropertySetInfo> lcl_createSettingsInfo()
|
||||
{ u"MinRowHeightInclBorder"_ustr, HANDLE_MIN_ROW_HEIGHT_INCL_BORDER, cppu::UnoType<bool>::get(), 0 },
|
||||
{ u"MsWordCompGridMetrics"_ustr, HANDLE_MS_WORD_COMP_GRID_METRICS, cppu::UnoType<bool>::get(), 0 },
|
||||
{ u"NoClippingWithWrapPolygon"_ustr, HANDLE_NO_CLIPPING_WITH_WRAP_POLYGON, cppu::UnoType<bool>::get(), 0 },
|
||||
{ u"MsWordUlTrailSpace"_ustr, HANDLE_MS_WORD_UL_TRAIL_SPACE, cppu::UnoType<bool>::get(), 0 },
|
||||
|
||||
/*
|
||||
* As OS said, we don't have a view when we need to set this, so I have to
|
||||
@@ -1207,13 +1209,19 @@ void SwXDocumentSettings::_setSingleValue( const comphelper::PropertyInfo & rInf
|
||||
}
|
||||
break;
|
||||
case HANDLE_NO_CLIPPING_WITH_WRAP_POLYGON:
|
||||
bool bTmp;
|
||||
if (rValue >>= bTmp)
|
||||
if (bool bTmp; rValue >>= bTmp)
|
||||
{
|
||||
mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::NO_CLIPPING_WITH_WRAP_POLYGON,
|
||||
bTmp);
|
||||
}
|
||||
break;
|
||||
case HANDLE_MS_WORD_UL_TRAIL_SPACE:
|
||||
if (bool bTmp; rValue >>= bTmp)
|
||||
{
|
||||
mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::MS_WORD_UL_TRAIL_SPACE,
|
||||
bTmp);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw UnknownPropertyException(OUString::number(rInfo.mnHandle));
|
||||
}
|
||||
@@ -1825,6 +1833,12 @@ void SwXDocumentSettings::_getSingleValue( const comphelper::PropertyInfo & rInf
|
||||
DocumentSettingId::NO_CLIPPING_WITH_WRAP_POLYGON);
|
||||
}
|
||||
break;
|
||||
case HANDLE_MS_WORD_UL_TRAIL_SPACE:
|
||||
{
|
||||
rValue <<= mpDoc->getIDocumentSettingAccess().get(
|
||||
DocumentSettingId::MS_WORD_UL_TRAIL_SPACE);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw UnknownPropertyException(OUString::number(rInfo.mnHandle));
|
||||
}
|
||||
|
Reference in New Issue
Block a user