feat: filesystem and Files app support for >64 file entries, 64-bit sizes, async ops, GUI toolkit improvements to devexplorer app

This commit is contained in:
2026-06-07 09:33:46 +02:00
parent fc5f5cacf0
commit 427876afa7
27 changed files with 1110 additions and 293 deletions
@@ -8,34 +8,25 @@
namespace filemanager {
static bool path_is_same_or_descendant(const char* path, const char* root) {
if (!path || !root) return false;
int root_len = montauk::slen(root);
while (root_len > 0 && root[root_len - 1] == '/') root_len--;
if (root_len <= 0) return false;
for (int i = 0; i < root_len; i++) {
if (path[i] == '\0' || path[i] != root[i]) return false;
}
return path[root_len] == '\0' || path[root_len] == '/';
}
static void filemanager_load_clipboard(FileManagerState* fm, bool is_cut) {
if (filemanager_is_computer_view(fm) || filemanager_is_virtual_view(fm)) return;
if (fm->entry_count <= 0) return;
int sel[64];
int n = filemanager_collect_selection(fm, sel, 64);
if (n <= 0) return;
int* sel = (int*)montauk::malloc((uint64_t)fm->entry_count * sizeof(int));
if (!sel) return;
int n = filemanager_collect_selection(fm, sel, fm->entry_count);
if (n <= 0) { montauk::mfree(sel); return; }
if (!filemanager_ensure_clipboard_capacity(fm, n)) { montauk::mfree(sel); return; }
int out = 0;
for (int i = 0; i < n && out < 64; i++) {
for (int i = 0; i < n && out < fm->clipboard_cap; i++) {
int idx = sel[i];
if (fm->entry_types[idx] == FM_ENTRY_DRIVE) continue;
filemanager_build_fullpath(fm->clipboard_paths[out], 256,
fm->current_path, fm->entry_names[idx]);
out++;
}
montauk::mfree(sel);
if (out == 0) return;
fm->clipboard_count = out;
@@ -51,35 +42,9 @@ void filemanager_do_cut(FileManagerState* fm) {
}
void filemanager_do_paste(FileManagerState* fm) {
if (fm->clipboard_count <= 0 ||
filemanager_is_computer_view(fm) || filemanager_is_virtual_view(fm)) return;
bool any_ok = false;
bool clear_clipboard = fm->clipboard_is_cut;
for (int i = 0; i < fm->clipboard_count; i++) {
const char* src = fm->clipboard_paths[i];
const char* basename = path_basename(src);
char dst[512];
filemanager_build_fullpath(dst, 512, fm->current_path, basename);
if (montauk::streq(dst, src)) continue;
const char* probe[1];
int probe_count = montauk::readdir(src, probe, 1);
bool src_is_dir = (probe_count >= 0);
if (src_is_dir && path_is_same_or_descendant(dst, src)) continue;
bool ok = src_is_dir ? filemanager_copy_dir_recursive(src, dst)
: filemanager_copy_file(src, dst);
any_ok = any_ok || ok;
if (ok && fm->clipboard_is_cut) {
if (src_is_dir) filemanager_delete_recursive(src);
else montauk::fdelete(src);
}
}
if (clear_clipboard) fm->clipboard_count = 0;
if (any_ok) filemanager_read_dir(fm);
// Copy/move runs on a worker thread with a progress dialog (a small single
// file pastes inline). Same-volume moves use rename (instant, no copy).
filemanager_start_paste_job(fm);
}
void filemanager_start_rename(FileManagerState* fm) {
@@ -157,13 +122,16 @@ void filemanager_new_folder(FileManagerState* fm) {
void filemanager_delete_selected(FileManagerState* fm) {
if (filemanager_is_computer_view(fm) || filemanager_is_virtual_view(fm)) return;
if (fm->entry_count <= 0) return;
int sel[64];
int n = filemanager_collect_selection(fm, sel, 64);
if (n <= 0) return;
int* sel = (int*)montauk::malloc((uint64_t)fm->entry_count * sizeof(int));
if (!sel) return;
int n = filemanager_collect_selection(fm, sel, fm->entry_count);
if (n <= 0) { montauk::mfree(sel); return; }
// Filter out drives.
int filtered[64];
int* filtered = (int*)montauk::malloc((uint64_t)n * sizeof(int));
if (!filtered) { montauk::mfree(sel); return; }
int fn = 0;
bool any_dir = false;
for (int i = 0; i < n; i++) {
@@ -172,7 +140,8 @@ void filemanager_delete_selected(FileManagerState* fm) {
filtered[fn++] = idx;
if (fm->is_dir[idx]) any_dir = true;
}
if (fn == 0) return;
montauk::mfree(sel);
if (fn == 0) { montauk::mfree(filtered); return; }
// Anything with a directory or multi-item selection: confirm first.
if (any_dir || fn > 1) {
@@ -181,6 +150,7 @@ void filemanager_delete_selected(FileManagerState* fm) {
} else {
filemanager_show_bulk_delete_confirmation(fm, filtered, fn);
}
montauk::mfree(filtered);
return;
}
@@ -188,6 +158,7 @@ void filemanager_delete_selected(FileManagerState* fm) {
char fullpath[512];
filemanager_build_fullpath(fullpath, 512,
fm->current_path, fm->entry_names[filtered[0]]);
montauk::mfree(filtered);
montauk::fdelete(fullpath);
filemanager_clear_multi_selection(fm);
filemanager_read_dir(fm);