Finish refactoring
This commit is contained in:
parent
fc5e50e4db
commit
2f560997e5
14 changed files with 160 additions and 170 deletions
|
@ -20,7 +20,7 @@ gcc -I include src/*.c -o kilo
|
||||||
|
|
||||||
## My additions
|
## My additions
|
||||||
- Split it up into multiple files and tried to follow good design and
|
- Split it up into multiple files and tried to follow good design and
|
||||||
organization practices (WIP).
|
organization practices.
|
||||||
|
|
||||||
## References
|
## References
|
||||||
- [antirez/kilo][1]
|
- [antirez/kilo][1]
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "utils.h"
|
|
||||||
#include "erow.h"
|
#include "erow.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
struct erow;
|
||||||
|
|
||||||
struct buffer {
|
struct buffer {
|
||||||
char *filename;
|
char *filename;
|
||||||
|
@ -25,6 +27,7 @@ ERRCODE buffer_write_file(struct buffer *buffer, size_t *bytes_written);
|
||||||
void buffer_insert_row(struct buffer *buffer, struct erow *erow, int at);
|
void buffer_insert_row(struct buffer *buffer, struct erow *erow, int at);
|
||||||
void buffer_delete_row(struct buffer *buffer, int at);
|
void buffer_delete_row(struct buffer *buffer, int at);
|
||||||
struct erow *buffer_get_crow(struct buffer *buffer);
|
struct erow *buffer_get_crow(struct buffer *buffer);
|
||||||
|
size_t buffer_get_crow_len(struct buffer *buffer);
|
||||||
void buffer_free(struct buffer *buffer);
|
void buffer_free(struct buffer *buffer);
|
||||||
|
|
||||||
|
|
||||||
|
|
10
include/cursor.h
Normal file
10
include/cursor.h
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef CURSOR_H
|
||||||
|
#define CURSOR_H
|
||||||
|
|
||||||
|
#include "buffer.h"
|
||||||
|
|
||||||
|
struct buffer;
|
||||||
|
|
||||||
|
void cursor_move(struct buffer *buffer, int dx, int dy);
|
||||||
|
|
||||||
|
#endif // CURSOR_H
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
struct buffer;
|
||||||
|
|
||||||
struct erow {
|
struct erow {
|
||||||
char *chars;
|
char *chars;
|
||||||
size_t n_chars;
|
size_t n_chars;
|
||||||
|
@ -15,7 +17,7 @@ struct erow {
|
||||||
|
|
||||||
struct erow *erow_create(const char* chars, size_t n_chars, struct buffer *buffer);
|
struct erow *erow_create(const char* chars, size_t n_chars, struct buffer *buffer);
|
||||||
void erow_insert_chars(struct erow *erow, const char *chars, size_t n_chars, int at);
|
void erow_insert_chars(struct erow *erow, const char *chars, size_t n_chars, int at);
|
||||||
void erow_delete_char(struct erow *erow, int at);
|
void erow_delete_chars(struct erow *erow, size_t n_chars, 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);
|
void erow_free(struct erow *erow);
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define CTRL_KEY(key) ((key) & 0x1f)
|
||||||
|
|
||||||
enum KEYS {
|
enum KEYS {
|
||||||
TAB = 9,
|
TAB = 9,
|
||||||
ENTER = 13,
|
ENTER = 13,
|
||||||
|
@ -21,6 +23,6 @@ enum KEYS {
|
||||||
};
|
};
|
||||||
typedef uint16_t KEY;
|
typedef uint16_t KEY;
|
||||||
|
|
||||||
void input_process_key(void);
|
void input_process_key(KEY c);
|
||||||
|
|
||||||
#endif // INPUT_H
|
#endif // INPUT_H
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#ifndef UTIL_H
|
#ifndef UTIL_H
|
||||||
#define UTIL_H
|
#define UTIL_H
|
||||||
|
|
||||||
#define CTRL_KEY(key) ((key) & 0x1f)
|
|
||||||
|
|
||||||
#define MAX(a,b) (((a)>(b))?(a):(b))
|
#define MAX(a,b) (((a)>(b))?(a):(b))
|
||||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||||
|
#define CLAMP(value, min, max) MIN(MAX(value, min), max)
|
||||||
|
|
||||||
#define _STRINGIZE(x) #x
|
#define _STRINGIZE(x) #x
|
||||||
#define STRINGIZE(x) _STRINGIZE(x)
|
#define STRINGIZE(x) _STRINGIZE(x)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# Progress log
|
# Progress log
|
||||||
|
|
||||||
- (4/9/2023) Finished 5 chapters out of 7, basic text editing is fully
|
- (4/9/2023) Finished 5 chapters out of 7, basic text editing is fully
|
||||||
possible. It has fun been working on this, but semester is starting now and I
|
possible. It has fun been working on this, but semester is starting now and I
|
||||||
might not get to work on this a lot anymore. It might have lots of bugs, and
|
might not get to work on this a lot anymore. It might have lots of bugs, and
|
||||||
|
@ -6,3 +7,11 @@ there's lots of things I don't like, there are TODOs everywhere. So many leaky
|
||||||
abstractions, near the end I started blindly following the tutorial and didn't
|
abstractions, near the end I started blindly following the tutorial and didn't
|
||||||
stop to think how it fits with the abstractions I have defined, but I might fix
|
stop to think how it fits with the abstractions I have defined, but I might fix
|
||||||
it all one of these days...
|
it all one of these days...
|
||||||
|
|
||||||
|
- (9/9/2023) Didn't implement any new features, but refactored heavily. All the
|
||||||
|
previous features should be working unless I introduced a bug. But I like the
|
||||||
|
abstractions better now, and I cleaned up most of TODOs. This was painful to
|
||||||
|
get right and I contemplated quitting, but proud of myself. I find it very
|
||||||
|
interesting that the total of amount of code barely changed, it actually
|
||||||
|
decreased as measured by tokei. It increased slightly in the header files and
|
||||||
|
decreased in the source files, yet it was a lot of work.
|
||||||
|
|
11
src/buffer.c
11
src/buffer.c
|
@ -1,4 +1,6 @@
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
@ -36,7 +38,6 @@ ERRCODE buffer_read_file(struct buffer *buffer, const char *filename) {
|
||||||
buffer_free_rows(buffer);
|
buffer_free_rows(buffer);
|
||||||
|
|
||||||
size_t buf_cap = 64;
|
size_t buf_cap = 64;
|
||||||
size_t buf_size = 0;
|
|
||||||
char *buf = malloc(buf_cap);
|
char *buf = malloc(buf_cap);
|
||||||
|
|
||||||
FILE *file = fopen(filename, "r");
|
FILE *file = fopen(filename, "r");
|
||||||
|
@ -45,6 +46,7 @@ ERRCODE buffer_read_file(struct buffer *buffer, const char *filename) {
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
char c;
|
char c;
|
||||||
|
size_t buf_size = 0;
|
||||||
|
|
||||||
while ((c = getc(file)) != '\n' && c != EOF) {
|
while ((c = getc(file)) != '\n' && c != EOF) {
|
||||||
if (buf_size >= buf_cap)
|
if (buf_size >= buf_cap)
|
||||||
|
@ -139,7 +141,6 @@ void buffer_insert_row(struct buffer *buffer, struct erow *erow, int at) {
|
||||||
memmove(buffer->rows + at + 1, buffer->rows + at, sizeof(struct erow *) * (buffer->n_rows - at));
|
memmove(buffer->rows + at + 1, buffer->rows + at, sizeof(struct erow *) * (buffer->n_rows - at));
|
||||||
|
|
||||||
buffer->rows[at] = erow;
|
buffer->rows[at] = erow;
|
||||||
|
|
||||||
buffer->n_rows++;
|
buffer->n_rows++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,6 +165,12 @@ void buffer_free(struct buffer *buffer) {
|
||||||
buffer_free_rows(buffer);
|
buffer_free_rows(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t buffer_get_crow_len(struct buffer *buffer) {
|
||||||
|
struct erow *crow = buffer_get_crow(buffer);
|
||||||
|
|
||||||
|
return crow ? crow->n_chars : 0;
|
||||||
|
}
|
||||||
|
|
||||||
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++)
|
||||||
erow_free(buffer->rows[i]);
|
erow_free(buffer->rows[i]);
|
||||||
|
|
192
src/commands.c
192
src/commands.c
|
@ -1,19 +1,16 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "commands.h"
|
#include "commands.h"
|
||||||
|
#include "cursor.h"
|
||||||
|
#include "erow.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "kilo.h"
|
#include "kilo.h"
|
||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
static void cursor_adjust_viewport(void);
|
|
||||||
static void cursor_check_file_bounds(bool horizontal);
|
|
||||||
static void cursor_update_rx(bool horizontal);
|
|
||||||
|
|
||||||
void command_quit(void) {
|
void command_quit(void) {
|
||||||
if (E.current_buf->modified && E.quit_times) {
|
if (E.current_buf->modified && E.quit_times) {
|
||||||
editor_set_message("Unsaved changed! Press quit %d more time(s)", E.quit_times);
|
editor_set_message("Unsaved changed! Press quit %d more time(s)", E.quit_times);
|
||||||
|
@ -25,110 +22,87 @@ void command_quit(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void command_move_cursor(KEY key) {
|
void command_move_cursor(KEY key) {
|
||||||
struct erow *rows = E.current_buf->rows;
|
|
||||||
int n_rows = E.current_buf->n_rows;
|
|
||||||
|
|
||||||
struct erow *erow = (rows && E.cy < n_rows ? rows + E.cy : NULL);
|
|
||||||
int max_x = (erow ? erow->n_chars : 0);
|
|
||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case ARROW_LEFT:
|
case ARROW_LEFT:
|
||||||
E.cx--;
|
cursor_move(E.current_buf, -1, 0);
|
||||||
break;
|
break;
|
||||||
case ARROW_DOWN:
|
case ARROW_DOWN:
|
||||||
E.cy++;
|
cursor_move(E.current_buf, 0, 1);
|
||||||
break;
|
break;
|
||||||
case ARROW_UP:
|
case ARROW_UP:
|
||||||
E.cy--;
|
cursor_move(E.current_buf, 0, -1);
|
||||||
break;
|
break;
|
||||||
case ARROW_RIGHT:
|
case ARROW_RIGHT:
|
||||||
E.cx++;
|
cursor_move(E.current_buf, 1, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HOME:
|
case HOME:
|
||||||
E.cx = 0;
|
cursor_move(E.current_buf, -E.current_buf->cx, 0);
|
||||||
break;
|
break;
|
||||||
case END:
|
case END:
|
||||||
E.cx = max_x;
|
cursor_move(E.current_buf, buffer_get_crow_len(E.current_buf) - E.current_buf->cx, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PG_UP:
|
case PG_UP:
|
||||||
E.cy -= E.screenrows;
|
cursor_move(E.current_buf, 0, -E.screenrows);
|
||||||
break;
|
break;
|
||||||
case PG_DOWN:
|
case PG_DOWN:
|
||||||
E.cy += E.screenrows;
|
cursor_move(E.current_buf, 0, E.screenrows);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool horizontal = (key == ARROW_LEFT ||
|
|
||||||
key == ARROW_RIGHT ||
|
|
||||||
key == HOME ||
|
|
||||||
key == END);
|
|
||||||
|
|
||||||
cursor_check_file_bounds(horizontal);
|
|
||||||
cursor_update_rx(horizontal);
|
|
||||||
cursor_adjust_viewport();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Improve this
|
|
||||||
void command_insert_line(void) {
|
void command_insert_line(void) {
|
||||||
if (E.cy == E.current_buf->n_rows) {
|
struct erow *erow = erow_create(NULL, 0, E.current_buf);
|
||||||
buffer_insert_row(E.current_buf, NULL, 0, E.cy);
|
|
||||||
|
if (E.current_buf->cy == E.current_buf->n_rows) {
|
||||||
|
buffer_insert_row(E.current_buf, erow, E.current_buf->cy);
|
||||||
} else {
|
} else {
|
||||||
buffer_insert_row(E.current_buf, NULL, 0, E.cy + 1);
|
buffer_insert_row(E.current_buf, erow, E.current_buf->cy + 1);
|
||||||
|
|
||||||
struct erow *c_row = E.current_buf->rows + E.cy;
|
struct erow *crow = buffer_get_crow(E.current_buf);
|
||||||
struct erow *n_row = E.current_buf->rows + E.cy + 1;
|
|
||||||
|
|
||||||
erow_append_string(n_row, c_row->chars + E.cx, c_row->n_chars - E.cx);
|
erow_insert_chars(erow, crow->chars + E.current_buf->cx, crow->n_chars - E.current_buf->cx, 0);
|
||||||
|
erow_delete_chars(crow, crow->n_chars - E.current_buf->cx, E.current_buf->cx);
|
||||||
c_row->chars = realloc(c_row->chars, E.cx);
|
|
||||||
c_row->n_chars = E.cx;
|
|
||||||
erow_update_rendering(c_row);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
E.cx = E.rx = 0;
|
input_process_key(ARROW_DOWN);
|
||||||
E.cy++;
|
input_process_key(HOME);
|
||||||
|
|
||||||
cursor_adjust_viewport();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void command_insert_char(char c) {
|
void command_insert_char(char c) {
|
||||||
if (E.cy == E.current_buf->n_rows)
|
struct erow *erow;
|
||||||
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);
|
if (E.current_buf->cy == E.current_buf->n_rows) {
|
||||||
E.rx = erow_cx_to_rx(E.current_buf->rows+E.cy, E.cx);
|
erow = erow_create(NULL, 0, E.current_buf);
|
||||||
|
buffer_insert_row(E.current_buf, erow, E.current_buf->n_rows);
|
||||||
|
} else erow = buffer_get_crow(E.current_buf);
|
||||||
|
|
||||||
cursor_adjust_viewport();
|
erow_insert_chars(erow, &c, 1, E.current_buf->cx);
|
||||||
|
input_process_key(ARROW_RIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void command_delete_char(void) { // TODO
|
void command_delete_char(void) {
|
||||||
if (E.cx == 0 && E.cy == 0) return;
|
if (E.current_buf->cy == E.current_buf->n_rows)
|
||||||
if (E.cy == E.current_buf->n_rows) {
|
input_process_key(ARROW_LEFT);
|
||||||
E.cx = E.current_buf->rows[--E.cy].n_chars;
|
|
||||||
E.rx = erow_cx_to_rx(E.current_buf->rows+E.cy, E.cx);
|
struct erow *crow = buffer_get_crow(E.current_buf);
|
||||||
return;
|
|
||||||
|
if (E.current_buf->cx == 0) {
|
||||||
|
if (E.current_buf->cy == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct erow *prow = E.current_buf->rows[E.current_buf->cy - 1];
|
||||||
|
|
||||||
|
input_process_key(ARROW_UP);
|
||||||
|
cursor_move(E.current_buf, prow->n_chars, 0);
|
||||||
|
|
||||||
|
erow_insert_chars(prow, crow->chars, crow->n_chars, prow->n_chars);
|
||||||
|
buffer_delete_row(E.current_buf, E.current_buf->cy + 1);
|
||||||
|
} else {
|
||||||
|
erow_delete_chars(crow, 1, E.current_buf->cx - 1);
|
||||||
|
input_process_key(ARROW_LEFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (E.cx > 0) {
|
|
||||||
erow_delete_char(E.current_buf->rows+E.cy, E.cx - 1);
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
|
|
||||||
cursor_adjust_viewport();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void command_save_buffer(void) {
|
void command_save_buffer(void) {
|
||||||
|
@ -140,79 +114,11 @@ void command_save_buffer(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int bytes_written;
|
size_t bytes_written;
|
||||||
ERRCODE errcode = buffer_write_file(E.current_buf, &bytes_written);
|
ERRCODE errcode = buffer_write_file(E.current_buf, &bytes_written);
|
||||||
|
|
||||||
if (errcode == 0)
|
if (errcode == 0)
|
||||||
editor_set_message("%d bytes written", bytes_written);
|
editor_set_message("%d bytes written", bytes_written);
|
||||||
else
|
else
|
||||||
editor_set_message("Save failed: ERRCODE %d: %s", errcode, strerror(errno));
|
editor_set_message("Write error %d: %s", errcode, strerror(errno));
|
||||||
}
|
|
||||||
|
|
||||||
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 *erow = (rows && E.cy < n_rows ? rows + E.cy : NULL);
|
|
||||||
int max_x = (erow ? erow->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)
|
|
||||||
{
|
|
||||||
erow = &rows[--E.cy];
|
|
||||||
max_x = erow->n_chars;
|
|
||||||
|
|
||||||
E.cx = max_x;
|
|
||||||
}
|
|
||||||
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 *erow = (rows && E.cy < n_rows ? rows + E.cy : NULL);
|
|
||||||
int max_x = (erow ? erow->n_chars : 0);
|
|
||||||
|
|
||||||
static int saved_rx = 0;
|
|
||||||
if (horizontal) saved_rx = erow_cx_to_rx(erow, E.cx);
|
|
||||||
else {
|
|
||||||
E.cx = erow_rx_to_cx(erow, saved_rx);
|
|
||||||
if (E.cx > max_x)
|
|
||||||
E.cx = max_x;
|
|
||||||
}
|
|
||||||
|
|
||||||
E.rx = erow_cx_to_rx(rows + E.cy, E.cx);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cursor_adjust_viewport(void) {
|
|
||||||
int max_row_off = E.cy;
|
|
||||||
if (E.row_off > max_row_off)
|
|
||||||
E.row_off = max_row_off;
|
|
||||||
|
|
||||||
int max_col_off = E.rx;
|
|
||||||
if (E.col_off > max_col_off)
|
|
||||||
E.col_off = max_col_off;
|
|
||||||
|
|
||||||
int min_row_off = E.cy - (E.screenrows - 1);
|
|
||||||
if (E.row_off < min_row_off)
|
|
||||||
E.row_off = min_row_off;
|
|
||||||
|
|
||||||
int min_col_off = E.rx - (E.screencols - 1);
|
|
||||||
if (E.col_off < min_col_off)
|
|
||||||
E.col_off = min_col_off;
|
|
||||||
}
|
}
|
||||||
|
|
45
src/cursor.c
Normal file
45
src/cursor.c
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#include "buffer.h"
|
||||||
|
#include "cursor.h"
|
||||||
|
#include "erow.h"
|
||||||
|
#include "kilo.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
static void cursor_adjust_viewport(struct buffer *buffer);
|
||||||
|
|
||||||
|
void cursor_move(struct buffer *buffer, int dx, int dy) {
|
||||||
|
static int saved_rx = 0;
|
||||||
|
|
||||||
|
buffer->cy = CLAMP(buffer->cy + dy, 0, buffer->n_rows);
|
||||||
|
|
||||||
|
if (dx == 0)
|
||||||
|
E.current_buf->cx = erow_rx_to_cx(buffer_get_crow(E.current_buf), saved_rx);
|
||||||
|
|
||||||
|
int new_x = buffer->cx + dx, max_x = buffer_get_crow_len(buffer);
|
||||||
|
if (new_x < 0) {
|
||||||
|
if (buffer->cy > 0) {
|
||||||
|
buffer->cy--;
|
||||||
|
buffer->cx = buffer_get_crow_len(buffer);
|
||||||
|
} else buffer->cx = 0;
|
||||||
|
} else if (new_x > max_x) {
|
||||||
|
if (buffer->cy < buffer->n_rows) {
|
||||||
|
buffer->cy++;
|
||||||
|
buffer->cx = 0;
|
||||||
|
} else buffer->cx = max_x;
|
||||||
|
} else buffer->cx = new_x;
|
||||||
|
|
||||||
|
cursor_adjust_viewport(buffer);
|
||||||
|
buffer->rx = erow_cx_to_rx(buffer_get_crow(buffer), buffer->cx);
|
||||||
|
|
||||||
|
if (dy == 0)
|
||||||
|
saved_rx = buffer->rx;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cursor_adjust_viewport(struct buffer *buffer) {
|
||||||
|
int min_row_off = buffer->cy - (E.screenrows - 1);
|
||||||
|
int max_row_off = buffer->cy;
|
||||||
|
buffer->row_off = CLAMP(buffer->row_off, min_row_off, max_row_off);
|
||||||
|
|
||||||
|
int min_col_off = buffer->rx - (E.screencols - 1);
|
||||||
|
int max_col_off = buffer->rx;
|
||||||
|
buffer->col_off = CLAMP(buffer->col_off, min_col_off, max_col_off);
|
||||||
|
}
|
30
src/erow.c
30
src/erow.c
|
@ -1,9 +1,11 @@
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "erow.h"
|
#include "erow.h"
|
||||||
#include "kilo.h"
|
#include "kilo.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
static void erow_update_rchars(struct erow *erow);
|
static void erow_update_rchars(struct erow *erow);
|
||||||
|
|
||||||
|
@ -14,6 +16,8 @@ struct erow *erow_create(const char* chars, size_t n_chars, struct buffer *buffe
|
||||||
erow->n_chars = n_chars;
|
erow->n_chars = n_chars;
|
||||||
|
|
||||||
memcpy(erow->chars, chars, erow->n_chars);
|
memcpy(erow->chars, chars, erow->n_chars);
|
||||||
|
|
||||||
|
erow->rchars = NULL;
|
||||||
erow_update_rchars(erow);
|
erow_update_rchars(erow);
|
||||||
|
|
||||||
erow->buffer = buffer;
|
erow->buffer = buffer;
|
||||||
|
@ -23,7 +27,7 @@ struct erow *erow_create(const char* chars, size_t n_chars, struct buffer *buffe
|
||||||
|
|
||||||
void erow_insert_chars(struct erow *erow, const char *chars, size_t n_chars, int at) {
|
void erow_insert_chars(struct erow *erow, const char *chars, size_t n_chars, int at) {
|
||||||
erow->chars = realloc(erow->chars, erow->n_chars + n_chars);
|
erow->chars = realloc(erow->chars, erow->n_chars + n_chars);
|
||||||
memmove(erow->chars + at + n_chars, erow->chars + at, n_chars - at);
|
memmove(erow->chars + at + n_chars, erow->chars + at, erow->n_chars - at);
|
||||||
memcpy(erow->chars + at, chars, n_chars);
|
memcpy(erow->chars + at, chars, n_chars);
|
||||||
|
|
||||||
erow->n_chars += n_chars;
|
erow->n_chars += n_chars;
|
||||||
|
@ -34,9 +38,9 @@ void erow_insert_chars(struct erow *erow, const char *chars, size_t n_chars, int
|
||||||
erow->buffer->modified = true;
|
erow->buffer->modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void erow_delete_char(struct erow *erow, int at) {
|
void erow_delete_chars(struct erow *erow, size_t n_chars, int at) {
|
||||||
memmove(erow->chars + at, erow->chars + at + 1, erow->n_chars - at);
|
memmove(erow->chars + at, erow->chars + at + n_chars, erow->n_chars - at - n_chars);
|
||||||
erow->chars = realloc(erow->chars, --erow->n_chars);
|
erow->chars = realloc(erow->chars, erow->n_chars -= n_chars);
|
||||||
|
|
||||||
erow_update_rchars(erow);
|
erow_update_rchars(erow);
|
||||||
|
|
||||||
|
@ -45,6 +49,11 @@ 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) {
|
||||||
|
if (erow == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cx = CLAMP(cx, 0, (int) erow->n_chars);
|
||||||
|
|
||||||
int rx = 0;
|
int rx = 0;
|
||||||
|
|
||||||
for (char *c = erow->chars; c < erow->chars + cx; c++) {
|
for (char *c = erow->chars; c < erow->chars + cx; c++) {
|
||||||
|
@ -58,17 +67,18 @@ 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) {
|
||||||
if ((size_t) rx >= erow->n_rchars)
|
if (erow == NULL)
|
||||||
return erow->n_chars;
|
return 0;
|
||||||
|
|
||||||
int c_rx = 0;
|
int cx = 0, c_rx = 0;
|
||||||
|
while ((size_t) cx < erow->n_chars) {
|
||||||
for (int cx = 0; (size_t) cx < erow->n_chars; cx++) {
|
|
||||||
if (erow->chars[cx] == '\t')
|
if (erow->chars[cx] == '\t')
|
||||||
c_rx += KILO_TAB_STOP - (c_rx % KILO_TAB_STOP);
|
c_rx += KILO_TAB_STOP - (c_rx % KILO_TAB_STOP);
|
||||||
else
|
else
|
||||||
c_rx++;
|
c_rx++;
|
||||||
|
|
||||||
|
cx++;
|
||||||
|
|
||||||
if (c_rx >= rx)
|
if (c_rx >= rx)
|
||||||
return cx;
|
return cx;
|
||||||
}
|
}
|
||||||
|
@ -86,7 +96,7 @@ static void erow_update_rchars(struct erow *erow) {
|
||||||
free(erow->rchars);
|
free(erow->rchars);
|
||||||
|
|
||||||
size_t n_rchars_max = 16;
|
size_t n_rchars_max = 16;
|
||||||
erow->rchars = malloc(erow->n_rchars);
|
erow->rchars = malloc(n_rchars_max);
|
||||||
erow->n_rchars = 0;
|
erow->n_rchars = 0;
|
||||||
|
|
||||||
for (char *c = erow->chars; c < erow->chars + erow->n_chars; c++) {
|
for (char *c = erow->chars; c < erow->chars + erow->n_chars; c++) {
|
||||||
|
|
10
src/input.c
10
src/input.c
|
@ -1,12 +1,8 @@
|
||||||
#include "commands.h"
|
#include "commands.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "kilo.h"
|
#include "kilo.h"
|
||||||
#include "terminal.h"
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
void input_process_key(void) {
|
|
||||||
KEY c = terminal_read_key();
|
|
||||||
|
|
||||||
|
void input_process_key(KEY c) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case ARROW_LEFT:
|
case ARROW_LEFT:
|
||||||
case ARROW_DOWN:
|
case ARROW_DOWN:
|
||||||
|
@ -20,7 +16,7 @@ void input_process_key(void) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CTRL_KEY('S'):
|
case CTRL_KEY('S'):
|
||||||
command_save_buffer();
|
// command_save_buffer();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENTER:
|
case ENTER:
|
||||||
|
@ -28,7 +24,7 @@ void input_process_key(void) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEL:
|
case DEL:
|
||||||
command_move_cursor(ARROW_RIGHT);
|
input_process_key(ARROW_RIGHT);
|
||||||
case BACKSPACE:
|
case BACKSPACE:
|
||||||
case CTRL_KEY('H'):
|
case CTRL_KEY('H'):
|
||||||
command_delete_char();
|
command_delete_char();
|
||||||
|
|
|
@ -22,7 +22,7 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
ui_draw_screen();
|
ui_draw_screen();
|
||||||
input_process_key();
|
input_process_key(terminal_read_key());
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
3
src/ui.c
3
src/ui.c
|
@ -6,6 +6,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "erow.h"
|
||||||
#include "kilo.h"
|
#include "kilo.h"
|
||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
|
@ -44,7 +45,7 @@ static void ui_draw_rows(struct append_buf *draw_buf) {
|
||||||
bool no_file = (E.current_buf->filename == NULL && E.current_buf->n_rows == 0);
|
bool no_file = (E.current_buf->filename == NULL && E.current_buf->n_rows == 0);
|
||||||
|
|
||||||
if (in_file) {
|
if (in_file) {
|
||||||
struct erow *crow = buffer_get_crow(E.current_buf);
|
struct erow *crow = E.current_buf->rows[y + E.current_buf->row_off];
|
||||||
|
|
||||||
size_t len = crow->n_rchars - E.current_buf->col_off;
|
size_t len = crow->n_rchars - E.current_buf->col_off;
|
||||||
len = MIN(len, (size_t) E.screencols);
|
len = MIN(len, (size_t) E.screencols);
|
||||||
|
|
Reference in a new issue