Resolves: tdf#122484 replace gtk autocomplete with vcl-alike autoselect

Change-Id: I941e32a973cdd1bc79e3739b24fdf834aa52cb11
Reviewed-on: https://gerrit.libreoffice.org/66628
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/basctl/uiconfig/basicide/ui/managebreakpoints.ui b/basctl/uiconfig/basicide/ui/managebreakpoints.ui
index 66cbb93..d02926e 100644
--- a/basctl/uiconfig/basicide/ui/managebreakpoints.ui
+++ b/basctl/uiconfig/basicide/ui/managebreakpoints.ui
@@ -10,14 +10,6 @@
      <column type="gchararray"/>
    </columns>
  </object>
  <object class="GtkEntryCompletion" id="entrycompletion1">
    <property name="model">liststore1</property>
    <property name="text_column">0</property>
    <property name="inline_completion">True</property>
    <property name="popup_completion">False</property>
    <property name="popup_set_width">False</property>
    <property name="popup_single_match">False</property>
  </object>
  <object class="GtkDialog" id="ManageBreakpointsDialog">
    <property name="can_focus">False</property>
    <property name="border_width">6</property>
diff --git a/cui/uiconfig/ui/charnamepage.ui b/cui/uiconfig/ui/charnamepage.ui
index 25cfe43..f96bfb0 100644
--- a/cui/uiconfig/ui/charnamepage.ui
+++ b/cui/uiconfig/ui/charnamepage.ui
@@ -10,14 +10,6 @@
      <column type="gchararray"/>
    </columns>
  </object>
  <object class="GtkEntryCompletion" id="entrycompletion1">
    <property name="model">liststore1</property>
    <property name="text_column">0</property>
    <property name="inline_completion">True</property>
    <property name="popup_completion">False</property>
    <property name="popup_set_width">False</property>
    <property name="popup_single_match">False</property>
  </object>
  <object class="GtkTreeStore" id="liststore2">
    <columns>
      <!-- column-name text -->
@@ -26,14 +18,6 @@
      <column type="gchararray"/>
    </columns>
  </object>
  <object class="GtkEntryCompletion" id="entrycompletion2">
    <property name="model">liststore2</property>
    <property name="text_column">0</property>
    <property name="inline_completion">True</property>
    <property name="popup_completion">False</property>
    <property name="popup_set_width">False</property>
    <property name="popup_single_match">False</property>
  </object>
  <object class="GtkTreeStore" id="liststore3">
    <columns>
      <!-- column-name text -->
@@ -42,14 +26,6 @@
      <column type="gchararray"/>
    </columns>
  </object>
  <object class="GtkEntryCompletion" id="entrycompletion3">
    <property name="model">liststore3</property>
    <property name="text_column">0</property>
    <property name="inline_completion">True</property>
    <property name="popup_completion">False</property>
    <property name="popup_set_width">False</property>
    <property name="popup_single_match">False</property>
  </object>
  <object class="GtkListStore" id="liststore4">
    <columns>
      <!-- column-name text -->
@@ -428,6 +404,7 @@
                    <child internal-child="entry">
                      <object class="GtkEntry">
                        <property name="can_focus">True</property>
                        <property name="activates_default">True</property>
                      </object>
                    </child>
                  </object>
@@ -558,6 +535,7 @@
                    <child internal-child="entry">
                      <object class="GtkEntry">
                        <property name="can_focus">True</property>
                        <property name="activates_default">True</property>
                      </object>
                    </child>
                  </object>
@@ -574,6 +552,7 @@
                    <child internal-child="entry">
                      <object class="GtkEntry">
                        <property name="can_focus">True</property>
                        <property name="activates_default">True</property>
                      </object>
                    </child>
                  </object>
@@ -590,6 +569,7 @@
                    <child internal-child="entry">
                      <object class="GtkEntry">
                        <property name="can_focus">True</property>
                        <property name="activates_default">True</property>
                      </object>
                    </child>
                  </object>
