#include "main.h"
 #include "bookmark.h"
 #include "util.h"
+#include "completion.h"
 
 extern VbCore vb;
 
     return removed;
 }
 
-/**
- * Retrieves all bookmark uri matching the given space separated tags string.
- * Don't forget to free the returned list.
- */
-GList *bookmark_get_by_tags(const char *tags)
+gboolean bookmark_fill_completion(GtkListStore *store, const char *input)
 {
-    GList *res = NULL, *src = NULL;
+    gboolean found = false;
     char **parts;
     unsigned int len;
+    GtkTreeIter iter;
+    GList *src = NULL;
     Bookmark *bm;
 
     src = load(vb.files[FILES_BOOKMARK]);
-    if (!tags || *tags == '\0') {
+    if (!input || *input == '\0') {
         /* without any tags return all bookmarked items */
         for (GList *l = src; l; l = l->next) {
             bm = (Bookmark*)l->data;
-            res = g_list_prepend(res, g_strdup(bm->uri));
+            gtk_list_store_append(store, &iter);
+            gtk_list_store_set(store, &iter, COMPLETION_STORE_FIRST, bm->uri, -1);
+            found = true;
         }
     } else {
-        parts = g_strsplit(tags, " ", 0);
+        parts = g_strsplit(input, " ", 0);
         len   = g_strv_length(parts);
 
         for (GList *l = src; l; l = l->next) {
             if (bm->tags
                 && util_array_contains_all_tags(bm->tags, g_strv_length(bm->tags), parts, len)
             ) {
-                res = g_list_prepend(res, g_strdup(bm->uri));
+                gtk_list_store_append(store, &iter);
+                gtk_list_store_set(store, &iter, COMPLETION_STORE_FIRST, bm->uri, -1);
+                found = true;
             }
         }
         g_strfreev(parts);
 
     g_list_free_full(src, (GDestroyNotify)free_bookmark);
 
-    return res;
+    return found;
 }
 
 static GList *load(const char *file)
 
 
 gboolean bookmark_add(const char *uri, const char *title, const char *tags);
 gboolean bookmark_remove(const char *uri);
-GList *bookmark_get_by_tags(const char *tags);
+gboolean bookmark_fill_completion(GtkListStore *store, const char *input);
 
 #endif /* end of include guard: _BOOKMARK_H */
 
     }
 }
 
