summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Luth <justin.luth@collabora.com>2022-11-09 17:02:03 -0500
committerMiklos Vajna <vmiklos@collabora.com>2022-11-10 08:59:24 +0100
commit2a26f136a36791c06caa895d5a25f4633fd10651 (patch)
treee5a98514cfeb7f8f4d9ecb779ccc180ed5b8f6fe
parente2f8558324091bddba0637942f4f000a24e673a7 (diff)
tdf#151548 vba FormFields: Add basic word::XFormField support
Unit tests will come in the following commits that represent actual FormFields that have content/results. This lays the foundation for adding Checkboxes, Textinputs, and Dropdowns. Change-Id: If85ae25f881198d5a0699b3350a7eb20b1735c45 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142507 Reviewed-by: Justin Luth <jluth@mail.com> Tested-by: Jenkins Reviewed-by: Tor Lillqvist <tml@collabora.com>
-rw-r--r--oovbaapi/ooo/vba/word/XFormField.idl50
-rw-r--r--oovbaapi/ooo/vba/word/XFormFields.idl7
-rw-r--r--sw/Library_vbaswobj.mk2
-rw-r--r--sw/inc/IMark.hxx8
-rw-r--r--sw/source/ui/vba/vbadocument.cxx10
-rw-r--r--sw/source/ui/vba/vbaformfield.cxx255
-rw-r--r--sw/source/ui/vba/vbaformfield.hxx98
-rw-r--r--sw/source/ui/vba/vbaformfields.cxx250
-rw-r--r--sw/source/ui/vba/vbaformfields.hxx56
9 files changed, 728 insertions, 8 deletions
diff --git a/oovbaapi/ooo/vba/word/XFormField.idl b/oovbaapi/ooo/vba/word/XFormField.idl
index 3131fda872f5..3d51fcd263cd 100644
--- a/oovbaapi/ooo/vba/word/XFormField.idl
+++ b/oovbaapi/ooo/vba/word/XFormField.idl
@@ -22,12 +22,60 @@ module ooo { module vba { module word {
interface XFormField
{
interface ooo::vba::XHelperInterface;
+ interface com::sun::star::script::XDefaultProperty;
+ /// Default member: returns the field type from WdFieldType
+ [attribute, readonly] long Type;
+
+ /**
+ * Returns or sets true if references to the specified form field
+ * are automatically updated whenever the field is exited.
+ */
+ [attribute] boolean CalculateOnExit;
+ /// Returns or sets a string that represents the result of the specified form field
[attribute] string Result;
+ /// Returns or sets true if a form field is enabled
[attribute] boolean Enabled;
+ /// Returns or sets the macro name that runs on keyboard (tab) navigation into the field
+ [attribute] string EntryMacro;
+ /// Returns or sets an exit macro name that runs on keyboard (tab) navigation out of the field
+ [attribute] string ExitMacro;
+ /**
+ * Returns or sets the text that's displayed in a message box
+ * when the form field has the focus and the user presses F1.
+ *
+ * When OwnHelp is False, HelpText specifies the name of an AutoText entry
+ * that contains help text for the form field
+ */
+ [attribute] string HelpText;
+ /**
+ * Returns or sets the specifies the source of the F1 text that's displayed in a message box
+ * If True, the text specified by the HelpText property is displayed.
+ * If False, the text in the AutoText entry specified by the HelpText property is displayed.
+ */
+ [attribute] boolean OwnHelp;
+ /// returns or sets the name of the specified object.
+ [attribute] string Name;
+ /// Returns or sets the text that is displayed in the status bar when a form field has the focus
+ [attribute] string StatusText;
+ /** OwnStatus:
+ * If True, the text specified by the StatusText property is displayed.
+ * If False, the text of the AutoText entry specified by the StatusText property is displayed.
+ */
+ [attribute] boolean OwnStatus;
any CheckBox();
-
+ any DropDown();
+ any TextInput();
+ /// Returns the next form field in the collection.
+ any Next();
+ /// returns the previous form field in the collection.
+ any Previous();
+ /**
+ * Represents a contiguous area in a document.
+ * Each Range object is defined by a starting and ending character position.
+ */
+ any Range();
};
}; }; };
diff --git a/oovbaapi/ooo/vba/word/XFormFields.idl b/oovbaapi/ooo/vba/word/XFormFields.idl
index bef2aa9d919b..8b98c6381681 100644
--- a/oovbaapi/ooo/vba/word/XFormFields.idl
+++ b/oovbaapi/ooo/vba/word/XFormFields.idl
@@ -23,10 +23,15 @@
module ooo { module vba { module word {
-
+interface XFormField;
interface XFormFields
{
interface ::ooo::vba::XCollection;
+
+ ///Returns and sets if shading is applied to form XFormFields
+ [attribute] boolean Shaded;
+ /// Resturns a FormField object that representa new WdFieldType added at a range
+ //XFormField Add( [in] any Range, [in] long Type ) raises ( com::sun::star::script::BasicErrorException );
};
}; }; };
diff --git a/sw/Library_vbaswobj.mk b/sw/Library_vbaswobj.mk
index 6e9f3539c816..752f682f2461 100644
--- a/sw/Library_vbaswobj.mk
+++ b/sw/Library_vbaswobj.mk
@@ -72,6 +72,8 @@ $(eval $(call gb_Library_add_exception_objects,vbaswobj,\
sw/source/ui/vba/vbacells \
sw/source/ui/vba/vbacolumn \
sw/source/ui/vba/vbacolumns \
+ sw/source/ui/vba/vbaformfield \
+ sw/source/ui/vba/vbaformfields \
sw/source/ui/vba/vbaframe \
sw/source/ui/vba/vbaframes \
sw/source/ui/vba/vbalistformat \
diff --git a/sw/inc/IMark.hxx b/sw/inc/IMark.hxx
index 151c9a9333fb..776d35c2f4e3 100644
--- a/sw/inc/IMark.hxx
+++ b/sw/inc/IMark.hxx
@@ -102,6 +102,10 @@ namespace sw::mark
virtual void SetFieldname(const OUString& rFieldname) =0;
virtual void SetFieldHelptext(const OUString& rFieldHelptext) =0;
virtual void Invalidate() = 0;
+
+ virtual OUString GetContent() const { return OUString(); }
+ virtual void ReplaceContent(const OUString& /*sNewContent*/) {}
+
private:
IFieldmark(IFieldmark const &) = delete;
IFieldmark &operator =(IFieldmark const&) = delete;
@@ -128,8 +132,8 @@ namespace sw::mark
IDateFieldmark() = default;
public:
- virtual OUString GetContent() const = 0;
- virtual void ReplaceContent(const OUString& sNewContent) = 0;
+ virtual OUString GetContent() const override = 0;
+ virtual void ReplaceContent(const OUString& sNewContent) override = 0;
virtual std::pair<bool, double> GetCurrentDate() const = 0;
virtual void SetCurrentDate(double fDate) = 0;
diff --git a/sw/source/ui/vba/vbadocument.cxx b/sw/source/ui/vba/vbadocument.cxx
index 969b893e5130..6dcbdbf5c0b4 100644
--- a/sw/source/ui/vba/vbadocument.cxx
+++ b/sw/source/ui/vba/vbadocument.cxx
@@ -22,6 +22,7 @@
#include "vbafilterpropsfromformat.hxx"
#include "vbadocument.hxx"
+#include "vbaformfields.hxx"
#include "vbarange.hxx"
#include "vbarangehelper.hxx"
#include "vbadocumentproperties.hxx"
@@ -296,11 +297,12 @@ SwVbaDocument::TablesOfContents( const uno::Any& index )
return uno::Any( xCol );
}
-uno::Any SAL_CALL
-SwVbaDocument::FormFields( const uno::Any& /*index*/ )
+uno::Any SAL_CALL SwVbaDocument::FormFields(const uno::Any& index)
{
- uno::Reference< XCollection > xCol;
- return uno::Any( xCol );
+ uno::Reference<XCollection> xCol(new SwVbaFormFields(this, mxContext, mxModel));
+ if (index.hasValue())
+ return xCol->Item(index, uno::Any());
+ return uno::Any(xCol);
}
uno::Any SAL_CALL
diff --git a/sw/source/ui/vba/vbaformfield.cxx b/sw/source/ui/vba/vbaformfield.cxx
new file mode 100644
index 000000000000..43b9f25cf660
--- /dev/null
+++ b/sw/source/ui/vba/vbaformfield.cxx
@@ -0,0 +1,255 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ooo/vba/word/WdFieldType.hpp>
+
+#include <sal/log.hxx>
+
+#include <doc.hxx>
+#include <docsh.hxx>
+
+#include "vbaformfield.hxx"
+#include "wordvbahelper.hxx"
+
+using namespace ::ooo::vba;
+using namespace ::com::sun::star;
+
+/**
+ * Information about the method and properties of FormFields was gathered from
+ * https://www.codevba.com/Word/FormField.htm
+ *
+ * FormFields are inline text objects that are only found in MS Word.
+ * They cannot be created in Excel or in Calc.
+ *
+ * There are three specific kinds of FormFields: CheckBox, DropDown, and TextInput.
+ */
+SwVbaFormField::SwVbaFormField(const uno::Reference<ooo::vba::XHelperInterface>& rParent,
+ const uno::Reference<uno::XComponentContext>& rContext,
+ const uno::Reference<frame::XModel>& xModel,
+ sw::mark::IFieldmark& rFormField)
+ : SwVbaFormField_BASE(rParent, rContext)
+ , mxModel(std::move(xModel))
+ , m_rFormField(rFormField)
+{
+}
+
+SwVbaFormField::~SwVbaFormField() {}
+
+uno::Any SAL_CALL SwVbaFormField::CheckBox()
+{
+ // return uno::Any(uno::Reference<word::XCheckBox>(
+ // new SwVbaFormFieldCheckBox(mxParent, mxContext, m_rFormField)));
+ return uno::Any();
+}
+
+uno::Any SAL_CALL SwVbaFormField::DropDown()
+{
+ // return uno::Any(uno::Reference<word::XDropDown>(
+ // new SwVbaFormFieldDropDown(mxParent, mxContext, m_rFormField)));
+ return uno::Any();
+}
+
+uno::Any SAL_CALL SwVbaFormField::TextInput()
+{
+ // return uno::Any(uno::Reference<word::XTextInput>(
+ // new SwVbaFormFieldTextInput(mxParent, mxContext, m_rFormField)));
+ return uno::Any();
+}
+
+uno::Any SAL_CALL SwVbaFormField::Previous()
+{
+ SwDoc* pDoc = word::getDocShell(mxModel)->GetDoc();
+ if (!pDoc)
+ return uno::Any();
+
+ const IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+ if (!pMarkAccess)
+ return uno::Any();
+
+ sw::mark::IFieldmark* pFieldMark = pMarkAccess->getFieldmarkBefore(m_rFormField.GetMarkPos());
+
+ // DateFields are a LO specialty, and do not exist natively in MS documents. Ignore if added...
+ auto pDateField = dynamic_cast<sw::mark::IDateFieldmark*>(pFieldMark);
+ while (pDateField)
+ {
+ pFieldMark = pMarkAccess->getFieldmarkBefore(pDateField->GetMarkPos());
+ pDateField = dynamic_cast<sw::mark::IDateFieldmark*>(pFieldMark);
+ }
+
+ if (!pFieldMark)
+ return uno::Any();
+
+ return uno::Any(uno::Reference<word::XFormField>(
+ new SwVbaFormField(mxParent, mxContext, mxModel, *pFieldMark)));
+}
+
+uno::Any SAL_CALL SwVbaFormField::Next()
+{
+ SwDoc* pDoc = word::getDocShell(mxModel)->GetDoc();
+ if (!pDoc)
+ return uno::Any();
+
+ const IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+ if (!pMarkAccess)
+ return uno::Any();
+
+ sw::mark::IFieldmark* pFieldMark = pMarkAccess->getFieldmarkAfter(m_rFormField.GetMarkPos());
+
+ // DateFields are a LO specialty, and do not exist natively in MS documents. Ignore if added...
+ auto pDateField = dynamic_cast<sw::mark::IDateFieldmark*>(pFieldMark);
+ while (pDateField)
+ {
+ pFieldMark = pMarkAccess->getFieldmarkAfter(pDateField->GetMarkPos());
+ pDateField = dynamic_cast<sw::mark::IDateFieldmark*>(pFieldMark);
+ }
+
+ if (!pFieldMark)
+ return uno::Any();
+
+ return uno::Any(uno::Reference<word::XFormField>(
+ new SwVbaFormField(mxParent, mxContext, mxModel, *pFieldMark)));
+}
+
+uno::Any SAL_CALL SwVbaFormField::Range()
+{
+ SAL_INFO("sw.vba", "SwVbaFormField::getRange stub");
+ return uno::Any();
+}
+
+OUString SwVbaFormField::getDefaultPropertyName() { return "Type"; }
+
+sal_Int32 SwVbaFormField::getType()
+{
+ IDocumentMarkAccess::MarkType aType = IDocumentMarkAccess::GetType(m_rFormField);
+ if (aType == IDocumentMarkAccess::MarkType::CHECKBOX_FIELDMARK)
+ return ooo::vba::word::WdFieldType::wdFieldFormCheckBox;
+ else if (aType == IDocumentMarkAccess::MarkType::TEXT_FIELDMARK)
+ return ooo::vba::word::WdFieldType::wdFieldFormTextInput;
+ return ooo::vba::word::WdFieldType::wdFieldFormDropDown;
+}
+
+sal_Bool SwVbaFormField::getCalculateOnExit()
+{
+ SAL_INFO("sw.vba", "SwVbaFormField::getCalculateOnExit stub");
+ return false;
+}
+
+void SwVbaFormField::setCalculateOnExit(sal_Bool /*bSet*/)
+{
+ SAL_INFO("sw.vba", "SwVbaFormField::setCalculateOnExit stub");
+}
+
+sal_Bool SwVbaFormField::getEnabled()
+{
+ SAL_INFO("sw.vba", "SwVbaFormField::getEnabled stub");
+ return true;
+}
+
+void SwVbaFormField::setEnabled(sal_Bool /*bSet*/)
+{
+ SAL_INFO("sw.vba", "SwVbaFormField::setEnabled stub");
+}
+
+OUString SwVbaFormField::getEntryMacro()
+{
+ OUString sMacro;
+ (*m_rFormField.GetParameters())["EntryMacro"] >>= sMacro;
+ return sMacro;
+}
+
+void SwVbaFormField::setEntryMacro(const OUString& rSet)
+{
+ (*m_rFormField.GetParameters())["EntryMacro"] <<= rSet;
+}
+
+OUString SwVbaFormField::getExitMacro()
+{
+ OUString sMacro;
+ (*m_rFormField.GetParameters())["ExitMacro"] >>= sMacro;
+ return sMacro;
+}
+
+void SwVbaFormField::setExitMacro(const OUString& rSet)
+{
+ (*m_rFormField.GetParameters())["ExitMacro"] <<= rSet;
+}
+
+OUString SwVbaFormField::getHelpText() { return m_rFormField.GetFieldHelptext(); }
+
+void SwVbaFormField::setHelpText(const OUString& rSet) { m_rFormField.SetFieldHelptext(rSet); }
+
+sal_Bool SwVbaFormField::getOwnHelp()
+{
+ SAL_INFO("sw.vba", "SwVbaFormField::getOwnHelp stub");
+ return true;
+}
+
+void SwVbaFormField::setOwnHelp(sal_Bool /*bSet*/)
+{
+ SAL_INFO("sw.vba", "SwVbaFormField::setOwnHelp stub");
+}
+
+OUString SwVbaFormField::getName() { return m_rFormField.GetName(); }
+
+void SwVbaFormField::setName(const OUString& rSet)
+{
+ SAL_WARN("sw.vba", "SwVbaFormField::setName[" << rSet << "] stub");
+}
+
+OUString SwVbaFormField::getResult() { return m_rFormField.GetContent(); }
+
+void SwVbaFormField::setResult(const OUString& rSet)
+{
+ if (dynamic_cast<sw::mark::ICheckboxFieldmark*>(&m_rFormField))
+ m_rFormField.ReplaceContent("false");
+ else
+ m_rFormField.ReplaceContent(rSet);
+}
+
+OUString SwVbaFormField::getStatusText()
+{
+ SAL_INFO("sw.vba", "SwVbaFormField::getStatusText stub");
+ return OUString();
+}
+
+void SwVbaFormField::setStatusText(const OUString& rSet)
+{
+ SAL_INFO("sw.vba", "SwVbaFormField::setStatusText[" << rSet << "] stub");
+}
+
+sal_Bool SwVbaFormField::getOwnStatus()
+{
+ SAL_INFO("sw.vba", "SwVbaFormField::getOwnStatus stub");
+ return true;
+}
+
+void SwVbaFormField::setOwnStatus(sal_Bool /*bSet*/)
+{
+ SAL_INFO("sw.vba", "SwVbaFormField::setOwnStatus stub");
+}
+
+OUString SwVbaFormField::getServiceImplName() { return "SwVbaFormField"; }
+
+uno::Sequence<OUString> SwVbaFormField::getServiceNames()
+{
+ static uno::Sequence<OUString> const aServiceNames{ "ooo.vba.word.FormField" };
+ return aServiceNames;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/vba/vbaformfield.hxx b/sw/source/ui/vba/vbaformfield.hxx
new file mode 100644
index 000000000000..14f44fc3c779
--- /dev/null
+++ b/sw/source/ui/vba/vbaformfield.hxx
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UI_VBA_VBAFORMFIELD_HXX
+#define INCLUDED_SW_SOURCE_UI_VBA_VBAFORMFIELD_HXX
+
+#include <ooo/vba/word/XFormField.hpp>
+
+#include <vbahelper/vbahelperinterface.hxx>
+
+#include <IDocumentMarkAccess.hxx>
+
+typedef InheritedHelperInterfaceWeakImpl<ooo::vba::word::XFormField> SwVbaFormField_BASE;
+
+class SwVbaFormField : public SwVbaFormField_BASE
+{
+private:
+ css::uno::Reference<css::frame::XModel> mxModel;
+ sw::mark::IFieldmark& m_rFormField;
+
+public:
+ /// @throws css::uno::RuntimeException
+ SwVbaFormField(const css::uno::Reference<ooo::vba::XHelperInterface>& rParent,
+ const css::uno::Reference<css::uno::XComponentContext>& rContext,
+ const css::uno::Reference<css::frame::XModel>& xModel,
+ sw::mark::IFieldmark& rFormField);
+ virtual ~SwVbaFormField() override;
+
+ // XFormField Methods
+ virtual OUString SAL_CALL getDefaultPropertyName() override;
+
+ virtual css::uno::Any SAL_CALL CheckBox() override;
+ virtual css::uno::Any SAL_CALL DropDown() override;
+ virtual css::uno::Any SAL_CALL TextInput() override;
+ virtual css::uno::Any SAL_CALL Previous() override;
+ virtual css::uno::Any SAL_CALL Next() override;
+ virtual css::uno::Any SAL_CALL Range() override;
+
+ // Indicates which of the three form fields this is: oovbaapi/ooo/vba/word/WdFieldType.idl
+ virtual sal_Int32 SAL_CALL getType() override;
+ // True if references to the specified form field
+ // are automatically updated whenever the field is exited
+ virtual sal_Bool SAL_CALL getCalculateOnExit() override;
+ virtual void SAL_CALL setCalculateOnExit(sal_Bool bSet) override;
+ virtual sal_Bool SAL_CALL getEnabled() override;
+ virtual void SAL_CALL setEnabled(sal_Bool bSet) override;
+ virtual OUString SAL_CALL getEntryMacro() override;
+ virtual void SAL_CALL setEntryMacro(const OUString& rSet) override;
+ virtual OUString SAL_CALL getExitMacro() override;
+ virtual void SAL_CALL setExitMacro(const OUString& rSet) override;
+ /*
+ * If the OwnHelp property is set to True,
+ * HelpText specifies the text string value.
+ * If OwnHelp is set to False, HelpText specifies the name of an AutoText entry
+ * that contains help text for the form field.
+ */
+ virtual OUString SAL_CALL getHelpText() override;
+ virtual void SAL_CALL setHelpText(const OUString& rSet) override;
+ virtual sal_Bool SAL_CALL getOwnHelp() override;
+ virtual void SAL_CALL setOwnHelp(sal_Bool bSet) override;
+
+ virtual OUString SAL_CALL getName() override;
+ virtual void SAL_CALL setName(const OUString& rSet) override;
+ virtual OUString SAL_CALL getResult() override;
+ virtual void SAL_CALL setResult(const OUString& rSet) override;
+ /*
+ * If the OwnStatus property is set to True,
+ * StatusText specifies the status bar value.
+ * If OwnStatus is set to False, StatusText specifies the name of an AutoText entry
+ * that contains status bar text for the form field.
+ */
+ virtual OUString SAL_CALL getStatusText() override;
+ virtual void SAL_CALL setStatusText(const OUString& rSet) override;
+ virtual sal_Bool SAL_CALL getOwnStatus() override;
+ virtual void SAL_CALL setOwnStatus(sal_Bool bSet) override;
+
+ // XHelperInterface
+ virtual OUString getServiceImplName() override;
+ virtual css::uno::Sequence<OUString> getServiceNames() override;
+};
+#endif // INCLUDED_SW_SOURCE_UI_VBA_VBAFORMFIELD_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/vba/vbaformfields.cxx b/sw/source/ui/vba/vbaformfields.cxx
new file mode 100644
index 000000000000..f4bdd8cb6470
--- /dev/null
+++ b/sw/source/ui/vba/vbaformfields.cxx
@@ -0,0 +1,250 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <comphelper/sequence.hxx>
+#include <sal/log.hxx>
+
+#include <doc.hxx>
+#include <docsh.hxx>
+#include <IDocumentMarkAccess.hxx>
+
+#include "vbaformfield.hxx"
+#include "vbaformfields.hxx"
+#include "wordvbahelper.hxx"
+
+using namespace ::ooo::vba;
+using namespace ::com::sun::star;
+
+// Helper function to access the fieldmarks
+// @param rIndex serves multiple purposes
+// [in] -1 to indicate searching using the provided name, SAL_MAX_INT32 for totals
+// [out] rIndex indicates the found index, or the total number of fieldmarks
+static sw::mark::IFieldmark* lcl_getFieldmark(std::string_view rName, sal_Int32& rIndex,
+ const css::uno::Reference<frame::XModel>& xModel,
+ uno::Sequence<OUString>* pElementNames = nullptr)
+{
+ SwDoc* pDoc = word::getDocShell(xModel)->GetDoc();
+ if (!pDoc)
+ return nullptr;
+
+ IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+ if (!pMarkAccess)
+ return nullptr;
+
+ sal_Int32 nCounter = 0;
+ std::vector<OUString> vElementNames;
+ IDocumentMarkAccess::iterator aIter = pMarkAccess->getFieldmarksBegin();
+ while (aIter != pMarkAccess->getFieldmarksEnd())
+ {
+ switch (IDocumentMarkAccess::GetType(**aIter))
+ {
+ case IDocumentMarkAccess::MarkType::CHECKBOX_FIELDMARK:
+ case IDocumentMarkAccess::MarkType::DROPDOWN_FIELDMARK:
+ case IDocumentMarkAccess::MarkType::TEXT_FIELDMARK:
+ {
+ if (rIndex < 0
+ && (*aIter)->GetName().equalsIgnoreAsciiCase(OUString::fromUtf8(rName)))
+ {
+ rIndex = nCounter;
+ return dynamic_cast<sw::mark::IFieldmark*>(*aIter);
+ }
+ else if (rIndex == nCounter)
+ return dynamic_cast<sw::mark::IFieldmark*>(*aIter);
+
+ ++nCounter;
+ if (pElementNames)
+ vElementNames.push_back((*aIter)->GetName());
+ break;
+ }
+ default:;
+ }
+ aIter++;
+ }
+ rIndex = nCounter;
+ if (pElementNames)
+ *pElementNames = comphelper::containerToSequence(vElementNames);
+ return nullptr;
+}
+
+namespace
+{
+class FormFieldsEnumWrapper : public EnumerationHelper_BASE
+{
+ uno::Reference<container::XIndexAccess> mxIndexAccess;
+ sal_Int32 nIndex;
+
+public:
+ explicit FormFieldsEnumWrapper(uno::Reference<container::XIndexAccess> xIndexAccess)
+ : mxIndexAccess(std::move(xIndexAccess))
+ , nIndex(0)
+ {
+ }
+ virtual sal_Bool SAL_CALL hasMoreElements() override
+ {
+ return (nIndex < mxIndexAccess->getCount());
+ }
+
+ virtual uno::Any SAL_CALL nextElement() override
+ {
+ if (nIndex < mxIndexAccess->getCount())
+ {
+ return mxIndexAccess->getByIndex(nIndex++);
+ }
+ throw container::NoSuchElementException();
+ }
+};
+
+class FormFieldCollectionHelper
+ : public ::cppu::WeakImplHelper<container::XNameAccess, container::XIndexAccess,
+ container::XEnumerationAccess>
+{
+private:
+ const uno::Reference<XHelperInterface> mxParent;
+ const uno::Reference<uno::XComponentContext> mxContext;
+ const css::uno::Reference<frame::XModel>& mxModel;
+ sw::mark::IFieldmark* m_pCache;
+
+public:
+ /// @throws css::uno::RuntimeException
+ FormFieldCollectionHelper(const css::uno::Reference<ov::XHelperInterface> xParent,
+ const css::uno::Reference<css::uno::XComponentContext> xContext,
+ const css::uno::Reference<frame::XModel>& xModel)
+ : mxParent(std::move(xParent))
+ , mxContext(std::move(xContext))
+ , mxModel(std::move(xModel))
+ {
+ }
+
+ // XIndexAccess
+ virtual sal_Int32 SAL_CALL getCount() override
+ {
+ sal_Int32 nCount = SAL_MAX_INT32;
+ lcl_getFieldmark("", nCount, mxModel);
+ return nCount == SAL_MAX_INT32 ? 0 : nCount;
+ }
+
+ virtual uno::Any SAL_CALL getByIndex(sal_Int32 Index) override
+ {
+ m_pCache = lcl_getFieldmark("", Index, mxModel);
+ if (!m_pCache)
+ throw css::lang::IndexOutOfBoundsException();
+
+ return uno::Any(uno::Reference<word::XFormField>(
+ new SwVbaFormField(mxParent, mxContext, mxModel, *m_pCache)));
+ }
+
+ // XNameAccess
+ virtual uno::Sequence<OUString> SAL_CALL getElementNames() override
+ {
+ sal_Int32 nCount = SAL_MAX_INT32;
+ uno::Sequence<OUString> aSeq;
+ lcl_getFieldmark("", nCount, mxModel, &aSeq);
+ return aSeq;
+ }
+
+ virtual uno::Any SAL_CALL getByName(const OUString& aName) override
+ {
+ if (!hasByName(aName))
+ throw container::NoSuchElementException();
+
+ return uno::Any(uno::Reference<word::XFormField>(
+ new SwVbaFormField(mxParent, mxContext, mxModel, *m_pCache)));
+ }
+
+ virtual sal_Bool SAL_CALL hasByName(const OUString& aName) override
+ {
+ sal_Int32 nCount = -1;
+ m_pCache = lcl_getFieldmark(aName.toUtf8(), nCount, mxModel);
+ return m_pCache != nullptr;
+ }
+
+ // XElementAccess
+ virtual uno::Type SAL_CALL getElementType() override
+ {
+ return cppu::UnoType<word::XFormField>::get();
+ }
+
+ virtual sal_Bool SAL_CALL hasElements() override { return getCount() != 0; }
+
+ // XEnumerationAccess
+ virtual uno::Reference<container::XEnumeration> SAL_CALL createEnumeration() override
+ {
+ return new FormFieldsEnumWrapper(this);
+ }
+};
+}
+
+SwVbaFormFields::SwVbaFormFields(const uno::Reference<XHelperInterface>& xParent,
+ const uno::Reference<uno::XComponentContext>& xContext,
+ const uno::Reference<frame::XModel>& xModel)
+ : SwVbaFormFields_BASE(xParent, xContext,
+ uno::Reference<container::XIndexAccess>(
+ new FormFieldCollectionHelper(xParent, xContext, xModel)))
+ , m_xModel(std::move(xModel))
+{
+}
+
+sal_Bool SwVbaFormFields::getShaded()
+{
+ SAL_INFO("sw.vba", "SwVbaFormFields::getShaded stub");
+ return false;
+}
+
+void SwVbaFormFields::setShaded(sal_Bool /*bSet*/)
+{
+ SAL_INFO("sw.vba", "SwVbaFormFields::setShaded stub");
+}
+
+// uno::Reference<ooo::vba::word::XFormField> SwVbaFormFields::Add(const css::uno::Any& Range,
+// sal_Int32 Type)
+// {
+// sw::mark::IFieldmark* pFieldmark = nullptr;
+// switch (Type)
+// {
+// case ooo::vba::word::WdFieldType::wdFieldFormCheckBox:
+// break;
+// case ooo::vba::word::WdFieldType::wdFieldFormDropDown:
+// break;
+// case ooo::vba::word::WdFieldType::wdFieldFormTextInput:
+// default:;
+// }
+//
+// return uno::Reference<ooo::vba::word::XFormField>(
+// new SwVbaFormField(mxParent, mxContext, m_xModel, *pFieldmark));
+// }
+
+// XEnumerationAccess
+uno::Type SwVbaFormFields::getElementType() { return cppu::UnoType<word::XFormField>::get(); }
+
+uno::Reference<container::XEnumeration> SwVbaFormFields::createEnumeration()
+{
+ return new FormFieldsEnumWrapper(m_xIndexAccess);
+}
+
+uno::Any SwVbaFormFields::createCollectionObject(const css::uno::Any& aSource) { return aSource; }
+
+OUString SwVbaFormFields::getServiceImplName() { return "SwVbaFormFields"; }
+
+css::uno::Sequence<OUString> SwVbaFormFields::getServiceNames()
+{
+ static uno::Sequence<OUString> const sNames{ "ooo.vba.word.FormFields" };
+ return sNames;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/vba/vbaformfields.hxx b/sw/source/ui/vba/vbaformfields.hxx
new file mode 100644
index 000000000000..22160dfb61cb
--- /dev/null
+++ b/sw/source/ui/vba/vbaformfields.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UI_VBA_VBAFORMFIELDS_HXX
+#define INCLUDED_SW_SOURCE_UI_VBA_VBAFORMFIELDS_HXX
+
+#include <ooo/vba/word/XFormFields.hpp>
+
+#include <vbahelper/vbacollectionimpl.hxx>
+
+typedef CollTestImplHelper<ooo::vba::word::XFormFields> SwVbaFormFields_BASE;
+
+class SwVbaFormFields : public SwVbaFormFields_BASE
+{
+private:
+ const css::uno::Reference<css::frame::XModel>& m_xModel;
+
+public:
+ /// @throws css::uno::RuntimeException
+ SwVbaFormFields(const css::uno::Reference<ov::XHelperInterface>& xParent,
+ const css::uno::Reference<css::uno::XComponentContext>& xContext,
+ const css::uno::Reference<css::frame::XModel>& xModel);
+
+ // XFormFields
+ virtual sal_Bool SAL_CALL getShaded() override;
+ virtual void SAL_CALL setShaded(sal_Bool bSet) override;
+ //virtual css::uno::Reference<ooo::vba::word::XFormField> SAL_CALL Add(const css::uno::Any& Range, sal_Int32 Type) override;
+
+ // XEnumerationAccess
+ virtual css::uno::Type SAL_CALL getElementType() override;
+ virtual css::uno::Reference<css::container::XEnumeration> SAL_CALL createEnumeration() override;
+
+ // SwVbaFormFields_BASE
+ virtual css::uno::Any createCollectionObject(const css::uno::Any& aSource) override;
+ virtual OUString getServiceImplName() override;
+ virtual css::uno::Sequence<OUString> getServiceNames() override;
+};
+
+#endif // INCLUDED_SW_SOURCE_UI_VBA_VBAFORMFIELDS_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */