sw/qa/uibase/shells/shells.cxx | 31 +++++++++++++++++++++++++++++++ sw/source/uibase/shells/textfld.cxx | 10 ++++++++++ 2 files changed, 41 insertions(+)
New commits: commit a178a2ac6df8dc63a7ab8d4a19b90ae8a17baca4 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Mon Jan 2 14:45:53 2023 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Mon Jan 2 18:26:32 2023 +0000 sw UI: fix crash on inserting a fieldmark inside a fieldmark Inserting a fieldmark using .uno:TextFormField, then entering into that fieldmark using the cursor, finally doing in insertion again using .uno:TextFormField resulted in a crash. The problem is that lcl_SetFieldMarks() uses 3 IDocumentContentOperations().InsertString() calls to insert the field start/separator/end, but right after inserting the field start we already create an sw::InsertText hint, which works with an inconsistent string (the start is already inserted but not the separator / end). Fix the problem by just not allowing the insertion of fieldmarks inside fieldmarks on the UI: these are meant to be read-only for the user, so fieldmark insertion is OK to be not working, as long as a clear error message is provided. An alternative approach would be to insert the inner fieldmark in a way similar to how import filters can do it, but that would be more work. Change-Id: I7d1a7c638b179fd9149ccdc47215329e3433b6e5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144947 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins diff --git a/sw/qa/uibase/shells/shells.cxx b/sw/qa/uibase/shells/shells.cxx index a6603984afbb..2f89720cf570 100644 --- a/sw/qa/uibase/shells/shells.cxx +++ b/sw/qa/uibase/shells/shells.cxx @@ -501,6 +501,37 @@ CPPUNIT_TEST_FIXTURE(SwUibaseShellsTest, testUpdateBookmarks) CPPUNIT_ASSERT_EQUAL(OUString("Anew result 1Cnew result 2E"), aActual); } +CPPUNIT_TEST_FIXTURE(SwUibaseShellsTest, testInsertFieldmarkReadonly) +{ + // Given a document with a fieldmark, the cursor inside the fieldmark: + createSwDoc(); + uno::Sequence<css::beans::PropertyValue> aArgs = { + comphelper::makePropertyValue("FieldType", uno::Any(OUString(ODF_UNHANDLED))), + comphelper::makePropertyValue("FieldCommand", uno::Any(OUString("my command"))), + comphelper::makePropertyValue("FieldResult", uno::Any(OUString("my result"))), + }; + dispatchCommand(mxComponent, ".uno:TextFormField", aArgs); + SwDoc* pDoc = getSwDoc(); + SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + SwCursor* pCursor = pWrtShell->GetCursor(); + pCursor->SttEndDoc(/*bSttDoc=*/true); + pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false); + + // When trying to insert an inner fieldmark: + // Without the accompanying fix in place, this test would have crashed. + dispatchCommand(mxComponent, ".uno:TextFormField", aArgs); + + // Then make sure the read-only content refuses to accept that inner fieldmark, so we still have + // just one: + size_t nActual = 0; + IDocumentMarkAccess& rIDMA = *pDoc->getIDocumentMarkAccess(); + for (auto it = rIDMA.getFieldmarksBegin(); it != rIDMA.getFieldmarksEnd(); ++it) + { + ++nActual; + } + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), nActual); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/shells/textfld.cxx b/sw/source/uibase/shells/textfld.cxx index 12cc13a15bd2..aad7d0891bd9 100644 --- a/sw/source/uibase/shells/textfld.cxx +++ b/sw/source/uibase/shells/textfld.cxx @@ -719,6 +719,16 @@ FIELD_INSERT: aFieldCode = pFieldCode->GetValue(); } + if (rSh.HasReadonlySel()) + { + // Inform the user that the request has been ignored. + auto xInfo = std::make_shared<weld::GenericDialogController>( + GetView().GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", + "InfoReadonlyDialog"); + weld::DialogController::runAsync(xInfo, [](sal_Int32 /*nResult*/) {}); + break; + } + rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT_FORM_FIELD, nullptr); // Don't update the layout after inserting content and before deleting temporary // text nodes.