@@ -615,6 +595,7 @@
                    <child internal-child="entry">
                      <object class="GtkEntry">
                        <property name="can_focus">True</property>
                        <property name="activates_default">True</property>
                      </object>
                    </child>
                  </object>
@@ -766,6 +747,7 @@
                    <child internal-child="entry">
                      <object class="GtkEntry">
                        <property name="can_focus">True</property>
                        <property name="activates_default">True</property>
                      </object>
                    </child>
                  </object>
@@ -782,6 +764,7 @@
                    <child internal-child="entry">
                      <object class="GtkEntry">
                        <property name="can_focus">True</property>
                        <property name="activates_default">True</property>
                      </object>
                    </child>
                  </object>
@@ -798,6 +781,7 @@
                    <child internal-child="entry">
                      <object class="GtkEntry">
                        <property name="can_focus">True</property>
                        <property name="activates_default">True</property>
                      </object>
                    </child>
                  </object>
@@ -973,6 +957,7 @@
                    <child internal-child="entry">
                      <object class="GtkEntry">
                        <property name="can_focus">True</property>
                        <property name="activates_default">True</property>
                      </object>
                    </child>
                  </object>
@@ -989,6 +974,7 @@
                    <child internal-child="entry">
                      <object class="GtkEntry">
                        <property name="can_focus">True</property>
                        <property name="activates_default">True</property>
                      </object>
                    </child>
                  </object>
@@ -1005,6 +991,7 @@
                    <child internal-child="entry">
                      <object class="GtkEntry">
                        <property name="can_focus">True</property>
                        <property name="activates_default">True</property>
                      </object>
                    </child>
                  </object>
diff --git a/cui/uiconfig/ui/paratabspage.ui b/cui/uiconfig/ui/paratabspage.ui
index bedddbb..08125e6 100644
--- a/cui/uiconfig/ui/paratabspage.ui
+++ b/cui/uiconfig/ui/paratabspage.ui
@@ -10,14 +10,6 @@
      <column type="gchararray"/>
    </columns>
  </object>
  <object class="GtkEntryCompletion" id="entrycompletion1">
    <property name="model">liststore1</property>
    <property name="text_column">0</property>
    <property name="inline_completion">True</property>
    <property name="popup_completion">False</property>
    <property name="popup_set_width">False</property>
    <property name="popup_single_match">False</property>
  </object>
  <object class="GtkAdjustment" id="adjustment1">
    <property name="lower">-56</property>
    <property name="upper">56</property>
diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index bf9f92f..dfb99158 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -929,6 +929,7 @@
    virtual int get_active() const override { return m_xTreeView->get_selected_index(); }
    virtual void set_active(int pos) override
    {
        m_xTreeView->set_cursor(pos);
        m_xTreeView->select(pos);
        m_xEntry->set_text(m_xTreeView->get_selected_text());
    }
diff --git a/sfx2/uiconfig/ui/newstyle.ui b/sfx2/uiconfig/ui/newstyle.ui
index 9761b00..af9b7e1 100644
--- a/sfx2/uiconfig/ui/newstyle.ui
+++ b/sfx2/uiconfig/ui/newstyle.ui
@@ -10,14 +10,6 @@
      <column type="gchararray"/>
    </columns>
  </object>
  <object class="GtkEntryCompletion" id="entrycompletion1">
    <property name="model">liststore1</property>
    <property name="text_column">0</property>
    <property name="inline_completion">True</property>
    <property name="popup_completion">False</property>
    <property name="popup_set_width">False</property>
    <property name="popup_single_match">False</property>
  </object>
  <object class="GtkDialog" id="CreateStyleDialog">
    <property name="can_focus">False</property>
    <property name="border_width">6</property>
