summaryrefslogtreecommitdiff
path: root/src/user/manual
diff options
context:
space:
mode:
authorBenji Dial <Benji3.141@gmail.com>2020-11-08 11:11:49 -0500
committerBenji Dial <Benji3.141@gmail.com>2020-11-08 11:11:49 -0500
commit21491514b3642a321ce65f2a07428f63c4d9feb5 (patch)
treecf2384926e9d8e4cb0dcf2c9babd37fc7809c5da /src/user/manual
parent594aeeb09bc24de7064eb1bddf6e86c1a134838e (diff)
downloadportland-os-21491514b3642a321ce65f2a07428f63c4d9feb5.tar.gz
manual viewer, "swap colors" system call
Diffstat (limited to 'src/user/manual')
-rw-r--r--src/user/manual/manual.c268
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, &lto_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