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