initial restoration of support for encodings different than utf-8

This commit is contained in:
Andrzej Rybczak
2012-10-05 20:50:14 +02:00
parent e40edade0e
commit 044464962c
16 changed files with 135 additions and 110 deletions

View File

@@ -18,12 +18,32 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include <boost/locale/encoding.hpp>
#include <boost/locale.hpp>
#include "charset.h"
#include "settings.h"
namespace Charset {//
std::locale internalLocale()
{
boost::locale::generator gen;
std::locale loc = gen("");
bool is_utf = std::use_facet<boost::locale::info>(loc).utf8();
std::string name = std::use_facet<boost::locale::info>(loc).name();
if (!is_utf && name != "C" && name != "POSIX")
{
// if current locale does not use unicode, use variant of this
// locale with utf8 as ncmpcpp uses utf8 internally and we need
// current locale for sorting, case conversions etc.
std::string new_name = std::use_facet<boost::locale::info>(loc).language()
+ "_"
+ std::use_facet<boost::locale::info>(loc).country()
+ ".UTF-8";
loc = gen(new_name);
}
return loc;
}
std::string toUtf8From(std::string s, const char *charset)
{
return boost::locale::conv::to_utf<char>(s, charset);
@@ -37,15 +57,15 @@ std::string fromUtf8To(std::string s, const char *charset)
std::string utf8ToLocale(std::string s)
{
return Config.system_encoding.empty()
? s
: boost::locale::conv::from_utf<char>(s, Config.system_encoding);
? s
: boost::locale::conv::from_utf<char>(s, Config.system_encoding);
}
std::string localeToUtf8(std::string s)
{
return Config.system_encoding.empty()
? s
: boost::locale::conv::to_utf<char>(s, Config.system_encoding);
? s
: boost::locale::conv::to_utf<char>(s, Config.system_encoding);
}
}

View File

@@ -21,10 +21,13 @@
#ifndef NCMPCPP_CHARSET_H
#define NCMPCPP_CHARSET_H
#include <locale>
#include <string>
namespace Charset {//
std::locale internalLocale();
std::string toUtf8From(std::string s, const char *charset);
std::string fromUtf8To(std::string s, const char *charset);

View File

@@ -21,6 +21,7 @@
#include <cassert>
#include "browser.h"
#include "charset.h"
#include "display.h"
#include "helpers.h"
#include "song_info.h"
@@ -108,7 +109,7 @@ void showSongs(NC::Menu<T> &menu, const MPD::Song &s, const ProxySongList &pl, c
setProperties(menu, s, pl, separate_albums, is_now_playing, is_selected, discard_colors);
size_t y = menu.getY();
std::string line = s.toString(format, Config.tags_separator, "$");
std::string line = Charset::utf8ToLocale(s.toString(format, Config.tags_separator, "$"));
for (auto it = line.begin(); it != line.end(); ++it)
{
if (*it == '$')
@@ -222,7 +223,8 @@ void showSongsInColumns(NC::Menu<T> &menu, const MPD::Song &s, const ProxySongLi
for (size_t i = 0; i < it->type.length(); ++i)
{
MPD::Song::GetFunction get = charToGetFunction(it->type[i]);
tag = ToWString(get ? s.getTags(get, Config.tags_separator) : "");
assert(get);
tag = ToWString(Charset::utf8ToLocale(s.getTags(get, Config.tags_separator)));
if (!tag.empty())
break;
}
@@ -326,11 +328,11 @@ std::string Display::Columns(size_t list_width)
if (it->right_alignment)
{
result += std::string(x_off, KEY_SPACE);
result += ToString(name);
result += Charset::utf8ToLocale(ToString(name));
}
else
{
result += ToString(name);
result += Charset::utf8ToLocale(ToString(name));
result += std::string(x_off, KEY_SPACE);
}
@@ -364,30 +366,29 @@ void Display::Tags(NC::Menu<MPD::MutableSong> &menu)
size_t i = myTagEditor->TagTypes->choice();
if (i < 11)
{
ShowTag(menu, s.getTags(SongInfo::Tags[i].Get, Config.tags_separator));
ShowTag(menu, Charset::utf8ToLocale(s.getTags(SongInfo::Tags[i].Get, Config.tags_separator)));
}
else if (i == 12)
{
if (s.getNewURI().empty())
menu << s.getName();
menu << Charset::utf8ToLocale(s.getName());
else
menu << s.getName() << Config.color2 << " -> " << NC::clEnd << s.getNewURI();
menu << Charset::utf8ToLocale(s.getName())
<< Config.color2 << " -> " << NC::clEnd
<< Charset::utf8ToLocale(s.getNewURI());
}
}
#endif // HAVE_TAGLIB_H
void Display::Outputs(NC::Menu<MPD::Output> &menu)
{
menu << menu.drawn()->value().name();
}
void Display::Items(NC::Menu<MPD::Item> &menu, const ProxySongList &pl)
{
const MPD::Item &item = menu.drawn()->value();
switch (item.type)
{
case MPD::itDirectory:
menu << "[" << getBasename(item.name) << "]";
menu << "["
<< Charset::utf8ToLocale(getBasename(item.name))
<< "]";
break;
case MPD::itSong:
if (!Config.columns_in_browser)
@@ -396,12 +397,13 @@ void Display::Items(NC::Menu<MPD::Item> &menu, const ProxySongList &pl)
showSongsInColumns(menu, *item.song, pl);
break;
case MPD::itPlaylist:
menu << Config.browser_playlist_prefix << getBasename(item.name);
menu << Config.browser_playlist_prefix
<< Charset::utf8ToLocale(getBasename(item.name));
break;
}
}
void Display::SearchEngine(NC::Menu<SEItem> &menu, const ProxySongList &pl)
void Display::SEItems(NC::Menu<SEItem> &menu, const ProxySongList &pl)
{
const SEItem &si = menu.drawn()->value();
if (si.isSong())

View File

@@ -30,21 +30,13 @@ namespace Display {//
std::string Columns(size_t);
template <typename ItemT>
void Default(NC::Menu<ItemT> &menu) { menu << menu.drawn()->value(); }
template <typename A, typename B>
void Pair(NC::Menu< std::pair<A, B> > &menu) { menu << menu.drawn()->value().first; }
void SongsInColumns(NC::Menu<MPD::Song> &menu, const ProxySongList &pl);
void Songs(NC::Menu<MPD::Song> &menu, const ProxySongList &pl, const std::string &format);
void Tags(NC::Menu<MPD::MutableSong> &menu);
void Outputs(NC::Menu<MPD::Output> &menu);
void SearchEngine(NC::Menu<SEItem> &menu, const ProxySongList &pl);
void SEItems(NC::Menu<SEItem> &menu, const ProxySongList &pl);
void Items(NC::Menu<MPD::Item> &menu, const ProxySongList &pl);

View File

@@ -473,7 +473,7 @@ template <typename T> void ShowTime(T &buf, size_t length, bool short_names)
buf << length << cnv(short_names ? "s" : (length == 1 ? " second" : " seconds"));
}
template <typename T> void ShowTag(T &buf, const std::string &tag)
template <typename BufferT> void ShowTag(BufferT &buf, const std::string &tag)
{
if (tag.empty())
buf << Config.empty_tags_color << Config.empty_tag << NC::clEnd;

View File

@@ -64,9 +64,6 @@ bool TagEntryMatcher(const Regex &rx, const MediaLibrary::PrimaryTag &tagmtime);
bool AlbumEntryMatcher(const Regex &rx, const NC::Menu<AlbumEntry>::Item &item, bool filter);
bool SongEntryMatcher(const Regex &rx, const MPD::Song &s);
void DisplayAlbums(NC::Menu<AlbumEntry> &menu);
void DisplayPrimaryTags(NC::Menu<MediaLibrary::PrimaryTag> &menu);
struct SortSongs {
static const std::array<MPD::Song::GetFunction, 3> GetFuns;
@@ -156,7 +153,13 @@ MediaLibrary::MediaLibrary()
Tags.centeredCursor(Config.centered_cursor);
Tags.setSelectedPrefix(Config.selected_item_prefix);
Tags.setSelectedSuffix(Config.selected_item_suffix);
Tags.setItemDisplayer(DisplayPrimaryTags);
Tags.setItemDisplayer([](NC::Menu<PrimaryTag> &menu) {
const std::string &tag = menu.drawn()->value().tag();
if (tag.empty())
menu << Config.empty_tag;
else
menu << Charset::utf8ToLocale(tag);
});
Albums = NC::Menu<AlbumEntry>(itsMiddleColStartX, MainStartY, itsMiddleColWidth, MainHeight, Config.titles_visibility ? "Albums" : "", Config.main_color, NC::brNone);
Albums.setHighlightColor(Config.main_highlight_color);
@@ -164,7 +167,9 @@ MediaLibrary::MediaLibrary()
Albums.centeredCursor(Config.centered_cursor);
Albums.setSelectedPrefix(Config.selected_item_prefix);
Albums.setSelectedSuffix(Config.selected_item_suffix);
Albums.setItemDisplayer(DisplayAlbums);
Albums.setItemDisplayer([](NC::Menu<AlbumEntry> &menu) {
menu << Charset::utf8ToLocale(AlbumToString(menu.drawn()->value()));
});
Songs = NC::Menu<MPD::Song>(itsRightColStartX, MainStartY, itsRightColWidth, MainHeight, Config.titles_visibility ? "Songs" : "", Config.main_color, NC::brNone);
Songs.setHighlightColor(Config.main_highlight_color);
@@ -1033,20 +1038,4 @@ bool SongEntryMatcher(const Regex &rx, const MPD::Song &s)
return rx.match(SongToString(s));
}
/***********************************************************************/
void DisplayAlbums(NC::Menu<AlbumEntry> &menu)
{
menu << AlbumToString(menu.drawn()->value());
}
void DisplayPrimaryTags(NC::Menu<MediaLibrary::PrimaryTag> &menu)
{
const std::string &tag = menu.drawn()->value().tag();
if (tag.empty())
menu << Config.empty_tag;
else
menu << tag;
}
}

View File

@@ -24,6 +24,7 @@
#include <cstring>
#include <sys/time.h>
#include <boost/locale.hpp>
#include <iostream>
#include <fstream>
#include <stdexcept>
@@ -33,6 +34,7 @@
#include "actions.h"
#include "bindings.h"
#include "browser.h"
#include "charset.h"
#include "cmdargs.h"
#include "global.h"
#include "helpers.h"
@@ -91,7 +93,7 @@ int main(int argc, char **argv)
std::srand(std::time(0));
std::setlocale(LC_ALL, "");
std::locale::global(std::locale(""));
std::locale::global(Charset::internalLocale());
Config.CheckForCommandLineConfigFilePath(argv, argc);

View File

@@ -22,6 +22,7 @@
#ifdef ENABLE_OUTPUTS
#include "charset.h"
#include "display.h"
#include "global.h"
#include "settings.h"
@@ -42,7 +43,9 @@ Outputs::Outputs()
w.cyclicScrolling(Config.use_cyclic_scrolling);
w.centeredCursor(Config.centered_cursor);
w.setHighlightColor(Config.main_highlight_color);
w.setItemDisplayer(Display::Outputs);
w.setItemDisplayer([](NC::Menu<MPD::Output> &menu) {
menu << Charset::utf8ToLocale(menu.drawn()->value().name());
});
FetchList();
}

View File

@@ -68,7 +68,9 @@ PlaylistEditor::PlaylistEditor()
Playlists.centeredCursor(Config.centered_cursor);
Playlists.setSelectedPrefix(Config.selected_item_prefix);
Playlists.setSelectedSuffix(Config.selected_item_suffix);
Playlists.setItemDisplayer(Display::Default<std::string>);
Playlists.setItemDisplayer([](NC::Menu<std::string> &menu) {
menu << Charset::utf8ToLocale(menu.drawn()->value());
});
Content = NC::Menu<MPD::Song>(RightColumnStartX, MainStartY, RightColumnWidth, MainHeight, Config.titles_visibility ? "Playlist content" : "", Config.main_color, NC::brNone);
Content.setHighlightColor(Config.main_highlight_color);

View File

@@ -108,7 +108,7 @@ SearchEngine::SearchEngine()
w.setHighlightColor(Config.main_highlight_color);
w.cyclicScrolling(Config.use_cyclic_scrolling);
w.centeredCursor(Config.centered_cursor);
w.setItemDisplayer(std::bind(Display::SearchEngine, _1, proxySongList()));
w.setItemDisplayer(std::bind(Display::SEItems, _1, proxySongList()));
w.setSelectedPrefix(Config.selected_item_prefix);
w.setSelectedSuffix(Config.selected_item_suffix);
SearchMode = &SearchModes[Config.search_engine_default_search_mode];

View File

@@ -27,53 +27,7 @@
#include "mpdpp.h"
#include "screen.h"
struct SEItem
{
SEItem() : isThisSong(false), itsBuffer(0) { }
SEItem(NC::Buffer *buf) : isThisSong(false), itsBuffer(buf) { }
SEItem(const MPD::Song &s) : isThisSong(true), itsSong(s) { }
SEItem(const SEItem &ei) { *this = ei; }
~SEItem() {
if (!isThisSong)
delete itsBuffer;
}
NC::Buffer &mkBuffer() {
assert(!isThisSong);
delete itsBuffer;
itsBuffer = new NC::Buffer();
return *itsBuffer;
}
bool isSong() const { return isThisSong; }
NC::Buffer &buffer() { assert(!isThisSong && itsBuffer); return *itsBuffer; }
MPD::Song &song() { assert(isThisSong); return itsSong; }
const NC::Buffer &buffer() const { assert(!isThisSong && itsBuffer); return *itsBuffer; }
const MPD::Song &song() const { assert(isThisSong); return itsSong; }
SEItem &operator=(const SEItem &se) {
if (this == &se)
return *this;
isThisSong = se.isThisSong;
if (se.isThisSong)
itsSong = se.itsSong;
else if (se.itsBuffer)
itsBuffer = new NC::Buffer(*se.itsBuffer);
else
itsBuffer = 0;
return *this;
}
private:
bool isThisSong;
NC::Buffer *itsBuffer;
MPD::Song itsSong;
};
struct SearchEngine: Screen<NC::Menu<SEItem>>, Filterable, HasSongs, Searchable, Tabbable
struct SearchEngine: Screen<NC::Menu<struct SEItem>>, Filterable, HasSongs, Searchable, Tabbable
{
SearchEngine();
@@ -135,6 +89,52 @@ private:
static bool MatchToPattern;
};
struct SEItem
{
SEItem() : m_is_song(false), m_buffer(0) { }
SEItem(NC::Buffer *buf) : m_is_song(false), m_buffer(buf) { }
SEItem(const MPD::Song &s) : m_is_song(true), m_song(s) { }
SEItem(const SEItem &ei) { *this = ei; }
~SEItem() {
if (!m_is_song)
delete m_buffer;
}
NC::Buffer &mkBuffer() {
assert(!m_is_song);
delete m_buffer;
m_buffer = new NC::Buffer();
return *m_buffer;
}
bool isSong() const { return m_is_song; }
NC::Buffer &buffer() { assert(!m_is_song && m_buffer); return *m_buffer; }
MPD::Song &song() { assert(m_is_song); return m_song; }
const NC::Buffer &buffer() const { assert(!m_is_song && m_buffer); return *m_buffer; }
const MPD::Song &song() const { assert(m_is_song); return m_song; }
SEItem &operator=(const SEItem &se) {
if (this == &se)
return *this;
m_is_song = se.m_is_song;
if (se.m_is_song)
m_song = se.m_song;
else if (se.m_buffer)
m_buffer = new NC::Buffer(*se.m_buffer);
else
m_buffer = 0;
return *this;
}
private:
bool m_is_song;
NC::Buffer *m_buffer;
MPD::Song m_song;
};
extern SearchEngine *mySearcher;
#endif // NCMPCPP_SEARCH_ENGINE_H

View File

@@ -30,6 +30,7 @@
#include "statusbar.h"
#include "utility/comparators.h"
#include "screen_switcher.h"
#include "charset.h"
SelectedItemsAdder *mySelectedItemsAdder;
@@ -37,7 +38,7 @@ namespace {//
void DisplayComponent(SelectedItemsAdder::Component &menu)
{
menu << menu.drawn()->value().item();
menu << Charset::utf8ToLocale(menu.drawn()->value().item());
}
}

View File

@@ -18,6 +18,7 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include "charset.h"
#include "display.h"
#include "global.h"
#include "helpers.h"
@@ -43,7 +44,7 @@ SortPlaylistDialog::SortPlaylistDialog()
w.cyclicScrolling(Config.use_cyclic_scrolling);
w.centeredCursor(Config.centered_cursor);
w.setItemDisplayer([](Self::WindowType &menu) {
menu << menu.drawn()->value().item().first;
menu << Charset::utf8ToLocale(menu.drawn()->value().item().first);
});
w.addItem(Entry(std::make_pair("Artist", &MPD::Song::getArtist),

View File

@@ -94,13 +94,17 @@ TagEditor::TagEditor() : FParser(0), FParserHelper(0), FParserLegend(0), FParser
Dirs->setHighlightColor(Config.active_column_color);
Dirs->cyclicScrolling(Config.use_cyclic_scrolling);
Dirs->centeredCursor(Config.centered_cursor);
Dirs->setItemDisplayer(Display::Pair<std::string, std::string>);
Dirs->setItemDisplayer([](NC::Menu<std::pair<std::string, std::string>> &menu) {
menu << Charset::utf8ToLocale(menu.drawn()->value().first);
});
TagTypes = new NC::Menu<std::string>(MiddleColumnStartX, MainStartY, MiddleColumnWidth, MainHeight, Config.titles_visibility ? "Tag types" : "", Config.main_color, NC::brNone);
TagTypes->setHighlightColor(Config.main_highlight_color);
TagTypes->cyclicScrolling(Config.use_cyclic_scrolling);
TagTypes->centeredCursor(Config.centered_cursor);
TagTypes->setItemDisplayer(Display::Default<std::string>);
TagTypes->setItemDisplayer([](NC::Menu<std::string> &menu) {
menu << Charset::utf8ToLocale(menu.drawn()->value());
});
for (const SongInfo::Metadata *m = SongInfo::Tags; m->Name; ++m)
TagTypes->addItem(m->Name);
@@ -124,10 +128,14 @@ TagEditor::TagEditor() : FParser(0), FParserHelper(0), FParserLegend(0), FParser
Tags->setSelectedSuffix(Config.selected_item_suffix);
Tags->setItemDisplayer(Display::Tags);
auto parser_display = [](NC::Menu<std::string> &menu) {
menu << Charset::utf8ToLocale(menu.drawn()->value());
};
FParserDialog = new NC::Menu<std::string>((COLS-FParserDialogWidth)/2, (MainHeight-FParserDialogHeight)/2+MainStartY, FParserDialogWidth, FParserDialogHeight, "", Config.main_color, Config.window_border);
FParserDialog->cyclicScrolling(Config.use_cyclic_scrolling);
FParserDialog->centeredCursor(Config.centered_cursor);
FParserDialog->setItemDisplayer(Display::Default<std::string>);
FParserDialog->setItemDisplayer(parser_display);
FParserDialog->addItem("Get tags from filename");
FParserDialog->addItem("Rename files");
FParserDialog->addSeparator();
@@ -136,7 +144,7 @@ TagEditor::TagEditor() : FParser(0), FParserHelper(0), FParserLegend(0), FParser
FParser = new NC::Menu<std::string>((COLS-FParserWidth)/2, (MainHeight-FParserHeight)/2+MainStartY, FParserWidthOne, FParserHeight, "_", Config.main_color, Config.active_window_border);
FParser->cyclicScrolling(Config.use_cyclic_scrolling);
FParser->centeredCursor(Config.centered_cursor);
FParser->setItemDisplayer(Display::Default<std::string>);
FParser->setItemDisplayer(parser_display);
FParserLegend = new NC::Scrollpad((COLS-FParserWidth)/2+FParserWidthOne, (MainHeight-FParserHeight)/2+MainStartY, FParserWidthTwo, FParserHeight, "Legend", Config.main_color, Config.window_border);

View File

@@ -51,7 +51,9 @@ TinyTagEditor::TinyTagEditor()
w.setHighlightColor(Config.main_highlight_color);
w.cyclicScrolling(Config.use_cyclic_scrolling);
w.centeredCursor(Config.centered_cursor);
w.setItemDisplayer(Display::Default<NC::Buffer>);
w.setItemDisplayer([](NC::Menu<NC::Buffer> &menu) {
menu << menu.drawn()->value();
});
}
void TinyTagEditor::resize()

View File

@@ -46,7 +46,7 @@ int LocaleStringComparison::operator()(const std::string &a, const std::string &
if (hasTheWord(b))
bc_off += 4;
}
return std::use_facet< std::collate<char> >(m_locale).compare(
return std::use_facet<std::collate<char>>(m_locale).compare(
ac+ac_off, ac+a.length(), bc+bc_off, bc+b.length()
);
}