diff --git a/bin/aed.bin b/bin/aed.bin index 526bff6..027a54a 100644 Binary files a/bin/aed.bin and b/bin/aed.bin differ diff --git a/src/cmd_ops.c b/src/cmd_ops.c index 76fa5ef..0518397 100644 --- a/src/cmd_ops.c +++ b/src/cmd_ops.c @@ -594,3 +594,58 @@ void cmd_page_down(editor* ed) { refresh_screen(scr, tb); scr_show_cursor_ch(scr, ch); } + +void cmd_goto(editor* ed) { + SCR(ed); + UI(ed); + TB(ed); + + int line = 0; + RESPONSE goto_line = ui_goto(ui, scr, &line); + if (goto_line != YES_OPT) { + return; + } + + const int ypos = tb_ypos(tb); + if (ypos == line) { + return; + } + + int diff = 0; + scr_hide_cursor_ch(scr, tb_peek(tb)); + if (line < ypos) { + for (; line < ypos; line++) { + diff--; + tb_up(tb); + if (tb_ypos(tb) == 1) { + break; + } + } + } else { + int curr = tb_ypos(tb); + for (; ypos < line; line--) { + tb_down(tb); + const int nyp = tb_ypos(tb); + if (nyp == curr) { + break; + } + curr = nyp; + diff++; + } + } + + diff = ((int)scr->currY_) + diff; + if (diff < (int)scr->topY_) { + scr->currY_ = scr->topY_; + } else if (diff >= (int) scr->bottomY_) { + scr->currY_ = scr->bottomY_-1; + } else { + scr->currY_ = diff; + } + vdp_cursor_tab(scr->currY_, scr->currX_); + + scr->currX_ = tb_xpos(tb) < scr->cols_ ? tb_xpos(tb)-1 : scr->cols_-1; + refresh_screen(scr, tb); + scr_show_cursor_ch(scr, tb_peek(tb)); +} + diff --git a/src/cmd_ops.h b/src/cmd_ops.h index 8acebc0..bbeca44 100644 --- a/src/cmd_ops.h +++ b/src/cmd_ops.h @@ -54,5 +54,6 @@ void cmd_home(editor* ed); void cmd_end(editor* ed); void cmd_page_up(editor* ed); void cmd_page_down(editor* ed); +void cmd_goto(editor* ed); #endif // _CMD_OPS_H_ diff --git a/src/editor.c b/src/editor.c index 1b0c465..e7715c8 100644 --- a/src/editor.c +++ b/src/editor.c @@ -116,8 +116,12 @@ key_command ctrlCmds(key_command kc, uint8_t mods) { kc.cmd = cmd_color_picker; } break; + case VK_G: + case VK_g: + kc.cmd = cmd_goto; + break; default: - kc.cmd = NULL;; + kc.cmd = NULL; break; } return kc; diff --git a/src/user_input.c b/src/user_input.c index 49d3e04..4d3955c 100644 --- a/src/user_input.c +++ b/src/user_input.c @@ -18,10 +18,10 @@ #include "user_input.h" +#include +#include #include -#include "agon/vdp_vdu.h" -#include "mos_api.h" #include "vkey.h" user_input* ui_init(user_input* ui, int size, char ypos, char cols) { @@ -37,6 +37,69 @@ void ui_destroy(user_input* ui) { cb_destroy(&ui->cb_); } + +static const char goto_line[11] = "Goto line: "; +static int atoi(uint8_t* str, uint8_t sz) { + int v = 0; + int mul = 1; + for (uint8_t i = 1; i <= sz; i++) { + v += (str[sz-i] - '0') * mul; + mul *= 10; + } + return v; +} + +RESPONSE ui_goto(user_input* ui, screen* scr, int* line) { + scr_write_line(scr, ui->ypos_, goto_line, sizeof(goto_line)); + vdp_cursor_tab(ui->ypos_, sizeof(goto_line)); + scr_show_cursor_ch(scr, scr->cursor_); + + char_buffer* cb = &ui->cb_; + cb_clear(cb); + + do { + uint8_t key = getch(); + VKey vkey = getsysvar_vkeycode(); + + if (key >= '0' && key <= '9') { + cb_put(cb, key); + putch(key); + scr_show_cursor_ch(scr, cb_peek(cb)); + continue; + } + + switch (vkey) { + case VK_ESCAPE: + return CANCEL_OPT; + case VK_RETURN: { + int sz = 0; + uint8_t* buf = cb_prefix(cb, &sz); + if (sz <= 0) { + return CANCEL_OPT; + } + *line = atoi(buf, (uint8_t) sz); + if (*line < 0) { + return CANCEL_OPT; + } + return YES_OPT; + } + case VK_BACKSPACE: + scr_hide_cursor_ch(scr, cb_peek(cb)); + if (cb_bksp(cb)) { + vdp_cursor_left(); + } + scr_show_cursor_ch(scr, cb_peek(cb)); + break; + default: + break; + + } + } while (true); + + return CANCEL_OPT; +} + + static const char col_select[39] = "Use UP/DOWN LEFT/RIGHT to select FG/BG"; RESPONSE ui_color_picker(user_input* ui, screen* scr) { diff --git a/src/user_input.h b/src/user_input.h index e154bfd..de842a1 100644 --- a/src/user_input.h +++ b/src/user_input.h @@ -38,6 +38,7 @@ typedef struct _user_input { user_input* ui_init(user_input* ui, int size, char ypos, char cols); void ui_destroy(user_input* ui); +RESPONSE ui_goto(user_input* ui, screen* scr, int* line); RESPONSE ui_color_picker(user_input* ui, screen* scr); RESPONSE ui_dialog(user_input* ui, screen* scr, const char* msg); RESPONSE ui_text(