sw/qa/extras/uiwriter/data/tdf65535.fodt |   14 +++++
 sw/qa/extras/uiwriter/uiwriter6.cxx      |   80 +++++++++++++++++++++++++++++++
 sw/source/uibase/shells/textsh1.cxx      |   23 ++++++++
 3 files changed, 116 insertions(+), 1 deletion(-)

New commits:
commit 1e4709f47dec87d5d2b66f3de222588c3babaf18
Author:     László Németh <nem...@numbertext.org>
AuthorDate: Sun Dec 18 10:03:18 2022 +0100
Commit:     László Németh <nem...@numbertext.org>
CommitDate: Mon Dec 19 12:21:29 2022 +0000

    tdf#65535 sw: fix lost comment at fixing spelling with context menu
    
    Also fix the bad Undo label, where the invisible IAA character
    became visible.
    
    Choosing one of the spelling suggestions of the context menu
    of a bad word fixed the spelling of the original word, but
    also deleted its inword comment. Keep the comment at the end
    of the fixed word.
    
    Fix also the bad Undo label, which contained the original
    word with the Interlinear Annotation Anchor (IAA) character.
    Now it shows only the word, but not the Unicode replacement
    glyph of IAA.
    
    Regression from commit b0f170d7df9cff12535d2ecfd146b32b745a8ef8
    "0xFFF9 is a better choice for CH_TXTATR_INWORD than 0x0002".
    
    Change-Id: I5bfa214a060c446e9897e806832bedfe54241e1e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144397
    Tested-by: László Németh <nem...@numbertext.org>
    Reviewed-by: László Németh <nem...@numbertext.org>

diff --git a/sw/qa/extras/uiwriter/data/tdf65535.fodt 
b/sw/qa/extras/uiwriter/data/tdf65535.fodt
new file mode 100644
index 000000000000..b3a738bc8ac8
--- /dev/null
+++ b/sw/qa/extras/uiwriter/data/tdf65535.fodt
@@ -0,0 +1,14 @@
+<?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:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
 xmlns:meta="u
 rn:oasis:names:tc:opendocument:xmlns:meta:1.0" 
xmlns:oooc="http://openoffice.org/2004/calc"; 
xmlns:dc="http://purl.org/dc/elements/1.1/"; 
xmlns:calcext="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" 
office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ 
<office:meta><meta:creation-date>2022-12-17T23:29:19.781993530</meta:creation-date><dc:date>2022-12-17T23:30:52.855431377</dc:date><meta:editing-duration>PT1M34S</meta:editing-duration><meta:editing-cycles>1</meta:editing-cycles><meta:document-statistic
 meta:table-count="0" meta:image-count="0" meta:object-count="0" 
meta:page-count="1" meta:paragraph-count="1" meta:word-count="1" 
meta:character-count="4" 
meta:non-whitespace-character-count="4"/><meta:generator>LibreOfficeDev/7.5.0.0.alpha0$Linux_X86_64
 
LibreOffice_project/be538308dd5dee33436ae0e247c315df63a8b958</meta:generator></office:meta>
+ <office:body>
+  <office:text>
+   <text:p text:style-name="P1">Ba<office:annotation loext:resolved="false">
+     <dc:creator>x</dc:creator>
+     <dc:date>2022-12-17T23:29:53.289798307</dc:date>
+     <text:p text:style-name="P2"><text:span text:style-name="T1">with 
comment</text:span></text:p>
+    </office:annotation>ad</text:p>
+  </office:text>
+ </office:body>
+</office:document>
diff --git a/sw/qa/extras/uiwriter/uiwriter6.cxx 
b/sw/qa/extras/uiwriter/uiwriter6.cxx
index 305e4fa18732..a3cda9eca08f 100644
--- a/sw/qa/extras/uiwriter/uiwriter6.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter6.cxx
@@ -29,6 +29,14 @@
 #include <UndoManager.hxx>
 #include <unotools/syslocaleoptions.hxx>
 
+#include <svl/stritem.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <comphelper/dispatchcommand.hxx>
+#include <sfx2/dispatch.hxx>
+#include <cmdid.h>
+#include <tools/json_writer.hxx>
+#include <boost/property_tree/json_parser.hpp>
+
 #include <com/sun/star/text/XTextTable.hpp>
 #include <com/sun/star/text/XTextViewCursorSupplier.hpp>
 #include <com/sun/star/view/XSelectionSupplier.hpp>
