basctl/uiconfig/basicide/ui/managebreakpoints.ui |    8 
 cui/uiconfig/ui/charnamepage.ui                  |   35 +--
 cui/uiconfig/ui/paratabspage.ui                  |    8 
 include/vcl/weld.hxx                             |    1 
 sfx2/uiconfig/ui/newstyle.ui                     |    8 
 starmath/uiconfig/smath/ui/fontdialog.ui         |    8 
 vcl/source/app/salvtables.cxx                    |    3 
 vcl/source/window/builder.cxx                    |   28 --
 vcl/unx/gtk3/gtk3gtkinst.cxx                     |  245 +++++++++++++++++++----
 9 files changed, 225 insertions(+), 119 deletions(-)

New commits:
commit ab8e0f5832fa910f8b1abd36d7cb3929cbac2395
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Fri Jan 18 17:08:58 2019 +0000
Commit:     Caolán McNamara <caol...@redhat.com>
CommitDate: Mon Jan 21 16:32:19 2019 +0100

    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 <caol...@redhat.com>
    Tested-by: Caolán McNamara <caol...@redhat.com>

diff --git a/basctl/uiconfig/basicide/ui/managebreakpoints.ui 
b/basctl/uiconfig/basicide/ui/managebreakpoints.ui
index 66cbb93aeb05..d02926ecb825 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 25cfe43b6e68..f96bfb050c9c 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 bedddbba6fe4..08125e6ad959 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 bf9f92f7f906..dfb99158acac 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -929,6 +929,7 @@ public:
     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 9761b0047d7c..af9b7e14716f 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 d57b8e0d72cd..b9530b00c728 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 828468d23a70..fb010d50c55a 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -2108,6 +2108,7 @@ public:
         {
             SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
             m_xTreeView->Select(pEntry, true);
+            m_xTreeView->MakeVisible(pEntry);
         }
         enable_notify_events();
     }
@@ -3501,6 +3502,8 @@ IMPL_LINK(SalInstanceEntryTreeView, AutocompleteHdl, 
Edit&, rEdit, void)
         }
     }
 
+    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 76ed9da95b80..fe406ed94b6f 100644
--- a/vcl/source/window/builder.cxx
+++ b/vcl/source/window/builder.cxx
@@ -376,34 +376,8 @@ namespace weld
         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 3ee29fcf83e3..9b8741578b28 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 @@ public:
             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 @@ namespace
         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 @@ public:
         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 @@ private:
     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 @@ private:
 
     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");
+        }
+        if (m_bAutoComplete)
+        {
+            // now check for autocompletes
+            if (m_nAutoCompleteIdleId)
+                g_source_remove(m_nAutoCompleteIdleId);
+            m_nAutoCompleteIdleId = g_idle_add(idleAutoComplete, this);
         }
-        g_signal_stop_emission_by_name(pEntry, "insert-text");
     }
 
     static void signalChanged(GtkComboBox*, gpointer widget)
@@ -6579,7 +6662,26 @@ private:
         }
     }
 
-    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 @@ private:
         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 @@ public:
         , 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 @@ public:
 
         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 @@ public:
 
     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 @@ public:
         {
             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 @@ public:
         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 @@ public:
 
     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 @@ private:
     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 @@ private:
             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 @@ private:
                 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 @@ private:
         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 @@ public:
     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 @@ public:
         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);
     }
 };
 
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to