]> Pileus Git - ~andy/gtk/blob - gtk/gtkentrycompletion.c
Fix entry completion window sizing
[~andy/gtk] / gtk / gtkentrycompletion.c
1 /* gtkentrycompletion.c
2  * Copyright (C) 2003  Kristian Rietveld  <kris@gtk.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "config.h"
21
22 #include "gtkentrycompletion.h"
23
24 #include "gtkentryprivate.h"
25 #include "gtkcelllayout.h"
26
27 #include "gtkintl.h"
28 #include "gtkcellrenderertext.h"
29 #include "gtkframe.h"
30 #include "gtktreeselection.h"
31 #include "gtktreeview.h"
32 #include "gtkscrolledwindow.h"
33 #include "gtksizerequest.h"
34 #include "gtkvbox.h"
35 #include "gtkwindow.h"
36 #include "gtkentry.h"
37 #include "gtkmain.h"
38 #include "gtkmarshalers.h"
39
40 #include "gtkprivate.h"
41
42 #include <string.h>
43
44
45 /* signals */
46 enum
47 {
48   INSERT_PREFIX,
49   MATCH_SELECTED,
50   ACTION_ACTIVATED,
51   CURSOR_ON_MATCH,
52   LAST_SIGNAL
53 };
54
55 /* properties */
56 enum
57 {
58   PROP_0,
59   PROP_MODEL,
60   PROP_MINIMUM_KEY_LENGTH,
61   PROP_TEXT_COLUMN,
62   PROP_INLINE_COMPLETION,
63   PROP_POPUP_COMPLETION,
64   PROP_POPUP_SET_WIDTH,
65   PROP_POPUP_SINGLE_MATCH,
66   PROP_INLINE_SELECTION
67 };
68
69
70 static void                                                             gtk_entry_completion_cell_layout_init    (GtkCellLayoutIface      *iface);
71 static void     gtk_entry_completion_set_property        (GObject      *object,
72                                                           guint         prop_id,
73                                                           const GValue *value,
74                                                           GParamSpec   *pspec);
75 static void     gtk_entry_completion_get_property        (GObject      *object,
76                                                           guint         prop_id,
77                                                           GValue       *value,
78                                                           GParamSpec   *pspec);
79 static void                                                             gtk_entry_completion_finalize            (GObject                 *object);
80
81 static void     gtk_entry_completion_pack_start          (GtkCellLayout         *cell_layout,
82                                                           GtkCellRenderer       *cell,
83                                                           gboolean               expand);
84 static void     gtk_entry_completion_pack_end            (GtkCellLayout         *cell_layout,
85                                                           GtkCellRenderer       *cell,
86                                                           gboolean               expand);
87 static void                                                                      gtk_entry_completion_clear               (GtkCellLayout           *cell_layout);
88 static void     gtk_entry_completion_add_attribute       (GtkCellLayout         *cell_layout,
89                                                           GtkCellRenderer       *cell,
90                                                           const char            *attribute,
91                                                           gint                   column);
92 static void     gtk_entry_completion_set_cell_data_func  (GtkCellLayout         *cell_layout,
93                                                           GtkCellRenderer       *cell,
94                                                           GtkCellLayoutDataFunc  func,
95                                                           gpointer               func_data,
96                                                           GDestroyNotify         destroy);
97 static void     gtk_entry_completion_clear_attributes    (GtkCellLayout         *cell_layout,
98                                                           GtkCellRenderer       *cell);
99 static void     gtk_entry_completion_reorder             (GtkCellLayout         *cell_layout,
100                                                           GtkCellRenderer       *cell,
101                                                           gint                   position);
102 static GList *  gtk_entry_completion_get_cells           (GtkCellLayout         *cell_layout);
103
104 static gboolean gtk_entry_completion_visible_func        (GtkTreeModel       *model,
105                                                           GtkTreeIter        *iter,
106                                                           gpointer            data);
107 static gboolean gtk_entry_completion_popup_key_event     (GtkWidget          *widget,
108                                                           GdkEventKey        *event,
109                                                           gpointer            user_data);
110 static gboolean gtk_entry_completion_popup_button_press  (GtkWidget          *widget,
111                                                           GdkEventButton     *event,
112                                                           gpointer            user_data);
113 static gboolean gtk_entry_completion_list_button_press   (GtkWidget          *widget,
114                                                           GdkEventButton     *event,
115                                                           gpointer            user_data);
116 static gboolean gtk_entry_completion_action_button_press (GtkWidget          *widget,
117                                                           GdkEventButton     *event,
118                                                           gpointer            user_data);
119 static void     gtk_entry_completion_selection_changed   (GtkTreeSelection   *selection,
120                                                           gpointer            data);
121 static gboolean gtk_entry_completion_list_enter_notify   (GtkWidget          *widget,
122                                                           GdkEventCrossing   *event,
123                                                           gpointer            data);
124 static gboolean gtk_entry_completion_list_motion_notify  (GtkWidget          *widget,
125                                                           GdkEventMotion     *event,
126                                                           gpointer            data);
127 static void     gtk_entry_completion_insert_action       (GtkEntryCompletion *completion,
128                                                           gint                index,
129                                                           const gchar        *string,
130                                                           gboolean            markup);
131 static void     gtk_entry_completion_action_data_func    (GtkTreeViewColumn  *tree_column,
132                                                           GtkCellRenderer    *cell,
133                                                           GtkTreeModel       *model,
134                                                           GtkTreeIter        *iter,
135                                                           gpointer            data);
136
137 static gboolean gtk_entry_completion_match_selected      (GtkEntryCompletion *completion,
138                                                           GtkTreeModel       *model,
139                                                           GtkTreeIter        *iter);
140 static gboolean gtk_entry_completion_real_insert_prefix  (GtkEntryCompletion *completion,
141                                                           const gchar        *prefix);
142 static gboolean gtk_entry_completion_cursor_on_match     (GtkEntryCompletion *completion,
143                                                           GtkTreeModel       *model,
144                                                           GtkTreeIter        *iter);
145 static gboolean gtk_entry_completion_insert_completion   (GtkEntryCompletion *completion,
146                                                           GtkTreeModel       *model,
147                                                           GtkTreeIter        *iter);
148 static void     gtk_entry_completion_insert_completion_text (GtkEntryCompletion *completion,
149                                                              const gchar *text);
150
151 static guint entry_completion_signals[LAST_SIGNAL] = { 0 };
152
153 /* GtkBuildable */
154 static void     gtk_entry_completion_buildable_init      (GtkBuildableIface  *iface);
155
156 G_DEFINE_TYPE_WITH_CODE (GtkEntryCompletion, gtk_entry_completion, G_TYPE_OBJECT,
157                          G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
158                                                 gtk_entry_completion_cell_layout_init)
159                          G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
160                                                 gtk_entry_completion_buildable_init))
161
162
163 static void
164 gtk_entry_completion_class_init (GtkEntryCompletionClass *klass)
165 {
166   GObjectClass *object_class;
167
168   object_class = (GObjectClass *)klass;
169
170   object_class->set_property = gtk_entry_completion_set_property;
171   object_class->get_property = gtk_entry_completion_get_property;
172   object_class->finalize = gtk_entry_completion_finalize;
173
174   klass->match_selected = gtk_entry_completion_match_selected;
175   klass->insert_prefix = gtk_entry_completion_real_insert_prefix;
176   klass->cursor_on_match = gtk_entry_completion_cursor_on_match;
177
178   /**
179    * GtkEntryCompletion::insert-prefix:
180    * @widget: the object which received the signal
181    * @prefix: the common prefix of all possible completions
182    *
183    * Gets emitted when the inline autocompletion is triggered.
184    * The default behaviour is to make the entry display the
185    * whole prefix and select the newly inserted part.
186    *
187    * Applications may connect to this signal in order to insert only a
188    * smaller part of the @prefix into the entry - e.g. the entry used in
189    * the #GtkFileChooser inserts only the part of the prefix up to the
190    * next '/'.
191    *
192    * Return value: %TRUE if the signal has been handled
193    *
194    * Since: 2.6
195    */
196   entry_completion_signals[INSERT_PREFIX] =
197     g_signal_new (I_("insert-prefix"),
198                   G_TYPE_FROM_CLASS (klass),
199                   G_SIGNAL_RUN_LAST,
200                   G_STRUCT_OFFSET (GtkEntryCompletionClass, insert_prefix),
201                   _gtk_boolean_handled_accumulator, NULL,
202                   _gtk_marshal_BOOLEAN__STRING,
203                   G_TYPE_BOOLEAN, 1,
204                   G_TYPE_STRING);
205
206   /**
207    * GtkEntryCompletion::match-selected:
208    * @widget: the object which received the signal
209    * @model: the #GtkTreeModel containing the matches
210    * @iter: a #GtkTreeIter positioned at the selected match
211    *
212    * Gets emitted when a match from the list is selected.
213    * The default behaviour is to replace the contents of the
214    * entry with the contents of the text column in the row
215    * pointed to by @iter.
216    *
217    * Return value: %TRUE if the signal has been handled
218    *
219    * Since: 2.4
220    */
221   entry_completion_signals[MATCH_SELECTED] =
222     g_signal_new (I_("match-selected"),
223                   G_TYPE_FROM_CLASS (klass),
224                   G_SIGNAL_RUN_LAST,
225                   G_STRUCT_OFFSET (GtkEntryCompletionClass, match_selected),
226                   _gtk_boolean_handled_accumulator, NULL,
227                   _gtk_marshal_BOOLEAN__OBJECT_BOXED,
228                   G_TYPE_BOOLEAN, 2,
229                   GTK_TYPE_TREE_MODEL,
230                   GTK_TYPE_TREE_ITER);
231
232   /**
233    * GtkEntryCompletion::cursor-on-match:
234    * @widget: the object which received the signal
235    * @model: the #GtkTreeModel containing the matches
236    * @iter: a #GtkTreeIter positioned at the selected match
237    *
238    * Gets emitted when a match from the cursor is on a match
239    * of the list. The default behaviour is to replace the contents
240    * of the entry with the contents of the text column in the row
241    * pointed to by @iter.
242    *
243    * Return value: %TRUE if the signal has been handled
244    *
245    * Since: 2.12
246    */
247   entry_completion_signals[CURSOR_ON_MATCH] =
248     g_signal_new (I_("cursor-on-match"),
249                   G_TYPE_FROM_CLASS (klass),
250                   G_SIGNAL_RUN_LAST,
251                   G_STRUCT_OFFSET (GtkEntryCompletionClass, cursor_on_match),
252                   _gtk_boolean_handled_accumulator, NULL,
253                   _gtk_marshal_BOOLEAN__OBJECT_BOXED,
254                   G_TYPE_BOOLEAN, 2,
255                   GTK_TYPE_TREE_MODEL,
256                   GTK_TYPE_TREE_ITER);
257
258   /**
259    * GtkEntryCompletion::action-activated:
260    * @widget: the object which received the signal
261    * @index: the index of the activated action
262    *
263    * Gets emitted when an action is activated.
264    * 
265    * Since: 2.4
266    */
267   entry_completion_signals[ACTION_ACTIVATED] =
268     g_signal_new (I_("action-activated"),
269                   G_TYPE_FROM_CLASS (klass),
270                   G_SIGNAL_RUN_LAST,
271                   G_STRUCT_OFFSET (GtkEntryCompletionClass, action_activated),
272                   NULL, NULL,
273                   _gtk_marshal_VOID__INT,
274                   G_TYPE_NONE, 1,
275                   G_TYPE_INT);
276
277   g_object_class_install_property (object_class,
278                                    PROP_MODEL,
279                                    g_param_spec_object ("model",
280                                                         P_("Completion Model"),
281                                                         P_("The model to find matches in"),
282                                                         GTK_TYPE_TREE_MODEL,
283                                                         GTK_PARAM_READWRITE));
284   g_object_class_install_property (object_class,
285                                    PROP_MINIMUM_KEY_LENGTH,
286                                    g_param_spec_int ("minimum-key-length",
287                                                      P_("Minimum Key Length"),
288                                                      P_("Minimum length of the search key in order to look up matches"),
289                                                      0,
290                                                      G_MAXINT,
291                                                      1,
292                                                      GTK_PARAM_READWRITE));
293   /**
294    * GtkEntryCompletion:text-column:
295    *
296    * The column of the model containing the strings.
297    * Note that the strings must be UTF-8.
298    *
299    * Since: 2.6
300    */
301   g_object_class_install_property (object_class,
302                                    PROP_TEXT_COLUMN,
303                                    g_param_spec_int ("text-column",
304                                                      P_("Text column"),
305                                                      P_("The column of the model containing the strings."),
306                                                      -1,
307                                                      G_MAXINT,
308                                                      -1,
309                                                      GTK_PARAM_READWRITE));
310
311   /**
312    * GtkEntryCompletion:inline-completion:
313    * 
314    * Determines whether the common prefix of the possible completions 
315    * should be inserted automatically in the entry. Note that this
316    * requires text-column to be set, even if you are using a custom
317    * match function.
318    *
319    * Since: 2.6
320    **/
321   g_object_class_install_property (object_class,
322                                    PROP_INLINE_COMPLETION,
323                                    g_param_spec_boolean ("inline-completion",
324                                                          P_("Inline completion"),
325                                                          P_("Whether the common prefix should be inserted automatically"),
326                                                          FALSE,
327                                                          GTK_PARAM_READWRITE));
328   /**
329    * GtkEntryCompletion:popup-completion:
330    * 
331    * Determines whether the possible completions should be 
332    * shown in a popup window. 
333    *
334    * Since: 2.6
335    **/
336   g_object_class_install_property (object_class,
337                                    PROP_POPUP_COMPLETION,
338                                    g_param_spec_boolean ("popup-completion",
339                                                          P_("Popup completion"),
340                                                          P_("Whether the completions should be shown in a popup window"),
341                                                          TRUE,
342                                                          GTK_PARAM_READWRITE));
343
344   /**
345    * GtkEntryCompletion:popup-set-width:
346    * 
347    * Determines whether the completions popup window will be
348    * resized to the width of the entry.
349    *
350    * Since: 2.8
351    */
352   g_object_class_install_property (object_class,
353                                    PROP_POPUP_SET_WIDTH,
354                                    g_param_spec_boolean ("popup-set-width",
355                                                          P_("Popup set width"),
356                                                          P_("If TRUE, the popup window will have the same size as the entry"),
357                                                          TRUE,
358                                                          GTK_PARAM_READWRITE));
359
360   /**
361    * GtkEntryCompletion:popup-single-match:
362    * 
363    * Determines whether the completions popup window will shown
364    * for a single possible completion. You probably want to set
365    * this to %FALSE if you are using 
366    * <link linkend="GtkEntryCompletion--inline-completion">inline 
367    * completion</link>.
368    *
369    * Since: 2.8
370    */
371   g_object_class_install_property (object_class,
372                                    PROP_POPUP_SINGLE_MATCH,
373                                    g_param_spec_boolean ("popup-single-match",
374                                                          P_("Popup single match"),
375                                                          P_("If TRUE, the popup window will appear for a single match."),
376                                                          TRUE,
377                                                          GTK_PARAM_READWRITE));
378   /**
379    * GtkEntryCompletion:inline-selection:
380    * 
381    * Determines whether the possible completions on the popup
382    * will appear in the entry as you navigate through them.
383    
384    * Since: 2.12
385    */
386   g_object_class_install_property (object_class,
387                                    PROP_INLINE_SELECTION,
388                                    g_param_spec_boolean ("inline-selection",
389                                                          P_("Inline selection"),
390                                                          P_("Your description here"),
391                                                          FALSE,
392                                                          GTK_PARAM_READWRITE));
393
394   g_type_class_add_private (object_class, sizeof (GtkEntryCompletionPrivate));
395 }
396
397 static void
398 gtk_entry_completion_buildable_init (GtkBuildableIface *iface)
399 {
400   iface->add_child = _gtk_cell_layout_buildable_add_child;
401   iface->custom_tag_start = _gtk_cell_layout_buildable_custom_tag_start;
402   iface->custom_tag_end = _gtk_cell_layout_buildable_custom_tag_end;
403 }
404
405 static void
406 gtk_entry_completion_cell_layout_init (GtkCellLayoutIface *iface)
407 {
408   iface->pack_start = gtk_entry_completion_pack_start;
409   iface->pack_end = gtk_entry_completion_pack_end;
410   iface->clear = gtk_entry_completion_clear;
411   iface->add_attribute = gtk_entry_completion_add_attribute;
412   iface->set_cell_data_func = gtk_entry_completion_set_cell_data_func;
413   iface->clear_attributes = gtk_entry_completion_clear_attributes;
414   iface->reorder = gtk_entry_completion_reorder;
415   iface->get_cells = gtk_entry_completion_get_cells;
416 }
417
418 static void
419 gtk_entry_completion_init (GtkEntryCompletion *completion)
420 {
421   GtkCellRenderer *cell;
422   GtkTreeSelection *sel;
423   GtkEntryCompletionPrivate *priv;
424   GtkWidget *popup_frame;
425
426   /* yes, also priv, need to keep the code readable */
427   completion->priv = G_TYPE_INSTANCE_GET_PRIVATE (completion,
428                                                   GTK_TYPE_ENTRY_COMPLETION,
429                                                   GtkEntryCompletionPrivate);
430   priv = completion->priv;
431
432   priv->minimum_key_length = 1;
433   priv->text_column = -1;
434   priv->has_completion = FALSE;
435   priv->inline_completion = FALSE;
436   priv->popup_completion = TRUE;
437   priv->popup_set_width = TRUE;
438   priv->popup_single_match = TRUE;
439   priv->inline_selection = FALSE;
440
441   /* completions */
442   priv->filter_model = NULL;
443
444   priv->tree_view = gtk_tree_view_new ();
445   g_signal_connect (priv->tree_view, "button-press-event",
446                     G_CALLBACK (gtk_entry_completion_list_button_press),
447                     completion);
448   g_signal_connect (priv->tree_view, "enter-notify-event",
449                     G_CALLBACK (gtk_entry_completion_list_enter_notify),
450                     completion);
451   g_signal_connect (priv->tree_view, "motion-notify-event",
452                     G_CALLBACK (gtk_entry_completion_list_motion_notify),
453                     completion);
454
455   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->tree_view), FALSE);
456   gtk_tree_view_set_hover_selection (GTK_TREE_VIEW (priv->tree_view), TRUE);
457
458   sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_view));
459   gtk_tree_selection_set_mode (sel, GTK_SELECTION_SINGLE);
460   gtk_tree_selection_unselect_all (sel);
461   g_signal_connect (sel, "changed",
462                     G_CALLBACK (gtk_entry_completion_selection_changed),
463                     completion);
464   priv->first_sel_changed = TRUE;
465
466   priv->column = gtk_tree_view_column_new ();
467   gtk_tree_view_append_column (GTK_TREE_VIEW (priv->tree_view), priv->column);
468
469   priv->scrolled_window = gtk_scrolled_window_new (NULL, NULL);
470   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scrolled_window),
471                                   GTK_POLICY_NEVER,
472                                   GTK_POLICY_AUTOMATIC);
473   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scrolled_window),
474                                        GTK_SHADOW_NONE);
475
476   /* a nasty hack to get the completions treeview to size nicely */
477   gtk_widget_set_size_request (gtk_scrolled_window_get_vscrollbar (GTK_SCROLLED_WINDOW (priv->scrolled_window)),
478                                -1, 0);
479
480   /* actions */
481   priv->actions = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
482
483   priv->action_view =
484     gtk_tree_view_new_with_model (GTK_TREE_MODEL (priv->actions));
485   g_object_ref_sink (priv->action_view);
486   g_signal_connect (priv->action_view, "button-press-event",
487                     G_CALLBACK (gtk_entry_completion_action_button_press),
488                     completion);
489   g_signal_connect (priv->action_view, "enter-notify-event",
490                     G_CALLBACK (gtk_entry_completion_list_enter_notify),
491                     completion);
492   g_signal_connect (priv->action_view, "motion-notify-event",
493                     G_CALLBACK (gtk_entry_completion_list_motion_notify),
494                     completion);
495   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->action_view), FALSE);
496   gtk_tree_view_set_hover_selection (GTK_TREE_VIEW (priv->action_view), TRUE);
497
498   sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->action_view));
499   gtk_tree_selection_set_mode (sel, GTK_SELECTION_SINGLE);
500   gtk_tree_selection_unselect_all (sel);
501
502   cell = gtk_cell_renderer_text_new ();
503   gtk_tree_view_insert_column_with_data_func (GTK_TREE_VIEW (priv->action_view),
504                                               0, "",
505                                               cell,
506                                               gtk_entry_completion_action_data_func,
507                                               NULL,
508                                               NULL);
509
510   /* pack it all */
511   priv->popup_window = gtk_window_new (GTK_WINDOW_POPUP);
512   gtk_window_set_resizable (GTK_WINDOW (priv->popup_window), FALSE);
513   gtk_window_set_type_hint (GTK_WINDOW(priv->popup_window),
514                             GDK_WINDOW_TYPE_HINT_COMBO);
515   g_signal_connect (priv->popup_window, "key-press-event",
516                     G_CALLBACK (gtk_entry_completion_popup_key_event),
517                     completion);
518   g_signal_connect (priv->popup_window, "key-release-event",
519                     G_CALLBACK (gtk_entry_completion_popup_key_event),
520                     completion);
521   g_signal_connect (priv->popup_window, "button-press-event",
522                     G_CALLBACK (gtk_entry_completion_popup_button_press),
523                     completion);
524
525   popup_frame = gtk_frame_new (NULL);
526   gtk_frame_set_shadow_type (GTK_FRAME (popup_frame),
527                              GTK_SHADOW_ETCHED_IN);
528   gtk_widget_show (popup_frame);
529   gtk_container_add (GTK_CONTAINER (priv->popup_window), popup_frame);
530
531   priv->vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
532   gtk_container_add (GTK_CONTAINER (popup_frame), priv->vbox);
533
534   gtk_container_add (GTK_CONTAINER (priv->scrolled_window), priv->tree_view);
535   gtk_box_pack_start (GTK_BOX (priv->vbox), priv->scrolled_window,
536                       TRUE, TRUE, 0);
537
538   /* we don't want to see the action treeview when no actions have
539    * been inserted, so we pack the action treeview after the first
540    * action has been added
541    */
542 }
543
544 static void
545 gtk_entry_completion_set_property (GObject      *object,
546                                    guint         prop_id,
547                                    const GValue *value,
548                                    GParamSpec   *pspec)
549 {
550   GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (object);
551   GtkEntryCompletionPrivate *priv = completion->priv;
552
553   switch (prop_id)
554     {
555       case PROP_MODEL:
556         gtk_entry_completion_set_model (completion,
557                                         g_value_get_object (value));
558         break;
559
560       case PROP_MINIMUM_KEY_LENGTH:
561         gtk_entry_completion_set_minimum_key_length (completion,
562                                                      g_value_get_int (value));
563         break;
564
565       case PROP_TEXT_COLUMN:
566         priv->text_column = g_value_get_int (value);
567         break;
568
569       case PROP_INLINE_COMPLETION:
570         priv->inline_completion = g_value_get_boolean (value);
571         break;
572
573       case PROP_POPUP_COMPLETION:
574         priv->popup_completion = g_value_get_boolean (value);
575         break;
576
577       case PROP_POPUP_SET_WIDTH:
578         priv->popup_set_width = g_value_get_boolean (value);
579         break;
580
581       case PROP_POPUP_SINGLE_MATCH:
582         priv->popup_single_match = g_value_get_boolean (value);
583         break;
584
585       case PROP_INLINE_SELECTION:
586         priv->inline_selection = g_value_get_boolean (value);
587         break;
588       
589       default:
590         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
591         break;
592     }
593 }
594
595 static void
596 gtk_entry_completion_get_property (GObject    *object,
597                                    guint       prop_id,
598                                    GValue     *value,
599                                    GParamSpec *pspec)
600 {
601   GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (object);
602
603   switch (prop_id)
604     {
605       case PROP_MODEL:
606         g_value_set_object (value,
607                             gtk_entry_completion_get_model (completion));
608         break;
609
610       case PROP_MINIMUM_KEY_LENGTH:
611         g_value_set_int (value, gtk_entry_completion_get_minimum_key_length (completion));
612         break;
613
614       case PROP_TEXT_COLUMN:
615         g_value_set_int (value, gtk_entry_completion_get_text_column (completion));
616         break;
617
618       case PROP_INLINE_COMPLETION:
619         g_value_set_boolean (value, gtk_entry_completion_get_inline_completion (completion));
620         break;
621
622       case PROP_POPUP_COMPLETION:
623         g_value_set_boolean (value, gtk_entry_completion_get_popup_completion (completion));
624         break;
625
626       case PROP_POPUP_SET_WIDTH:
627         g_value_set_boolean (value, gtk_entry_completion_get_popup_set_width (completion));
628         break;
629
630       case PROP_POPUP_SINGLE_MATCH:
631         g_value_set_boolean (value, gtk_entry_completion_get_popup_single_match (completion));
632         break;
633
634       case PROP_INLINE_SELECTION:
635         g_value_set_boolean (value, gtk_entry_completion_get_inline_selection (completion));
636         break;
637
638       default:
639         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
640         break;
641     }
642 }
643
644 static void
645 gtk_entry_completion_finalize (GObject *object)
646 {
647   GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (object);
648   GtkEntryCompletionPrivate *priv = completion->priv;
649
650   if (priv->tree_view)
651     gtk_widget_destroy (priv->tree_view);
652
653   if (priv->entry)
654     gtk_entry_set_completion (GTK_ENTRY (priv->entry), NULL);
655
656   if (priv->actions)
657     g_object_unref (priv->actions);
658   if (priv->action_view)
659     g_object_unref (priv->action_view);
660
661   g_free (priv->case_normalized_key);
662   g_free (priv->completion_prefix);
663
664   if (priv->popup_window)
665     gtk_widget_destroy (priv->popup_window);
666
667   if (priv->match_notify)
668     (* priv->match_notify) (priv->match_data);
669
670   G_OBJECT_CLASS (gtk_entry_completion_parent_class)->finalize (object);
671 }
672
673 /* implement cell layout interface */
674 static void
675 gtk_entry_completion_pack_start (GtkCellLayout   *cell_layout,
676                                  GtkCellRenderer *cell,
677                                  gboolean         expand)
678 {
679   GtkEntryCompletionPrivate *priv;
680
681   priv = GTK_ENTRY_COMPLETION (cell_layout)->priv;
682
683   gtk_tree_view_column_pack_start (priv->column, cell, expand);
684 }
685
686 static void
687 gtk_entry_completion_pack_end (GtkCellLayout   *cell_layout,
688                                GtkCellRenderer *cell,
689                                gboolean         expand)
690 {
691   GtkEntryCompletionPrivate *priv;
692
693   priv = GTK_ENTRY_COMPLETION (cell_layout)->priv;
694
695   gtk_tree_view_column_pack_end (priv->column, cell, expand);
696 }
697
698 static void
699 gtk_entry_completion_clear (GtkCellLayout *cell_layout)
700 {
701   GtkEntryCompletionPrivate *priv;
702
703   priv = GTK_ENTRY_COMPLETION (cell_layout)->priv;
704
705   gtk_tree_view_column_clear (priv->column);
706 }
707
708 static void
709 gtk_entry_completion_add_attribute (GtkCellLayout   *cell_layout,
710                                     GtkCellRenderer *cell,
711                                     const gchar     *attribute,
712                                     gint             column)
713 {
714   GtkEntryCompletionPrivate *priv;
715
716   priv = GTK_ENTRY_COMPLETION  (cell_layout)->priv;
717
718   gtk_tree_view_column_add_attribute (priv->column, cell, attribute, column);
719 }
720
721 static void
722 gtk_entry_completion_set_cell_data_func (GtkCellLayout          *cell_layout,
723                                          GtkCellRenderer        *cell,
724                                          GtkCellLayoutDataFunc   func,
725                                          gpointer                func_data,
726                                          GDestroyNotify          destroy)
727 {
728   GtkEntryCompletionPrivate *priv;
729
730   priv = GTK_ENTRY_COMPLETION (cell_layout)->priv;
731
732   gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (priv->column),
733                                       cell, func, func_data, destroy);
734 }
735
736 static void
737 gtk_entry_completion_clear_attributes (GtkCellLayout   *cell_layout,
738                                        GtkCellRenderer *cell)
739 {
740   GtkEntryCompletionPrivate *priv;
741
742   priv = GTK_ENTRY_COMPLETION (cell_layout)->priv;
743
744   gtk_tree_view_column_clear_attributes (priv->column, cell);
745 }
746
747 static void
748 gtk_entry_completion_reorder (GtkCellLayout   *cell_layout,
749                               GtkCellRenderer *cell,
750                               gint             position)
751 {
752   GtkEntryCompletionPrivate *priv;
753
754   priv = GTK_ENTRY_COMPLETION (cell_layout)->priv;
755
756   gtk_cell_layout_reorder (GTK_CELL_LAYOUT (priv->column), cell, position);
757 }
758
759 static GList *
760 gtk_entry_completion_get_cells (GtkCellLayout *cell_layout)
761 {
762   GtkEntryCompletionPrivate *priv;
763
764   priv = GTK_ENTRY_COMPLETION (cell_layout)->priv;
765
766   return gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (priv->column));
767 }
768
769 /* all those callbacks */
770 static gboolean
771 gtk_entry_completion_default_completion_func (GtkEntryCompletion *completion,
772                                               const gchar        *key,
773                                               GtkTreeIter        *iter,
774                                               gpointer            user_data)
775 {
776   gchar *item = NULL;
777   gchar *normalized_string;
778   gchar *case_normalized_string;
779
780   gboolean ret = FALSE;
781
782   GtkTreeModel *model;
783
784   model = gtk_tree_model_filter_get_model (completion->priv->filter_model);
785
786   g_return_val_if_fail (gtk_tree_model_get_column_type (model, completion->priv->text_column) == G_TYPE_STRING, 
787                         FALSE);
788
789   gtk_tree_model_get (model, iter,
790                       completion->priv->text_column, &item,
791                       -1);
792
793   if (item != NULL)
794     {
795       normalized_string = g_utf8_normalize (item, -1, G_NORMALIZE_ALL);
796
797       if (normalized_string != NULL)
798         {
799           case_normalized_string = g_utf8_casefold (normalized_string, -1);
800
801           if (!strncmp (key, case_normalized_string, strlen (key)))
802             ret = TRUE;
803
804           g_free (case_normalized_string);
805         }
806       g_free (normalized_string);
807     }
808   g_free (item);
809
810   return ret;
811 }
812
813 static gboolean
814 gtk_entry_completion_visible_func (GtkTreeModel *model,
815                                    GtkTreeIter  *iter,
816                                    gpointer      data)
817 {
818   gboolean ret = FALSE;
819
820   GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (data);
821
822   if (!completion->priv->case_normalized_key)
823     return ret;
824
825   if (completion->priv->match_func)
826     ret = (* completion->priv->match_func) (completion,
827                                             completion->priv->case_normalized_key,
828                                             iter,
829                                             completion->priv->match_data);
830   else if (completion->priv->text_column >= 0)
831     ret = gtk_entry_completion_default_completion_func (completion,
832                                                         completion->priv->case_normalized_key,
833                                                         iter,
834                                                         NULL);
835
836   return ret;
837 }
838
839 static gboolean
840 gtk_entry_completion_popup_key_event (GtkWidget   *widget,
841                                       GdkEventKey *event,
842                                       gpointer     user_data)
843 {
844   GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (user_data);
845
846   if (!gtk_widget_get_mapped (completion->priv->popup_window))
847     return FALSE;
848
849   /* propagate event to the entry */
850   gtk_widget_event (completion->priv->entry, (GdkEvent *)event);
851
852   return TRUE;
853 }
854
855 static gboolean
856 gtk_entry_completion_popup_button_press (GtkWidget      *widget,
857                                          GdkEventButton *event,
858                                          gpointer        user_data)
859 {
860   GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (user_data);
861
862   if (!gtk_widget_get_mapped (completion->priv->popup_window))
863     return FALSE;
864
865   /* if we come here, it's usually time to popdown */
866   _gtk_entry_completion_popdown (completion);
867
868   return TRUE;
869 }
870
871 static gboolean
872 gtk_entry_completion_list_button_press (GtkWidget      *widget,
873                                         GdkEventButton *event,
874                                         gpointer        user_data)
875 {
876   GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (user_data);
877   GtkTreePath *path = NULL;
878
879   if (!gtk_widget_get_mapped (completion->priv->popup_window))
880     return FALSE;
881
882   if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget),
883                                      event->x, event->y,
884                                      &path, NULL, NULL, NULL))
885     {
886       GtkTreeIter iter;
887       gboolean entry_set;
888       GtkTreeModel *model;
889       GtkTreeIter child_iter;
890
891       gtk_tree_model_get_iter (GTK_TREE_MODEL (completion->priv->filter_model),
892                                &iter, path);
893       gtk_tree_path_free (path);
894       gtk_tree_model_filter_convert_iter_to_child_iter (completion->priv->filter_model,
895                                                         &child_iter,
896                                                         &iter);
897       model = gtk_tree_model_filter_get_model (completion->priv->filter_model);
898
899       g_signal_handler_block (completion->priv->entry,
900                               completion->priv->changed_id);
901       g_signal_emit (completion, entry_completion_signals[MATCH_SELECTED],
902                      0, model, &child_iter, &entry_set);
903       g_signal_handler_unblock (completion->priv->entry,
904                                 completion->priv->changed_id);
905
906       _gtk_entry_completion_popdown (completion);
907
908       return TRUE;
909     }
910
911   return FALSE;
912 }
913
914 static gboolean
915 gtk_entry_completion_action_button_press (GtkWidget      *widget,
916                                           GdkEventButton *event,
917                                           gpointer        user_data)
918 {
919   GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (user_data);
920   GtkTreePath *path = NULL;
921
922   if (!gtk_widget_get_mapped (completion->priv->popup_window))
923     return FALSE;
924
925   _gtk_entry_reset_im_context (GTK_ENTRY (completion->priv->entry));
926
927   if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget),
928                                      event->x, event->y,
929                                      &path, NULL, NULL, NULL))
930     {
931       g_signal_emit (completion, entry_completion_signals[ACTION_ACTIVATED],
932                      0, gtk_tree_path_get_indices (path)[0]);
933       gtk_tree_path_free (path);
934
935       _gtk_entry_completion_popdown (completion);
936       return TRUE;
937     }
938
939   return FALSE;
940 }
941
942 static void
943 gtk_entry_completion_action_data_func (GtkTreeViewColumn *tree_column,
944                                        GtkCellRenderer   *cell,
945                                        GtkTreeModel      *model,
946                                        GtkTreeIter       *iter,
947                                        gpointer           data)
948 {
949   gchar *string = NULL;
950   gboolean markup;
951
952   gtk_tree_model_get (model, iter,
953                       0, &string,
954                       1, &markup,
955                       -1);
956
957   if (!string)
958     return;
959
960   if (markup)
961     g_object_set (cell,
962                   "text", NULL,
963                   "markup", string,
964                   NULL);
965   else
966     g_object_set (cell,
967                   "markup", NULL,
968                   "text", string,
969                   NULL);
970
971   g_free (string);
972 }
973
974 static void
975 gtk_entry_completion_selection_changed (GtkTreeSelection *selection,
976                                         gpointer          data)
977 {
978   GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (data);
979
980   if (completion->priv->first_sel_changed)
981     {
982       completion->priv->first_sel_changed = FALSE;
983       if (gtk_widget_is_focus (completion->priv->tree_view))
984         gtk_tree_selection_unselect_all (selection);
985     }
986 }
987
988 /* public API */
989
990 /**
991  * gtk_entry_completion_new:
992  *
993  * Creates a new #GtkEntryCompletion object.
994  *
995  * Return value: A newly created #GtkEntryCompletion object.
996  *
997  * Since: 2.4
998  */
999 GtkEntryCompletion *
1000 gtk_entry_completion_new (void)
1001 {
1002   GtkEntryCompletion *completion;
1003
1004   completion = g_object_new (GTK_TYPE_ENTRY_COMPLETION, NULL);
1005
1006   return completion;
1007 }
1008
1009 /**
1010  * gtk_entry_completion_get_entry:
1011  * @completion: A #GtkEntryCompletion.
1012  *
1013  * Gets the entry @completion has been attached to.
1014  *
1015  * Return value: (transfer none): The entry @completion has been attached to.
1016  *
1017  * Since: 2.4
1018  */
1019 GtkWidget *
1020 gtk_entry_completion_get_entry (GtkEntryCompletion *completion)
1021 {
1022   g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), NULL);
1023
1024   return completion->priv->entry;
1025 }
1026
1027 /**
1028  * gtk_entry_completion_set_model:
1029  * @completion: A #GtkEntryCompletion.
1030  * @model: (allow-none): The #GtkTreeModel.
1031  *
1032  * Sets the model for a #GtkEntryCompletion. If @completion already has
1033  * a model set, it will remove it before setting the new model.
1034  * If model is %NULL, then it will unset the model.
1035  *
1036  * Since: 2.4
1037  */
1038 void
1039 gtk_entry_completion_set_model (GtkEntryCompletion *completion,
1040                                 GtkTreeModel       *model)
1041 {
1042   g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1043   g_return_if_fail (model == NULL || GTK_IS_TREE_MODEL (model));
1044
1045   if (!model)
1046     {
1047       gtk_tree_view_set_model (GTK_TREE_VIEW (completion->priv->tree_view),
1048                                NULL);
1049       _gtk_entry_completion_popdown (completion);
1050       completion->priv->filter_model = NULL;
1051       return;
1052     }
1053      
1054   /* code will unref the old filter model (if any) */
1055   completion->priv->filter_model =
1056     GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (model, NULL));
1057   gtk_tree_model_filter_set_visible_func (completion->priv->filter_model,
1058                                           gtk_entry_completion_visible_func,
1059                                           completion,
1060                                           NULL);
1061
1062   gtk_tree_view_set_model (GTK_TREE_VIEW (completion->priv->tree_view),
1063                            GTK_TREE_MODEL (completion->priv->filter_model));
1064   g_object_unref (completion->priv->filter_model);
1065
1066   g_object_notify (G_OBJECT (completion), "model");
1067
1068   if (gtk_widget_get_visible (completion->priv->popup_window))
1069     _gtk_entry_completion_resize_popup (completion);
1070 }
1071
1072 /**
1073  * gtk_entry_completion_get_model:
1074  * @completion: A #GtkEntryCompletion.
1075  *
1076  * Returns the model the #GtkEntryCompletion is using as data source.
1077  * Returns %NULL if the model is unset.
1078  *
1079  * Return value: (transfer none): A #GtkTreeModel, or %NULL if none
1080  *     is currently being used.
1081  *
1082  * Since: 2.4
1083  */
1084 GtkTreeModel *
1085 gtk_entry_completion_get_model (GtkEntryCompletion *completion)
1086 {
1087   g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), NULL);
1088
1089   if (!completion->priv->filter_model)
1090     return NULL;
1091
1092   return gtk_tree_model_filter_get_model (completion->priv->filter_model);
1093 }
1094
1095 /**
1096  * gtk_entry_completion_set_match_func:
1097  * @completion: A #GtkEntryCompletion.
1098  * @func: The #GtkEntryCompletionMatchFunc to use.
1099  * @func_data: The user data for @func.
1100  * @func_notify: Destroy notifier for @func_data.
1101  *
1102  * Sets the match function for @completion to be @func. The match function
1103  * is used to determine if a row should or should not be in the completion
1104  * list.
1105  *
1106  * Since: 2.4
1107  */
1108 void
1109 gtk_entry_completion_set_match_func (GtkEntryCompletion          *completion,
1110                                      GtkEntryCompletionMatchFunc  func,
1111                                      gpointer                     func_data,
1112                                      GDestroyNotify               func_notify)
1113 {
1114   g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1115
1116   if (completion->priv->match_notify)
1117     (* completion->priv->match_notify) (completion->priv->match_data);
1118
1119   completion->priv->match_func = func;
1120   completion->priv->match_data = func_data;
1121   completion->priv->match_notify = func_notify;
1122 }
1123
1124 /**
1125  * gtk_entry_completion_set_minimum_key_length:
1126  * @completion: A #GtkEntryCompletion.
1127  * @length: The minimum length of the key in order to start completing.
1128  *
1129  * Requires the length of the search key for @completion to be at least
1130  * @length. This is useful for long lists, where completing using a small
1131  * key takes a lot of time and will come up with meaningless results anyway
1132  * (ie, a too large dataset).
1133  *
1134  * Since: 2.4
1135  */
1136 void
1137 gtk_entry_completion_set_minimum_key_length (GtkEntryCompletion *completion,
1138                                              gint                length)
1139 {
1140   g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1141   g_return_if_fail (length >= 0);
1142
1143   if (completion->priv->minimum_key_length != length)
1144     {
1145       completion->priv->minimum_key_length = length;
1146      
1147       g_object_notify (G_OBJECT (completion), "minimum-key-length");
1148     }
1149 }
1150
1151 /**
1152  * gtk_entry_completion_get_minimum_key_length:
1153  * @completion: A #GtkEntryCompletion.
1154  *
1155  * Returns the minimum key length as set for @completion.
1156  *
1157  * Return value: The currently used minimum key length.
1158  *
1159  * Since: 2.4
1160  */
1161 gint
1162 gtk_entry_completion_get_minimum_key_length (GtkEntryCompletion *completion)
1163 {
1164   g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), 0);
1165
1166   return completion->priv->minimum_key_length;
1167 }
1168
1169 /**
1170  * gtk_entry_completion_complete:
1171  * @completion: A #GtkEntryCompletion.
1172  *
1173  * Requests a completion operation, or in other words a refiltering of the
1174  * current list with completions, using the current key. The completion list
1175  * view will be updated accordingly.
1176  *
1177  * Since: 2.4
1178  */
1179 void
1180 gtk_entry_completion_complete (GtkEntryCompletion *completion)
1181 {
1182   gchar *tmp;
1183
1184   g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1185
1186   if (!completion->priv->filter_model)
1187     return;
1188   
1189   g_free (completion->priv->case_normalized_key);
1190
1191   tmp = g_utf8_normalize (gtk_entry_get_text (GTK_ENTRY (completion->priv->entry)),
1192                           -1, G_NORMALIZE_ALL);
1193   completion->priv->case_normalized_key = g_utf8_casefold (tmp, -1);
1194   g_free (tmp);
1195
1196   gtk_tree_model_filter_refilter (completion->priv->filter_model);
1197
1198   if (gtk_widget_get_visible (completion->priv->popup_window))
1199     _gtk_entry_completion_resize_popup (completion);
1200 }
1201
1202 static void
1203 gtk_entry_completion_insert_action (GtkEntryCompletion *completion,
1204                                     gint                index,
1205                                     const gchar        *string,
1206                                     gboolean            markup)
1207 {
1208   GtkTreeIter iter;
1209
1210   gtk_list_store_insert (completion->priv->actions, &iter, index);
1211   gtk_list_store_set (completion->priv->actions, &iter,
1212                       0, string,
1213                       1, markup,
1214                       -1);
1215
1216   if (!gtk_widget_get_parent (completion->priv->action_view))
1217     {
1218       GtkTreePath *path = gtk_tree_path_new_from_indices (0, -1);
1219
1220       gtk_tree_view_set_cursor (GTK_TREE_VIEW (completion->priv->action_view),
1221                                 path, NULL, FALSE);
1222       gtk_tree_path_free (path);
1223
1224       gtk_box_pack_start (GTK_BOX (completion->priv->vbox),
1225                           completion->priv->action_view, FALSE, FALSE, 0);
1226       gtk_widget_show (completion->priv->action_view);
1227     }
1228 }
1229
1230 /**
1231  * gtk_entry_completion_insert_action_text:
1232  * @completion: A #GtkEntryCompletion.
1233  * @index_: The index of the item to insert.
1234  * @text: Text of the item to insert.
1235  *
1236  * Inserts an action in @completion's action item list at position @index_
1237  * with text @text. If you want the action item to have markup, use
1238  * gtk_entry_completion_insert_action_markup().
1239  *
1240  * Since: 2.4
1241  */
1242 void
1243 gtk_entry_completion_insert_action_text (GtkEntryCompletion *completion,
1244                                          gint                index_,
1245                                          const gchar        *text)
1246 {
1247   g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1248   g_return_if_fail (text != NULL);
1249
1250   gtk_entry_completion_insert_action (completion, index_, text, FALSE);
1251 }
1252
1253 /**
1254  * gtk_entry_completion_insert_action_markup:
1255  * @completion: A #GtkEntryCompletion.
1256  * @index_: The index of the item to insert.
1257  * @markup: Markup of the item to insert.
1258  *
1259  * Inserts an action in @completion's action item list at position @index_
1260  * with markup @markup.
1261  *
1262  * Since: 2.4
1263  */
1264 void
1265 gtk_entry_completion_insert_action_markup (GtkEntryCompletion *completion,
1266                                            gint                index_,
1267                                            const gchar        *markup)
1268 {
1269   g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1270   g_return_if_fail (markup != NULL);
1271
1272   gtk_entry_completion_insert_action (completion, index_, markup, TRUE);
1273 }
1274
1275 /**
1276  * gtk_entry_completion_delete_action:
1277  * @completion: A #GtkEntryCompletion.
1278  * @index_: The index of the item to Delete.
1279  *
1280  * Deletes the action at @index_ from @completion's action list.
1281  *
1282  * Since: 2.4
1283  */
1284 void
1285 gtk_entry_completion_delete_action (GtkEntryCompletion *completion,
1286                                     gint                index_)
1287 {
1288   GtkTreeIter iter;
1289
1290   g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1291   g_return_if_fail (index_ >= 0);
1292
1293   gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (completion->priv->actions),
1294                                  &iter, NULL, index_);
1295   gtk_list_store_remove (completion->priv->actions, &iter);
1296 }
1297
1298 /**
1299  * gtk_entry_completion_set_text_column:
1300  * @completion: A #GtkEntryCompletion.
1301  * @column: The column in the model of @completion to get strings from.
1302  *
1303  * Convenience function for setting up the most used case of this code: a
1304  * completion list with just strings. This function will set up @completion
1305  * to have a list displaying all (and just) strings in the completion list,
1306  * and to get those strings from @column in the model of @completion.
1307  *
1308  * This functions creates and adds a #GtkCellRendererText for the selected 
1309  * column. If you need to set the text column, but don't want the cell 
1310  * renderer, use g_object_set() to set the ::text_column property directly.
1311  * 
1312  * Since: 2.4
1313  */
1314 void
1315 gtk_entry_completion_set_text_column (GtkEntryCompletion *completion,
1316                                       gint                column)
1317 {
1318   GtkCellRenderer *cell;
1319
1320   g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1321   g_return_if_fail (column >= 0);
1322
1323   completion->priv->text_column = column;
1324
1325   cell = gtk_cell_renderer_text_new ();
1326   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion),
1327                               cell, TRUE);
1328   gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (completion),
1329                                  cell,
1330                                  "text", column);
1331
1332   g_object_notify (G_OBJECT (completion), "text-column");
1333 }
1334
1335 /**
1336  * gtk_entry_completion_get_text_column:
1337  * @completion: a #GtkEntryCompletion
1338  * 
1339  * Returns the column in the model of @completion to get strings from.
1340  * 
1341  * Return value: the column containing the strings
1342  *
1343  * Since: 2.6
1344  **/
1345 gint
1346 gtk_entry_completion_get_text_column (GtkEntryCompletion *completion)
1347 {
1348   g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), -1);
1349
1350   return completion->priv->text_column;  
1351 }
1352
1353 /* private */
1354
1355 static gboolean
1356 gtk_entry_completion_list_enter_notify (GtkWidget        *widget,
1357                                         GdkEventCrossing *event,
1358                                         gpointer          data)
1359 {
1360   GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (data);
1361   
1362   return completion->priv->ignore_enter;
1363 }
1364
1365 static gboolean
1366 gtk_entry_completion_list_motion_notify (GtkWidget      *widget,
1367                                          GdkEventMotion *event,
1368                                          gpointer        data)
1369 {
1370   GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (data);
1371
1372   completion->priv->ignore_enter = FALSE;
1373   
1374   return FALSE;
1375 }
1376
1377
1378 /* some nasty size requisition */
1379 gboolean
1380 _gtk_entry_completion_resize_popup (GtkEntryCompletion *completion)
1381 {
1382   GtkAllocation allocation;
1383   gint x, y;
1384   gint matches, actions, items, height, x_border, y_border;
1385   GdkScreen *screen;
1386   gint monitor_num;
1387   gint vertical_separator;
1388   GdkRectangle monitor;
1389   GdkWindow *window;
1390   GtkRequisition popup_req;
1391   GtkRequisition entry_req;
1392   GtkTreePath *path;
1393   gboolean above;
1394   gint width;
1395   GtkTreeViewColumn *action_column;
1396   gint action_height;
1397
1398   window = gtk_widget_get_window (completion->priv->entry);
1399
1400   if (!window)
1401     return FALSE;
1402
1403   gtk_widget_get_allocation (completion->priv->entry, &allocation);
1404   gtk_widget_get_preferred_size (completion->priv->entry,
1405                                  &entry_req, NULL);
1406
1407   gdk_window_get_origin (window, &x, &y);
1408   x += allocation.x;
1409   y += allocation.y + (allocation.height - entry_req.height) / 2;
1410
1411   _gtk_entry_get_borders (GTK_ENTRY (completion->priv->entry), &x_border, &y_border);
1412
1413   matches = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (completion->priv->filter_model), NULL);
1414   actions = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (completion->priv->actions), NULL);
1415   action_column  = gtk_tree_view_get_column (GTK_TREE_VIEW (completion->priv->action_view), 0);
1416
1417   gtk_tree_view_column_cell_get_size (completion->priv->column, NULL,
1418                                       NULL, NULL, NULL, &height);
1419   gtk_tree_view_column_cell_get_size (action_column, NULL,
1420                                       NULL, NULL, NULL, &action_height);
1421
1422   gtk_widget_style_get (GTK_WIDGET (completion->priv->tree_view),
1423                         "vertical-separator", &vertical_separator,
1424                         NULL);
1425
1426   height += vertical_separator;
1427   
1428   gtk_widget_realize (completion->priv->tree_view);
1429
1430   screen = gtk_widget_get_screen (GTK_WIDGET (completion->priv->entry));
1431   monitor_num = gdk_screen_get_monitor_at_window (screen, window);
1432   gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
1433
1434   
1435
1436   if (y > monitor.height / 2)
1437     items = MIN (matches, (((monitor.y + y) - (actions * action_height)) / height) - 1);
1438   else
1439     items = MIN (matches, (((monitor.height - y) - (actions * action_height)) / height) - 1);
1440
1441   if (items <= 0)
1442     gtk_widget_hide (completion->priv->scrolled_window);
1443   else
1444     gtk_widget_show (completion->priv->scrolled_window);
1445
1446   if (completion->priv->popup_set_width)
1447     width = MIN (allocation.width, monitor.width) - 2 * x_border;
1448   else
1449     width = -1;
1450
1451   gtk_tree_view_columns_autosize (GTK_TREE_VIEW (completion->priv->tree_view));
1452   gtk_scrolled_window_set_min_content_width (GTK_SCROLLED_WINDOW (completion->priv->scrolled_window), width);
1453   gtk_widget_set_size_request (completion->priv->scrolled_window, width, -1);
1454   gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (completion->priv->scrolled_window), items * height);
1455
1456   if (actions)
1457     {
1458       gtk_widget_show (completion->priv->action_view);
1459       gtk_widget_set_size_request (completion->priv->action_view, width, -1);
1460     }
1461   else
1462     gtk_widget_hide (completion->priv->action_view);
1463
1464   gtk_widget_get_preferred_size (completion->priv->popup_window,
1465                                  &popup_req, NULL);
1466
1467   if (x < monitor.x)
1468     x = monitor.x;
1469   else if (x + popup_req.width > monitor.x + monitor.width)
1470     x = monitor.x + monitor.width - popup_req.width;
1471   
1472   if (y + entry_req.height + popup_req.height <= monitor.y + monitor.height ||
1473       y - monitor.y < (monitor.y + monitor.height) - (y + entry_req.height))
1474     {
1475       y += entry_req.height;
1476       above = FALSE;
1477     }
1478   else
1479     {
1480       y -= popup_req.height;
1481       above = TRUE;
1482     }
1483   
1484   if (matches > 0) 
1485     {
1486       path = gtk_tree_path_new_from_indices (above ? matches - 1 : 0, -1);
1487       gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (completion->priv->tree_view), path, 
1488                                     NULL, FALSE, 0.0, 0.0);
1489       gtk_tree_path_free (path);
1490     }
1491
1492   gtk_window_move (GTK_WINDOW (completion->priv->popup_window), x, y);
1493
1494   return above;
1495 }
1496
1497 void
1498 _gtk_entry_completion_popup (GtkEntryCompletion *completion,
1499                              GdkDevice          *device)
1500 {
1501   GtkTreeViewColumn *column;
1502   GList *renderers;
1503   GtkWidget *toplevel;
1504
1505   if (gtk_widget_get_mapped (completion->priv->popup_window))
1506     return;
1507
1508   if (!gtk_widget_get_mapped (completion->priv->entry))
1509     return;
1510
1511   if (!gtk_widget_has_focus (completion->priv->entry))
1512     return;
1513
1514   if (completion->priv->grab_device)
1515     return;
1516
1517   completion->priv->ignore_enter = TRUE;
1518     
1519   column = gtk_tree_view_get_column (GTK_TREE_VIEW (completion->priv->action_view), 0);
1520   renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
1521   gtk_widget_ensure_style (completion->priv->tree_view);
1522   g_object_set (GTK_CELL_RENDERER (renderers->data), "cell-background-gdk",
1523                 &gtk_widget_get_style (completion->priv->tree_view)->bg[GTK_STATE_NORMAL],
1524                 NULL);
1525   g_list_free (renderers);
1526
1527   gtk_widget_show_all (completion->priv->vbox);
1528
1529   /* default on no match */
1530   completion->priv->current_selected = -1;
1531
1532   _gtk_entry_completion_resize_popup (completion);
1533
1534   toplevel = gtk_widget_get_toplevel (completion->priv->entry);
1535   if (GTK_IS_WINDOW (toplevel))
1536     gtk_window_group_add_window (gtk_window_get_group (GTK_WINDOW (toplevel)), 
1537                                  GTK_WINDOW (completion->priv->popup_window));
1538
1539   /* prevent the first row being focused */
1540   gtk_widget_grab_focus (completion->priv->tree_view);
1541
1542   gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->tree_view)));
1543   gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->action_view)));
1544
1545   gtk_window_set_screen (GTK_WINDOW (completion->priv->popup_window),
1546                          gtk_widget_get_screen (completion->priv->entry));
1547
1548   gtk_widget_show (completion->priv->popup_window);
1549
1550   gtk_device_grab_add (completion->priv->popup_window, device, TRUE);
1551   gdk_device_grab (device, gtk_widget_get_window (completion->priv->popup_window),
1552                    GDK_OWNERSHIP_WINDOW, TRUE,
1553                    GDK_BUTTON_PRESS_MASK |
1554                    GDK_BUTTON_RELEASE_MASK |
1555                    GDK_POINTER_MOTION_MASK,
1556                    NULL, GDK_CURRENT_TIME);
1557
1558   completion->priv->grab_device = device;
1559 }
1560
1561 void
1562 _gtk_entry_completion_popdown (GtkEntryCompletion *completion)
1563 {
1564   if (!gtk_widget_get_mapped (completion->priv->popup_window))
1565     return;
1566
1567   completion->priv->ignore_enter = FALSE;
1568
1569   if (completion->priv->grab_device)
1570     {
1571       gdk_device_ungrab (completion->priv->grab_device, GDK_CURRENT_TIME);
1572       gtk_device_grab_remove (completion->priv->popup_window,
1573                               completion->priv->grab_device);
1574       completion->priv->grab_device = NULL;
1575     }
1576
1577   gtk_widget_hide (completion->priv->popup_window);
1578 }
1579
1580 static gboolean 
1581 gtk_entry_completion_match_selected (GtkEntryCompletion *completion,
1582                                      GtkTreeModel       *model,
1583                                      GtkTreeIter        *iter)
1584 {
1585   gchar *str = NULL;
1586
1587   gtk_tree_model_get (model, iter, completion->priv->text_column, &str, -1);
1588   gtk_entry_set_text (GTK_ENTRY (completion->priv->entry), str ? str : "");
1589   
1590   /* move cursor to the end */
1591   gtk_editable_set_position (GTK_EDITABLE (completion->priv->entry), -1);
1592   
1593   g_free (str);
1594
1595   return TRUE;
1596 }
1597
1598 static gboolean
1599 gtk_entry_completion_cursor_on_match (GtkEntryCompletion *completion,
1600                                       GtkTreeModel       *model,
1601                                       GtkTreeIter        *iter)
1602 {
1603   gtk_entry_completion_insert_completion (completion, model, iter);
1604
1605   return TRUE;
1606 }
1607
1608 static gchar *
1609 gtk_entry_completion_compute_prefix (GtkEntryCompletion *completion)
1610 {
1611   GtkTreeIter iter;
1612   gchar *prefix = NULL;
1613   gboolean valid;
1614   const gchar *key;
1615
1616   if (completion->priv->text_column < 0)
1617     return NULL;
1618
1619   key = gtk_entry_get_text (GTK_ENTRY (completion->priv->entry));
1620
1621   valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (completion->priv->filter_model),
1622                                          &iter);
1623   
1624   while (valid)
1625     {
1626       gchar *text;
1627       
1628       gtk_tree_model_get (GTK_TREE_MODEL (completion->priv->filter_model),
1629                           &iter, completion->priv->text_column, &text,
1630                           -1);
1631
1632       if (text && g_str_has_prefix (text, key))
1633         {
1634           if (!prefix)
1635             prefix = g_strdup (text);
1636           else
1637             {
1638               gchar *p = prefix;
1639               gchar *q = text;
1640               
1641               while (*p && *p == *q)
1642                 {
1643                   p++;
1644                   q++;
1645                 }
1646               
1647               *p = '\0';
1648               
1649               if (p > prefix)
1650                 {
1651                   /* strip a partial multibyte character */
1652                   q = g_utf8_find_prev_char (prefix, p);
1653                   switch (g_utf8_get_char_validated (q, p - q))
1654                     {
1655                     case (gunichar)-2:
1656                     case (gunichar)-1:
1657                       *q = 0;
1658                     default: ;
1659                     }
1660                 }
1661             }
1662         }
1663       
1664       g_free (text);
1665       valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (completion->priv->filter_model),
1666                                         &iter);
1667     }
1668
1669   return prefix;
1670 }
1671
1672
1673 static gboolean
1674 gtk_entry_completion_real_insert_prefix (GtkEntryCompletion *completion,
1675                                          const gchar        *prefix)
1676 {
1677   if (prefix)
1678     {
1679       gint key_len;
1680       gint prefix_len;
1681       const gchar *key;
1682
1683       prefix_len = g_utf8_strlen (prefix, -1);
1684
1685       key = gtk_entry_get_text (GTK_ENTRY (completion->priv->entry));
1686       key_len = g_utf8_strlen (key, -1);
1687
1688       if (prefix_len > key_len)
1689         {
1690           gint pos = prefix_len;
1691
1692           gtk_editable_insert_text (GTK_EDITABLE (completion->priv->entry),
1693                                     prefix + strlen (key), -1, &pos);
1694           gtk_editable_select_region (GTK_EDITABLE (completion->priv->entry),
1695                                       key_len, prefix_len);
1696
1697           completion->priv->has_completion = TRUE;
1698         }
1699     }
1700
1701   return TRUE;
1702 }
1703
1704 /**
1705  * gtk_entry_completion_get_completion_prefix:
1706  * @completion: a #GtkEntryCompletion
1707  * 
1708  * Get the original text entered by the user that triggered
1709  * the completion or %NULL if there's no completion ongoing.
1710  * 
1711  * Returns: the prefix for the current completion
1712  * 
1713  * Since: 2.12
1714  **/
1715 const gchar*
1716 gtk_entry_completion_get_completion_prefix (GtkEntryCompletion *completion)
1717 {
1718   g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), NULL);
1719
1720   return completion->priv->completion_prefix;
1721 }
1722
1723 static void
1724 gtk_entry_completion_insert_completion_text (GtkEntryCompletion *completion,
1725                                              const gchar *text)
1726 {
1727   GtkEntryCompletionPrivate *priv = completion->priv;
1728   gint len;
1729
1730   priv = completion->priv;
1731
1732   if (priv->changed_id > 0)
1733     g_signal_handler_block (priv->entry, priv->changed_id);
1734
1735   if (priv->insert_text_id > 0)
1736     g_signal_handler_block (priv->entry, priv->insert_text_id);
1737
1738   gtk_entry_set_text (GTK_ENTRY (priv->entry), text);
1739
1740   len = strlen (priv->completion_prefix);
1741   gtk_editable_select_region (GTK_EDITABLE (priv->entry), len, -1);
1742
1743   if (priv->changed_id > 0)
1744     g_signal_handler_unblock (priv->entry, priv->changed_id);
1745
1746   if (priv->insert_text_id > 0)
1747     g_signal_handler_unblock (priv->entry, priv->insert_text_id);
1748 }
1749
1750 static gboolean
1751 gtk_entry_completion_insert_completion (GtkEntryCompletion *completion,
1752                                         GtkTreeModel       *model,
1753                                         GtkTreeIter        *iter)
1754 {
1755   gchar *str = NULL;
1756
1757   if (completion->priv->text_column < 0)
1758     return FALSE;
1759
1760   gtk_tree_model_get (model, iter,
1761                       completion->priv->text_column, &str,
1762                       -1);
1763
1764   gtk_entry_completion_insert_completion_text (completion, str);
1765
1766   g_free (str);
1767
1768   return TRUE;
1769 }
1770
1771 /**
1772  * gtk_entry_completion_insert_prefix:
1773  * @completion: a #GtkEntryCompletion
1774  * 
1775  * Requests a prefix insertion. 
1776  * 
1777  * Since: 2.6
1778  **/
1779
1780 void
1781 gtk_entry_completion_insert_prefix (GtkEntryCompletion *completion)
1782 {
1783   gboolean done;
1784   gchar *prefix;
1785
1786   if (completion->priv->insert_text_id > 0)
1787     g_signal_handler_block (completion->priv->entry,
1788                             completion->priv->insert_text_id);
1789
1790   prefix = gtk_entry_completion_compute_prefix (completion);
1791   if (prefix)
1792     {
1793       g_signal_emit (completion, entry_completion_signals[INSERT_PREFIX],
1794                      0, prefix, &done);
1795       g_free (prefix);
1796     }
1797
1798   if (completion->priv->insert_text_id > 0)
1799     g_signal_handler_unblock (completion->priv->entry,
1800                               completion->priv->insert_text_id);
1801 }
1802
1803 /**
1804  * gtk_entry_completion_set_inline_completion:
1805  * @completion: a #GtkEntryCompletion
1806  * @inline_completion: %TRUE to do inline completion
1807  * 
1808  * Sets whether the common prefix of the possible completions should
1809  * be automatically inserted in the entry.
1810  * 
1811  * Since: 2.6
1812  **/
1813 void 
1814 gtk_entry_completion_set_inline_completion (GtkEntryCompletion *completion,
1815                                             gboolean            inline_completion)
1816 {
1817   g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1818   
1819   inline_completion = inline_completion != FALSE;
1820
1821   if (completion->priv->inline_completion != inline_completion)
1822     {
1823       completion->priv->inline_completion = inline_completion;
1824
1825       g_object_notify (G_OBJECT (completion), "inline-completion");
1826     }
1827 }
1828
1829 /**
1830  * gtk_entry_completion_get_inline_completion:
1831  * @completion: a #GtkEntryCompletion
1832  * 
1833  * Returns whether the common prefix of the possible completions should
1834  * be automatically inserted in the entry.
1835  * 
1836  * Return value: %TRUE if inline completion is turned on
1837  * 
1838  * Since: 2.6
1839  **/
1840 gboolean
1841 gtk_entry_completion_get_inline_completion (GtkEntryCompletion *completion)
1842 {
1843   g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), FALSE);
1844   
1845   return completion->priv->inline_completion;
1846 }
1847
1848 /**
1849  * gtk_entry_completion_set_popup_completion:
1850  * @completion: a #GtkEntryCompletion
1851  * @popup_completion: %TRUE to do popup completion
1852  * 
1853  * Sets whether the completions should be presented in a popup window.
1854  * 
1855  * Since: 2.6
1856  **/
1857 void 
1858 gtk_entry_completion_set_popup_completion (GtkEntryCompletion *completion,
1859                                            gboolean            popup_completion)
1860 {
1861   g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1862   
1863   popup_completion = popup_completion != FALSE;
1864
1865   if (completion->priv->popup_completion != popup_completion)
1866     {
1867       completion->priv->popup_completion = popup_completion;
1868
1869       g_object_notify (G_OBJECT (completion), "popup-completion");
1870     }
1871 }
1872
1873
1874 /**
1875  * gtk_entry_completion_get_popup_completion:
1876  * @completion: a #GtkEntryCompletion
1877  * 
1878  * Returns whether the completions should be presented in a popup window.
1879  * 
1880  * Return value: %TRUE if popup completion is turned on
1881  * 
1882  * Since: 2.6
1883  **/
1884 gboolean
1885 gtk_entry_completion_get_popup_completion (GtkEntryCompletion *completion)
1886 {
1887   g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), TRUE);
1888   
1889   return completion->priv->popup_completion;
1890 }
1891
1892 /**
1893  * gtk_entry_completion_set_popup_set_width:
1894  * @completion: a #GtkEntryCompletion
1895  * @popup_set_width: %TRUE to make the width of the popup the same as the entry
1896  *
1897  * Sets whether the completion popup window will be resized to be the same
1898  * width as the entry.
1899  *
1900  * Since: 2.8
1901  */
1902 void 
1903 gtk_entry_completion_set_popup_set_width (GtkEntryCompletion *completion,
1904                                           gboolean            popup_set_width)
1905 {
1906   g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1907   
1908   popup_set_width = popup_set_width != FALSE;
1909
1910   if (completion->priv->popup_set_width != popup_set_width)
1911     {
1912       completion->priv->popup_set_width = popup_set_width;
1913
1914       g_object_notify (G_OBJECT (completion), "popup-set-width");
1915     }
1916 }
1917
1918 /**
1919  * gtk_entry_completion_get_popup_set_width:
1920  * @completion: a #GtkEntryCompletion
1921  * 
1922  * Returns whether the  completion popup window will be resized to the 
1923  * width of the entry.
1924  * 
1925  * Return value: %TRUE if the popup window will be resized to the width of 
1926  *   the entry
1927  * 
1928  * Since: 2.8
1929  **/
1930 gboolean
1931 gtk_entry_completion_get_popup_set_width (GtkEntryCompletion *completion)
1932 {
1933   g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), TRUE);
1934   
1935   return completion->priv->popup_set_width;
1936 }
1937
1938
1939 /**
1940  * gtk_entry_completion_set_popup_single_match:
1941  * @completion: a #GtkEntryCompletion
1942  * @popup_single_match: %TRUE if the popup should appear even for a single
1943  *   match
1944  *
1945  * Sets whether the completion popup window will appear even if there is
1946  * only a single match. You may want to set this to %FALSE if you
1947  * are using <link linkend="GtkEntryCompletion--inline-completion">inline
1948  * completion</link>.
1949  *
1950  * Since: 2.8
1951  */
1952 void 
1953 gtk_entry_completion_set_popup_single_match (GtkEntryCompletion *completion,
1954                                              gboolean            popup_single_match)
1955 {
1956   g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1957   
1958   popup_single_match = popup_single_match != FALSE;
1959
1960   if (completion->priv->popup_single_match != popup_single_match)
1961     {
1962       completion->priv->popup_single_match = popup_single_match;
1963
1964       g_object_notify (G_OBJECT (completion), "popup-single-match");
1965     }
1966 }
1967
1968 /**
1969  * gtk_entry_completion_get_popup_single_match:
1970  * @completion: a #GtkEntryCompletion
1971  * 
1972  * Returns whether the completion popup window will appear even if there is
1973  * only a single match. 
1974  * 
1975  * Return value: %TRUE if the popup window will appear regardless of the
1976  *    number of matches.
1977  * 
1978  * Since: 2.8
1979  **/
1980 gboolean
1981 gtk_entry_completion_get_popup_single_match (GtkEntryCompletion *completion)
1982 {
1983   g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), TRUE);
1984   
1985   return completion->priv->popup_single_match;
1986 }
1987
1988 /**
1989  * gtk_entry_completion_set_inline_selection:
1990  * @completion: a #GtkEntryCompletion
1991  * @inline_selection: %TRUE to do inline selection
1992  * 
1993  * Sets whether it is possible to cycle through the possible completions
1994  * inside the entry.
1995  * 
1996  * Since: 2.12
1997  **/
1998 void
1999 gtk_entry_completion_set_inline_selection (GtkEntryCompletion *completion,
2000                                            gboolean inline_selection)
2001 {
2002   g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
2003
2004   inline_selection = inline_selection != FALSE;
2005
2006   if (completion->priv->inline_selection != inline_selection)
2007     {
2008       completion->priv->inline_selection = inline_selection;
2009
2010       g_object_notify (G_OBJECT (completion), "inline-selection");
2011     }
2012 }
2013
2014 /**
2015  * gtk_entry_completion_get_inline_selection:
2016  * @completion: a #GtkEntryCompletion
2017  *
2018  * Returns %TRUE if inline-selection mode is turned on.
2019  *
2020  * Returns: %TRUE if inline-selection mode is on
2021  *
2022  * Since: 2.12
2023  **/
2024 gboolean
2025 gtk_entry_completion_get_inline_selection (GtkEntryCompletion *completion)
2026 {
2027   g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), FALSE);
2028
2029   return completion->priv->inline_selection;
2030 }