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 93f2c3d9e196ac27e218a0230ac98f5c03f81881
Author:     Aron Budea <aron.bu...@collabora.com>
AuthorDate: Fri Apr 11 03:54:20 2025 +0930
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Wed Apr 23 14:37:23 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/+/184453
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184488

diff --git a/i18npool/source/characterclassification/cclass_unicode_parser.cxx 
b/i18npool/source/characterclassification/cclass_unicode_parser.cxx
index 97fae9518adc..484973f751af 100644
--- a/i18npool/source/characterclassification/cclass_unicode_parser.cxx
+++ b/i18npool/source/characterclassification/cclass_unicode_parser.cxx
@@ -672,6 +672,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 8983756b6d41..40e80ae72601 100644
--- a/sc/qa/unit/subsequent_export_test4.cxx
+++ b/sc/qa/unit/subsequent_export_test4.cxx
@@ -2012,6 +2012,43 @@ CPPUNIT_TEST_FIXTURE(ScExportTest4, testNotesAuthor)
     pBatch->commit();
 }
 
+CPPUNIT_TEST_FIXTURE(ScExportTest4, testTdf165886)
+{
+    createScDoc("xlsx/tdf165886.xlsx");
+
+    save(u"Calc Office Open XML"_ustr);
+
+    xmlDocUniquePtr pSheet = parseExport(u"xl/worksheets/sheet1.xml"_ustr);
+    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