#include #include #include #include #include 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(); } }