|
@@ -4,10 +4,13 @@
|
|
#include <errno.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <string.h>
|
|
#include "./editor.h"
|
|
#include "./editor.h"
|
|
|
|
+#include "./sv.h"
|
|
|
|
|
|
#define LINE_INIT_CAPACITY 1024
|
|
#define LINE_INIT_CAPACITY 1024
|
|
#define EDITOR_INIT_CAPACITY 128
|
|
#define EDITOR_INIT_CAPACITY 128
|
|
|
|
|
|
|
|
+static void editor_create_first_new_line(Editor *editor);
|
|
|
|
+
|
|
static void line_grow(Line *line, size_t n)
|
|
static void line_grow(Line *line, size_t n)
|
|
{
|
|
{
|
|
size_t new_capacity = line->capacity;
|
|
size_t new_capacity = line->capacity;
|
|
@@ -27,13 +30,23 @@ static void line_grow(Line *line, size_t n)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-void line_insert_text_before(Line *line, const char *text, size_t *col)
|
|
|
|
|
|
+void line_append_text(Line *line, const char *text)
|
|
|
|
+{
|
|
|
|
+ line_append_text_sized(line, text, strlen(text));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void line_append_text_sized(Line *line, const char *text, size_t text_size)
|
|
|
|
+{
|
|
|
|
+ size_t col = line->size;
|
|
|
|
+ line_insert_text_sized_before(line, text, text_size, &col);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void line_insert_text_sized_before(Line *line, const char *text, size_t text_size, size_t *col)
|
|
{
|
|
{
|
|
if (*col > line->size) {
|
|
if (*col > line->size) {
|
|
*col = line->size;
|
|
*col = line->size;
|
|
}
|
|
}
|
|
|
|
|
|
- const size_t text_size = strlen(text);
|
|
|
|
line_grow(line, text_size);
|
|
line_grow(line, text_size);
|
|
|
|
|
|
memmove(line->chars + *col + text_size,
|
|
memmove(line->chars + *col + text_size,
|
|
@@ -44,6 +57,11 @@ void line_insert_text_before(Line *line, const char *text, size_t *col)
|
|
*col += text_size;
|
|
*col += text_size;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void line_insert_text_before(Line *line, const char *text, size_t *col)
|
|
|
|
+{
|
|
|
|
+ line_insert_text_sized_before(line, text, strlen(text), col);
|
|
|
|
+}
|
|
|
|
+
|
|
void line_backspace(Line *line, size_t *col)
|
|
void line_backspace(Line *line, size_t *col)
|
|
{
|
|
{
|
|
if (*col > line->size) {
|
|
if (*col > line->size) {
|
|
@@ -110,49 +128,34 @@ void editor_insert_new_line(Editor *editor)
|
|
editor->size += 1;
|
|
editor->size += 1;
|
|
}
|
|
}
|
|
|
|
|
|
-void editor_push_new_line(Editor *editor)
|
|
|
|
-{
|
|
|
|
- editor_grow(editor, 1);
|
|
|
|
- memset(&editor->lines[editor->size], 0, sizeof(editor->lines[0]));
|
|
|
|
- editor->size += 1;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-void editor_insert_text_before_cursor(Editor *editor, const char *text)
|
|
|
|
|
|
+static void editor_create_first_new_line(Editor *editor)
|
|
{
|
|
{
|
|
if (editor->cursor_row >= editor->size) {
|
|
if (editor->cursor_row >= editor->size) {
|
|
if (editor->size > 0) {
|
|
if (editor->size > 0) {
|
|
editor->cursor_row = editor->size - 1;
|
|
editor->cursor_row = editor->size - 1;
|
|
} else {
|
|
} else {
|
|
- editor_push_new_line(editor);
|
|
|
|
|
|
+ editor_grow(editor, 1);
|
|
|
|
+ memset(&editor->lines[editor->size], 0, sizeof(editor->lines[0]));
|
|
|
|
+ editor->size += 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+}
|
|
|
|
|
|
|
|
+void editor_insert_text_before_cursor(Editor *editor, const char *text)
|
|
|
|
+{
|
|
|
|
+ editor_create_first_new_line(editor);
|
|
line_insert_text_before(&editor->lines[editor->cursor_row], text, &editor->cursor_col);
|
|
line_insert_text_before(&editor->lines[editor->cursor_row], text, &editor->cursor_col);
|
|
}
|
|
}
|
|
|
|
|
|
void editor_backspace(Editor *editor)
|
|
void editor_backspace(Editor *editor)
|
|
{
|
|
{
|
|
- if (editor->cursor_row >= editor->size) {
|
|
|
|
- if (editor->size > 0) {
|
|
|
|
- editor->cursor_row = editor->size - 1;
|
|
|
|
- } else {
|
|
|
|
- editor_push_new_line(editor);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
|
|
+ editor_create_first_new_line(editor);
|
|
line_backspace(&editor->lines[editor->cursor_row], &editor->cursor_col);
|
|
line_backspace(&editor->lines[editor->cursor_row], &editor->cursor_col);
|
|
}
|
|
}
|
|
|
|
|
|
void editor_delete(Editor *editor)
|
|
void editor_delete(Editor *editor)
|
|
{
|
|
{
|
|
- if (editor->cursor_row >= editor->size) {
|
|
|
|
- if (editor->size > 0) {
|
|
|
|
- editor->cursor_row = editor->size - 1;
|
|
|
|
- } else {
|
|
|
|
- editor_push_new_line(editor);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
|
|
+ editor_create_first_new_line(editor);
|
|
line_delete(&editor->lines[editor->cursor_row], &editor->cursor_col);
|
|
line_delete(&editor->lines[editor->cursor_row], &editor->cursor_col);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -182,3 +185,34 @@ void editor_save_to_file(const Editor *editor, const char *file_path)
|
|
|
|
|
|
fclose(f);
|
|
fclose(f);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+void editor_load_from_file(Editor *editor, FILE *file)
|
|
|
|
+{
|
|
|
|
+ assert(editor->lines == NULL && "You can only load files into an empty editor");
|
|
|
|
+ editor_create_first_new_line(editor);
|
|
|
|
+
|
|
|
|
+ static char chunk[640 * 1024];
|
|
|
|
+
|
|
|
|
+ while (!feof(file)) {
|
|
|
|
+ size_t n = fread(chunk, 1, sizeof(chunk), file);
|
|
|
|
+
|
|
|
|
+ String_View chunk_sv = {
|
|
|
|
+ .data = chunk,
|
|
|
|
+ .count = n
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ while (chunk_sv.count > 0) {
|
|
|
|
+ String_View chunk_line = {0};
|
|
|
|
+ Line *line = &editor->lines[editor->size - 1];
|
|
|
|
+ if (sv_try_chop_by_delim(&chunk_sv, '\n', &chunk_line)) {
|
|
|
|
+ line_append_text_sized(line, chunk_line.data, chunk_line.count);
|
|
|
|
+ editor_insert_new_line(editor);
|
|
|
|
+ } else {
|
|
|
|
+ line_append_text_sized(line, chunk_sv.data, chunk_sv.count);
|
|
|
|
+ chunk_sv = SV_NULL;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ editor->cursor_row = 0;
|
|
|
|
+}
|