diff --git a/Marlin/src/sd/SdBaseFile.cpp b/Marlin/src/sd/SdBaseFile.cpp index 48ee94780e..a40f20c4f2 100644 --- a/Marlin/src/sd/SdBaseFile.cpp +++ b/Marlin/src/sd/SdBaseFile.cpp @@ -1122,47 +1122,45 @@ int8_t SdBaseFile::readDir(dir_t* dir, char* longFilename) { } } - // Return if normal file or subdirectory - if (DIR_IS_FILE_OR_SUBDIR(dir)) { - #if ENABLED(UTF_FILENAME_SUPPORT) - if (longFilename) { - // Convert filename from utf-16 to utf-8 as Marlin expects - #if LONG_FILENAME_CHARSIZE > 2 - // Add warning for developers for currently not supported 3-byte cases (Conversion series of 2-byte - // codepoints to 3-byte in-place will break the rest of filename) - #error "Currently filename re-encoding is done in-place. It may break the remaining chars to use 3-byte codepoints." - #endif - uint16_t currentPos = 0; + #if ENABLED(UTF_FILENAME_SUPPORT) + // Return if normal file or subdirectory + if (DIR_IS_FILE_OR_SUBDIR(dir)) { + // Convert filename from utf-16 to utf-8 as Marlin expects + #if LONG_FILENAME_CHARSIZE > 2 + // Add warning for developers for currently not supported 3-byte cases (Conversion series of 2-byte + // codepoints to 3-byte in-place will break the rest of filename) + #error "Currently filename re-encoding is done in-place. It may break the remaining chars to use 3-byte codepoints." + #endif - LOOP_L_N(i, (LONG_FILENAME_LENGTH / 2)) { - uint16_t idx = i * 2; // This is fixed as FAT LFN always contain UTF-16LE encoding + // Is there a long filename to decode? + if (!longFilename) return n; // sizeof(dir_t) - uint16_t utf16_ch = longFilename[idx] | (longFilename[idx + 1] << 8); - if (0xD800 == (utf16_ch & 0xF800)) // Surrogate pair - encode as '_' - longFilename[currentPos++] = '_'; - else if (0 == (utf16_ch & 0xFF80)) // Encode as 1-byte utf-8 char - longFilename[currentPos++] = utf16_ch & 0x007F; - else if (0 == (utf16_ch & 0xF800)) { // Encode as 2-byte utf-8 char - longFilename[currentPos++] = 0xC0 | ((utf16_ch >> 6) & 0x1F); - longFilename[currentPos++] = 0x80 | (utf16_ch & 0x3F); - } - else { - #if LONG_FILENAME_CHARSIZE > 2 // Encode as 3-byte utf-8 char - longFilename[currentPos++] = 0xE0 | ((utf16_ch >> 12) & 0x0F); - longFilename[currentPos++] = 0xC0 | ((utf16_ch >> 6) & 0x3F); - longFilename[currentPos++] = 0xC0 | (utf16_ch & 0x3F); - #else // Encode as '_' - longFilename[currentPos++] = '_'; - #endif - } - - if (0 == utf16_ch) break; // End of filename + // Reset n to the start of the long name + n = 0; + for (uint16_t idx = 0; idx < (LONG_FILENAME_LENGTH) / 2; idx += 2) { // idx is fixed since FAT LFN always contains UTF-16LE encoding + uint16_t utf16_ch = longFilename[idx] | (longFilename[idx + 1] << 8); + if (0xD800 == (utf16_ch & 0xF800)) // Surrogate pair - encode as '_' + longFilename[n++] = '_'; + else if (0 == (utf16_ch & 0xFF80)) // Encode as 1-byte UTF-8 char + longFilename[n++] = utf16_ch & 0x007F; + else if (0 == (utf16_ch & 0xF800)) { // Encode as 2-byte UTF-8 char + longFilename[n++] = 0xC0 | ((utf16_ch >> 6) & 0x1F); + longFilename[n++] = 0x80 | ( utf16_ch & 0x3F); } - n = currentPos; + else { + #if LONG_FILENAME_CHARSIZE > 2 // Encode as 3-byte UTF-8 char + longFilename[n++] = 0xE0 | ((utf16_ch >> 12) & 0x0F); + longFilename[n++] = 0xC0 | ((utf16_ch >> 6) & 0x3F); + longFilename[n++] = 0xC0 | ( utf16_ch & 0x3F); + #else // Encode as '_' + longFilename[n++] = '_'; + #endif + } + if (0 == utf16_ch) break; // End of filename } - #endif - return n; - } + return n; + } + #endif } }