diff --git a/inc/lektor/commands.h b/inc/lektor/commands.h
index 3329c8a48a5e26e2799d045e74eae4251f1797ed..1cc95b662f09d14105422e3284922576e58fdca0 100644
--- a/inc/lektor/commands.h
+++ b/inc/lektor/commands.h
@@ -70,10 +70,8 @@ enum lkt_find_action {
 };
 
 /* Find and send karas in the db that match the search expression */
-bool command_find(struct lkt_state *srv,
-                  size_t c,
-                  char *cmd_args[LKT_MESSAGE_ARGS_MAX],
-                  enum lkt_find_action action);
+bool command_find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MAX],
+                  long continuation, enum lkt_find_action action);
 
 /* Set options for the lektor such as `random`, `single`, `repeat`, etc */
 enum lkt_playback_option {
diff --git a/inc/lektor/database.h b/inc/lektor/database.h
index 475206c5e695c6419e26f7077487e4d6236edb19..748916227b2fe9597a9e86c5fd5be187302ca837 100644
--- a/inc/lektor/database.h
+++ b/inc/lektor/database.h
@@ -74,18 +74,37 @@ bool database_queue_play(sqlite3 *db, int pos);
 bool database_queue_stop(sqlite3 *db);
 
 /* A search callback to be called after each matched row */
-typedef bool (*database_search_callback_t)(void *args, int id, int id_len, const char *sql_row);
+struct lkt_callback {
+    bool (*call)(void *args, int id, int id_len, const char *sql_row);
+    struct lkt_state *srv;
+    size_t c;
+    int iterations;
+};
 
 /* List the content of the queue */
-bool database_queue_list_from(sqlite3 *db, unsigned int count, void *args,
-                              database_search_callback_t callback);
-bool database_queue_list_abs(sqlite3 *db, unsigned int from, unsigned int to, void *args,
-                             database_search_callback_t callback);
+bool database_queue_list(sqlite3 *db, size_t from, size_t to, struct lkt_callback *callback);
 
 /* Search the database */
-bool database_search_init(sqlite3 *db, char *col_name, char *rgx, sqlite3_stmt **ret);
-bool database_search_iter(sqlite3 *db, sqlite3_stmt *item, void *args,
-                          database_search_callback_t callback, bool *need_free);
+struct lkt_search {
+    sqlite3 *db;
+    sqlite3_stmt *stmt;
+    enum lkt_search_type {
+        lkt_search_database,
+        lkt_search_playlist,
+        lkt_search_queue,
+    } type;
+    void (*call)(void); /* Will be casted. */
+    struct lkt_state *srv;
+    size_t c;
+    long continuation;  /* Is this a continuation from a previous command? */
+    int msg_count;      /* How much messages we can send. */
+};
+
+typedef bool (*lkt_search_database_func)(struct lkt_state *srv, size_t c, int id, int id_len,
+        const char *row);
+
+bool database_search_queue_init(sqlite3 *db, char *col_name, char *rgx, struct lkt_search *ret);
+bool database_search_iter(struct lkt_search *item);
 
 /* Next and prev operation on the queue. */
 bool database_queue_next(sqlite3 *db, char filepath[PATH_MAX]);
@@ -126,14 +145,18 @@ bool database_user_authentificate(sqlite3 *db, const char *password);
 bool database_user_add(sqlite3 *db, const char *username, const char *password);
 
 /* Stickers manipulations. */
-typedef bool (*database_sticker_callback_t)(void *args, const char *sticker, const char *type,
-        int uri, int value);
+struct sticker_callback {
+    struct lkt_state *srv;
+    size_t c;
+    int uri, value, is_ok;
+    const char *name;
+    bool (*call)(void *args, const char *sticker, const char *type, int uri, int value);
+};
 
 bool database_sticker_create(sqlite3 *db, const char *name);
 bool database_sticker_delete(sqlite3 *db, const char *name);
-bool database_sticker_delete_specify(sqlite3 *sb, const char *type, int uri,
-                                     const char *name /* Can be null */);
-bool database_sticker_list(sqlite3 *db, const char *type, void *args, database_sticker_callback_t call);
+bool database_sticker_delete_specify(sqlite3 *sb, const char *type, int uri, const char *name);
+bool database_sticker_list(sqlite3 *db, const char *type, struct sticker_callback *call);
 bool database_sticker_set(sqlite3 *db, const char *type, const char *name, int uri, int value);
-bool database_sticker_get(sqlite3 *db, const char *type, const char *name, int uri, void *args,
-                          database_sticker_callback_t call);
+bool database_sticker_get(sqlite3 *db, const char *type, const char *name, int uri,
+                          struct sticker_callback *call);
diff --git a/inc/lektor/defines.h b/inc/lektor/defines.h
index 600d4b503c1157c510fa4f94eb0d5cc77939c79a..c6eac5cdabfa5a5119f7f8be73bd1c53f2e2603c 100644
--- a/inc/lektor/defines.h
+++ b/inc/lektor/defines.h
@@ -9,7 +9,7 @@
 #define LKT_DATABASE_NAME_KTITLE        "song_title"
 #define LKT_DATABASE_NAME_KCAT          "song_type"
 #define LKT_DATABASE_NAME_KTYPE         "category"
-#define LKT_DATABASE_NAME_KAUTHOR       "author"
+#define LKT_DATABASE_NAME_KAUTHOR       "author_name"
 #define LKT_DATABASE_NAME_KAUTHOR_YEAR  "author_year"
 #define LKT_DATABASE_NAME_KLANG         "language"
 #define LKT_DATABASE_KARA_COLUMNT_ANY   "any_col"
diff --git a/inc/lektor/net.h b/inc/lektor/net.h
index f862eb6dd44c0b86fd753e45af3a2721db6dc1d2..0b29e70f41dcafa1f28fc3e345d1863bcba9b975 100644
--- a/inc/lektor/net.h
+++ b/inc/lektor/net.h
@@ -11,6 +11,7 @@
 struct lkt_command {
     char *name;
     char *args[LKT_MESSAGE_ARGS_MAX];
+    long cont;
 };
 
 /* Create and destruct a command structure. */
@@ -46,6 +47,12 @@ struct lkt_state {
 /* Send a message to the connected client. */
 void lkt_state_send(struct lkt_state *srv, size_t c, struct lkt_message *msg);
 
+/* Get and set continuation state for a client. */
+size_t lkt_remaining_msg(struct lkt_state *srv, size_t c);
+
+int lkt_get_continuation(struct lkt_state *srv, size_t c);
+void lkt_set_continuation(struct lkt_state *srv, size_t c, int i);
+
 /* Get the mask to watch for events for a given client, to be used with the `idle` command.
  * Return a pointer to the client's mask */
 enum mpd_idle_flag *lkt_client_get_mask(struct lkt_state *srv, size_t c);
diff --git a/src/commands.c b/src/commands.c
index 1c5254629204d094134de368286e49adac14bd12..9f29e29adf6a6a26fcdccaad8d24905dfa3c25e2 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -1,5 +1,6 @@
 #define _POSIX_C_SOURCE 200809L
 
+#include <lektor/macro.h>
 #include <lektor/commands.h>
 #include <lektor/database.h>
 #include <lektor/net.h>
@@ -21,15 +22,6 @@
 #define SELF_EXECUTABLE_FREEBSD "/proc/curproc/file"
 #define SELF_EXECUTABLE_SOLARIS "/proc/self/path/a.out"
 
-struct _client_trace_t {
-    struct lkt_state *srv;
-    size_t c;
-    int uri;
-    const char *name;
-    int value;
-    bool is_ok;
-};
-
 inline bool
 command_restart(struct lkt_state *srv, size_t c)
 {
@@ -67,12 +59,10 @@ bool
 command_rescan(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX])
 {
     (void) argv;
-
     if (!lkt_client_auth(srv, c, false)) {
         fprintf(stderr, " ! command_rescan: Failed, user %lu not authentificated\n", c);
         return false;
     }
-
     return ! repo_get_allid_async();
 }
 
@@ -83,7 +73,6 @@ command_kill(struct lkt_state *srv, size_t c)
         fprintf(stderr, " ! command_restart: Failed to restart, user not authentificated %lu\n", c);
         return false;
     }
-
     fprintf(stderr, " * Stopping lektord\n");
     close(srv->fds[0].fd);
     exit(EXIT_SUCCESS);
@@ -252,10 +241,8 @@ command_stop(sqlite3 *db, struct lkt_win *win, enum mpd_idle_flag *watch_mask_pt
 {
     *watch_mask_ptr |= MPD_IDLE_PLAYER;
     bool res = database_queue_stop(db);
-
     if (res)
         win->close(win);
-
     return res;
 }
 
@@ -272,16 +259,11 @@ command_add(sqlite3 *db, struct lkt_win *win, char *args[LKT_MESSAGE_ARGS_MAX],
     struct lkt_uri_t uri;
     char *query = args[0];
     bool ret, is_insert = false;
-    int priority = 1; /* To be modified according to the command (insert or add) later */
-
+    int priority = 1;   /* To be modified according to the command (insert or add) later */
 
     (void) is_insert;   // Don't know what insert looks like
     (void) win;         // No callbacks to the window for the moment
 
-    int i;
-    for (i = 0; args[i] != NULL; ++i)
-        printf("%s", args[i]);
-
     if (!lkt_uri_from(&uri, query)) {
         fprintf(stderr, " ! command_add: failed to parse query '%s', invalid uri\n", query);
         return false;
@@ -351,14 +333,14 @@ command_addid(sqlite3 *db, struct lkt_win *win, char *args[LKT_MESSAGE_ARGS_MAX]
     return database_queue_add_id(db, id, priority);
 }
 
-bool
+inline bool
 command_clear(sqlite3 *db, enum mpd_idle_flag *watch_mask_ptr)
 {
     *watch_mask_ptr |= MPD_IDLE_PLAYLIST;
     return database_queue_clear(db);
 }
 
-bool
+inline bool
 command_crop(sqlite3 *db, enum mpd_idle_flag *watch_mask_ptr)
 {
     *watch_mask_ptr |= MPD_IDLE_PLAYLIST;
@@ -511,38 +493,27 @@ command_idle(struct lkt_state *srv, size_t c, struct lkt_command *cmd)
     return true;
 }
 
-bool
+inline bool
 command_noidle(struct lkt_state *srv, size_t c)
 {
     enum mpd_idle_flag *clt_mask = lkt_client_get_mask(srv, c);
     *clt_mask = MPD_IDLE_NONE;
-
     return true;
 }
 
 /* Functions for the searchadd and the search mpd commands */
 static bool
-lkt_callback_print_row_v1(void *args, int id, int id_len, const char *sql_row)
+lkt_callback_print_row_v1(struct lkt_state *srv, size_t c, int id, int id_len, const char *sql_row)
 {
-    printf(" . from client %ld:\t%*d:%s\n", ((struct _client_trace_t *) args)->c,
-           id_len, id, sql_row);
-    return true;
-}
-
-static bool
-lkt_callback_none(void *args, int id, int id_len, const char *sql_row)
-{
-    (void) args;
-    (void) id;
-    (void) id_len;
-    (void) sql_row;
+    (void) srv;
+    printf(" . from client %ld:\t%*d:%s\n", c, id_len, id, sql_row);
     return true;
 }
 
 static bool
 lkt_callback_send_row_v1(void *_args, int id, int id_len, const char *sql_row)
 {
-    struct _client_trace_t *args = (struct _client_trace_t *) _args;
+    struct lkt_callback *args = (struct lkt_callback *) _args;
     struct lkt_message *out;
 
     out = lkt_message_new();
@@ -552,26 +523,35 @@ lkt_callback_send_row_v1(void *_args, int id, int id_len, const char *sql_row)
 }
 
 static bool
-lkt_callback_insert_v1(void *_args, int id, int id_len, const char *sql_row)
+lkt_callback_send_row_v2(struct lkt_state *srv, size_t c, int id, int id_len, const char *sql_row)
+{
+    struct lkt_message *out = lkt_message_new();
+    out->data_len = snprintf(out->data, LKT_MESSAGE_MAX, "%*d %s\n", id_len, id, sql_row);
+    lkt_state_send(srv, c, out);
+    return true;
+}
+
+static bool
+lkt_callback_insert_v1(struct lkt_state *srv, size_t c, int id, int id_len, const char *sql_row)
 {
+    (void) c;
     (void) sql_row;
     (void) id_len;
-    struct _client_trace_t *args = (struct _client_trace_t *) _args;
-    return database_queue_add_id(args->srv->db, id, 5);
+    return database_queue_add_id(srv->db, id, 5);
 }
 
 bool
-command_find(struct lkt_state *srv,
-             size_t c,
-             char *cmd_args[LKT_MESSAGE_ARGS_MAX],
+command_find(struct lkt_state *srv, size_t c, char *cmd_args[LKT_MESSAGE_ARGS_MAX], long continuation,
              enum lkt_find_action action)
 {
-    sqlite3_stmt *stmt;
     char rgx[PATH_MAX], *col_name, *mpd_tag;
-    bool once, free_stmt;
-    struct _client_trace_t args;
-    struct lkt_message *not_found_msg;
-    database_search_callback_t callback;
+    int count;
+    struct lkt_search search = {
+        .srv = srv,
+        .c = c,
+        .continuation = continuation,
+        .msg_count = lkt_remaining_msg(srv, c) - 3, /* Reserve slots for OK/ACK and continue: */
+    };
 
     // Check args //
     if (cmd_args == NULL || cmd_args[0] == NULL) {
@@ -582,23 +562,17 @@ command_find(struct lkt_state *srv,
     // Select callback //
     switch (action) {
     case LKT_FND_ACT_RESPOND:
-        callback = lkt_callback_send_row_v1;
-        args.srv = srv;
-        args.c = c;
+        search.call = (void(*)(void)) lkt_callback_send_row_v2;
         break;
     case LKT_FND_ACT_PRINT:
-        callback = lkt_callback_print_row_v1;
+        search.call = (void(*)(void)) lkt_callback_print_row_v1;
         break;
     case LKT_FND_ACT_ENQUEUE:
-        callback = lkt_callback_insert_v1;
+        search.call = (void(*)(void)) lkt_callback_insert_v1;
         srv->mpd_idle_events |= MPD_IDLE_PLAYLIST;
-        args.srv = srv;
-        args.c = c;
         break;
-    case LKT_FND_ACT_NONE:
     default:
-        callback = lkt_callback_none;
-        break;
+        return false;
     }
 
     // Select the right column //
@@ -637,28 +611,19 @@ command_find(struct lkt_state *srv,
     }
 
     // Make the search langand do the right action //
-    if (!database_search_init(srv->db, col_name, rgx, &stmt)) {
+    if (!database_search_queue_init(srv->db, col_name, rgx, &search)) {
         fprintf(stderr, " ! command_find: Failed to init the search\n");
         return false;
     }
 
-    for (once = false; database_search_iter(srv->db, stmt, &args, callback, &free_stmt); once |= true)
+    for (count = 0; database_search_iter(&search); ++count)
         continue;
 
-    // End //
-    if (free_stmt)
-        sqlite3_finalize(stmt);
-
-    if (!once) {
-no_rgx:
-        not_found_msg = lkt_message_new();
-        not_found_msg->data_len = snprintf(not_found_msg->data,
-                                           LKT_MESSAGE_MAX,
-                                           "No kara found with regex\n");
-        lkt_state_send(srv, c, not_found_msg);
-    }
-
+    if (count)
+        lkt_set_continuation(srv, c, continuation + count);
     return true;
+no_rgx:
+    return false;
 }
 
 bool
@@ -669,8 +634,7 @@ command_set_playback_option(struct lkt_state *srv, size_t c,
         return false;
 
     (void) c;
-    long val;
-    bool ret = false;
+    long val, ret = false;
     char *endptr;
     struct lkt_win *win = &srv->win;
 
@@ -924,14 +888,13 @@ command_shuffle(sqlite3 *db, enum mpd_idle_flag *watch_mask_ptr)
 }
 
 bool
-command_queue_list(struct lkt_state *srv, size_t c,
-                   char *args[LKT_MESSAGE_ARGS_MAX])
+command_queue_list(struct lkt_state *srv, size_t c, char *args[LKT_MESSAGE_ARGS_MAX])
 {
-    unsigned int count;
     unsigned int from, to, tmp_switch;
     long val;
     char *endptr, *str;
-    struct _client_trace_t callback_args = {
+    struct lkt_callback callback = {
+        .call = lkt_callback_send_row_v1,
         .srv = srv,
         .c = c,
     };
@@ -957,16 +920,15 @@ command_queue_list(struct lkt_state *srv, size_t c,
         return false;
     }
 
-    if (*endptr == '\0') {
-        /* There is nothing after, is is the relative forme of the command. */
-        count = labs(val);
-        goto is_relative;
-    }
+    from = labs(val);
 
+    /* There is nothing after, is is the song pos version. */
+    if (*endptr == '\0')
+        goto only_one;
+
+    /* There is something after, this is the absolute forme of the command. Then
+       parse the second value. Skip the supposed ':' character. */
     else {
-        /* There is something after, this is the absolute forme of the command. Then
-           parse the second value. Skip the supposed ':' character. */
-        from = labs(val);
         str = endptr + strspn(endptr, "-+: "); // NO NEGATIVE! //
         val = strtol(str, &endptr, 0);
 
@@ -990,21 +952,26 @@ command_queue_list(struct lkt_state *srv, size_t c,
             from = tmp_switch;
         }
 
-        goto is_absolute;
+        goto is_a_range;
     }
 
     return false;
 
     /* The command is used in its relative forme, display elements from the
        current one. */
-is_relative:
-    return database_queue_list_from(srv->db, count, &callback_args,
-                                    lkt_callback_send_row_v1);
+only_one:
+    return database_queue_list(srv->db, from, from, &callback);
 
     /* The command is used with a range specifier. */
-is_absolute:
-    return database_queue_list_abs(srv->db, from, to, &callback_args,
-                                   lkt_callback_send_row_v1);
+is_a_range:
+    if (to - from + 1 < lkt_remaining_msg(srv, c) - 2) {
+        lkt_set_continuation(srv, c, 0);
+        return database_queue_list(srv->db, from, to, &callback);
+    } else {
+        to = from + lkt_remaining_msg(srv, c) - 3;
+        lkt_set_continuation(srv, c, to + 1);
+        return database_queue_list(srv->db, from, to, &callback);
+    }
 }
 
 bool
@@ -1042,16 +1009,16 @@ command_user_add(sqlite3 *db, char *argv[LKT_MESSAGE_ARGS_MAX])
     fprintf(stderr, " . command_user_add: Failed to add user %s\n", argv[0]);
 }
 
+/* Stickers */
+
 static bool
 sticker_send_one_value(void *_args, const char *sticker, const char *type, int uri, int value)
 {
-    struct _client_trace_t *args = (struct _client_trace_t *) _args;
-    struct lkt_message *out;
     (void) sticker;
     (void) type;
     (void) uri;
-
-    out = lkt_message_new();
+    struct sticker_callback *args = (struct sticker_callback *) _args;
+    struct lkt_message *out = lkt_message_new();
     out->data_len = snprintf(out->data, LKT_MESSAGE_MAX, "value: %d\n", value);
     lkt_state_send(args->srv, args->c, out);
     return false;
@@ -1060,10 +1027,8 @@ sticker_send_one_value(void *_args, const char *sticker, const char *type, int u
 static bool
 sticker_send_all(void *_args, const char *sticker, const char *type, int uri, int value)
 {
-    struct _client_trace_t *args = (struct _client_trace_t *) _args;
-    struct lkt_message *out;
-
-    out = lkt_message_new();
+    struct sticker_callback *args = (struct sticker_callback *) _args;
+    struct lkt_message *out = lkt_message_new();
     out->data_len = snprintf(out->data, LKT_MESSAGE_MAX, "%s: %d\nsticker: %s\nvalue: %d\n",
                              type, uri, sticker, value);
     lkt_state_send(args->srv, args->c, out);
@@ -1073,12 +1038,11 @@ sticker_send_all(void *_args, const char *sticker, const char *type, int uri, in
 static bool
 sticker_send_check_uri(void *_args, const char *sticker, const char *type, int uri, int value)
 {
-    struct _client_trace_t *args = (struct _client_trace_t *) _args;
-    struct lkt_message *out;
+    struct sticker_callback *args = (struct sticker_callback *) _args;
     (void) type;
 
     if (uri == args->uri) {
-        out = lkt_message_new();
+        struct lkt_message *out = lkt_message_new();
         out->data_len = snprintf(out->data, LKT_MESSAGE_MAX, "%s: %d\n", sticker, value);
         lkt_state_send(args->srv, args->c, out);
     }
@@ -1089,7 +1053,7 @@ sticker_send_check_uri(void *_args, const char *sticker, const char *type, int u
 static bool
 sticker_send_value_check_uri_name(void *_args, const char *sticker, const char *type, int uri, int value)
 {
-    struct _client_trace_t *args = (struct _client_trace_t *) _args;
+    struct sticker_callback *args = (struct sticker_callback *) _args;
     struct lkt_message *out;
     (void) type;
 
@@ -1106,7 +1070,7 @@ static bool
 sticker_check_is_present_eq(void *_args, const char *sticker, const char *type, int uri, int value)
 {
     (void) type;
-    struct _client_trace_t *args = (struct _client_trace_t *) _args;
+    struct sticker_callback *args = (struct sticker_callback *) _args;
     args->is_ok |= (uri == args->uri) && !strcasecmp(sticker, args->name) && (value == args->value);
     return true;
 }
@@ -1115,7 +1079,7 @@ static bool
 sticker_check_is_present_lt(void *_args, const char *sticker, const char *type, int uri, int value)
 {
     (void) type;
-    struct _client_trace_t *args = (struct _client_trace_t *) _args;
+    struct sticker_callback *args = (struct sticker_callback *) _args;
     args->is_ok |= (uri == args->uri) && !strcasecmp(sticker, args->name) && (value < args->value);
     return true;
 }
@@ -1124,7 +1088,7 @@ static bool
 sticker_check_is_present_gt(void *_args, const char *sticker, const char *type, int uri, int value)
 {
     (void) type;
-    struct _client_trace_t *args = (struct _client_trace_t *) _args;
+    struct sticker_callback *args = (struct sticker_callback *) _args;
     args->is_ok |= (uri == args->uri) && !strcasecmp(sticker, args->name) && (value > args->value);
     return true;
 }
@@ -1138,12 +1102,13 @@ command_sticker_get(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS
     }
 
     int uri = atoi(argv[1]); /* FIXME: Use strtol. */
-    struct _client_trace_t args = {
+    struct sticker_callback callback = {
         .srv = srv,
         .c = c,
+        .call = sticker_send_one_value,
     };
 
-    if (!database_sticker_get(srv->db, argv[0], argv[2], uri, &args, sticker_send_one_value)) {
+    if (!database_sticker_get(srv->db, argv[0], argv[2], uri, &callback)) {
         fprintf(stderr, " . command_sticker_get: Failed to get sticker '%s' for object %s(%d)\n",
                 argv[2], argv[0], uri);
         return false;
@@ -1170,13 +1135,14 @@ command_sticker_set(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS
         return false;
     }
 
+    srv->mpd_idle_events |= MPD_IDLE_STICKER;
     return true;
 }
 
 bool
 command_sticker_list(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX])
 {
-    struct _client_trace_t args = {
+    struct sticker_callback callback = {
         .srv = srv,
         .c = c,
     };
@@ -1204,29 +1170,35 @@ command_sticker_list(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARG
         goto unknown;
 
 just_list_all:
-    return database_sticker_list(srv->db, argv[0], &args, sticker_send_all);
+    callback.call = sticker_send_all;
+    return database_sticker_list(srv->db, argv[0], &callback);
 
 simple_list_command:
-    args.uri = atoi(argv[1]);   /* FIXME: Use strtol. */
-    return database_sticker_list(srv->db, argv[0], &args, sticker_send_check_uri);
+    callback.uri  = atoi(argv[1]);   /* FIXME: Use strtol. */
+    callback.call = sticker_send_check_uri;
+    return database_sticker_list(srv->db, argv[0], &callback);
 
 list_stickers_in_uri:
-    args.uri  = atoi(argv[1]);  /* FIXME: Use strtol. */
-    args.name = argv[2];
-    return database_sticker_list(srv->db, argv[0], &args, sticker_send_value_check_uri_name);
+    callback.uri  = atoi(argv[1]);  /* FIXME: Use strtol. */
+    callback.name = argv[2];
+    callback.call = sticker_send_value_check_uri_name;
+    return database_sticker_list(srv->db, argv[0], &callback);
     return false;
 
 list_stickers_check_value:
-    args.uri   = atoi(argv[1]); /* FIXME: Use strtol. */
-    args.value = atoi(argv[4]); /* FIXME: Use strtol. */
-    args.name  = argv[2];
+    callback.uri   = atoi(argv[1]); /* FIXME: Use strtol. */
+    callback.value = atoi(argv[4]); /* FIXME: Use strtol. */
+    callback.name  = argv[2];
     switch (argv[3][0]) {
     case '=':
-        return database_sticker_list(srv->db, argv[0], &args, sticker_check_is_present_eq);
+        callback.call = sticker_check_is_present_eq;
+        return database_sticker_list(srv->db, argv[0], &callback);
     case '<':
-        return database_sticker_list(srv->db, argv[0], &args, sticker_check_is_present_lt);
+        callback.call = sticker_check_is_present_lt;
+        return database_sticker_list(srv->db, argv[0], &callback);
     case '>':
-        return database_sticker_list(srv->db, argv[0], &args, sticker_check_is_present_gt);
+        callback.call = sticker_check_is_present_gt;
+        return database_sticker_list(srv->db, argv[0], &callback);
     default:
         return 0;
     }
@@ -1246,5 +1218,6 @@ command_sticker_delete(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_A
 
     (void) c;
     int uri = atoi(argv[1]);
+    srv->mpd_idle_events |= MPD_IDLE_STICKER;
     return database_sticker_delete_specify(srv->db, argv[0], uri, argv[2]);
 }
diff --git a/src/database/find.c b/src/database/find.c
index f9c8a62d20e01b826b0a36f23dc5b21e2c8fa043..a0366d65482adc127bb0aa9af4d627205cb6be22 100644
--- a/src/database/find.c
+++ b/src/database/find.c
@@ -8,7 +8,7 @@
 #include <string.h>
 
 bool
-database_search_init(sqlite3 *db, char *col_name, char *rgx, sqlite3_stmt **ret)
+database_search_queue_init(sqlite3 *db, char *col_name, char *rgx, struct lkt_search *ret)
 {
     if (ret == NULL) {
         fprintf(stderr, " ! database_search_init: Exit because return pointer is NULL\n");
@@ -20,32 +20,29 @@ database_search_init(sqlite3 *db, char *col_name, char *rgx, sqlite3_stmt **ret)
         " SELECT kara.id AS id, string AS any_col, LENGTH(CAST(kara.id AS TEXT)) AS len"
         " FROM kara WHERE %s LIKE ?)"
         "SELECT id, any_col, (SELECT MAX(len) FROM content)"
-        "FROM content;";
+        "FROM content LIMIT %d OFFSET %d;";
     char SQL_STMT[LKT_MAX_SQLITE_STATEMENT];
 
-    snprintf(SQL_STMT, LKT_MAX_SQLITE_STATEMENT - 1, SQL_STMT_TEMPLATE, col_name);
+    snprintf(SQL_STMT, LKT_MAX_SQLITE_STATEMENT - 1, SQL_STMT_TEMPLATE, col_name,
+             ret->msg_count, ret->continuation);
     SQL_STMT[LKT_MAX_SQLITE_STATEMENT - 1] = 0;
-    SQLITE_PREPARE(db, *ret, SQL_STMT, error);
-    SQLITE_BIND_TEXT(db, *ret, 1, rgx, error);
+    SQLITE_PREPARE(db, ret->stmt, SQL_STMT, error);
+    SQLITE_BIND_TEXT(db, ret->stmt, 1, rgx, error);
+    ret->db = db;
+    /* Assign the callback. */
     return true;
 error:
-    sqlite3_finalize(*ret);
-    *ret = NULL;
+    sqlite3_finalize(ret->stmt);
     return false;
 }
 
 bool
-database_search_iter(sqlite3 *db,
-                     sqlite3_stmt *item,
-                     void *args,
-                     database_search_callback_t callback,
-                     bool *need_free)
+database_search_iter(struct lkt_search *item)
 {
     const char *sql_row;
     int id, code, id_len;
 
-    *need_free = true;
-    code = sqlite3_step(item);
+    code = sqlite3_step(item->stmt);
 
     if (item == NULL) {
         fprintf(stderr, " * database_search_iter: Exit function because the sqlite3_stmt* is NULL\n");
@@ -55,16 +52,24 @@ database_search_iter(sqlite3 *db,
     if (code == SQLITE_DONE)
         goto error_or_done;
 
-    if (code == SQLITE_ROW) {
-        id = sqlite3_column_int(item, 0);
-        sql_row = (const char *) sqlite3_column_text(item, 1);
-        id_len = sqlite3_column_int(item, 2);
-        return callback(args, id, id_len, sql_row);
+    if (code != SQLITE_ROW)
+        goto error;
+
+    switch (item->type) {
+    case lkt_search_database:
+        id = sqlite3_column_int(item->stmt, 0);
+        sql_row = (const char *) sqlite3_column_text(item->stmt, 1);
+        id_len = sqlite3_column_int(item->stmt, 2);
+        return ((lkt_search_database_func) item->call)(item->srv, item->c, id, id_len, sql_row);
+    case lkt_search_queue:
+    case lkt_search_playlist:
+    default:
+        goto error;
     }
 
-    fprintf(stderr, " ! database_search_iter: sqlite3_step failed: %s\n", sqlite3_errmsg(db));
+error:
+    fprintf(stderr, " ! database_search_iter: sqlite3_step failed: %s\n", sqlite3_errmsg(item->db));
 error_or_done:
-    sqlite3_finalize(item);
-    *need_free = false;
+    sqlite3_finalize(item->stmt);
     return false;
 }
diff --git a/src/database/queue.c b/src/database/queue.c
index 1ec0e4292ae8c8821db2cfc6cddfdbd6335fbf54..2b54a4d4e238300db2422b1b5fd42de49b87a11e 100644
--- a/src/database/queue.c
+++ b/src/database/queue.c
@@ -79,7 +79,7 @@ database_queue_current_kara(sqlite3 *db, struct kara_metadata *res, int *id)
         res->song_number = sqlite3_column_int(stmt, 6);
 no_metadata:
         /* Most of the time this will be NULL. */
-        if (id)
+        if (id && sqlite3_column_type(stmt, 7) != SQLITE_NULL)
             *id = sqlite3_column_int(stmt, 7);
     } else {
         fprintf(stderr, " ! database_queue_current_kara: failed: %s\n",
@@ -673,8 +673,7 @@ error:
 }
 
 bool
-database_queue_list_abs(sqlite3 *db, unsigned int from, unsigned int to, void *args,
-                        database_search_callback_t callback)
+database_queue_list(sqlite3 *db, size_t from, size_t to, struct lkt_callback *callback)
 {
     const char *SQL_STMT =
         "WITH content AS ("
@@ -691,61 +690,8 @@ database_queue_list_abs(sqlite3 *db, unsigned int from, unsigned int to, void *a
     sqlite3_stmt *stmt;
 
     SQLITE_PREPARE(db, stmt, SQL_STMT, error);
-    SQLITE_BIND_INT(db, stmt, 1, from, error);
-    SQLITE_BIND_INT(db, stmt, 2, to, error);
-
-    for (;;) {
-        code = sqlite3_step(stmt);
-
-
-        if (code == SQLITE_ROW) {
-            id = sqlite3_column_int(stmt, 0);
-            row = (const char *) sqlite3_column_text(stmt, 1);
-            id_len = sqlite3_column_int(stmt, 2);
-            if (callback(args, id, id_len, row))
-                continue;
-            else
-                break;
-        }
-
-        else if (code == SQLITE_OK || code == SQLITE_DONE)
-            goto done;
-
-        else
-            break;
-    }
-
-done:
-    ret = true;
-error:
-    sqlite3_finalize(stmt);
-    return ret;
-}
-
-bool
-database_queue_list_from(sqlite3 *db, unsigned int count, void *args,
-                         database_search_callback_t callback)
-{
-    const char *SQL_TEMPLATE =
-        "WITH content AS ("
-        " SELECT kara.id AS id, string, LENGTH(CAST(kara.id AS TEXT)) AS len"
-        "  FROM queue_"
-        "  JOIN queue_state ON queue_.position >= CASE"
-        "    WHEN queue_state.current IS NULL THEN 1"
-        "    ELSE queue_state.current END"
-        "  JOIN kara ON kara_id = kara.id"
-        "  GROUP BY position ORDER BY position LIMIT %d)"
-        "SELECT id, string, (SELECT MAX(len) FROM content)"
-        " FROM content;";
-    static const int stmt_len = 512;
-    char SQL_STMT[stmt_len];
-    int code, id, id_len;
-    const char *row;
-    bool ret = false;
-    sqlite3_stmt *stmt;
-
-    snprintf(SQL_STMT, stmt_len, SQL_TEMPLATE, count);
-    SQLITE_PREPARE(db, stmt, SQL_STMT, error);
+    SQLITE_BIND_INT(db, stmt, 1, (int) from, error);
+    SQLITE_BIND_INT(db, stmt, 2, (int) to, error);
 
     for (;;) {
         code = sqlite3_step(stmt);
@@ -755,7 +701,8 @@ database_queue_list_from(sqlite3 *db, unsigned int count, void *args,
             id = sqlite3_column_int(stmt, 0);
             row = (const char *) sqlite3_column_text(stmt, 1);
             id_len = sqlite3_column_int(stmt, 2);
-            if (callback(args, id, id_len, row))
+            ++(callback->iterations);
+            if (callback->call(callback, id, id_len, row))
                 continue;
             else
                 break;
diff --git a/src/database/stickers.c b/src/database/stickers.c
index afeb6209b62dd438d7a9cc57e8e1cae23e7fc5b4..1fd2b2375190587c35883a955087f3453a855313 100644
--- a/src/database/stickers.c
+++ b/src/database/stickers.c
@@ -71,8 +71,7 @@ error:
 }
 
 bool
-database_sticker_list(sqlite3 *db, const char *type, void *args,
-                      database_sticker_callback_t call)
+database_sticker_list(sqlite3 *db, const char *type, struct sticker_callback *call)
 {
     const char *SQL = NULL;
     int ret = false, uri, value;
@@ -112,7 +111,7 @@ database_sticker_list(sqlite3 *db, const char *type, void *args,
             sticker = (const char *) sqlite3_column_text(stmt, 0);
             uri     = sqlite3_column_int(stmt, 1);
             value   = sqlite3_column_int(stmt, 2);
-            if (!call(args, sticker, type, uri, value))
+            if (!call->call(call, sticker, type, uri, value))
                 goto end_loop;
             continue;
 
@@ -179,8 +178,7 @@ error:
 }
 
 bool
-database_sticker_get(sqlite3 *db, const char *type, const char *name, int uri, void *args,
-                     database_sticker_callback_t call)
+database_sticker_get(sqlite3 *db, const char *type, const char *name, int uri, struct sticker_callback *call)
 {
     const char *SQL = NULL;
     sqlite3_stmt *stmt;
@@ -212,7 +210,7 @@ database_sticker_get(sqlite3 *db, const char *type, const char *name, int uri, v
         switch (sqlite3_step(stmt)) {
         case SQLITE_ROW:
             value = sqlite3_column_int(stmt, 1);
-            if (!call(args, name, type, uri, value))
+            if (!call->call(call, name, type, uri, value))
                 goto end_loop;
             continue;
 
diff --git a/src/main/lkt.c b/src/main/lkt.c
index d28fb1a93bfa1d9447b2cc41cf08b1a1b780c16d..ca1875c915f442f750855d5ac1e85c22cb613598 100644
--- a/src/main/lkt.c
+++ b/src/main/lkt.c
@@ -1,5 +1,6 @@
 #define _POSIX_C_SOURCE 200809L
 
+#include <lektor/defines.h>
 #include <lektor/net.h>
 #include <lektor/cmd.h>
 #include <arpa/inet.h>
@@ -36,38 +37,49 @@ help(void)
         "USAGE: lkt [OPTIONS] <COMMAND> [ARGS [...]]\n"
         "\n"
         "  OPTIONS:\n"
-        "    host:        named of the lektor's host, can be resolved.\n"
-        "    port:        port on which lektor is listening.\n"
+        "    host         named of the lektor's host, can be resolved.\n"
+        "    port         port on which lektor is listening.\n"
         "\n"
         "    options most be passed as one word (no spaced), such as the following:\n"
         "    % lkt host=sakura port=6601 play\n"
         "\n"
         "  COMMANDS:\n"
-        "    help:          display this help message\n"
-        "    play <?idx>:   toggle play/pause state of lektor, may start at a certain index,\n"
-        "    status:        get the status of lektor.\n"
-        "    current:       get the currently playing song.\n"
-        "    add <query>:   add a kara to the playlist with a query.\n"
-        "    delete <id>:   delete the id from the queue.\n"
-        "    clear:         clear the queue of lektor.\n"
-        "    prev:          play previous kara in the queue.\n"
-        "    next:          play the next kara in the queue.\n"
-        "    shuffle:       shuffle lektor's playlist and play it from the begening.\n"
-        "    queue <?arg>:  prints the queue. The argument is either a range or a count from the current kara.\n"
-        "    plt:           the playlist sub command.\n"
+        "    help           display this help message.\n"
+        "    play <?idx>    toggle play/pause state of lektor, may start at a certain index.\n"
+        "    stop           stop the playback but not the window if it exists.\n"
+        "    status         get the status of lektor.\n"
+        "    current        get the currently playing song.\n"
+        "    add <query>    add a kara to the playlist with a query.\n"
+        "    delete <id>    delete the id from the queue.\n"
+        "    clear          clear the queue of lektor.\n"
+        "    prev           play previous kara in the queue.\n"
+        "    next           play the next kara in the queue.\n"
+        "    shuffle        shuffle lektor's playlist and play it from the begening.\n"
+        "    queue <?arg>   prints the queue. The argument is either a range or a count from the current kara.\n"
+        "    plt            the playlist sub command.\n"
+        "    search         the search sub command.\n"
         "\n"
         "  PLAYLIST COMMANDS:\n"
-        "    help:                      display this help message\n"
-        "    create <plt>:              creates a playlist after the argument.\n"
-        "    destroy <plt>:             delete a playlist after the argument.\n"
-        "    add <plt> <type> <query>:  add something to a playlist from the database.\n"
-        "    delete: <plt> <id>:        delete domething from a playlist.\n"
+        "    help                       display this help message.\n"
+        "    create <plt>               creates a playlist after the argument.\n"
+        "    destroy <plt>              delete a playlist after the argument.\n"
+        "    add <plt> <type> <query>   add something to a playlist from the database.\n"
+        "    delete <plt> <id>          delete domething from a playlist.\n"
+        "\n"
+        "  SEARCH COMMANDS:\n"
+        "    help                   display this help message.\n"
+        "    get <query>            prints the results of the query.\n"
+        "    add <query>            add to the queue and prints the results of the query.\n"
+        "    insert <query>         insert on top of the aueue and prints the results of the query.\n"
+        "    plt <plt> <query>      search inside a playlist and prints the results.\n"
+        "    count <query>          count the number of songs that matches the query.\n"
+        "    queue <query>          prints kara that matches from the queue.\n"
         "\n"
         "  QUERY:\n"
         "    A query is passed in argument of a COMMAND and is composed of:\n"
         "     - The first word must be the type\n"
         "     - the rest is used for the sqlite regex\n"
-        "    Supported types are: title, [a]ny, source, [auth]or, [lang]uage, type.\n"
+        "    Supported types are: title, [a]ny, source, [auth]or, [lang]uage, type, title\n"
         "\n"
         "  RANGE:\n"
         "    A range is specified like in python:\n"
@@ -145,7 +157,7 @@ end:
     return i;
 }
 
-static int
+static inline int
 write_socket(FILE *sock, const char *buff, size_t len)
 {
     int ret = 1;
@@ -213,11 +225,11 @@ create_socket(const char *host, const char *port)
 static FILE *
 lkt_connect(void)
 {
-    char buff[1024];
-    size_t buff_len = 1024, recv_len;
+    char buff[LKT_MESSAGE_MAX];
+    size_t recv_len;
 
     FILE *sock = create_socket(host, port);
-    recv_len = read_socket(sock, buff, buff_len);
+    recv_len = read_socket(sock, buff, LKT_MESSAGE_MAX);
 
     assert(recv_len > 0);
 
@@ -246,8 +258,8 @@ clear__(struct lkt_cmd_args *args)
 {
     if (args->argc != 0)
         fail("Invalid argument, the clear command takes no arguments");
-    static const char *const cmd__ = "clear\nclose\n";
-    lkt_send_and_exit(cmd__, strlen(cmd__));
+    static const char cmd__[] = "clear\nclose\n";
+    lkt_send_and_exit(cmd__, sizeof(cmd__));
 }
 
 
@@ -256,8 +268,8 @@ next__(struct lkt_cmd_args *args)
 {
     if (args->argc != 0)
         fail("Invalid argument, the next command takes no arguments");
-    static const char *const cmd__ = "next\nclose\n";
-    lkt_send_and_exit(cmd__, strlen(cmd__));
+    static const char cmd__[] = "next\nclose\n";
+    lkt_send_and_exit(cmd__, sizeof(cmd__));    /* In bytes. */
 }
 
 noreturn void
@@ -265,8 +277,17 @@ prev__(struct lkt_cmd_args *args)
 {
     if (args->argc != 0)
         fail("Invalid argument, the previous command takes no arguments");
-    static const char *const cmd__ = "previous\nclose\n";
-    lkt_send_and_exit(cmd__, strlen(cmd__));
+    static const char cmd__[] = "previous\nclose\n";
+    lkt_send_and_exit(cmd__, sizeof(cmd__));    /* In bytes. */
+}
+
+noreturn void
+stop__(struct lkt_cmd_args *args)
+{
+    if (args->argc != 0)
+        fail("Invalid argument, the stop command takes no arguments");
+    static const char cmd__[] = "stop\nclose\n";
+    lkt_send_and_exit(cmd__, sizeof(cmd__));    /* In bytes. */
 }
 
 noreturn void
@@ -279,22 +300,21 @@ play__(struct lkt_cmd_args *args)
     if (args->argc != 0)
         pos = atoi(args->argv[0]);
 
-    static const char *const status__        = "status\n";
-    static const char *const cmd_play__      = "play\nclose\n";
-    static const char *const cmd_play_from__ = "play %d\nclose\n";
-    static const char *const cmd_pause__     = "pause\nclose\n";
+    static const char status__[]        = "status\n";
+    static const char cmd_play__[]      = "play\nclose\n";
+    static const char cmd_play_from__[] = "play %d\nclose\n";
+    static const char cmd_pause__[]     = "pause\nclose\n";
 
-    const size_t buff_len = 1024;
-    char buff[buff_len];
+    char buff[LKT_MESSAGE_MAX];
 
     FILE *sock = lkt_connect();
 
-    if (write_socket(sock, status__, strlen(status__)))
+    if (write_socket(sock, status__, sizeof(status__))) /* In bytes. */
         goto error;
 
     for (;;) {
-        memset(buff, 0, buff_len * sizeof(char));
-        if (read_socket(sock, buff, buff_len - 1) <= 0)
+        memset(buff, 0, LKT_MESSAGE_MAX * sizeof(char));
+        if (read_socket(sock, buff, LKT_MESSAGE_MAX - 1) <= 0)
             exit(EXIT_FAILURE);
 
         size_t len = strcspn(buff, LKT_KEY_VALUE_SEP);
@@ -304,13 +324,13 @@ play__(struct lkt_cmd_args *args)
 
             if (STR_NMATCH(lkt_skip_key(buff), "stop", 4)) {
                 if (!pos)
-                    lkt_send_and_exit(cmd_play__, strlen(cmd_play__));
+                    lkt_send_and_exit(cmd_play__, sizeof(cmd_play__));  /* In bytes. */
                 else
                     exit(write_socket_format(lkt_connect(), cmd_play_from__, pos));
             }
 
             else
-                lkt_send_and_exit(cmd_pause__, strlen(cmd_pause__));
+                lkt_send_and_exit(cmd_pause__, sizeof(cmd_pause__));    /* In bytes. */
 
             goto error;
         }
@@ -326,30 +346,28 @@ current__(struct lkt_cmd_args *args)
     if (args->argc != 0)
         fail("Invalid argument, the current command takes no arguments");
 
-    static const char *const current_song__ = "currentsong\n";
-    const size_t buff_len = 1024;
-    char buff[buff_len];
+    static const char current_song__[] = "currentsong\n";
+    char buff[LKT_MESSAGE_MAX];
 
     char *mem = NULL;
     FILE *sock = lkt_connect();
 
-    if (write_socket(sock, current_song__, strlen(current_song__)))
+    if (write_socket(sock, current_song__, sizeof(current_song__))) /* In bytes. */
         goto error;
 
-    assert(mem = calloc(6 * buff_len, sizeof(char)));
-    assert(memset(mem, 0, 6 * buff_len * sizeof(char)));
+    assert(mem = calloc(6 * LKT_MESSAGE_MAX, sizeof(char)));
+    assert(memset(mem, 0, 6 * LKT_MESSAGE_MAX * sizeof(char)));
 
     char *const title    = &mem[0];
-    char *const author   = &mem[buff_len];
-    char *const source   = &mem[2 * buff_len];
-    char *const type     = &mem[3 * buff_len];
-    char *const category = &mem[4 * buff_len];
-    char *const language = &mem[5 * buff_len];
-
+    char *const author   = &mem[LKT_MESSAGE_MAX];
+    char *const source   = &mem[2 * LKT_MESSAGE_MAX];
+    char *const type     = &mem[3 * LKT_MESSAGE_MAX];
+    char *const category = &mem[4 * LKT_MESSAGE_MAX];
+    char *const language = &mem[5 * LKT_MESSAGE_MAX];
 
     for (;;) {
-        memset(buff, 0, buff_len * sizeof(char));
-        if (read_socket(sock, buff, buff_len - 1) <= 0)
+        memset(buff, 0, LKT_MESSAGE_MAX * sizeof(char));
+        if (read_socket(sock, buff, LKT_MESSAGE_MAX - 1) <= 0)
             goto error;
 
         const size_t len = strcspn(buff, LKT_KEY_VALUE_SEP);
@@ -403,8 +421,7 @@ status__(struct lkt_cmd_args *args)
     static const char *const status_str__ = "status\n";
     int ret = EXIT_FAILURE, it = 0;
 
-    const size_t buff_len = 1024;
-    char buff[buff_len];
+    char buff[LKT_MESSAGE_MAX];
     char flags[24];
 
     bool play = false, stopped = true;
@@ -422,8 +439,8 @@ status__(struct lkt_cmd_args *args)
 #define assign_int(str, var) if (! strncmp(buff, str, len)) { var = (atoi(lkt_skip_key(buff))); continue; }
 
     for (;;) {
-        memset(buff, 0, buff_len * sizeof(char));
-        if (read_socket(sock, buff, buff_len - 1) <= 0)
+        memset(buff, 0, LKT_MESSAGE_MAX * sizeof(char));
+        if (read_socket(sock, buff, LKT_MESSAGE_MAX - 1) <= 0)
             goto error;
 
         size_t len = strcspn(buff, LKT_KEY_VALUE_SEP);
@@ -511,8 +528,7 @@ check:
 noreturn void
 add__(struct lkt_cmd_args *args)
 {
-    const size_t buff_len = 1025;
-    char buff[buff_len];
+    char buff[LKT_MESSAGE_MAX];
     int i;
 
     if (args->argc < 1)
@@ -537,8 +553,8 @@ add__(struct lkt_cmd_args *args)
     write_socket(sock, "\n", sizeof(char));
 
     for (;;) {
-        memset(buff, 0, buff_len * sizeof(char));
-        assert(read_socket(sock, buff, buff_len - 1) > 0);
+        memset(buff, 0, LKT_MESSAGE_MAX * sizeof(char));
+        assert(read_socket(sock, buff, LKT_MESSAGE_MAX - 1) > 0);
 
         if (! strncmp(buff, "OK", 2))
             exit(EXIT_SUCCESS);
@@ -551,8 +567,7 @@ add__(struct lkt_cmd_args *args)
 noreturn void
 list__(struct lkt_cmd_args *args)
 {
-    const size_t buff_len = 1025;
-    char buff[buff_len];
+    char buff[LKT_MESSAGE_MAX], *endptr;
 
     if (args->argc == 0)
         args->argv = LKT_QUEUE_DEFAULT;
@@ -560,15 +575,40 @@ list__(struct lkt_cmd_args *args)
     else if (args->argc > 1)
         fail("Invalid argument for the queue command");
 
-    FILE *sock = lkt_connect();
+    long continuation = 0, up = 0;
 
-    write_socket(sock, "playlist ", strlen("playlist "));
-    write_socket(sock, args->argv[0], strlen(args->argv[0]));
-    write_socket(sock, "\n", sizeof(char));
+    continuation = strtol(args->argv[0], &endptr, 0);
+    if ((errno == ERANGE && (continuation == LONG_MAX || continuation == LONG_MIN)) || (errno != 0
+            && continuation == 0) || (endptr == args->argv[0]))
+        fail("Invalid argument, not an integer");
+
+    if (*endptr != '\0') {
+        /* A range */
+        if (*(++endptr) == '\0')
+            fail("Invalid argument, a range is two integers");
+        up = atoi(endptr);
+    }
+
+
+    FILE *sock = NULL;
+redo:
+    sock = lkt_connect();
+    if (up != 0)
+        write_socket_format(sock, "playlist %d:%d\n", continuation, up);
+    else
+        write_socket_format(sock, "playlist %d\n", continuation);
 
     for (;;) {
-        memset(buff, 0, buff_len * sizeof(char));
-        assert(read_socket(sock, buff, buff_len - 1) > 0);
+        memset(buff, 0, LKT_MESSAGE_MAX * sizeof(char));
+        assert(read_socket(sock, buff, LKT_MESSAGE_MAX - 1) > 0);
+
+        if (! strncmp(buff, "continue:", strlen("continue:"))) {
+            continuation = atoi(lkt_skip_key(buff));
+            if (continuation > 0) {
+                fclose(sock);
+                goto redo;
+            }
+        }
 
         if (! strncmp(buff, "OK", 2))
             exit(EXIT_SUCCESS);
@@ -639,7 +679,6 @@ plt_delete__(struct lkt_cmd_args *args)
     write_socket(sock, args->argv[i], strlen(args->argv[i]));
     write_socket(sock, "\n", sizeof(char));
 
-
     assert(read_socket(sock, buff, 2) > 0);
     if (buff[0] == 'O' && buff[1] == 'K')
         exit(EXIT_SUCCESS);
@@ -689,17 +728,115 @@ plt_create__(struct lkt_cmd_args *args)
         exit(EXIT_FAILURE);
 }
 
+/* Search functions. */
+
+noreturn void
+search_with_cmd__(struct lkt_cmd_args *args, const char *cmd)
+{
+    if (args->argc < 2)
+        fail("Invalid number of arguments, need at least a valid query");
+
+    if (!lkt_valid_type(args->argv[0]))
+        fail("Invalid type for the query");
+
+    char buff[LKT_MESSAGE_MAX];
+    int continuation = 0, i;
+    FILE *sock = NULL;
+redo:
+    sock = lkt_connect();
+
+    write_socket_format(sock, "%d %s", continuation, cmd);
+    for (i = 0; i < args->argc; ++i)
+        write_socket_format(sock, " %s", args->argv[i]);
+    write_socket(sock, "\n", sizeof("\n") / sizeof(char));
+
+    for (;;) {
+        memset(buff, 0, LKT_MESSAGE_MAX * sizeof(char));
+        assert(read_socket(sock, buff, LKT_MESSAGE_MAX - 1) > 0);
+
+        if (! strncmp(buff, "continue:", strlen("continue:"))) {
+            continuation = atoi(lkt_skip_key(buff));
+            fclose(sock);
+            goto redo;
+        }
+
+        if (! strncmp(buff, "OK", 2))
+            exit(EXIT_SUCCESS);
+        else if (! strncmp(buff, "ACK", 3))
+            exit(EXIT_FAILURE);
+
+        fprintf(stdout, "%s", buff);
+    }
+}
+
+noreturn void
+search_get__(struct lkt_cmd_args *args)
+{
+    search_with_cmd__(args, "search");
+}
+
+noreturn void
+search_add__(struct lkt_cmd_args *args)
+{
+    search_with_cmd__(args, "searchadd");
+}
+
+noreturn void
+search_insert__(struct lkt_cmd_args *args)
+{
+    (void) args;
+    fail("Not implemented");
+}
+
+noreturn void
+search_plt__(struct lkt_cmd_args *args)
+{
+    search_with_cmd__(args, "listplaylist");
+}
+
+noreturn void
+search_count__(struct lkt_cmd_args *args)
+{
+    search_with_cmd__(args, "count");
+}
+
+noreturn void
+search_queue__(struct lkt_cmd_args *args)
+{
+    search_with_cmd__(args, "playlistinfo");
+}
+
 /* Parsing stuff. */
 
 static struct lkt_cmd_opt options_plt[] = {
-    { .name = "help",       .call = help__        },
-    { .name = "add",        .call = plt_add__     },
-    { .name = "delete",     .call = plt_delete__  },
-    { .name = "destroy",    .call = plt_destroy__ },
-    { .name = "create",     .call = plt_create__  },
+    { .name = "help",       .call = help__          },
+    { .name = "add",        .call = plt_add__       },
+    { .name = "delete",     .call = plt_delete__    },
+    { .name = "destroy",    .call = plt_destroy__   },
+    { .name = "create",     .call = plt_create__    },
     LKT_OPT_NULL,
 };
 
+static struct lkt_cmd_opt options_search[] = {
+    { .name = "help",       .call = help__          },
+    { .name = "get",        .call = search_get__    },
+    { .name = "add",        .call = search_add__    },
+    { .name = "insert",     .call = search_insert__ },
+    { .name = "plt",        .call = search_plt__    },
+    { .name = "count",      .call = search_count__  },
+    { .name = "queue",      .call = search_queue__  },
+    LKT_OPT_NULL,
+};
+
+noreturn void
+search__(struct lkt_cmd_args *args)
+{
+    if (args->argc == 0)
+        fail("Invalid argument, you must specify a sub command for the search command");
+
+    lkt_cmd_parse(options_search, args->argc, args->argv, help);
+}
+
 noreturn void
 plt__(struct lkt_cmd_args *args)
 {
@@ -721,7 +858,9 @@ static struct lkt_cmd_opt options_[] = {
     { .name = "add",        .call = add__     },
     { .name = "shuffle",    .call = shuffle__ },
     { .name = "status",     .call = status__  },
+    { .name = "stop",       .call = stop__    },
     { .name = "plt",        .call = plt__     },
+    { .name = "search",     .call = search__  },
     LKT_OPT_NULL,
 };
 
diff --git a/src/net/command.c b/src/net/command.c
index b41d44194965b6409232df722eef73485342df5e..33df59b7ea8856018480657dc5c2f7e42ab93932 100644
--- a/src/net/command.c
+++ b/src/net/command.c
@@ -4,12 +4,39 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <errno.h>
+#include <limits.h>
 
 struct lkt_command
 lkt_command_parse(char *raw)
 {
-    struct lkt_command res = { .name = raw, .args = {0} };
+    errno = 0;
+    char *endptr;
+    struct lkt_command res = { .name = raw, .args = {0}, .cont = strtol(raw, &endptr, 10) };
 
+    if ((errno == ERANGE && (res.cont == LONG_MAX || res.cont == LONG_MIN)) || (errno != 0)) {
+        res.cont = 0;
+        goto skip_cont;
+    }
+
+    if (endptr == raw) {
+        res.cont = 0;
+        goto skip_cont;
+    }
+
+    if (*endptr == '\0') {
+        /* That thing is an error. */
+        return res;
+    }
+
+    /* Get the real command name. */
+    raw += strspn(raw, " 1234567890");
+    if (!*raw)
+        return res;
+    res.name = raw;
+
+    /* Get the args. */
+skip_cont:
     raw += strcspn(raw, " ");
     if (!*raw)
         return res;
diff --git a/src/net/listen.c b/src/net/listen.c
index 58b2743261ccb31c37f0f414f2e9868858abd834..3ec2fdf1e321ecd212cfec5c20a9827065e1be4f 100644
--- a/src/net/listen.c
+++ b/src/net/listen.c
@@ -54,13 +54,31 @@ struct lkt_client {
     bool request_close;
 
     bool authentificated;
+    int continuation;
 };
 
-static bool
+static inline bool
 lkt_close_client(struct lkt_state *srv, size_t c)
 {
-    srv->clients[c - 1].request_close = true;
-    return true;
+    return srv->clients[c - 1].request_close = true;
+}
+
+inline int
+lkt_get_continuation(struct lkt_state *srv, size_t c)
+{
+    return srv->clients[c - 1].continuation;
+}
+
+inline void
+lkt_set_continuation(struct lkt_state *srv, size_t c, int i)
+{
+    srv->clients[c - 1].continuation = i;
+}
+
+inline size_t
+lkt_remaining_msg(struct lkt_state *srv, size_t c)
+{
+    return BUFFER_OUT_MAX - srv->clients[c - 1].buffer_out_len;
 }
 
 void
@@ -77,6 +95,15 @@ lkt_state_send(struct lkt_state *srv, size_t c, struct lkt_message *msg)
     srv->fds[c].events |= POLLOUT;
 }
 
+static inline void
+send_continue(struct lkt_state *srv, size_t c, int i)
+{
+    struct lkt_message *cont = lkt_message_new();
+    cont->data_len = snprintf(cont->data, LKT_MESSAGE_MAX, "continue: %d\n", i);
+    cont->data[LKT_MESSAGE_MAX - 1] = '\0';
+    lkt_state_send(srv, c, cont);
+}
+
 static void
 send_ok(struct lkt_state *srv, size_t c)
 {
@@ -133,11 +160,12 @@ command_list_begin(struct lkt_state *srv, size_t c, int list_ok)
 static int
 handle_simple_command(struct lkt_state *srv, size_t c, struct lkt_command cmd)
 {
-    int err;
+    int err, continuation = 0;
 
     switch (*lkt_client_get_mask(srv, c)) {
     case MPD_IDLE_NONE:
-        /* Commands that require authentification. */
+        /* Commands that require authentification.
+           TODO: Move authentification verification inside commands. */
         if (lkt_client_auth(srv, c, false)) {
             if (!strcmp(cmd.name, "__adduser")) {
                 err = !command_user_add(srv->db, cmd.args);
@@ -246,10 +274,10 @@ handle_simple_command(struct lkt_state *srv, size_t c, struct lkt_command cmd)
             goto end_no_send_status;
         } else if (!strcmp(cmd.name, "searchadd") ||
                    !strcmp(cmd.name, "findadd"))
-            err = !command_find(srv, c, cmd.args, LKT_FND_ACT_ENQUEUE);
+            err = !command_find(srv, c, cmd.args, cmd.cont, LKT_FND_ACT_RESPOND);
         else if (!strcmp(cmd.name, "search") ||
                  !strcmp(cmd.name, "find"))
-            err = !command_find(srv, c, cmd.args, LKT_FND_ACT_RESPOND);
+            err = !command_find(srv, c, cmd.args, cmd.cont, LKT_FND_ACT_RESPOND);
         else
             err = 2;
 
@@ -268,6 +296,11 @@ handle_simple_command(struct lkt_state *srv, size_t c, struct lkt_command cmd)
         break;
     }
 
+    continuation = lkt_get_continuation(srv, c);
+    if (continuation > 0) {
+        fprintf(stderr, " * Client should continue from %d\n", continuation);
+        send_continue(srv, c, continuation);
+    }
     send_status(srv, c, err, cmd.name);
 end_no_send_status:
     return err;
@@ -321,10 +354,13 @@ static int
 handle_incoming_data(struct lkt_state *srv, size_t i)
 {
     struct lkt_client *cli = &srv->clients[i - 1];
+    int n;
 
     for (;;) {
-        int n = recv(srv->fds[i].fd, cli->buffer_in + cli->buffer_in_len,
-                     LKT_MESSAGE_MAX - cli->buffer_in_len, 0);
+        /* Recieve some data. */
+recv:
+        n = recv(srv->fds[i].fd, cli->buffer_in + cli->buffer_in_len,
+                 LKT_MESSAGE_MAX - cli->buffer_in_len, 0);
         if (n < 0) {
             if (errno == EWOULDBLOCK || errno == EAGAIN)
                 return 0;
@@ -334,11 +370,12 @@ handle_incoming_data(struct lkt_state *srv, size_t i)
             return -1;
         cli->buffer_in_len += n;
 
+        /* Handle the data. */
         char *buf = cli->buffer_in;
         for (;;) {
             size_t line_len = strcspn(buf, "\n");
             if (line_len >= cli->buffer_in_len)
-                break;
+                goto recv;
             buf[line_len] = 0;
 
             struct lkt_command cmd = lkt_command_parse(buf);
@@ -349,7 +386,7 @@ handle_incoming_data(struct lkt_state *srv, size_t i)
         }
 
         if (cli->buffer_in < buf)
-            memcpy(cli->buffer_in, buf, cli->buffer_in_len);
+            memmove(cli->buffer_in, buf, cli->buffer_in_len);
         else if (cli->buffer_in_len == LKT_MESSAGE_MAX)
             return -1;
     }