Skip to content

fix: keep whole UTF-8 characters in GFX_truncateText() - #876

Open
nborodikhin wants to merge 2 commits into
LoveRetro:mainfrom
nborodikhin:fix/truncate-text-utf8
Open

nborodikhin wants to merge 2 commits into
LoveRetro:mainfrom
nborodikhin:fix/truncate-text-utf8

Conversation

@nborodikhin

@nborodikhin nborodikhin commented Oct 25, 2026 •

Copy link
Copy Markdown

Description

NextUI's GFX_truncateText() is used to cut a long text to fit the screen and put an ellipsis "..." at the end. The current code works on a byte basis, which works for ASCII but is generally wrong for multi-byte UTF8 characters. The truncation also has a bug - for too short a string, it would write the memory before the start of the output buffer.

Change

  • GFX_truncateText()
    • remove whole UTF-8 characters from the end, and keep the result no longer than the input
    • stop when no text is left, thus the function never writes before out_name

Testing

  • desktop run: cut Cyrillic and accented Latin text at widths one character apart, each result is valid UTF-8
  • desktop run: text that wraps to 2 lines truncates its last line to valid UTF-8

Note red "BAD" marks - an invalid UTF-8 string results in extra space between the truncated character and the ellipsis.

  Before After
GFX_truncateText GFX_truncateText before the fix GFX_truncateText after the fix
GFX_wrapText() with 2 lines GFX_wrapText before the fix GFX_wrapText after the fix

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.
@nborodikhin
nborodikhin marked this pull request as ready for review October 25, 2026 20:21
nborodikhin added a commit to nborodikhin/nextui-music-player that referenced this pull request Oct 26, 2026
## Description

Now Playing shows `???` or an empty field for a track with Chinese or
Japanese tags encoded as UTF16 characters.

The root cause is that id3 tag reader reads UTF16 characters, but drops
everything above U+00FF, and `???` is used as a default value.

This change improves reading phase, ensuring internal representation of
text as UTF-8, and fixes a few related issues.

Addresses issue #63 - `Now Playing show ??? or nothing`

## Change

- `utf8.c`
- add `UTF8_fromUtf16()` and `UTF8_fromUnknown()` to convert UTF-16
text, and text with no declared charset, to UTF-8
- `id3.c` - ID3 utilities
  - text tag: the encoding byte, the end of a text, and the ID3v1 fields
- ignore an ID3v1 field of `?` and spaces, which a tagger writes for
characters not represented by ISO-8859-1
- `player.c`
- read ID3v2 frames, lyrics and the other tag formats with the new
converters
- take an ID3v1 field only where ID3v2 gives none, and the file name
only where no tag gives a title
- `icy.c` - ICY broadcasting functions
- `ICY_parseStreamTitle()` to read the stream title of a radio station
as UTF-8
- `radio_hls.c`
- read playlist titles and ID3 frames of HLS streams as UTF-8, including
UTF-16 frames
- `ui_utils.c`
  - add `UI_truncateText()` to cut text to a width at whole characters
- call it in place of `GFX_truncateText()` of NextUI, until
LoveRetro/NextUI#876 gives the same fix
- ensure the output buffer is at least the same size as the input
(confirmation dialog, podcast description)

## Testing

| | Before | After |
|---|---|---|
| Sample of #63<br>UTF-16 tag | <img width="300" alt="before-sample"
src="https://github.com/user-attachments/assets/869adb56-1757-42a3-8533-ca3d5ce3ea30"
/> | <img width="300" alt="after-sample"
src="https://github.com/user-attachments/assets/a79fdeeb-1214-432d-b29b-dd337f6123b1"
/> |
| Long artist<br>UTF-8 tag<br>truncation was wrong (space before
ellipsis) | <img width="300" alt="before-long"
src="https://github.com/user-attachments/assets/c8a15646-77f3-45af-9fdf-06f3710a803a"
/> | <img width="300" alt="after-long"
src="https://github.com/user-attachments/assets/f095e7f7-8ade-4d19-8360-91449ef48215"
/> |

- [x] unit tests
- [x] build of all platforms
- [x] #63: the sample file shows its CJK title and artist, not `???`
(device, Miyoo Flip)
- [x] a long Japanese artist ends in `...` with no broken character
(device, Miyoo Flip)
- [x] an ICY radio station and an HLS station show their stream titles
on a device
- [x] tested on my355

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant