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