From dcdf829699a571f62a74ee854f87fa503d5a4bb4 Mon Sep 17 00:00:00 2001 From: Nikita Borodikhin Date: Sun, 25 Oct 2026 15:03:19 -0500 Subject: [PATCH 1/2] fix: keep whole UTF-8 characters in GFX_truncateText() The old loop removed one byte for each pass. A cut inside a multi-byte character left invalid UTF-8 before the dots. When even "..." did not fit, the loop wrote before the start of out_name. --- workspace/all/common/api.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/workspace/all/common/api.c b/workspace/all/common/api.c index e107225da..ec33f6404 100644 --- a/workspace/all/common/api.c +++ b/workspace/all/common/api.c @@ -1018,14 +1018,27 @@ FALLBACK_IMPLEMENTATION void PLAT_setEffectColor(int next_color) {} int GFX_truncateText(TTF_Font *font, const char *in_name, char *out_name, int max_width, int padding) { int text_width; + int len = strlen(in_name); + int kept = len; strcpy(out_name, in_name); TTF_SizeUTF8(font, out_name, &text_width, NULL); text_width += padding; - while (text_width > max_width) + while (text_width > max_width && kept > 0) { - int len = strlen(out_name); - strcpy(&out_name[len - 4], "...\0"); + // remove whole UTF-8 characters until "..." fits in the bytes of the removed text + do + { + kept--; + while (kept > 0 && ((unsigned char)out_name[kept] & 0xC0) == 0x80) + kept--; + } while (kept > 0 && kept + 3 > len); + + if (kept + 3 <= len) + strcpy(&out_name[kept], "..."); + else + out_name[0] = '\0'; + TTF_SizeUTF8(font, out_name, &text_width, NULL); text_width += padding; } From 338df6fe75ebf66cb54f0a4e278f84f3bcd11d0d Mon Sep 17 00:00:00 2001 From: Nikita Borodikhin Date: Sun, 25 Oct 2026 15:19:54 -0500 Subject: [PATCH 2/2] chore: rename kept to keep_bytes in GFX_truncateText() --- workspace/all/common/api.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/workspace/all/common/api.c b/workspace/all/common/api.c index ec33f6404..7c6027eea 100644 --- a/workspace/all/common/api.c +++ b/workspace/all/common/api.c @@ -1019,23 +1019,23 @@ int GFX_truncateText(TTF_Font *font, const char *in_name, char *out_name, int ma { int text_width; int len = strlen(in_name); - int kept = len; + int keep_bytes = len; strcpy(out_name, in_name); TTF_SizeUTF8(font, out_name, &text_width, NULL); text_width += padding; - while (text_width > max_width && kept > 0) + while (text_width > max_width && keep_bytes > 0) { // remove whole UTF-8 characters until "..." fits in the bytes of the removed text do { - kept--; - while (kept > 0 && ((unsigned char)out_name[kept] & 0xC0) == 0x80) - kept--; - } while (kept > 0 && kept + 3 > len); + keep_bytes--; + while (keep_bytes > 0 && ((unsigned char)out_name[keep_bytes] & 0xC0) == 0x80) + keep_bytes--; + } while (keep_bytes > 0 && keep_bytes + 3 > len); - if (kept + 3 <= len) - strcpy(&out_name[kept], "..."); + if (keep_bytes + 3 <= len) + strcpy(&out_name[keep_bytes], "..."); else out_name[0] = '\0';