From c5f60c285eb406e6a8925dfec476f89ece03a7e9 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Mon, 18 Nov 2024 21:13:28 +0000 Subject: [PATCH] frontend: line-ed: convert all escape code usage to s_tty calls --- frontend/line-ed/history.c | 2 +- frontend/line-ed/input.c | 5 ++- frontend/line-ed/line-ed.c | 12 ++++-- frontend/line-ed/refresh.c | 34 +++++++++++++---- frontend/line-ed/tty.h | 10 +++++ frontend/sys/windows/line-ed/tty.c | 61 ++++++++++++++++++++++++++++-- 6 files changed, 106 insertions(+), 18 deletions(-) diff --git a/frontend/line-ed/history.c b/frontend/line-ed/history.c index d57a104..285c9cc 100644 --- a/frontend/line-ed/history.c +++ b/frontend/line-ed/history.c @@ -7,7 +7,7 @@ void alloc_empty_history_entry(struct line_ed *ed) { b_string *str = (b_string *)b_array_at( ed->l_history, b_array_size(ed->l_history) - 1); - if (!str || !b_string_get_size(str, B_STRLEN_NORMAL)) { + if (!str || b_string_get_size(str, B_STRLEN_NORMAL) > 0) { str = b_string_create(); b_array_append(ed->l_history, (b_object *)str); } diff --git a/frontend/line-ed/input.c b/frontend/line-ed/input.c index 006f333..0215833 100644 --- a/frontend/line-ed/input.c +++ b/frontend/line-ed/input.c @@ -181,9 +181,10 @@ void arrow_up(struct line_ed *ed) s_tty_move_cursor_y(ed->l_tty, TTY_POS_CURSOR, ed->l_cursor_y); } - printf("\033[%zuG\033[J", prompt_length(ed, PROMPT_MAIN) + 1); + //printf("\033[%zuG\033[J", prompt_length(ed, PROMPT_MAIN) + 1); s_tty_move_cursor_x( - ed->l_tty, TTY_POS_START, prompt_length(ed, PROMPT_MAIN) + 1); + ed->l_tty, TTY_POS_START, prompt_length(ed, PROMPT_MAIN)); + s_tty_clear(ed->l_tty, TTY_CLEAR_SCREEN | TTY_CLEAR_FROM_CURSOR); save_buf_to_history(ed); ed->l_history_pos--; diff --git a/frontend/line-ed/line-ed.c b/frontend/line-ed/line-ed.c index 28e79f5..51c4d38 100644 --- a/frontend/line-ed/line-ed.c +++ b/frontend/line-ed/line-ed.c @@ -208,6 +208,10 @@ long line_ed_readline(struct line_ed *ed, char *out, size_t max) break; } + if (key & S_MOD_CTRL) { + continue; + } + switch (key) { case S_KEY_RETURN: s_tty_reset_vmode(tty); @@ -232,7 +236,9 @@ long line_ed_readline(struct line_ed *ed, char *out, size_t max) ed->l_cursor_x = 0; ed->l_cursor_y++; ed->l_continuations++; - fputs("\033[G\n", stdout); + fputc('\r', stdout); + fputc('\n', stdout); + // fputs("\033[G\n", stdout); show_prompt(ed); break; case S_KEY_BACKSPACE: @@ -251,7 +257,7 @@ long line_ed_readline(struct line_ed *ed, char *out, size_t max) arrow_down(ed); break; default: - if (isgraph(key) || key == ' ') { + if (iswgraph(key) || key == ' ') { put_char(ed, key); } break; @@ -259,7 +265,7 @@ long line_ed_readline(struct line_ed *ed, char *out, size_t max) } s_tty_set_canon(tty); - printf("\n"); + fputc('\n', stdout); if (*ed->l_buf == '\0') { return eof ? -1 : 0; diff --git a/frontend/line-ed/refresh.c b/frontend/line-ed/refresh.c index 89780f7..774cef1 100644 --- a/frontend/line-ed/refresh.c +++ b/frontend/line-ed/refresh.c @@ -5,6 +5,7 @@ #include "buffer.h" #include "cursor.h" #include "hl-range.h" +#include "tty.h" /* prints the provided string to the terminal, applying any relevant highlight ranges. * this function prints all characters in `s` until it encounters a null char (\0) or @@ -105,7 +106,8 @@ void put_refresh(struct line_ed *ed, struct refresh_state *state) if (ed->l_flags & LINE_ED_FULL_REPRINT) { if (start_x) { - fprintf(stdout, "\033[%uD", start_x); + //fprintf(stdout, "\033[%uD", start_x); + s_tty_move_cursor_x(ed->l_tty, TTY_POS_CURSOR, -start_x); } start_x = 0; @@ -117,10 +119,13 @@ void put_refresh(struct line_ed *ed, struct refresh_state *state) * so that the physical cursor will be placed AFTER the character that * was just inserted. */ cursor_rdelta--; + s_tty_move_cursor_x(ed->l_tty, TTY_POS_CURSOR, -cursor_rdelta); + #if 0 for (unsigned int i = 0; i < cursor_rdelta; i++) { fputs("\010", stdout); } + #endif fflush(stdout); } @@ -156,17 +161,22 @@ void backspace_nl_refresh(struct line_ed *ed, struct refresh_state *state) /* the physical cursor is currently at the beginning of the line that * has just been moved up. from here, clear this line and the rest * from the screen. */ - fputs("\033[J", stdout); + //fputs("\033[J", stdout); + s_tty_clear(ed->l_tty, TTY_CLEAR_SCREEN | TTY_CLEAR_FROM_CURSOR); if (ed->l_flags & LINE_ED_FULL_REPRINT) { /* next, move the physical cursor up and to the beginning of the previous line */ unsigned int tmp_x; line_ed_coords_to_physical_coords(ed, 0, ed->l_cursor_y, &tmp_x, NULL); - fprintf(stdout, "\033[A\033[%uG", tmp_x + 1); + s_tty_move_cursor_y(ed->l_tty, TTY_POS_CURSOR, -1); + s_tty_move_cursor_x(ed->l_tty, TTY_POS_START, tmp_x); + //fprintf(stdout, "\033[A\033[%uG", tmp_x + 1); start_x = 0; } else { /* next, move the physical cursor up and to the end of the previous line */ - fprintf(stdout, "\033[A\033[%uG", new_x); + //fprintf(stdout, "\033[A\033[%uG", new_x); + s_tty_move_cursor_y(ed->l_tty, TTY_POS_CURSOR, -1); + s_tty_move_cursor_x(ed->l_tty, TTY_POS_START, new_x); } /* now reprint all of the buffer lines, starting with the first of the @@ -191,10 +201,12 @@ void backspace_nl_refresh(struct line_ed *ed, struct refresh_state *state) /* finally, move the cursor BACK to the point where the two lines * were concatenated. */ if (ydiff) { - fprintf(stdout, "\033[%uA", ydiff); + //fprintf(stdout, "\033[%uA", ydiff); + s_tty_move_cursor_y(ed->l_tty, TTY_POS_CURSOR, ydiff); } - fprintf(stdout, "\033[%uG", new_x); + //fprintf(stdout, "\033[%uG", new_x); + s_tty_move_cursor_x(ed->l_tty, TTY_POS_START, new_x); fflush(stdout); } @@ -219,13 +231,15 @@ void backspace_simple_refresh(struct line_ed *ed, struct refresh_state *state) if (ed->l_flags & LINE_ED_FULL_REPRINT) { if (start_x) { - fprintf(stdout, "\033[%uD", start_x); + //fprintf(stdout, "\033[%uD", start_x); + s_tty_move_cursor_x(ed->l_tty, TTY_POS_CURSOR, -start_x); } start_x = 0; } - fputc('\010', stdout); + //fputc('\010', stdout); + s_tty_move_cursor_x(ed->l_tty, TTY_POS_CURSOR, -1); print_text(ed, start_x, ed->l_cursor_y, line_buf + start_x); fputc(' ', stdout); @@ -234,9 +248,13 @@ void backspace_simple_refresh(struct line_ed *ed, struct refresh_state *state) * the fact that backspace was just pressed) */ cursor_rdelta++; + s_tty_move_cursor_x(ed->l_tty, TTY_POS_CURSOR, -cursor_rdelta); + + #if 0 for (unsigned int i = 0; i < cursor_rdelta; i++) { fputs("\010", stdout); } + #endif fflush(stdout); } diff --git a/frontend/line-ed/tty.h b/frontend/line-ed/tty.h index 7ca5789..b764d0f 100644 --- a/frontend/line-ed/tty.h +++ b/frontend/line-ed/tty.h @@ -101,6 +101,15 @@ enum s_tty_attrib { TTY_ATTRIB_ITALIC = 0x04u, }; +enum s_tty_clear_mode { + TTY_CLEAR_LINE = 0x01u, + TTY_CLEAR_SCREEN = 0x02, + + TTY_CLEAR_TO_CURSOR = 0x0100u, + TTY_CLEAR_FROM_CURSOR = 0x0200u, + TTY_CLEAR_ALL = 0x0400u, +}; + struct s_tty_colour { enum s_tty_colour_mode c_mode; @@ -146,5 +155,6 @@ extern void s_tty_move_cursor_x( struct s_tty *tty, enum s_tty_position_base base, int pos); extern void s_tty_move_cursor_y( struct s_tty *tty, enum s_tty_position_base base, int pos); +extern void s_tty_clear(struct s_tty *tty, enum s_tty_clear_mode mode); #endif diff --git a/frontend/sys/windows/line-ed/tty.c b/frontend/sys/windows/line-ed/tty.c index a633e29..db55fe4 100644 --- a/frontend/sys/windows/line-ed/tty.c +++ b/frontend/sys/windows/line-ed/tty.c @@ -347,9 +347,7 @@ s_keycode s_tty_read_key(struct s_tty *tty) s_keycode key = 0; - if (d.Event.KeyEvent.uChar.UnicodeChar == 0) { - continue; - } + switch (d.Event.KeyEvent.wVirtualKeyCode) { case VK_CONTROL: @@ -377,6 +375,10 @@ s_keycode s_tty_read_key(struct s_tty *tty) key = S_KEY_RETURN; break; default: + if (d.Event.KeyEvent.uChar.UnicodeChar == 0) { + continue; + } + key = d.Event.KeyEvent.uChar.AsciiChar; break; } @@ -437,4 +439,55 @@ void s_tty_move_cursor_y(struct s_tty *tty, enum s_tty_position_base base, int p } SetConsoleCursorPosition(tty->t_out, cursor_pos); -} \ No newline at end of file +} + +void s_tty_clear(struct s_tty *tty, enum s_tty_clear_mode mode) +{ + CONSOLE_SCREEN_BUFFER_INFO console = {0}; + GetConsoleScreenBufferInfo(tty->t_out, &console); + + WCHAR fill = L' '; + DWORD length = 0; + COORD start; + + DWORD all_length = 0, line_length = 0; + + if (mode & TTY_CLEAR_ALL) { + line_length = console.dwSize.X; + all_length = line_length * console.dwSize.Y; + } else if (mode & TTY_CLEAR_FROM_CURSOR) { + line_length = console.dwSize.X - console.dwCursorPosition.X + 1; + all_length = line_length + ((console.dwSize.Y - console.dwCursorPosition.Y) * console.dwSize.X); + } else if (mode & TTY_CLEAR_TO_CURSOR) { + line_length = console.dwCursorPosition.X; + all_length = line_length + + ((console.dwCursorPosition.Y - 1) * console.dwSize.X); + } else { + abort(); + } + + if (mode & TTY_CLEAR_SCREEN) { + length = all_length; + + if ((mode & TTY_CLEAR_ALL) || (mode & TTY_CLEAR_TO_CURSOR)) { + start.X = 0; + start.Y = 0; + } else if (mode & TTY_CLEAR_FROM_CURSOR) { + start = console.dwCursorPosition; + } + } else if (mode & TTY_CLEAR_LINE) { + length = line_length; + + if ((mode & TTY_CLEAR_ALL) || (mode & TTY_CLEAR_TO_CURSOR)) { + start.X = 0; + start.Y = console.dwCursorPosition.Y; + } else if (mode & TTY_CLEAR_FROM_CURSOR) { + start = console.dwCursorPosition; + } + } else { + abort(); + } + + DWORD nr_written = 0; + FillConsoleOutputCharacterW(tty->t_out, fill, length, start, &nr_written); +}