temp commit
This commit is contained in:
+282
-205
@@ -13,6 +13,7 @@
|
||||
#include "../include/row_op.h"
|
||||
#include "../include/split_screen.h"
|
||||
#include "../include/syntax_highlighter.h"
|
||||
#include "../include/terminal.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -23,127 +24,135 @@ extern struct editorConfig E;
|
||||
/**
|
||||
* @brief Renders a single pane with its buffer content
|
||||
*/
|
||||
static void editorDrawPane(struct abuf *ab, EditorPane *pane) {
|
||||
if (pane == NULL || pane->buffer_id < 0)
|
||||
return;
|
||||
|
||||
struct buffer_t *buf = bufferFindById(pane->buffer_id);
|
||||
if (buf == NULL)
|
||||
return;
|
||||
|
||||
// Draw content for this pane
|
||||
for (int y = 0; y < pane->height; y++) {
|
||||
int file_row = y + pane->row_offset;
|
||||
|
||||
// Position cursor at start of pane row
|
||||
static void editorDrawPane(struct abuf* ab, EditorPane* pane)
|
||||
{
|
||||
int file_row;
|
||||
char pos_buf[32];
|
||||
int pos_len = snprintf(pos_buf, sizeof(pos_buf), "\x1b[%d;%dH",
|
||||
pane->start_row + y + 1, pane->start_col + 1);
|
||||
abAppend(ab, pos_buf, pos_len);
|
||||
int pos_len;
|
||||
int chars_printed;
|
||||
int start_offset;
|
||||
int byte_len_to_print;
|
||||
int bytes_to_print;
|
||||
char* highlighted;
|
||||
char welcome[80];
|
||||
int welcome_len;
|
||||
int padding;
|
||||
|
||||
// Apply background color (6 bytes for RGB format)
|
||||
abAppend(ab, E.theme.BACKGROUND_COLOR, strlen(E.theme.BACKGROUND_COLOR));
|
||||
if (pane == NULL || pane->buffer_id < 0)
|
||||
return;
|
||||
|
||||
int chars_printed = 0;
|
||||
const struct buffer_t* buf = bufferFindById(pane->buffer_id);
|
||||
if (buf == NULL)
|
||||
return;
|
||||
|
||||
if (file_row >= buf->numrows) {
|
||||
// Empty line - show tilde
|
||||
if (buf->numrows == 0 && y == pane->height / 3) {
|
||||
char welcome[80];
|
||||
int welcome_len =
|
||||
snprintf(welcome, sizeof(welcome), "Buffer %d", pane->buffer_id);
|
||||
if (welcome_len > pane->width)
|
||||
welcome_len = pane->width;
|
||||
// Draw all pane
|
||||
for (int y = 0; y < pane->height; y++)
|
||||
{
|
||||
file_row = y + pane->y_offset;
|
||||
|
||||
int padding = (pane->width - welcome_len) / 2;
|
||||
if (padding) {
|
||||
abAppend(ab, "~", 1);
|
||||
chars_printed++;
|
||||
padding--;
|
||||
// Set cursor at start of pane row
|
||||
pos_len = snprintf(pos_buf, sizeof(pos_buf), "\x1b[%d;%dH",
|
||||
pane->origin_y + y + 1, pane->origin_x + 1);
|
||||
abAppend(ab, pos_buf, pos_len);
|
||||
|
||||
// Apply background color (6 bytes for RGB format)
|
||||
abAppend(ab, E.theme.BACKGROUND_COLOR, strlen(E.theme.BACKGROUND_COLOR));
|
||||
|
||||
chars_printed = 0;
|
||||
|
||||
// pane line is out of buffer
|
||||
if (file_row >= buf->numrows)
|
||||
{
|
||||
// Empty line - show tilde
|
||||
|
||||
abAppend(ab, "~", 1);
|
||||
for (int i = 0;
|
||||
i < pane->width - 1;
|
||||
++i)
|
||||
{
|
||||
abAppend(ab, " ", 1);
|
||||
}
|
||||
}
|
||||
while (padding-- && chars_printed < pane->width) {
|
||||
abAppend(ab, " ", 1);
|
||||
chars_printed++;
|
||||
else
|
||||
{
|
||||
start_offset = pane->x_offset;
|
||||
|
||||
if (buf->filename[strlen(buf->filename) - 1] == 'c')
|
||||
{
|
||||
// Render line with syntax highlighting, constrain to pane width
|
||||
highlighted = highlight_line(
|
||||
&buf->row[file_row].chars[pane->x_offset], &byte_len_to_print);
|
||||
|
||||
// Print only up to pane width
|
||||
abAppend(ab, highlighted, byte_len_to_print);
|
||||
free(highlighted);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Render basic line
|
||||
bytes_to_print =
|
||||
buf->row[file_row].size - pane->x_offset < pane->width
|
||||
? buf->row[file_row].size - pane->x_offset
|
||||
: pane->width;
|
||||
abAppend(ab, &buf->row[file_row].chars[pane->x_offset], bytes_to_print);
|
||||
}
|
||||
// Fill remaining space with background color to pane width
|
||||
for (int i = 0;
|
||||
i < pane->width - editorRowCharCount(&buf->row[file_row], pane->width) + pane->x_offset;
|
||||
++i)
|
||||
{
|
||||
abAppend(ab, " ", 1);
|
||||
}
|
||||
}
|
||||
abAppend(ab, welcome, welcome_len);
|
||||
chars_printed += welcome_len;
|
||||
} else {
|
||||
abAppend(ab, "~", 1);
|
||||
chars_printed++;
|
||||
}
|
||||
} else {
|
||||
// Render line with syntax highlighting, constrain to pane width
|
||||
int start_offset = pane->col_offset;
|
||||
int visible_len = buf->row[file_row].rsize - start_offset;
|
||||
if (visible_len < 0)
|
||||
visible_len = 0;
|
||||
if (visible_len > pane->width)
|
||||
visible_len = pane->width;
|
||||
|
||||
if (buf->filename[strlen(buf->filename) - 1] == 'c') {
|
||||
int byte_len_to_print;
|
||||
|
||||
char *highlighted = highlight_line(
|
||||
&buf->row[file_row].render[start_offset], &byte_len_to_print);
|
||||
|
||||
// Print only up to pane width
|
||||
|
||||
abAppend(ab, highlighted, byte_len_to_print);
|
||||
free(highlighted);
|
||||
} else {
|
||||
abAppend(ab, &buf->row[file_row].render[start_offset], buf->row[file_row].rsize);
|
||||
}
|
||||
|
||||
chars_printed = visible_len;
|
||||
}
|
||||
|
||||
// Fill remaining space with background color to pane width
|
||||
abAppend(ab, E.theme.BACKGROUND_COLOR, strlen(E.theme.BACKGROUND_COLOR));
|
||||
while (chars_printed < pane->width) {
|
||||
abAppend(ab, " ", 1);
|
||||
chars_printed++;
|
||||
}
|
||||
|
||||
// Restore background color at end of line
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Renders all panes based on current split configuration
|
||||
*/
|
||||
static void editorDrawAllPanes(struct abuf *ab) {
|
||||
ScreenLayout *layout = splitScreenGetLayout();
|
||||
static void editorDrawAllPanes(struct abuf* ab)
|
||||
{
|
||||
const ScreenLayout* layout = splitScreenGetLayout();
|
||||
|
||||
if (layout->num_panes == 1) {
|
||||
// Single pane fullscreen
|
||||
editorDrawPane(ab, &layout->panes[0]);
|
||||
} else if (layout->num_panes == 2) {
|
||||
// Draw both panes
|
||||
for (int i = 0; i < 2; i++) {
|
||||
editorDrawPane(ab, &layout->panes[i]);
|
||||
|
||||
// Draw pane border/divider if not the last pane
|
||||
if (layout->mode == SPLIT_VERTICAL && i == 0) {
|
||||
// Draw vertical divider
|
||||
int divider_col = layout->panes[0].width;
|
||||
for (int y = 0; y < layout->panes[0].height; y++) {
|
||||
char pos_buf[32];
|
||||
snprintf(pos_buf, sizeof(pos_buf), "\x1b[%d;%dH", y + 1, divider_col);
|
||||
abAppend(ab, pos_buf, strlen(pos_buf));
|
||||
abAppend(ab, "\x1b[1m|\x1b[0m", 9); // Bold pipe divider
|
||||
}
|
||||
} else if (layout->mode == SPLIT_HORIZONTAL && i == 0) {
|
||||
// Draw horizontal divider
|
||||
int divider_row = layout->panes[0].height;
|
||||
char pos_buf[32];
|
||||
snprintf(pos_buf, sizeof(pos_buf), "\x1b[%d;%dH", divider_row + 1, 1);
|
||||
abAppend(ab, pos_buf, strlen(pos_buf));
|
||||
for (int x = 0; x < E.screencols; x++) {
|
||||
abAppend(ab, "\x1b[1m-\x1b[0m", 9); // Bold dash divider
|
||||
}
|
||||
}
|
||||
if (layout->num_panes == 1)
|
||||
{
|
||||
// Single pane fullscreen
|
||||
editorDrawPane(ab, &layout->panes[0]);
|
||||
}
|
||||
else if (layout->num_panes == 2)
|
||||
{
|
||||
// Draw both panes
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
editorDrawPane(ab, &layout->panes[i]);
|
||||
|
||||
// Draw pane border/divider if not the last pane
|
||||
if (layout->mode == SPLIT_VERTICAL && i == 0)
|
||||
{
|
||||
// Draw vertical divider
|
||||
int divider_col = layout->panes[0].width;
|
||||
for (int y = 0; y < layout->panes[0].height; y++)
|
||||
{
|
||||
char pos_buf[32];
|
||||
snprintf(pos_buf, sizeof(pos_buf), "\x1b[%d;%dH", y + 1, divider_col);
|
||||
abAppend(ab, pos_buf, strlen(pos_buf));
|
||||
abAppend(ab, "\x1b[1m|\x1b[0m", 9); // Bold pipe divider
|
||||
}
|
||||
}
|
||||
else if (layout->mode == SPLIT_HORIZONTAL && i == 0)
|
||||
{
|
||||
// Draw horizontal divider
|
||||
int divider_row = layout->panes[0].height;
|
||||
char pos_buf[32];
|
||||
snprintf(pos_buf, sizeof(pos_buf), "\x1b[%d;%dH", divider_row + 1, 1);
|
||||
abAppend(ab, pos_buf, strlen(pos_buf));
|
||||
for (int x = 0; x < E.screencols; x++)
|
||||
{
|
||||
abAppend(ab, "\x1b[1m-\x1b[0m", 9); // Bold dash divider
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,35 +162,89 @@ static void editorDrawAllPanes(struct abuf *ab) {
|
||||
* @note Updates global editor state E
|
||||
* @see editorRowCxToRx()
|
||||
*/
|
||||
void editorScroll() {
|
||||
EditorPane *active = splitScreenGetActivePane();
|
||||
struct buffer_t *buf = bufferFindById(active->buffer_id);
|
||||
active->rx = active->cursor_x;
|
||||
void editorScroll()
|
||||
{
|
||||
EditorPane* active = splitScreenGetActivePane();
|
||||
struct buffer_t* buf = bufferFindById(active->buffer_id);
|
||||
int rel_x, rel_y;
|
||||
|
||||
fprintf(stderr, "%d %d / %d %d\n", active->cursor_x, active->col_offset,
|
||||
active->cursor_y, active->row_offset);
|
||||
// compute relative coordinates
|
||||
rel_x = editorRowCharCount(&buf->row[buf->y], buf->x);
|
||||
appDebug("counting %d\n", rel_x);
|
||||
rel_y = buf->y;
|
||||
|
||||
if (active->cursor_x < 0) {
|
||||
active->cursor_x = 0;
|
||||
active->col_offset = active->col_offset == 0 ? 0 : --active->col_offset;
|
||||
}
|
||||
appDebug("%d %d / %d %d\n", active->cursor_x, active->x_offset,
|
||||
active->cursor_y, active->y_offset);
|
||||
|
||||
if (active->cursor_y < 0) {
|
||||
active->cursor_y = 0;
|
||||
active->row_offset = active->row_offset == 0 ? 0 : --active->row_offset;
|
||||
}
|
||||
while (rel_x != active->cursor_x + active->x_offset ||
|
||||
rel_y != active->cursor_y + active->y_offset)
|
||||
{
|
||||
if (rel_x < active->cursor_x + active->x_offset)
|
||||
{
|
||||
// LEFT
|
||||
if (active->cursor_x == 0 && active->x_offset)
|
||||
{
|
||||
active->x_offset--;
|
||||
} else
|
||||
{
|
||||
active->cursor_x--;
|
||||
}
|
||||
} else
|
||||
{
|
||||
// RIGHT
|
||||
if (rel_x > active->cursor_x + active->x_offset)
|
||||
{
|
||||
if (active->cursor_x == active->width - 1)
|
||||
{
|
||||
active->x_offset++;
|
||||
} else
|
||||
{
|
||||
active->cursor_x++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (active->cursor_x == active->width) {
|
||||
if (rel_y < active->cursor_y + active->y_offset)
|
||||
{
|
||||
if (active->cursor_y == 0 && active->y_offset)
|
||||
{
|
||||
active->y_offset--;
|
||||
} else
|
||||
{
|
||||
active->cursor_y--;
|
||||
}
|
||||
}
|
||||
|
||||
active->cursor_x--;
|
||||
active->col_offset++;
|
||||
}
|
||||
if (rel_y > active->cursor_y + active->y_offset)
|
||||
{
|
||||
if (active->cursor_y == active->height - 1)
|
||||
{
|
||||
active->y_offset++;
|
||||
} else
|
||||
{
|
||||
active->cursor_y++;
|
||||
}
|
||||
}
|
||||
|
||||
if (active->cursor_y == active->height) {
|
||||
}
|
||||
}
|
||||
|
||||
active->cursor_y--;
|
||||
active->row_offset++;
|
||||
}
|
||||
char * basename(char *path)
|
||||
{
|
||||
int len = strlen(path);
|
||||
int flag=0;
|
||||
|
||||
|
||||
for(int i=len-1; i>0; i--)
|
||||
{
|
||||
if(path[i]=='/' )
|
||||
{
|
||||
flag=1;
|
||||
path = path+i+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,55 +255,63 @@ void editorScroll() {
|
||||
* @param ab Pointer to append buffer structure for accumulating output
|
||||
* @note Uses ANSI escape codes for color inversion
|
||||
*/
|
||||
void editorDrawStatusBar(struct abuf *ab) {
|
||||
int len, render_len;
|
||||
char status[80], render_status[80];
|
||||
EditorPane *active = splitScreenGetActivePane();
|
||||
struct buffer_t *buf = bufferFindById(active->buffer_id);
|
||||
void editorDrawStatusBar(struct abuf* ab)
|
||||
{
|
||||
// TO MODIFY
|
||||
int len, render_len;
|
||||
char status[E.screencols], render_status[E.screencols * 4];
|
||||
EditorPane* active = splitScreenGetActivePane();
|
||||
struct buffer_t* buf = bufferFindById(active->buffer_id);
|
||||
|
||||
abAppend(ab, "\x1b[7m", 4); // inverting colors
|
||||
abAppend(ab, "\x1b[7m", 4); // inverting colors
|
||||
|
||||
const char *mode_str = "";
|
||||
ScreenLayout *layout = splitScreenGetLayout();
|
||||
if (layout->mode == SPLIT_VERTICAL)
|
||||
mode_str = " [V-SPLIT]";
|
||||
else if (layout->mode == SPLIT_HORIZONTAL)
|
||||
mode_str = " [H-SPLIT]";
|
||||
const char* mode_str = "";
|
||||
ScreenLayout* layout = splitScreenGetLayout();
|
||||
if (layout->mode == SPLIT_VERTICAL)
|
||||
mode_str = " [V-SPLIT]";
|
||||
else if (layout->mode == SPLIT_HORIZONTAL)
|
||||
mode_str = " [H-SPLIT]";
|
||||
|
||||
// Build buffer status showing all buffers with dirty indicators
|
||||
char buf_status[200] = "";
|
||||
int offset = 0;
|
||||
for (int i = 0; i < E.number_of_buffer; i++) {
|
||||
struct buffer_t *b = &E.buffers[i];
|
||||
char marker = (b->buffer_id == active->buffer_id) ? '>' : ' ';
|
||||
char dirty_marker = b->dirty ? '*' : ' ';
|
||||
offset += snprintf(&buf_status[offset], sizeof(buf_status) - offset,
|
||||
"%c%d:%s%c ", marker, b->buffer_id,
|
||||
b->filename ? b->filename : "[No Name]", dirty_marker);
|
||||
}
|
||||
|
||||
len = snprintf(status, sizeof(status), "%s%s", buf_status, mode_str);
|
||||
|
||||
render_len = snprintf(render_status, sizeof(render_status), "%d/%d",
|
||||
active->cursor_y + 1, buf->numrows);
|
||||
|
||||
if (len > E.screencols) {
|
||||
len = E.screencols;
|
||||
}
|
||||
|
||||
abAppend(ab, status, len);
|
||||
while (len < E.screencols) {
|
||||
if (E.screencols - len == render_len) {
|
||||
abAppend(ab, render_status, render_len);
|
||||
break;
|
||||
} else {
|
||||
abAppend(ab, " ", 1);
|
||||
++len;
|
||||
// Build buffer status showing all buffers with dirty indicators
|
||||
char buf_status[1024] = "";
|
||||
int offset = 0;
|
||||
for (int i = 0; i < E.number_of_buffer; i++)
|
||||
{
|
||||
struct buffer_t* b = &E.buffers[i];
|
||||
char marker = (b->buffer_id == active->buffer_id) ? '>' : ' ';
|
||||
char dirty_marker = b->dirty ? '*' : ' ';
|
||||
offset += snprintf(&buf_status[offset], sizeof(buf_status) - offset,
|
||||
"%c%d:%s%c ", marker, b->buffer_id,
|
||||
b->filename ? basename(b->filename) : "[No Name]", dirty_marker);
|
||||
}
|
||||
}
|
||||
|
||||
abAppend(ab, "\x1b[m", 3); // normal text mode
|
||||
abAppend(ab, "\r\n", 2);
|
||||
len = snprintf(status, sizeof(status), "%s%s", buf_status, mode_str);
|
||||
|
||||
render_len = snprintf(render_status, sizeof(render_status), "%d/%d",
|
||||
active->cursor_y + 1, buf->numrows);
|
||||
|
||||
if (len > E.screencols)
|
||||
{
|
||||
len = E.screencols;
|
||||
}
|
||||
|
||||
abAppend(ab, status, len);
|
||||
while (len < E.screencols)
|
||||
{
|
||||
if (E.screencols - len == render_len + 1)
|
||||
{
|
||||
abAppend(ab, render_status, render_len);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
abAppend(ab, " ", 1);
|
||||
++len;
|
||||
}
|
||||
}
|
||||
|
||||
abAppend(ab, "\x1b[m", 3); // normal text mode
|
||||
abAppend(ab, "\r\n", 2);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -250,15 +321,18 @@ void editorDrawStatusBar(struct abuf *ab) {
|
||||
* @param ab Pointer to append buffer structure for accumulating output
|
||||
* @note Messages are set by editorSetStatusMessage()
|
||||
*/
|
||||
void editorDrawMessageBar(struct abuf *ab) {
|
||||
int msg_len = strlen(E.status_msg);
|
||||
abAppend(ab, ERASE_END_LINE, 3);
|
||||
if (msg_len > E.screencols) {
|
||||
msg_len = E.screencols;
|
||||
}
|
||||
if (msg_len && time(NULL) - E.status_msg_time < 5) {
|
||||
abAppend(ab, E.status_msg, msg_len);
|
||||
}
|
||||
void editorDrawMessageBar(struct abuf* ab)
|
||||
{
|
||||
int msg_len = strlen(E.status_msg);
|
||||
abAppend(ab, ERASE_END_LINE, 3);
|
||||
if (msg_len > E.screencols)
|
||||
{
|
||||
msg_len = E.screencols;
|
||||
}
|
||||
if (msg_len && time(NULL) - E.status_msg_time < 5)
|
||||
{
|
||||
abAppend(ab, E.status_msg, msg_len);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -272,33 +346,36 @@ void editorDrawMessageBar(struct abuf *ab) {
|
||||
* @see editorDrawMessageBar()
|
||||
*/
|
||||
|
||||
void editorRefreshScreen() {
|
||||
struct abuf ab = ABUF_INIT;
|
||||
char buf[32];
|
||||
void editorRefreshScreen()
|
||||
{
|
||||
struct abuf ab = ABUF_INIT;
|
||||
char buf[32];
|
||||
|
||||
abAppend(&ab, HIDE_CURSOR, 6);
|
||||
abAppend(&ab, CURSOR_TOP_LEFT, 3);
|
||||
abAppend(&ab, E.theme.BACKGROUND_COLOR,
|
||||
strlen(E.theme.BACKGROUND_COLOR)); // RGB background is 12 bytes
|
||||
abAppend(&ab, HIDE_CURSOR, 6);
|
||||
abAppend(&ab, CURSOR_TOP_LEFT, 3);
|
||||
abAppend(&ab, E.theme.BACKGROUND_COLOR,
|
||||
strlen(E.theme.BACKGROUND_COLOR)); // RGB background is 12 bytes
|
||||
|
||||
// Draw all panes
|
||||
editorScroll();
|
||||
editorDrawAllPanes(&ab);
|
||||
// Draw all panes
|
||||
editorScroll();
|
||||
editorDrawAllPanes(&ab);
|
||||
|
||||
// Draw status bar and message bar
|
||||
editorDrawStatusBar(&ab);
|
||||
editorDrawMessageBar(&ab);
|
||||
// Draw status bar and message bar
|
||||
editorDrawStatusBar(&ab);
|
||||
editorDrawMessageBar(&ab);
|
||||
|
||||
// Position cursor in active pane
|
||||
EditorPane *active = splitScreenGetActivePane();
|
||||
if (active != NULL) {
|
||||
snprintf(buf, sizeof(buf), "\x1b[%d;%dH",
|
||||
active->cursor_y + active->start_row + 1,
|
||||
active->cursor_x + active->start_col + 1);
|
||||
abAppend(&ab, buf, strlen(buf));
|
||||
}
|
||||
// Position cursor in active pane
|
||||
EditorPane* active = splitScreenGetActivePane();
|
||||
struct buffer_t* buffer = bufferGetCurrent();
|
||||
if (active != NULL)
|
||||
{
|
||||
snprintf(buf, sizeof(buf), "\x1b[%d;%dH",
|
||||
active->cursor_y + active->origin_y + 1,
|
||||
active->cursor_x + active->origin_x + 1);
|
||||
abAppend(&ab, buf, strlen(buf));
|
||||
}
|
||||
|
||||
abAppend(&ab, SHOW_CURSOR, 6);
|
||||
write(STDOUT_FILENO, ab.b, ab.len);
|
||||
abFree(&ab);
|
||||
abAppend(&ab, SHOW_CURSOR, 6);
|
||||
write(STDOUT_FILENO, ab.b, ab.len);
|
||||
abFree(&ab);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user