#include "edit.h" #include "arena_alloc.h" #include "gapbuffer.h" #include "mprintf.h" #include "self.h" #include "walloc.h" #include #include #include #include #include #include #include #include #include #include #include #include #include struct edit_line { struct list_node_link lines_link; struct gapbuffer gb; }; struct cursor { size_t col; size_t line; }; struct editor { struct list_node_link* lines; struct edit_line* current_line; struct cursor cursor; }; static struct editor editor; static bool prepare_lines_cb (void* ctx, const char* start, size_t len) { struct edit_line* line = malloc (sizeof (*line)); if (line == NULL) return false; memset (line, 0, sizeof (*line)); gapbuffer_init (&wmalloc, NULL, &line->gb, len); for (size_t chr = 0; chr < len; chr++) gapbuffer_insert (&wrealloc, NULL, &line->gb, start[chr]); list_append (editor.lines, &line->lines_link); if (editor.current_line == NULL) editor.current_line = line; return true; } static void prepare_lines (const char* text) { strtokenize (text, '\n', NULL, &prepare_lines_cb); } void edit_start (const char* text) { prepare_lines (text); struct arena temp_arena; mprintf (ANSIQ_SCR_SAVE ANSIQ_SCR_CLR_ALL ANSIQ_CUR_INVISIBLE); for (;;) { const size_t backbuffer_max = 128 * 1024; char* backbuffer = arena_malloc (&temp_arena, backbuffer_max); memset (backbuffer, 0, backbuffer_max); strncat (backbuffer, ANSIQ_CUR_HOME ANSIQ_SCR_CLR_ALL, backbuffer_max); struct list_node_link *line_link, *tmp_line_link; list_foreach (editor.lines, line_link, tmp_line_link) { struct edit_line* line = list_entry (line_link, struct edit_line, lines_link); strncat (backbuffer, ANSIQ_SCR_CLR_LINE, backbuffer_max); char* render = gapbuffer_get_string (&warena_malloc, &temp_arena, &line->gb); strncat (backbuffer, render, backbuffer_max); strncat (backbuffer, "\n", backbuffer_max); } char tmp[128]; snprintf (tmp, sizeof (tmp), ANSIQ_DYN_CUR_SET ANSIQ_CUR_VISIBLE, (int)editor.cursor.line + 1, (int)editor.cursor.col + 1); strncat (backbuffer, tmp, backbuffer_max); mail_send (e_pgid, backbuffer, strlen (backbuffer)); uint8_t ch = 0; mail_receive (&ch, 1); gapbuffer_move (&editor.current_line->gb, editor.cursor.col); switch (ch) { case '\b': if (editor.cursor.col > 0) { editor.cursor.col--; gapbuffer_backspace (&editor.current_line->gb); } break; case KB_DELETE: if (editor.cursor.col < gapbuffer_length (&editor.current_line->gb)) { editor.current_line->gb.gap_end++; } break; case KB_LEFT: if (editor.cursor.col > 0) { editor.cursor.col--; } break; case KB_RIGHT: if (editor.cursor.col < gapbuffer_length (&editor.current_line->gb)) { editor.cursor.col++; } break; default: if (isprint (ch)) { gapbuffer_insert (&wrealloc, NULL, &editor.current_line->gb, ch); editor.cursor.col++; } break; } arena_reset (&temp_arena); } mprintf (ANSIQ_CUR_VISIBLE ANSIQ_SCR_RESTORE); arena_destroy (&temp_arena); struct list_node_link *line_link, *tmp_line_link; list_foreach (editor.lines, line_link, tmp_line_link) { struct edit_line* line = list_entry (line_link, struct edit_line, lines_link); free (line->gb.buffer); free (line); } }