1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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();
}
}
|