plugin: convert plugin_fd_add() to method
[ncmpc-debian.git] / src / SearchPage.cxx
index 388999d..e8d0367 100644 (file)
@@ -1,5 +1,5 @@
 /* ncmpc (Ncurses MPD Client)
- * (c) 2004-2018 The Music Player Daemon Project
+ * (c) 2004-2019 The Music Player Daemon Project
  * Project homepage: http://musicpd.org
  *
  * This program is free software; you can redistribute it and/or modify
  */
 
 #include "SearchPage.hxx"
-#include "screen_interface.hxx"
+#include "PageMeta.hxx"
 #include "screen_status.hxx"
 #include "TextListRenderer.hxx"
 #include "i18n.h"
-#include "options.hxx"
+#include "Options.hxx"
 #include "Bindings.hxx"
 #include "GlobalBindings.hxx"
 #include "charset.hxx"
 #include "mpdclient.hxx"
-#include "strfsong.hxx"
 #include "screen_utils.hxx"
 #include "FileListPage.hxx"
 #include "filelist.hxx"
 #include "util/Macros.hxx"
 
-#include <glib.h>
-
 #include <string.h>
 
 enum {
@@ -42,7 +39,7 @@ enum {
        SEARCH_ARTIST_TITLE
 };
 
-static const struct {
+static constexpr struct {
        enum mpd_tag_type tag_type;
        const char *name;
        const char *localname;
@@ -63,7 +60,7 @@ static const struct {
 static int
 search_get_tag_id(const char *name)
 {
-       if (g_ascii_strcasecmp(name, "file") == 0 ||
+       if (strcasecmp(name, "file") == 0 ||
            strcasecmp(name, _("file")) == 0)
                return SEARCH_URI;
 
@@ -80,7 +77,7 @@ typedef struct {
        const char *label;
 } search_type_t;
 
-static search_type_t mode[] = {
+static constexpr search_type_t mode[] = {
        { MPD_TAG_TITLE, N_("Title") },
        { MPD_TAG_ARTIST, N_("Artist") },
        { MPD_TAG_ALBUM, N_("Album") },
@@ -90,6 +87,9 @@ static search_type_t mode[] = {
 };
 
 static const char *const help_text[] = {
+       "",
+       "",
+       "",
        "Quick     -  Enter a string and ncmpc will search according",
        "             to the current search mode (displayed above).",
        "",
@@ -113,8 +113,8 @@ public:
                              !options.search_format.empty()
                              ? options.search_format.c_str()
                              : options.list_format.c_str()) {
+               lw.DisableCursor();
                lw.SetLength(ARRAY_SIZE(help_text));
-               lw.hide_cursor = true;
        }
 
 private:
@@ -124,20 +124,37 @@ private:
 
 public:
        /* virtual methods from class Page */
-       void OnOpen(struct mpdclient &c) override;
-       void Paint() const override;
-       void Update(struct mpdclient &c, unsigned events) override;
-       bool OnCommand(struct mpdclient &c, command_t cmd) override;
-       const char *GetTitle(char *s, size_t size) const override;
+       void Paint() const noexcept override;
+       void Update(struct mpdclient &c, unsigned events) noexcept override;
+       bool OnCommand(struct mpdclient &c, Command cmd) override;
+       const char *GetTitle(char *s, size_t size) const noexcept override;
 };
 
 /* search info */
 class SearchHelpText final : public ListText {
 public:
        /* virtual methods from class ListText */
-       const char *GetListItemText(char *, size_t, unsigned idx) const override {
+       const char *GetListItemText(char *buffer, size_t size,
+                                   unsigned idx) const noexcept override {
                assert(idx < ARRAY_SIZE(help_text));
 
+               if (idx == 0) {
+                       snprintf(buffer, size,
+                                " %s : %s",
+                                GetGlobalKeyBindings().GetKeyNames(Command::SCREEN_SEARCH).c_str(),
+                                "New search");
+                       return buffer;
+               }
+
+               if (idx == 1) {
+                       snprintf(buffer, size,
+                                " %s : %s [%s]",
+                                GetGlobalKeyBindings().GetKeyNames(Command::SEARCH_MODE).c_str(),
+                                get_key_description(Command::SEARCH_MODE),
+                                gettext(mode[options.search_mode].label));
+                       return buffer;
+               }
+
                return help_text[idx];
        }
 };
@@ -214,20 +231,13 @@ search_advanced_query(struct mpd_connection *connection, const char *query)
        if (strchr(query, ':') == nullptr)
                return nullptr;
 
-       int i, j;
-       char *str = g_strdup(query);
-
-       char *tabv[10];
-       char *matchv[10];
-       int table[10];
-       char *arg[10];
+       std::string str(query);
 
-       memset(tabv, 0, 10 * sizeof(char *));
-       memset(matchv, 0, 10 * sizeof(char *));
-       memset(arg, 0, 10 * sizeof(char *));
+       static constexpr size_t N = 10;
 
-       for (i = 0; i < 10; i++)
-               table[i] = -1;
+       char *tabv[N];
+       char *matchv[N];
+       int table[N];
 
        /*
         * Replace every : with a '\0' and every space character
@@ -235,8 +245,8 @@ search_advanced_query(struct mpd_connection *connection, const char *query)
         * to their proper vector.
         */
        int spi = -1;
-       j = 0;
-       for (i = 0; str[i] != '\0' && j < 10; i++) {
+       size_t n = 0;
+       for (size_t i = 0; str[i] != '\0' && n < N; i++) {
                switch(str[i]) {
                case ' ':
                        spi = i;
@@ -246,9 +256,16 @@ search_advanced_query(struct mpd_connection *connection, const char *query)
                        if (spi != -1)
                                str[spi] = '\0';
 
-                       matchv[j] = str + i + 1;
-                       tabv[j] = str + spi + 1;
-                       j++;
+                       matchv[n] = &str[i + 1];
+                       tabv[n] = &str[spi + 1];
+                       table[n] = search_get_tag_id(tabv[n]);
+                       if (table[n] < 0) {
+                               screen_status_printf(_("Bad search tag %s"),
+                                                    tabv[n]);
+                               return nullptr;
+                       }
+
+                       ++n;
                        /* FALLTHROUGH */
                default:
                        continue;
@@ -256,34 +273,12 @@ search_advanced_query(struct mpd_connection *connection, const char *query)
        }
 
        /* Get rid of obvious failure case */
-       if (matchv[j - 1][0] == '\0') {
-               screen_status_printf(_("No argument for search tag %s"), tabv[j - 1]);
-               g_free(str);
+       if (matchv[n - 1][0] == '\0') {
+               screen_status_printf(_("No argument for search tag %s"), tabv[n - 1]);
                return nullptr;
        }
 
-       int id = j = i = 0;
-       while (matchv[i] && matchv[i][0] != '\0' && i < 10) {
-               id = search_get_tag_id(tabv[i]);
-               if (id == -1) {
-                       screen_status_printf(_("Bad search tag %s"), tabv[i]);
-               } else {
-                       table[j] = id;
-                       arg[j] = locale_to_utf8(matchv[i]);
-                       j++;
-                       advanced_search_mode = true;
-               }
-
-               i++;
-       }
-
-       g_free(str);
-
-       if (!advanced_search_mode || j == 0) {
-               for (i = 0; arg[i] != nullptr; ++i)
-                       g_free(arg[i]);
-               return nullptr;
-       }
+       advanced_search_mode = true;
 
        /*-----------------------------------------------------------------------
         * NOTE (again): This code exists to test a new search ui,
@@ -294,15 +289,18 @@ search_advanced_query(struct mpd_connection *connection, const char *query)
        /** stupid - but this is just a test...... (fulhack)  */
        mpd_search_db_songs(connection, false);
 
-       for (i = 0; i < 10 && arg[i] != nullptr; i++) {
+       for (size_t i = 0; i < n; i++) {
+               const LocaleToUtf8 value(matchv[i]);
+
                if (table[i] == SEARCH_URI)
                        mpd_search_add_uri_constraint(connection,
                                                      MPD_OPERATOR_DEFAULT,
-                                                     arg[i]);
+                                                     value.c_str());
                else
                        mpd_search_add_tag_constraint(connection,
                                                      MPD_OPERATOR_DEFAULT,
-                                                     (enum mpd_tag_type)table[i], arg[i]);
+                                                     (enum mpd_tag_type)table[i],
+                                                     value.c_str());
        }
 
        mpd_search_commit(connection);
@@ -312,9 +310,6 @@ search_advanced_query(struct mpd_connection *connection, const char *query)
                fl = nullptr;
        }
 
-       for (i = 0; arg[i] != nullptr; ++i)
-               g_free(arg[i]);
-
        return fl;
 }
 
@@ -348,7 +343,7 @@ SearchPage::Reload(struct mpdclient &c)
        if (pattern.empty())
                return;
 
-       lw.hide_cursor = false;
+       lw.EnableCursor();
        delete filelist;
        filelist = do_search(&c, pattern.c_str());
        if (filelist == nullptr)
@@ -381,24 +376,14 @@ SearchPage::Start(struct mpdclient &c)
        Reload(c);
 }
 
-static Page *
+static std::unique_ptr<Page>
 screen_search_init(ScreenManager &_screen, WINDOW *w, Size size)
 {
-       return new SearchPage(_screen, w, size);
+       return std::make_unique<SearchPage>(_screen, w, size);
 }
 
 void
-SearchPage::OnOpen(gcc_unused struct mpdclient &c)
-{
-       //  if( pattern==nullptr )
-       //    search_new(screen, c);
-       // else
-       screen_status_printf(_("Press %s for a new search"),
-                            GetGlobalKeyBindings().GetKeyNames(CMD_SCREEN_SEARCH, false));
-}
-
-void
-SearchPage::Paint() const
+SearchPage::Paint() const noexcept
 {
        if (filelist) {
                FileListPage::Paint();
@@ -408,26 +393,24 @@ SearchPage::Paint() const
 }
 
 const char *
-SearchPage::GetTitle(char *str, size_t size) const
+SearchPage::GetTitle(char *str, size_t size) const noexcept
 {
        if (advanced_search_mode && !pattern.empty())
-               snprintf(str, size, _("Search: %s"), pattern.c_str());
+               snprintf(str, size, "%s '%s'", _("Search"), pattern.c_str());
        else if (!pattern.empty())
                snprintf(str, size,
-                        _("Search: Results for %s [%s]"),
+                        "%s '%s' [%s]",
+                        _("Search"),
                         pattern.c_str(),
-                        _(mode[options.search_mode].label));
+                        gettext(mode[options.search_mode].label));
        else
-               snprintf(str, size, _("Search: Press %s for a new search [%s]"),
-                        GetGlobalKeyBindings().GetKeyNames(CMD_SCREEN_SEARCH,
-                                                           false),
-                        _(mode[options.search_mode].label));
+               return _("Search");
 
        return str;
 }
 
 void
-SearchPage::Update(struct mpdclient &c, unsigned events)
+SearchPage::Update(struct mpdclient &c, unsigned events) noexcept
 {
        if (filelist != nullptr && events & MPD_IDLE_QUEUE) {
                screen_browser_sync_highlights(filelist, &c.playlist);
@@ -436,25 +419,34 @@ SearchPage::Update(struct mpdclient &c, unsigned events)
 }
 
 bool
-SearchPage::OnCommand(struct mpdclient &c, command_t cmd)
+SearchPage::OnCommand(struct mpdclient &c, Command cmd)
 {
        switch (cmd) {
-       case CMD_SEARCH_MODE:
+       case Command::SEARCH_MODE:
                options.search_mode++;
                if (mode[options.search_mode].label == nullptr)
                        options.search_mode = 0;
                screen_status_printf(_("Search mode: %s"),
-                                    _(mode[options.search_mode].label));
-               /* fall through */
-       case CMD_SCREEN_UPDATE:
+                                    gettext(mode[options.search_mode].label));
+
+               if (pattern.empty())
+                       /* show the new mode in the help text */
+                       SetDirty();
+               else if (!advanced_search_mode)
+                       /* reload only if the new search mode is going
+                          to be considered */
+                       Reload(c);
+               return true;
+
+       case Command::SCREEN_UPDATE:
                Reload(c);
                return true;
 
-       case CMD_SCREEN_SEARCH:
+       case Command::SCREEN_SEARCH:
                Start(c);
                return true;
 
-       case CMD_CLEAR:
+       case Command::CLEAR:
                Clear(true);
                lw.Reset();
                return true;
@@ -469,7 +461,9 @@ SearchPage::OnCommand(struct mpdclient &c, command_t cmd)
        return false;
 }
 
-const struct screen_functions screen_search = {
+const PageMeta screen_search = {
        "search",
+       N_("Search"),
+       Command::SCREEN_SEARCH,
        screen_search_init,
 };