commit 7ab113c2bfc7b4114f11cd517cd9a39db17e07f2
parent 55d0e193e2417318336a7eb5fd8e42fe8c519de0
Author: rexim <reximkut@gmail.com>
Date: Fri, 2 Jul 2021 21:22:25 +0700
Implement multiple lines
Diffstat:
| M | Makefile | | | 2 | +- |
| D | buffer.c | | | 56 | -------------------------------------------------------- |
| D | buffer.h | | | 16 | ---------------- |
| A | editor.c | | | 165 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | editor.h | | | 30 | ++++++++++++++++++++++++++++++ |
| M | main.c | | | 64 | ++++++++++++++++++++++++++++++++++++++++++++-------------------- |
6 files changed, 240 insertions(+), 93 deletions(-)
diff --git a/Makefile b/Makefile
@@ -2,4 +2,4 @@ CFLAGS=-Wall -Wextra -std=c11 -pedantic -ggdb `pkg-config --cflags sdl2`
LIBS=`pkg-config --libs sdl2` -lm
te: main.c
- $(CC) $(CFLAGS) -o te main.c la.c buffer.c $(LIBS)
+ $(CC) $(CFLAGS) -o te main.c la.c editor.c $(LIBS)
diff --git a/buffer.c b/buffer.c
@@ -1,56 +0,0 @@
-#include <assert.h>
-#include <string.h>
-#include "./buffer.h"
-
-#define LINE_INIT_CAPACITY 1024
-
-static void line_grow(Line *line, size_t n)
-{
- size_t new_capacity = line->capacity;
-
- assert(new_capacity >= line->size);
- while (new_capacity - line->size < n) {
- if (new_capacity == 0) {
- new_capacity = LINE_INIT_CAPACITY;
- } else {
- new_capacity *= 2;
- }
- }
-
- if (new_capacity != line->capacity) {
- line->chars = realloc(line->chars, new_capacity);
- line->capacity = new_capacity;
- }
-}
-
-void line_insert_text_before(Line *line, const char *text, size_t col)
-{
- const size_t text_size = strlen(text);
- line_grow(line, text_size);
-
- memmove(line->chars + col + text_size,
- line->chars + col,
- line->size - col);
- memcpy(line->chars + col, text, text_size);
- line->size += text_size;
-}
-
-void line_backspace(Line *line, size_t col)
-{
- if (col > 0 && line->size > 0) {
- memmove(line->chars + col - 1,
- line->chars + col,
- line->size - col);
- line->size -= 1;
- }
-}
-
-void line_delete(Line *line, size_t col)
-{
- if (col < line->size && line->size > 0) {
- memmove(line->chars + col,
- line->chars + col + 1,
- line->size - col);
- line->size -= 1;
- }
-}
diff --git a/buffer.h b/buffer.h
@@ -1,16 +0,0 @@
-#ifndef BUFFER_H_
-#define BUFFER_H_
-
-#include <stdlib.h>
-
-typedef struct {
- size_t capacity;
- size_t size;
- char *chars;
-} Line;
-
-void line_insert_text_before(Line *line, const char *text, size_t col);
-void line_backspace(Line *line, size_t col);
-void line_delete(Line *line, size_t col);
-
-#endif // BUFFER_H_
diff --git a/editor.c b/editor.c
@@ -0,0 +1,165 @@
+#include <assert.h>
+#include <string.h>
+#include <stdbool.h>
+#include "./editor.h"
+
+#define LINE_INIT_CAPACITY 1024
+#define EDITOR_INIT_CAPACITY 128
+
+static void line_grow(Line *line, size_t n)
+{
+ size_t new_capacity = line->capacity;
+
+ assert(new_capacity >= line->size);
+ while (new_capacity - line->size < n) {
+ if (new_capacity == 0) {
+ new_capacity = LINE_INIT_CAPACITY;
+ } else {
+ new_capacity *= 2;
+ }
+ }
+
+ if (new_capacity != line->capacity) {
+ line->chars = realloc(line->chars, new_capacity);
+ line->capacity = new_capacity;
+ }
+}
+
+void line_insert_text_before(Line *line, const char *text, size_t *col)
+{
+ if (*col > line->size) {
+ *col = line->size;
+ }
+
+ const size_t text_size = strlen(text);
+ line_grow(line, text_size);
+
+ memmove(line->chars + *col + text_size,
+ line->chars + *col,
+ line->size - *col);
+ memcpy(line->chars + *col, text, text_size);
+ line->size += text_size;
+ *col += text_size;
+}
+
+void line_backspace(Line *line, size_t *col)
+{
+ if (*col > line->size) {
+ *col = line->size;
+ }
+
+ if (*col > 0 && line->size > 0) {
+ memmove(line->chars + *col - 1,
+ line->chars + *col,
+ line->size - *col);
+ line->size -= 1;
+ *col -= 1;
+ }
+}
+
+void line_delete(Line *line, size_t *col)
+{
+ if (*col > line->size) {
+ *col = line->size;
+ }
+
+ if (*col < line->size && line->size > 0) {
+ memmove(line->chars + *col,
+ line->chars + *col + 1,
+ line->size - *col);
+ line->size -= 1;
+ }
+}
+
+static void editor_grow(Editor *editor, size_t n)
+{
+ size_t new_capacity = editor->capacity;
+
+ assert(new_capacity >= editor->size);
+ while (new_capacity - editor->size < n) {
+ if (new_capacity == 0) {
+ new_capacity = EDITOR_INIT_CAPACITY;
+ } else {
+ new_capacity *= 2;
+ }
+ }
+
+ if (new_capacity != editor->capacity) {
+ editor->lines = realloc(editor->lines, new_capacity * sizeof(editor->lines[0]));
+ editor->capacity = new_capacity;
+ }
+}
+
+void editor_insert_new_line(Editor *editor)
+{
+ if (editor->cursor_row > editor->size) {
+ editor->cursor_row = editor->size;
+ }
+
+ editor_grow(editor, 1);
+
+ const size_t line_size = sizeof(editor->lines[0]);
+ memmove(editor->lines + editor->cursor_row + 1,
+ editor->lines + editor->cursor_row,
+ (editor->size - editor->cursor_row) * line_size);
+ memset(&editor->lines[editor->cursor_row + 1], 0, line_size);
+ editor->cursor_row += 1;
+ editor->cursor_col = 0;
+ 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)
+{
+ if (editor->cursor_row >= editor->size) {
+ if (editor->size > 0) {
+ editor->cursor_row = editor->size - 1;
+ } else {
+ editor_push_new_line(editor);
+ }
+ }
+
+ line_insert_text_before(&editor->lines[editor->cursor_row], text, &editor->cursor_col);
+}
+
+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);
+ }
+ }
+
+ line_backspace(&editor->lines[editor->cursor_row], &editor->cursor_col);
+}
+
+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);
+ }
+ }
+
+ line_delete(&editor->lines[editor->cursor_row], &editor->cursor_col);
+}
+
+const char *editor_char_under_cursor(const Editor *editor)
+{
+ if (editor->cursor_row < editor->size) {
+ if (editor->cursor_col < editor->lines[editor->cursor_row].size) {
+ return &editor->lines[editor->cursor_row].chars[editor->cursor_col];
+ }
+ }
+ return NULL;
+}
diff --git a/editor.h b/editor.h
@@ -0,0 +1,30 @@
+#ifndef EDITOR_H_
+#define EDITOR_H_
+
+#include <stdlib.h>
+
+typedef struct {
+ size_t capacity;
+ size_t size;
+ char *chars;
+} Line;
+
+void line_insert_text_before(Line *line, const char *text, size_t *col);
+void line_backspace(Line *line, size_t *col);
+void line_delete(Line *line, size_t *col);
+
+typedef struct {
+ size_t capacity;
+ size_t size;
+ Line *lines;
+ size_t cursor_row;
+ size_t cursor_col;
+} Editor;
+
+void editor_insert_text_before_cursor(Editor *editor, const char *text);
+void editor_insert_new_line(Editor *editor);
+void editor_backspace(Editor *editor);
+void editor_delete(Editor *editor);
+const char *editor_char_under_cursor(const Editor *editor);
+
+#endif // EDITOR_H_
diff --git a/main.c b/main.c
@@ -9,7 +9,7 @@
#define STB_IMAGE_IMPLEMENTATION
#include "./stb_image.h"
-#include "./buffer.h"
+#include "./editor.h"
#define FONT_WIDTH 128
#define FONT_HEIGHT 64
@@ -138,8 +138,7 @@ void render_text_sized(SDL_Renderer *renderer, Font *font, const char *text, siz
}
}
-Line line = {0};
-size_t cursor = 0;
+Editor editor = {0};
#define UNHEX(color) \
((color) >> (8 * 0)) & 0xFF, \
@@ -149,7 +148,9 @@ size_t cursor = 0;
void render_cursor(SDL_Renderer *renderer, const Font *font)
{
- const Vec2f pos = vec2f((float) cursor * FONT_CHAR_WIDTH * FONT_SCALE, 0.0f);
+ const Vec2f pos =
+ vec2f((float) editor.cursor_col * FONT_CHAR_WIDTH * FONT_SCALE,
+ (float) editor.cursor_row * FONT_CHAR_HEIGHT * FONT_SCALE);
const SDL_Rect rect = {
.x = (int) floorf(pos.x),
@@ -161,9 +162,10 @@ void render_cursor(SDL_Renderer *renderer, const Font *font)
scc(SDL_SetRenderDrawColor(renderer, UNHEX(0xFFFFFFFF)));
scc(SDL_RenderFillRect(renderer, &rect));
- set_texture_color(font->spritesheet, 0xFF000000);
- if (cursor < line.size) {
- render_char(renderer, font, line.chars[cursor], pos, FONT_SCALE);
+ const char *c = editor_char_under_cursor(&editor);
+ if (c) {
+ set_texture_color(font->spritesheet, 0xFF000000);
+ render_char(renderer, font, *c, pos, FONT_SCALE);
}
}
@@ -178,6 +180,16 @@ int main(int argc, char **argv)
(void) argc;
(void) argv;
+ editor_insert_text_before_cursor(&editor, "dhjfhskjdfhkjshdf");
+ editor_insert_new_line(&editor);
+ editor_insert_text_before_cursor(&editor, "3j4k23l4j");
+ editor_insert_new_line(&editor);
+ editor_insert_text_before_cursor(&editor, "456kj356klj35l6j");
+ editor_insert_new_line(&editor);
+ editor_insert_text_before_cursor(&editor, "46jkl45jkljclslkj");
+ editor_insert_new_line(&editor);
+ editor_insert_text_before_cursor(&editor, "tjk5kfkdjgk");
+
scc(SDL_Init(SDL_INIT_VIDEO));
SDL_Window *window =
@@ -203,28 +215,38 @@ int main(int argc, char **argv)
case SDL_KEYDOWN: {
switch (event.key.keysym.sym) {
case SDLK_BACKSPACE: {
- line_backspace(&line, cursor);
- if (cursor > 0) {
- cursor -= 1;
- }
+ editor_backspace(&editor);
}
break;
+ case SDLK_RETURN: {
+ editor_insert_new_line(&editor);
+ } break;
+
case SDLK_DELETE: {
- line_delete(&line, cursor);
+ editor_delete(&editor);
+ }
+ break;
+
+ case SDLK_UP: {
+ if (editor.cursor_row > 0) {
+ editor.cursor_row -= 1;
+ }
+ } break;
+
+ case SDLK_DOWN: {
+ editor.cursor_row += 1;
} break;
case SDLK_LEFT: {
- if (cursor > 0) {
- cursor -= 1;
+ if (editor.cursor_col > 0) {
+ editor.cursor_col -= 1;
}
}
break;
case SDLK_RIGHT: {
- if (cursor < line.size) {
- cursor += 1;
- }
+ editor.cursor_col += 1;
}
break;
}
@@ -232,8 +254,7 @@ int main(int argc, char **argv)
break;
case SDL_TEXTINPUT: {
- line_insert_text_before(&line, event.text.text, cursor);
- cursor += strlen(event.text.text);
+ editor_insert_text_before_cursor(&editor, event.text.text);
}
break;
}
@@ -242,7 +263,10 @@ int main(int argc, char **argv)
scc(SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0));
scc(SDL_RenderClear(renderer));
- render_text_sized(renderer, &font, line.chars, line.size, vec2f(0.0, 0.0), 0xFFFFFFFF, FONT_SCALE);
+ for (size_t row = 0; row < editor.size; ++row) {
+ const Line *line = editor.lines + row;
+ render_text_sized(renderer, &font, line->chars, line->size, vec2f(0.0f, row * FONT_CHAR_HEIGHT * FONT_SCALE), 0xFFFFFFFF, FONT_SCALE);
+ }
render_cursor(renderer, &font);
SDL_RenderPresent(renderer);