i18npool/source/characterclassification/cclass_unicode_parser.cxx |   20 +++++
 sc/qa/unit/data/xlsx/tdf165886.xlsx                               |binary
 sc/qa/unit/subsequent_export_test4.cxx                            |   37 
++++++++++
 3 files changed, 57 insertions(+)

New commits:
commit a9a2a62e814cedfd208506e3959e78ec63852e6d
Author:     Aron Budea <aron.bu...@collabora.com>
AuthorDate: Fri Apr 11 03:54:20 2025 +0930
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Tue Apr 22 06:23:53 2025 +0200

    tdf#165886 sc: parse various quote characters
    
    Otherwise roundtripped formulas in XLSX containing them
    can end up with extra parenthesis, eg:
     - Expected: OR(D1=0,D1<>““)
     - Actual  : OR(D1=0,D1<>““))
    
    Change-Id: I6d296687cc2467ca0cdee329f9b04f6c956d2de0
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/183987
    Reviewed-by: Aron Budea <aron.bu...@collabora.com>
    Tested-by: Jenkins
    (cherry picked from commit 8397af1bc49897a2d8ebe30c1e960661271503e9)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184394
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    (cherry picked from commit 61f97ff0cd21459d10648124ce561342f324b4a6)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184402
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/i18npool/source/characterclassification/cclass_unicode_parser.cxx 
b/i18npool/source/characterclassification/cclass_unicode_parser.cxx
index 9ed95e2f907a..6f04a4e4450f 100644
--- a/i18npool/source/characterclassification/cclass_unicode_parser.cxx
+++ b/i18npool/source/characterclassification/cclass_unicode_parser.cxx
@@ -667,6 +667,26 @@ ParserFlags cclass_Unicode::getFlagsExtended(sal_uInt32 
const c, const cclass_Un
                     ParserFlags::WORD : ParserFlags::ILLEGAL;
             }
             break;
+        case U_START_PUNCTUATION:
+            // left angle, double angle and corner brackets
+            if (c != 0x3008 && c != 0x300a && c != 0x300c && c != 0x300e)
+                return ParserFlags::ILLEGAL;
+            return bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD;
+        case U_END_PUNCTUATION:
+            // right angle, double angle and corner brackets
+            if (c != 0x3009 && c != 0x300b && c != 0x300d && c != 0x300f)
+                return ParserFlags::ILLEGAL;
+            return bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD;
+        case U_INITIAL_PUNCTUATION:
+            // left single / double quotation marks
+            if (c != 0x2018 && c != 0x201c)
+                return ParserFlags::ILLEGAL;
+            return bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD;
+        case U_FINAL_PUNCTUATION:
+            // right single / double quotation marks
+            if (c != 0x2019 && c != 0x201d)
+                return ParserFlags::ILLEGAL;
+            return bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD;
     }
 
     return ParserFlags::ILLEGAL;
diff --git a/sc/qa/unit/data/xlsx/tdf165886.xlsx 
b/sc/qa/unit/data/xlsx/tdf165886.xlsx
new file mode 100644
index 000000000000..146d08823181
Binary files /dev/null and b/sc/qa/unit/data/xlsx/tdf165886.xlsx differ
diff --git a/sc/qa/unit/subsequent_export_test4.cxx 
b/sc/qa/unit/subsequent_export_test4.cxx
index 0c0c5359978e..787444bdb0e9 100644
--- a/sc/qa/unit/subsequent_export_test4.cxx
+++ b/sc/qa/unit/subsequent_export_test4.cxx
@@ -1910,6 +1910,43 @@ CPPUNIT_TEST_FIXTURE(ScExportTest4, testTdf165655)
     CPPUNIT_ASSERT_EQUAL(3, aNodes);
 }
 
+CPPUNIT_TEST_FIXTURE(ScExportTest4, testTdf165886)
+{
+    createScDoc("xlsx/tdf165886.xlsx");
+
+    save(u"Calc Office Open XML"_ustr);
+
+    xmlDocUniquePtr pSheet = parseExport("xl/worksheets/sheet1.xml");
+    CPPUNIT_ASSERT(pSheet);
+
+    assertXPathContent(pSheet, 
"/x:worksheet/x:sheetData/x:row[1]/x:c[1]/x:f"_ostr, u"“"_ustr);
+    // Without the accompanying fix in place, this test would have failed with
+    // - Expected: OR(D1=0,D1<>““)
+    // - Actual  : OR(D1=0,D1<>““))
+    assertXPathContent(pSheet, 
"/x:worksheet/x:sheetData/x:row[1]/x:c[2]/x:f"_ostr,
+                       u"OR(D1=0,D1<>““)"_ustr);
+    // Similarly
+    // - Expected: OR(E1=0,E1<>“)
+    // - Actual  : OR(E1=0,E1<>“))
+    assertXPathContent(pSheet, 
"/x:worksheet/x:sheetData/x:row[1]/x:c[3]/x:f"_ostr,
+                       u"OR(E1=0,E1<>“)"_ustr);
+    // Similarly
+    // - Expected: OR(D2=0,D2<>””)
+    // - Actual  : OR(D2=0,D2<>””))
+    assertXPathContent(pSheet, 
"/x:worksheet/x:sheetData/x:row[2]/x:c[2]/x:f"_ostr,
+                       u"OR(D2=0,D2<>””)"_ustr);
+    // Similarly
+    // - Expected: OR(D3=0,D3<>‘‘)
+    // - Actual  : OR(D3=0,D3<>‘‘))
+    assertXPathContent(pSheet, 
"/x:worksheet/x:sheetData/x:row[3]/x:c[2]/x:f"_ostr,
+                       u"OR(D3=0,D3<>‘‘)"_ustr);
+    // Similarly
+    // - Expected: OR(D4=0,D4<>’’)
+    // - Actual  : OR(D4=0,D4<>’’))
+    assertXPathContent(pSheet, 
"/x:worksheet/x:sheetData/x:row[4]/x:c[2]/x:f"_ostr,
+                       u"OR(D4=0,D4<>’’)"_ustr);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to