diff --git a/starmath/uiconfig/smath/ui/fontdialog.ui b/starmath/uiconfig/smath/ui/fontdialog.ui
index d57b8e0..b9530b00 100644
--- a/starmath/uiconfig/smath/ui/fontdialog.ui
+++ b/starmath/uiconfig/smath/ui/fontdialog.ui
@@ -10,14 +10,6 @@
      <column type="gchararray"/>
    </columns>
  </object>
  <object class="GtkEntryCompletion" id="entrycompletion1">
    <property name="model">liststore1</property>
    <property name="text_column">0</property>
    <property name="inline_completion">True</property>
    <property name="popup_completion">False</property>
    <property name="popup_set_width">False</property>
    <property name="popup_single_match">False</property>
  </object>
  <object class="GtkDialog" id="FontDialog">
    <property name="can_focus">False</property>
    <property name="border_width">6</property>
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index 828468d..fb010d5 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -2108,6 +2108,7 @@
        {
            SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
            m_xTreeView->Select(pEntry, true);
            m_xTreeView->MakeVisible(pEntry);
        }
        enable_notify_events();
    }
@@ -3501,6 +3502,8 @@
        }
    }

    m_xTreeView->select(nPos);

    if (nPos != -1)
    {
        OUString aText = m_xTreeView->get_text(nPos);
diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx
index 76ed9da..fe406ed 100644
--- a/vcl/source/window/builder.cxx
+++ b/vcl/source/window/builder.cxx
@@ -376,34 +376,8 @@
        m_aChangeHdl.Call(*this);
    }

    void EntryTreeView::EntryModifyHdl(weld::Entry& rBox)
    IMPL_LINK_NOARG(EntryTreeView, ModifyHdl, weld::Entry&, void)
    {
        OUString sText(rBox.get_text());
        int nExists = m_xTreeView->find_text(sText);
        if (nExists != -1)
        {
            m_xTreeView->select(nExists);
            return;
        }

        m_xTreeView->select(-1);
        if (sText.isEmpty())
            return;

        int nCount = m_xTreeView->n_children();
        for (int i = 0; i < nCount; ++i)
        {
            if (m_xTreeView->get_text(i).startsWith(sText))
            {
                m_xTreeView->select(i);
                break;
            }
        }
    }

    IMPL_LINK(EntryTreeView, ModifyHdl, weld::Entry&, rBox, void)
    {
        EntryModifyHdl(rBox);
        m_aChangeHdl.Call(*this);
    }

diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index 3ee29fc..9b87415 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -37,6 +37,7 @@
#include <tools/stream.hxx>
#include <unotools/resmgr.hxx>
#include <vcl/ImageTree.hxx>
#include <vcl/i18nhelp.hxx>
#include <vcl/quickselectionengine.hxx>
#include <vcl/mnemonic.hxx>
#include <vcl/syswin.hxx>
@@ -221,7 +222,7 @@
            OUString aStr;
            gchar *pText = gtk_clipboard_wait_for_text(clipboard);
            if (pText)
                aStr = OUString(pText, rtl_str_getLength(pText), RTL_TEXTENCODING_UTF8);
                aStr = OUString(pText, strlen(pText), RTL_TEXTENCODING_UTF8);
            g_free(pText);
            css::uno::Any aRet;
            aRet <<= aStr.replaceAll("\r\n", "\n");
@@ -4867,6 +4868,29 @@
        g_free(pName2);
        return ret;
    }

    int starts_with(GtkTreeModel* pTreeModel, const OUString& rStr, int col, int nStartRow)
    {
        GtkTreeIter iter;
        if (!gtk_tree_model_iter_nth_child(pTreeModel, &iter, nullptr, nStartRow))
            return -1;

        const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
        int nRet = nStartRow;
        do
        {
            gchar* pStr;
            gtk_tree_model_get(pTreeModel, &iter, col, &pStr, -1);
            OUString aStr(pStr, pStr ? strlen(pStr) : 0, RTL_TEXTENCODING_UTF8);
            g_free(pStr);
            const bool bMatch = rI18nHelper.MatchString(rStr, aStr);
            if (bMatch)
                return nRet;
            ++nRet;
        } while (gtk_tree_model_iter_next(pTreeModel, &iter));

        return -1;
    }
}

