move wstring related functions to wide_char file

This commit is contained in:
Andrzej Rybczak
2012-09-08 18:42:59 +02:00
parent d5e2d315fd
commit 84326efc46
23 changed files with 204 additions and 151 deletions

View File

@@ -4,6 +4,7 @@ ncmpcpp_SOURCES = \
utility/html.cpp \ utility/html.cpp \
utility/string.cpp \ utility/string.cpp \
utility/type_conversions.cpp \ utility/type_conversions.cpp \
utility/wide_string.cpp \
actions.cpp \ actions.cpp \
bindings.cpp \ bindings.cpp \
browser.cpp \ browser.cpp \
@@ -52,6 +53,7 @@ noinst_HEADERS = \
utility/string.h \ utility/string.h \
utility/numeric_conversions.h \ utility/numeric_conversions.h \
utility/type_conversions.h \ utility/type_conversions.h \
utility/wide_string.h \
bindings.h \ bindings.h \
browser.h \ browser.h \
charset.h \ charset.h \

View File

@@ -800,7 +800,7 @@ void Delete::Run()
question = "Delete "; question = "Delete ";
question += itemTypeToString(item.type); question += itemTypeToString(item.type);
question += " \""; question += " \"";
question += Shorten(ToWString(name), COLS-question.size()-10); question += ToString(wideShorten(ToWString(name), COLS-question.size()-10));
question += "\"?"; question += "\"?";
} }
bool yes = AskYesNoQuestion(question, TraceMpdStatus); bool yes = AskYesNoQuestion(question, TraceMpdStatus);
@@ -814,13 +814,13 @@ void Delete::Run()
std::string name = i.type == MPD::itSong ? i.song->getName() : i.name; std::string name = i.type == MPD::itSong ? i.song->getName() : i.name;
if (myBrowser->deleteItem(i)) if (myBrowser->deleteItem(i))
{ {
const char msg[] = "\"%s\" deleted"; const char msg[] = "\"%ls\" deleted";
ShowMessage(msg, Shorten(ToWString(name), COLS-const_strlen(msg)).c_str()); ShowMessage(msg, wideShorten(ToWString(name), COLS-const_strlen(msg)).c_str());
} }
else else
{ {
const char msg[] = "Couldn't delete \"%s\": %s"; const char msg[] = "Couldn't delete \"%ls\": %s";
ShowMessage(msg, Shorten(ToWString(name), COLS-const_strlen(msg)-25).c_str(), strerror(errno)); ShowMessage(msg, wideShorten(ToWString(name), COLS-const_strlen(msg)-25).c_str(), strerror(errno));
success = false; success = false;
break; break;
} }
@@ -845,7 +845,7 @@ void Delete::Run()
else else
{ {
question = "Delete playlist \""; question = "Delete playlist \"";
question += Shorten(ToWString(myPlaylistEditor->Playlists->current().value()), COLS-question.size()-10); question += ToString(wideShorten(ToWString(myPlaylistEditor->Playlists->current().value()), COLS-question.size()-10));
question += "\"?"; question += "\"?";
} }
bool yes = AskYesNoQuestion(question, TraceMpdStatus); bool yes = AskYesNoQuestion(question, TraceMpdStatus);
@@ -1384,8 +1384,8 @@ void EditLibraryTag::Run()
std::string path = Config.mpd_music_dir + es.getURI(); std::string path = Config.mpd_music_dir + es.getURI();
if (!TagEditor::WriteTags(es)) if (!TagEditor::WriteTags(es))
{ {
const char msg[] = "Error while updating tags in \"%s\""; const char msg[] = "Error while updating tags in \"%ls\"";
ShowMessage(msg, Shorten(ToWString(es.getURI()), COLS-const_strlen(msg)).c_str()); ShowMessage(msg, wideShorten(ToWString(es.getURI()), COLS-const_strlen(msg)).c_str());
success = false; success = false;
break; break;
} }
@@ -1430,16 +1430,16 @@ void EditLibraryAlbum::Run()
TagLib::FileRef f(path.c_str()); TagLib::FileRef f(path.c_str());
if (f.isNull()) if (f.isNull())
{ {
const char msg[] = "Error while opening file \"%s\""; const char msg[] = "Error while opening file \"%ls\"";
ShowMessage(msg, Shorten(ToWString((*myLibrary->Songs)[i].value().getURI()), COLS-const_strlen(msg)).c_str()); ShowMessage(msg, wideShorten(ToWString((*myLibrary->Songs)[i].value().getURI()), COLS-const_strlen(msg)).c_str());
success = 0; success = 0;
break; break;
} }
f.tag()->setAlbum(ToWString(new_album)); f.tag()->setAlbum(ToWString(new_album));
if (!f.save()) if (!f.save())
{ {
const char msg[] = "Error while writing tags in \"%s\""; const char msg[] = "Error while writing tags in \"%ls\"";
ShowMessage(msg, Shorten(ToWString((*myLibrary->Songs)[i].value().getURI()), COLS-const_strlen(msg)).c_str()); ShowMessage(msg, wideShorten(ToWString((*myLibrary->Songs)[i].value().getURI()), COLS-const_strlen(msg)).c_str());
success = 0; success = 0;
break; break;
} }
@@ -1491,16 +1491,16 @@ void EditDirectoryName::Run()
int rename_result = rename(full_old_dir.c_str(), full_new_dir.c_str()); int rename_result = rename(full_old_dir.c_str(), full_new_dir.c_str());
if (rename_result == 0) if (rename_result == 0)
{ {
const char msg[] = "Directory renamed to \"%s\""; const char msg[] = "Directory renamed to \"%ls\"";
ShowMessage(msg, Shorten(ToWString(new_dir), COLS-const_strlen(msg)).c_str()); ShowMessage(msg, wideShorten(ToWString(new_dir), COLS-const_strlen(msg)).c_str());
if (!myBrowser->isLocal()) if (!myBrowser->isLocal())
Mpd.UpdateDirectory(locale_to_utf_cpy(getSharedDirectory(old_dir, new_dir))); Mpd.UpdateDirectory(locale_to_utf_cpy(getSharedDirectory(old_dir, new_dir)));
myBrowser->GetDirectory(myBrowser->CurrentDir()); myBrowser->GetDirectory(myBrowser->CurrentDir());
} }
else else
{ {
const char msg[] = "Couldn't rename \"%s\": %s"; const char msg[] = "Couldn't rename \"%ls\": %s";
ShowMessage(msg, Shorten(ToWString(old_dir), COLS-const_strlen(msg)-25).c_str(), strerror(errno)); ShowMessage(msg, wideShorten(ToWString(old_dir), COLS-const_strlen(msg)-25).c_str(), strerror(errno));
} }
} }
} }
@@ -1518,14 +1518,14 @@ void EditDirectoryName::Run()
std::string full_new_dir = Config.mpd_music_dir + myTagEditor->CurrentDir() + "/" + locale_to_utf_cpy(new_dir); std::string full_new_dir = Config.mpd_music_dir + myTagEditor->CurrentDir() + "/" + locale_to_utf_cpy(new_dir);
if (rename(full_old_dir.c_str(), full_new_dir.c_str()) == 0) if (rename(full_old_dir.c_str(), full_new_dir.c_str()) == 0)
{ {
const char msg[] = "Directory renamed to \"%s\""; const char msg[] = "Directory renamed to \"%ls\"";
ShowMessage(msg, Shorten(ToWString(new_dir), COLS-const_strlen(msg)).c_str()); ShowMessage(msg, wideShorten(ToWString(new_dir), COLS-const_strlen(msg)).c_str());
Mpd.UpdateDirectory(myTagEditor->CurrentDir()); Mpd.UpdateDirectory(myTagEditor->CurrentDir());
} }
else else
{ {
const char msg[] = "Couldn't rename \"%s\": %s"; const char msg[] = "Couldn't rename \"%ls\": %s";
ShowMessage(msg, Shorten(ToWString(old_dir), COLS-const_strlen(msg)-25).c_str(), strerror(errno)); ShowMessage(msg, wideShorten(ToWString(old_dir), COLS-const_strlen(msg)-25).c_str(), strerror(errno));
} }
} }
} }
@@ -1558,8 +1558,8 @@ void EditPlaylistName::Run()
{ {
if (Mpd.Rename(locale_to_utf_cpy(old_name), locale_to_utf_cpy(new_name))) if (Mpd.Rename(locale_to_utf_cpy(old_name), locale_to_utf_cpy(new_name)))
{ {
const char msg[] = "Playlist renamed to \"%s\""; const char msg[] = "Playlist renamed to \"%ls\"";
ShowMessage(msg, Shorten(ToWString(new_name), COLS-const_strlen(msg)).c_str()); ShowMessage(msg, wideShorten(ToWString(new_name), COLS-const_strlen(msg)).c_str());
if (myBrowser->Main() && !myBrowser->isLocal()) if (myBrowser->Main() && !myBrowser->isLocal())
myBrowser->GetDirectory("/"); myBrowser->GetDirectory("/");
if (myPlaylistEditor->Main()) if (myPlaylistEditor->Main())

View File

@@ -23,6 +23,7 @@
#include "global.h" #include "global.h"
#include "bindings.h" #include "bindings.h"
#include "utility/string.h" #include "utility/string.h"
#include "utility/wide_string.h"
BindingsConfiguration Bindings; BindingsConfiguration Bindings;

View File

@@ -549,13 +549,13 @@ void Browser::ClearDirectory(const std::string &path) const
ClearDirectory(full_path); ClearDirectory(full_path);
if (remove(full_path.c_str()) == 0) if (remove(full_path.c_str()) == 0)
{ {
const char msg[] = "Deleting \"%s\"..."; const char msg[] = "Deleting \"%ls\"...";
ShowMessage(msg, Shorten(ToWString(full_path), COLS-const_strlen(msg)).c_str()); ShowMessage(msg, wideShorten(ToWString(full_path), COLS-const_strlen(msg)).c_str());
} }
else else
{ {
const char msg[] = "Couldn't remove \"%s\": %s"; const char msg[] = "Couldn't remove \"%ls\": %s";
ShowMessage(msg, Shorten(ToWString(full_path), COLS-const_strlen(msg)-25).c_str(), strerror(errno)); ShowMessage(msg, wideShorten(ToWString(full_path), COLS-const_strlen(msg)-25).c_str(), strerror(errno));
} }
} }
closedir(dir); closedir(dir);

View File

@@ -225,7 +225,7 @@ void showSongsInColumns(NC::Menu<T> &menu, const MPD::Song &s, HasSongs &screen)
} }
if (tag.empty() && it->display_empty_tag) if (tag.empty() && it->display_empty_tag)
tag = ToWString(Config.empty_tag); tag = ToWString(Config.empty_tag);
NC::Window::cut(tag, width); wideCut(tag, width);
if (!discard_colors && it->color != NC::clDefault) if (!discard_colors && it->color != NC::clDefault)
menu << it->color; menu << it->color;
@@ -234,7 +234,7 @@ void showSongsInColumns(NC::Menu<T> &menu, const MPD::Song &s, HasSongs &screen)
// if column uses right alignment, calculate proper offset. // if column uses right alignment, calculate proper offset.
// otherwise just assume offset is 0, ie. we start from the left. // otherwise just assume offset is 0, ie. we start from the left.
if (it->right_alignment) if (it->right_alignment)
x_off = std::max(0, width - int(NC::Window::length(tag))); x_off = std::max(0, width - int(wideLength(tag)));
whline(menu.raw(), KEY_SPACE, width); whline(menu.raw(), KEY_SPACE, width);
menu.goToXY(x + x_off, y); menu.goToXY(x + x_off, y);
@@ -314,9 +314,9 @@ std::string Display::Columns(size_t list_width)
} }
else else
name = it->name; name = it->name;
NC::Window::cut(name, width); wideCut(name, width);
int x_off = std::max(0, width - int(NC::Window::length(name))); int x_off = std::max(0, width - int(wideLength(name)));
if (it->right_alignment) if (it->right_alignment)
{ {
result += std::string(x_off, KEY_SPACE); result += std::string(x_off, KEY_SPACE);

View File

@@ -25,6 +25,7 @@
#include "help.h" #include "help.h"
#include "settings.h" #include "settings.h"
#include "status.h" #include "status.h"
#include "utility/wide_string.h"
using Global::MainHeight; using Global::MainHeight;
using Global::MainStartY; using Global::MainStartY;

View File

@@ -296,7 +296,7 @@ std::wstring Scroller(const std::wstring &str, size_t &pos, size_t width)
if (!Config.header_text_scrolling) if (!Config.header_text_scrolling)
return s; return s;
std::wstring result; std::wstring result;
size_t len = NC::Window::length(s); size_t len = wideLength(s);
if (len > width) if (len > width)
{ {
@@ -322,15 +322,3 @@ std::wstring Scroller(const std::wstring &str, size_t &pos, size_t width)
result = s; result = s;
return result; return result;
} }
std::string Shorten(const std::wstring &s, size_t max_length)
{
if (s.length() <= max_length)
return ToString(s);
if (max_length < 2)
return "";
std::wstring result(s, 0, max_length/2-!(max_length%2));
result += L"..";
result += s.substr(s.length()-max_length/2+1);
return ToString(result);
}

View File

@@ -26,6 +26,7 @@
#include "screen.h" #include "screen.h"
#include "settings.h" #include "settings.h"
#include "status.h" #include "status.h"
#include "utility/wide_string.h"
inline HasSongs *hasSongs(BasicScreen *screen) inline HasSongs *hasSongs(BasicScreen *screen)
{ {
@@ -463,6 +464,4 @@ void markSongsInPlaylist(std::shared_ptr<ProxySongList> pl);
std::wstring Scroller(const std::wstring &str, size_t &pos, size_t width); std::wstring Scroller(const std::wstring &str, size_t &pos, size_t width);
std::string Shorten(const std::wstring &s, size_t max_length);
#endif #endif

View File

@@ -210,8 +210,8 @@ void Lastfm::Refetch()
{ {
if (remove(itsFilename.c_str()) && errno != ENOENT) if (remove(itsFilename.c_str()) && errno != ENOENT)
{ {
const char msg[] = "Couldn't remove \"%s\": %s"; const char msg[] = "Couldn't remove \"%ls\": %s";
ShowMessage(msg, Shorten(ToWString(itsFilename), COLS-const_strlen(msg)-25).c_str(), strerror(errno)); ShowMessage(msg, wideShorten(ToWString(itsFilename), COLS-const_strlen(msg)-25).c_str(), strerror(errno));
return; return;
} }
Load(); Load();

View File

@@ -405,8 +405,8 @@ void Lyrics::Refetch()
{ {
if (remove(itsFilename.c_str()) && errno != ENOENT) if (remove(itsFilename.c_str()) && errno != ENOENT)
{ {
const char msg[] = "Couldn't remove \"%s\": %s"; const char msg[] = "Couldn't remove \"%ls\": %s";
ShowMessage(msg, Shorten(ToWString(itsFilename), COLS-const_strlen(msg)-25).c_str(), strerror(errno)); ShowMessage(msg, wideShorten(ToWString(itsFilename), COLS-const_strlen(msg)-25).c_str(), strerror(errno));
return; return;
} }
Load(); Load();

View File

@@ -21,6 +21,7 @@
#include <cassert> #include <cassert>
#include "scrollpad.h" #include "scrollpad.h"
#include "utility/wide_string.h"
namespace NC {// namespace NC {//

View File

@@ -545,7 +545,7 @@ void Configuration::Read()
{ {
selected_item_prefix.clear(); selected_item_prefix.clear();
String2Buffer(v, selected_item_prefix); String2Buffer(v, selected_item_prefix);
selected_item_prefix_length = NC::Window::length(ToWString(selected_item_prefix.str())); selected_item_prefix_length = wideLength(ToWString(selected_item_prefix.str()));
} }
} }
else if (name == "selected_item_suffix") else if (name == "selected_item_suffix")
@@ -554,7 +554,7 @@ void Configuration::Read()
{ {
selected_item_suffix.clear(); selected_item_suffix.clear();
String2Buffer(v, selected_item_suffix); String2Buffer(v, selected_item_suffix);
selected_item_suffix_length = NC::Window::length(ToWString(selected_item_suffix.str())); selected_item_suffix_length = wideLength(ToWString(selected_item_suffix.str()));
} }
} }
else if (name == "now_playing_prefix") else if (name == "now_playing_prefix")
@@ -563,7 +563,7 @@ void Configuration::Read()
{ {
now_playing_prefix.clear(); now_playing_prefix.clear();
String2Buffer(v, now_playing_prefix); String2Buffer(v, now_playing_prefix);
now_playing_prefix_length = NC::Window::length(ToWString(now_playing_prefix.str())); now_playing_prefix_length = wideLength(ToWString(now_playing_prefix.str()));
} }
} }
else if (name == "now_playing_suffix") else if (name == "now_playing_suffix")
@@ -572,7 +572,7 @@ void Configuration::Read()
{ {
now_playing_suffix.clear(); now_playing_suffix.clear();
String2Buffer(ToWString(v), now_playing_suffix); String2Buffer(ToWString(v), now_playing_suffix);
now_playing_suffix_length = NC::Window::length(now_playing_suffix.str()); now_playing_suffix_length = wideLength(now_playing_suffix.str());
} }
} }
else if (name == "color1") else if (name == "color1")

View File

@@ -26,6 +26,7 @@
#include "song.h" #include "song.h"
#include "utility/numeric_conversions.h" #include "utility/numeric_conversions.h"
#include "utility/type_conversions.h" #include "utility/type_conversions.h"
#include "utility/wide_string.h"
#include "window.h" #include "window.h"
namespace {// namespace {//
@@ -38,19 +39,6 @@ size_t calc_hash(const char* s, unsigned seed = 0)
return hash; return hash;
} }
// temporary hack, it won't work properly with wide characters
std::string Shorten(const std::wstring &s, size_t max_length)
{
if (s.length() <= max_length)
return ToString(s);
if (max_length < 2)
return "";
std::wstring result(s, 0, max_length/2-!(max_length%2));
result += L"..";
result += s.substr(s.length()-max_length/2+1);
return ToString(result);
}
} }
namespace MPD {// namespace MPD {//
@@ -289,10 +277,12 @@ std::string Song::ShowTime(unsigned length)
length -= minutes*60; length -= minutes*60;
int seconds = length; int seconds = length;
std::string result;
if (hours > 0) if (hours > 0)
return print<32, std::string>::apply("%d:%02d:%02d", hours, minutes, seconds); result = print<32, std::string>::apply("%d:%02d:%02d", hours, minutes, seconds);
else else
return print<32, std::string>::apply("%d:%02d", minutes, seconds); result = print<32, std::string>::apply("%d:%02d", minutes, seconds);
return result;
} }
bool MPD::Song::isFormatOk(const std::string &type, const std::string &fmt) bool MPD::Song::isFormatOk(const std::string &type, const std::string &fmt)
@@ -324,7 +314,8 @@ bool MPD::Song::isFormatOk(const std::string &type, const std::string &fmt)
return true; return true;
} }
std::string Song::ParseFormat(std::string::const_iterator &it, const std::string &tag_separator, const std::string &escape_chars) const std::string Song::ParseFormat(std::string::const_iterator &it, const std::string &tag_separator,
const std::string &escape_chars) const
{ {
std::string result; std::string result;
bool has_some_tags = 0; bool has_some_tags = 0;
@@ -371,12 +362,8 @@ std::string Song::ParseFormat(std::string::const_iterator &it, const std::string
} }
if (!tag.empty() && (get != &MPD::Song::getLength || getDuration() > 0)) if (!tag.empty() && (get != &MPD::Song::getLength || getDuration() > 0))
{ {
if (delimiter) if (delimiter && tag.size() > delimiter)
{ tag = ToString(wideShorten(ToWString(tag), delimiter));
std::wstring s = ToWString(tag);
if (NC::Window::length(s) > delimiter)
tag = Shorten(s, delimiter);
}
has_some_tags = 1; has_some_tags = 1;
result += tag; result += tag;
} }

View File

@@ -447,11 +447,11 @@ void NcmpcppStatusChanged(MPD::Connection *, MPD::StatusChanges changed, void *)
String2Buffer(ToWString(utf_to_locale_cpy(np.toString(Config.new_header_first_line, "$"))), first); String2Buffer(ToWString(utf_to_locale_cpy(np.toString(Config.new_header_first_line, "$"))), first);
String2Buffer(ToWString(utf_to_locale_cpy(np.toString(Config.new_header_second_line, "$"))), second); String2Buffer(ToWString(utf_to_locale_cpy(np.toString(Config.new_header_second_line, "$"))), second);
size_t first_len = NC::Window::length(first.str()); size_t first_len = wideLength(first.str());
size_t first_margin = (std::max(tracklength.length()+1, VolumeState.length()))*2; size_t first_margin = (std::max(tracklength.length()+1, VolumeState.length()))*2;
size_t first_start = first_len < COLS-first_margin ? (COLS-first_len)/2 : tracklength.length()+1; size_t first_start = first_len < COLS-first_margin ? (COLS-first_len)/2 : tracklength.length()+1;
size_t second_len = NC::Window::length(second.str()); size_t second_len = wideLength(second.str());
size_t second_margin = (std::max(player_state.length(), size_t(8))+1)*2; size_t second_margin = (std::max(player_state.length(), size_t(8))+1)*2;
size_t second_start = second_len < COLS-second_margin ? (COLS-second_len)/2 : player_state.length()+1; size_t second_start = second_len < COLS-second_margin ? (COLS-second_len)/2 : player_state.length()+1;
@@ -654,7 +654,7 @@ void DrawHeader()
*wHeader << NC::fmtBold << Config.alternative_ui_separator_color; *wHeader << NC::fmtBold << Config.alternative_ui_separator_color;
mvwhline(wHeader->raw(), 2, 0, 0, COLS); mvwhline(wHeader->raw(), 2, 0, 0, COLS);
mvwhline(wHeader->raw(), 4, 0, 0, COLS); mvwhline(wHeader->raw(), 4, 0, 0, COLS);
*wHeader << NC::XY((COLS-NC::Window::length(title))/2, 3); *wHeader << NC::XY((COLS-wideLength(title))/2, 3);
*wHeader << Config.header_color << title << NC::clEnd; *wHeader << Config.header_color << title << NC::clEnd;
*wHeader << NC::clEnd << NC::fmtBoldEnd; *wHeader << NC::clEnd << NC::fmtBoldEnd;
} }

