oovbaapi/UnoApi_oovbaapi.mk                |    1 
 oovbaapi/ooo/vba/word/XTextInput.idl       |   38 ++++++++
 sw/Library_vbaswobj.mk                     |    1 
 sw/qa/core/data/docm/testVBA.docm          |binary
 sw/source/core/crsr/bookmark.cxx           |   41 +++++++++
 sw/source/core/inc/bookmark.hxx            |    6 +
 sw/source/ui/vba/vbaformfield.cxx          |    6 -
 sw/source/ui/vba/vbaformfieldtextinput.cxx |  130 +++++++++++++++++++++++++++++
 sw/source/ui/vba/vbaformfieldtextinput.hxx |   68 +++++++++++++++
 9 files changed, 288 insertions(+), 3 deletions(-)

New commits:
commit 1eb6b6320338057a25d014b3ee9abef730614402
Author:     Justin Luth <justin.l...@collabora.com>
AuthorDate: Thu Nov 3 17:59:14 2022 -0400
Commit:     Justin Luth <jl...@mail.com>
CommitDate: Tue Nov 22 22:03:14 2022 +0100

    tdf#151548 vba FormFields: Add basic word::XTextInput support
    
    make CppunitTest_sw_macros_test CPPUNIT_TEST_NAME=testVba
    
    This now allows MS Word Basic legacy text form fields
    to be controlled by VBA basic.
    -allows getting and setting the text string
    
    Change-Id: Ib4601d4e087233a3db257728374b362bb34d1ecb
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142262
    Tested-by: Jenkins
    Reviewed-by: Justin Luth <jl...@mail.com>
    Reviewed-by: Tor Lillqvist <t...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143083
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>