struct GtkInstanceTreeIter : public weld::TreeIter
@@ -5714,6 +5738,11 @@
        return gtk_tree_selection_count_selected_rows(gtk_tree_view_get_selection(m_pTreeView));
    }

    int starts_with(const OUString& rStr, int col, int nStartRow)
    {
        return ::starts_with(GTK_TREE_MODEL(m_pTreeStore), rStr, col, nStartRow);
    }

    virtual void disable_notify_events() override
    {
        g_signal_handler_block(gtk_tree_view_get_selection(m_pTreeView), m_nChangedSignalId);
@@ -6522,11 +6551,56 @@
    vcl::QuickSelectionEngine m_aQuickSelectionEngine;
    std::vector<int> m_aSeparatorRows;
    gboolean m_bPopupActive;
    bool m_bAutoComplete;
    gulong m_nChangedSignalId;
    gulong m_nPopupShownSignalId;
    gulong m_nKeyPressEventSignalId;
    gulong m_nEntryInsertTextSignalId;
    gulong m_nEntryActivateSignalId;
    gulong m_nEntryFocusOutSignalId;
    guint m_nAutoCompleteIdleId;

    static gboolean idleAutoComplete(gpointer widget)
    {
        GtkInstanceComboBox* pThis = static_cast<GtkInstanceComboBox*>(widget);
        pThis->auto_complete();
        return false;
    }

    void auto_complete()
    {
        m_nAutoCompleteIdleId = 0;
        OUString aStartText = get_active_text();
        int nStartPos, nEndPos;
        get_entry_selection_bounds(nStartPos, nEndPos);
        int nMaxSelection = std::max(nStartPos, nEndPos);
        if (nMaxSelection != aStartText.getLength())
            return;

        disable_notify_events();
        int nActive = get_active();
        int nStart = nActive;

        if (nStart == -1)
            nStart = 0;

        // Try match case insensitive from current position
        int nPos = starts_with(m_pTreeModel, aStartText, 0, nStart);
        if (nPos == -1 && nStart != 0)
        {
            // Try match case insensitive, but from start
            nPos = starts_with(m_pTreeModel, aStartText, 0, 0);
        }

        if (nPos != -1)
        {
            OUString aText = get_text(nPos);
            if (aText != aStartText)
                set_active_text(aText);
            select_entry_region(aText.getLength(), aStartText.getLength());
        }
        enable_notify_events();
    }

    static void signalEntryInsertText(GtkEntry* pEntry, const gchar* pNewText, gint nNewTextLength,
                                      gint* position, gpointer widget)
@@ -6538,18 +6612,27 @@

    void signal_entry_insert_text(GtkEntry* pEntry, const gchar* pNewText, gint nNewTextLength, gint* position)
    {
        if (!m_aEntryInsertTextHdl.IsSet())
            return;
        OUString sText(pNewText, nNewTextLength, RTL_TEXTENCODING_UTF8);
        const bool bContinue = m_aEntryInsertTextHdl.Call(sText);
        if (bContinue && !sText.isEmpty())
        // first filter inserted text
        if (m_aEntryInsertTextHdl.IsSet())
        {
            OString sFinalText(OUStringToOString(sText, RTL_TEXTENCODING_UTF8));
            g_signal_handlers_block_by_func(pEntry, gpointer(signalEntryInsertText), this);
            gtk_editable_insert_text(GTK_EDITABLE(pEntry), sFinalText.getStr(), sFinalText.getLength(), position);
            g_signal_handlers_unblock_by_func(pEntry, gpointer(signalEntryInsertText), this);
            OUString sText(pNewText, nNewTextLength, RTL_TEXTENCODING_UTF8);
            const bool bContinue = m_aEntryInsertTextHdl.Call(sText);
            if (bContinue && !sText.isEmpty())
            {
                OString sFinalText(OUStringToOString(sText, RTL_TEXTENCODING_UTF8));
                g_signal_handlers_block_by_func(pEntry, gpointer(signalEntryInsertText), this);
                gtk_editable_insert_text(GTK_EDITABLE(pEntry), sFinalText.getStr(), sFinalText.getLength(), position);
                g_signal_handlers_unblock_by_func(pEntry, gpointer(signalEntryInsertText), this);
            }
            g_signal_stop_emission_by_name(pEntry, "insert-text");
        }
        g_signal_stop_emission_by_name(pEntry, "insert-text");
        if (m_bAutoComplete)
        {
            // now check for autocompletes
            if (m_nAutoCompleteIdleId)
                g_source_remove(m_nAutoCompleteIdleId);
            m_nAutoCompleteIdleId = g_idle_add(idleAutoComplete, this);
        }
    }

    static void signalChanged(GtkComboBox*, gpointer widget)
@@ -6579,7 +6662,26 @@
        }
    }

    static void signalEntryActivate(GtkComboBox*, gpointer widget)
    static void signalEntryFocusOut(GtkWidget*, GdkEvent*, gpointer widget)
    {
        GtkInstanceComboBox* pThis = static_cast<GtkInstanceComboBox*>(widget);
        pThis->signal_entry_focus_out();
    }

    void signal_entry_focus_out()
    {
        // if we have an untidy selection on losing focus remove the selection
        int nStartPos, nEndPos;
        if (get_entry_selection_bounds(nStartPos, nEndPos))
        {
            int nMin = std::min(nStartPos, nEndPos);
            int nMax = std::max(nStartPos, nEndPos);
            if (nMin != 0 || nMax != get_active_text().getLength())
                select_entry_region(0, 0);
        }
    }

    static void signalEntryActivate(GtkEntry*, gpointer widget)
    {
        GtkInstanceComboBox* pThis = static_cast<GtkInstanceComboBox*>(widget);
        pThis->signal_entry_activate();
@@ -6649,20 +6751,6 @@
        return GTK_ENTRY(pChild);
    }

    void setup_completion(GtkEntry* pEntry)
    {
        if (gtk_entry_get_completion(pEntry))
            return;
        GtkEntryCompletion* pCompletion = gtk_entry_completion_new();
        gtk_entry_completion_set_model(pCompletion, m_pTreeModel);
        gtk_entry_completion_set_text_column(pCompletion, 0);
        gtk_entry_completion_set_inline_selection(pCompletion, true);
        gtk_entry_completion_set_inline_completion(pCompletion, true);
        gtk_entry_completion_set_popup_completion(pCompletion, false);
        gtk_entry_set_completion(pEntry, pCompletion);
        g_object_unref(pCompletion);
    }

    bool separator_function(int nIndex)
    {
        return std::find(m_aSeparatorRows.begin(), m_aSeparatorRows.end(), nIndex) != m_aSeparatorRows.end();
@@ -6822,8 +6910,10 @@
        , m_pMenu(nullptr)
        , m_aQuickSelectionEngine(*this)
        , m_bPopupActive(false)
        , m_bAutoComplete(false)
        , m_nChangedSignalId(g_signal_connect(m_pComboBox, "changed", G_CALLBACK(signalChanged), this))
        , m_nPopupShownSignalId(g_signal_connect(m_pComboBox, "notify::popup-shown", G_CALLBACK(signalPopupShown), this))
        , m_nAutoCompleteIdleId(0)
    {
        GList* cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(m_pComboBox));
        if (!g_list_length(cells))
@@ -6848,15 +6938,17 @@

        if (GtkEntry* pEntry = get_entry())
        {
            setup_completion(pEntry);
            m_bAutoComplete = true;
            m_nEntryInsertTextSignalId = g_signal_connect(pEntry, "insert-text", G_CALLBACK(signalEntryInsertText), this);
            m_nEntryActivateSignalId = g_signal_connect(pEntry, "activate", G_CALLBACK(signalEntryActivate), this);
            m_nEntryFocusOutSignalId = g_signal_connect(pEntry, "focus-out-event", G_CALLBACK(signalEntryFocusOut), this);
            m_nKeyPressEventSignalId = 0;
        }
        else
        {
            m_nEntryInsertTextSignalId = 0;
            m_nEntryActivateSignalId = 0;
            m_nEntryFocusOutSignalId = 0;
            m_nKeyPressEventSignalId = g_signal_connect(m_pWidget, "key-press-event", G_CALLBACK(signalKeyPress), this);
        }
        install_menu_typeahead();
@@ -7118,12 +7210,7 @@

    virtual void set_entry_completion(bool bEnable) override
    {
        GtkEntry* pEntry = get_entry();
        assert(pEntry);
        if (bEnable)
            setup_completion(pEntry);
        else
            gtk_entry_set_completion(pEntry, nullptr);
        m_bAutoComplete = bEnable;
    }

    virtual void disable_notify_events() override
@@ -7132,6 +7219,7 @@
        {
            g_signal_handler_block(pEntry, m_nEntryInsertTextSignalId);
            g_signal_handler_block(pEntry, m_nEntryActivateSignalId);
            g_signal_handler_block(pEntry, m_nEntryFocusOutSignalId);
        }
        else
            g_signal_handler_block(m_pComboBox, m_nKeyPressEventSignalId);
@@ -7148,6 +7236,7 @@
        if (GtkEntry* pEntry = get_entry())
        {
            g_signal_handler_unblock(pEntry, m_nEntryActivateSignalId);
            g_signal_handler_unblock(pEntry, m_nEntryFocusOutSignalId);
            g_signal_handler_unblock(pEntry, m_nEntryInsertTextSignalId);
        }
        else
@@ -7191,10 +7280,13 @@

    virtual ~GtkInstanceComboBox() override
    {
        if (m_nAutoCompleteIdleId)
            g_source_remove(m_nAutoCompleteIdleId);
        if (GtkEntry* pEntry = get_entry())
        {
            g_signal_handler_disconnect(pEntry, m_nEntryInsertTextSignalId);
            g_signal_handler_disconnect(pEntry, m_nEntryActivateSignalId);
            g_signal_handler_disconnect(pEntry, m_nEntryFocusOutSignalId);
        }
        else
            g_signal_handler_disconnect(m_pComboBox, m_nKeyPressEventSignalId);
@@ -7209,6 +7301,8 @@
    GtkInstanceEntry* m_pEntry;
    GtkInstanceTreeView* m_pTreeView;
    gulong m_nKeyPressSignalId;
    gulong m_nEntryInsertTextSignalId;
    guint m_nAutoCompleteIdleId;

    gboolean signal_key_press(GdkEventKey* pEvent)
    {
@@ -7216,10 +7310,11 @@
            pEvent->keyval == GDK_KEY_KP_Down || pEvent->keyval == GDK_KEY_Down || pEvent->keyval == GDK_KEY_KP_Page_Down || pEvent->keyval == GDK_KEY_Page_Down)
        {
            gboolean ret;
            m_pTreeView->disable_notify_events();
            disable_notify_events();
            GtkWidget* pWidget = m_pTreeView->getWidget();
            if (m_pTreeView->get_selected_index() == -1)
            {
                m_pTreeView->set_cursor(0);
                m_pTreeView->select(0);
                m_xEntry->set_text(m_xTreeView->get_selected_text());
            }
@@ -7231,7 +7326,7 @@
                gtk_widget_grab_focus(m_pEntry->getWidget());
            }
            m_xEntry->select_region(0, -1);
            m_pTreeView->enable_notify_events();
            enable_notify_events();
            m_pEntry->fire_signal_changed();
            return true;
        }
@@ -7244,16 +7339,76 @@
        return pThis->signal_key_press(pEvent);
    }

    static gboolean idleAutoComplete(gpointer widget)
    {
        GtkInstanceEntryTreeView* pThis = static_cast<GtkInstanceEntryTreeView*>(widget);
        pThis->auto_complete();
        return false;
    }

    void auto_complete()
    {
        m_nAutoCompleteIdleId = 0;
        OUString aStartText = get_active_text();
        int nStartPos, nEndPos;
        get_entry_selection_bounds(nStartPos, nEndPos);
        int nMaxSelection = std::max(nStartPos, nEndPos);
        if (nMaxSelection != aStartText.getLength())
            return;

        disable_notify_events();
        int nActive = get_active();
        int nStart = nActive;

        if (nStart == -1)
            nStart = 0;

        // Try match case insensitive from current position
        int nPos = m_pTreeView->starts_with(aStartText, 0, nStart);
        if (nPos == -1 && nStart != 0)
        {
            // Try match case insensitive, but from start
            nPos = m_pTreeView->starts_with(aStartText, 0, 0);
        }

        if (nPos != -1)
        {
            OUString aText = get_text(nPos);
            if (aText != aStartText)
                set_active_text(aText);
            select_entry_region(aText.getLength(), aStartText.getLength());
        }
        enable_notify_events();
    }

    void signal_entry_insert_text(GtkEntry*, const gchar*, gint, gint*)
    {
        // now check for autocompletes
        if (m_nAutoCompleteIdleId)
            g_source_remove(m_nAutoCompleteIdleId);
        m_nAutoCompleteIdleId = g_idle_add(idleAutoComplete, this);
    }

    static void signalEntryInsertText(GtkEntry* pEntry, const gchar* pNewText, gint nNewTextLength,
                                      gint* position, gpointer widget)
    {
        GtkInstanceEntryTreeView* pThis = static_cast<GtkInstanceEntryTreeView*>(widget);
        pThis->signal_entry_insert_text(pEntry, pNewText, nNewTextLength, position);
    }


