overflow errors
This commit is contained in:
@@ -7,6 +7,6 @@
|
|||||||
|
|
||||||
void abAppend(struct abuf *ab, const char *s, int len);
|
void abAppend(struct abuf *ab, const char *s, int len);
|
||||||
|
|
||||||
void abFree(const struct abuf *ab);
|
void abFree(struct abuf *ab);
|
||||||
|
|
||||||
#endif // APPEND_BUFFER_H_
|
#endif // APPEND_BUFFER_H_
|
||||||
|
|||||||
@@ -13,6 +13,10 @@
|
|||||||
#define TAB "\t"
|
#define TAB "\t"
|
||||||
#define SPACE "\x20"
|
#define SPACE "\x20"
|
||||||
|
|
||||||
|
#ifndef PATH_MAX
|
||||||
|
#define PATH_MAX 1024
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Uncomment to see debug logs on stderr */
|
/* Uncomment to see debug logs on stderr */
|
||||||
#define APP_DEBUG
|
#define APP_DEBUG
|
||||||
|
|
||||||
|
|||||||
@@ -28,42 +28,39 @@
|
|||||||
struct editorConfig E;
|
struct editorConfig E;
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
// Get HOME with NULL check
|
||||||
|
const char *home = getenv("HOME");
|
||||||
|
if (!home) {
|
||||||
|
fprintf(stderr, "Error: HOME environment variable not set\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
char * splash_screen = strdup(getenv("HOME"));
|
// Allocate and build splash screen path safely
|
||||||
int home_path_len = (int) strlen(splash_screen);
|
char *splash_screen;
|
||||||
char * splash_screen_relative_path = strdup("/.beluga/assets/beluga.txt");
|
if (asprintf(&splash_screen, "%s/.beluga/assets/beluga.txt", home) == -1) {
|
||||||
int splash_screen_relative_path_len = (int) strlen(splash_screen_relative_path);
|
fprintf(stderr, "Error: Failed to allocate splash screen path\n");
|
||||||
|
return 1;
|
||||||
signal(SIGPIPE, SIG_IGN); // don't die on broken pipe, just get EPIPE from write()
|
}
|
||||||
|
|
||||||
|
signal(SIGPIPE, SIG_IGN);
|
||||||
enableRawMode();
|
enableRawMode();
|
||||||
initEditor();
|
initEditor();
|
||||||
|
|
||||||
EditorPane *active = splitScreenGetActivePane();
|
EditorPane *active = splitScreenGetActivePane();
|
||||||
struct buffer_t *buf;
|
struct buffer_t *buf;
|
||||||
|
|
||||||
splash_screen = realloc(splash_screen, sizeof(char) * (home_path_len + splash_screen_relative_path_len + 1));
|
|
||||||
strcat(splash_screen, "/.beluga/assets/beluga.txt");
|
|
||||||
free(splash_screen_relative_path);
|
|
||||||
|
|
||||||
appDebug("splash : %s\n", splash_screen);
|
appDebug("splash : %s\n", splash_screen);
|
||||||
active->buffer_id = bufferCreate(splash_screen, READ_ONLY);
|
active->buffer_id = bufferCreate(splash_screen, READ_ONLY);
|
||||||
|
|
||||||
if (argc >= 2) {
|
if (argc >= 2) {
|
||||||
if (E.constantes.LSP) {
|
|
||||||
|
|
||||||
}
|
|
||||||
active->buffer_id = bufferCreate(argv[1], READ_AND_WRITE);
|
active->buffer_id = bufferCreate(argv[1], READ_AND_WRITE);
|
||||||
|
|
||||||
buf = &E.buffers[active->buffer_id];
|
buf = &E.buffers[active->buffer_id];
|
||||||
|
appDebug("project root : %s\n", dirname(buf->fullname));
|
||||||
appDebug("peoject root : %s\n", dirname(buf->fullname));
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
free(splash_screen);
|
|
||||||
|
free(splash_screen); // Now guaranteed safe
|
||||||
|
|
||||||
editorSetStatusMessage("HELP: Ctrl-x Ctrl-s = save | Ctrl-x Ctrl-c = quit");
|
editorSetStatusMessage("HELP: Ctrl-x Ctrl-s = save | Ctrl-x Ctrl-c = quit");
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
editorRefreshScreen();
|
editorRefreshScreen();
|
||||||
editorProcessKeypress();
|
editorProcessKeypress();
|
||||||
|
|||||||
+5
-1
@@ -11,4 +11,8 @@ void abAppend(struct abuf *ab, const char *s, int len) {
|
|||||||
ab->len += len;
|
ab->len += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
void abFree(const struct abuf *ab) { free(ab->b); }
|
void abFree(struct abuf *ab) {
|
||||||
|
free(ab->b);
|
||||||
|
ab->b = NULL;
|
||||||
|
ab->len = 0;
|
||||||
|
}
|
||||||
|
|||||||
+45
-13
@@ -81,7 +81,16 @@ int bufferCreate(const char* path, enum bufferStatus_e state)
|
|||||||
struct buffer_t* new_buf = &E.buffers[E.number_of_buffer];
|
struct buffer_t* new_buf = &E.buffers[E.number_of_buffer];
|
||||||
new_buf->buffer_id = E.number_of_buffer;
|
new_buf->buffer_id = E.number_of_buffer;
|
||||||
new_buf->filename = strdup(filename);
|
new_buf->filename = strdup(filename);
|
||||||
|
if (!new_buf->filename)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
new_buf->fullname = malloc(1024 * sizeof(char));
|
new_buf->fullname = malloc(1024 * sizeof(char));
|
||||||
|
if (!new_buf->fullname)
|
||||||
|
{
|
||||||
|
free(new_buf->filename);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
realpath(path, new_buf->fullname);
|
realpath(path, new_buf->fullname);
|
||||||
new_buf->path = dirname(new_buf->fullname);
|
new_buf->path = dirname(new_buf->fullname);
|
||||||
new_buf->type = FILE_BUFF;
|
new_buf->type = FILE_BUFF;
|
||||||
@@ -98,8 +107,7 @@ int bufferCreate(const char* path, enum bufferStatus_e state)
|
|||||||
{
|
{
|
||||||
if (E.lsp_client->state == LSP_SHUTDOWN)
|
if (E.lsp_client->state == LSP_SHUTDOWN)
|
||||||
lspStart(E.lsp_client, dirname(new_buf->path));
|
lspStart(E.lsp_client, dirname(new_buf->path));
|
||||||
while (E.lsp_client->state != LSP_READY)
|
while (E.lsp_client->state != LSP_READY);
|
||||||
;
|
|
||||||
lspDidOpen(E.lsp_client, new_buf);
|
lspDidOpen(E.lsp_client, new_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,7 +345,8 @@ void bufferFindReverse(struct buffer_t* buf)
|
|||||||
free(query);
|
free(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bufferInsertRow(struct buffer_t *buffer, int at, char *s, size_t len) {
|
void bufferInsertRow(struct buffer_t* buffer, int at, char* s, size_t len)
|
||||||
|
{
|
||||||
if (at < 0 || at > buffer->numrows)
|
if (at < 0 || at > buffer->numrows)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -347,7 +356,8 @@ void bufferInsertRow(struct buffer_t *buffer, int at, char *s, size_t len) {
|
|||||||
buffer->row = tmp;
|
buffer->row = tmp;
|
||||||
|
|
||||||
/* Shift existing rows to make room at 'at' — no at++ */
|
/* Shift existing rows to make room at 'at' — no at++ */
|
||||||
if (at < buffer->numrows) {
|
if (at < buffer->numrows)
|
||||||
|
{
|
||||||
memmove(&buffer->row[at + 1], &buffer->row[at],
|
memmove(&buffer->row[at + 1], &buffer->row[at],
|
||||||
sizeof(row_t) * (buffer->numrows - at)); /* not -at+1 */
|
sizeof(row_t) * (buffer->numrows - at)); /* not -at+1 */
|
||||||
}
|
}
|
||||||
@@ -371,17 +381,34 @@ void bufferFreeRow(row_t *row) { free(row->chars); }
|
|||||||
* \param at Index of where we want to insert the char */
|
* \param at Index of where we want to insert the char */
|
||||||
|
|
||||||
void bufferRowInsertBytes(struct buffer_t* buffer, row_t* row, int at,
|
void bufferRowInsertBytes(struct buffer_t* buffer, row_t* row, int at,
|
||||||
const char *src, int n) {
|
const char* src, int n)
|
||||||
|
{
|
||||||
if (buffer->state == READ_ONLY)
|
if (buffer->state == READ_ONLY)
|
||||||
return;
|
return;
|
||||||
if (row->size + n + 1 > row->cap) {
|
if (at < 0 || at > row->size)
|
||||||
row->cap = (row->size + n + 1) * 2;
|
{
|
||||||
row->chars = realloc(row->chars, row->cap);
|
return;
|
||||||
|
}
|
||||||
|
if (row->size + n + 1 > row->cap)
|
||||||
|
{
|
||||||
|
size_t new_cap = row->cap == 0 ? 128 : row->cap * 2;
|
||||||
|
while (new_cap < row->size + n + 1) {
|
||||||
|
new_cap *= 2;
|
||||||
|
}
|
||||||
|
char *new_chars = realloc(row->chars, new_cap);
|
||||||
|
if (!new_chars) {
|
||||||
|
return; // Allocation failed
|
||||||
|
}
|
||||||
|
row->chars = new_chars;
|
||||||
|
row->cap = (int) new_cap;
|
||||||
}
|
}
|
||||||
memmove(row->chars + at + n, row->chars + at, row->size - at);
|
memmove(row->chars + at + n, row->chars + at, row->size - at);
|
||||||
|
|
||||||
|
// Copy new bytes
|
||||||
memcpy(row->chars + at, src, n);
|
memcpy(row->chars + at, src, n);
|
||||||
row->size += n;
|
row->size += n;
|
||||||
row->chars = realloc(row->chars, row->size + 2);
|
|
||||||
|
row->chars[row->size] = '\0';
|
||||||
++buffer->dirty;
|
++buffer->dirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,7 +417,8 @@ void bufferRowInsertBytes(struct buffer_t *buffer, row_t *row, int at,
|
|||||||
* \brief Delete the a char at the chosen position on the given row
|
* \brief Delete the a char at the chosen position on the given row
|
||||||
* \param at Index of the char to delete
|
* \param at Index of the char to delete
|
||||||
* \param row Row on operation is made */
|
* \param row Row on operation is made */
|
||||||
void bufferRowDelByte(struct buffer_t *buffer, row_t *row, int at, int n) {
|
void bufferRowDelByte(struct buffer_t* buffer, row_t* row, int at, int n)
|
||||||
|
{
|
||||||
if (buffer->state == READ_ONLY)
|
if (buffer->state == READ_ONLY)
|
||||||
return;
|
return;
|
||||||
if (at < 0 || at >= row->size)
|
if (at < 0 || at >= row->size)
|
||||||
@@ -461,17 +489,21 @@ void bufferDelBytes(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void bufferInsertNewLine(void) {
|
void bufferInsertNewLine(void)
|
||||||
|
{
|
||||||
appDebug("Inserting new line\n");
|
appDebug("Inserting new line\n");
|
||||||
EditorPane* active = splitScreenGetActivePane();
|
EditorPane* active = splitScreenGetActivePane();
|
||||||
struct buffer_t* buf = bufferFindById(active->buffer_id);
|
struct buffer_t* buf = bufferFindById(active->buffer_id);
|
||||||
|
|
||||||
appDebug("buf x %d\n", buf->x);
|
appDebug("buf x %d\n", buf->x);
|
||||||
|
|
||||||
if (buf->y >= buf->numrows) {
|
if (buf->y >= buf->numrows)
|
||||||
|
{
|
||||||
/* Cursor is past the last row: just append a blank line */
|
/* Cursor is past the last row: just append a blank line */
|
||||||
bufferInsertRow(buf, buf->numrows, "", 0);
|
bufferInsertRow(buf, buf->numrows, "", 0);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
row_t* row = &buf->row[buf->y];
|
row_t* row = &buf->row[buf->y];
|
||||||
|
|
||||||
/* Insert the tail (from cursor to end) as a new row below */
|
/* Insert the tail (from cursor to end) as a new row below */
|
||||||
|
|||||||
+30
-20
@@ -137,24 +137,27 @@ void bFree_structs(void)
|
|||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
free(E.prefix);
|
free(E.prefix);
|
||||||
for (i = 0; i < E.number_of_keybinds; ++i)
|
for (i = 0; i < E.number_of_keybinds; ++i) {
|
||||||
{
|
|
||||||
free(E.key_binds[i].key_sequence);
|
free(E.key_binds[i].key_sequence);
|
||||||
|
E.key_binds[i].key_sequence = NULL;
|
||||||
}
|
}
|
||||||
free(E.key_binds);
|
free(E.key_binds);
|
||||||
// bFree layout
|
E.key_binds = NULL;
|
||||||
free(E.layout.panes);
|
E.number_of_keybinds = 0;
|
||||||
|
|
||||||
// bFree buffers
|
// Similar fix for buffers
|
||||||
for (i = 0; i < E.number_of_buffer; ++i)
|
for (i = 0; i < E.number_of_buffer; ++i) {
|
||||||
{
|
|
||||||
free(E.buffers[i].filename);
|
free(E.buffers[i].filename);
|
||||||
for (j = 0; j < E.buffers[i].numrows; ++j)
|
E.buffers[i].filename = NULL;
|
||||||
{
|
for (j = 0; j < E.buffers[i].numrows; ++j) {
|
||||||
free(E.buffers[i].row[j].chars);
|
free(E.buffers[i].row[j].chars);
|
||||||
|
E.buffers[i].row[j].chars = NULL;
|
||||||
}
|
}
|
||||||
free(E.buffers[i].row);
|
free(E.buffers[i].row);
|
||||||
|
E.buffers[i].row = NULL;
|
||||||
}
|
}
|
||||||
|
// bFree layout
|
||||||
|
free(E.layout.panes);
|
||||||
|
|
||||||
free(E.init_file_path);
|
free(E.init_file_path);
|
||||||
fclose(E.fd_init_file);
|
fclose(E.fd_init_file);
|
||||||
@@ -187,7 +190,7 @@ Lisp editorQuit(Lisp args, LispError* e, LispContext ctx)
|
|||||||
write(STDOUT_FILENO, CURSOR_TOP_LEFT, 3);
|
write(STDOUT_FILENO, CURSOR_TOP_LEFT, 3);
|
||||||
lspShutdown(E.lsp_client);
|
lspShutdown(E.lsp_client);
|
||||||
lisp_shutdown(E.ctx);
|
lisp_shutdown(E.ctx);
|
||||||
deInitEditor();
|
// deInitEditor();
|
||||||
disableRawMode();
|
disableRawMode();
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
@@ -414,16 +417,23 @@ Lisp addPackage(Lisp args, LispError* e, LispContext ctx)
|
|||||||
{
|
{
|
||||||
const char* package_name = lisp_string(lisp_car(args));
|
const char* package_name = lisp_string(lisp_car(args));
|
||||||
appDebug("%s\n", package_name);
|
appDebug("%s\n", package_name);
|
||||||
char* package_dir = calloc(256, sizeof(char));
|
const char *home = getenv("HOME");
|
||||||
FILE* fd_package = NULL;
|
if (!home) {
|
||||||
strcat(package_dir, getenv("HOME"));
|
return lisp_null();
|
||||||
strcat(package_dir, "/.beluga/packages/");
|
}
|
||||||
strcat(package_dir, package_name);
|
|
||||||
strcat(package_dir, "/init.lisp");
|
char *package_dir;
|
||||||
appDebug("%s\n", package_dir);
|
if (asprintf(&package_dir, "%s/.beluga/packages/%s/init.lisp", home, package_name) == -1) {
|
||||||
fd_package = fopen(package_dir, "r");
|
return lisp_null();
|
||||||
lisp_eval(lisp_read_file(fd_package, &E.ctx_error, E.ctx), &E.ctx_error,
|
}
|
||||||
E.ctx);
|
|
||||||
|
FILE* fd_package = fopen(package_dir, "r");
|
||||||
|
if (!fd_package) {
|
||||||
|
free(package_dir);
|
||||||
|
return lisp_null();
|
||||||
|
}
|
||||||
|
|
||||||
|
lisp_eval(lisp_read_file(fd_package, &E.ctx_error, E.ctx), &E.ctx_error, E.ctx);
|
||||||
fclose(fd_package);
|
fclose(fd_package);
|
||||||
free(package_dir);
|
free(package_dir);
|
||||||
|
|
||||||
|
|||||||
+14
-4
@@ -49,13 +49,13 @@ int editorMoveCursor(int key) {
|
|||||||
if (row && buf->x < row->size) {
|
if (row && buf->x < row->size) {
|
||||||
int len = utf8Seqlen(row->chars[buf->x]);
|
int len = utf8Seqlen(row->chars[buf->x]);
|
||||||
buf->x += len;
|
buf->x += len;
|
||||||
} else if (row && buf->y < buf->numrows) {
|
} else if (row && buf->y < buf->numrows - 1) {
|
||||||
buf->y++;
|
buf->y++;
|
||||||
buf->x = 0;
|
buf->x = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ARROW_DOWN:
|
case ARROW_DOWN:
|
||||||
if (buf->y < buf->numrows) {
|
if (buf->y < buf->numrows - 1) {
|
||||||
|
|
||||||
buf->y++;
|
buf->y++;
|
||||||
}
|
}
|
||||||
@@ -86,18 +86,28 @@ char *editorGetClipboard(void) {
|
|||||||
size_t cap = 4096;
|
size_t cap = 4096;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
char *buf = malloc(cap);
|
char *buf = malloc(cap);
|
||||||
|
if (!buf) {
|
||||||
|
pclose(pipe);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int c;
|
int c;
|
||||||
while ((c = fgetc(pipe)) != EOF) {
|
while ((c = fgetc(pipe)) != EOF) {
|
||||||
if (len + 1 >= cap) {
|
if (len + 1 >= cap) {
|
||||||
cap *= 2;
|
cap *= 2;
|
||||||
buf = realloc(buf, cap);
|
char *new_buf = realloc(buf, cap);
|
||||||
|
if (!new_buf) {
|
||||||
|
free(buf);
|
||||||
|
pclose(pipe);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
buf = new_buf;
|
||||||
}
|
}
|
||||||
buf[len++] = (char)c;
|
buf[len++] = (char)c;
|
||||||
}
|
}
|
||||||
buf[len] = '\0';
|
buf[len] = '\0';
|
||||||
pclose(pipe);
|
pclose(pipe);
|
||||||
return buf; // caller must free
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void editorSetClipboard(const char *text, int len) {
|
void editorSetClipboard(const char *text, int len) {
|
||||||
|
|||||||
+4
-12
@@ -60,19 +60,12 @@ void editorCloseFile(void) {
|
|||||||
*/
|
*/
|
||||||
void editorOpen(struct buffer_t* buffer) {
|
void editorOpen(struct buffer_t* buffer) {
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char full_name[1024];
|
fp = fopen(buffer->fullname, "a+");
|
||||||
strcpy(full_name, buffer->path);
|
|
||||||
strcat(full_name, "/");
|
|
||||||
strcat(full_name, buffer->filename);
|
|
||||||
strcat(full_name, "\0");
|
|
||||||
appDebug("full name : %s", full_name);
|
|
||||||
|
|
||||||
fp = fopen(full_name, "a+");
|
|
||||||
if (!fp)
|
if (!fp)
|
||||||
die("fopen");
|
die("fopen");
|
||||||
|
|
||||||
char *line = NULL;
|
char *line = NULL;
|
||||||
size_t line_cap;
|
size_t line_cap = 0;
|
||||||
ssize_t line_len;
|
ssize_t line_len;
|
||||||
|
|
||||||
rewind(fp);
|
rewind(fp);
|
||||||
@@ -82,12 +75,11 @@ void editorOpen(struct buffer_t* buffer) {
|
|||||||
(line[line_len - 1] == '\n' || line[line_len - 1] == '\r')) {
|
(line[line_len - 1] == '\n' || line[line_len - 1] == '\r')) {
|
||||||
--line_len;
|
--line_len;
|
||||||
}
|
}
|
||||||
appDebug("line %s\n", line);
|
|
||||||
bufferInsertRow(buffer, buffer->numrows, line, line_len);
|
bufferInsertRow(buffer, buffer->numrows, line, line_len);
|
||||||
free(line);
|
free(line);
|
||||||
line = NULL;
|
line = NULL;
|
||||||
|
line_cap = 0; // Reset for next iteration
|
||||||
}
|
}
|
||||||
free(line);
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
E.dirty = 0;
|
E.dirty = 0;
|
||||||
}
|
}
|
||||||
@@ -114,7 +106,7 @@ void editorSave() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fd = open(buffer->fullname, O_RDWR | O_CREAT, 0644);
|
fd = open(buffer->fullname, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||||
if (fd != -1) {
|
if (fd != -1) {
|
||||||
for (int i = 0; i < buffer->numrows; ++i)
|
for (int i = 0; i < buffer->numrows; ++i)
|
||||||
{
|
{
|
||||||
|
|||||||
+28
-8
@@ -57,7 +57,7 @@ void initBuiltins() {
|
|||||||
void initConfig() {
|
void initConfig() {
|
||||||
|
|
||||||
E.ctx = lisp_init();
|
E.ctx = lisp_init();
|
||||||
E.ctx.p->err_port = fopen("log.err", "w");
|
E.ctx.p->err_port = fopen("lisp_log.err", "w");
|
||||||
E.env = lisp_env(E.ctx);
|
E.env = lisp_env(E.ctx);
|
||||||
lisp_lib_load(E.ctx);
|
lisp_lib_load(E.ctx);
|
||||||
// Init builtins lisp functions
|
// Init builtins lisp functions
|
||||||
@@ -117,14 +117,26 @@ void initEditor() {
|
|||||||
active->width = E.screencols;
|
active->width = E.screencols;
|
||||||
active->height = E.screenrows;
|
active->height = E.screenrows;
|
||||||
|
|
||||||
E.init_file_path = (char *)calloc(256, sizeof(char));
|
const char *home = getenv("HOME");
|
||||||
strcat(E.init_file_path, getenv("HOME"));
|
if (!home) {
|
||||||
strcat(E.init_file_path, "/.beluga/config/init.lisp");
|
die("HOME environment variable not set");
|
||||||
appDebug("%s\n", E.init_file_path);
|
}
|
||||||
E.fd_init_file = fopen(E.init_file_path, "r");
|
|
||||||
|
|
||||||
// Status bar
|
if (asprintf(&E.init_file_path, "%s/.beluga/config/init.lisp", home) == -1) {
|
||||||
E.status_msg = (char *)calloc(E.screencols, sizeof(char));
|
die("asprintf failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
E.fd_init_file = fopen(E.init_file_path, "r");
|
||||||
|
if (!E.fd_init_file) {
|
||||||
|
// File might not exist, that's okay for some cases
|
||||||
|
// Handle accordingly
|
||||||
|
}
|
||||||
|
|
||||||
|
E.status_msg = calloc(E.screencols, sizeof(char));
|
||||||
|
if (!E.status_msg) {
|
||||||
|
die("malloc failed");
|
||||||
|
}
|
||||||
|
E.status_msg[0] = '\0';
|
||||||
E.status_msg[0] = '\0';
|
E.status_msg[0] = '\0';
|
||||||
E.status_msg_time = 0;
|
E.status_msg_time = 0;
|
||||||
|
|
||||||
@@ -168,5 +180,13 @@ void deInitEditor()
|
|||||||
{
|
{
|
||||||
free(E.key_binds[i].key_sequence);
|
free(E.key_binds[i].key_sequence);
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i < E.number_of_buffer; ++i)
|
||||||
|
{
|
||||||
|
free(E.buffers[i].filename);
|
||||||
|
free(E.buffers[i].path);
|
||||||
|
free(E.buffers[i].fullname);
|
||||||
|
free(E.buffers[i].row->chars);
|
||||||
|
free(E.buffers[i].row);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-3
@@ -158,10 +158,13 @@ char *editorPrompt(char *prompt, char *placeHolder, char bPathMode) {
|
|||||||
} else if (!iscntrl(c) && c < 256) {
|
} else if (!iscntrl(c) && c < 256) {
|
||||||
if (buf_len == buf_size - 1) {
|
if (buf_len == buf_size - 1) {
|
||||||
buf_size *= 2;
|
buf_size *= 2;
|
||||||
buf = realloc(buf, buf_size);
|
char *new_buf = realloc(buf, buf_size);
|
||||||
|
if (!new_buf) {
|
||||||
|
free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
buf = new_buf;
|
||||||
}
|
}
|
||||||
buf[buf_len++] = (char)c;
|
|
||||||
buf[buf_len] = '\0';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-3
@@ -20,7 +20,12 @@ void splitScreenInit(void) {
|
|||||||
E.layout.num_panes = 1;
|
E.layout.num_panes = 1;
|
||||||
E.layout.active_pane = 0;
|
E.layout.active_pane = 0;
|
||||||
|
|
||||||
E.layout.panes = malloc(sizeof(EditorPane) * 2);
|
EditorPane *new_panes = realloc(E.layout.panes, sizeof(EditorPane) * 2);
|
||||||
|
if (!new_panes) {
|
||||||
|
editorSetStatusMessage("Error: realloc failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
E.layout.panes = new_panes;
|
||||||
|
|
||||||
// Initialize single fullscreen pane
|
// Initialize single fullscreen pane
|
||||||
E.layout.panes[0].buffer_id = -1; // No buffer for now
|
E.layout.panes[0].buffer_id = -1; // No buffer for now
|
||||||
@@ -218,9 +223,11 @@ EditorPane *splitScreenGetActivePane(void) {
|
|||||||
return &E.layout.panes[E.layout.active_pane];
|
return &E.layout.panes[E.layout.active_pane];
|
||||||
}
|
}
|
||||||
|
|
||||||
void freeScreenLayout(ScreenLayout *layout)
|
void freeScreenLayout(ScreenLayout *layout) {
|
||||||
{
|
if (layout) {
|
||||||
free(layout->panes);
|
free(layout->panes);
|
||||||
|
layout->panes = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void freePane(EditorPane *pane)
|
void freePane(EditorPane *pane)
|
||||||
|
|||||||
+20
-16
@@ -110,9 +110,13 @@ int comment_section = 0;
|
|||||||
char *highlight_line(const char *line, int *length) {
|
char *highlight_line(const char *line, int *length) {
|
||||||
// Each byte can expand to at most (color_prefix + 4 bytes + color_reset).
|
// Each byte can expand to at most (color_prefix + 4 bytes + color_reset).
|
||||||
// Allocate generously based on line length to avoid overflow.
|
// Allocate generously based on line length to avoid overflow.
|
||||||
int line_len = strlen(line);
|
int line_len = (int) strlen(line);
|
||||||
int buf_size = line_len * 32 + 256;
|
int buf_size = line_len * 32 + 256;
|
||||||
char *result = malloc(buf_size);
|
char *result = malloc(buf_size);
|
||||||
|
if (!result) {
|
||||||
|
*length = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
int result_pos = 0;
|
int result_pos = 0;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
@@ -125,31 +129,31 @@ char *highlight_line(const char *line, int *length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (comment_section) {
|
if (comment_section) {
|
||||||
result_pos += sprintf(&result[result_pos], "%s", E.theme.COLOR_COMMENT);
|
result_pos += snprintf(&result[result_pos], 10, "%s", E.theme.COLOR_COMMENT);
|
||||||
while (line[i] != '\0' && line[i] != '\n') {
|
while (line[i] != '\0' && line[i] != '\n') {
|
||||||
if (line[i] == '*' && line[i + 1] == '/') {
|
if (line[i] == '*' && line[i + 1] == '/') {
|
||||||
comment_section = 0;
|
comment_section = 0;
|
||||||
}
|
}
|
||||||
copy_utf8_char(result, &result_pos, line, &i);
|
copy_utf8_char(result, &result_pos, line, &i);
|
||||||
}
|
}
|
||||||
result_pos += sprintf(&result[result_pos], "%s", COLOR_RESET);
|
result_pos += snprintf(&result[result_pos], 10, "%s", COLOR_RESET);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle line comments
|
// Handle line comments
|
||||||
if (line[i] == '/' && line[i + 1] == '/') {
|
if (line[i] == '/' && line[i + 1] == '/') {
|
||||||
result_pos += sprintf(&result[result_pos], "%s", E.theme.COLOR_COMMENT);
|
result_pos += snprintf(&result[result_pos], 10, "%s", E.theme.COLOR_COMMENT);
|
||||||
while (line[i] != '\0' && line[i] != '\n') {
|
while (line[i] != '\0' && line[i] != '\n') {
|
||||||
copy_utf8_char(result, &result_pos, line, &i);
|
copy_utf8_char(result, &result_pos, line, &i);
|
||||||
}
|
}
|
||||||
result_pos += sprintf(&result[result_pos], "%s", COLOR_RESET);
|
result_pos += snprintf(&result[result_pos], 10, "%s", COLOR_RESET);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle block comments
|
// Handle block comments
|
||||||
if (line[i] == '/' && line[i + 1] == '*') {
|
if (line[i] == '/' && line[i + 1] == '*') {
|
||||||
comment_section = 1;
|
comment_section = 1;
|
||||||
result_pos += sprintf(&result[result_pos], "%s", E.theme.COLOR_COMMENT);
|
result_pos += snprintf(&result[result_pos], 10, "%s", E.theme.COLOR_COMMENT);
|
||||||
result[result_pos++] = line[i++];
|
result[result_pos++] = line[i++];
|
||||||
result[result_pos++] = line[i++];
|
result[result_pos++] = line[i++];
|
||||||
while (line[i] != '\0') {
|
while (line[i] != '\0') {
|
||||||
@@ -161,13 +165,13 @@ char *highlight_line(const char *line, int *length) {
|
|||||||
}
|
}
|
||||||
copy_utf8_char(result, &result_pos, line, &i);
|
copy_utf8_char(result, &result_pos, line, &i);
|
||||||
}
|
}
|
||||||
result_pos += sprintf(&result[result_pos], "%s", COLOR_RESET);
|
result_pos += snprintf(&result[result_pos], 10, "%s", COLOR_RESET);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle strings
|
// Handle strings
|
||||||
if (line[i] == '"') {
|
if (line[i] == '"') {
|
||||||
result_pos += sprintf(&result[result_pos], "%s\"", E.theme.COLOR_STRING);
|
result_pos += snprintf(&result[result_pos], 10, "%s\"", E.theme.COLOR_STRING);
|
||||||
i++;
|
i++;
|
||||||
while (line[i] != '\0' && line[i] != '"') {
|
while (line[i] != '\0' && line[i] != '"') {
|
||||||
if (line[i] == '\\') {
|
if (line[i] == '\\') {
|
||||||
@@ -179,13 +183,13 @@ char *highlight_line(const char *line, int *length) {
|
|||||||
}
|
}
|
||||||
if (line[i] == '"')
|
if (line[i] == '"')
|
||||||
result[result_pos++] = line[i++];
|
result[result_pos++] = line[i++];
|
||||||
result_pos += sprintf(&result[result_pos], "%s", COLOR_RESET);
|
result_pos += snprintf(&result[result_pos], 10, "%s", COLOR_RESET);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle character literals
|
// Handle character literals
|
||||||
if (line[i] == '\'') {
|
if (line[i] == '\'') {
|
||||||
result_pos += sprintf(&result[result_pos], "%s'", E.theme.COLOR_STRING);
|
result_pos += snprintf(&result[result_pos], 10, "%s'", E.theme.COLOR_STRING);
|
||||||
i++;
|
i++;
|
||||||
while (line[i] != '\0' && line[i] != '\'') {
|
while (line[i] != '\0' && line[i] != '\'') {
|
||||||
if (line[i] == '\\') {
|
if (line[i] == '\\') {
|
||||||
@@ -197,17 +201,17 @@ char *highlight_line(const char *line, int *length) {
|
|||||||
}
|
}
|
||||||
if (line[i] == '\'')
|
if (line[i] == '\'')
|
||||||
result[result_pos++] = line[i++];
|
result[result_pos++] = line[i++];
|
||||||
result_pos += sprintf(&result[result_pos], "%s", COLOR_RESET);
|
result_pos += snprintf(&result[result_pos], 10, "%s", COLOR_RESET);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle numbers
|
// Handle numbers
|
||||||
if (line[i] >= '0' && line[i] <= '9') {
|
if (line[i] >= '0' && line[i] <= '9') {
|
||||||
result_pos += sprintf(&result[result_pos], "%s", E.theme.COLOR_NUMBER);
|
result_pos += snprintf(&result[result_pos], 10, "%s", E.theme.COLOR_NUMBER);
|
||||||
while (is_word_char(&line[i]) || line[i] == '.') {
|
while (is_word_char(&line[i]) || line[i] == '.') {
|
||||||
copy_utf8_char(result, &result_pos, line, &i);
|
copy_utf8_char(result, &result_pos, line, &i);
|
||||||
}
|
}
|
||||||
result_pos += sprintf(&result[result_pos], "%s", COLOR_RESET);
|
result_pos += snprintf(&result[result_pos], 10, "%s", COLOR_RESET);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,15 +235,15 @@ char *highlight_line(const char *line, int *length) {
|
|||||||
else if (is_type(word))
|
else if (is_type(word))
|
||||||
type = TOKEN_TYPE;
|
type = TOKEN_TYPE;
|
||||||
|
|
||||||
result_pos += sprintf(&result[result_pos], "%s%s%s", get_color(type),
|
result_pos += snprintf(&result[result_pos], 100, "%s%s%s", get_color(type),
|
||||||
word, COLOR_RESET);
|
word, COLOR_RESET);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle operators and other characters (including non-ASCII multi-byte)
|
// Handle operators and other characters (including non-ASCII multi-byte)
|
||||||
result_pos += sprintf(&result[result_pos], "%s", E.theme.COLOR_DEFAULT);
|
result_pos += snprintf(&result[result_pos], 10, "%s", E.theme.COLOR_DEFAULT);
|
||||||
copy_utf8_char(result, &result_pos, line, &i);
|
copy_utf8_char(result, &result_pos, line, &i);
|
||||||
result_pos += sprintf(&result[result_pos], "%s", COLOR_RESET);
|
result_pos += snprintf(&result[result_pos], 10, "%s", COLOR_RESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
result[result_pos] = '\0';
|
result[result_pos] = '\0';
|
||||||
|
|||||||
Reference in New Issue
Block a user