@@ -1430,6 +1438,78 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf124603)
     }
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf65535)
+{
+#if !defined(MACOSX)
+    createSwDoc("tdf65535.fodt");
+    SwXTextDocument* pTextDoc = 
dynamic_cast<SwXTextDocument*>(mxComponent.get());
+    SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell();
+    const SwViewOption* pOpt = pWrtShell->GetViewOptions();
+    uno::Sequence<beans::PropertyValue> params
+        = comphelper::InitPropertySequence({ { "Enable", uno::Any(true) } });
+    dispatchCommand(mxComponent, ".uno:SpellOnline", params);
+
+    // Automatic Spell Checking is enabled
+
+    CPPUNIT_ASSERT(pOpt->IsOnlineSpell());
+
+    // check available en_US dictionary and test spelling with it
+    uno::Reference<XLinguServiceManager2> xLngSvcMgr(GetLngSvcMgr_Impl());
+    uno::Reference<XSpellChecker1> xSpell;
+    xSpell.set(xLngSvcMgr->getSpellChecker(), UNO_QUERY);
+    LanguageType eLang = LanguageTag::convertToLanguageType(lang::Locale("en", 
"US", OUString()));
+    if (xSpell.is() && xSpell->hasLanguage(static_cast<sal_uInt16>(eLang)))
+    {
+        // trigger online spell checking by (a few) spaces to be sure to get it
+
+        emulateTyping(*pTextDoc, u" ");
+
+        // FIXME: inserting a space before the bad word removes the red 
underline
+        // Insert a second space to get the red underline (back)
+
+        pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, 
/*bBasicCall=*/false);
+        emulateTyping(*pTextDoc, u" ");
+
+        // Select the bad word (right to left, as during right click)
+
+        pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 5, 
/*bBasicCall=*/false);
+        pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 4, 
/*bBasicCall=*/false);
+
+        // choose the word "Baaed" from the spelling suggestions of the 
context menu
+
+        SfxViewShell* pViewShell = SfxViewShell::Current();
+        {
+            static const OUStringLiteral sApplyRule(u"Spelling_Baaed");
+            SfxStringItem aApplyItem(FN_PARAM_1, sApplyRule);
+            pViewShell->GetViewFrame()->GetDispatcher()->ExecuteList(
+                SID_SPELLCHECK_APPLY_SUGGESTION, SfxCallMode::SYNCHRON, { 
&aApplyItem });
+        }
+
+        // check the replacement in the text
+
+        CPPUNIT_ASSERT_EQUAL(OUString("  Baaed"), 
getParagraph(1)->getString());
+    }
+
+    // check the remaining comment
+
+    tools::JsonWriter aJsonWriter;
+    pTextDoc->getPostIts(aJsonWriter);
+    char* pChar = aJsonWriter.extractData();
+    std::stringstream aStream(pChar);
+    free(pChar);
+    boost::property_tree::ptree aTree;
+    boost::property_tree::read_json(aStream, aTree);
+    OString sCommentText;
+    for (const boost::property_tree::ptree::value_type& rValue : 
aTree.get_child("comments"))
+    {
+        const boost::property_tree::ptree& rComment = rValue.second;
+        sCommentText = OString(rComment.get<std::string>("text").c_str());
+    }
+    // This was false (lost comment with spelling replacement)
+    CPPUNIT_ASSERT_EQUAL(OString("with comment"), sCommentText);
+#endif
+}
+
 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testRedlineAutoCorrect)
 {
     createSwDoc("redline-autocorrect.fodt");
diff --git a/sw/source/uibase/shells/textsh1.cxx 
b/sw/source/uibase/shells/textsh1.cxx
index 665bae00c524..eb60aaa839f6 100644
--- a/sw/source/uibase/shells/textsh1.cxx
+++ b/sw/source/uibase/shells/textsh1.cxx
@@ -1755,7 +1755,9 @@ void SwTextShell::Execute(SfxRequest &rReq)
 
         SwRewriter aRewriter;
 
-        aRewriter.AddRule(UndoArg1, rWrtSh.GetCursorDescr());
+        aRewriter.AddRule(UndoArg1, rWrtSh.GetCursorDescr()
+            // don't show the hidden control character of the comment
+            .replaceAll(OUStringChar(CH_TXTATR_INWORD), "") );
         aRewriter.AddRule(UndoArg2, SwResId(STR_YIELDS));
 
         OUString aTmpStr = SwResId(STR_START_QUOTE) +
@@ -1765,6 +1767,25 @@ void SwTextShell::Execute(SfxRequest &rReq)
         rWrtSh.StartUndo(SwUndoId::UI_REPLACE, &aRewriter);
         rWrtSh.StartAction();
 
+        // if there is a comment inside the original word, don't delete it:
+        // but keep it at the end of the replacement
+        // TODO: keep all the comments with a recursive function
+
+        if (SwPaM *pPaM = rWrtSh.GetCursor())
+        {
+            sal_Int32 
nCommentPos(pPaM->GetText().indexOf(OUStringChar(CH_TXTATR_INWORD)));
+            if ( nCommentPos > -1 )
+            {
+
+                // delete the original word after the comment
+                pPaM->GetPoint()->AdjustContent(nCommentPos + 1);
+                rWrtSh.Replace(OUString(), false);
+                // and select only the remaining part before the comment
+                pPaM->GetPoint()->AdjustContent(-(nCommentPos + 1));
+                pPaM->GetMark()->AdjustContent(-1);
+            }
+        }
+
         rWrtSh.Replace(aTmp, false);
 
         rWrtSh.EndAction();

Reply via email to