Skip to content

Commit

Permalink
Proper UTF-8 <--> current system codepage conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
Xottab-DUTY committed Aug 3, 2018
1 parent c4d4dd1 commit e27c4da
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 18 deletions.
21 changes: 21 additions & 0 deletions src/xrCore/Text/MbHelpers.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#include "stdafx.h"
#include "MbHelpers.h"
#include <codecvt>

// XXX: use c++11 functions and kill that DUMP_CONVERSION!!!11

#define BITS1_MASK 0x80 // 10000000b
#define BITS2_MASK 0xC0 // 11000000b
Expand Down Expand Up @@ -127,3 +130,21 @@ u16 mbhMulti2Wide(wchar_t* WideStr, wchar_t* WidePos, u16 WideStrSize, const cha
WideStr[0] = dpos;
return dpos;
}

xr_string StringFromUTF8(const char* in, const std::locale& locale /*= std::locale("")*/)
{
using wcvt = std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>;
auto wstr = wcvt{}.from_bytes(in);
xr_string result(wstr.size(), '\0');
std::use_facet<std::ctype<wchar_t>>(locale).narrow(wstr.data(), wstr.data() + wstr.size(), '?', &result[0]);
return result;
}

xr_string StringToUTF8(const char* in, const std::locale& locale /*= std::locale("")*/)
{
using wcvt = std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>;
std::wstring wstr(xr_strlen(in), L'\0');
std::use_facet<std::ctype<wchar_t>>(locale).widen(in, in + xr_strlen(in), &wstr[0]);
std::string result = wcvt{}.to_bytes(wstr.data(), wstr.data() + wstr.size());
return result.data();
}
6 changes: 6 additions & 0 deletions src/xrCore/Text/MbHelpers.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#pragma once
#include "xrCore/xrCore.h"

// XXX: rename this file to StringConversion.hpp
// XXX: use c++11 functions

#define MAX_MB_CHARS 4096

XRCORE_API u16 mbhMulti2Wide(wchar_t* WideStr, wchar_t* WidePos, u16 WideStrSize, const char* MultiStr);
Expand All @@ -27,3 +30,6 @@ IC bool IsAlphaCharacter(wchar_t wc)
((wc >= 0x0061) && (wc <= 0x007A)) || ((wc >= 0xFF10) && (wc <= 0xFF19)) ||
((wc >= 0xFF21) && (wc <= 0xFF3A)) || ((wc >= 0xFF41) && (wc <= 0xFF5A)));
}

XRCORE_API xr_string StringFromUTF8(const char* string, const std::locale& locale = std::locale(""));
XRCORE_API xr_string StringToUTF8(const char* string, const std::locale& locale = std::locale(""));
15 changes: 2 additions & 13 deletions src/xrEngine/edit_actions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#include "edit_actions.h"
#include "line_edit_control.h"
#include "xr_input.h"
#include <codecvt>
#include "xrCore/Text/MbHelpers.h"

namespace text_editor
{
Expand Down Expand Up @@ -55,17 +55,6 @@ void type_pair::init(int dik, char c, char c_shift, bool b_translate)
m_char_shift = c_shift;
}

xr_string utf8_to_string(const char* utf8str, const std::locale& loc)
{
// UTF-8 to wstring
std::wstring_convert<std::codecvt_utf8<wchar_t>> wconv;
std::wstring wstr = wconv.from_bytes(utf8str);
// wstring to string
std::vector<char> buf(wstr.size());
std::use_facet<std::ctype<wchar_t>>(loc).narrow(wstr.data(), wstr.data() + wstr.size(), '?', buf.data());
return xr_string(buf.data(), buf.size());
}

void type_pair::on_key_press(line_edit_control* const control)
{
char c = 0;
Expand All @@ -82,7 +71,7 @@ void type_pair::on_key_press(line_edit_control* const control)
case SDL_TEXTINPUT:
{
const std::locale locale("");
auto str = utf8_to_string(event.text.text, locale);
auto str = StringFromUTF8(event.text.text, locale);

if (std::isalpha(str[0], locale) || str[0] == char(-1)) // "я" = -1
{
Expand Down
11 changes: 6 additions & 5 deletions src/xrEngine/xr_input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "Include/editor/ide.hpp"
#include "GameFont.h"
#include "PerformanceAlert.hpp"
#include "xrCore/Text/MbHelpers.h"

#ifndef _EDITOR
#include "xr_input_xinput.h"
Expand Down Expand Up @@ -196,14 +197,14 @@ pcstr KeyToMouseButtonName(const int dik)

bool CInput::get_dik_name(int dik, LPSTR dest_str, int dest_sz)
{
pcstr keyname;
xr_string keyname;

if (dik < SDL_NUM_SCANCODES)
keyname = SDL_GetKeyName(SDL_GetKeyFromScancode((SDL_Scancode)dik));
keyname = StringFromUTF8(SDL_GetKeyName(SDL_GetKeyFromScancode((SDL_Scancode)dik)));
else
keyname = KeyToMouseButtonName(dik);

if (0 == strlen(keyname))
if (keyname.empty())
{
if (dik == SDL_SCANCODE_UNKNOWN)
keyname = "Unknown";
Expand All @@ -214,7 +215,7 @@ bool CInput::get_dik_name(int dik, LPSTR dest_str, int dest_sz)
}
}

xr_strcpy(dest_str, dest_sz, keyname);
xr_strcpy(dest_str, dest_sz, keyname.c_str());
return true;
}

Expand Down

0 comments on commit e27c4da

Please sign in to comment.