]> Pileus Git - ~andy/gtk/blob - gtk/gtkentrycompletion.c
Tons of transfer annotations
[~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_vbox_new (FALSE, 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   gdk_window_get_origin (window, &x, &y);
1404   _gtk_entry_get_borders (GTK_ENTRY (completion->priv->entry), &x_border, &y_border);
1405
1406   matches = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (completion->priv->filter_model), NULL);
1407   actions = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (completion->priv->actions), NULL);
1408   action_column  = gtk_tree_view_get_column (GTK_TREE_VIEW (completion->priv->action_view), 0);
1409
1410   gtk_tree_view_column_cell_get_size (completion->priv->column, NULL,
1411                                       NULL, NULL, NULL, &height);
1412   gtk_tree_view_column_cell_get_size (action_column, NULL,
1413                                       NULL, NULL, NULL, &action_height);
1414
1415   gtk_widget_style_get (GTK_WIDGET (completion->priv->tree_view),
1416                         "vertical-separator", &vertical_separator,
1417                         NULL);
1418
1419   height += vertical_separator;
1420   
1421   gtk_widget_realize (completion->priv->tree_view);
1422
1423   screen = gtk_widget_get_screen (GTK_WIDGET (completion->priv->entry));
1424   monitor_num = gdk_screen_get_monitor_at_window (screen, window);
1425   gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
1426
1427   
1428
1429   if (y > monitor.height / 2)
1430     items = MIN (matches, (((monitor.y + y) - (actions * action_height)) / height) - 1);
1431   else
1432     items = MIN (matches, (((monitor.height - y) - (actions * action_height)) / height) - 1);
1433
1434   if (items <= 0)
1435     gtk_widget_hide (completion->priv->scrolled_window);
1436   else
1437     gtk_widget_show (completion->priv->scrolled_window);
1438
1439   gtk_widget_get_allocation (completion->priv->entry, &allocation);
1440   if (completion->priv->popup_set_width)
1441     width = MIN (allocation.width, monitor.width) - 2 * x_border;
1442   else
1443     width = -1;
1444
1445   gtk_tree_view_columns_autosize (GTK_TREE_VIEW (completion->priv->tree_view));
1446   gtk_widget_set_size_request (completion->priv->tree_view, width, items * height);
1447
1448   if (actions)
1449     {
1450       gtk_widget_show (completion->priv->action_view);
1451       gtk_widget_set_size_request (completion->priv->action_view, width, -1);
1452     }
1453   else
1454     gtk_widget_hide (completion->priv->action_view);
1455
1456   gtk_size_request_get_size (GTK_SIZE_REQUEST (completion->priv->popup_window),
1457                              &popup_req, NULL);
1458   gtk_size_request_get_size (GTK_SIZE_REQUEST (completion->priv->entry),
1459                              &entry_req, NULL);
1460
1461   if (x < monitor.x)
1462     x = monitor.x;
1463   else if (x + popup_req.width > monitor.x + monitor.width)
1464     x = monitor.x + monitor.width - popup_req.width;
1465   
1466   if (y + entry_req.height + popup_req.height <= monitor.y + monitor.height ||
1467       y - monitor.y < (monitor.y + monitor.height) - (y + entry_req.height))
1468     {
1469       y += entry_req.height;
1470       above = FALSE;
1471     }
1472   else
1473     {
1474       y -= popup_req.height;
1475       above = TRUE;
1476     }
1477   
1478   if (matches > 0) 
1479     {
1480       path = gtk_tree_path_new_from_indices (above ? matches - 1 : 0, -1);
1481       gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (completion->priv->tree_view), path, 
1482                                     NULL, FALSE, 0.0, 0.0);
1483       gtk_tree_path_free (path);
1484     }
1485
1486   gtk_window_move (GTK_WINDOW (completion->priv->popup_window), x, y);
1487
1488   return above;
1489 }
1490
1491 void
1492 _gtk_entry_completion_popup (GtkEntryCompletion *completion,
1493                              GdkDevice          *device)
1494 {
1495   GtkTreeViewColumn *column;
1496   GList *renderers;
1497   GtkWidget *toplevel;
1498
1499   if (gtk_widget_get_mapped (completion->priv->popup_window))
1500     return;
1501
1502   if (!gtk_widget_get_mapped (completion->priv->entry))
1503     return;
1504
1505   if (!gtk_widget_has_focus (completion->priv->entry))
1506     return;
1507
1508   if (completion->priv->grab_device)
1509     return;
1510
1511   completion->priv->ignore_enter = TRUE;
1512     
1513   column = gtk_tree_view_get_column (GTK_TREE_VIEW (completion->priv->action_view), 0);
1514   renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
1515   gtk_widget_ensure_style (completion->priv->tree_view);
1516   g_object_set (GTK_CELL_RENDERER (renderers->data), "cell-background-gdk",
1517                 &gtk_widget_get_style (completion->priv->tree_view)->bg[GTK_STATE_NORMAL],
1518                 NULL);
1519   g_list_free (renderers);
1520
1521   gtk_widget_show_all (completion->priv->vbox);
1522
1523   /* default on no match */
1524   completion->priv->current_selected = -1;
1525
1526   _gtk_entry_completion_resize_popup (completion);
1527
1528   toplevel = gtk_widget_get_toplevel (completion->priv->entry);
1529   if (GTK_IS_WINDOW (toplevel))
1530     gtk_window_group_add_window (gtk_window_get_group (GTK_WINDOW (toplevel)), 
1531                                  GTK_WINDOW (completion->priv->popup_window));
1532
1533   /* prevent the first row being focused */
1534   gtk_widget_grab_focus (completion->priv->tree_view);
1535
1536   gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->tree_view)));
1537   gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->action_view)));
1538
1539   gtk_window_set_screen (GTK_WINDOW (completion->priv->popup_window),
1540                          gtk_widget_get_screen (completion->priv->entry));
1541
1542   gtk_widget_show (completion->priv->popup_window);
1543
1544   gtk_device_grab_add (completion->priv->popup_window, device, TRUE);
1545   gdk_device_grab (device, gtk_widget_get_window (completion->priv->popup_window),
1546                    GDK_OWNERSHIP_WINDOW, TRUE,
1547                    GDK_BUTTON_PRESS_MASK |
1548                    GDK_BUTTON_RELEASE_MASK |
1549                    GDK_POINTER_MOTION_MASK,
1550                    NULL, GDK_CURRENT_TIME);
1551
1552   completion->priv->grab_device = device;
1553 }
1554
1555 void
1556 _gtk_entry_completion_popdown (GtkEntryCompletion *completion)
1557 {
1558   if (!gtk_widget_get_mapped (completion->priv->popup_window))
1559     return;
1560
1561   completion->priv->ignore_enter = FALSE;
1562
1563   if (completion->priv->grab_device)
1564     {
1565       gdk_device_ungrab (completion->priv->grab_device, GDK_CURRENT_TIME);
1566       gtk_device_grab_remove (completion->priv->popup_window,
1567                               completion->priv->grab_device);
1568       completion->priv->grab_device = NULL;
1569     }
1570
1571   gtk_widget_hide (completion->priv->popup_window);
1572 }
1573
1574 static gboolean 
1575 gtk_entry_completion_match_selected (GtkEntryCompletion *completion,
1576                                      GtkTreeModel       *model,
1577                                      GtkTreeIter        *iter)
1578 {
1579   gchar *str = NULL;
1580
1581   gtk_tree_model_get (model, iter, completion->priv->text_column, &str, -1);
1582   gtk_entry_set_text (GTK_ENTRY (completion->priv->entry), str ? str : "");
1583   
1584   /* move cursor to the end */
1585   gtk_editable_set_position (GTK_EDITABLE (completion->priv->entry), -1);
1586   
1587   g_free (str);
1588
1589   return TRUE;
1590 }
1591
1592 static gboolean
1593 gtk_entry_completion_cursor_on_match (GtkEntryCompletion *completion,
1594                                       GtkTreeModel       *model,
1595                                       GtkTreeIter        *iter)
1596 {
1597   gtk_entry_completion_insert_completion (completion, model, iter);
1598
1599   return TRUE;
1600 }
1601
1602 static gchar *
1603 gtk_entry_completion_compute_prefix (GtkEntryCompletion *completion)
1604 {
1605   GtkTreeIter iter;
1606   gchar *prefix = NULL;
1607   gboolean valid;
1608   const gchar *key;
1609
1610   if (completion->priv->text_column < 0)
1611     return NULL;
1612
1613   key = gtk_entry_get_text (GTK_ENTRY (completion->priv->entry));
1614
1615   valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (completion->priv->filter_model),
1616                                          &iter);
1617   
1618   while (valid)
1619     {
1620       gchar *text;
1621       
1622       gtk_tree_model_get (GTK_TREE_MODEL (completion->priv->filter_model),
1623                           &iter, completion->priv->text_column, &text,
1624                           -1);
1625
1626       if (text && g_str_has_prefix (text, key))
1627         {
1628           if (!prefix)
1629             prefix = g_strdup (text);
1630           else
1631             {
1632               gchar *p = prefix;
1633               gchar *q = text;
1634               
1635               while (*p && *p == *q)
1636                 {
1637                   p++;
1638                   q++;
1639                 }
1640               
1641               *p = '\0';
1642               
1643               if (p > prefix)
1644                 {
1645                   /* strip a partial multibyte character */
1646                   q = g_utf8_find_prev_char (prefix, p);
1647                   switch (g_utf8_get_char_validated (q, p - q))
1648                     {
1649                     case (gunichar)-2:
1650                     case (gunichar)-1:
1651                       *q = 0;
1652                     default: ;
1653                     }
1654                 }
1655             }
1656         }
1657       
1658       g_free (text);
1659       valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (completion->priv->filter_model),
1660                                         &iter);
1661     }
1662
1663   return prefix;
1664 }
1665
1666
1667 static gboolean
1668 gtk_entry_completion_real_insert_prefix (GtkEntryCompletion *completion,
1669                                          const gchar        *prefix)
1670 {
1671   if (prefix)
1672     {
1673       gint key_len;
1674       gint prefix_len;
1675       const gchar *key;
1676
1677       prefix_len = g_utf8_strlen (prefix, -1);
1678
1679       key = gtk_entry_get_text (GTK_ENTRY (completion->priv->entry));
1680       key_len = g_utf8_strlen (key, -1);
1681
1682       if (prefix_len > key_len)
1683         {
1684           gint pos = prefix_len;
1685
1686           gtk_editable_insert_text (GTK_EDITABLE (completion->priv->entry),
1687                                     prefix + strlen (key), -1, &pos);
1688           gtk_editable_select_region (GTK_EDITABLE (completion->priv->entry),
1689                                       key_len, prefix_len);
1690
1691           completion->priv->has_completion = TRUE;
1692         }
1693     }
1694
1695   return TRUE;
1696 }
1697
1698 /**
1699  * gtk_entry_completion_get_completion_prefix:
1700  * @completion: a #GtkEntryCompletion
1701  * 
1702  * Get the original text entered by the user that triggered
1703  * the completion or %NULL if there's no completion ongoing.
1704  * 
1705  * Returns: the prefix for the current completion
1706  * 
1707  * Since: 2.12
1708  **/
1709 const gchar*
1710 gtk_entry_completion_get_completion_prefix (GtkEntryCompletion *completion)
1711 {
1712   g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), NULL);
1713
1714   return completion->priv->completion_prefix;
1715 }
1716
1717 static void
1718 gtk_entry_completion_insert_completion_text (GtkEntryCompletion *completion,
1719                                              const gchar *text)
1720 {
1721   GtkEntryCompletionPrivate *priv = completion->priv;
1722   gint len;
1723
1724   priv = completion->priv;
1725
1726   if (priv->changed_id > 0)
1727     g_signal_handler_block (priv->entry, priv->changed_id);
1728
1729   if (priv->insert_text_id > 0)
1730     g_signal_handler_block (priv->entry, priv->insert_text_id);
1731
1732   gtk_entry_set_text (GTK_ENTRY (priv->entry), text);
1733
1734   len = strlen (priv->completion_prefix);
1735   gtk_editable_select_region (GTK_EDITABLE (priv->entry), len, -1);
1736
1737   if (priv->changed_id > 0)
1738     g_signal_handler_unblock (priv->entry, priv->changed_id);
1739
1740   if (priv->insert_text_id > 0)
1741     g_signal_handler_unblock (priv->entry, priv->insert_text_id);
1742 }
1743
1744 static gboolean
1745 gtk_entry_completion_insert_completion (GtkEntryCompletion *completion,
1746                                         GtkTreeModel       *model,
1747                                         GtkTreeIter        *iter)
1748 {
1749   gchar *str = NULL;
1750
1751   if (completion->priv->text_column < 0)
1752     return FALSE;
1753
1754   gtk_tree_model_get (model, iter,
1755                       completion->priv->text_column, &str,
1756                       -1);
1757
1758   gtk_entry_completion_insert_completion_text (completion, str);
1759
1760   g_free (str);
1761
1762   return TRUE;
1763 }
1764
1765 /**
1766  * gtk_entry_completion_insert_prefix:
1767  * @completion: a #GtkEntryCompletion
1768  * 
1769  * Requests a prefix insertion. 
1770  * 
1771  * Since: 2.6
1772  **/
1773
1774 void
1775 gtk_entry_completion_insert_prefix (GtkEntryCompletion *completion)
1776 {
1777   gboolean done;
1778   gchar *prefix;
1779
1780   if (completion->priv->insert_text_id > 0)
1781     g_signal_handler_block (completion->priv->entry,
1782                             completion->priv->insert_text_id);
1783
1784   prefix = gtk_entry_completion_compute_prefix (completion);
1785   if (prefix)
1786     {
1787       g_signal_emit (completion, entry_completion_signals[INSERT_PREFIX],
1788                      0, prefix, &done);
1789       g_free (prefix);
1790     }
1791
1792   if (completion->priv->insert_text_id > 0)
1793     g_signal_handler_unblock (completion->priv->entry,
1794                               completion->priv->insert_text_id);
1795 }
1796
1797 /**
1798  * gtk_entry_completion_set_inline_completion:
1799  * @completion: a #GtkEntryCompletion
1800  * @inline_completion: %TRUE to do inline completion
1801  * 
1802  * Sets whether the common prefix of the possible completions should
1803  * be automatically inserted in the entry.
1804  * 
1805  * Since: 2.6
1806  **/
1807 void 
1808 gtk_entry_completion_set_inline_completion (GtkEntryCompletion *completion,
1809                                             gboolean            inline_completion)
1810 {
1811   g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1812   
1813   inline_completion = inline_completion != FALSE;
1814
1815   if (completion->priv->inline_completion != inline_completion)
1816     {
1817       completion->priv->inline_completion = inline_completion;
1818
1819       g_object_notify (G_OBJECT (completion), "inline-completion");
1820     }
1821 }
1822
1823 /**
1824  * gtk_entry_completion_get_inline_completion:
1825  * @completion: a #GtkEntryCompletion
1826  * 
1827  * Returns whether the common prefix of the possible completions should
1828  * be automatically inserted in the entry.
1829  * 
1830  * Return value: %TRUE if inline completion is turned on
1831  * 
1832  * Since: 2.6
1833  **/
1834 gboolean
1835 gtk_entry_completion_get_inline_completion (GtkEntryCompletion *completion)
1836 {
1837   g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), FALSE);
1838   
1839   return completion->priv->inline_completion;
1840 }
1841
1842 /**
1843  * gtk_entry_completion_set_popup_completion:
1844  * @completion: a #GtkEntryCompletion
1845  * @popup_completion: %TRUE to do popup completion
1846  * 
1847  * Sets whether the completions should be presented in a popup window.
1848  * 
1849  * Since: 2.6
1850  **/
1851 void 
1852 gtk_entry_completion_set_popup_completion (GtkEntryCompletion *completion,
1853                                            gboolean            popup_completion)
1854 {
1855   g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1856   
1857   popup_completion = popup_completion != FALSE;
1858
1859   if (completion->priv->popup_completion != popup_completion)
1860     {
1861       completion->priv->popup_completion = popup_completion;
1862
1863       g_object_notify (G_OBJECT (completion), "popup-completion");
1864     }
1865 }
1866
1867
1868 /**
1869  * gtk_entry_completion_get_popup_completion:
1870  * @completion: a #GtkEntryCompletion
1871  * 
1872  * Returns whether the completions should be presented in a popup window.
1873  * 
1874  * Return value: %TRUE if popup completion is turned on
1875  * 
1876  * Since: 2.6
1877  **/
1878 gboolean
1879 gtk_entry_completion_get_popup_completion (GtkEntryCompletion *completion)
1880 {
1881   g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), TRUE);
1882   
1883   return completion->priv->popup_completion;
1884 }
1885
1886 /**
1887  * gtk_entry_completion_set_popup_set_width:
1888  * @completion: a #GtkEntryCompletion
1889  * @popup_set_width: %TRUE to make the width of the popup the same as the entry
1890  *
1891  * Sets whether the completion popup window will be resized to be the same
1892  * width as the entry.
1893  *
1894  * Since: 2.8
1895  */
1896 void 
1897 gtk_entry_completion_set_popup_set_width (GtkEntryCompletion *completion,
1898                                           gboolean            popup_set_width)
1899 {
1900   g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1901   
1902   popup_set_width = popup_set_width != FALSE;
1903
1904   if (completion->priv->popup_set_width != popup_set_width)
1905     {
1906       completion->priv->popup_set_width = popup_set_width;
1907
1908       g_object_notify (G_OBJECT (completion), "popup-set-width");
1909     }
1910 }
1911
1912 /**
1913  * gtk_entry_completion_get_popup_set_width:
1914  * @completion: a #GtkEntryCompletion
1915  * 
1916  * Returns whether the  completion popup window will be resized to the 
1917  * width of the entry.
1918  * 
1919  * Return value: %TRUE if the popup window will be resized to the width of 
1920  *   the entry
1921  * 
1922  * Since: 2.8
1923  **/
1924 gboolean
1925 gtk_entry_completion_get_popup_set_width (GtkEntryCompletion *completion)
1926 {
1927   g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), TRUE);
1928   
1929   return completion->priv->popup_set_width;
1930 }
1931
1932
1933 /**
1934  * gtk_entry_completion_set_popup_single_match:
1935  * @completion: a #GtkEntryCompletion
1936  * @popup_single_match: %TRUE if the popup should appear even for a single
1937  *   match
1938  *
1939  * Sets whether the completion popup window will appear even if there is
1940  * only a single match. You may want to set this to %FALSE if you
1941  * are using <link linkend="GtkEntryCompletion--inline-completion">inline
1942  * completion</link>.
1943  *
1944  * Since: 2.8
1945  */
1946 void 
1947 gtk_entry_completion_set_popup_single_match (GtkEntryCompletion *completion,
1948                                              gboolean            popup_single_match)
1949 {
1950   g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1951   
1952   popup_single_match = popup_single_match != FALSE;
1953
1954   if (completion->priv->popup_single_match != popup_single_match)
1955     {
1956       completion->priv->popup_single_match = popup_single_match;
1957
1958       g_object_notify (G_OBJECT (completion), "popup-single-match");
1959     }
1960 }
1961
1962 /**
1963  * gtk_entry_completion_get_popup_single_match:
1964  * @completion: a #GtkEntryCompletion
1965  * 
1966  * Returns whether the completion popup window will appear even if there is
1967  * only a single match. 
1968  * 
1969  * Return value: %TRUE if the popup window will appear regardless of the
1970  *    number of matches.
1971  * 
1972  * Since: 2.8
1973  **/
1974 gboolean
1975 gtk_entry_completion_get_popup_single_match (GtkEntryCompletion *completion)
1976 {
1977   g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), TRUE);
1978   
1979   return completion->priv->popup_single_match;
1980 }
1981
1982 /**
1983  * gtk_entry_completion_set_inline_selection:
1984  * @completion: a #GtkEntryCompletion
1985  * @inline_selection: %TRUE to do inline selection
1986  * 
1987  * Sets whether it is possible to cycle through the possible completions
1988  * inside the entry.
1989  * 
1990  * Since: 2.12
1991  **/
1992 void
1993 gtk_entry_completion_set_inline_selection (GtkEntryCompletion *completion,
1994                                            gboolean inline_selection)
1995 {
1996   g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
1997
1998   inline_selection = inline_selection != FALSE;
1999
2000   if (completion->priv->inline_selection != inline_selection)
2001     {
2002       completion->priv->inline_selection = inline_selection;
2003
2004       g_object_notify (G_OBJECT (completion), "inline-selection");
2005     }
2006 }
2007
2008 /**
2009  * gtk_entry_completion_get_inline_selection:
2010  * @completion: a #GtkEntryCompletion
2011  *
2012  * Returns %TRUE if inline-selection mode is turned on.
2013  *
2014  * Returns: %TRUE if inline-selection mode is on
2015  *
2016  * Since: 2.12
2017  **/
2018 gboolean
2019 gtk_entry_completion_get_inline_selection (GtkEntryCompletion *completion)
2020 {
2021   g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), FALSE);
2022
2023   return completion->priv->inline_selection;
2024 }