Added SDL_utf8strlcpy to copy at UTF-8 character boundaries.
authordewyatt
Tue, 13 Jul 2010 15:05:45 -0400
changeset 4754 2072fed2f583
parent 4753 11b0a6a3eb4d
child 4755 436183eb30c8
Added SDL_utf8strlcpy to copy at UTF-8 character boundaries. Changed SDL_SendKeyboardText and SDL_SendEditingText to use SDL_utf8strlcpy.
include/SDL_stdinc.h
src/events/SDL_keyboard.c
src/stdlib/SDL_string.c
--- a/include/SDL_stdinc.h	Mon Jul 12 14:17:43 2010 -0400
+++ b/include/SDL_stdinc.h	Tue Jul 13 15:05:45 2010 -0400
@@ -470,6 +470,9 @@
                                            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
--- a/src/events/SDL_keyboard.c	Mon Jul 12 14:17:43 2010 -0400
+++ b/src/events/SDL_keyboard.c	Tue Jul 13 15:05:45 2010 -0400
@@ -766,7 +766,7 @@
         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 @@
         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);
--- a/src/stdlib/SDL_string.c	Mon Jul 12 14:17:43 2010 -0400
+++ b/src/stdlib/SDL_string.c	Tue Jul 13 15:05:45 2010 -0400
@@ -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 @@
 }
 #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)