From 16f4b7cae4f73956caa965340594ef8e66c8432e Mon Sep 17 00:00:00 2001 From: dewyatt Date: Tue, 13 Jul 2010 15:05:45 -0400 Subject: [PATCH] Added SDL_utf8strlcpy to copy at UTF-8 character boundaries. Changed SDL_SendKeyboardText and SDL_SendEditingText to use SDL_utf8strlcpy. --- include/SDL_stdinc.h | 3 +++ src/events/SDL_keyboard.c | 4 ++-- src/stdlib/SDL_string.c | 47 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/include/SDL_stdinc.h b/include/SDL_stdinc.h index c7e7edd57..fb143acb5 100644 --- a/include/SDL_stdinc.h +++ b/include/SDL_stdinc.h @@ -470,6 +470,9 @@ extern DECLSPEC size_t SDLCALL SDL_strlcpy(char *dst, const char *src, size_t maxlen); #endif +extern DECLSPEC size_t SDLCALL SDL_utf8strlcpy(char *dst, const char *src, + size_t dst_bytes); + #ifdef HAVE_STRLCAT #define SDL_strlcat strlcat #else diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c index f25bc6af8..f56075eaa 100644 --- a/src/events/SDL_keyboard.c +++ b/src/events/SDL_keyboard.c @@ -766,7 +766,7 @@ SDL_SendKeyboardText(const char *text) SDL_Event event; event.text.type = SDL_TEXTINPUT; event.text.windowID = keyboard->focus ? keyboard->focus->id : 0; - SDL_strlcpy(event.text.text, text, SDL_arraysize(event.text.text)); + SDL_utf8strlcpy(event.text.text, text, SDL_arraysize(event.text.text)); event.text.windowID = keyboard->focus ? keyboard->focus->id : 0; posted = (SDL_PushEvent(&event) > 0); } @@ -787,7 +787,7 @@ SDL_SendEditingText(const char *text, int start, int length) event.edit.windowID = keyboard->focus ? keyboard->focus->id : 0; event.edit.start = start; event.edit.length = length; - SDL_strlcpy(event.edit.text, text, SDL_arraysize(event.edit.text)); + SDL_utf8strlcpy(event.edit.text, text, SDL_arraysize(event.edit.text)); posted = (SDL_PushEvent(&event) > 0); } return (posted); diff --git a/src/stdlib/SDL_string.c b/src/stdlib/SDL_string.c index d70f8666a..b6839c1cf 100644 --- a/src/stdlib/SDL_string.c +++ b/src/stdlib/SDL_string.c @@ -29,6 +29,21 @@ #define SDL_isupperhex(X) (((X) >= 'A') && ((X) <= 'F')) #define SDL_islowerhex(X) (((X) >= 'a') && ((X) <= 'f')) +#define UTF8_IsLeadByte(c) ((c) >= 0xC0 && (c) <= 0xF4) +#define UTF8_IsTrailingByte(c) ((c) >= 0x80 && (c) <= 0xBF) + +int UTF8_TrailingBytes(unsigned char c) +{ + if (c >= 0xC0 && c<= 0xDF) + return 1; + else if (c >= 0xE0 && c <= 0xEF) + return 2; + else if (c >= 0xF0 && c <= 0xF4) + return 3; + else + return 0; +} + #if !defined(HAVE_SSCANF) || !defined(HAVE_STRTOL) static size_t SDL_ScanLong(const char *text, int radix, long *valuep) @@ -362,6 +377,38 @@ SDL_strlcpy(char *dst, const char *src, size_t maxlen) } #endif +size_t SDL_utf8strlcpy(char *dst, const char *src, size_t dst_bytes) +{ + size_t src_bytes = SDL_strlen(src); + size_t bytes = SDL_min(src_bytes, dst_bytes - 1); + int i = 0; + char trailing_bytes = 0; + if (bytes) + { + unsigned char c = (unsigned char)src[bytes - 1]; + if (UTF8_IsLeadByte(c)) + --bytes; + else if (UTF8_IsTrailingByte(c)) + { + for (i = bytes - 1; i != 0; --i) + { + c = (unsigned char)src[i]; + trailing_bytes = UTF8_TrailingBytes(c); + if (trailing_bytes) + { + if (bytes - i != trailing_bytes + 1) + bytes = i; + + break; + } + } + } + SDL_memcpy(dst, src, bytes); + } + dst[bytes] = '\0'; + return bytes; +} + #ifndef HAVE_STRLCAT size_t SDL_strlcat(char *dst, const char *src, size_t maxlen)