diff options
Diffstat (limited to 'src/user/fileman')
-rw-r--r-- | src/user/fileman/fileman.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/src/user/fileman/fileman.c b/src/user/fileman/fileman.c new file mode 100644 index 0000000..0b28d1d --- /dev/null +++ b/src/user/fileman/fileman.c @@ -0,0 +1,130 @@ +#include <pland/syscall.h> +#include <knob/block.h> +#include <knob/file.h> +#include <knob/heap.h> +#include <knob/task.h> + +char path_sz[1024] = ""; +uint32_t path_len = 0; + +_dir_info_entry_t *dir_info; +uint32_t dir_info_len; + +uint32_t scroll; +uint32_t selected; +#define MAX_PER_SCREEN 18 + +void paint_screen() { + _clear_screen(); + + _set_color(0x70); + _print_at(0, 0, path_sz); + _log_string("/"); + _set_color(0x07); + + for (uint32_t i = scroll, row = 2; (i < dir_info_len) && (row < MAX_PER_SCREEN + 2); ++i, ++row) { + if (i == selected) + _set_color(0x17); + _print_at(row, 0, dir_info[i].name); + if (dir_info[i].is_dir) + _log_string("/"); + if (i == selected) + _set_color(0x07); + } + + _print_at(21, 0, "keybindings:\n" + "UP, DOWN, PAGE UP, PAGE DOWN, HOME, END: move selection\n" + "ENTER: enter selected directory, run selected program\n" + "ESC: go up a directory Q: quit"); +} + +void load_dir() { + free_block(dir_info); + dir_info = get_directory_info(path_sz, &dir_info_len); + scroll = 0; + selected = 0; +} + +void main(const char *sz) { + path_len = strcpy(path_sz, sz); + dir_info = get_directory_info(sz, &dir_info_len); + + paint_screen(); + + while (true) { + _key_code_t key; + switch (key = _get_key()) { + case 0: + _yield_task(); + continue; + case '\n': + { + uint32_t old_len = path_len; + if (path_len) + path_sz[path_len++] = '/'; + path_len += strcpy(path_sz + path_len, dir_info[selected].name); + if (dir_info[selected].is_dir) + load_dir(); + else { + try_run_command_blocking(path_sz); + //TODO: handle error + path_sz[old_len] = '\0'; + path_len = old_len; + } + } + break; + case _KEY_ESC: + { + char *cutoff = path_sz; + for (char *i = path_sz + path_len - 1; i >= path_sz; --i) + if (*i == '/') { + cutoff = i; + break; + } + *cutoff = '\0'; + path_len = cutoff - path_sz; + load_dir(); + } + break; + case _KEY_HOME: + scroll = 0; + selected = 0; + break; + case _KEY_END: + selected = dir_info_len - 1; + scroll = dir_info_len >= MAX_PER_SCREEN + ? dir_info_len - MAX_PER_SCREEN : 0; + break; + case _KEY_UP: + if (!selected) + continue; + if (--selected < scroll) + scroll = selected; + break; + case _KEY_DOWN: + if (selected == dir_info_len - 1) + continue; + if (++selected >= scroll + MAX_PER_SCREEN) + ++scroll; + break; + case _KEY_PUP: + selected = selected >= MAX_PER_SCREEN + ? selected - MAX_PER_SCREEN : 0; + scroll = scroll >= MAX_PER_SCREEN + ? scroll - MAX_PER_SCREEN : 0; + break; + case _KEY_PDOWN: + if ((selected += MAX_PER_SCREEN) >= dir_info_len) + selected = dir_info_len - 1; + if ((scroll += MAX_PER_SCREEN) > selected) + scroll = selected; + break; + case 'q': + _clear_screen(); + return; + default: + continue; + } + paint_screen(); + } +}
\ No newline at end of file |