Added SDL_utf8strlcpy to copy at UTF-8 character boundaries.
authordewyatt
Tue, 13 Jul 2010 15:05:45 -0400
changeset 47542072fed2f583
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
     1.1 --- a/include/SDL_stdinc.h	Mon Jul 12 14:17:43 2010 -0400
     1.2 +++ b/include/SDL_stdinc.h	Tue Jul 13 15:05:45 2010 -0400
     1.3 @@ -470,6 +470,9 @@
     1.4                                             size_t maxlen);
     1.5  #endif
     1.6  
     1.7 +extern DECLSPEC size_t SDLCALL SDL_utf8strlcpy(char *dst, const char *src,
     1.8 +                                            size_t dst_bytes);
     1.9 +
    1.10  #ifdef HAVE_STRLCAT
    1.11  #define SDL_strlcat    strlcat
    1.12  #else
     2.1 --- a/src/events/SDL_keyboard.c	Mon Jul 12 14:17:43 2010 -0400
     2.2 +++ b/src/events/SDL_keyboard.c	Tue Jul 13 15:05:45 2010 -0400
     2.3 @@ -766,7 +766,7 @@
     2.4          SDL_Event event;
     2.5          event.text.type = SDL_TEXTINPUT;
     2.6          event.text.windowID = keyboard->focus ? keyboard->focus->id : 0;
     2.7 -        SDL_strlcpy(event.text.text, text, SDL_arraysize(event.text.text));
     2.8 +        SDL_utf8strlcpy(event.text.text, text, SDL_arraysize(event.text.text));
     2.9          event.text.windowID = keyboard->focus ? keyboard->focus->id : 0;
    2.10          posted = (SDL_PushEvent(&event) > 0);
    2.11      }
    2.12 @@ -787,7 +787,7 @@
    2.13          event.edit.windowID = keyboard->focus ? keyboard->focus->id : 0;
    2.14          event.edit.start = start;
    2.15          event.edit.length = length;
    2.16 -        SDL_strlcpy(event.edit.text, text, SDL_arraysize(event.edit.text));
    2.17 +        SDL_utf8strlcpy(event.edit.text, text, SDL_arraysize(event.edit.text));
    2.18          posted = (SDL_PushEvent(&event) > 0);
    2.19      }
    2.20      return (posted);
     3.1 --- a/src/stdlib/SDL_string.c	Mon Jul 12 14:17:43 2010 -0400
     3.2 +++ b/src/stdlib/SDL_string.c	Tue Jul 13 15:05:45 2010 -0400
     3.3 @@ -29,6 +29,21 @@
     3.4  #define SDL_isupperhex(X)   (((X) >= 'A') && ((X) <= 'F'))
     3.5  #define SDL_islowerhex(X)   (((X) >= 'a') && ((X) <= 'f'))
     3.6  
     3.7 +#define UTF8_IsLeadByte(c) ((c) >= 0xC0 && (c) <= 0xF4)
     3.8 +#define UTF8_IsTrailingByte(c) ((c) >= 0x80 && (c) <= 0xBF)
     3.9 +
    3.10 +int UTF8_TrailingBytes(unsigned char c)
    3.11 +{
    3.12 +    if (c >= 0xC0 && c<= 0xDF)
    3.13 +        return 1;
    3.14 +    else if (c >= 0xE0 && c <= 0xEF)
    3.15 +        return 2;
    3.16 +    else if (c >= 0xF0 && c <= 0xF4)
    3.17 +        return 3;
    3.18 +    else
    3.19 +        return 0;
    3.20 +}
    3.21 +
    3.22  #if !defined(HAVE_SSCANF) || !defined(HAVE_STRTOL)
    3.23  static size_t
    3.24  SDL_ScanLong(const char *text, int radix, long *valuep)
    3.25 @@ -362,6 +377,38 @@
    3.26  }
    3.27  #endif
    3.28  
    3.29 +size_t SDL_utf8strlcpy(char *dst, const char *src, size_t dst_bytes)
    3.30 +{
    3.31 +    size_t src_bytes = SDL_strlen(src);
    3.32 +    size_t bytes = SDL_min(src_bytes, dst_bytes - 1);
    3.33 +    int i = 0;
    3.34 +    char trailing_bytes = 0;
    3.35 +    if (bytes)
    3.36 +    {
    3.37 +        unsigned char c = (unsigned char)src[bytes - 1];
    3.38 +        if (UTF8_IsLeadByte(c))
    3.39 +            --bytes;
    3.40 +        else if (UTF8_IsTrailingByte(c))
    3.41 +        {
    3.42 +            for (i = bytes - 1; i != 0; --i)
    3.43 +            {
    3.44 +                c = (unsigned char)src[i];
    3.45 +                trailing_bytes = UTF8_TrailingBytes(c);
    3.46 +                if (trailing_bytes)
    3.47 +                {
    3.48 +                    if (bytes - i != trailing_bytes + 1)
    3.49 +                        bytes = i;
    3.50 +
    3.51 +                    break;
    3.52 +                }
    3.53 +            }
    3.54 +        }
    3.55 +        SDL_memcpy(dst, src, bytes);
    3.56 +    }
    3.57 +    dst[bytes] = '\0';
    3.58 +    return bytes;
    3.59 +}
    3.60 +
    3.61  #ifndef HAVE_STRLCAT
    3.62  size_t
    3.63  SDL_strlcat(char *dst, const char *src, size_t maxlen)