Skip to content

Commit

Permalink
simplewallet: Add Unicode input_line [Ryo backport]
Browse files Browse the repository at this point in the history
  • Loading branch information
fireice-uk committed Sep 17, 2018
1 parent bb30a72 commit e08ab7d
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 43 deletions.
28 changes: 28 additions & 0 deletions src/common/util.cpp
Expand Up @@ -939,4 +939,32 @@ std::string get_nix_version_display_string()
}
return newval;
}

#ifdef _WIN32
std::string input_line_win()
{
HANDLE hConIn = CreateFileW(L"CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
DWORD oldMode;

FlushConsoleInputBuffer(hConIn);
GetConsoleMode(hConIn, &oldMode);
SetConsoleMode(hConIn, ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT);

wchar_t buffer[1024];
DWORD read;

ReadConsoleW(hConIn, buffer, sizeof(buffer)/sizeof(wchar_t)-1, &read, nullptr);
buffer[read] = 0;

SetConsoleMode(hConIn, oldMode);
CloseHandle(hConIn);

int size_needed = WideCharToMultiByte(CP_UTF8, 0, buffer, -1, NULL, 0, NULL, NULL);
std::string buf(size_needed, '\0');
WideCharToMultiByte(CP_UTF8, 0, buffer, -1, &buf[0], size_needed, NULL, NULL);
buf.pop_back(); //size_needed includes null that we needed to have space for
return buf;
}
#endif

}
3 changes: 3 additions & 0 deletions src/common/util.h
Expand Up @@ -235,4 +235,7 @@ namespace tools
boost::optional<std::pair<uint32_t, uint32_t>> parse_subaddress_lookahead(const std::string& str);

std::string glob_to_regex(const std::string &val);
#ifdef _WIN32
std::string input_line_win();
#endif
}
46 changes: 3 additions & 43 deletions src/simplewallet/simplewallet.cpp
Expand Up @@ -138,47 +138,6 @@ namespace

const command_line::arg_descriptor< std::vector<std::string> > arg_command = {"command", ""};

#ifdef WIN32
// Translate from CP850 to UTF-8;
// std::getline for a Windows console returns a string in CP437 or CP850; as simplewallet,
// like all of Monero, is assumed to work internally with UTF-8 throughout, even on Windows
// (although only implemented partially), a translation to UTF-8 is needed for input.
//
// Note that if a program is started inside the MSYS2 shell somebody already translates
// console input to UTF-8, but it's not clear how one could detect that in order to avoid
// double-translation; this code here thus breaks UTF-8 input within a MSYS2 shell,
// unfortunately.
//
// Note also that input for passwords is NOT translated, to remain compatible with any
// passwords containing special characters that predate this switch to UTF-8 support.
template<typename T>
static T cp850_to_utf8(const T &cp850_str)
{
boost::locale::generator gen;
gen.locale_cache_enabled(true);
std::locale loc = gen("en_US.CP850");
const boost::locale::conv::method_type how = boost::locale::conv::default_method;
T result;
const char *begin = cp850_str.data();
const char *end = begin + cp850_str.size();
result.reserve(end-begin);
typedef std::back_insert_iterator<T> inserter_type;
inserter_type inserter(result);
boost::locale::utf::code_point c;
while(begin!=end) {
c=boost::locale::utf::utf_traits<char>::template decode<char const *>(begin,end);
if(c==boost::locale::utf::illegal || c==boost::locale::utf::incomplete) {
if(how==boost::locale::conv::stop)
throw boost::locale::conv::conversion_error();
}
else {
boost::locale::utf::utf_traits<char>::template encode<inserter_type>(c,inserter);
}
}
return result;
}
#endif

std::string input_line(const std::string& prompt)
{
#ifdef HAVE_READLINE
Expand All @@ -187,9 +146,10 @@ namespace
std::cout << prompt;

std::string buf;
#ifdef _WIN32
buf = tools::input_line_win();
#else
std::getline(std::cin, buf);
#ifdef WIN32
buf = cp850_to_utf8(buf);
#endif

return epee::string_tools::trim(buf);
Expand Down

0 comments on commit e08ab7d

Please sign in to comment.