-GList *command_get_by_prefix(const char *prefix)
-{
-    GList *res = NULL;
-    /* according to vim we return only the long commands here */
-    GList *src = g_hash_table_get_keys(commands);
-
-    if (!prefix || prefix == '\0') {
-        for (GList *l = src; l; l = l->next) {
-            res = g_list_prepend(res, l->data);
-        }
-    } else {
-        for (GList *l = src; l; l = l->next) {
-            char *value = (char*)l->data;
-            if (g_str_has_prefix(value, prefix)) {
-                res = g_list_prepend(res, value);
-            }
-        }
-    }
-    g_list_free(src);
-
-    return res;
-}
-
 void command_cleanup(void)
 {
     if (commands) {
     return result;
 }
 
+gboolean command_fill_completion(GtkListStore *store, const char *input)
+{
+    gboolean found = false;
+    GtkTreeIter iter;
+    /* according to vim we return only the long commands here */
+    GList *src = g_hash_table_get_keys(commands);
+
+    if (!input || input == '\0') {
+        for (GList *l = src; l; l = l->next) {
+            gtk_list_store_append(store, &iter);
+            gtk_list_store_set(store, &iter, COMPLETION_STORE_FIRST, l->data, -1);
+            found = true;
+        }
+    } else {
+        for (GList *l = src; l; l = l->next) {
+            char *value = (char*)l->data;
+            if (g_str_has_prefix(value, input)) {
+                gtk_list_store_append(store, &iter);
+                gtk_list_store_set(store, &iter, COMPLETION_STORE_FIRST, l->data, -1);
+                found = true;
+            }
+        }
+    }
+    g_list_free(src);
+
+    return found;
+}
+
 gboolean command_open(const Arg *arg)
 {
     vb_set_mode(VB_MODE_NORMAL, false);
 
 typedef gboolean (*Command)(const Arg *arg);
 
 void command_init(void);
-GList *command_get_by_prefix(const char *prefix);
 void command_cleanup(void);
 gboolean command_parse_from_string(const char *input, Command *func, Arg *arg, guint *count);
 gboolean command_run_string(const char *input);
 gboolean command_run_multi(const Arg *arg);
+gboolean command_fill_completion(GtkListStore *store, const char *input);
 
 gboolean command_open(const Arg *arg);
 gboolean command_open_home(const Arg *arg);
 
 #include "setting.h"
 
 #define TAG_INDICATOR '!'
-#define COMP_ITEM 0
 
 extern VbCore vb;
 
     char      *text;   /* text of the current active tree item */
 } comp;
 
-static GtkTreeModel *get_tree_model(GList *source);
 static void init_completion(GtkTreeModel *model);
 static void show(gboolean back);
 static void move_cursor(gboolean back);
 {
     VbInputType type;
     const char *input, *prefix, *suffix;
-    GList *source = NULL;
-    GtkTreeModel *model = NULL;
+    GtkListStore *store = NULL;
+    gboolean res = false;
 
     input = GET_TEXT();
     type  = vb_get_input_parts(input, &prefix, &suffix);
         return false;
     }
 
+    /* create the list store model */
+    store = gtk_list_store_new(1, G_TYPE_STRING);
     if (type == VB_INPUT_SET) {
-        source = g_list_sort(setting_get_by_prefix(suffix), (GCompareFunc)g_strcmp0);
-        if (!g_list_first(source)) {
-            return false;
-        }
-        model  = get_tree_model(source);
-        g_list_free(source);
+        res = setting_fill_completion(store, suffix);
     } else if (type == VB_INPUT_OPEN || type == VB_INPUT_TABOPEN) {
         /* if search string begins with TAG_INDICATOR lookup the bookmarks */
         if (suffix && *suffix == TAG_INDICATOR) {
-            source = g_list_sort(bookmark_get_by_tags(suffix + 1), (GCompareFunc)g_strcmp0);
+            res = bookmark_fill_completion(store, suffix + 1);
         } else {
-            source = history_get_by_tags(HISTORY_URL, suffix);
-        }
-        if (!g_list_first(source)) {
-            return false;
+            res = history_fill_completion(store, HISTORY_URL, suffix);
         }
-        model = get_tree_model(source);
-        g_list_free_full(source, (GDestroyNotify)g_free);
     } else if (type == VB_INPUT_COMMAND) {
         char *command = NULL;
         /* remove counts before command and save it to print it later in inputbox */
         comp.count = g_ascii_strtoll(suffix, &command, 10);
 
-        source = g_list_sort(command_get_by_prefix(command), (GCompareFunc)g_strcmp0);
-        if (!g_list_first(source)) {
-            return false;
-        }
-        model = get_tree_model(source);
-        g_list_free(source);
+        res = command_fill_completion(store, command);
     } else if (type == VB_INPUT_SEARCH_FORWARD || type == VB_INPUT_SEARCH_BACKWARD) {
-        source = g_list_sort(history_get_by_tags(HISTORY_SEARCH, suffix), (GCompareFunc)g_strcmp0);
-        if (!g_list_first(source)) {
-            return false;
-        }
-        model  = get_tree_model(source);
-        g_list_free_full(source, (GDestroyNotify)g_free);
+        res = history_fill_completion(store, HISTORY_SEARCH, suffix);
+    }
+
+    if (!res) {
+        return false;
     }
 
     vb_set_mode(VB_MODE_COMMAND | VB_MODE_COMPLETE, false);
 
     OVERWRITE_STRING(comp.prefix, prefix);
-    init_completion(model);
+    init_completion(GTK_TREE_MODEL(store));
     show(back);
 
     return true;
     vb.state.mode &= ~VB_MODE_COMPLETE;
 }
 
-static GtkTreeModel *get_tree_model(GList *source)
-{
-    GtkTreeIter iter;
-    GtkListStore *store = gtk_list_store_new(1, G_TYPE_STRING);
-
-    for (GList *l = source; l; l = l->next) {
-        gtk_list_store_append(store, &iter);
-        gtk_list_store_set(store, &iter, COMP_ITEM, l->data, -1);
-    }
-    return GTK_TREE_MODEL(store);
-}
-
 static void init_completion(GtkTreeModel *model)
 {
     GtkCellRenderer *renderer;
     );
     gtk_tree_view_insert_column_with_attributes(
         GTK_TREE_VIEW(comp.tree), -1, "", renderer,
-        "text", COMP_ITEM,
+        "text", COMPLETION_STORE_FIRST,
         NULL
     );
 
     /* if not selected means the item is going to be selected which we are
      * interested in */
     if (!selected && gtk_tree_model_get_iter(model, &iter, path)) {
-        gtk_tree_model_get(model, &iter, COMP_ITEM, &value, -1);
+        gtk_tree_model_get(model, &iter, COMPLETION_STORE_FIRST, &value, -1);
         /* save the content of the selected item so wen can access it easy */
         if (comp.text) {
             g_free(comp.text);
 
 
 #include "main.h"
 
+enum {
+    COMPLETION_STORE_FIRST,
+    COMPLETION_STORE_SECOND
+};
+
 void completion_clean(void);
 gboolean completion_complete(gboolean back);
 
 
 #include "main.h"
 #include "history.h"
 #include "util.h"
+#include "completion.h"
 
 extern VbCore vb;
 
     }
 }
 
