From 49414086b0284777d0886eb559c1442bc48073a1 Mon Sep 17 00:00:00 2001 From: Hadeed Ahmad Date: Thu, 31 Aug 2023 10:48:27 +0500 Subject: [PATCH] Move append buffer to separate file --- include/append_buf.h | 15 ++++++ include/kilo.h | 10 ++-- include/terminal.h | 32 +++++++++--- src/append_buf.c | 26 ++++++++++ src/kilo.c | 118 ++++++++++++++----------------------------- src/terminal.c | 30 +++++++---- 6 files changed, 127 insertions(+), 104 deletions(-) create mode 100644 include/append_buf.h create mode 100644 src/append_buf.c diff --git a/include/append_buf.h b/include/append_buf.h new file mode 100644 index 0000000..4db2a71 --- /dev/null +++ b/include/append_buf.h @@ -0,0 +1,15 @@ +#ifndef APPEND_BUF_H +#define APPEND_BUF_H + +// A simple append only buffer to build strings + +struct append_buf { + char *chars; + int n_chars; +}; + +struct append_buf *ab_init(void); +void ab_append(struct append_buf *ab, const char *chars, int n_chars); +void ab_free(struct append_buf *ab); + +#endif // APPEND_BUF_H diff --git a/include/kilo.h b/include/kilo.h index 8258e02..bb68524 100644 --- a/include/kilo.h +++ b/include/kilo.h @@ -6,6 +6,10 @@ #include #include +// Stuff I couldn' figure out where else to put + +typedef int ERRCODE; + struct editor_state { char *filename; int cx, cy; @@ -24,10 +28,6 @@ struct editor_state { }; extern struct editor_state E; -typedef uint16_t KEY; - -void die(const char *); - enum KEYS { TAB = 9, HOME = 0x100, @@ -41,6 +41,8 @@ enum KEYS { ARROW_RIGHT, NOP }; +typedef uint16_t KEY; +void die(const char *context); #endif // KILO_H diff --git a/include/terminal.h b/include/terminal.h index b971ce1..356a471 100644 --- a/include/terminal.h +++ b/include/terminal.h @@ -5,13 +5,29 @@ #include "kilo.h" -int term_enable_raw(void); -void term_disable_raw(void); -int term_clear(void); -int term_cursor_hidden(bool); -int term_get_win_size(int *, int *); -int term_get_cursor_pos(int *, int *); -int term_set_cursor_pos(int, int); -KEY term_read_key(void); +// Functions to perform low level terminal operations, using escape codes + +ERRCODE terminal_enable_raw(void); +void terminal_disable_raw(void); + +// Cursor positioned at the start +ERRCODE terminal_clear(void); + +// Hide or show the cursor +enum cursor_visibility { + CURSOR_SHOWN = 0, + CURSOR_HIDDEN = 1 +}; +ERRCODE terminal_cursor_visibility(enum cursor_visibility visibility); + +// Calculate the current window size +ERRCODE terminal_get_win_size(int *rows, int *cols); + +// Get and set the cursor position, 1-based indexing +ERRCODE terminal_get_cursor_pos(int *row, int *col); +ERRCODE terminal_set_cursor_pos(int, int); + +// Read input from the terminal and parse it into a KEY +KEY terminal_read_key(void); #endif // TERMINAL_H diff --git a/src/append_buf.c b/src/append_buf.c new file mode 100644 index 0000000..531e877 --- /dev/null +++ b/src/append_buf.c @@ -0,0 +1,26 @@ +#include +#include + +#include "append_buf.h" + +struct append_buf *ab_init(void) { + size_t buf_size = sizeof(struct append_buf); + struct append_buf *sb = (struct append_buf *) malloc(buf_size); + + sb->chars = NULL; + sb->n_chars = 0; + + return sb; +} + +void ab_append(struct append_buf *sb, const char *chars, int n_chars) { + sb->chars = realloc(sb->chars, sb->n_chars + n_chars); + + memcpy(sb->chars + sb->n_chars, chars, n_chars); + sb->n_chars += n_chars; +} + +void ab_free(struct append_buf *sb) { + free(sb->chars); + free(sb); +} diff --git a/src/kilo.c b/src/kilo.c index 3d96179..0a6eedf 100644 --- a/src/kilo.c +++ b/src/kilo.c @@ -10,6 +10,7 @@ #include #include "kilo.h" +#include "append_buf.h" #include "terminal.h" #define CTRL_KEY(key) ((key) & 0x1f) @@ -19,8 +20,6 @@ /*****************************************************************************/ -struct string_buf; - struct EROW { char *chars; int n_chars; @@ -39,9 +38,9 @@ void editor_append_row(const char *, int); void editor_set_message(const char *, ...); void editor_redraw_screen(void); -void editor_draw_rows(struct string_buf *); -void editor_draw_statusbar(struct string_buf *); -void editor_draw_messagebar(struct string_buf *); +void editor_draw_rows(struct append_buf *); +void editor_draw_statusbar(struct append_buf *); +void editor_draw_messagebar(struct append_buf *); void editor_process_key(void); void editor_move_cursor(KEY); @@ -49,12 +48,6 @@ void editor_adjust_viewport(void); int editor_get_rx(int); int editor_get_cx(int); -struct string_buf *sb_init(void); -char *sb_get_string(struct string_buf *); -int sb_get_size(struct string_buf *); -void sb_append(struct string_buf *, const char *, int); -void sb_free(struct string_buf *); - /*****************************************************************************/ int main(int argc, char **argv) { @@ -68,7 +61,7 @@ int main(int argc, char **argv) { editor_process_key(); } - term_clear(); + terminal_clear(); return 0; } @@ -80,8 +73,8 @@ void editor_init(void) { exit(1); } - if (term_enable_raw() == -1) die("term_enable_raw"); - if (term_get_win_size(&E.screenrows, &E.screencols) == -1) + if (terminal_enable_raw() == -1) die("term_enable_raw"); + if (terminal_get_win_size(&E.screenrows, &E.screencols) == -1) die("term_get_win_size"); E.filename = NULL; @@ -126,26 +119,26 @@ void editor_append_row(const char *s, int len) { new_row->chars = malloc(len); new_row->n_chars = len; - struct string_buf *sb = sb_init(); + struct append_buf *sb = ab_init(); for (int i = 0; i < len; i++) { new_row->chars[i] = s[i]; switch (s[i]) { case TAB: { - int tabs = KILO_TAB_STOP - (sb_get_size(sb) % KILO_TAB_STOP); - while (tabs--) sb_append(sb, " ", 1); + int tabs = KILO_TAB_STOP - (sb->n_chars % KILO_TAB_STOP); + while (tabs--) ab_append(sb, " ", 1); break; } default: - sb_append(sb, s+i, 1); + ab_append(sb, s+i, 1); } } - new_row->rchars = malloc(sb_get_size(sb)); - new_row->n_rchars = sb_get_size(sb); - memcpy(new_row->rchars, sb_get_string(sb), sb_get_size(sb)); + new_row->rchars = malloc(sb->n_chars); + new_row->n_rchars = sb->n_chars; + memcpy(new_row->rchars, sb->chars, sb->n_chars); - sb_free(sb); + ab_free(sb); E.n_rows++; } @@ -161,30 +154,30 @@ void editor_set_message(const char *fmt, ...) { void editor_redraw_screen(void) { - if (term_cursor_hidden(true) == -1) + if (terminal_cursor_visibility(true) == -1) die("term_cursor_hidden"); - struct string_buf *draw_buf = sb_init(); + struct append_buf *draw_buf = ab_init(); editor_draw_rows(draw_buf); editor_draw_statusbar(draw_buf); editor_draw_messagebar(draw_buf); - write(STDIN_FILENO, sb_get_string(draw_buf), sb_get_size(draw_buf)); - sb_free(draw_buf); + write(STDIN_FILENO, draw_buf->chars, draw_buf->n_chars); + ab_free(draw_buf); int row_pos = E.cy - E.row_off + 1; int col_pos = E.rx - E.col_off + 1; - if (term_set_cursor_pos(row_pos, col_pos) == -1) + if (terminal_set_cursor_pos(row_pos, col_pos) == -1) die("term_set_cursor_pos"); - if (term_cursor_hidden(false) == -1) + if (terminal_cursor_visibility(false) == -1) die("term_cursor_hidden"); } -void editor_draw_rows(struct string_buf *draw_buf) { - term_set_cursor_pos(1, 1); +void editor_draw_rows(struct append_buf *draw_buf) { + terminal_set_cursor_pos(1, 1); for (int y = 0; y < E.screenrows; y++) { bool in_file = y < E.n_rows - E.row_off; bool no_file = E.n_rows == 0; @@ -193,7 +186,7 @@ void editor_draw_rows(struct string_buf *draw_buf) { struct EROW curr_row = E.rows[y + E.row_off]; int max_len = MIN(curr_row.n_rchars - E.col_off, E.screencols); - sb_append(draw_buf, curr_row.rchars + E.col_off, MAX(max_len, 0)); + ab_append(draw_buf, curr_row.rchars + E.col_off, MAX(max_len, 0)); } else if (no_file && y == E.screenrows / 2) { char welcome[64]; int len = snprintf(welcome, sizeof(welcome), @@ -201,22 +194,22 @@ void editor_draw_rows(struct string_buf *draw_buf) { int padding = (E.screencols - len) / 2; for (int i = 0; i < padding; i++) - sb_append(draw_buf, (i == 0 ? "~" : " "), 1); + ab_append(draw_buf, (i == 0 ? "~" : " "), 1); - sb_append(draw_buf, welcome, len); - } else sb_append(draw_buf, "~", 1); + ab_append(draw_buf, welcome, len); + } else ab_append(draw_buf, "~", 1); - sb_append(draw_buf, "\x1b[K\r\n", 5); + ab_append(draw_buf, "\x1b[K\r\n", 5); } } -void editor_draw_statusbar(struct string_buf *draw_buf) { +void editor_draw_statusbar(struct append_buf *draw_buf) { char *status_buf = malloc(E.screencols), buf[256]; int len; memset(status_buf, ' ', E.screencols); - sb_append(draw_buf, "\x1b[7m", 4); + ab_append(draw_buf, "\x1b[7m", 4); len = sprintf(buf, "%s -- %d lines", (E.filename ? E.filename : "[NO NAME]"), E.n_rows); @@ -225,24 +218,24 @@ void editor_draw_statusbar(struct string_buf *draw_buf) { len = sprintf(buf, "%d:%d", E.cy + 1, E.rx + 1); memcpy(status_buf + E.screencols - len, buf, len); - sb_append(draw_buf, status_buf, E.screencols); - sb_append(draw_buf, "\x1b[m\r\n", 5); + ab_append(draw_buf, status_buf, E.screencols); + ab_append(draw_buf, "\x1b[m\r\n", 5); free(status_buf); } -void editor_draw_messagebar(struct string_buf *draw_buf) { - sb_append(draw_buf, "\x1b[K", 3); +void editor_draw_messagebar(struct append_buf *draw_buf) { + ab_append(draw_buf, "\x1b[K", 3); int len = strlen(E.message); if (len > E.screencols) len = E.screencols; if (len && time(NULL) - E.message_time < 5) - sb_append(draw_buf, E.message, len); + ab_append(draw_buf, E.message, len); } void editor_process_key(void) { - KEY c = term_read_key(); + KEY c = terminal_read_key(); switch (c) { case ARROW_LEFT: @@ -365,45 +358,8 @@ int editor_get_cx(int rx_target) { /*****************************************************************************/ -struct string_buf { - char *chars; - int n_chars; -}; - -struct string_buf *sb_init(void) { - size_t buf_size = sizeof(struct string_buf); - struct string_buf *sb = (struct string_buf *) malloc(buf_size); - - sb->chars = NULL; - sb->n_chars = 0; - - return sb; -} - -char *sb_get_string(struct string_buf *sb) { - return sb->chars; -} - -int sb_get_size(struct string_buf *sb) { - return sb->n_chars; -} - -void sb_append(struct string_buf *sb, const char *chars, int n_chars) { - sb->chars = realloc(sb->chars, sb->n_chars + n_chars); - - memcpy(sb->chars + sb->n_chars, chars, n_chars); - sb->n_chars += n_chars; -} - -void sb_free(struct string_buf *sb) { - free(sb->chars); - free(sb); -} - -/*****************************************************************************/ - void die(const char *s) { - term_clear(); + terminal_clear(); perror(s); exit(1); diff --git a/src/terminal.c b/src/terminal.c index 22a6696..d724788 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -7,7 +7,7 @@ #include "kilo.h" #include "terminal.h" -int term_enable_raw(void) { +ERRCODE terminal_enable_raw(void) { if (tcgetattr(STDIN_FILENO, &E.orig_termios) == -1) return -1; @@ -19,30 +19,30 @@ int term_enable_raw(void) { raw.c_cc[VMIN] = 0; raw.c_cc[VTIME] = 1; - atexit(term_disable_raw); + atexit(terminal_disable_raw); return tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw); } -void term_disable_raw(void) { +void terminal_disable_raw(void) { if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &E.orig_termios) == -1) die ("term_disable_raw"); } -int term_clear(void) { +ERRCODE terminal_clear(void) { if (write(STDOUT_FILENO, "\x1b[2J", 4) != 4) return -1; if (write(STDOUT_FILENO, "\x1b[H", 3) != 3) return -1; return 0; } -int term_cursor_hidden(bool hidden) { - if (write(STDOUT_FILENO, (hidden ? "\x1b[?25l" : "\x1b[?25h"), 6) != 6) +ERRCODE terminal_cursor_visibility(enum cursor_visibility visibility) { + if (write(STDOUT_FILENO, (visibility ? "\x1b[?25l" : "\x1b[?25h"), 6) != 6) return -1; return 0; } -int term_get_win_size(int *row, int *col) { +ERRCODE terminal_get_win_size(int *row, int *col) { struct winsize ws; if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1 && ws.ws_col != 0) { @@ -51,13 +51,14 @@ int term_get_win_size(int *row, int *col) { return 0; } else { + // Fallback implementation if (write(STDOUT_FILENO, "\x1b[999C\x1b[999B", 12) != 12) return -1; - return term_get_cursor_pos(row, col); + return terminal_get_cursor_pos(row, col); } } -int term_get_cursor_pos(int *row, int *col) { +ERRCODE terminal_get_cursor_pos(int *row, int *col) { char buf[16]; if (write(STDOUT_FILENO, "\x1b[6n", 4) != 4) return -1; @@ -75,7 +76,7 @@ int term_get_cursor_pos(int *row, int *col) { return 0; } -int term_set_cursor_pos(int row, int col) { +ERRCODE terminal_set_cursor_pos(int row, int col) { char buf[16]; int len = snprintf(buf, sizeof(buf), "\x1b[%d;%dH", row, col); @@ -85,7 +86,7 @@ int term_set_cursor_pos(int row, int col) { return 0; } -KEY term_read_key(void) { +KEY terminal_read_key(void) { char c; while (read(STDIN_FILENO, &c, 1) == 0); @@ -107,6 +108,13 @@ KEY term_read_key(void) { } } + if (sscanf(buf, "O%c", &escape_char) != EOF) { + switch (escape_char) { + case 'H': return HOME; + case 'F': return END; + } + } + int escape_int; if (sscanf(buf, "[%d~", &escape_int) != EOF) { switch (escape_int) {