summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcflip <cflip@cflip.net>2023-01-18 13:50:02 -0700
committercflip <cflip@cflip.net>2023-01-18 15:45:25 -0700
commit8d4c8b32faadd97631904e411ff39cb8282030f5 (patch)
tree694416b94bf330d2490daaa0c26da1fbb6bcffb0
parent4b1811912d45bdefadc933ff2b8fc3f63471a192 (diff)
Refactor text rendering code
Previously, the editor would print visible lines plus the statusline and message bar into a buffer, then the window would display this entire buffer. This refactor makes the window directly read lines from the editor and individually display them on the screen. This will make it easier to do syntax highlighting, since that information is stored per line. The statusline and message line are still printed into a buffer to be displayed by the window, but they are now positioned from the bottom of the screen.
-rw-r--r--editor.h5
-rw-r--r--window.c93
2 files changed, 62 insertions, 36 deletions
diff --git a/editor.h b/editor.h
index aaed086..e8e4976 100644
--- a/editor.h
+++ b/editor.h
@@ -55,9 +55,8 @@ void editor_add_line_below(struct editor_state* editor);
void editor_find(struct editor_state* editor);
void editor_scroll(struct editor_state* editor);
void editor_update_screen_size(struct editor_state *);
-void editor_draw_rows(struct editor_state* editor, struct append_buffer* buffer);
-void editor_draw_status_bar(struct editor_state* editor, struct append_buffer* buffer);
-void editor_draw_message_bar(struct editor_state* editor, struct append_buffer* buffer);
+void editor_draw_status_bar(struct editor_state *editor, struct append_buffer *buffer);
+void editor_draw_message_bar(struct editor_state *editor, struct append_buffer *buffer);
void editor_destroy(struct editor_state *editor);
diff --git a/window.c b/window.c
index cbb23b8..f158701 100644
--- a/window.c
+++ b/window.c
@@ -12,6 +12,9 @@ static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static SDL_Texture *font_texture = NULL;
+static int window_width;
+static int window_height;
+
static PSFFont font;
void window_init(const char *title, int rows, int cols)
@@ -20,8 +23,8 @@ void window_init(const char *title, int rows, int cols)
fatal_error("Failed to init SDL: %s\n", SDL_GetError());
font = font_load("terminus/ter-u24n.psf");
- int window_width = cols * font.width;
- int window_height = rows * font.height;
+ window_width = cols * font.width;
+ window_height = rows * font.height;
window = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, window_width, window_height, SDL_WINDOW_RESIZABLE);
if (window == NULL)
@@ -60,62 +63,88 @@ int window_handle_event(struct editor_state *editor)
editor_insert_char(editor, *e.text.text);
break;
case SDL_WINDOWEVENT:
- if (e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
+ if (e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
+ SDL_GetWindowSize(window, &window_width, &window_height);
editor_update_screen_size(editor);
+ }
break;
}
return 1;
}
-static void draw_font_text(struct append_buffer *buffer)
+static void draw_string(const char *str, size_t len, int x, int y)
{
- SDL_Rect dstrect = { 0, 0, 0, 0 };
- SDL_Rect srcrect = { 0, 0, 0, 0 };
+ SDL_Rect dstrect = { x, y, font.width, font.height };
+ SDL_Rect srcrect = { 0, 0, font.width, font.height };
- for (int i = 0; i < buffer->length; i++) {
- const char letter = buffer->buffer[i];
-
- if (letter == ' ') {
- dstrect.x += font.width;
- continue;
- }
+ for (int i = 0; i < len; i++) {
+ const char letter = str[i];
if (letter == '\n') {
- dstrect.x = 0;
+ dstrect.x = x;
dstrect.y += font.height;
continue;
}
- int glyph_index = letter;
- if (font.unicode_desc != NULL) {
- glyph_index = font.unicode_desc[glyph_index];
+ if (isspace(letter)) {
+ dstrect.x += font.width;
+ continue;
}
- dstrect.w = font.width;
- dstrect.h = font.height;
+ if (letter == '\0')
+ break;
+ int glyph_index = letter;
+ if (font.unicode_desc != NULL)
+ glyph_index = font.unicode_desc[glyph_index];
srcrect.x = glyph_index * font.width;
- srcrect.y = 0;
- srcrect.w = font.width;
- srcrect.h = font.height;
+
SDL_RenderCopy(renderer, font_texture, &srcrect, &dstrect);
dstrect.x += font.width;
}
}
+static void draw_editor(struct editor_state *editor)
+{
+ int line_y;
+
+ /* Draw each line of text. */
+ for (int i = 0; i < editor->screen_rows; i++) {
+ line_y = i * font.height;
+
+ if (i + editor->line_offset >= editor->num_lines) {
+ draw_string("~", 1, 0, line_y);
+ continue;
+ }
+
+ line_t *line = &editor->lines[i + editor->line_offset];
+
+ /* Size and length of the text including the scroll offset. */
+ char *printed_text = &line->render[editor->col_offset];
+ size_t printed_size = line->render_size - editor->col_offset;
+ if (line->render_size >= printed_size)
+ draw_string(printed_text, printed_size, 0, line_y);
+ }
+
+ /* Draw the statusline containing file information */
+ struct append_buffer statusbuf = ABUF_INIT;
+
+ editor_draw_status_bar(editor, &statusbuf);
+ editor_draw_message_bar(editor, &statusbuf);
+
+ line_y = window_height - (font.height * 2);
+ draw_string(statusbuf.buffer, statusbuf.length, 0, line_y);
+
+ ab_free(&statusbuf);
+}
+
void window_redraw(struct editor_state *editor)
{
SDL_RenderClear(renderer);
editor_scroll(editor);
- struct append_buffer buffer = ABUF_INIT;
-
- editor_draw_rows(editor, &buffer);
- editor_draw_status_bar(editor, &buffer);
- editor_draw_message_bar(editor, &buffer);
-
- draw_font_text(&buffer);
+ draw_editor(editor);
SDL_Rect cursor_rect;
cursor_rect.x = (editor->cursor_display_x - editor->col_offset) * font.width;
@@ -133,10 +162,8 @@ void window_redraw(struct editor_state *editor)
void window_get_size(int *rows, int *cols)
{
- int w, h;
- SDL_GetWindowSize(window, &w, &h);
- *cols = w / font.width;
- *rows = h / font.height;
+ *cols = window_width / font.width;
+ *rows = window_height / font.height;
}
void window_destroy()