-/**
- * Retrieves the list of matching history items to given tag string.
- * Returned list must be freed.
- */
-GList *history_get_by_tags(HistoryType type, const char *tags)
-{
-    GList *res = NULL, *src = NULL;
-    char **parts;
-    unsigned int len;
-    History *item;
-
-    src = load(get_file_by_type(type));
-    if (!tags || *tags == '\0') {
-        /* without any tags return all items */
-        for (GList *l = src; l; l = l->next) {
-            item = l->data;
-            res = g_list_prepend(res, g_strdup(item->first));
-        }
-    } else if (HISTORY_URL == type) {
-        parts = g_strsplit(tags, " ", 0);
-        len   = g_strv_length(parts);
-
-        for (GList *l = src; l; l = l->next) {
-            item = l->data;
-            if (util_string_contains_all_tags(item->first, parts, len)) {
-                res = g_list_prepend(res, g_strdup(item->first));
-            }
-        }
-        g_strfreev(parts);
-    } else {
-        for (GList *l = src; l; l = l->next) {
-            item = l->data;
-            if (g_str_has_prefix(item->first, tags)) {
-                res = g_list_prepend(res, g_strdup(item->first));
-            }
-        }
-    }
-    g_list_free_full(src, (GDestroyNotify)g_free);
-
-    return res;
-}
-
 /**
  * Retrieves the item from history to be shown in input box.
  * The result must be freed by the caller.
     }
 }
 
+gboolean history_fill_completion(GtkListStore *store, HistoryType type, const char *input)
+{
+    char **parts;
+    unsigned int len;
+    gboolean found = false;
+    GList *src = NULL;
+    GtkTreeIter iter;
+    History *item;
+
+    src = load(get_file_by_type(type));
+    if (!input || *input == '\0') {
+        /* without any tags return all items */
+        for (GList *l = src; l; l = l->next) {
+            item = l->data;
+            gtk_list_store_append(store, &iter);
+            gtk_list_store_set(store, &iter, COMPLETION_STORE_FIRST, item->first, -1);
+            found = true;
+        }
+    } else if (HISTORY_URL == type) {
+        parts = g_strsplit(input, " ", 0);
+        len   = g_strv_length(parts);
+
+        for (GList *l = src; l; l = l->next) {
+            item = l->data;
+            if (util_string_contains_all_tags(item->first, parts, len)) {
+                gtk_list_store_append(store, &iter);
+                gtk_list_store_set(store, &iter, COMPLETION_STORE_FIRST, item->first, -1);
+                found = true;
+            }
+        }
+        g_strfreev(parts);
+    } else {
+        for (GList *l = src; l; l = l->next) {
+            item = l->data;
+            if (g_str_has_prefix(item->first, input)) {
+                gtk_list_store_append(store, &iter);
+                gtk_list_store_set(store, &iter, COMPLETION_STORE_FIRST, item->first, -1);
+                found = true;
+            }
+        }
+    }
+    g_list_free_full(src, (GDestroyNotify)g_free);
+
+    return found;
+}
+
 /**
  * Retrieves the list of matching history items.
  * The list must be freed.
 
 GList *history_get_by_tags(HistoryType type, const char *tags);
 char *history_get(const char *input, gboolean prev);
 void history_rewind(void);
+gboolean history_fill_completion(GtkListStore *store, HistoryType type, const char *input);
 
 #endif /* end of include guard: _HISTORY_H */
 
 
 #include "setting.h"
 #include "util.h"
+#include "completion.h"
 
 static GHashTable *settings;
 
     }
 }
 
-/**
- * Retrieves the settings names as list for given prefix.
- */
-GList* setting_get_by_prefix(const char *prefix)
-{
-    GList *res = NULL;
-    GList *src = g_hash_table_get_keys(settings);
-
-    if (!prefix || prefix == '\0') {
-        for (GList *l = src; l; l = l->next) {
-            res = g_list_prepend(res, l->data);
-        }
-    } else {
-        for (GList *l = src; l; l = l->next) {
-            char *value = (char*)l->data;
-            if (g_str_has_prefix(value, prefix)) {
-                res = g_list_prepend(res, value);
-            }
-        }
-    }
-    g_list_free(src);
-
-    return res;
-}
-
 void setting_cleanup(void)
 {
     if (settings) {
     return result;
 }
 
+gboolean setting_fill_completion(GtkListStore *store, const char *input)
+{
+    gboolean found = false;
+    GtkTreeIter iter;
+    GList *src = g_hash_table_get_keys(settings);
+
+    if (!input || input == '\0') {
+        for (GList *l = src; l; l = l->next) {
+            gtk_list_store_append(store, &iter);
+            gtk_list_store_set(store, &iter, COMPLETION_STORE_FIRST, l->data, -1);
+            found = true;
+        }
+    } else {
+        for (GList *l = src; l; l = l->next) {
+            char *value = (char*)l->data;
+            if (g_str_has_prefix(value, input)) {
+                gtk_list_store_append(store, &iter);
+                gtk_list_store_set(store, &iter, COMPLETION_STORE_FIRST, l->data, -1);
+                found = true;
+            }
+        }
+    }
+    /* TODO sort the store model */
+    g_list_free(src);
+
+    return found;
+}
+
 /**
  * Converts string representing also given data type into and Arg.
  */
 
 };
 
 void setting_init(void);
-GList* setting_get_by_prefix(const char *prefix);
 void setting_cleanup(void);
 gboolean setting_run(char* name, const char* param);
+gboolean setting_fill_completion(GtkListStore *store, const char *input);
 
 #endif /* end of include guard: _SETTING_H */