Merge pull request #1487 from pestoffne/fix/editor-input-utf8
Fixed input of long UTF-8 symbols in editor (#1423)fix-squashed-planets
commit
6aebf60300
|
@ -156,11 +156,17 @@ std::wstring StrUtils::Utf8StringToUnicode(const std::string &str)
|
|||
{
|
||||
std::wstring result;
|
||||
unsigned int pos = 0;
|
||||
int len;
|
||||
while (pos < str.size())
|
||||
{
|
||||
int len = StrUtils::Utf8CharSizeAt(str, pos);
|
||||
if (len == 0)
|
||||
try
|
||||
{
|
||||
len = StrUtils::Utf8CharSizeAt(str, pos);
|
||||
}
|
||||
catch (std::out_of_range &e)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
std::string ch = str.substr(pos, len);
|
||||
result += static_cast<wchar_t>(StrUtils::Utf8CharToUnicode(ch));
|
||||
|
@ -172,21 +178,24 @@ std::wstring StrUtils::Utf8StringToUnicode(const std::string &str)
|
|||
int StrUtils::Utf8CharSizeAt(const std::string &str, unsigned int pos)
|
||||
{
|
||||
if (pos >= str.size())
|
||||
return 0;
|
||||
throw std::out_of_range("Index is greater than size");
|
||||
|
||||
const char c = str[pos];
|
||||
if((c & 0xF8) == 0xF0)
|
||||
return 4;
|
||||
if((c & 0xF0) == 0xE0)
|
||||
return 3;
|
||||
if((c & 0xE0) == 0xC0)
|
||||
if((c & 0b1000'0000) == 0b0000'0000)
|
||||
return 1;
|
||||
if((c & 0b1110'0000) == 0b1100'0000)
|
||||
return 2;
|
||||
if((c & 0b1111'0000) == 0b1110'0000)
|
||||
return 3;
|
||||
if((c & 0b1111'1000) == 0b1111'0000)
|
||||
return 4;
|
||||
|
||||
// Invalid char - unexpected continuation byte
|
||||
if((c & 0xC0) == 0x80)
|
||||
if (isUtf8ContinuationByte(c))
|
||||
throw std::invalid_argument("Unexpected UTF-8 continuation byte");
|
||||
|
||||
return 1;
|
||||
// (c & 0b1111'1000) == 0b1111'1000 is true here
|
||||
throw std::invalid_argument("Byte value has no sense in UTF-8");
|
||||
}
|
||||
|
||||
std::size_t StrUtils::Utf8StringLength(const std::string &str)
|
||||
|
@ -201,3 +210,7 @@ std::size_t StrUtils::Utf8StringLength(const std::string &str)
|
|||
return result;
|
||||
}
|
||||
|
||||
bool StrUtils::isUtf8ContinuationByte(char c)
|
||||
{
|
||||
return (c & 0b1100'0000) == 0b1000'0000;
|
||||
}
|
||||
|
|
|
@ -87,5 +87,8 @@ int Utf8CharSizeAt(const std::string &str, unsigned int pos);
|
|||
//! Returns the length in characters of UTF-8 string \a str
|
||||
std::size_t Utf8StringLength(const std::string &str);
|
||||
|
||||
//! Returns true if char is continuation UTF-8 byte
|
||||
bool isUtf8ContinuationByte(char c);
|
||||
|
||||
} // namespace StrUtil
|
||||
|
||||
|
|
|
@ -1112,7 +1112,14 @@ int CText::GetCharSizeAt(Gfx::FontType font, const std::string& text, unsigned i
|
|||
}
|
||||
else
|
||||
{
|
||||
len = StrUtils::Utf8CharSizeAt(text, index);
|
||||
try
|
||||
{
|
||||
len = StrUtils::Utf8CharSizeAt(text, index);
|
||||
}
|
||||
catch (std::invalid_argument &e)
|
||||
{
|
||||
len = 1;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "common/logger.h"
|
||||
#include "common/make_unique.h"
|
||||
#include "common/stringutils.h"
|
||||
|
||||
#include "common/resources/inputstream.h"
|
||||
#include "common/resources/outputstream.h"
|
||||
|
@ -492,7 +493,10 @@ bool CEdit::EventProcess(const Event &event)
|
|||
if ( event.type == EVENT_TEXT_INPUT && !bControl && m_bFocus )
|
||||
{
|
||||
auto data = event.GetData<TextInputData>();
|
||||
Insert(data->text[0]); // TODO: insert utf-8 char
|
||||
for ( char c : data->text )
|
||||
{
|
||||
Insert(c);
|
||||
}
|
||||
SendModifEvent();
|
||||
return true;
|
||||
}
|
||||
|
@ -2258,7 +2262,7 @@ void CEdit::MoveChar(int move, bool bWord, bool bSelect)
|
|||
{
|
||||
int character;
|
||||
|
||||
if ( move == -1 ) // back?
|
||||
if ( move == -1 ) // back
|
||||
{
|
||||
if ( bWord )
|
||||
{
|
||||
|
@ -2303,12 +2307,18 @@ void CEdit::MoveChar(int move, bool bWord, bool bSelect)
|
|||
}
|
||||
else
|
||||
{
|
||||
m_cursor1 --;
|
||||
if ( m_cursor1 < 0 ) m_cursor1 = 0;
|
||||
if ( m_cursor1 > 0 )
|
||||
{
|
||||
m_cursor1 --;
|
||||
while ( m_cursor1 > 0 && StrUtils::isUtf8ContinuationByte(m_text[m_cursor1]) )
|
||||
{
|
||||
m_cursor1 --;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( move == 1 ) // advance?
|
||||
if ( move == 1 ) // advance
|
||||
{
|
||||
if ( bWord )
|
||||
{
|
||||
|
@ -2353,8 +2363,14 @@ void CEdit::MoveChar(int move, bool bWord, bool bSelect)
|
|||
}
|
||||
else
|
||||
{
|
||||
m_cursor1 ++;
|
||||
if ( m_cursor1 > m_len ) m_cursor1 = m_len;
|
||||
if ( m_cursor1 < m_len )
|
||||
{
|
||||
m_cursor1 ++;
|
||||
while ( m_cursor1 < m_len && StrUtils::isUtf8ContinuationByte(m_text[m_cursor1]) )
|
||||
{
|
||||
m_cursor1 ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2784,6 +2800,11 @@ void CEdit::DeleteOne(int dir)
|
|||
}
|
||||
|
||||
if ( m_cursor1 > m_cursor2 ) Math::Swap(m_cursor1, m_cursor2);
|
||||
|
||||
// Expands selection to delete integer number of UTF-8 symbols
|
||||
while ( m_cursor1 > 0 && StrUtils::isUtf8ContinuationByte(m_text[m_cursor1]) ) m_cursor1 --;
|
||||
while ( m_cursor2 < m_len && StrUtils::isUtf8ContinuationByte(m_text[m_cursor2]) ) m_cursor2 ++;
|
||||
|
||||
hole = m_cursor2-m_cursor1;
|
||||
end = m_len-hole;
|
||||
for ( i=m_cursor1 ; i<end ; i++ )
|
||||
|
|
Loading…
Reference in New Issue