From 4e8720a40dff785e1e79e89e8985072e5d95d967 Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Wed, 12 Aug 2026 16:43:57 +0900 Subject: [PATCH] fix: terminate XIM UTF-8 text runs --- tests/xim_test.c | 21 +++++++++++++++++++++ xim/ximtext.c | 38 ++++++++++++++++++++++++++------------ xim/ximtext.h | 1 + 3 files changed, 48 insertions(+), 12 deletions(-) diff --git a/tests/xim_test.c b/tests/xim_test.c index ffb2aee..17ea467 100644 --- a/tests/xim_test.c +++ b/tests/xim_test.c @@ -32,6 +32,26 @@ checktext(const char *s) free(ct); } +static void +checkfallback(void) +{ + static const char s[] = "😀"; + static const char want[] = "\033%G😀\033%@"; + char *ct, *utf8; + size_t clen, ulen; + + ct = ximutf8compound(s, sizeof s - 1, &clen); + assert(ct != NULL); + assert(clen == sizeof want - 1); + assert(memcmp(ct, want, clen) == 0); + utf8 = xcb_compound_text_to_utf8(ct, clen, &ulen); + assert(utf8 != NULL); + assert(ulen == sizeof s - 1); + assert(memcmp(utf8, s, ulen) == 0); + free(utf8); + free(ct); +} + int main(void) { @@ -61,5 +81,6 @@ main(void) checktext("😀"); checktext("❤️"); checktext("A😀한"); + checkfallback(); return 0; } diff --git a/xim/ximtext.c b/xim/ximtext.c index 5e59db2..f6087b5 100644 --- a/xim/ximtext.c +++ b/xim/ximtext.c @@ -4,25 +4,39 @@ #include #include "ximtext.h" +char* +ximutf8compound(const char *s, size_t len, size_t *outlen) +{ + static const char begin[] = "\033%G"; + static const char end[] = "\033%@"; + char *ct; + size_t n; + + if(s == NULL || len > SIZE_MAX - (sizeof begin + sizeof end - 1)) + return NULL; + n = len + sizeof begin + sizeof end - 2; + ct = malloc(n + 1); + if(ct == NULL) + return NULL; + memcpy(ct, begin, sizeof begin - 1); + memcpy(ct + sizeof begin - 1, s, len); + memcpy(ct + sizeof begin - 1 + len, end, sizeof end - 1); + ct[n] = '\0'; + if(outlen != NULL) + *outlen = n; + return ct; +} + char* ximcompound(const char *s, size_t len, size_t *outlen) { - static const char utf8[] = "\033%G"; char *ct; - if(s == NULL || len > SIZE_MAX - sizeof utf8) + if(s == NULL) return NULL; ct = xcb_utf8_to_compound_text(s, len, outlen); if(ct != NULL) return ct; - /* X11 Compound Text reserves ESC % G for an embedded UTF-8 run. */ - ct = malloc(len + sizeof utf8); - if(ct == NULL) - return NULL; - memcpy(ct, utf8, sizeof utf8 - 1); - memcpy(ct + sizeof utf8 - 1, s, len); - ct[len + sizeof utf8 - 1] = '\0'; - if(outlen != NULL) - *outlen = len + sizeof utf8 - 1; - return ct; + /* X.Org Compound Text extension for characters in no legacy charset. */ + return ximutf8compound(s, len, outlen); } diff --git a/xim/ximtext.h b/xim/ximtext.h index 0e793af..4f1ed4b 100644 --- a/xim/ximtext.h +++ b/xim/ximtext.h @@ -1,3 +1,4 @@ #include char *ximcompound(const char*, size_t, size_t*); +char *ximutf8compound(const char*, size_t, size_t*);