#include "../include/editor_op.h" #include #include "../include/row_op.h" #include "../include/buffer.h" #include "../include/data.h" #include "../include/split_screen.h" #include "../include/terminal.h" #include "../include/utf8.h" extern struct editorConfig E; /** * @brief Sets a temporary status message for display * @details Formats and stores a message that will be displayed in the message * bar for 5 seconds. Uses printf-style variable argument formatting. * @param fmt Printf-style format string * @param ... Variable arguments for format string * @note Updates global editor state E (status_msg, status_msg_time) * @see editorDrawMessageBar() */ void editorSetStatusMessage(const char* fmt, ...) { va_list ap; va_start(ap, fmt); vsnprintf(E.status_msg, E.screencols, fmt, ap); va_end(ap); E.status_msg_time = time(NULL); } void bufferInsertBytes(char* src, int n) { appDebug("bufferInsertBytes \r\n"); EditorPane* active = splitScreenGetActivePane(); struct buffer_t* buf = bufferFindById(active->buffer_id); if (buf->y == buf->numrows) { bufferInsertRow(buf, buf->numrows, "", 0); } bufferRowInsertBytes(buf, &buf->row[buf->y], buf->x, src, n); buf->x += n; } void bufferDelBytes(void) { EditorPane* active = splitScreenGetActivePane(); struct buffer_t* buf = bufferFindById(active->buffer_id); /* Nothing to delete */ if (buf->numrows == 0) return; if (buf->x == 0 && buf->y == 0) return; /* Use row_offset, not col_offset, for row indexing */ row_t* r = &buf->row[buf->y]; if (buf->x > 0) { int byte_end = editorRowCxToByte(r, buf->x); int byte_start = editorRowCxToByte(r, buf->x - 1); int char_width = byte_end - byte_start; /* byte width of the character */ bufferRowDelByte(buf, r, byte_start, char_width); E.dirty = 1; } else { /* Merge current row into the previous one */ row_t* prev = &buf->row[buf->y - 1]; // FIX: was buf->y (same as r) int prev_char_count = editorRowCharCount(prev, prev->size); bufferRowInsertBytes(buf, prev, prev->size, r->chars, r->size); free(r->chars); r->chars = NULL; memmove(&buf->row[buf->y], &buf->row[buf->y + 1], sizeof(row_t) * (buf->numrows - buf->y - 1)); buf->numrows--; active->cursor_x = prev_char_count; buf->x = prev_char_count; active->cursor_y--; buf->y--; E.dirty = 1; } } void bufferInsertNewLine(void) { appDebug("Inserting new line\n"); EditorPane *active = splitScreenGetActivePane(); struct buffer_t *buf = bufferFindById(active->buffer_id); appDebug("buf x %d\n", buf->x); if (buf->y >= buf->numrows) { /* Cursor is past the last row: just append a blank line */ bufferInsertRow(buf, buf->numrows, "", 0); } else { row_t *row = &buf->row[buf->y]; /* Insert the tail (from cursor to end) as a new row below */ bufferInsertRow(buf, buf->y + 1, &row->chars[buf->x], row->size - buf->x); /* Re-fetch: realloc inside bufferInsertRow may have moved the array */ row = &buf->row[buf->y]; /* Truncate the current row at the cursor */ row->size = buf->x; row->chars[row->size] = '\0'; /* Do NOT touch row->cap — the allocation is still valid */ } buf->y++; buf->x = 0; appDebug("Insert new line done\n"); }