Archived
1
Fork 0

Begin work on text editing

Along with lots of stuff I was too lazy to commit separately
This commit is contained in:
Hadeed 2023-09-02 10:30:25 +05:00
parent bd8da6f4ee
commit f866add58f
8 changed files with 119 additions and 31 deletions

View file

@ -20,6 +20,7 @@ void buffer_read_file(struct buffer *buffer, const char *filename);
void buffer_append_row(struct buffer *buffer, const char *chars, int n_chars); void buffer_append_row(struct buffer *buffer, const char *chars, int n_chars);
void erow_update_rendering(struct erow *erow); void erow_update_rendering(struct erow *erow);
void erow_insert_char(struct erow *erow, int at, char c);
int erow_cx_to_rx(struct erow *erow, int cx); int erow_cx_to_rx(struct erow *erow, int cx);
int erow_rx_to_cx(struct erow *erow, int rx); int erow_rx_to_cx(struct erow *erow, int rx);

View file

@ -3,6 +3,7 @@
#include "input.h" #include "input.h"
void editor_move_cursor(KEY key); void command_move_cursor(KEY key);
void command_insert_char(char c);
#endif // COMMANDS_H #endif // COMMANDS_H

View file

@ -20,4 +20,6 @@ struct editor_state {
}; };
extern struct editor_state E; extern struct editor_state E;
void editor_set_message(const char *, ...);
#endif // KILO_H #endif // KILO_H

View file

