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