View File

@@ -23,6 +23,7 @@
#include <list> #include <list>
#include "utility/numeric_conversions.h" #include "utility/numeric_conversions.h"
#include "utility/wide_string.h"
#include "window.h" #include "window.h"
namespace NC {// namespace NC {//
@@ -306,7 +307,7 @@ template <typename CharT> void basic_buffer<CharT>::write(
) const ) const
{ {
std::basic_string<CharT> s = m_string; std::basic_string<CharT> s = m_string;
size_t len = Window::length(s); size_t len = wideLength(s);
if (len > width) if (len > width)
{ {

View File

@@ -596,8 +596,8 @@ void TagEditor::EnterPressed()
ShowMessage("Writing tags in \"%s\"...", (*it)->getName().c_str()); ShowMessage("Writing tags in \"%s\"...", (*it)->getName().c_str());
if (!WriteTags(**it)) if (!WriteTags(**it))
{ {
const char msg[] = "Error while writing tags in \"%s\""; const char msg[] = "Error while writing tags in \"%ls\"";
ShowMessage(msg, Shorten(ToWString((*it)->getURI()), COLS-const_strlen(msg)).c_str()); ShowMessage(msg, wideShorten(ToWString((*it)->getURI()), COLS-const_strlen(msg)).c_str());
success = 0; success = 0;
break; break;
} }

View File

@@ -91,10 +91,8 @@ void TinyTagEditor::SwitchTo()
full_path += Config.mpd_music_dir; full_path += Config.mpd_music_dir;
full_path += itsEdited.getURI(); full_path += itsEdited.getURI();
std::string message = "Couldn't read file \""; const char msg[] = "Couldn't read file \"%ls\"";
message += Shorten(ToWString(full_path), COLS-message.length()-3); ShowMessage(msg, wideShorten(ToWString(full_path), COLS-const_strlen(msg)).c_str());
message += "\"!";
ShowMessage("%s", message.c_str());
} }
} }

