diff --git a/src/display.cpp b/src/display.cpp index f2099f43..ef9a34d2 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -221,12 +221,17 @@ void Display::Songs(const MPD::Song &s, void *data, Menu *menu) if (is_now_playing) *menu << Config.now_playing_prefix; - std::string line = s.toString(*static_cast(data)); + std::string line = s.toString(*static_cast(data), "$"); for (std::string::const_iterator it = line.begin(); it != line.end(); ++it) { if (*it == '$') { - if (isdigit(*++it)) + if (++it == line.end()) // end of format + { + *menu << '$'; + break; + } + else if (isdigit(*it)) // color { *menu << Color(*it-'0'); } @@ -240,8 +245,15 @@ void Display::Songs(const MPD::Song &s, void *data, Menu *menu) *menu << XY(menu->GetWidth()-buf.Str().length(), menu->Y()) << buf; return; } - else - *menu << *it; + else // not a color nor right align, just a random character + *menu << *--it; + } + else if (*it == MPD::Song::FormatEscapeCharacter) + { + // treat '$' as a normal character if song format escape char is prepended to it + if (++it == line.end() || *it != '$') + --it; + *menu << *it; } else *menu << *it; diff --git a/src/helpers.h b/src/helpers.h index ef5e7ceb..e44e375c 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -92,48 +92,73 @@ template void String2Buffer(const std::basic_string &s, basic_bu { for (typename std::basic_string::const_iterator it = s.begin(); it != s.end(); ++it) { - if (*it != '$') - buf << *it; - else if (isdigit(*++it)) - buf << Color(*it-'0'); - else + if (*it == '$') { - switch (*it) + if (++it == s.end()) { - case 'b': - buf << fmtBold; - break; - case 'u': - buf << fmtUnderline; - break; - case 'a': - buf << fmtAltCharset; - break; - case 'r': - buf << fmtReverse; - break; - case '/': - switch (*++it) - { - case 'b': - buf << fmtBoldEnd; + buf << '$'; + break; + } + else if (isdigit(*it)) + { + buf << Color(*it-'0'); + } + else + { + switch (*it) + { + case 'b': + buf << fmtBold; + break; + case 'u': + buf << fmtUnderline; + break; + case 'a': + buf << fmtAltCharset; + break; + case 'r': + buf << fmtReverse; + break; + case '/': + if (++it == s.end()) + { + buf << "$/"; break; - case 'u': - buf << fmtUnderlineEnd; - break; - case 'a': - buf << fmtAltCharsetEnd; - break; - case 'r': - buf << fmtReverseEnd; - break; - } - break; - default: - buf << *it; - break; + } + switch (*it) + { + case 'b': + buf << fmtBoldEnd; + break; + case 'u': + buf << fmtUnderlineEnd; + break; + case 'a': + buf << fmtAltCharsetEnd; + break; + case 'r': + buf << fmtReverseEnd; + break; + default: + buf << '$' << *--it; + break; + } + break; + default: + buf << *--it; + break; + } } } + else if (*it == MPD::Song::FormatEscapeCharacter) + { + // treat '$' as a normal character if song format escape char is prepended to it + if (++it == s.end() || *it != '$') + --it; + buf << *it; + } + else + buf << *it; } } diff --git a/src/song.cpp b/src/song.cpp index 2ad8d45b..2849bcb4 100644 --- a/src/song.cpp +++ b/src/song.cpp @@ -305,7 +305,7 @@ void MPD::Song::SetPosition(int pos) itsSong->pos = pos; } -std::string MPD::Song::ParseFormat(std::string::const_iterator &it) const +std::string MPD::Song::ParseFormat(std::string::const_iterator &it, const char *escape_chars) const { std::string result; bool has_some_tags = 0; @@ -314,7 +314,7 @@ std::string MPD::Song::ParseFormat(std::string::const_iterator &it) const { while (*it == '{') { - std::string tags = ParseFormat(it); + std::string tags = ParseFormat(it, escape_chars); if (!tags.empty()) { has_some_tags = 1; @@ -379,6 +379,10 @@ std::string MPD::Song::ParseFormat(std::string::const_iterator &it) const if (get) { std::string tag = (this->*get)(); + if (escape_chars) // prepend format escape character to all given chars to escape + for (const char *ch = escape_chars; *ch; ++ch) + for (size_t i = tag.find(*ch); i != std::string::npos; i = tag.find(*ch, i += 2)) + tag.replace(i, 1, std::string(1, FormatEscapeCharacter) + ch); if (!tag.empty() && (get != &MPD::Song::GetLength || GetTotalLength())) { has_some_tags = 1; @@ -402,7 +406,7 @@ std::string MPD::Song::ParseFormat(std::string::const_iterator &it) const --brace_counter; } if (*++it == '|') - return ParseFormat(++it); + return ParseFormat(++it, escape_chars); else return ""; } @@ -423,10 +427,10 @@ std::string MPD::Song::ParseFormat(std::string::const_iterator &it) const } } -std::string MPD::Song::toString(const std::string &format) const +std::string MPD::Song::toString(const std::string &format, const char *escape_chars) const { std::string::const_iterator it = format.begin(); - return ParseFormat(it); + return ParseFormat(it, escape_chars); } MPD::Song &MPD::Song::operator=(const MPD::Song &s) diff --git a/src/song.h b/src/song.h index 0f81e298..bf07d6e7 100644 --- a/src/song.h +++ b/src/song.h @@ -78,7 +78,8 @@ namespace MPD void SetNewName(const std::string &name) { itsNewName = name == GetName() ? "" : name; } std::string GetNewName() const { return itsNewName; } - std::string toString(const std::string &) const; + std::string toString(const std::string &, const char *escape_chars = 0) const; + static const char FormatEscapeCharacter = 1; void NullMe() { itsSong = 0; } void CopyPtr(bool copy) { copyPtr = copy; } @@ -97,7 +98,7 @@ namespace MPD private: void SetHashAndSlash(); - std::string ParseFormat(std::string::const_iterator &it) const; + std::string ParseFormat(std::string::const_iterator &it, const char *escape_chars) const; mpd_Song *itsSong; std::string itsNewName;