diff --git a/src/uosc/lib/utils.lua b/src/uosc/lib/utils.lua index d001ed1a..8156793d 100644 --- a/src/uosc/lib/utils.lua +++ b/src/uosc/lib/utils.lua @@ -5,7 +5,55 @@ --- In place sorting of filenames ---@param filenames string[] -function sort_filenames(filenames) + +-- this function was taken from https://github.com/mpvnet-player/mpv.net/issues/575#issuecomment-1817413401 +local winapi = {} + +if state.platform == 'windows' then + local is_ffi_loaded, ffi = pcall(require, 'ffi') + + if is_ffi_loaded then + winapi = { + ffi = ffi, + C = ffi.C, + CP_UTF8 = 65001, + shlwapi = ffi.load('shlwapi'), + } + + -- ffi code from https://github.com/po5/thumbfast, Mozilla Public License Version 2.0 + ffi.cdef[[ + int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, + int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar); + int __stdcall StrCmpLogicalW(wchar_t *psz1, wchar_t *psz2); + ]] + + winapi.utf8_to_wide = function(utf8_str) + if utf8_str then + local utf16_len = winapi.C.MultiByteToWideChar(winapi.CP_UTF8, 0, utf8_str, -1, nil, 0) + + if utf16_len > 0 then + local utf16_str = winapi.ffi.new('wchar_t[?]', utf16_len) + + if winapi.C.MultiByteToWideChar(winapi.CP_UTF8, 0, utf8_str, -1, utf16_str, utf16_len) > 0 then + return utf16_str + end + end + end + + return '' + end + end +end + +function sort_filenames_windows(filenames) + table.sort(filenames, function(a, b) + local a_wide = winapi.utf8_to_wide(a) + local b_wide = winapi.utf8_to_wide(b) + return winapi.shlwapi.StrCmpLogicalW(a_wide, b_wide) == -1 + end) +end + +function sort_filenames_lua(filenames) -- alphanum sorting for humans in Lua -- http://notebook.kulchenko.com/algorithms/alphanumeric-natural-sorting-for-humans-in-lua local function padnum(n, d) @@ -24,6 +72,15 @@ function sort_filenames(filenames) return filenames end +function sort_filenames(filenames) + local is_ffi_loaded = pcall(require, 'ffi') + if state.platform == 'windows' and is_ffi_loaded then + sort_filenames_windows(filenames) + else + sort_filenames_lua(filenames) + end +end + -- Creates in-between frames to animate value from `from` to `to` numbers. ---@param from number ---@param to number|fun():number