summaryrefslogtreecommitdiff
path: root/sw/source/uibase/shells/basesh.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/uibase/shells/basesh.cxx')
-rw-r--r--sw/source/uibase/shells/basesh.cxx108
1 files changed, 108 insertions, 0 deletions
diff --git a/sw/source/uibase/shells/basesh.cxx b/sw/source/uibase/shells/basesh.cxx
index 5e13fece9132..81eaec0f7c41 100644
--- a/sw/source/uibase/shells/basesh.cxx
+++ b/sw/source/uibase/shells/basesh.cxx
@@ -90,6 +90,7 @@
#include <svx/galleryitem.hxx>
#include <sfx2/devtools/DevelopmentToolChildWindow.hxx>
#include <com/sun/star/gallery/GalleryItemType.hpp>
+#include <com/sun/star/beans/PropertyValues.hpp>
#include <memory>
#include <svx/unobrushitemhelper.hxx>
@@ -98,12 +99,16 @@
#include <osl/diagnose.h>
#include <svx/svxdlg.hxx>
+#include <comphelper/sequenceashashmap.hxx>
#include <shellres.hxx>
#include <UndoTable.hxx>
#include <ndtxt.hxx>
#include <UndoManager.hxx>
+#include <fmtrfmrk.hxx>
+#include <txtrfmrk.hxx>
+#include <translatehelper.hxx>
FlyMode SwBaseShell::s_eFrameMode = FLY_DRAG_END;
@@ -765,6 +770,102 @@ void SwBaseShell::StateUndo(SfxItemSet &rSet)
}
}
+namespace
+{
+/// Searches for the specified field type and field name prefix and update the matching fields to
+/// have the provided new name and content.
+bool UpdateFieldConents(SfxRequest& rReq, SwWrtShell& rWrtSh)
+{
+ const SfxStringItem* pTypeName = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
+ if (!pTypeName || pTypeName->GetValue() != "SetRef")
+ {
+ // This is implemented so far only for reference marks.
+ return false;
+ }
+
+ const SfxStringItem* pNamePrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_2);
+ if (!pNamePrefix)
+ {
+ return false;
+ }
+ const OUString& rNamePrefix = pNamePrefix->GetValue();
+
+ const SfxUnoAnyItem* pFields = rReq.GetArg<SfxUnoAnyItem>(FN_PARAM_3);
+ if (!pFields)
+ {
+ return false;
+ }
+ uno::Sequence<beans::PropertyValues> aFields;
+ pFields->GetValue() >>= aFields;
+
+ SwDoc* pDoc = rWrtSh.GetDoc();
+ pDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSBOOKMARK, nullptr);
+ rWrtSh.StartAction();
+ for (sal_uInt16 nRefMark = 0; nRefMark < pDoc->GetRefMarks(); ++nRefMark)
+ {
+ auto pRefMark = const_cast<SwFormatRefMark*>(pDoc->GetRefMark(nRefMark));
+ if (!pRefMark->GetRefName().startsWith(rNamePrefix))
+ {
+ continue;
+ }
+
+ if (aFields.getLength() <= nRefMark)
+ {
+ continue;
+ }
+ comphelper::SequenceAsHashMap aMap(aFields[nRefMark]);
+ auto aName = aMap["Name"].get<OUString>();
+ pRefMark->GetRefName() = aName;
+
+ OUString aContent = aMap["Content"].get<OUString>();
+ auto pTextRefMark = const_cast<SwTextRefMark*>(pRefMark->GetTextRefMark());
+ if (!pTextRefMark->End())
+ {
+ continue;
+ }
+
+ // Insert markers to remember where the paste positions are.
+ const SwTextNode& rTextNode = pTextRefMark->GetTextNode();
+ SwPaM aMarkers(SwPosition(rTextNode, *pTextRefMark->End()));
+ IDocumentContentOperations& rIDCO = pDoc->getIDocumentContentOperations();
+ pTextRefMark->SetDontExpand(false);
+ bool bSuccess = rIDCO.InsertString(aMarkers, "XY");
+ if (bSuccess)
+ {
+ SwPaM aPasteEnd(SwPosition(rTextNode, *pTextRefMark->End()));
+ aPasteEnd.Move(fnMoveBackward, GoInContent);
+
+ // Paste HTML content.
+ SwPaM* pCursorPos = rWrtSh.GetCursor();
+ *pCursorPos = aPasteEnd;
+ SwTranslateHelper::PasteHTMLToPaM(rWrtSh, pCursorPos, aContent.toUtf8(), true);
+
+ // Update the refmark to point to the new content.
+ sal_Int32 nOldStart = pTextRefMark->GetStart();
+ sal_Int32 nNewStart = *pTextRefMark->End();
+ // First grow it to include text till the end of the paste position.
+ pTextRefMark->SetEnd(aPasteEnd.GetPoint()->GetContentIndex());
+ // Then shrink it to only start at the paste start: we know that the refmark was
+ // truncated to the paste start, as the refmark has to stay inside a single text node
+ pTextRefMark->SetStart(nNewStart);
+ rTextNode.GetSwpHints().SortIfNeedBe();
+ SwPaM aEndMarker(*aPasteEnd.GetPoint());
+ aEndMarker.SetMark();
+ aEndMarker.GetMark()->AdjustContent(1);
+ SwPaM aStartMarker(SwPosition(rTextNode, nOldStart), SwPosition(rTextNode, nNewStart));
+
+ // Remove markers. The start marker includes the old content as well.
+ rIDCO.DeleteAndJoin(aStartMarker);
+ rIDCO.DeleteAndJoin(aEndMarker);
+ }
+ }
+
+ rWrtSh.EndAction();
+ pDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSBOOKMARK, nullptr);
+ return true;
+}
+}
+
// Evaluate respectively dispatching the slot Id
void SwBaseShell::Execute(SfxRequest &rReq)
@@ -787,6 +888,13 @@ void SwBaseShell::Execute(SfxRequest &rReq)
break;
case FN_UPDATE_FIELDS:
{
+ if (UpdateFieldConents(rReq, rSh))
+ {
+ // Parameters indicated that the name / content of fields has to be updated to
+ // the provided values, don't do an actual fields update.
+ break;
+ }
+
rSh.UpdateDocStat();
rSh.EndAllTableBoxEdit();
rSh.SwViewShell::UpdateFields(true);