From b06e620913f0f35947a889929d185afb1a72d011 Mon Sep 17 00:00:00 2001 From: Andrzej Rybczak Date: Wed, 29 Aug 2012 14:34:39 +0200 Subject: [PATCH] more cleanup and grouping functions logically together --- src/Makefile.am | 6 +- src/actions.cpp | 50 ++-- src/browser.cpp | 4 +- src/conv.cpp | 295 --------------------- src/display.cpp | 3 +- src/display.h | 1 + src/help.cpp | 62 ++++- src/helpers.cpp | 12 + src/helpers.h | 3 +- src/lastfm.cpp | 5 +- src/lastfm_service.cpp | 11 +- src/lyrics.cpp | 5 +- src/lyrics_fetcher.cpp | 5 +- src/media_library.cpp | 13 +- src/settings.cpp | 108 +++++--- src/song.cpp | 18 +- src/song_info.h | 2 +- src/strbuffer.h | 3 +- src/tag_editor.cpp | 8 +- src/tag_editor.h | 1 + src/tiny_tag_editor.h | 1 + src/{ => utility}/numeric_conversions.h | 41 +-- src/utility/string.cpp | 67 ++++- src/utility/string.h | 37 ++- src/utility/type_conversions.cpp | 157 +++++++++++ src/{conv.h => utility/type_conversions.h} | 42 +-- src/window.cpp | 26 +- src/window.h | 12 - 28 files changed, 486 insertions(+), 512 deletions(-) delete mode 100644 src/conv.cpp rename src/{ => utility}/numeric_conversions.h (76%) create mode 100644 src/utility/type_conversions.cpp rename src/{conv.h => utility/type_conversions.h} (64%) diff --git a/src/Makefile.am b/src/Makefile.am index 741bbaee..71351588 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -3,11 +3,11 @@ ncmpcpp_SOURCES = \ utility/comparators.cpp \ utility/html.cpp \ utility/string.cpp \ + utility/type_conversions.cpp \ actions.cpp \ browser.cpp \ charset.cpp \ clock.cpp \ - conv.cpp \ curl_handle.cpp \ display.cpp \ error.cpp \ @@ -49,10 +49,11 @@ noinst_HEADERS = \ utility/comparators.h \ utility/html.h \ utility/string.h \ + utility/numeric_conversions.h \ + utility/type_conversions.h \ browser.h \ charset.h \ clock.h \ - conv.h \ curl_handle.h \ display.h \ error.h \ @@ -68,7 +69,6 @@ noinst_HEADERS = \ menu.h \ mpdpp.h \ mutable_song.h \ - numeric_conversions.h \ outputs.h \ playlist_editor.h \ screen.h \ diff --git a/src/actions.cpp b/src/actions.cpp index e51330ee..fcc7c16e 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include "actions.h" @@ -44,6 +45,7 @@ #include "song_info.h" #include "outputs.h" #include "utility/string.h" +#include "utility/type_conversions.h" #include "tag_editor.h" #include "tiny_tag_editor.h" #include "visualizer.h" @@ -786,7 +788,7 @@ void Delete::Run() if (Mpd.DeletePlaylist(locale_to_utf_cpy(name))) { const char msg[] = "Playlist \"%s\" deleted"; - ShowMessage(msg, Shorten(TO_WSTRING(name), COLS-static_strlen(msg)).c_str()); + ShowMessage(msg, Shorten(TO_WSTRING(name), COLS-const_strlen(msg)).c_str()); if (myBrowser->Main() && !myBrowser->isLocal() && myBrowser->CurrentDir() == "/") myBrowser->GetDirectory("/"); } @@ -844,12 +846,12 @@ void Delete::Run() if (myBrowser->DeleteItem(it)) { const char msg[] = "\"%s\" deleted"; - ShowMessage(msg, Shorten(TO_WSTRING(name), COLS-static_strlen(msg)).c_str()); + ShowMessage(msg, Shorten(TO_WSTRING(name), COLS-const_strlen(msg)).c_str()); } else { const char msg[] = "Couldn't delete \"%s\": %s"; - ShowMessage(msg, Shorten(TO_WSTRING(name), COLS-static_strlen(msg)-25).c_str(), strerror(errno)); + ShowMessage(msg, Shorten(TO_WSTRING(name), COLS-const_strlen(msg)-25).c_str(), strerror(errno)); success = 0; break; } @@ -1109,7 +1111,7 @@ void Add::Run() else { const char lastfm_url[] = "lastfm://"; - if (path.compare(0, static_strlen(lastfm_url), lastfm_url) == 0 + if (path.compare(0, const_strlen(lastfm_url), lastfm_url) == 0 || path.find(".asx", path.length()-4) != std::string::npos || path.find(".cue", path.length()-4) != std::string::npos || path.find(".m3u", path.length()-4) != std::string::npos @@ -1372,7 +1374,7 @@ void SetCrossfade::Run() Statusbar() << "Set crossfade to: "; std::string crossfade = wFooter->GetString(3); UnlockStatusbar(); - int cf = StrToInt(crossfade); + int cf = stringToInt(crossfade); if (cf > 0) { Config.crossfade_time = cf; @@ -1419,7 +1421,7 @@ void EditLibraryTag::Run() if (!isMPDMusicDirSet()) return; LockStatusbar(); - Statusbar() << fmtBold << IntoStr(Config.media_lib_primary_tag) << fmtBoldEnd << ": "; + Statusbar() << fmtBold << tagTypeToString(Config.media_lib_primary_tag) << fmtBoldEnd << ": "; std::string new_tag = wFooter->GetString(myLibrary->Artists->Current()); UnlockStatusbar(); if (!new_tag.empty() && new_tag != myLibrary->Artists->Current()) @@ -1427,7 +1429,7 @@ void EditLibraryTag::Run() ShowMessage("Updating tags..."); Mpd.StartSearch(1); Mpd.AddSearch(Config.media_lib_primary_tag, locale_to_utf_cpy(myLibrary->Artists->Current())); - MPD::MutableSong::SetFunction set = IntoSetFunction(Config.media_lib_primary_tag); + MPD::MutableSong::SetFunction set = tagTypeToSetFunction(Config.media_lib_primary_tag); assert(set); bool success = true; std::string dir_to_update; @@ -1441,7 +1443,7 @@ void EditLibraryTag::Run() if (!TagEditor::WriteTags(es)) { const char msg[] = "Error while updating tags in \"%s\""; - ShowMessage(msg, Shorten(TO_WSTRING(es.getURI()), COLS-static_strlen(msg)).c_str()); + ShowMessage(msg, Shorten(TO_WSTRING(es.getURI()), COLS-const_strlen(msg)).c_str()); success = false; } if (dir_to_update.empty()) @@ -1491,7 +1493,7 @@ void EditLibraryAlbum::Run() if (f.isNull()) { const char msg[] = "Error while opening file \"%s\""; - ShowMessage(msg, Shorten(TO_WSTRING((*myLibrary->Songs)[i].getURI()), COLS-static_strlen(msg)).c_str()); + ShowMessage(msg, Shorten(TO_WSTRING((*myLibrary->Songs)[i].getURI()), COLS-const_strlen(msg)).c_str()); success = 0; break; } @@ -1499,7 +1501,7 @@ void EditLibraryAlbum::Run() if (!f.save()) { const char msg[] = "Error while writing tags in \"%s\""; - ShowMessage(msg, Shorten(TO_WSTRING((*myLibrary->Songs)[i].getURI()), COLS-static_strlen(msg)).c_str()); + ShowMessage(msg, Shorten(TO_WSTRING((*myLibrary->Songs)[i].getURI()), COLS-const_strlen(msg)).c_str()); success = 0; break; } @@ -1553,7 +1555,7 @@ void EditDirectoryName::Run() if (rename_result == 0) { const char msg[] = "Directory renamed to \"%s\""; - ShowMessage(msg, Shorten(TO_WSTRING(new_dir), COLS-static_strlen(msg)).c_str()); + ShowMessage(msg, Shorten(TO_WSTRING(new_dir), COLS-const_strlen(msg)).c_str()); if (!myBrowser->isLocal()) Mpd.UpdateDirectory(locale_to_utf_cpy(getSharedDirectory(old_dir, new_dir))); myBrowser->GetDirectory(myBrowser->CurrentDir()); @@ -1561,7 +1563,7 @@ void EditDirectoryName::Run() else { const char msg[] = "Couldn't rename \"%s\": %s"; - ShowMessage(msg, Shorten(TO_WSTRING(old_dir), COLS-static_strlen(msg)-25).c_str(), strerror(errno)); + ShowMessage(msg, Shorten(TO_WSTRING(old_dir), COLS-const_strlen(msg)-25).c_str(), strerror(errno)); } } } @@ -1580,13 +1582,13 @@ void EditDirectoryName::Run() if (rename(full_old_dir.c_str(), full_new_dir.c_str()) == 0) { const char msg[] = "Directory renamed to \"%s\""; - ShowMessage(msg, Shorten(TO_WSTRING(new_dir), COLS-static_strlen(msg)).c_str()); + ShowMessage(msg, Shorten(TO_WSTRING(new_dir), COLS-const_strlen(msg)).c_str()); Mpd.UpdateDirectory(myTagEditor->CurrentDir()); } else { const char msg[] = "Couldn't rename \"%s\": %s"; - ShowMessage(msg, Shorten(TO_WSTRING(old_dir), COLS-static_strlen(msg)-25).c_str(), strerror(errno)); + ShowMessage(msg, Shorten(TO_WSTRING(old_dir), COLS-const_strlen(msg)-25).c_str(), strerror(errno)); } } } @@ -1620,7 +1622,7 @@ void EditPlaylistName::Run() if (Mpd.Rename(locale_to_utf_cpy(old_name), locale_to_utf_cpy(new_name))) { const char msg[] = "Playlist renamed to \"%s\""; - ShowMessage(msg, Shorten(TO_WSTRING(new_name), COLS-static_strlen(msg)).c_str()); + ShowMessage(msg, Shorten(TO_WSTRING(new_name), COLS-const_strlen(msg)).c_str()); if (myBrowser->Main() && !myBrowser->isLocal()) myBrowser->GetDirectory("/"); if (myPlaylistEditor->Main()) @@ -1696,7 +1698,7 @@ void ToggleScreenLock::Run() UnlockStatusbar(); if (str_part.empty()) return; - part = StrToInt(str_part); + part = stringToInt(str_part); } if (part < 20 || part > 80) { @@ -1760,7 +1762,7 @@ void JumpToPositionInSong::Run() int newpos = 0; if (position.find(':') != std::string::npos) // probably time in mm:ss { - newpos = StrToInt(position)*60 + StrToInt(position.substr(position.find(':')+1)); + newpos = stringToInt(position)*60 + stringToInt(position.substr(position.find(':')+1)); if (newpos >= 0 && newpos <= Mpd.GetTotalTime()) Mpd.Seek(newpos); else @@ -1768,7 +1770,7 @@ void JumpToPositionInSong::Run() } else if (position.find('s') != std::string::npos) // probably position in seconds { - newpos = StrToInt(position); + newpos = stringToInt(position); if (newpos >= 0 && newpos <= Mpd.GetTotalTime()) Mpd.Seek(newpos); else @@ -1776,7 +1778,7 @@ void JumpToPositionInSong::Run() } else { - newpos = StrToInt(position); + newpos = stringToInt(position); if (newpos >= 0 && newpos <= 100) Mpd.Seek(Mpd.GetTotalTime()*newpos/100.0); else @@ -2163,13 +2165,13 @@ void AddRandomItems::Run() while (answer != 's' && answer != 'a' && answer != 'b'); UnlockStatusbar(); - mpd_tag_type tag_type = IntoTagItem(answer); - std::string tag_type_str = answer == 's' ? "song" : IntoStr(tag_type); + mpd_tag_type tag_type = charToTagType(answer); + std::string tag_type_str = answer == 's' ? "song" : tagTypeToString(tag_type); lowercase(tag_type_str); LockStatusbar(); Statusbar() << "Number of random " << tag_type_str << "s: "; - size_t number = StrToLong(wFooter->GetString()); + size_t number = stringToLongInt(wFooter->GetString()); UnlockStatusbar(); if (number && (answer == 's' ? Mpd.AddRandomSongs(number) : Mpd.AddRandomTag(tag_type, number))) ShowMessage("%zu random %s%s added to playlist", number, tag_type_str.c_str(), number == 1 ? "" : "s"); @@ -2225,11 +2227,11 @@ void ToggleLibraryTagType::Run() } while (answer != 'a' && answer != 'A' && answer != 'y' && answer != 'g' && answer != 'c' && answer != 'p'); UnlockStatusbar(); - mpd_tag_type new_tagitem = IntoTagItem(answer); + mpd_tag_type new_tagitem = charToTagType(answer); if (new_tagitem != Config.media_lib_primary_tag) { Config.media_lib_primary_tag = new_tagitem; - std::string item_type = IntoStr(Config.media_lib_primary_tag); + std::string item_type = tagTypeToString(Config.media_lib_primary_tag); myLibrary->Artists->SetTitle(Config.titles_visibility ? item_type + "s" : ""); myLibrary->Artists->Reset(); lowercase(item_type); diff --git a/src/browser.cpp b/src/browser.cpp index 1c082f58..98c408a9 100644 --- a/src/browser.cpp +++ b/src/browser.cpp @@ -516,12 +516,12 @@ void Browser::ClearDirectory(const std::string &path) const if (remove(full_path.c_str()) == 0) { const char msg[] = "Deleting \"%s\"..."; - ShowMessage(msg, Shorten(TO_WSTRING(full_path), COLS-static_strlen(msg)).c_str()); + ShowMessage(msg, Shorten(TO_WSTRING(full_path), COLS-const_strlen(msg)).c_str()); } else { const char msg[] = "Couldn't remove \"%s\": %s"; - ShowMessage(msg, Shorten(TO_WSTRING(full_path), COLS-static_strlen(msg)-25).c_str(), strerror(errno)); + ShowMessage(msg, Shorten(TO_WSTRING(full_path), COLS-const_strlen(msg)-25).c_str(), strerror(errno)); } } closedir(dir); diff --git a/src/conv.cpp b/src/conv.cpp deleted file mode 100644 index 06b8a70d..00000000 --- a/src/conv.cpp +++ /dev/null @@ -1,295 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008-2012 by Andrzej Rybczak * - * electricityispower@gmail.com * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * - ***************************************************************************/ - -#include -#include "conv.h" - -int StrToInt(const std::string &str) -{ - return atoi(str.c_str()); -} - -long StrToLong(const std::string &str) -{ - return atol(str.c_str()); -} - -std::string IntoStr(mpd_tag_type tag) // this is only for left column's title in media library -{ - switch (tag) - { - case MPD_TAG_ARTIST: - return "Artist"; - case MPD_TAG_ALBUM: - return "Album"; - case MPD_TAG_ALBUM_ARTIST: - return "Album Artist"; - case MPD_TAG_TITLE: - return "Title"; - case MPD_TAG_TRACK: - return "Track"; - case MPD_TAG_GENRE: - return "Genre"; - case MPD_TAG_DATE: - return "Date"; - case MPD_TAG_COMPOSER: - return "Composer"; - case MPD_TAG_PERFORMER: - return "Performer"; - case MPD_TAG_COMMENT: - return "Comment"; - case MPD_TAG_DISC: - return "Disc"; - default: - return ""; - } -} - -std::string IntoStr(NCurses::Color color) -{ - std::string result; - - if (color == NCurses::clDefault) - result = "default"; - else if (color == NCurses::clBlack) - result = "black"; - else if (color == NCurses::clRed) - result = "red"; - else if (color == NCurses::clGreen) - result = "green"; - else if (color == NCurses::clYellow) - result = "yellow"; - else if (color == NCurses::clBlue) - result = "blue"; - else if (color == NCurses::clMagenta) - result = "magenta"; - else if (color == NCurses::clCyan) - result = "cyan"; - else if (color == NCurses::clWhite) - result = "white"; - - return result; -} - -std::string IntoStr(const Action::Key &key, bool *print_backspace) -{ - std::string result; - if (key == Action::Key(KEY_UP, ctNCurses)) - result += "Up"; - else if (key == Action::Key(KEY_DOWN, ctNCurses)) - result += "Down"; - else if (key == Action::Key(KEY_PPAGE, ctNCurses)) - result += "PageUp"; - else if (key == Action::Key(KEY_NPAGE, ctNCurses)) - result += "PageDown"; - else if (key == Action::Key(KEY_HOME, ctNCurses)) - result += "Home"; - else if (key == Action::Key(KEY_END, ctNCurses)) - result += "End"; - else if (key == Action::Key(KEY_SPACE, ctStandard)) - result += "Space"; - else if (key == Action::Key(KEY_ENTER, ctStandard)) - result += "Enter"; - else if (key == Action::Key(KEY_DC, ctNCurses)) - result += "Delete"; - else if (key == Action::Key(KEY_RIGHT, ctNCurses)) - result += "Right"; - else if (key == Action::Key(KEY_LEFT, ctNCurses)) - result += "Left"; - else if (key == Action::Key(KEY_TAB, ctStandard)) - result += "Tab"; - else if (key == Action::Key(KEY_SHIFT_TAB, ctNCurses)) - result += "Shift-Tab"; - else if (key >= Action::Key(KEY_CTRL_A, ctStandard) && key <= Action::Key(KEY_CTRL_Z, ctStandard)) - { - result += "Ctrl-"; - result += key.getChar()+64; - } - else if (key >= Action::Key(KEY_F1, ctNCurses) && key <= Action::Key(KEY_F12, ctNCurses)) - { - result += "F"; - result += intTo::apply(key.getChar()-264); - } - else if ((key == Action::Key(KEY_BACKSPACE, ctNCurses) || key == Action::Key(KEY_BACKSPACE_2, ctStandard))) - { - // since some terminals interpret KEY_BACKSPACE as backspace and other need KEY_BACKSPACE_2, - // actions have to be bound to either of them, but we want to display "Backspace" only once, - // hance this 'print_backspace' switch. - if (!print_backspace || *print_backspace) - { - result += "Backspace"; - if (print_backspace) - *print_backspace = false; - } - } - else - result += ToString(std::wstring(1, key.getChar())); - return result; -} - -NCurses::Color IntoColor(const std::string &color) -{ - NCurses::Color result = NCurses::clDefault; - - if (color == "black") - result = NCurses::clBlack; - else if (color == "red") - result = NCurses::clRed; - else if (color == "green") - result = NCurses::clGreen; - else if (color == "yellow") - result = NCurses::clYellow; - else if (color == "blue") - result = NCurses::clBlue; - else if (color == "magenta") - result = NCurses::clMagenta; - else if (color == "cyan") - result = NCurses::clCyan; - else if (color == "white") - result = NCurses::clWhite; - - return result; -} - -mpd_tag_type IntoTagItem(char c) -{ - switch (c) - { - case 'a': - return MPD_TAG_ARTIST; - case 'A': - return MPD_TAG_ALBUM_ARTIST; - case 'b': - return MPD_TAG_ALBUM; - case 'y': - return MPD_TAG_DATE; - case 'g': - return MPD_TAG_GENRE; - case 'c': - return MPD_TAG_COMPOSER; - case 'p': - return MPD_TAG_PERFORMER; - default: - return MPD_TAG_ARTIST; - } -} - -MPD::Song::GetFunction toGetFunction(char c) -{ - switch (c) - { - case 'l': - return &MPD::Song::getLength; - case 'D': - return &MPD::Song::getDirectory; - case 'f': - return &MPD::Song::getName; - case 'a': - return &MPD::Song::getArtist; - case 'A': - return &MPD::Song::getAlbumArtist; - case 'b': - return &MPD::Song::getAlbum; - case 'y': - return &MPD::Song::getDate; - case 'n': - return &MPD::Song::getTrackNumber; - case 'N': - return &MPD::Song::getTrack; - case 'g': - return &MPD::Song::getGenre; - case 'c': - return &MPD::Song::getComposer; - case 'p': - return &MPD::Song::getPerformer; - case 'd': - return &MPD::Song::getDisc; - case 'C': - return &MPD::Song::getComment; - case 't': - return &MPD::Song::getTitle; - case 'P': - return &MPD::Song::getPriority; - default: - return 0; - } -} - -#ifdef HAVE_TAGLIB_H -MPD::MutableSong::SetFunction IntoSetFunction(mpd_tag_type tag) -{ - switch (tag) - { - case MPD_TAG_ARTIST: - return &MPD::MutableSong::setArtist; - case MPD_TAG_ALBUM: - return &MPD::MutableSong::setAlbum; - case MPD_TAG_ALBUM_ARTIST: - return &MPD::MutableSong::setAlbumArtist; - case MPD_TAG_TITLE: - return &MPD::MutableSong::setTitle; - case MPD_TAG_TRACK: - return &MPD::MutableSong::setTrack; - case MPD_TAG_GENRE: - return &MPD::MutableSong::setGenre; - case MPD_TAG_DATE: - return &MPD::MutableSong::setDate; - case MPD_TAG_COMPOSER: - return &MPD::MutableSong::setComposer; - case MPD_TAG_PERFORMER: - return &MPD::MutableSong::setPerformer; - case MPD_TAG_COMMENT: - return &MPD::MutableSong::setComment; - case MPD_TAG_DISC: - return &MPD::MutableSong::setDisc; - default: - return 0; - } -} -#endif // HAVE_TAGLIB_H - -std::string Shorten(const std::basic_string &s, size_t max_length) -{ - if (s.length() <= max_length) - return TO_STRING(s); - if (max_length < 2) - return ""; - std::basic_string result(s, 0, max_length/2-!(max_length%2)); - result += U(".."); - result += s.substr(s.length()-max_length/2+1); - return TO_STRING(result); -} - -void EscapeUnallowedChars(std::string &s) -{ - static const std::string unallowed_chars = "\"*/:<>?\\|"; - - for (std::string::const_iterator it = unallowed_chars.begin(); it != unallowed_chars.end(); ++it) - { - for (size_t i = 0; i < s.length(); ++i) - { - if (s[i] == *it) - { - s.erase(s.begin()+i); - i--; - } - } - } -} diff --git a/src/display.cpp b/src/display.cpp index 1175459e..31478c40 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -25,6 +25,7 @@ #include "song_info.h" #include "playlist.h" #include "global.h" +#include "utility/type_conversions.h" using Global::myScreen; @@ -214,7 +215,7 @@ void Display::SongsInColumns(const MPD::Song &s, void *data, Menu *me std::basic_string tag; for (size_t i = 0; i < it->type.length(); ++i) { - MPD::Song::GetFunction get = toGetFunction(it->type[i]); + MPD::Song::GetFunction get = charToGetFunction(it->type[i]); tag = TO_WSTRING(get ? s.getTags(get) : ""); if (!tag.empty()) break; diff --git a/src/display.h b/src/display.h index 474b7dde..22a44f40 100644 --- a/src/display.h +++ b/src/display.h @@ -24,6 +24,7 @@ #include "ncmpcpp.h" #include "menu.h" #include "mpdpp.h" +#include "mutable_song.h" #include "screen.h" #include "search_engine.h" diff --git a/src/help.cpp b/src/help.cpp index a20021f8..b0bae533 100644 --- a/src/help.cpp +++ b/src/help.cpp @@ -30,6 +30,66 @@ using Global::MainStartY; Help *myHelp = new Help; +namespace {// + +std::string keyToString(const Action::Key &key, bool *print_backspace) +{ + std::string result; + if (key == Action::Key(KEY_UP, ctNCurses)) + result += "Up"; + else if (key == Action::Key(KEY_DOWN, ctNCurses)) + result += "Down"; + else if (key == Action::Key(KEY_PPAGE, ctNCurses)) + result += "PageUp"; + else if (key == Action::Key(KEY_NPAGE, ctNCurses)) + result += "PageDown"; + else if (key == Action::Key(KEY_HOME, ctNCurses)) + result += "Home"; + else if (key == Action::Key(KEY_END, ctNCurses)) + result += "End"; + else if (key == Action::Key(KEY_SPACE, ctStandard)) + result += "Space"; + else if (key == Action::Key(KEY_ENTER, ctStandard)) + result += "Enter"; + else if (key == Action::Key(KEY_DC, ctNCurses)) + result += "Delete"; + else if (key == Action::Key(KEY_RIGHT, ctNCurses)) + result += "Right"; + else if (key == Action::Key(KEY_LEFT, ctNCurses)) + result += "Left"; + else if (key == Action::Key(KEY_TAB, ctStandard)) + result += "Tab"; + else if (key == Action::Key(KEY_SHIFT_TAB, ctNCurses)) + result += "Shift-Tab"; + else if (key >= Action::Key(KEY_CTRL_A, ctStandard) && key <= Action::Key(KEY_CTRL_Z, ctStandard)) + { + result += "Ctrl-"; + result += key.getChar()+64; + } + else if (key >= Action::Key(KEY_F1, ctNCurses) && key <= Action::Key(KEY_F12, ctNCurses)) + { + result += "F"; + result += intTo::apply(key.getChar()-264); + } + else if ((key == Action::Key(KEY_BACKSPACE, ctNCurses) || key == Action::Key(KEY_BACKSPACE_2, ctStandard))) + { + // since some terminals interpret KEY_BACKSPACE as backspace and other need KEY_BACKSPACE_2, + // actions have to be bound to either of them, but we want to display "Backspace" only once, + // hance this 'print_backspace' switch. + if (!print_backspace || *print_backspace) + { + result += "Backspace"; + if (print_backspace) + *print_backspace = false; + } + } + else + result += ToString(std::wstring(1, key.getChar())); + return result; +} + +} + void Help::Init() { w = new Scrollpad(0, MainStartY, COLS, MainHeight, "", Config.main_color, brNone); @@ -84,7 +144,7 @@ std::string Help::DisplayKeys(const ActionType at) { if (it->second.isSingle() && it->second.getAction()->Type() == at) { - result += IntoStr(it->first, &print_backspace); + result += keyToString(it->first, &print_backspace); result += " "; } } diff --git a/src/helpers.cpp b/src/helpers.cpp index ee1722ab..27565356 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -353,3 +353,15 @@ std::basic_string Scroller(const std::basic_string &str, s result = s; return result; } + +std::string Shorten(const std::basic_string &s, size_t max_length) +{ + if (s.length() <= max_length) + return TO_STRING(s); + if (max_length < 2) + return ""; + std::basic_string result(s, 0, max_length/2-!(max_length%2)); + result += U(".."); + result += s.substr(s.length()-max_length/2+1); + return TO_STRING(result); +} diff --git a/src/helpers.h b/src/helpers.h index 73d40181..3e53bfb3 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -21,7 +21,6 @@ #ifndef _HELPERS_H #define _HELPERS_H -#include "conv.h" #include "mpdpp.h" #include "ncmpcpp.h" #include "settings.h" @@ -194,4 +193,6 @@ template std::string getSharedDirectory(Menu *menu) std::basic_string Scroller(const std::basic_string &str, size_t &pos, size_t width); +std::string Shorten(const std::basic_string &s, size_t max_length); + #endif diff --git a/src/lastfm.cpp b/src/lastfm.cpp index a0a9bf9a..628dc98d 100644 --- a/src/lastfm.cpp +++ b/src/lastfm.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -125,7 +126,7 @@ void Lastfm::Load() std::string file = artist + ".txt"; lowercase(file); - EscapeUnallowedChars(file); + removeInvalidCharsFromFilename(file); itsFilename = itsFolder + "/" + file; @@ -211,7 +212,7 @@ void Lastfm::Refetch() if (remove(itsFilename.c_str()) && errno != ENOENT) { const char msg[] = "Couldn't remove \"%s\": %s"; - ShowMessage(msg, Shorten(TO_WSTRING(itsFilename), COLS-static_strlen(msg)-25).c_str(), strerror(errno)); + ShowMessage(msg, Shorten(TO_WSTRING(itsFilename), COLS-const_strlen(msg)-25).c_str(), strerror(errno)); return; } Load(); diff --git a/src/lastfm_service.cpp b/src/lastfm_service.cpp index 81d72d0b..c0f3b32c 100644 --- a/src/lastfm_service.cpp +++ b/src/lastfm_service.cpp @@ -22,7 +22,6 @@ #ifdef HAVE_CURL_CURL_H -#include "conv.h" #include "curl_handle.h" #include "settings.h" #include "utility/html.h" @@ -118,7 +117,7 @@ bool ArtistInfo::parse(std::string &data) if ((a = data.find("")) != std::string::npos) { - a += static_strlen(""); + a += const_strlen(""); if ((b = data.find("")) == std::string::npos) parse_failed = true; } @@ -142,17 +141,17 @@ bool ArtistInfo::parse(std::string &data) i != std::string::npos; i = data.find("", i), k = data.find("", k)) { j = data.find("", i); - i += static_strlen(""); + i += const_strlen(""); l = data.find("", k); - k += static_strlen(""); + k += const_strlen(""); similars.push_back(std::make_pair(data.substr(i, j-i), data.substr(k, l-k))); stripHtmlTags(similars.back().first); } - a += static_strlen(""); + a += const_strlen(""); data = data.substr(a, b-a); postProcess(data); diff --git a/src/lyrics.cpp b/src/lyrics.cpp index a55aa5f4..1e4e4f5e 100644 --- a/src/lyrics.cpp +++ b/src/lyrics.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include "browser.h" @@ -305,7 +306,7 @@ std::string Lyrics::GenerateFilename(const MPD::Song &s) file += " - "; file += locale_to_utf_cpy(s.getTitle()); file += ".txt"; - EscapeUnallowedChars(file); + removeInvalidCharsFromFilename(file); filename = Config.lyrics_directory; filename += "/"; filename += file; @@ -402,7 +403,7 @@ void Lyrics::Refetch() if (remove(itsFilename.c_str()) && errno != ENOENT) { const char msg[] = "Couldn't remove \"%s\": %s"; - ShowMessage(msg, Shorten(TO_WSTRING(itsFilename), COLS-static_strlen(msg)-25).c_str(), strerror(errno)); + ShowMessage(msg, Shorten(TO_WSTRING(itsFilename), COLS-const_strlen(msg)-25).c_str(), strerror(errno)); return; } Load(); diff --git a/src/lyrics_fetcher.cpp b/src/lyrics_fetcher.cpp index 01081987..13e060e8 100644 --- a/src/lyrics_fetcher.cpp +++ b/src/lyrics_fetcher.cpp @@ -23,11 +23,12 @@ #ifdef HAVE_CURL_CURL_H #include +#include #include "charset.h" -#include "conv.h" #include "lyrics_fetcher.h" #include "utility/html.h" +#include "utility/string.h" LyricsFetcher *lyricsPlugins[] = { @@ -270,7 +271,7 @@ void LyricsvipFetcher::postProcess(std::string &data) // throw away
with ad size_t i = data.find("
"); if (i != std::string::npos && i != std::string::npos) - data.replace(i, j-i+static_strlen("
"), ""); + data.replace(i, j-i+const_strlen("
"), ""); data = unescapeHtmlUtf8(data); LyricsFetcher::postProcess(data); } diff --git a/src/media_library.cpp b/src/media_library.cpp index 3b36c052..9f5ff36f 100644 --- a/src/media_library.cpp +++ b/src/media_library.cpp @@ -30,6 +30,7 @@ #include "playlist.h" #include "status.h" #include "utility/comparators.h" +#include "utility/type_conversions.h" using Global::MainHeight; using Global::MainStartY; @@ -60,7 +61,7 @@ void MediaLibrary::Init() itsRightColWidth = COLS-COLS/3*2-1; itsRightColStartX = itsLeftColWidth+itsMiddleColWidth+2; - Artists = new Menu(0, MainStartY, itsLeftColWidth, MainHeight, Config.titles_visibility ? IntoStr(Config.media_lib_primary_tag) + "s" : "", Config.main_color, brNone); + Artists = new Menu(0, MainStartY, itsLeftColWidth, MainHeight, Config.titles_visibility ? tagTypeToString(Config.media_lib_primary_tag) + "s" : "", Config.main_color, brNone); Artists->HighlightColor(Config.active_column_color); Artists->CyclicScrolling(Config.use_cyclic_scrolling); Artists->CenteredCursor(Config.centered_cursor); @@ -162,7 +163,7 @@ void MediaLibrary::SwitchTo() NextColumn(); if (Config.titles_visibility) { - std::string item_type = IntoStr(Config.media_lib_primary_tag); + std::string item_type = tagTypeToString(Config.media_lib_primary_tag); lowercase(item_type); Albums->SetTitle("Albums (sorted by " + item_type + ")"); } @@ -635,7 +636,7 @@ void MediaLibrary::LocateSong(const MPD::Song &s) } if (primary_tag.empty()) { - std::string item_type = IntoStr(Config.media_lib_primary_tag); + std::string item_type = tagTypeToString(Config.media_lib_primary_tag); lowercase(item_type); ShowMessage("Can't use this function because the song has no %s tag set", item_type.c_str()); return; @@ -726,7 +727,7 @@ void MediaLibrary::AddToPlaylist(bool add_n_play) if ((!Artists->Empty() && w == Artists) || (w == Albums && Albums->Current().Date == AllTracksMarker)) { - std::string tag_type = IntoStr(Config.media_lib_primary_tag); + std::string tag_type = tagTypeToString(Config.media_lib_primary_tag); lowercase(tag_type); ShowMessage("Songs with %s = \"%s\" added", tag_type.c_str(), Artists->Current().c_str()); } @@ -790,9 +791,9 @@ bool MediaLibrary::SearchConstraintsSorting::operator()(const SearchConstraints bool MediaLibrary::SortSongsByTrack(const MPD::Song &a, const MPD::Song &b) { if (a.getDisc() == b.getDisc()) - return StrToInt(a.getTrack()) < StrToInt(b.getTrack()); + return stringToInt(a.getTrack()) < stringToInt(b.getTrack()); else - return StrToInt(a.getDisc()) < StrToInt(b.getDisc()); + return stringToInt(a.getDisc()) < stringToInt(b.getDisc()); } bool MediaLibrary::SortAllTracks(const MPD::Song &a, const MPD::Song &b) diff --git a/src/settings.cpp b/src/settings.cpp index f8bf685e..1445d956 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -26,6 +26,7 @@ # include #endif // WIN32 #include +#include #include #include #include @@ -46,6 +47,7 @@ #include "settings.h" #include "tag_editor.h" #include "visualizer.h" +#include "utility/type_conversions.h" #ifdef HAVE_LANGINFO_H # include @@ -56,12 +58,36 @@ KeyConfiguration Keys; namespace { - Border IntoBorder(const std::string &color) + NCurses::Color stringToColor(const std::string &color) { - return Border(IntoColor(color)); + NCurses::Color result = NCurses::clDefault; + + if (color == "black") + result = NCurses::clBlack; + else if (color == "red") + result = NCurses::clRed; + else if (color == "green") + result = NCurses::clGreen; + else if (color == "yellow") + result = NCurses::clYellow; + else if (color == "blue") + result = NCurses::clBlue; + else if (color == "magenta") + result = NCurses::clMagenta; + else if (color == "cyan") + result = NCurses::clCyan; + else if (color == "white") + result = NCurses::clWhite; + + return result; } - BasicScreen *IntoScreen(int n) + Border stringToBorder(const std::string &border) + { + return Border(stringToColor(border)); + } + + BasicScreen *intToScreen(int n) { switch (n) { @@ -488,33 +514,33 @@ void Configuration::Read() } else if (name == "mpd_port") { - if (StrToInt(v)) - mpd_port = StrToInt(v); + if (stringToInt(v)) + mpd_port = stringToInt(v); } else if (name == "mpd_connection_timeout") { - if (StrToInt(v)) - mpd_connection_timeout = StrToInt(v); + if (stringToInt(v)) + mpd_connection_timeout = stringToInt(v); } else if (name == "mpd_crossfade_time") { - if (StrToInt(v) > 0) - crossfade_time = StrToInt(v); + if (stringToInt(v) > 0) + crossfade_time = stringToInt(v); } else if (name == "seek_time") { - if (StrToInt(v) > 0) - seek_time = StrToInt(v); + if (stringToInt(v) > 0) + seek_time = stringToInt(v); } else if (name == "playlist_disable_highlight_delay") { - if (StrToInt(v) >= 0) - playlist_disable_highlight_delay = StrToInt(v); + if (stringToInt(v) >= 0) + playlist_disable_highlight_delay = stringToInt(v); } else if (name == "message_delay_time") { - if (StrToInt(v) > 0) - message_delay_time = StrToInt(v); + if (stringToInt(v) > 0) + message_delay_time = stringToInt(v); } else if (name == "song_list_format") { @@ -689,12 +715,12 @@ void Configuration::Read() else if (name == "color1") { if (!v.empty()) - color1 = IntoColor(v); + color1 = stringToColor(v); } else if (name == "color2") { if (!v.empty()) - color2 = IntoColor(v); + color2 = stringToColor(v); } else if (name == "mpd_communication_mode") { @@ -768,7 +794,7 @@ void Configuration::Read() ++it; if (it == v.end()) break; - if (BasicScreen *screen = IntoScreen(atoi(&*it))) + if (BasicScreen *screen = intToScreen(atoi(&*it))) screens_seq.push_back(screen); while (it != v.end() && isdigit(*it)) ++it; @@ -779,7 +805,7 @@ void Configuration::Read() } else if (name == "startup_screen") { - startup_screen = IntoScreen(atoi(v.c_str())); + startup_screen = intToScreen(atoi(v.c_str())); if (!startup_screen) startup_screen = myPlaylist; } @@ -932,20 +958,20 @@ void Configuration::Read() else if (name == "lines_scrolled") { if (!v.empty()) - lines_scrolled = StrToInt(v); + lines_scrolled = stringToInt(v); } else if (name == "search_engine_default_search_mode") { if (!v.empty()) { - unsigned mode = StrToInt(v); + unsigned mode = stringToInt(v); if (--mode < 3) search_engine_default_search_mode = mode; } } else if (name == "visualizer_sync_interval") { - unsigned interval = StrToInt(v); + unsigned interval = stringToInt(v); if (interval) visualizer_sync_interval = interval; } @@ -960,7 +986,7 @@ void Configuration::Read() } else if (name == "locked_screen_width_part") { - int part = StrToInt(v); + int part = stringToInt(v); if (part) locked_screen_width_part = part/100.0; } @@ -990,82 +1016,82 @@ void Configuration::Read() else if (name == "empty_tag_color") { if (!v.empty()) - empty_tags_color = IntoColor(v); + empty_tags_color = stringToColor(v); } else if (name == "header_window_color") { if (!v.empty()) - header_color = IntoColor(v); + header_color = stringToColor(v); } else if (name == "volume_color") { if (!v.empty()) - volume_color = IntoColor(v); + volume_color = stringToColor(v); } else if (name == "state_line_color") { if (!v.empty()) - state_line_color = IntoColor(v); + state_line_color = stringToColor(v); } else if (name == "state_flags_color") { if (!v.empty()) - state_flags_color = IntoColor(v); + state_flags_color = stringToColor(v); } else if (name == "main_window_color") { if (!v.empty()) - main_color = IntoColor(v); + main_color = stringToColor(v); } else if (name == "main_window_highlight_color") { if (!v.empty()) - main_highlight_color = IntoColor(v); + main_highlight_color = stringToColor(v); } else if (name == "progressbar_color") { if (!v.empty()) - progressbar_color = IntoColor(v); + progressbar_color = stringToColor(v); } else if (name == "progressbar_elapsed_color") { if (!v.empty()) - progressbar_elapsed_color = IntoColor(v); + progressbar_elapsed_color = stringToColor(v); } else if (name == "statusbar_color") { if (!v.empty()) - statusbar_color = IntoColor(v); + statusbar_color = stringToColor(v); } else if (name == "alternative_ui_separator_color") { if (!v.empty()) - alternative_ui_separator_color = IntoColor(v); + alternative_ui_separator_color = stringToColor(v); } else if (name == "active_column_color") { if (!v.empty()) - active_column_color = IntoColor(v); + active_column_color = stringToColor(v); } else if (name == "visualizer_color") { if (!v.empty()) - visualizer_color = IntoColor(v); + visualizer_color = stringToColor(v); } else if (name == "window_border_color") { if (!v.empty()) - window_border = IntoBorder(v); + window_border = stringToBorder(v); } else if (name == "active_window_border") { if (!v.empty()) - active_window_border = IntoBorder(v); + active_window_border = stringToBorder(v); } else if (name == "media_library_left_column") { if (!v.empty()) - media_lib_primary_tag = IntoTagItem(v[0]); + media_lib_primary_tag = charToTagType(v[0]); } else std::cout << "Unknown option: " << name << ", ignoring.\n"; @@ -1082,7 +1108,7 @@ void Configuration::GenerateColumns() while (!(width = getEnclosedString(song_list_columns_format, '(', ')', &pos)).empty()) { Column col; - col.color = IntoColor(getEnclosedString(song_list_columns_format, '[', ']', &pos)); + col.color = stringToColor(getEnclosedString(song_list_columns_format, '[', ']', &pos)); std::string tag_type = getEnclosedString(song_list_columns_format, '{', '}', &pos); col.fixed = *width.rbegin() == 'f'; @@ -1121,7 +1147,7 @@ void Configuration::GenerateColumns() else // empty column col.display_empty_tag = 0; - col.width = StrToInt(width); + col.width = stringToInt(width); columns.push_back(col); } diff --git a/src/song.cpp b/src/song.cpp index fde1619c..48612fb5 100644 --- a/src/song.cpp +++ b/src/song.cpp @@ -24,7 +24,9 @@ #include #include "song.h" -#include "conv.h" +#include "utility/numeric_conversions.h" +#include "utility/type_conversions.h" +#include "window.h" namespace {// @@ -282,12 +284,10 @@ std::string Song::ShowTime(unsigned length) length -= minutes*60; int seconds = length; - char buf[32]; if (hours > 0) - snprintf(buf, sizeof(buf), "%d:%02d:%02d", hours, minutes, seconds); + return print<32, std::string>::apply("%d:%02d:%02d", hours, minutes, seconds); else - snprintf(buf, sizeof(buf), "%d:%02d", minutes, seconds); - return buf; + return print<32, std::string>::apply("%d:%02d", minutes, seconds); } bool MPD::Song::isFormatOk(const std::string &type, const std::string &fmt) @@ -310,7 +310,7 @@ bool MPD::Song::isFormatOk(const std::string &type, const std::string &fmt) { if (isdigit(fmt[++i])) while (isdigit(fmt[++i])) { } - if (!toGetFunction(fmt[i])) + if (!charToGetFunction(fmt[i])) { std::cerr << type << ": invalid character at position " << unsignedLongIntTo::apply(i+1) << ": '" << fmt[i] << "'\n"; return false; @@ -353,7 +353,7 @@ std::string Song::ParseFormat(std::string::const_iterator &it, const std::string get = 0; } else - get = toGetFunction(*it); + get = charToGetFunction(*it); if (get) { @@ -368,9 +368,9 @@ std::string Song::ParseFormat(std::string::const_iterator &it, const std::string { if (delimiter) { - const std::basic_string &s = TO_WSTRING(tag); + /*const std::basic_string &s = TO_WSTRING(tag); if (NCurses::Window::Length(s) > delimiter) - tag = Shorten(s, delimiter); + tag = Shorten(s, delimiter);*/ } has_some_tags = 1; result += tag; diff --git a/src/song_info.h b/src/song_info.h index b9ae4eb5..ad369850 100644 --- a/src/song_info.h +++ b/src/song_info.h @@ -22,7 +22,7 @@ #define _SONG_INFO_H #include "screen.h" -#include "song.h" +#include "mutable_song.h" class SongInfo : public Screen { diff --git a/src/strbuffer.h b/src/strbuffer.h index a3ca15c1..f951664c 100644 --- a/src/strbuffer.h +++ b/src/strbuffer.h @@ -21,9 +21,8 @@ #ifndef _STRBUFFER_H #define _STRBUFFER_H -#include "numeric_conversions.h" #include "window.h" -#include "utility/string.h" +#include "utility/numeric_conversions.h" #include diff --git a/src/tag_editor.cpp b/src/tag_editor.cpp index d4cc9bb4..78492176 100644 --- a/src/tag_editor.cpp +++ b/src/tag_editor.cpp @@ -625,7 +625,7 @@ void TagEditor::EnterPressed() if (!WriteTags(**it)) { const char msg[] = "Error while writing tags in \"%s\""; - ShowMessage(msg, Shorten(TO_WSTRING((*it)->getURI()), COLS-static_strlen(msg)).c_str()); + ShowMessage(msg, Shorten(TO_WSTRING((*it)->getURI()), COLS-const_strlen(msg)).c_str()); success = 0; break; } @@ -1026,8 +1026,8 @@ bool TagEditor::WriteTags(MPD::MutableSong &s) f.tag()->setTitle(ToWString(s.getTitle())); f.tag()->setArtist(ToWString(s.getArtist())); f.tag()->setAlbum(ToWString(s.getAlbum())); - f.tag()->setYear(StrToInt(s.getDate())); - f.tag()->setTrack(StrToInt(s.getTrack())); + f.tag()->setYear(stringToInt(s.getDate())); + f.tag()->setTrack(stringToInt(s.getTrack())); f.tag()->setGenre(ToWString(s.getGenre())); f.tag()->setComment(ToWString(s.getComment())); if (TagLib::MPEG::File *mp3_file = dynamic_cast(f.file())) @@ -1219,7 +1219,7 @@ MPD::MutableSong::SetFunction TagEditor::IntoSetFunction(char c) std::string TagEditor::GenerateFilename(const MPD::MutableSong &s, const std::string &pattern) { std::string result = s.toString(pattern); - EscapeUnallowedChars(result); + removeInvalidCharsFromFilename(result); return result; } diff --git a/src/tag_editor.h b/src/tag_editor.h index 5c49b32e..6171286e 100644 --- a/src/tag_editor.h +++ b/src/tag_editor.h @@ -33,6 +33,7 @@ #include "tag.h" #include "mpdpp.h" +#include "mutable_song.h" #include "screen.h" class TagEditor : public Screen diff --git a/src/tiny_tag_editor.h b/src/tiny_tag_editor.h index 93872284..be172354 100644 --- a/src/tiny_tag_editor.h +++ b/src/tiny_tag_editor.h @@ -28,6 +28,7 @@ // taglib includes #include "tfile.h" +#include "mutable_song.h" #include "screen.h" class TinyTagEditor : public Screen< Menu > diff --git a/src/numeric_conversions.h b/src/utility/numeric_conversions.h similarity index 76% rename from src/numeric_conversions.h rename to src/utility/numeric_conversions.h index 11bff331..c2ee9673 100644 --- a/src/numeric_conversions.h +++ b/src/utility/numeric_conversions.h @@ -18,75 +18,58 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ -#include -#include #include +#include "string.h" -#ifndef _NUMERIC_CONVERSIONS_H -#define _NUMERIC_CONVERSIONS_H +#ifndef _UTILITY_NUMERIC_CONVERSIONS_H +#define _UTILITY_NUMERIC_CONVERSIONS_H template struct intTo { }; template <> struct intTo { static std::string apply(int n) { - char buf[32]; - snprintf(buf, sizeof(buf), "%d", n); - return buf; + return print<32, std::string>::apply("%d", n); } }; template <> struct intTo { static std::wstring apply(int n) { - wchar_t buf[32]; - swprintf(buf, sizeof(buf)/sizeof(wchar_t), L"%d", n); - return buf; + return print<32, std::wstring>::apply(L"%d", n); } }; template struct longIntTo { }; template <> struct longIntTo { static std::string apply(long int n) { - char buf[32]; - snprintf(buf, sizeof(buf), "%ld", n); - return buf; + return print<32, std::string>::apply("%ld", n); } }; template <> struct longIntTo { static std::wstring apply(long int n) { - wchar_t buf[32]; - swprintf(buf, sizeof(buf)/sizeof(wchar_t), L"%ld", n); - return buf; + return print<32, std::wstring>::apply(L"%ld", n); } }; template struct unsignedIntTo { }; template <> struct unsignedIntTo { static std::string apply(unsigned int n) { - char buf[32]; - snprintf(buf, sizeof(buf), "%u", n); - return buf; + return print<32, std::string>::apply("%u", n); } }; template <> struct unsignedIntTo { static std::wstring apply(unsigned int n) { - wchar_t buf[32]; - swprintf(buf, sizeof(buf)/sizeof(wchar_t), L"%u", n); - return buf; + return print<32, std::wstring>::apply(L"%u", n); } }; template struct unsignedLongIntTo { }; template <> struct unsignedLongIntTo { static std::string apply(unsigned long int n) { - char buf[32]; - snprintf(buf, sizeof(buf), "%lu", n); - return buf; + return print<32, std::string>::apply("%lu", n); } }; template <> struct unsignedLongIntTo { static std::wstring apply(unsigned long int n) { - wchar_t buf[32]; - swprintf(buf, sizeof(buf)/sizeof(wchar_t), L"%lu", n); - return buf; + return print<32, std::wstring>::apply(L"%lu", n); } }; -#endif // _NUMERIC_CONVERSIONS_H +#endif // _UTILITY_NUMERIC_CONVERSIONS_H diff --git a/src/utility/string.cpp b/src/utility/string.cpp index e6219c75..c1cd9a38 100644 --- a/src/utility/string.cpp +++ b/src/utility/string.cpp @@ -23,6 +23,52 @@ #include #include "utility/string.h" +int stringToInt(const std::string &s) +{ + return atoi(s.c_str()); +} + +long stringToLongInt(const std::string &s) +{ + return atol(s.c_str()); +} + +bool isInteger(const char *s) +{ + assert(s); + if (*s == '\0') + return false; + for (const char *it = s; *it != '\0'; ++it) + if (!isdigit(*it) && (it != s || *it != '-')) + return false; + return true; +} + +std::string ToString(const std::wstring &ws) +{ + std::string result; + char s[MB_CUR_MAX]; + for (size_t i = 0; i < ws.length(); ++i) + { + int n = wcrtomb(s, ws[i], 0); + if (n > 0) + result.append(s, n); + } + return result; +} + +std::wstring ToWString(const std::string &s) +{ + std::wstring result; + wchar_t *ws = new wchar_t[s.length()]; + const char *c_s = s.c_str(); + int n = mbsrtowcs(ws, &c_s, s.length(), 0); + if (n > 0) + result.append(ws, n); + delete [] ws; + return result; +} + std::vector split(const std::string &s, const std::string &delimiter) { if (delimiter.empty()) @@ -134,13 +180,18 @@ std::string getEnclosedString(const std::string &s, char a, char b, size_t *pos) return result; } -bool isInteger(const char *s) +void removeInvalidCharsFromFilename(std::string &filename) { - assert(s); - if (*s == '\0') - return false; - for (const char *it = s; *it != '\0'; ++it) - if (!isdigit(*it) && (it != s || *it != '-')) - return false; - return true; + const char *unallowed_chars = "\"*/:<>?\\|"; + for (const char *c = unallowed_chars; *c; ++c) + { + for (size_t i = 0; i < filename.length(); ++i) + { + if (filename[i] == *c) + { + filename.erase(filename.begin()+i); + --i; + } + } + } } diff --git a/src/utility/string.h b/src/utility/string.h index a80d0c72..94a7a783 100644 --- a/src/utility/string.h +++ b/src/utility/string.h @@ -21,8 +21,43 @@ #ifndef _UTILITY_STRING #define _UTILITY_STRING +#include #include #include +#include "gcc.h" + +template size_t const_strlen(const char (&)[N]) { + return N-1; +} + +template struct print { }; +template struct print { + static std::string apply(const char *format, ...) GNUC_PRINTF(1, 2) { + char buf[N]; + va_list args; + va_start(args, format); + vsnprintf(buf, sizeof(buf)/sizeof(char), format, args); + va_end(args); + return buf; + } +}; +template struct print { + static std::wstring apply(const wchar_t *format, ...) { + wchar_t buf[N]; + va_list args; + va_start(args, format); + vswprintf(buf, sizeof(buf)/sizeof(wchar_t), format, args); + va_end(args); + return buf; + } +}; + +int stringToInt(const std::string &s); +long stringToLongInt(const std::string &s); +bool isInteger(const char *s); + +std::string ToString(const std::wstring &ws); +std::wstring ToWString(const std::string &s); std::vector split(const std::string &s, const std::string &delimiter); void replace(std::string &s, const std::string &from, const std::string &to); @@ -38,6 +73,6 @@ std::string getSharedDirectory(const std::string &dir1, const std::string &dir2) std::string getEnclosedString(const std::string &s, char a, char b, size_t *pos); -bool isInteger(const char *s); +void removeInvalidCharsFromFilename(std::string &filename); #endif // _UTILITY_STRING diff --git a/src/utility/type_conversions.cpp b/src/utility/type_conversions.cpp new file mode 100644 index 00000000..5787f4e3 --- /dev/null +++ b/src/utility/type_conversions.cpp @@ -0,0 +1,157 @@ +/*************************************************************************** + * Copyright (C) 2008-2012 by Andrzej Rybczak * + * electricityispower@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include +#include "utility/type_conversions.h" + +std::string tagTypeToString(mpd_tag_type tag) +{ + switch (tag) + { + case MPD_TAG_ARTIST: + return "Artist"; + case MPD_TAG_ALBUM: + return "Album"; + case MPD_TAG_ALBUM_ARTIST: + return "Album Artist"; + case MPD_TAG_TITLE: + return "Title"; + case MPD_TAG_TRACK: + return "Track"; + case MPD_TAG_GENRE: + return "Genre"; + case MPD_TAG_DATE: + return "Date"; + case MPD_TAG_COMPOSER: + return "Composer"; + case MPD_TAG_PERFORMER: + return "Performer"; + case MPD_TAG_COMMENT: + return "Comment"; + case MPD_TAG_DISC: + return "Disc"; + default: + return ""; + } +} + +MPD::MutableSong::SetFunction tagTypeToSetFunction(mpd_tag_type tag) +{ + switch (tag) + { + case MPD_TAG_ARTIST: + return &MPD::MutableSong::setArtist; + case MPD_TAG_ALBUM: + return &MPD::MutableSong::setAlbum; + case MPD_TAG_ALBUM_ARTIST: + return &MPD::MutableSong::setAlbumArtist; + case MPD_TAG_TITLE: + return &MPD::MutableSong::setTitle; + case MPD_TAG_TRACK: + return &MPD::MutableSong::setTrack; + case MPD_TAG_GENRE: + return &MPD::MutableSong::setGenre; + case MPD_TAG_DATE: + return &MPD::MutableSong::setDate; + case MPD_TAG_COMPOSER: + return &MPD::MutableSong::setComposer; + case MPD_TAG_PERFORMER: + return &MPD::MutableSong::setPerformer; + case MPD_TAG_COMMENT: + return &MPD::MutableSong::setComment; + case MPD_TAG_DISC: + return &MPD::MutableSong::setDisc; + default: + return 0; + } +} + +mpd_tag_type charToTagType(char c) +{ + switch (c) + { + case 'a': + return MPD_TAG_ARTIST; + case 'A': + return MPD_TAG_ALBUM_ARTIST; + case 't': + return MPD_TAG_TITLE; + case 'b': + return MPD_TAG_ALBUM; + case 'y': + return MPD_TAG_DATE; + case 'n': + return MPD_TAG_TRACK; + case 'g': + return MPD_TAG_GENRE; + case 'c': + return MPD_TAG_COMPOSER; + case 'p': + return MPD_TAG_PERFORMER; + case 'd': + return MPD_TAG_DISC; + case 'C': + return MPD_TAG_COMMENT; + default: + assert(false); + return MPD_TAG_ARTIST; + } +} + +MPD::Song::GetFunction charToGetFunction(char c) +{ + switch (c) + { + case 'l': + return &MPD::Song::getLength; + case 'D': + return &MPD::Song::getDirectory; + case 'f': + return &MPD::Song::getName; + case 'a': + return &MPD::Song::getArtist; + case 'A': + return &MPD::Song::getAlbumArtist; + case 't': + return &MPD::Song::getTitle; + case 'b': + return &MPD::Song::getAlbum; + case 'y': + return &MPD::Song::getDate; + case 'n': + return &MPD::Song::getTrackNumber; + case 'N': + return &MPD::Song::getTrack; + case 'g': + return &MPD::Song::getGenre; + case 'c': + return &MPD::Song::getComposer; + case 'p': + return &MPD::Song::getPerformer; + case 'd': + return &MPD::Song::getDisc; + case 'C': + return &MPD::Song::getComment; + case 'P': + return &MPD::Song::getPriority; + default: + return 0; + } +} diff --git a/src/conv.h b/src/utility/type_conversions.h similarity index 64% rename from src/conv.h rename to src/utility/type_conversions.h index 39c3f1b4..631ca107 100644 --- a/src/conv.h +++ b/src/utility/type_conversions.h @@ -18,43 +18,15 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ -#ifndef _CONV_H -#define _CONV_H +#ifndef _UTILITY_TYPE_CONVERSIONS +#define _UTILITY_TYPE_CONVERSIONS -#include -#include - -#include "numeric_conversions.h" -#include "actions.h" -#include "window.h" #include "mutable_song.h" -#include "song.h" -template inline size_t static_strlen(const char (&)[N]) -{ - return N-1; -} +std::string tagTypeToString(mpd_tag_type tag); +MPD::MutableSong::SetFunction tagTypeToSetFunction(mpd_tag_type tag); -int StrToInt(const std::string &); -long StrToLong(const std::string &); - -std::string IntoStr(mpd_tag_type); -std::string IntoStr(NCurses::Color); -std::string IntoStr(const Action::Key &key, bool *print_backspace = 0); - -NCurses::Color IntoColor(const std::string &); - -mpd_tag_type IntoTagItem(char); - -MPD::Song::GetFunction toGetFunction(char c); - -#ifdef HAVE_TAGLIB_H -MPD::MutableSong::SetFunction IntoSetFunction(mpd_tag_type); -#endif // HAVE_TAGLIB_H - -std::string Shorten(const std::basic_string &s, size_t max_length); - -void EscapeUnallowedChars(std::string &); - -#endif +mpd_tag_type charToTagType(char c); +MPD::Song::GetFunction charToGetFunction(char c); +#endif // _UTILITY_TYPE_CONVERSIONS diff --git a/src/window.cpp b/src/window.cpp index 4f31b959..a379dbc7 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -29,6 +29,7 @@ #endif #include "error.h" +#include "utility/string.h" #include "window.h" using namespace NCurses; @@ -923,31 +924,6 @@ Window &Window::operator<<(size_t s) return *this; } -std::string ToString(const std::wstring &ws) -{ - std::string result; - char s[MB_CUR_MAX]; - for (size_t i = 0; i < ws.length(); ++i) - { - int n = wcrtomb(s, ws[i], 0); - if (n > 0) - result.append(s, n); - } - return result; -} - -std::wstring ToWString(const std::string &s) -{ - std::wstring result; - wchar_t *ws = new wchar_t[s.length()]; - const char *c_s = s.c_str(); - int n = mbsrtowcs(ws, &c_s, s.length(), 0); - if (n > 0) - result.append(ws, n); - delete [] ws; - return result; -} - size_t Window::Length(const std::wstring &ws) { # ifdef WIN32 diff --git a/src/window.h b/src/window.h index aa6779fc..93d1e3ea 100644 --- a/src/window.h +++ b/src/window.h @@ -117,18 +117,6 @@ # define wcwidth(x) int(!iscntrl(x)) #endif -/// Converts wide string to narrow string -/// @param ws wide string -/// @return narrow string -/// -std::string ToString(const std::wstring &ws); - -/// Converts narrow string to wide string -/// @param s narrow string -/// @return wide string -/// -std::wstring ToWString(const std::string &s); - /// NCurses namespace provides set of easy-to-use /// wrappers over original curses library ///