Fix UTF filename scroll (#20121)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									288eb06708
								
							
						
					
					
						commit
						99c377b4e4
					
				@ -461,8 +461,8 @@ 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) {
 | 
					    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 (mark_as_selected(row, sel)) {
 | 
				
			||||||
 | 
					        const uint8_t maxlen = LCD_WIDTH - isDir;
 | 
				
			||||||
        if (isDir) lcd_put_wchar(LCD_STR_FOLDER[0]);
 | 
					        if (isDir) lcd_put_wchar(LCD_STR_FOLDER[0]);
 | 
				
			||||||
        constexpr uint8_t maxlen = LCD_WIDTH - 1;
 | 
					 | 
				
			||||||
        const pixel_len_t pixw = maxlen * (MENU_FONT_WIDTH);
 | 
					        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);
 | 
					        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(' ');
 | 
					        while (n > MENU_FONT_WIDTH) n -= lcd_put_wchar(' ');
 | 
				
			||||||
 | 
				
			|||||||
@ -75,6 +75,11 @@ int pf_bsearch_r(void *userdata, size_t num_data, pf_bsearch_cb_comp_t cb_comp,
 | 
				
			|||||||
  return -1;
 | 
					  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
 | 
					/* This function gets the character at the pstart position, interpreting UTF8 multibyte sequences
 | 
				
			||||||
   and returns the pointer to the next character */
 | 
					   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) {
 | 
					uint8_t* get_utf8_value_cb(uint8_t *pstart, read_byte_cb_t cb_read_byte, wchar_t *pval) {
 | 
				
			||||||
@ -131,8 +136,8 @@ uint8_t* get_utf8_value_cb(uint8_t *pstart, read_byte_cb_t cb_read_byte, wchar_t
 | 
				
			|||||||
      p++;
 | 
					      p++;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
  else if (0x80 == (0xC0 & valcur))
 | 
					  else if (!utf8_is_start_byte_of_char(valcur))
 | 
				
			||||||
    for (; 0x80 == (0xC0 & valcur); ) { p++; valcur = cb_read_byte(p); }
 | 
					    for (; !utf8_is_start_byte_of_char(valcur); ) { p++; valcur = cb_read_byte(p); }
 | 
				
			||||||
  else
 | 
					  else
 | 
				
			||||||
    for (; 0xFC < (0xFE & valcur); ) { p++; valcur = cb_read_byte(p); }
 | 
					    for (; 0xFC < (0xFE & valcur); ) { p++; valcur = cb_read_byte(p); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -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) {
 | 
					static inline uint8_t utf8_strlen_cb(const char *pstart, read_byte_cb_t cb_read_byte) {
 | 
				
			||||||
  uint8_t cnt = 0;
 | 
					  uint8_t cnt = 0;
 | 
				
			||||||
  uint8_t *pnext = (uint8_t *)pstart;
 | 
					  uint8_t *p = (uint8_t *)pstart;
 | 
				
			||||||
  for (;;) {
 | 
					  for (;;) {
 | 
				
			||||||
    wchar_t ch;
 | 
					    const uint8_t b = cb_read_byte(p);
 | 
				
			||||||
    pnext = get_utf8_value_cb(pnext, cb_read_byte, &ch);
 | 
					    if (!b) break;
 | 
				
			||||||
    if (!ch) break;
 | 
					    if (utf8_is_start_byte_of_char(b)) cnt++;
 | 
				
			||||||
    cnt++;
 | 
					    p++;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return cnt;
 | 
					  return cnt;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -160,3 +165,26 @@ uint8_t utf8_strlen(const char *pstart) {
 | 
				
			|||||||
uint8_t utf8_strlen_P(PGM_P pstart) {
 | 
					uint8_t utf8_strlen_P(PGM_P pstart) {
 | 
				
			||||||
  return utf8_strlen_cb(pstart, read_byte_rom);
 | 
					  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 (;;) {
 | 
				
			||||||
 | 
					    const 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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -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 */
 | 
					/* Returns length of string in CHARACTERS, NOT BYTES */
 | 
				
			||||||
uint8_t utf8_strlen(const char *pstart);
 | 
					uint8_t utf8_strlen(const char *pstart);
 | 
				
			||||||
uint8_t utf8_strlen_P(PGM_P 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);
 | 
				
			||||||
 | 
				
			|||||||
@ -208,10 +208,13 @@ millis_t MarlinUI::next_button_update_ms; // = 0
 | 
				
			|||||||
            filename_scroll_pos = 0;                                       // Reset scroll to the start
 | 
					            filename_scroll_pos = 0;                                       // Reset scroll to the start
 | 
				
			||||||
            lcd_status_update_delay = 8;                                   // Don't scroll right away
 | 
					            lcd_status_update_delay = 8;                                   // Don't scroll right away
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          outstr += filename_scroll_pos;
 | 
					          // Advance byte position corresponding to filename_scroll_pos char position
 | 
				
			||||||
 | 
					          outstr += TERN(UTF_FILENAME_SUPPORT, utf8_byte_pos_by_char_num(outstr, filename_scroll_pos), filename_scroll_pos);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      #else
 | 
					      #else
 | 
				
			||||||
        theCard.longFilename[maxlen] = '\0'; // cutoff at screen edge
 | 
					        theCard.longFilename[
 | 
				
			||||||
 | 
					          TERN(UTF_FILENAME_SUPPORT, utf8_byte_pos_by_char_num(theCard.longFilename, maxlen), maxlen)
 | 
				
			||||||
 | 
					        ] = '\0'; // cutoff at screen edge
 | 
				
			||||||
      #endif
 | 
					      #endif
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return outstr;
 | 
					    return outstr;
 | 
				
			||||||
@ -1006,11 +1009,8 @@ void MarlinUI::update() {
 | 
				
			|||||||
      // If scrolling of long file names is enabled and we are in the sd card menu,
 | 
					      // If scrolling of long file names is enabled and we are in the sd card menu,
 | 
				
			||||||
      // cause a refresh to occur until all the text has scrolled into view.
 | 
					      // cause a refresh to occur until all the text has scrolled into view.
 | 
				
			||||||
      if (currentScreen == menu_media && !lcd_status_update_delay--) {
 | 
					      if (currentScreen == menu_media && !lcd_status_update_delay--) {
 | 
				
			||||||
        lcd_status_update_delay = 4;
 | 
					        lcd_status_update_delay = ++filename_scroll_pos >= filename_scroll_max ? 12 : 4; // Long delay at end and start
 | 
				
			||||||
        if (++filename_scroll_pos > filename_scroll_max) {
 | 
					        if (filename_scroll_pos > filename_scroll_max) filename_scroll_pos = 0;
 | 
				
			||||||
          filename_scroll_pos = 0;
 | 
					 | 
				
			||||||
          lcd_status_update_delay = 12;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        refresh(LCDVIEW_REDRAW_NOW);
 | 
					        refresh(LCDVIEW_REDRAW_NOW);
 | 
				
			||||||
        RESET_STATUS_TIMEOUT();
 | 
					        RESET_STATUS_TIMEOUT();
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user