tdf#133524 AutoCorrect: fix Romanian nested quotations
typing " inside primary quotation marks: use
the correct order of the double angle quotes:
„... «quote» ...”
Add also Aragonese, Asturian and Catalan to the
"<<" and ">>" replacement.
See commit 57f07b1d7378d218648667c5b1315cc8ad905875
(tdf#133524 AutoCorrect: support double angle quotes).
Change-Id: I2e80cc45768eefa3eb62b446ca822ee6c46f7242
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/97970
Tested-by: Jenkins
Reviewed-by: László Németh <nemeth@numbertext.org>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/98140
Reviewed-by: Adolfo Jayme Barrientos <fitojb@ubuntu.com>
diff --git a/editeng/source/misc/svxacorr.cxx b/editeng/source/misc/svxacorr.cxx
index f991370..217143f 100644
--- a/editeng/source/misc/svxacorr.cxx
+++ b/editeng/source/misc/svxacorr.cxx
@@ -318,8 +318,10 @@ static constexpr sal_Unicode cLeftSingleAngleQuote = 0x2039;
static constexpr sal_Unicode cRightSingleAngleQuote = 0x203A;
// stop characters for searching preceding quotes
// (the first character is also the opening quote we are looking for)
const sal_Unicode aStopDoubleAngleQuoteStart[] = { 0x201E, 0x201D, 0 }; // preceding ,,
const sal_Unicode aStopDoubleAngleQuoteStart[] = { 0x201E, 0x201D, 0x201C, 0 }; // preceding ,,
const sal_Unicode aStopDoubleAngleQuoteEnd[] = { cRightDoubleAngleQuote, cLeftDoubleAngleQuote, 0x201D, 0x201E, 0 }; // preceding >>
// preceding << for Romanian, handle also alternative primary closing quotation mark U+201C
const sal_Unicode aStopDoubleAngleQuoteEndRo[] = { cLeftDoubleAngleQuote, cRightDoubleAngleQuote, 0x201D, 0x201E, 0x201C, 0 };
const sal_Unicode aStopSingleQuoteEnd[] = { 0x201A, 0x2018, 0x201C, 0x201E, 0 };
const sal_Unicode aStopSingleQuoteEndRuUa[] = { 0x201E, 0x201C, cRightDoubleAngleQuote, cLeftDoubleAngleQuote, 0 };
@@ -1212,7 +1214,12 @@ void SvxAutoCorrect::InsertQuote( SvxAutoCorrDoc& rDoc, sal_Int32 nInsPos,
if ( eType == ACQuotes::DoubleAngleQuote )
{
bool bSwiss = eLang == LANGUAGE_FRENCH_SWISS;
cRet = ( '<' == cInsChar || ('\"' == cInsChar && !bSttQuote) )
// pressing " inside a quotation -> use second level angle quotes
bool bLeftQuote = '\"' == cInsChar &&
// start position and Romanian OR
// not start position and Hungarian
bSttQuote == (eLang != LANGUAGE_HUNGARIAN);
cRet = ( '<' == cInsChar || bLeftQuote )
? ( bSwiss ? cLeftSingleAngleQuote : cLeftDoubleAngleQuote )
: ( bSwiss ? cRightSingleAngleQuote : cRightDoubleAngleQuote );
}
@@ -1348,13 +1355,23 @@ void SvxAutoCorrect::DoAutoCorrect( SvxAutoCorrDoc& rDoc, const OUString& rTxt,
{
eType = ACQuotes::CapitalizeIAm;
}
// tdf#133524 support << and >> in Hungarian and Romanian
else if ( !bSingle && nInsPos && eLang.anyOf( LANGUAGE_HUNGARIAN, LANGUAGE_ROMANIAN ) &&
lcl_HasPrecedingChar( rTxt, nInsPos,
// tdf#133524 support >>Hungarian<< and <<Romanian>> secondary level quotations
else if ( !bSingle && nInsPos &&
( ( eLang == LANGUAGE_HUNGARIAN &&
lcl_HasPrecedingChar( rTxt, nInsPos,
bSttQuote ? aStopDoubleAngleQuoteStart[0] : aStopDoubleAngleQuoteEnd[0],
bSttQuote ? aStopDoubleAngleQuoteStart + 1 : aStopDoubleAngleQuoteEnd + 1 ) )
bSttQuote ? aStopDoubleAngleQuoteStart + 1 : aStopDoubleAngleQuoteEnd + 1 ) ) ||
( eLang.anyOf(
LANGUAGE_ROMANIAN,
LANGUAGE_ROMANIAN_MOLDOVA ) &&
lcl_HasPrecedingChar( rTxt, nInsPos,
bSttQuote ? aStopDoubleAngleQuoteStart[0] : aStopDoubleAngleQuoteEndRo[0],
bSttQuote ? aStopDoubleAngleQuoteStart + 1 : aStopDoubleAngleQuoteEndRo + 1 ) ) ) )
{
eType = ACQuotes::DoubleAngleQuote;
LocaleDataWrapper& rLcl = GetLocaleDataWrapper( eLang );
// only if the opening double quotation mark is the default one
if ( rLcl.getDoubleQuotationMarkStart() == OUStringChar(aStopDoubleAngleQuoteStart[0]) )
eType = ACQuotes::DoubleAngleQuote;
}
else if ( bSingle && nInsPos && !bSttQuote &&
// tdf#128860 use apostrophe outside of second level quotation in Czech, German, Icelandic,
@@ -1403,9 +1420,11 @@ void SvxAutoCorrect::DoAutoCorrect( SvxAutoCorrDoc& rDoc, const OUString& rTxt,
{
const LanguageType eLang = GetDocLanguage( rDoc, nInsPos );
if ( eLang.anyOf(
LANGUAGE_CATALAN, // primary level
LANGUAGE_CATALAN_VALENCIAN, // primary level
LANGUAGE_FINNISH, // alternative primary level
LANGUAGE_FRENCH_SWISS, // second level
LANGUAGE_GALICIAN,
LANGUAGE_GALICIAN, // primary level
LANGUAGE_HUNGARIAN, // second level
LANGUAGE_POLISH, // second level
LANGUAGE_PORTUGUESE, // primary level
@@ -1414,7 +1433,9 @@ void SvxAutoCorrect::DoAutoCorrect( SvxAutoCorrDoc& rDoc, const OUString& rTxt,
LANGUAGE_ROMANIAN_MOLDOVA, // second level
LANGUAGE_SWEDISH, // alternative primary level
LANGUAGE_SWEDISH_FINLAND, // alternative primary level
LANGUAGE_UKRAINIAN ) || // primary level
LANGUAGE_UKRAINIAN, // primary level
LANGUAGE_USER_ARAGONESE, // primary level
LANGUAGE_USER_ASTURIAN ) || // primary level
primary(eLang) == primary(LANGUAGE_GERMAN) || // alternative primary level
primary(eLang) == primary(LANGUAGE_SPANISH) ) // primary level
{
diff --git a/sw/qa/extras/uiwriter/data/tdf133524_ro.fodt b/sw/qa/extras/uiwriter/data/tdf133524_ro.fodt
new file mode 100644
index 0000000..591db1f
--- /dev/null
+++ b/sw/qa/extras/uiwriter/data/tdf133524_ro.fodt
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text">
<office:styles>
<style:style style:name="Standard" style:family="paragraph" style:class="text"/>
<style:default-style style:family="paragraph">
<style:text-properties fo:language="ro" fo:country="RO"/>
</style:default-style>
</office:styles>
<office:body>
<office:text>
<text:p text:style-name="Standard"></text:p>
</office:text>
</office:body>
</office:document>
diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx b/sw/qa/extras/uiwriter/uiwriter.cxx
index 2e295b8..f3d92a4 100644
--- a/sw/qa/extras/uiwriter/uiwriter.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter.cxx
@@ -370,6 +370,7 @@ public:
void testTdf38394();
void testTdf59666();
void testTdf133524();
void testTdf133524_Romanian();
void testTdf128860();
void testTdf123786();
#if ENABLE_LIBNUMBERTEXT
@@ -591,6 +592,7 @@ public:
CPPUNIT_TEST(testTdf38394);
CPPUNIT_TEST(testTdf59666);
CPPUNIT_TEST(testTdf133524);
CPPUNIT_TEST(testTdf133524_Romanian);
CPPUNIT_TEST(testTdf128860);
CPPUNIT_TEST(testTdf123786);
#if ENABLE_LIBNUMBERTEXT
@@ -7193,7 +7195,6 @@ void SwUiWriterTest::testTdf38394()
// tdf#132301 autocorrect of qu'«
pWrtShell->Insert(u" qu\u2019");
pWrtShell->AutoCorrect(corr, cChar);
nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
sReplaced += u" qu\u2019« ";
CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
}
@@ -7228,7 +7229,6 @@ void SwUiWriterTest::testTdf133524()
// <<
pWrtShell->Insert(u"word<");
pWrtShell->AutoCorrect(corr, '<');
nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
sReplaced += u"word«";
CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
// 2. Testing autocorrect of " to >> and << inside „...”
@@ -7236,29 +7236,64 @@ void SwUiWriterTest::testTdf133524()
// opening primary level quote
pWrtShell->Insert(u" ");
pWrtShell->AutoCorrect(corr, '"');
nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
sReplaced += u" „";
CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
// opening second level quote
pWrtShell->Insert(u"Sentence and ");
pWrtShell->AutoCorrect(corr, '"');
nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
sReplaced += u"Sentence and »";
CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
// closing second level quote
pWrtShell->Insert(u"word");
pWrtShell->AutoCorrect(corr, '"');
nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
sReplaced += u"word«";
CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
// closing primary level quote
pWrtShell->Insert(u".");
pWrtShell->AutoCorrect(corr, '"');
nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
sReplaced += u".”";
CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
}
void SwUiWriterTest::testTdf133524_Romanian()
{
SwDoc* pDoc = createDoc("tdf133524_ro.fodt");
SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
SwAutoCorrect corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
// 1. Testing autocorrect of " to << and >> inside „...”
// Example: „Sentence and «word».”
// opening primary level quote
pWrtShell->AutoCorrect(corr, '"');
sal_uLong nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
OUString sReplaced(u"„");
CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
// opening second level quote
pWrtShell->Insert(u"Sentence and ");
pWrtShell->AutoCorrect(corr, '"');
sReplaced += u"Sentence and «";
CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
// closing second level quote
pWrtShell->Insert(u"word");
pWrtShell->AutoCorrect(corr, '"');
sReplaced += u"word»";
CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
// closing primary level quote
pWrtShell->Insert(u".");
pWrtShell->AutoCorrect(corr, '"');
sReplaced += u".”";
CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
// 2. Testing recognition of closing double quotation mark ”
pWrtShell->Insert(u" ");
pWrtShell->AutoCorrect(corr, '"');
sReplaced += u" „";
CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
// 3. Testing recognition of alternative closing double quotation mark “
pWrtShell->Insert(u"Alternative.“ ");
pWrtShell->AutoCorrect(corr, '"');
sReplaced += u"Alternative.“ „";
CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
}
void SwUiWriterTest::testTdf128860()
{
SwDoc* pDoc = createDoc("tdf128860.fodt");
@@ -7273,13 +7308,11 @@ void SwUiWriterTest::testTdf128860()
// Us apostrophe without preceding starting quote: word' -> word’
pWrtShell->Insert(u" word");
pWrtShell->AutoCorrect(corr, '\'');
nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
sReplaced += u" word’";
CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
// But only after letters: word.' -> word.‘
pWrtShell->Insert(u" word.");
pWrtShell->AutoCorrect(corr, '\'');
nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
sReplaced += u" word.‘";
CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
}
@@ -7298,13 +7331,11 @@ void SwUiWriterTest::testTdf123786()
// Us apostrophe without preceding starting quote: word' -> word’
pWrtShell->Insert(u" слово");
pWrtShell->AutoCorrect(corr, '\'');
nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
sReplaced += u" слово’";
CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
// But only after letters: word.' -> word.“
pWrtShell->Insert(u" слово.");
pWrtShell->AutoCorrect(corr, '\'');
nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
sReplaced += u" слово.“";
CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
}
@@ -7325,7 +7356,6 @@ void SwUiWriterTest::testTdf133589()
// disambiguate consonants: asszony -> asz|szony
pWrtShell->Insert(u"asszony");
pWrtShell->AutoCorrect(corr, ' ');
nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
sReplaced += u"𐳀𐳥𐳥𐳛𐳚 ";
CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
// disambiguate consonants: kosszarv -> kos|szarv
@@ -7334,13 +7364,11 @@ void SwUiWriterTest::testTdf133589()
// pWrtShell->Insert(u"kosszarv");
pWrtShell->Insert(u"kosszarv");
pWrtShell->AutoCorrect(corr, ' ');
nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
sReplaced += u"𐳓𐳛𐳤𐳥𐳀𐳢𐳮 ";
CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
// transliterate numbers to Old Hungarian
pWrtShell->Insert(u"2020");
pWrtShell->AutoCorrect(corr, ' ');
nIndex = pWrtShell->GetCursor()->GetNode().GetIndex();
sReplaced += u"𐳺𐳺𐳿𐳼𐳼 ";
CPPUNIT_ASSERT_EQUAL(sReplaced, static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex])->GetText());
}