View File

@@ -44,31 +44,6 @@ bool isInteger(const char *s, bool accept_signed)
return true; 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<std::string> split(const std::string &s, const std::string &delimiter) std::vector<std::string> split(const std::string &s, const std::string &delimiter)
{ {
if (delimiter.empty()) if (delimiter.empty())

View File

@@ -67,9 +67,6 @@ int stringToInt(const std::string &s);
long stringToLongInt(const std::string &s); long stringToLongInt(const std::string &s);
bool isInteger(const char *s, bool accept_signed); bool isInteger(const char *s, bool accept_signed);
std::string ToString(const std::wstring &ws);
std::wstring ToWString(const std::string &s);
std::vector<std::string> split(const std::string &s, const std::string &delimiter); std::vector<std::string> split(const std::string &s, const std::string &delimiter);
void replace(std::string &s, const std::string &from, const std::string &to); void replace(std::string &s, const std::string &from, const std::string &to);

105
src/utility/wide_string.cpp Normal file
View File

@@ -0,0 +1,105 @@
/***************************************************************************
* 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 "utility/wide_string.h"
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 wideLength(const std::wstring &ws)
{
int len = wcswidth(ws.c_str(), -1);
if (len < 0)
return ws.length();
else
return len;
}
void wideCut(std::wstring &ws, size_t max_length)
{
size_t i = 0;
int remained_len = max_length;
for (; i < ws.length(); ++i)
{
remained_len -= wcwidth(ws[i]);
if (remained_len < 0)
{
ws.resize(i);
break;
}
}
}
std::wstring wideShorten(const std::wstring &ws, size_t max_length)
{
std::wstring result;
if (wideLength(ws) > max_length)
{
const size_t half_max = max_length/2 - 1;
size_t len = 0;
// get beginning of string
for (auto it = ws.begin(); it != ws.end(); ++it)
{
len += wcwidth(*it);
if (len > half_max)
break;
result += *it;
}
len = 0;
std::wstring end;
// get end of string in reverse order
for (auto it = ws.rbegin(); it != ws.rend(); ++it)
{
len += wcwidth(*it);
if (len > half_max)
break;
end += *it;
}
// apply end of string to its beginning
result += L"..";
result.append(end.rbegin(), end.rend());
}
else
result = ws;
return result;
}

34
src/utility/wide_string.h Normal file
View File

@@ -0,0 +1,34 @@
/***************************************************************************
* 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. *
***************************************************************************/
#ifndef _UTILITY_WIDE_STRING
#define _UTILITY_WIDE_STRING
#include <string>
std::string ToString(const std::wstring &ws);
std::wstring ToWString(const std::string &s);
size_t wideLength(const std::wstring &ws);
void wideCut(std::wstring &ws, size_t max_length);
std::wstring wideShorten(const std::wstring &ws, size_t max_length);
#endif // _UTILITY_WIDE_STRING

View File

@@ -30,6 +30,7 @@
#include "error.h" #include "error.h"
#include "utility/string.h" #include "utility/string.h"
#include "utility/wide_string.h"
#include "window.h" #include "window.h"
namespace NC {// namespace NC {//
@@ -456,7 +457,7 @@ std::string Window::getString(const std::string &base, size_t length_, size_t wi
block_scrolling = 0; block_scrolling = 0;
maxbeginning = block_scrolling ? 0 : (tmp->length() < width ? 0 : tmp->length()-width); maxbeginning = block_scrolling ? 0 : (tmp->length() < width ? 0 : tmp->length()-width);
maxx = minx + (Window::length(*tmp) < width ? Window::length(*tmp) : width); maxx = minx + (wideLength(*tmp) < width ? wideLength(*tmp) : width);
real_maxx = minx + (tmp->length() < width ? tmp->length() : width); real_maxx = minx + (tmp->length() < width ? tmp->length() : width);
@@ -902,29 +903,4 @@ Window &Window::operator<<(size_t s)
return *this; return *this;
} }
size_t Window::length(const std::wstring &ws)
{
# ifdef WIN32
return ws.length();
# else
int len = wcswidth(ws.c_str(), -1);
return len < 0 ? ws.length() : len;
# endif // WIN32
}
void Window::cut(std::wstring &ws, size_t max_len)
{
size_t i = 0;
int remained_len = max_len;
for (; i < ws.length(); ++i)
{
remained_len -= wcwidth(ws[i]);
if (remained_len < 0)
{
ws.resize(i);
break;
}
}
}
} }

View File

@@ -413,18 +413,6 @@ struct Window
/// @param ws wide string to be printed /// @param ws wide string to be printed
/// @return reference to itself /// @return reference to itself
Window &operator<<(const std::wstring &ws); Window &operator<<(const std::wstring &ws);
/// Measures real length of wide string (required if e.g. asian characters are used)
/// @param ws wide string that real length has to be measured
/// @return real length of wide string
static size_t length(const std::wstring &ws);
/// Cuts string so it fits desired length on the screen. Note that it uses
/// wcwidth to check real width of all characters it contains. If string
/// fits requested length it's not modified at all.
/// @param ws wide string to be cut
/// @param max_len maximal length of string
static void cut(std::wstring &ws, size_t max_len);
protected: protected:
/// Sets colors of window (interal use only) /// Sets colors of window (interal use only)
/// @param fg foregound color /// @param fg foregound color