I want to make
print an UTF-8 literal. This seems to be an easy task with gcc, but an extremely difficult one with Windows.
The code that I'm trying to get to work is:
Environment:
<ul>
<li>Windows 10, Visual Studio 2015</li>
<li>Default encoding: 1251</li>
<li>Console encoding: 866</li>
<li>Source encoding: UTF-8 with BOM</li>
</ul>
Requirements:
<ul>
<li>No changes to the line of code itself must be made</li>
<li>Full Unicode range support</li>
<li>Some setup code may be added in the beginning of
</li>
</ul>
What I've tried:
<ul>
<li>
</li>
<li>
</li>
<li>Set console font to Lucida Console system-wide</li>
<li>
in project properties</li>
<li>Setup code from <a href="https://alfps.wordpress.com/2011/11/22/unicode-part-1-windows-console-io-approaches/" rel="nofollow noreferrer">this</a> blog</li>
</ul>
Nothing helped, and no StackOverflow answer solved the problem.
<strong>Edit</strong>
To get Unicode <strong>partially</strong> working, do the following:
<ul>
<li>Call
from the listing below at the start</li>
<li>Turn on
in Project Settings</li>
<li>Add
option</li>
</ul>
Not working:
<ul>
<li>
</li>
<li>
/
</li>
<li>Chinese characters</li>
</ul>
implementation:
Code:
std::cout
The code that I'm trying to get to work is:
Code:
std::cout << "Ελληνικά Русский 你好";
Environment:
<ul>
<li>Windows 10, Visual Studio 2015</li>
<li>Default encoding: 1251</li>
<li>Console encoding: 866</li>
<li>Source encoding: UTF-8 with BOM</li>
</ul>
Requirements:
<ul>
<li>No changes to the line of code itself must be made</li>
<li>Full Unicode range support</li>
<li>Some setup code may be added in the beginning of
Code:
main()
</ul>
What I've tried:
<ul>
<li>
Code:
#pragma execution_character_set("utf-8")
<li>
Code:
SetConsoleCP(CP_UTF8); SetConsoleOutputCP(CP_UTF8);
<li>Set console font to Lucida Console system-wide</li>
<li>
Code:
Use Unicode character set
<li>Setup code from <a href="https://alfps.wordpress.com/2011/11/22/unicode-part-1-windows-console-io-approaches/" rel="nofollow noreferrer">this</a> blog</li>
</ul>
Nothing helped, and no StackOverflow answer solved the problem.
<strong>Edit</strong>
To get Unicode <strong>partially</strong> working, do the following:
<ul>
<li>Call
Code:
initStreams()
<li>Turn on
Code:
Use Unicode Character Set
<li>Add
Code:
/utf-8
</ul>
Not working:
<ul>
<li>
Code:
wprintf
<li>
Code:
cin
Code:
wcin
<li>Chinese characters</li>
</ul>
Code:
initStreams()
Code:
#include <cassert> // assert
#include <codecvt> // std::codecvt_utf8 (C++11)
#include <stdexcept> // std::exception
#include <streambuf> // std::basic_streambuf
#include <iostream> // std::cout, std::endl
#include <locale> // std::locale
#include <memory> // std::unique_ptr (C++11)
#undef UNICODE
#define UNICODE
#undef STRICT
#define STRING
#include <windows.h> // MultiByteToWideChar
class OutputForwarderBuffer : public std::basic_streambuf<char>
{
public:
using Base = std::basic_streambuf<char>;
using Traits = Base::traits_type;
using StreamBuffer = std::basic_streambuf<char>;
using WideStreamBuffer = std::basic_streambuf<wchar_t>;
using Base::int_type;
using Base::char_type;
OutputForwarderBuffer(
StreamBuffer& existingBuffer,
WideStreamBuffer* pWideStreamBuffer
)
: Base(existingBuffer)
, pWideStreamBuffer_(pWideStreamBuffer)
{
}
OutputForwarderBuffer(OutputForwarderBuffer const&) = delete;
void operator=(OutputForwarderBuffer const&) = delete;
protected:
std::streamsize xsputn(char const* s, std::streamsize n) override
{
if (n == 0) { return 0; }
int const sourceSize = static_cast<int>(n);
int const destinationSize = MultiByteToWideChar(CP_UTF8, 0, s, sourceSize, nullptr, 0);
wideCharBuffer_.resize(static_cast<size_t>(sourceSize));
int const nWideCharacters = MultiByteToWideChar(CP_UTF8, 0, s, sourceSize, &wideCharBuffer_[0], destinationSize);
assert(nWideCharacters > 0 && nWideCharacters == destinationSize);
return pWideStreamBuffer_->sputn(&wideCharBuffer_[0], destinationSize);
}
int_type overflow(int_type c) override
{
bool const cIsEOF = Traits::eq_int_type(c, Traits::eof());
int_type const failureValue = Traits::eof();
int_type const successValue = (cIsEOF ? Traits::not_eof(c) : c);
if (!cIsEOF) {
char_type const ch = Traits::to_char_type(c);
std::streamsize const nCharactersWritten = xsputn(&ch, 1);
return (nCharactersWritten == 1 ? successValue : failureValue);
}
return successValue;
}
private:
WideStreamBuffer* pWideStreamBuffer_;
std::wstring wideCharBuffer_;
};
void setUtf8Conversion(std::basic_ios<wchar_t>& stream)
{
stream.imbue(std::locale(std::locale::empty(), new std::codecvt_utf8_utf16<wchar_t>()));
}
bool isConsole(HANDLE streamHandle)
{
DWORD consoleMode;
return !!GetConsoleMode(streamHandle, &consoleMode);
}
bool isConsole(DWORD stdStreamId)
{
return isConsole(GetStdHandle(stdStreamId));
}
void initStreams()
{
SetConsoleCP(CP_UTF8);
SetConsoleOutputCP(CP_UTF8);
setUtf8Conversion(std::wcout);
setUtf8Conversion(std::wcerr);
setUtf8Conversion(std::wclog);
static OutputForwarderBuffer coutBuffer(*std::cout.rdbuf(), std::wcout.rdbuf());
static OutputForwarderBuffer cerrBuffer(*std::cerr.rdbuf(), std::wcerr.rdbuf());
static OutputForwarderBuffer clogBuffer(*std::clog.rdbuf(), std::wclog.rdbuf());
std::cout.rdbuf(&coutBuffer);
std::cerr.rdbuf(&cerrBuffer);
std::clog.rdbuf(&clogBuffer);
}