summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan-Marek Glogowski <glogow@fbihome.de>2015-12-30 01:20:23 +0100
committerJan-Marek Glogowski <glogow@fbihome.de>2016-01-02 03:50:53 +0100
commitc91024891ff10c2ae01e11a28a9aecca2f36b6c3 (patch)
tree7746c0bee55b9ebf535a94490934afca99f7d3f1
parentc1258abe50f1508ea0f628ff963bc1914ab86b67 (diff)
tdf#96479 workaround bookmark end pos handling...
... when inserting text into a text node. Seems SwTextNode::InsertText doesn't handle bookmark end positions correctly. This is just handled correctly, if it also contains the bookmark start. This workaround simply concats the three strings to be inserted in advance, so we just have to call SwTextNode::InsertText once for the whole string. Change-Id: Iab7708b4cc4df406bdbc3a685c7410e0e797fdc4
-rw-r--r--sw/qa/extras/uiwriter/uiwriter.cxx97
-rw-r--r--sw/source/core/txtnode/thints.cxx7
2 files changed, 100 insertions, 4 deletions
diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx b/sw/qa/extras/uiwriter/uiwriter.cxx
index 4ea139ee0c3d..50a70ee38db9 100644
--- a/sw/qa/extras/uiwriter/uiwriter.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter.cxx
@@ -178,6 +178,7 @@ public:
void testTdf92648();
void testTdf96515();
void testTdf96536();
+ void testTdf96479();
CPPUNIT_TEST_SUITE(SwUiWriterTest);
CPPUNIT_TEST(testReplaceForward);
@@ -262,6 +263,7 @@ public:
CPPUNIT_TEST(testTdf92648);
CPPUNIT_TEST(testTdf96515);
CPPUNIT_TEST(testTdf96536);
+ CPPUNIT_TEST(testTdf96479);
CPPUNIT_TEST_SUITE_END();
private:
@@ -2966,6 +2968,101 @@ void SwUiWriterTest::testTdf96536()
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(276), parseDump("/root/infos/bounds", "height").toInt32());
}
+void SwUiWriterTest::testTdf96479()
+{
+ // We want to verify the empty input text field in the bookmark
+ static const OUString emptyInputTextField =
+ OUString(CH_TXT_ATR_INPUTFIELDSTART) + OUString(CH_TXT_ATR_INPUTFIELDEND);
+
+ SwDoc* pDoc = createDoc();
+ SwXTextDocument *xTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+ CPPUNIT_ASSERT(xTextDoc);
+
+ // So we can clean up all references for reload
+ {
+ // Append bookmark
+ SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
+ SwPaM aPaM(aIdx);
+ IDocumentMarkAccess &rIDMA = *pDoc->getIDocumentMarkAccess();
+ sw::mark::IMark *pMark =
+ rIDMA.makeMark(aPaM, "original", IDocumentMarkAccess::MarkType::BOOKMARK);
+ CPPUNIT_ASSERT(!pMark->IsExpanded());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getBookmarksCount());
+
+ // Get helper objects
+ uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<css::lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
+
+ // Create cursor from bookmark
+ uno::Reference<text::XTextContent> xTextContent(xBookmarksSupplier->getBookmarks()->getByName("original"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xTextContent->getAnchor(), uno::UNO_QUERY);
+ uno::Reference<text::XTextCursor> xCursor(xRange->getText()->createTextCursorByRange(xRange), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xCursor->isCollapsed());
+
+ // Remove bookmark
+ xRange->getText()->removeTextContent(xTextContent);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), rIDMA.getBookmarksCount());
+
+ // Insert replacement bookmark
+ uno::Reference<text::XTextContent> xBookmarkNew(xFactory->createInstance("com.sun.star.text.Bookmark"), uno::UNO_QUERY);
+ uno::Reference<container::XNamed> xBookmarkName(xBookmarkNew, uno::UNO_QUERY);
+ xBookmarkName->setName("replacement");
+ CPPUNIT_ASSERT(xCursor->isCollapsed());
+ // Force bookmark expansion
+ xCursor->getText()->insertString(xCursor, ".", true);
+ xCursor->getText()->insertTextContent(xCursor, xBookmarkNew, true);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getBookmarksCount());
+ auto mark = *(rIDMA.getBookmarksBegin());
+ CPPUNIT_ASSERT(mark->IsExpanded());
+
+ // Create and insert input textfield with some content
+ uno::Reference<text::XTextField> xTextField(xFactory->createInstance("com.sun.star.text.TextField.Input"), uno::UNO_QUERY);
+ uno::Reference<text::XTextCursor> xCursorNew(xBookmarkNew->getAnchor()->getText()->createTextCursorByRange(xBookmarkNew->getAnchor()));
+ CPPUNIT_ASSERT(!xCursorNew->isCollapsed());
+ xCursorNew->getText()->insertTextContent(xCursorNew, xTextField, true);
+ xBookmarkNew = uno::Reference<text::XTextContent>(xBookmarksSupplier->getBookmarks()->getByName("replacement"), uno::UNO_QUERY);
+ xCursorNew = uno::Reference<text::XTextCursor>(xBookmarkNew->getAnchor()->getText()->createTextCursorByRange(xBookmarkNew->getAnchor()));
+ CPPUNIT_ASSERT(!xCursorNew->isCollapsed());
+
+ // Can't check the actual content of the text node via UNO
+ mark = *(rIDMA.getBookmarksBegin());
+ CPPUNIT_ASSERT(mark->IsExpanded());
+ SwPaM pam(mark->GetMarkStart(), mark->GetMarkEnd());
+ // Check for the actual bug, which didn't include CH_TXT_ATR_INPUTFIELDEND in the bookmark
+ CPPUNIT_ASSERT_EQUAL(emptyInputTextField, pam.GetText());
+ }
+
+ {
+ // Save and load cycle
+ // Actually not needed, but the bug symptom of a missing bookmark
+ // occured because a broken bookmar was saved and loading silently
+ // dropped the broken bookmark!
+ utl::TempFile aTempFile;
+ save("writer8", aTempFile);
+ loadURL(aTempFile.GetURL(), nullptr);
+ xTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+ CPPUNIT_ASSERT(xTextDoc);
+ pDoc = xTextDoc->GetDocShell()->GetDoc();
+
+ // Lookup "replacement" bookmark
+ IDocumentMarkAccess &rIDMA = *pDoc->getIDocumentMarkAccess();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getBookmarksCount());
+ uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xBookmarksSupplier->getBookmarks()->hasByName("replacement"));
+
+ uno::Reference<text::XTextContent> xTextContent(xBookmarksSupplier->getBookmarks()->getByName("replacement"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xTextContent->getAnchor(), uno::UNO_QUERY);
+ uno::Reference<text::XTextCursor> xCursor(xRange->getText()->createTextCursorByRange(xRange), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(!xCursor->isCollapsed());
+
+ // Verify bookmark content via text node / PaM
+ auto mark = *(rIDMA.getBookmarksBegin());
+ CPPUNIT_ASSERT(mark->IsExpanded());
+ SwPaM pam(mark->GetMarkStart(), mark->GetMarkEnd());
+ CPPUNIT_ASSERT_EQUAL(emptyInputTextField, pam.GetText());
+ }
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(SwUiWriterTest);
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/core/txtnode/thints.cxx b/sw/source/core/txtnode/thints.cxx
index 986a98532eee..0cbdd5e89a2a 100644
--- a/sw/source/core/txtnode/thints.cxx
+++ b/sw/source/core/txtnode/thints.cxx
@@ -1507,16 +1507,15 @@ bool SwTextNode::InsertHint( SwTextAttr * const pAttr, const SetAttrMode nMode )
if( !(SetAttrMode::NOTXTATRCHR & nMode) )
{
SwIndex aIdx( this, pAttr->GetStart() );
- InsertText( OUString(CH_TXT_ATR_INPUTFIELDSTART), aIdx, nInsertFlags );
- const OUString aContent = pTextInputField->GetFieldContent();
+ const OUString aContent = OUString(CH_TXT_ATR_INPUTFIELDSTART)
+ + pTextInputField->GetFieldContent() + OUString(CH_TXT_ATR_INPUTFIELDEND);
InsertText( aContent, aIdx, nInsertFlags );
- InsertText( OUString(CH_TXT_ATR_INPUTFIELDEND), aIdx, nInsertFlags );
sal_Int32* const pEnd(pAttr->GetEnd());
OSL_ENSURE( pEnd != nullptr, "<SwTextNode::InsertHint(..)> - missing end of RES_TXTATR_INPUTFIELD!" );
if ( pEnd != nullptr )
{
- *pEnd = *pEnd + 2 + aContent.getLength();
+ *pEnd = *pEnd + aContent.getLength();
nEnd = *pEnd;
}
}