121 lines
3.5 KiB
C
121 lines
3.5 KiB
C
#include "../include/editor_op.h"
|
|
|
|
#include <stdarg.h>
|
|
|
|
#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");
|
|
}
|