diff options
Diffstat (limited to 'src/user/manual')
-rw-r--r-- | src/user/manual/manual.c | 268 |
1 files changed, 268 insertions, 0 deletions
diff --git a/src/user/manual/manual.c b/src/user/manual/manual.c new file mode 100644 index 0000000..48f4f65 --- /dev/null +++ b/src/user/manual/manual.c @@ -0,0 +1,268 @@ +#include <knob/heap.h> +#include <knob/file.h> +#include <knob/block.h> +#include <knob/format.h> +#include <pland/syscall.h> + +#define ERROR_COLOR _COLOR_BG_LGRAY | _COLOR_FG_RED +#define UI_COLOR _COLOR_BG_LGRAY | _COLOR_FG_BLACK +#define DEFAULT_TEXT_COLOR _COLOR_BG_BLACK | _COLOR_FG_WHITE + +#define MAN_ROOT "man/" +#define MRL 4 +#define MAN_EXT "man" + +#define MAX_PATH_LEN 255 + +#define SP80 " " +#define SP79 " " +#define SP69 " " +#define SP10 " " + +struct file *cur_file = 0; + +uint32_t *line_offsets = 0; +uint32_t n_lines; + +struct link { + uint32_t line; + uint8_t col; + uint8_t len; + char *lto; +}; + +struct link *link_table_start = 0; +struct link *link_table_end; + +struct link *cur_link = 0; + +uint32_t line_on; + +#define DATA_BUF_SIZE 2000 + +void print_page() { + uint8_t buf[DATA_BUF_SIZE];//1840 + up to 160 color codes + seek_file_to(cur_file, line_offsets[line_on]); + uint8_t *bufp = buf + DATA_BUF_SIZE; + uint8_t *bufend; + uint8_t row = 1, col = 0; + + _set_color(DEFAULT_TEXT_COLOR); + while (row != 24) { + if (bufp == buf + DATA_BUF_SIZE) { + bufp = buf; + uint16_t bl = read_from_file(cur_file, DATA_BUF_SIZE, buf); + bufend = bl == DATA_BUF_SIZE ? 0 : buf + bl; + } + if (bufp == bufend) { + uint32_t *i = buf; + uint16_t l = 80 - col + (23 - row) * 80; + uint32_t *e = i + l / 4 + 1; + while (i != e) + *(i++) = 0x20202020; + buf[l] = '\0'; + _print_at(row, col, buf); + break; + } + if (*bufp & 0x80) + _set_color(*bufp & 0x7f); + else { + char bufpb[2] = {*bufp, '\0'}; + _print_at(row, col, bufpb); + if (++col == 80) { + col = 0; + ++row; + } + } + ++bufp; + } + + if (cur_link) + for (uint8_t c = cur_link->col; c < cur_link->col + cur_link->len; ++c) + _swap_color(cur_link->line - line_on + 1, c); +} + +void scroll_to(uint32_t n) { + if (n > n_lines - 23) + n = n_lines - 23; + + if (cur_link && ((cur_link->line < n) || (cur_link->line >= n + 23))) + cur_link = 0; + + line_on = n; + print_page(); + + char b[16] = "Line "; + itosz(line_on, b + 5); + + _set_color(UI_COLOR); + _print_at(24, 0, SP69); + _print_at(24, 0, b); +} + +void scroll_link() { + if (cur_link->line < line_on) + scroll_to(cur_link->line); + else if (cur_link->line >= line_on + 23) + scroll_to(cur_link->line - 22); + else + print_page(); +} + +void load_file(const char *name) { + static char cur_page[MAX_PATH_LEN + 1] = MAN_ROOT; + uint32_t name_len = strcpy(cur_page + MRL, name); + strcpy(cur_page + MRL + name_len, "." MAN_EXT); + + struct file *new_file = open_file(cur_page); + if (!new_file) { + _set_color(ERROR_COLOR); + _print_at(24, 0, SP79); + _print_at(24, 0, "Could not open file."); + return; + } + + if (cur_file) + close_file(cur_file); + cur_file = new_file; + + uint32_t tlen; + read_from_file(cur_file, 4, &tlen); + char title[81]; + read_from_file(cur_file, tlen + 1, title); + + _set_color(UI_COLOR); + _print_at(0, 0, SP80); + _print_at(0, 0, title); + + if (link_table_start) { + for (struct link *l = link_table_start; l != link_table_end; ++l) + free_block(l->lto); + free_block(link_table_start); + } + + uint32_t linktc; + read_from_file(cur_file, 4, &linktc); + if (linktc) { + link_table_start = get_block(sizeof(struct link) * linktc); + link_table_end = link_table_start + linktc; + read_from_file(cur_file, 4, &linktc);//dummy + + for (struct link *l = link_table_start; l != link_table_end; ++l) { + read_from_file(cur_file, 4, &l->line); + read_from_file(cur_file, 1, &l->col); + read_from_file(cur_file, 1, &l->len); + uint32_t lto_l; + read_from_file(cur_file, 4, <o_l); + l->lto = get_block(lto_l + 1); + read_from_file(cur_file, lto_l + 1, l->lto); + } + } + else { + link_table_start = 0; + read_from_file(cur_file, 4, &linktc);//dummy + } + + cur_link = 0; + + if (line_offsets) + free_block(line_offsets); + + read_from_file(cur_file, 4, &n_lines); + line_offsets = get_block(n_lines * 4); + read_from_file(cur_file, n_lines * 4, line_offsets); + + char b[11]; + itosz(n_lines, b); + + _set_color(UI_COLOR); + _print_at(24, 69, SP10); + _print_at(24, 69, b); + + scroll_to(0); +} + +void main() { + _set_color(UI_COLOR); + _print_at(24, 79, " "); + + load_file("index"); + + while (true) { + switch (_get_key()) { + case 0: + default: + _yield_task(); + break; + case _KEY_UP: + if (n_lines <= 23) + break; + if (line_on) + scroll_to(line_on - 1); + break; + case _KEY_DOWN: + if (n_lines <= 23) + break; + if (line_on < n_lines - 23) + scroll_to(line_on + 1); + break; + case _KEY_PUP: + if (n_lines <= 23) + break; + scroll_to(line_on <= 22 ? 0 : line_on - 22); + break; + case _KEY_PDOWN: + if (n_lines <= 23) + break; + scroll_to(line_on + 22); + break; + case _KEY_LEFT: + if (cur_link == link_table_start) + break; + if (cur_link) { + --cur_link; + scroll_link(); + } + else if (link_table_start) { + struct link *l = link_table_end; + while (l != link_table_start) { + --l; + if (l->line <= line_on + 22) + break; + } + cur_link = l; + scroll_link(); + } + break; + case _KEY_RIGHT: + if (cur_link == link_table_end - 1) + break; + if (cur_link) { + ++cur_link; + scroll_link(); + } + else if (link_table_start) { + struct link *l = link_table_start; + while (l != link_table_end) { + if (l->line >= line_on) + break; + ++l; + } + cur_link = l; + scroll_link(); + } + break; + case ' ': + case '\n': + case _KEY_NENTER: + if (cur_link) + load_file(cur_link->lto); + break; + case _KEY_ESC: + //TODO + break; + case 'q': + return; + } + } +}
\ No newline at end of file |