@ -64,6 +64,9 @@ void buffer_append_row(struct buffer *buffer, const char *chars, int n_chars) {
memcpy(new_row->chars, chars, n_chars); memcpy(new_row->chars, chars, n_chars);
new_row->n_chars = n_chars; new_row->n_chars = n_chars;
new_row->rchars = NULL;
new_row->n_rchars = 0;
erow_update_rendering(new_row); erow_update_rendering(new_row);
} }
@ -116,6 +119,19 @@ void erow_update_rendering(struct erow *erow) {
free(line_buffer); free(line_buffer);
} }
void erow_insert_char(struct erow *erow, int at, char c) {
if (at < 0) at = 0;
if (at > erow->n_chars) at = erow->n_chars;
erow->chars = realloc(erow->chars, erow->n_chars + 1);
memmove(erow->chars + at + 1, erow->chars + at, erow->n_chars - at);
erow->chars[at] = c;
erow->n_chars++;
erow_update_rendering(erow);
}
int erow_cx_to_rx(struct erow *erow, int cx) { int erow_cx_to_rx(struct erow *erow, int cx) {
int rx = 0; int rx = 0;

View file

@ -1,33 +1,33 @@
#include <stdbool.h> #include <stdbool.h>
#include "commands.h" #include "commands.h"
#include "input.h"
#include "kilo.h" #include "kilo.h"
#include "buffer.h" #include "buffer.h"
void editor_move_cursor(KEY key) { static void cursor_adjust_viewport(void);
static void cursor_check_file_bounds(bool horizontal);
static void cursor_update_rx(bool horizontal);
void command_move_cursor(KEY key) {
struct erow *rows = E.current_buf->rows; struct erow *rows = E.current_buf->rows;
int n_rows = E.current_buf->n_rows; int n_rows = E.current_buf->n_rows;
struct erow *current_row = (E.cy < n_rows ? rows + E.cy : NULL); struct erow *current_row = (rows && E.cy < n_rows ? rows + E.cy : NULL);
int max_x = (current_row ? current_row->n_chars : 0); int max_x = (current_row ? current_row->n_chars : 0);
switch (key) { switch (key) {
case ARROW_LEFT: case ARROW_LEFT:
if (E.cx > 0) E.cx--; E.cx--;
else if (E.cy > 0) E.cx = rows[--E.cy].n_chars;
break; break;
case ARROW_DOWN: case ARROW_DOWN:
if (E.cy < n_rows) E.cy++; E.cy++;
break; break;
case ARROW_UP: case ARROW_UP:
if (E.cy > 0) E.cy--; E.cy--;
break; break;
case ARROW_RIGHT: case ARROW_RIGHT:
if (E.cx < max_x) E.cx++; E.cx++;
else if (E.cy < n_rows) {
E.cx = 0;
E.cy++;
}
break; break;
case HOME: case HOME:
@ -38,29 +38,76 @@ void editor_move_cursor(KEY key) {
break; break;
case PG_UP: case PG_UP:
if ((E.cy -= E.screenrows) < 0) E.cy -= E.screenrows;
E.cy = 0;
break; break;
case PG_DOWN: case PG_DOWN:
if ((E.cy += E.screenrows) > n_rows) E.cy += E.screenrows;
E.cy = n_rows;
break; break;
} }
current_row = (E.cy < n_rows ? rows + E.cy : NULL); bool horizontal = (key == ARROW_LEFT ||
max_x = (current_row ? current_row->n_chars : 0); key == ARROW_RIGHT ||
key == HOME ||
key == END);
cursor_check_file_bounds(horizontal);
cursor_update_rx(horizontal);
cursor_adjust_viewport();
}
void command_insert_char(char c) {
if (E.cy == E.current_buf->n_rows)
buffer_append_row(E.current_buf, NULL, 0);
erow_insert_char(E.current_buf->rows+E.cy, E.cx++, c);
E.rx = erow_cx_to_rx(E.current_buf->rows+E.cy, E.cx);
}
static void cursor_check_file_bounds(bool horizontal) {
struct erow *rows = E.current_buf->rows;
int n_rows = E.current_buf->n_rows;
struct erow *current_row = (rows && E.cy < n_rows ? rows + E.cy : NULL);
int max_x = (current_row ? current_row->n_chars : 0);
if (E.cy < 0)
E.cy = 0;
if (E.cy > n_rows)
E.cy = n_rows;
if (E.cx < 0) {
if (E.cy > 0 && horizontal) E.cx = rows[--E.cy].n_chars;
else E.cx = 0;
}
if (E.cx > max_x) {
if (E.cy < n_rows && horizontal) {
E.cx = 0;
E.cy++;
} else E.cx = max_x;
}
}
static void cursor_update_rx(bool horizontal) {
struct erow *rows = E.current_buf->rows;
int n_rows = E.current_buf->n_rows;
struct erow *current_row = (rows && E.cy < n_rows ? rows + E.cy : NULL);
int max_x = (current_row ? current_row->n_chars : 0);
static int saved_rx = 0; static int saved_rx = 0;
bool horizontal = (key == ARROW_LEFT || key == ARROW_RIGHT ||
key == HOME || key == END);
if (horizontal) saved_rx = erow_cx_to_rx(current_row, E.cx); if (horizontal) saved_rx = erow_cx_to_rx(current_row, E.cx);
else E.cx = erow_rx_to_cx(current_row, saved_rx); else {
E.cx = erow_rx_to_cx(current_row, saved_rx);
if (E.cx > max_x) if (E.cx > max_x)
E.cx = max_x; E.cx = max_x;
}
E.rx = erow_cx_to_rx(&E.current_buf->rows[E.cy], E.cx); E.rx = erow_cx_to_rx(rows + E.cy, E.cx);
}
static void cursor_adjust_viewport(void) {
int max_row_off = E.cy; int max_row_off = E.cy;
if (E.row_off > max_row_off) if (E.row_off > max_row_off)
E.row_off = max_row_off; E.row_off = max_row_off;

View file

@ -3,6 +3,7 @@
#include "input.h" #include "input.h"
#include "terminal.h" #include "terminal.h"
#include "commands.h" #include "commands.h"
#include "utils.h"
void input_process_key(void) { void input_process_key(void) {
KEY c = terminal_read_key(); KEY c = terminal_read_key();
@ -16,12 +17,23 @@ void input_process_key(void) {
case END: case END:
case PG_UP: case PG_UP:
case PG_DOWN: case PG_DOWN:
editor_move_cursor(c); command_move_cursor(c);
break; break;
case CTRL_KEY('Q'): case CTRL_KEY('Q'):
terminal_clear(); terminal_clear();
exit(0); exit(0);
break; break;
case '\r':
break;
case 127:
case DEL:
case CTRL_KEY('H'):
break;
default:
command_insert_char(c);
} }
} }

View file

@ -1,3 +1,4 @@
#include <ctype.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
@ -11,7 +12,6 @@
#include "terminal.h" #include "terminal.h"
void editor_init(char *filename); void editor_init(char *filename);
void editor_set_message(const char *, ...);
struct editor_state E; struct editor_state E;
@ -46,6 +46,7 @@ void editor_init(char *filename) {
buffer_read_file(E.current_buf, filename); buffer_read_file(E.current_buf, filename);
editor_set_message("Welcome to kilo. Press CTRL-Q to quit."); editor_set_message("Welcome to kilo. Press CTRL-Q to quit.");
terminal_clear();
} }
void editor_set_message(const char *fmt, ...) { void editor_set_message(const char *fmt, ...) {

View file

@ -89,6 +89,7 @@ ERRCODE terminal_set_cursor_pos(int row, int col) {
KEY terminal_read_key(void) { KEY terminal_read_key(void) {
char c; char c;
int n;
while (read(STDIN_FILENO, &c, 1) == 0); while (read(STDIN_FILENO, &c, 1) == 0);
if (c == '\x1b') { if (c == '\x1b') {
@ -98,7 +99,11 @@ KEY terminal_read_key(void) {
if (read(STDIN_FILENO, buf+i, 1) == 0) break; if (read(STDIN_FILENO, buf+i, 1) == 0) break;
char escape_char; char escape_char;
if (sscanf(buf, "[%c~", &escape_char) != EOF) { int escape_int;
n = 0;
sscanf(buf, "[%c%n", &escape_char, &n);
if (n > 0) {
switch (escape_char) { switch (escape_char) {
case 'A': return ARROW_UP; case 'A': return ARROW_UP;
case 'B': return ARROW_DOWN; case 'B': return ARROW_DOWN;
@ -109,15 +114,18 @@ KEY terminal_read_key(void) {
} }
} }
if (sscanf(buf, "O%c", &escape_char) != EOF) { n = 0;
sscanf(buf, "O%c%n", &escape_char, &n);
if (n > 0) {
switch (escape_char) { switch (escape_char) {
case 'H': return HOME; case 'H': return HOME;
case 'F': return END; case 'F': return END;
} }
} }
int escape_int; n = 0;
if (sscanf(buf, "[%d~", &escape_int) != EOF) { sscanf(buf, "[%d~%n", &escape_int, &n);
if (n > 0) {
switch (escape_int) { switch (escape_int) {
case 1: case 1:
case 7: case 7: