Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix incorrect UTF filename scrolling #20121

Merged
merged 6 commits into from
Nov 13, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Marlin/src/lcd/dogm/marlinui_DOGM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -461,8 +461,11 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop

void MenuItem_sdbase::draw(const bool sel, const uint8_t row, PGM_P const, CardReader &theCard, const bool isDir) {
if (mark_as_selected(row, sel)) {
if (isDir) lcd_put_wchar(LCD_STR_FOLDER[0]);
constexpr uint8_t maxlen = LCD_WIDTH - 1;
thinkyhead marked this conversation as resolved.
Show resolved Hide resolved
uint8_t maxlen = LCD_WIDTH;
if (isDir) {
lcd_put_wchar(LCD_STR_FOLDER[0]);
maxlen--;
}
const pixel_len_t pixw = maxlen * (MENU_FONT_WIDTH);
pixel_len_t n = pixw - lcd_put_u8str_max(ui.scrolled_filename(theCard, maxlen, row, sel), pixw);
while (n > MENU_FONT_WIDTH) n -= lcd_put_wchar(' ');
Expand Down
42 changes: 35 additions & 7 deletions Marlin/src/lcd/fontutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ int pf_bsearch_r(void *userdata, size_t num_data, pf_bsearch_cb_comp_t cb_comp,
return -1;
}

/* Returns true if passed byte is first byte of UTF-8 char sequence */
static inline bool utf8_is_start_byte_of_char(const uint8_t b) {
return 0x80 != (b & 0xC0);
}

/* This function gets the character at the pstart position, interpreting UTF8 multibyte sequences
and returns the pointer to the next character */
uint8_t* get_utf8_value_cb(uint8_t *pstart, read_byte_cb_t cb_read_byte, wchar_t *pval) {
Expand Down Expand Up @@ -131,8 +136,8 @@ uint8_t* get_utf8_value_cb(uint8_t *pstart, read_byte_cb_t cb_read_byte, wchar_t
p++;
}
#endif
else if (0x80 == (0xC0 & valcur))
for (; 0x80 == (0xC0 & valcur); ) { p++; valcur = cb_read_byte(p); }
else if (!utf8_is_start_byte_of_char(valcur))
thinkyhead marked this conversation as resolved.
Show resolved Hide resolved
for (; !utf8_is_start_byte_of_char(valcur); ) { p++; valcur = cb_read_byte(p); }
else
for (; 0xFC < (0xFE & valcur); ) { p++; valcur = cb_read_byte(p); }

Expand All @@ -143,12 +148,12 @@ uint8_t* get_utf8_value_cb(uint8_t *pstart, read_byte_cb_t cb_read_byte, wchar_t

static inline uint8_t utf8_strlen_cb(const char *pstart, read_byte_cb_t cb_read_byte) {
uint8_t cnt = 0;
uint8_t *pnext = (uint8_t *)pstart;
uint8_t *p = (uint8_t *)pstart;
for (;;) {
wchar_t ch;
pnext = get_utf8_value_cb(pnext, cb_read_byte, &ch);
thinkyhead marked this conversation as resolved.
Show resolved Hide resolved
if (!ch) break;
cnt++;
uint8_t b = cb_read_byte(p);
if (!b) break;
if (utf8_is_start_byte_of_char(b)) cnt++;
p++;
}
return cnt;
}
Expand All @@ -160,3 +165,26 @@ uint8_t utf8_strlen(const char *pstart) {
uint8_t utf8_strlen_P(PGM_P pstart) {
return utf8_strlen_cb(pstart, read_byte_rom);
}

static inline uint8_t utf8_byte_pos_by_char_num_cb(const char *pstart, read_byte_cb_t cb_read_byte, const uint8_t charnum) {
uint8_t *p = (uint8_t *)pstart;
uint8_t char_idx = 0;
uint8_t byte_idx = 0;
for (;;) {
uint8_t b = cb_read_byte(p+byte_idx);
if (!b) return byte_idx; // Termination byte of string
if (utf8_is_start_byte_of_char(b)) {
char_idx++;
if (char_idx == charnum + 1) return byte_idx;
}
byte_idx++;
}
}

uint8_t utf8_byte_pos_by_char_num(const char *pstart, const uint8_t charnum) {
return utf8_byte_pos_by_char_num_cb(pstart, read_byte_ram, charnum);
}

uint8_t utf8_byte_pos_by_char_num_P(PGM_P pstart, const uint8_t charnum) {
return utf8_byte_pos_by_char_num_cb(pstart, read_byte_rom, charnum);
}
4 changes: 4 additions & 0 deletions Marlin/src/lcd/fontutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,7 @@ uint8_t* get_utf8_value_cb(uint8_t *pstart, read_byte_cb_t cb_read_byte, wchar_t
/* Returns length of string in CHARACTERS, NOT BYTES */
uint8_t utf8_strlen(const char *pstart);
uint8_t utf8_strlen_P(PGM_P pstart);

/* Returns start byte position of desired char number */
uint8_t utf8_byte_pos_by_char_num(const char *pstart, const uint8_t charnum);
uint8_t utf8_byte_pos_by_char_num_P(PGM_P pstart, const uint8_t charnum);
18 changes: 15 additions & 3 deletions Marlin/src/lcd/marlinui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,10 +208,19 @@ millis_t MarlinUI::next_button_update_ms; // = 0
filename_scroll_pos = 0; // Reset scroll to the start
lcd_status_update_delay = 8; // Don't scroll right away
}
outstr += filename_scroll_pos;
#if ENABLED(UTF_FILENAME_SUPPORT)
// Advance byte position corresponding to filename_scroll_pos char position
outstr += utf8_byte_pos_by_char_num(outstr, filename_scroll_pos);
#else
outstr += filename_scroll_pos;
#endif
}
#else
theCard.longFilename[maxlen] = '\0'; // cutoff at screen edge
#if ENABLED(UTF_FILENAME_SUPPORT)
theCard.longFilename[utf8_byte_pos_by_char_num(theCard.longFilename, maxlen)] = '\0'; // cutoff at screen edge
#else
theCard.longFilename[maxlen] = '\0'; // cutoff at screen edge
#endif
#endif
}
return outstr;
Expand Down Expand Up @@ -1007,7 +1016,10 @@ void MarlinUI::update() {
// cause a refresh to occur until all the text has scrolled into view.
if (currentScreen == menu_media && !lcd_status_update_delay--) {
lcd_status_update_delay = 4;
if (++filename_scroll_pos > filename_scroll_max) {
filename_scroll_pos++;
if (filename_scroll_pos == filename_scroll_max){
lcd_status_update_delay = 12;
thinkyhead marked this conversation as resolved.
Show resolved Hide resolved
} else if (filename_scroll_pos > filename_scroll_max) {
filename_scroll_pos = 0;
lcd_status_update_delay = 12;
}
Expand Down