public:
    GtkInstanceEntryTreeView(GtkContainer* pContainer, bool bTakeOwnership, std::unique_ptr<weld::Entry> xEntry, std::unique_ptr<weld::TreeView> xTreeView)
        : EntryTreeView(std::move(xEntry), std::move(xTreeView))
        , GtkInstanceContainer(pContainer, bTakeOwnership)
        , m_pEntry(dynamic_cast<GtkInstanceEntry*>(m_xEntry.get()))
        , m_pTreeView(dynamic_cast<GtkInstanceTreeView*>(m_xTreeView.get()))
        , m_nAutoCompleteIdleId(0)
    {
        assert(m_pEntry);
        GtkWidget* pWidget = m_pEntry->getWidget();
        m_nKeyPressSignalId = g_signal_connect(pWidget, "key-press-event", G_CALLBACK(signalKeyPress), this);
        m_nEntryInsertTextSignalId = g_signal_connect(pWidget, "insert-text", G_CALLBACK(signalEntryInsertText), this);
    }

    virtual void insert_separator(int /*pos*/) override
@@ -7272,7 +7427,6 @@
    virtual void set_entry_completion(bool bEnable) override
    {
        assert(!bEnable && "not implemented yet"); (void)bEnable;
        gtk_entry_set_completion(GTK_ENTRY(m_pEntry->getWidget()), nullptr);
    }

    virtual void grab_focus() override { m_xEntry->grab_focus(); }
@@ -7287,10 +7441,29 @@
        m_xEntry->connect_focus_out(rLink);
    }

    virtual void disable_notify_events() override
    {
        GtkWidget* pWidget = m_pEntry->getWidget();
        g_signal_handler_block(pWidget, m_nEntryInsertTextSignalId);
        g_signal_handler_block(pWidget, m_nKeyPressSignalId);
        m_pTreeView->disable_notify_events();
        GtkInstanceContainer::disable_notify_events();
    }

    virtual void enable_notify_events() override
    {
        GtkWidget* pWidget = m_pEntry->getWidget();
        g_signal_handler_unblock(pWidget, m_nKeyPressSignalId);
        g_signal_handler_unblock(pWidget, m_nEntryInsertTextSignalId);
        m_pTreeView->enable_notify_events();
        GtkInstanceContainer::disable_notify_events();
    }

    virtual ~GtkInstanceEntryTreeView() override
    {
        GtkWidget* pWidget = m_pEntry->getWidget();
        g_signal_handler_disconnect(pWidget, m_nKeyPressSignalId);
        g_signal_handler_disconnect(pWidget, m_nEntryInsertTextSignalId);
    }
};