diff --git a/src/base/system.c b/src/base/system.c index 8f398b542..060924861 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -3182,6 +3182,50 @@ int str_utf8_check(const char *str) return 1; } +void str_utf8_copy(char *dst, const char *src, int dst_size) +{ + strncpy(dst, src, dst_size); + dst[dst_size-1] = 0; /* assure null termination */ + + // check whether we need to remove a broken utf8 character + char *end = dst + (dst_size-2); + char *ptr = end; + while(ptr > dst) + { + if((*ptr&0xC0) == 0x80) + { + ptr--; + } + else if((*ptr&0x80) == 0) + { + return; + } + else if((*ptr&0xE0) == 0xC0) + { + if(end-ptr != 1) + *ptr = 0; + return; + } + else if((*ptr&0xF0) == 0xE0) + { + if(end-ptr != 2) + *ptr = 0; + return; + } + else if((*ptr&0xF8) == 0xF0) + { + if(end-ptr != 3) + *ptr = 0; + return; + } + else + { + return; + } + } + + *ptr = 0; +} unsigned str_quickhash(const char *str) { diff --git a/src/base/system.h b/src/base/system.h index b936b33cc..a511e9ed3 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -1918,6 +1918,23 @@ int str_utf16le_encode(char *ptr, int chr); */ int str_utf8_check(const char *str); +/* + Function: str_utf8_copy + Copies a utf8 string to a buffer. + + Parameters: + dst - Pointer to a buffer that shall receive the string. + src - utf8 string to be copied. + dst_size - Size of the buffer dst. + + Remarks: + - The strings are treated as zero-terminated strings. + - Guarantees that dst string will contain zero-termination. + - Guarantees that dst always ends with a valid utf8 sequence. + - Does not guarantee the entire string is a valid utf8 string. +*/ +void str_utf8_copy(char *dst, const char *src, int dst_size); + /* Function: str_next_token Writes the next token after str into buf, returns the rest of the string. diff --git a/src/engine/client/input.cpp b/src/engine/client/input.cpp index 310c6e852..9171ecd3c 100644 --- a/src/engine/client/input.cpp +++ b/src/engine/client/input.cpp @@ -26,7 +26,7 @@ void CInput::AddEvent(char *pText, int Key, int Flags) if(!pText) m_aInputEvents[m_NumEvents].m_aText[0] = 0; else - str_copy(m_aInputEvents[m_NumEvents].m_aText, pText, sizeof(m_aInputEvents[m_NumEvents].m_aText)); + str_utf8_copy(m_aInputEvents[m_NumEvents].m_aText, pText, sizeof(m_aInputEvents[m_NumEvents].m_aText)); m_aInputEvents[m_NumEvents].m_InputCount = m_InputCounter; m_NumEvents++; } diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index d00428577..539c1d993 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -168,14 +168,14 @@ bool CChat::OnInput(IInput::CEvent Event) if(Text[i] == '\n') { int max = minimum(i - Begin + 1, (int)sizeof(Line)); - str_copy(Line, Text + Begin, max); + str_utf8_copy(Line, Text + Begin, max); Begin = i+1; SayChat(Line); while(Text[i] == '\n') i++; } } int max = minimum(i - Begin + 1, (int)sizeof(Line)); - str_copy(Line, Text + Begin, max); + str_utf8_copy(Line, Text + Begin, max); Begin = i+1; m_Input.Add(Line); }