mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-09-21 18:58:13 +00:00
stdlib: Clean up and export SDL_UCS4ToUTF8().
Also fix internal usage of the function. Fixes #10157.
This commit is contained in:
@@ -1309,6 +1309,35 @@ extern SDL_DECLSPEC int SDLCALL SDL_strncasecmp(const char *str1, const char *st
|
||||
*/
|
||||
extern SDL_DECLSPEC Uint32 SDLCALL SDL_StepUTF8(const char **pstr, size_t *pslen);
|
||||
|
||||
/**
|
||||
* Convert a single Unicode codepoint to UTF-8.
|
||||
*
|
||||
* The buffer pointed to by `dst` must be at least 4 bytes long, as this
|
||||
* function may generate between 1 and 4 bytes of output.
|
||||
*
|
||||
* This function returns the first byte _after_ the newly-written UTF-8
|
||||
* sequence, which is useful for encoding multiple codepoints in a loop, or
|
||||
* knowing where to write a NULL-terminator character to end the string (in
|
||||
* either case, plan to have a buffer of _more_ than 4 bytes!).
|
||||
*
|
||||
* If `codepoint` is an invalid value (outside the Unicode range, or a UTF-16
|
||||
* surrogate value, etc), this will use U+FFFD (REPLACEMENT CHARACTER) for
|
||||
* the codepoint instead, and not set an error.
|
||||
*
|
||||
* If `dst` is NULL, this returns NULL immediately without writing to the
|
||||
* pointer and without setting an error.
|
||||
*
|
||||
* \param codepoint a Unicode codepoint to convert to UTF-8.
|
||||
* \param dst the location to write the encoded UTF-8. Must point to at least 4 bytes!
|
||||
* \returns the first byte past the newly-written UTF-8 sequence.
|
||||
*
|
||||
* \threadsafety It is safe to call this function from any thread.
|
||||
*
|
||||
* \since This function is available since SDL 3.0.0.
|
||||
*/
|
||||
extern SDL_DECLSPEC char * SDLCALL SDL_UCS4ToUTF8(Uint32 codepoint, char *dst);
|
||||
|
||||
|
||||
extern SDL_DECLSPEC int SDLCALL SDL_sscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, ...) SDL_SCANF_VARARG_FUNC(2);
|
||||
extern SDL_DECLSPEC int SDLCALL SDL_vsscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, va_list ap) SDL_SCANF_VARARG_FUNCV(2);
|
||||
extern SDL_DECLSPEC int SDLCALL SDL_snprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, ... ) SDL_PRINTF_VARARG_FUNC(3);
|
||||
|
@@ -101,31 +101,6 @@ SDL_bool SDL_endswith(const char *string, const char *suffix)
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
char *SDL_UCS4ToUTF8(Uint32 ch, char *dst)
|
||||
{
|
||||
Uint8 *p = (Uint8 *)dst;
|
||||
if (ch <= 0x7F) {
|
||||
*p = (Uint8)ch;
|
||||
++dst;
|
||||
} else if (ch <= 0x7FF) {
|
||||
p[0] = 0xC0 | (Uint8)((ch >> 6) & 0x1F);
|
||||
p[1] = 0x80 | (Uint8)(ch & 0x3F);
|
||||
dst += 2;
|
||||
} else if (ch <= 0xFFFF) {
|
||||
p[0] = 0xE0 | (Uint8)((ch >> 12) & 0x0F);
|
||||
p[1] = 0x80 | (Uint8)((ch >> 6) & 0x3F);
|
||||
p[2] = 0x80 | (Uint8)(ch & 0x3F);
|
||||
dst += 3;
|
||||
} else {
|
||||
p[0] = 0xF0 | (Uint8)((ch >> 18) & 0x07);
|
||||
p[1] = 0x80 | (Uint8)((ch >> 12) & 0x3F);
|
||||
p[2] = 0x80 | (Uint8)((ch >> 6) & 0x3F);
|
||||
p[3] = 0x80 | (Uint8)(ch & 0x3F);
|
||||
dst += 4;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
/* Assume we can wrap SDL_AtomicInt values and cast to Uint32 */
|
||||
SDL_COMPILE_TIME_ASSERT(sizeof_object_id, sizeof(int) == sizeof(Uint32));
|
||||
|
||||
|
@@ -32,8 +32,6 @@ extern void SDL_CalculateFraction(float x, int *numerator, int *denominator);
|
||||
|
||||
extern SDL_bool SDL_endswith(const char *string, const char *suffix);
|
||||
|
||||
extern char *SDL_UCS4ToUTF8(Uint32 ch, char *dst);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SDL_OBJECT_TYPE_UNKNOWN,
|
||||
|
@@ -811,6 +811,7 @@ SDL3_0.0.0 {
|
||||
SDL_TryLockRWLockForWriting;
|
||||
SDL_TryLockSpinlock;
|
||||
SDL_TryWaitSemaphore;
|
||||
SDL_UCS4ToUTF8;
|
||||
SDL_UnbindAudioStream;
|
||||
SDL_UnbindAudioStreams;
|
||||
SDL_UnloadObject;
|
||||
|
@@ -836,6 +836,7 @@
|
||||
#define SDL_TryLockRWLockForWriting SDL_TryLockRWLockForWriting_REAL
|
||||
#define SDL_TryLockSpinlock SDL_TryLockSpinlock_REAL
|
||||
#define SDL_TryWaitSemaphore SDL_TryWaitSemaphore_REAL
|
||||
#define SDL_UCS4ToUTF8 SDL_UCS4ToUTF8_REAL
|
||||
#define SDL_UnbindAudioStream SDL_UnbindAudioStream_REAL
|
||||
#define SDL_UnbindAudioStreams SDL_UnbindAudioStreams_REAL
|
||||
#define SDL_UnloadObject SDL_UnloadObject_REAL
|
||||
|
@@ -846,6 +846,7 @@ SDL_DYNAPI_PROC(int,SDL_TryLockRWLockForReading,(SDL_RWLock *a),(a),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_TryLockRWLockForWriting,(SDL_RWLock *a),(a),return)
|
||||
SDL_DYNAPI_PROC(SDL_bool,SDL_TryLockSpinlock,(SDL_SpinLock *a),(a),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_TryWaitSemaphore,(SDL_Semaphore *a),(a),return)
|
||||
SDL_DYNAPI_PROC(char*,SDL_UCS4ToUTF8,(Uint32 a, char *b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(void,SDL_UnbindAudioStream,(SDL_AudioStream *a),(a),)
|
||||
SDL_DYNAPI_PROC(void,SDL_UnbindAudioStreams,(SDL_AudioStream **a, int b),(a,b),)
|
||||
SDL_DYNAPI_PROC(void,SDL_UnloadObject,(void *a),(a),)
|
||||
|
@@ -42,6 +42,42 @@
|
||||
SDL_COMPILE_TIME_ASSERT(sizeof_wchar_t, sizeof(wchar_t) == SDL_SIZEOF_WCHAR_T);
|
||||
|
||||
|
||||
char *SDL_UCS4ToUTF8(Uint32 codepoint, char *dst)
|
||||
{
|
||||
if (!dst) {
|
||||
return NULL; // I guess...?
|
||||
} else if (codepoint > 0x10FFFF) { // Outside the range of Unicode codepoints (also, larger than can be encoded in 4 bytes of UTF-8!).
|
||||
codepoint = SDL_INVALID_UNICODE_CODEPOINT;
|
||||
} else if ((codepoint >= 0xD800) && (codepoint <= 0xDFFF)) { // UTF-16 surrogate values are illegal in UTF-8.
|
||||
codepoint = SDL_INVALID_UNICODE_CODEPOINT;
|
||||
}
|
||||
|
||||
Uint8 *p = (Uint8 *)dst;
|
||||
if (codepoint <= 0x7F) {
|
||||
*p = (Uint8)codepoint;
|
||||
++dst;
|
||||
} else if (codepoint <= 0x7FF) {
|
||||
p[0] = 0xC0 | (Uint8)((codepoint >> 6) & 0x1F);
|
||||
p[1] = 0x80 | (Uint8)(codepoint & 0x3F);
|
||||
dst += 2;
|
||||
} else if (codepoint <= 0xFFFF) {
|
||||
p[0] = 0xE0 | (Uint8)((codepoint >> 12) & 0x0F);
|
||||
p[1] = 0x80 | (Uint8)((codepoint >> 6) & 0x3F);
|
||||
p[2] = 0x80 | (Uint8)(codepoint & 0x3F);
|
||||
dst += 3;
|
||||
} else {
|
||||
SDL_assert(codepoint <= 0x10FFFF);
|
||||
p[0] = 0xF0 | (Uint8)((codepoint >> 18) & 0x07);
|
||||
p[1] = 0x80 | (Uint8)((codepoint >> 12) & 0x3F);
|
||||
p[2] = 0x80 | (Uint8)((codepoint >> 6) & 0x3F);
|
||||
p[3] = 0x80 | (Uint8)(codepoint & 0x3F);
|
||||
dst += 4;
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
// this expects `from` and `to` to be UTF-32 encoding!
|
||||
int SDL_CaseFoldUnicode(const Uint32 from, Uint32 *to)
|
||||
{
|
||||
|
@@ -543,9 +543,9 @@ static EM_BOOL Emscripten_HandleKeyPress(int eventType, const EmscriptenKeyboard
|
||||
|
||||
if (SDL_TextInputActive(window_data->window)) {
|
||||
char text[5];
|
||||
if (SDL_UCS4ToUTF8(keyEvent->charCode, text)) {
|
||||
char *end = SDL_UCS4ToUTF8(keyEvent->charCode, text);
|
||||
*end = '\0';
|
||||
SDL_SendKeyboardText(text);
|
||||
}
|
||||
return EM_TRUE;
|
||||
}
|
||||
return EM_FALSE;
|
||||
|
@@ -1286,10 +1286,10 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
|
||||
} else {
|
||||
if (SDL_TextInputActive(data->window)) {
|
||||
char text[5];
|
||||
if (SDL_UCS4ToUTF8((Uint32)wParam, text) != text) {
|
||||
char *end = SDL_UCS4ToUTF8((Uint32)wParam, text);
|
||||
*end = '\0';
|
||||
SDL_SendKeyboardText(text);
|
||||
}
|
||||
}
|
||||
returnCode = 0;
|
||||
}
|
||||
break;
|
||||
|
Reference in New Issue
Block a user