diff --git a/oovbaapi/UnoApi_oovbaapi.mk b/oovbaapi/UnoApi_oovbaapi.mk
index 400528dd75c6..6d83196dbcf6 100644
--- a/oovbaapi/UnoApi_oovbaapi.mk
+++ b/oovbaapi/UnoApi_oovbaapi.mk
@@ -1097,6 +1097,7 @@ $(eval $(call 
gb_UnoApi_add_idlfiles,oovbaapi,ooo/vba/word,\
        XTabStop \
        XTabStops \
        XTemplate \
+       XTextInput \
        XVariable \
        XVariables \
        XView \
diff --git a/oovbaapi/ooo/vba/word/XTextInput.idl 
b/oovbaapi/ooo/vba/word/XTextInput.idl
new file mode 100644
index 000000000000..ec7b3465cdd7
--- /dev/null
+++ b/oovbaapi/ooo/vba/word/XTextInput.idl
@@ -0,0 +1,38 @@
+/* -*- 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/.
+ */
+
+module ooo {  module vba {  module word {
+
+interface XTextInput
+{
+    interface ooo::vba::XHelperInterface;
+    interface com::sun::star::script::XDefaultProperty;
+
+    /// Default member: True if the specified form field object is a valid 
text input form field.
+    [attribute, readonly] boolean Valid;
+
+    /// Returns and sets the default text.
+    [attribute] string Default;
+    /// Returns the string that specifies how the text should be formated 
(like date/time, currency)
+    [attribute, readonly] string Format;
+    /// Returns the type of content: 
oovbaapi/ooo/vba/word/WdTextFormFieldType.idl
+    [attribute, readonly] long Type;
+    /// Returns and sets the width, in points, of the specified text input 
field.
+    [attribute] long Width;
+
+    /// Deletes the text from the text form field.
+    void Clear();
+    /// Sets options for the specified text form field.
+    void EditType( [in] long Type, [in] /*optional string*/ any Default,
+        [in] /*optional string*/ any Format, [in] /*optional boolean*/ any 
Enabled);
+};
+
+}; }; };
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/Library_vbaswobj.mk b/sw/Library_vbaswobj.mk
index f4264d365b89..fc84d7c7e81b 100644
--- a/sw/Library_vbaswobj.mk
+++ b/sw/Library_vbaswobj.mk
@@ -75,6 +75,7 @@ $(eval $(call gb_Library_add_exception_objects,vbaswobj,\
     sw/source/ui/vba/vbaformfield \
     sw/source/ui/vba/vbaformfields \
     sw/source/ui/vba/vbaformfieldcheckbox \
+    sw/source/ui/vba/vbaformfieldtextinput \
     sw/source/ui/vba/vbaframe \
     sw/source/ui/vba/vbaframes \
     sw/source/ui/vba/vbalistformat \
diff --git a/sw/qa/core/data/docm/testVBA.docm 
b/sw/qa/core/data/docm/testVBA.docm
index 58ac4e8bd3ae..9abcd091638d 100644
Binary files a/sw/qa/core/data/docm/testVBA.docm and 
b/sw/qa/core/data/docm/testVBA.docm differ
diff --git a/sw/source/core/crsr/bookmark.cxx b/sw/source/core/crsr/bookmark.cxx
index 65e1bb76b08b..9d2f670ce6c9 100644
--- a/sw/source/core/crsr/bookmark.cxx
+++ b/sw/source/core/crsr/bookmark.cxx
@@ -558,6 +558,7 @@ namespace sw::mark
 
     TextFieldmark::TextFieldmark(const SwPaM& rPaM, const OUString& rName)
         : Fieldmark(rPaM)
+        , m_pDocumentContentOperationsManager(nullptr)
     {
         if ( !rName.isEmpty() )
             m_aName = rName;
@@ -566,6 +567,7 @@ namespace sw::mark
     void TextFieldmark::InitDoc(SwDoc& io_rDoc,
             sw::mark::InsertMode const eMode, SwPosition const*const pSepPos)
     {
+        m_pDocumentContentOperationsManager = 
&io_rDoc.GetDocumentContentOperationsManager();
         if (eMode == sw::mark::InsertMode::New)
         {
             lcl_SetFieldMarks(*this, io_rDoc, CH_TXT_ATR_FIELDSTART, 
CH_TXT_ATR_FIELDEND, pSepPos);
@@ -590,6 +592,45 @@ namespace sw::mark
         sw::UpdateFramesForRemoveDeleteRedline(rDoc, tmp);
     }
 
+    OUString TextFieldmark::GetContent() const
+    {
+        const SwTextNode& rTextNode = 
*GetMarkEnd().nNode.GetNode().GetTextNode();
+        SwPosition const sepPos(sw::mark::FindFieldSep(*this));
+        const sal_Int32 nStart(sepPos.nContent.GetIndex());
+        const sal_Int32 nEnd(GetMarkEnd().nContent.GetIndex());
+
+        OUString sContent;
+        const sal_Int32 nLen = rTextNode.GetText().getLength();
+        if (nStart + 1 < nLen && nEnd <= nLen && nEnd > nStart + 2)
+            sContent = rTextNode.GetText().copy(nStart + 1, nEnd - nStart - 2);
+
+        return sContent;
+    }
+
+    void TextFieldmark::ReplaceContent(const OUString& sNewContent)
+    {
+        if (!m_pDocumentContentOperationsManager)
+            return;
+
+        SwPosition const sepPos(sw::mark::FindFieldSep(*this));
+        const sal_Int32 nStart(sepPos.nContent.GetIndex());
+        const sal_Int32 nEnd(GetMarkEnd().nContent.GetIndex());
+
+        const sal_Int32 nLen = 
GetMarkEnd().nNode.GetNode().GetTextNode()->GetText().getLength();
+        if (nStart + 1 < nLen && nEnd <= nLen && nEnd > nStart + 2)
+        {
+            SwPaM aFieldPam(GetMarkStart().nNode.GetNode(), nStart + 1,
+                            GetMarkStart().nNode.GetNode(), nEnd - 1);
+            m_pDocumentContentOperationsManager->ReplaceRange(aFieldPam, 
sNewContent, false);
+        }
+        else
+        {
+            SwPaM aFieldStartPam(GetMarkStart().nNode.GetNode(), nStart + 1);
+            m_pDocumentContentOperationsManager->InsertString(aFieldStartPam, 
sNewContent);
+        }
+        Invalidate();
+    }
+
     NonTextFieldmark::NonTextFieldmark(const SwPaM& rPaM)
         : Fieldmark(rPaM)
     { }
diff --git a/sw/source/core/inc/bookmark.hxx b/sw/source/core/inc/bookmark.hxx
index a3ce8f28466b..6e42d554ecf0 100644
--- a/sw/source/core/inc/bookmark.hxx
+++ b/sw/source/core/inc/bookmark.hxx
@@ -241,6 +241,12 @@ namespace sw::mark {
             TextFieldmark(const SwPaM& rPaM, const OUString& rName);
             virtual void InitDoc(SwDoc& io_rDoc, sw::mark::InsertMode eMode, 
SwPosition const* pSepPos) override;
             virtual void ReleaseDoc(SwDoc& rDoc) override;
+
+            OUString GetContent() const override;
+            void ReplaceContent(const OUString& sNewContent) override;
+
+        private:
+            sw::DocumentContentOperationsManager* 
m_pDocumentContentOperationsManager;
         };
 
         // Non text fieldmarks have no content between the start and end marks.
diff --git a/sw/source/ui/vba/vbaformfield.cxx 
b/sw/source/ui/vba/vbaformfield.cxx
index 35e8927fe02e..dd43e47b84bf 100644
--- a/sw/source/ui/vba/vbaformfield.cxx
+++ b/sw/source/ui/vba/vbaformfield.cxx
@@ -26,6 +26,7 @@
 
 #include "vbaformfield.hxx"
 #include "vbaformfieldcheckbox.hxx"
+#include "vbaformfieldtextinput.hxx"
 #include "wordvbahelper.hxx"
 
 using namespace ::ooo::vba;
@@ -67,9 +68,8 @@ uno::Any SAL_CALL SwVbaFormField::DropDown()
 
 uno::Any SAL_CALL SwVbaFormField::TextInput()
 {
-    // return uno::Any(uno::Reference<word::XTextInput>(
-    //     new SwVbaFormFieldTextInput(mxParent, mxContext, m_rFormField)));
-    return uno::Any();
+    return uno::Any(uno::Reference<word::XTextInput>(
+        new SwVbaFormFieldTextInput(mxParent, mxContext, m_rFormField)));
 }
 
 uno::Any SAL_CALL SwVbaFormField::Previous()
diff --git a/sw/source/ui/vba/vbaformfieldtextinput.cxx 
b/sw/source/ui/vba/vbaformfieldtextinput.cxx
new file mode 100644
index 000000000000..4f78761f4eb1
--- /dev/null
+++ b/sw/source/ui/vba/vbaformfieldtextinput.cxx
@@ -0,0 +1,130 @@
+/* -*- 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/.
+ */
+
+#include <ooo/vba/word/WdTextFormFieldType.hpp>
+
+#include <sal/log.hxx>
+
+#include "vbaformfieldtextinput.hxx"
+
+using namespace ::ooo::vba;
+using namespace ::com::sun::star;
+
+/**
+ * TextInput formfields are inline text objects that are only found in MS Word.
+ * They cannot be created in Excel or in Calc.
+ *
+ * Note that VBA might call this a TextInput, but it might not actually be one,
+ * so make good use of getValid()
+ */
+SwVbaFormFieldTextInput::SwVbaFormFieldTextInput(
+    const uno::Reference<ooo::vba::XHelperInterface>& rParent,
+    const uno::Reference<uno::XComponentContext>& rContext, 
sw::mark::IFieldmark& rFormField)
+    : SwVbaFormFieldTextInput_BASE(rParent, rContext)
+    , m_rTextInput(rFormField)
+{
+}
+
+SwVbaFormFieldTextInput::~SwVbaFormFieldTextInput() {}
+
+OUString SwVbaFormFieldTextInput::getDefaultPropertyName() { return "Valid"; }
+
+sal_Bool SwVbaFormFieldTextInput::getValid()
+{
+    return IDocumentMarkAccess::GetType(m_rTextInput)
+           == IDocumentMarkAccess::MarkType::TEXT_FIELDMARK;
+}
+
+OUString SwVbaFormFieldTextInput::getDefault()
+{
+    if (!getValid())
+        return OUString();
+
+    return m_rTextInput.GetContent();
+}
+
+void SwVbaFormFieldTextInput::setDefault(const OUString& sSet)
+{
+    // Hard to know what to do here, since LO doesn't have a default property 
for text input.
+    // This really only makes sense when macro-adding a text input.
+    // In that case, we want it to affect the actual text content.
+    // However, if the text has already been set by the user, then this 
shouldn't do anything.
+    // Assuming this is only ever set when adding a text input seems the 
sanest approach.
+    if (!getValid() || getDefault() == sSet)
+        return;
+
+    m_rTextInput.ReplaceContent(sSet);
+}
+
+OUString SwVbaFormFieldTextInput::getFormat()
+{
+    if (!getValid())
+        return OUString();
+
+    SAL_INFO("sw.vba", "SwVbaFormFieldTextInput::getFormat stub");
+    return OUString();
+}
+
+sal_Int32 SwVbaFormFieldTextInput::getType()
+{
+    if (!getValid())
+        return word::WdTextFormFieldType::wdRegularText;
+
+    SAL_INFO("sw.vba", "SwVbaFormFieldTextInput::getType stub");
+    return word::WdTextFormFieldType::wdRegularText;
+}
+
+sal_Int32 SwVbaFormFieldTextInput::getWidth()
+{
+    if (!getValid())
+        return 0;
+
+    SAL_INFO("sw.vba", "SwVbaFormFieldTextInput::getWidth stub");
+    return 11 * 50;
+}
+
+void SwVbaFormFieldTextInput::setWidth(sal_Int32 nWidth)
+{
+    if (!getValid())
+        return;
+
+    SAL_INFO("sw.vba", "SwVbaFormFieldTextInput::setWidth[" << nWidth << "] 
stub");
+}
+
+void SwVbaFormFieldTextInput::Clear()
+{
+    if (!getValid() || m_rTextInput.GetContent().isEmpty())
+        return;
+
+    m_rTextInput.ReplaceContent("");
+}
+
+void SwVbaFormFieldTextInput::EditType(sal_Int32 nType, const uno::Any& 
rDefault,
+                                       const uno::Any& rFormat, const 
uno::Any& rEnabled)
+{
+    OUString sDefault;
+    OUString sFormat;
+    bool bEnabled = true;
+    rDefault >>= sDefault;
+    rFormat >>= sFormat;
+    rEnabled >>= bEnabled;
+    SAL_INFO("sw.vba", "SwVbaFormFieldTextInput::EditType["
+                           << nType << "] sDefault[" << sDefault << "] 
sFormat[" << sFormat
+                           << "] bEnabled[" << bEnabled << "] stub");
+}
+
+OUString SwVbaFormFieldTextInput::getServiceImplName() { return 
"SwVbaFormFieldTextInput"; }
+
+uno::Sequence<OUString> SwVbaFormFieldTextInput::getServiceNames()
+{
+    static uno::Sequence<OUString> const aServiceNames{ 
"ooo.vba.word.TextInput" };
+    return aServiceNames;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/vba/vbaformfieldtextinput.hxx 
b/sw/source/ui/vba/vbaformfieldtextinput.hxx
new file mode 100644
index 000000000000..513cac64defd
--- /dev/null
+++ b/sw/source/ui/vba/vbaformfieldtextinput.hxx
@@ -0,0 +1,68 @@
+/* -*- 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/.
+ */
+#pragma once
+
+#include <ooo/vba/word/XTextInput.hpp>
+
+#include <vbahelper/vbahelperinterface.hxx>
+
+#include <IDocumentMarkAccess.hxx>
+
+typedef InheritedHelperInterfaceWeakImpl<ooo::vba::word::XTextInput> 
SwVbaFormFieldTextInput_BASE;
+
+class SwVbaFormFieldTextInput : public SwVbaFormFieldTextInput_BASE
+{
+private:
+    sw::mark::IFieldmark& m_rTextInput;
+
+public:
+    /// @throws css::uno::RuntimeException
+    SwVbaFormFieldTextInput(const 
css::uno::Reference<ooo::vba::XHelperInterface>& rParent,
+                            const 
css::uno::Reference<css::uno::XComponentContext>& rContext,
+                            sw::mark::IFieldmark& rFormField);
+    ~SwVbaFormFieldTextInput() override;
+
+    // XTextInput
+    OUString SAL_CALL getDefaultPropertyName() override;
+
+    // default member: True if the specified form field object is a valid text 
form field
+    sal_Bool SAL_CALL getValid() override;
+
+    // Returns and sets the default text string of the input box
+    OUString SAL_CALL getDefault() override;
+    void SAL_CALL setDefault(const OUString& bSet) override;
+    // Returns the format string for the current text
+    OUString SAL_CALL getFormat() override;
+    /*
+     * Returns the type of text form field.
+     * Possible return values are:
+     * wdCalculationText - Calculation text field,
+     * wdCurrentDateText - Current date text field,
+     * wdCurrentTimeText - Current time text field,
+     * wdDateText - Date text field,
+     * wdNumberText - Number text field,
+     * wdRegularText - Regular text field.
+     */
+    sal_Int32 SAL_CALL getType() override;
+    // Returns and sets the width, in points
+    sal_Int32 SAL_CALL getWidth() override;
+    void SAL_CALL setWidth(sal_Int32 nSet) override;
+
+    // Deletes the text from the text form field.
+    void SAL_CALL Clear() override;
+    // Sets the type, default text string, format string, and enabled status
+    void SAL_CALL EditType(sal_Int32 nType, const css::uno::Any& rDefault,
+                           const css::uno::Any& rFormat, const css::uno::Any& 
rEnabled) override;
+
+    // XHelperInterface
+    OUString getServiceImplName() override;
+    css::uno::Sequence<OUString> getServiceNames() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to