Do some work on the text editing
A little is left, and there are bugs
This commit is contained in:
parent
818ef8d40b
commit
165eea1844
6 changed files with 102 additions and 53 deletions
|
@ -2,6 +2,7 @@
|
||||||
#define BUFFER_H
|
#define BUFFER_H
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
@ -22,13 +23,16 @@ struct buffer {
|
||||||
|
|
||||||
struct buffer *buffer_create(void);
|
struct buffer *buffer_create(void);
|
||||||
void buffer_read_file(struct buffer *buffer, const char *filename);
|
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_insert_row(struct buffer *buffer, const char *chars, int n_chars, int at);
|
||||||
|
void buffer_delete_row(struct buffer *buffer, int at);
|
||||||
ERRCODE buffer_write_file(struct buffer *buffer);
|
ERRCODE buffer_write_file(struct buffer *buffer);
|
||||||
|
|
||||||
void erow_update_rendering(struct erow *erow);
|
void erow_update_rendering(struct erow *erow);
|
||||||
|
void erow_append_string(struct erow *erow, const char *s, size_t s_len);
|
||||||
void erow_insert_char(struct erow *erow, int at, char c);
|
void erow_insert_char(struct erow *erow, int at, char c);
|
||||||
void erow_delete_char(struct erow *erow, int at);
|
void erow_delete_char(struct erow *erow, int at);
|
||||||
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);
|
||||||
|
void erow_free(struct erow *erow);
|
||||||
|
|
||||||
#endif // BUFFER_H
|
#endif // BUFFER_H
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
void command_quit(void);
|
void command_quit(void);
|
||||||
void command_move_cursor(KEY key);
|
void command_move_cursor(KEY key);
|
||||||
|
void command_insert_line(void);
|
||||||
void command_insert_char(char c);
|
void command_insert_char(char c);
|
||||||
void command_delete_char(void);
|
void command_delete_char(void);
|
||||||
void command_save_buffer(void);
|
void command_save_buffer(void);
|
||||||
|
|
81
src/buffer.c
81
src/buffer.c
|
@ -23,8 +23,7 @@ struct buffer *buffer_create(void) {
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Handle file not existing
|
void buffer_read_file(struct buffer *buffer, const char *filename) { // TODO: Add error handling
|
||||||
void buffer_read_file(struct buffer *buffer, const char *filename) {
|
|
||||||
if (buffer->filename)
|
if (buffer->filename)
|
||||||
free(buffer->filename);
|
free(buffer->filename);
|
||||||
|
|
||||||
|
@ -53,7 +52,7 @@ void buffer_read_file(struct buffer *buffer, const char *filename) {
|
||||||
line_buffer[i] = c;
|
line_buffer[i] = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_append_row(buffer, line_buffer, i);
|
buffer_insert_row(buffer, line_buffer, i, buffer->n_rows);
|
||||||
file_remaining = (c != EOF);
|
file_remaining = (c != EOF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,18 +94,31 @@ END:
|
||||||
return errcode;
|
return errcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void buffer_append_row(struct buffer *buffer, const char *chars, int n_chars) {
|
void buffer_insert_row(struct buffer *buffer, const char *chars, int n_chars, int at) { // TODO: Make this take an erow
|
||||||
buffer->rows = realloc(buffer->rows, sizeof(struct erow) * (buffer->n_rows + 1));
|
buffer->rows = realloc(buffer->rows, sizeof(struct erow) * (buffer->n_rows + 1));
|
||||||
struct erow *new_row = &buffer->rows[buffer->n_rows++];
|
memmove(buffer->rows + at, buffer->rows + at + 1, sizeof(struct erow) * (buffer->n_rows - at));
|
||||||
|
struct erow *erow = buffer->rows + at;
|
||||||
|
|
||||||
new_row->chars = malloc(n_chars);
|
erow->chars = malloc(n_chars);
|
||||||
memcpy(new_row->chars, chars, n_chars);
|
memcpy(erow->chars, chars, n_chars);
|
||||||
new_row->n_chars = n_chars;
|
erow->n_chars = n_chars;
|
||||||
|
|
||||||
new_row->rchars = NULL;
|
erow->rchars = NULL;
|
||||||
new_row->n_rchars = 0;
|
erow->n_rchars = 0;
|
||||||
|
|
||||||
erow_update_rendering(new_row);
|
erow_update_rendering(erow);
|
||||||
|
|
||||||
|
buffer->modified = true;
|
||||||
|
buffer->n_rows++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void buffer_delete_row(struct buffer *buffer, int at) {
|
||||||
|
if (!(0 <= at && at < buffer->n_rows))
|
||||||
|
return;
|
||||||
|
|
||||||
|
erow_free(buffer->rows + at);
|
||||||
|
memmove(buffer->rows + at, buffer->rows + at + 1, sizeof(struct erow) * (buffer->n_rows - at - 1));
|
||||||
|
buffer->n_rows--;
|
||||||
|
|
||||||
buffer->modified = true;
|
buffer->modified = true;
|
||||||
}
|
}
|
||||||
|
@ -117,10 +129,8 @@ void buffer_free(struct buffer *buffer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void buffer_free_rows(struct buffer *buffer) {
|
static void buffer_free_rows(struct buffer *buffer) {
|
||||||
for (int i = 0; i < buffer->n_rows; i++) {
|
for (int i = 0; i < buffer->n_rows; i++)
|
||||||
if (buffer->rows->chars) free(buffer->rows->chars);
|
erow_free(buffer->rows + i);
|
||||||
if (buffer->rows->rchars) free(buffer->rows->rchars);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *buffer_get_string(struct buffer *buffer, size_t *len_p) {
|
static char *buffer_get_string(struct buffer *buffer, size_t *len_p) {
|
||||||
|
@ -179,9 +189,19 @@ void erow_update_rendering(struct erow *erow) {
|
||||||
free(line_buffer);
|
free(line_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void erow_append_string(struct erow *erow, const char *s, size_t s_len) {
|
||||||
|
erow->n_chars = erow->n_chars + s_len;
|
||||||
|
erow->chars = realloc(erow->chars, erow->n_chars);
|
||||||
|
|
||||||
|
memcpy(erow->chars + erow->n_chars - s_len, s, s_len);
|
||||||
|
erow_update_rendering(erow);
|
||||||
|
|
||||||
|
E.current_buf->modified = true; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
void erow_insert_char(struct erow *erow, int at, char c) {
|
void erow_insert_char(struct erow *erow, int at, char c) {
|
||||||
if (at < 0) at = 0;
|
if (!(0 <= at && at <= erow->n_chars))
|
||||||
if (at > erow->n_chars) at = erow->n_chars;
|
return;
|
||||||
|
|
||||||
erow->chars = realloc(erow->chars, erow->n_chars + 1);
|
erow->chars = realloc(erow->chars, erow->n_chars + 1);
|
||||||
memmove(erow->chars + at + 1, erow->chars + at, erow->n_chars - at);
|
memmove(erow->chars + at + 1, erow->chars + at, erow->n_chars - at);
|
||||||
|
@ -191,24 +211,20 @@ void erow_insert_char(struct erow *erow, int at, char c) {
|
||||||
|
|
||||||
erow_update_rendering(erow);
|
erow_update_rendering(erow);
|
||||||
|
|
||||||
// TODO: Seems like a bad idea
|
E.current_buf->modified = true; // TODO
|
||||||
E.current_buf->modified = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void erow_delete_char(struct erow *erow, int at) {
|
void erow_delete_char(struct erow *erow, int at) {
|
||||||
if (at < 0) at = 0;
|
if (!(0 <= at && at < erow->n_chars))
|
||||||
if (at > erow->n_chars) at = erow->n_chars;
|
return;
|
||||||
|
|
||||||
if (at != 0) {
|
memmove(erow->chars + at, erow->chars + at + 1, erow->n_chars - at);
|
||||||
memmove(erow->chars + at, erow->chars + at + 1, erow->n_chars - at);
|
erow->n_chars--;
|
||||||
erow->n_chars--;
|
erow->chars = realloc(erow->chars, erow->n_chars);
|
||||||
erow->chars = realloc(erow->chars, erow->n_chars);
|
E.cx--;
|
||||||
E.cx--;
|
erow_update_rendering(erow);
|
||||||
erow_update_rendering(erow);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO
|
E.current_buf->modified = true; // TODO
|
||||||
E.current_buf->modified = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int erow_cx_to_rx(struct erow *erow, int cx) {
|
int erow_cx_to_rx(struct erow *erow, int cx) {
|
||||||
|
@ -242,3 +258,8 @@ int erow_rx_to_cx(struct erow *erow, int rx) {
|
||||||
|
|
||||||
return (_rx >= rx ? cx : erow->n_chars);
|
return (_rx >= rx ? cx : erow->n_chars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void erow_free(struct erow *erow) {
|
||||||
|
if (erow->chars) free(erow->chars);
|
||||||
|
if (erow->rchars) free(erow->rchars);
|
||||||
|
}
|
||||||
|
|
|
@ -28,8 +28,8 @@ 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 = (rows && E.cy < n_rows ? rows + E.cy : NULL);
|
struct erow *erow = (rows && E.cy < n_rows ? rows + E.cy : NULL);
|
||||||
int max_x = (current_row ? current_row->n_chars : 0);
|
int max_x = (erow ? erow->n_chars : 0);
|
||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case ARROW_LEFT:
|
case ARROW_LEFT:
|
||||||
|
@ -70,21 +70,43 @@ void command_move_cursor(KEY key) {
|
||||||
cursor_adjust_viewport();
|
cursor_adjust_viewport();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void command_insert_line(void) {
|
||||||
|
buffer_insert_row(E.current_buf, NULL, 0, ++E.cy);
|
||||||
|
|
||||||
|
E.cx = 0;
|
||||||
|
E.rx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void command_insert_char(char c) {
|
void command_insert_char(char c) {
|
||||||
if (E.cy == E.current_buf->n_rows)
|
if (E.cy == E.current_buf->n_rows)
|
||||||
buffer_append_row(E.current_buf, NULL, 0);
|
buffer_insert_row(E.current_buf, NULL, 0, E.current_buf->n_rows);
|
||||||
|
|
||||||
erow_insert_char(E.current_buf->rows+E.cy, E.cx++, c);
|
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);
|
E.rx = erow_cx_to_rx(E.current_buf->rows+E.cy, E.cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void command_delete_char(void) {
|
void command_delete_char(void) { // TODO
|
||||||
struct erow *row = E.current_buf->rows + E.cy;
|
if (E.cx == 0 && E.cy == 0) return;
|
||||||
|
if (E.cy == E.current_buf->n_rows) {
|
||||||
|
E.cx = E.current_buf->rows[--E.cy].n_chars;
|
||||||
|
E.rx = erow_cx_to_rx(E.current_buf->rows+E.cy, E.cx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (E.cx == 0) {
|
if (E.cx > 0) {
|
||||||
// TODO
|
erow_delete_char(E.current_buf->rows+E.cy, E.cx - 1);
|
||||||
} else
|
}
|
||||||
erow_delete_char(row, E.cx);
|
else {
|
||||||
|
struct erow *c_row = E.current_buf->rows + E.cy;
|
||||||
|
struct erow *p_row = E.current_buf->rows + E.cy - 1;
|
||||||
|
|
||||||
|
E.cx = p_row->n_chars;
|
||||||
|
|
||||||
|
erow_append_string(p_row, c_row->chars, c_row->n_chars);
|
||||||
|
buffer_delete_row(E.current_buf, E.cy);
|
||||||
|
|
||||||
|
E.cy--;
|
||||||
|
}
|
||||||
|
|
||||||
E.rx = erow_cx_to_rx(E.current_buf->rows+E.cy, E.cx);
|
E.rx = erow_cx_to_rx(E.current_buf->rows+E.cy, E.cx);
|
||||||
}
|
}
|
||||||
|
@ -102,8 +124,8 @@ static void cursor_check_file_bounds(bool horizontal) {
|
||||||
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 = (rows && E.cy < n_rows ? rows + E.cy : NULL);
|
struct erow *erow = (rows && E.cy < n_rows ? rows + E.cy : NULL);
|
||||||
int max_x = (current_row ? current_row->n_chars : 0);
|
int max_x = (erow ? erow->n_chars : 0);
|
||||||
|
|
||||||
if (E.cy < 0)
|
if (E.cy < 0)
|
||||||
E.cy = 0;
|
E.cy = 0;
|
||||||
|
@ -114,8 +136,8 @@ static void cursor_check_file_bounds(bool horizontal) {
|
||||||
if (E.cx < 0) {
|
if (E.cx < 0) {
|
||||||
if (E.cy > 0 && horizontal)
|
if (E.cy > 0 && horizontal)
|
||||||
{
|
{
|
||||||
current_row = &rows[--E.cy];
|
erow = &rows[--E.cy];
|
||||||
max_x = current_row->n_chars;
|
max_x = erow->n_chars;
|
||||||
|
|
||||||
E.cx = max_x;
|
E.cx = max_x;
|
||||||
}
|
}
|
||||||
|
@ -134,13 +156,13 @@ static void cursor_update_rx(bool horizontal) {
|
||||||
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 = (rows && E.cy < n_rows ? rows + E.cy : NULL);
|
struct erow *erow = (rows && E.cy < n_rows ? rows + E.cy : NULL);
|
||||||
int max_x = (current_row ? current_row->n_chars : 0);
|
int max_x = (erow ? erow->n_chars : 0);
|
||||||
|
|
||||||
static int saved_rx = 0;
|
static int saved_rx = 0;
|
||||||
if (horizontal) saved_rx = erow_cx_to_rx(current_row, E.cx);
|
if (horizontal) saved_rx = erow_cx_to_rx(erow, E.cx);
|
||||||
else {
|
else {
|
||||||
E.cx = erow_rx_to_cx(current_row, saved_rx);
|
E.cx = erow_rx_to_cx(erow, saved_rx);
|
||||||
if (E.cx > max_x)
|
if (E.cx > max_x)
|
||||||
E.cx = max_x;
|
E.cx = max_x;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,12 +30,13 @@ void input_process_key(void) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '\r':
|
case '\r':
|
||||||
// TODO
|
command_insert_line();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DEL:
|
||||||
|
command_move_cursor(ARROW_RIGHT);
|
||||||
case BACKSPACE:
|
case BACKSPACE:
|
||||||
case CTRL_KEY('H'):
|
case CTRL_KEY('H'):
|
||||||
case DEL:
|
|
||||||
command_delete_char();
|
command_delete_char();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
6
src/ui.c
6
src/ui.c
|
@ -43,10 +43,10 @@ static void ui_draw_rows(struct append_buf *draw_buf) {
|
||||||
bool no_file = (E.current_buf->n_rows == 0);
|
bool no_file = (E.current_buf->n_rows == 0);
|
||||||
|
|
||||||
if (in_file) {
|
if (in_file) {
|
||||||
struct erow curr_row = E.current_buf->rows[y + E.row_off];
|
struct erow erow = E.current_buf->rows[y + E.row_off];
|
||||||
int max_len = MIN(curr_row.n_rchars - E.col_off, E.screencols);
|
int max_len = MIN(erow.n_rchars - E.col_off, E.screencols);
|
||||||
|
|
||||||
ab_append(draw_buf, curr_row.rchars + E.col_off, MAX(max_len, 0));
|
ab_append(draw_buf, erow.rchars + E.col_off, MAX(max_len, 0));
|
||||||
} else if (no_file && y == E.screenrows / 2) {
|
} else if (no_file && y == E.screenrows / 2) {
|
||||||
char welcome[64];
|
char welcome[64];
|
||||||
int len = snprintf(welcome, sizeof(welcome),
|
int len = snprintf(welcome, sizeof(welcome),
|
||||||
|
|
Reference in a new issue