2 Commits

Author SHA1 Message Date
5d581c1c2f fixups
Some checks failed
Release / Bump Homebrew formula (push) Has been cancelled
2025-11-28 03:20:33 -08:00
78e4f84f7b fix bug into goto_line
Some checks failed
Release / Bump Homebrew formula (push) Has been cancelled
2025-11-28 03:12:08 -08:00
6 changed files with 97 additions and 49 deletions

View File

@@ -2,9 +2,9 @@ cmake_minimum_required(VERSION 3.15)
project(ke C) # Specify C language explicitly project(ke C) # Specify C language explicitly
set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD 99)
set(KE_VERSION "2.0.0") set(KE_VERSION "2.0.1")
set(CMAKE_C_FLAGS "-Wall -Wextra -pedantic -Wshadow -Werror -std=c99 -g") set(CMAKE_C_FLAGS "-Wall -Wextra -pedantic -Wshadow -Werror -std=c99 -g -Werror=stringop-truncation")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_DEFAULT_SOURCE -D_XOPEN_SOURCE") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_DEFAULT_SOURCE -D_XOPEN_SOURCE")
# Optionally enable AddressSanitizer (ASan) # Optionally enable AddressSanitizer (ASan)

33
abuf.c
View File

@@ -6,6 +6,15 @@
#include "core.h" #include "core.h"
static void
abuf_grow(abuf *buf, size_t delta)
{
if (buf->cap - buf->size < delta) {
ab_resize(buf, buf->cap + delta);
}
}
void void
ab_init(abuf *buf) ab_init(abuf *buf)
{ {
@@ -38,6 +47,7 @@ ab_resize(abuf *buf, size_t cap)
void void
ab_appendch(abuf *buf, char c) ab_appendch(abuf *buf, char c)
{ {
abuf_grow(buf, 1);
ab_append(buf, &c, 1); ab_append(buf, &c, 1);
} }
@@ -45,20 +55,10 @@ ab_appendch(abuf *buf, char c)
void void
ab_append(abuf *buf, const char *s, size_t len) ab_append(abuf *buf, const char *s, size_t len)
{ {
char *nc = buf->b; char *nc = NULL;
size_t sz = buf->size + len;
if (sz >= buf->cap) { abuf_grow(buf, len);
while (sz > buf->cap) { nc = buf->b;
if (buf->cap == 0) {
buf->cap = 1;
} else {
buf->cap *= 2;
}
}
nc = realloc(nc, buf->cap);
assert(nc != NULL);
}
memcpy(&nc[buf->size], s, len); memcpy(&nc[buf->size], s, len);
buf->b = nc; buf->b = nc;
@@ -69,6 +69,8 @@ ab_append(abuf *buf, const char *s, size_t len)
void void
ab_prependch(abuf *buf, const char c) ab_prependch(abuf *buf, const char c)
{ {
abuf_grow(buf, 1);
ab_prepend(buf, &c, 1); ab_prepend(buf, &c, 1);
} }
@@ -76,7 +78,10 @@ ab_prependch(abuf *buf, const char c)
void void
ab_prepend(abuf *buf, const char *s, const size_t len) ab_prepend(abuf *buf, const char *s, const size_t len)
{ {
char *nc = realloc(buf->b, buf->size + len); char *nc = NULL;
abuf_grow(buf, len);
nc = buf->b;
assert(nc != NULL); assert(nc != NULL);
memmove(nc + len, nc, buf->size); memmove(nc + len, nc, buf->size);

View File

@@ -71,6 +71,7 @@ buffer_collect_prefix_matches(const char *prefix, int *out_idx, const int max_ou
size_t plen = (prefix ? strlen(prefix) : 0); size_t plen = (prefix ? strlen(prefix) : 0);
for (int i = 0; i < editor.bufcount; i++) { for (int i = 0; i < editor.bufcount; i++) {
matched = 0;
b = editor.buffers[i]; b = editor.buffers[i];
const char *cand1 = b->filename; const char *cand1 = b->filename;
@@ -267,21 +268,35 @@ buffers_init(void)
editor.buffers = NULL; editor.buffers = NULL;
editor.bufcount = 0; editor.bufcount = 0;
editor.curbuf = -1; editor.curbuf = -1;
editor.bufcap = 0;
idx = buffer_add_empty(); idx = buffer_add_empty();
buffer_switch(idx); buffer_switch(idx);
} }
static void
buffer_list_resize(void)
{
buffer **newlist = NULL;
if (editor.bufcount == (int)editor.bufcap) {
editor.bufcap = cap_growth((int)editor.bufcap, editor.bufcount + 1);
newlist = realloc(editor.buffers, sizeof(buffer *) * editor.bufcap);
assert(newlist != NULL);
editor.buffers = newlist;
}
}
int int
buffer_add_empty(void) buffer_add_empty(void)
{ {
buffer *buf = NULL; buffer *buf = NULL;
buffer **newlist = realloc(editor.buffers, sizeof(buffer *) * (editor.bufcount + 1));
int idx = 0; int idx = 0;
assert(newlist != NULL); buffer_list_resize();
editor.buffers = newlist;
buf = calloc(1, sizeof(buffer)); buf = calloc(1, sizeof(buffer));
assert(buf != NULL); assert(buf != NULL);

View File

@@ -92,6 +92,7 @@ init_editor(void)
/* initialize buffer system on first init */ /* initialize buffer system on first init */
if (editor.buffers == NULL && editor.bufcount == 0) { if (editor.buffers == NULL && editor.bufcount == 0) {
editor.bufcap = 0;
buffers_init(); buffers_init();
} }
} }

View File

@@ -35,6 +35,7 @@ struct editor {
struct buffer **buffers; /* array of buffers */ struct buffer **buffers; /* array of buffers */
int bufcount; /* number of buffers */ int bufcount; /* number of buffers */
int curbuf; /* current buffer index */ int curbuf; /* current buffer index */
size_t bufcap; /* current buffer capacity */
}; };

56
main.c
View File

@@ -298,8 +298,15 @@ file_open_prompt_cb(char *buf, const int16_t key)
strncat(newbuf, "/", sizeof(newbuf) - strlen(newbuf) - 1); strncat(newbuf, "/", sizeof(newbuf) - strlen(newbuf) - 1);
} }
strncpy(buf, newbuf[0] ? newbuf : names[0], 127); /* copy to input buffer (max 127 chars + NUL) avoiding truncation warnings */
buf[127] = '\0'; do {
const char *src__ = newbuf[0] ? newbuf : names[0];
size_t cap__ = 128u;
size_t len__ = strnlen(src__, cap__ - 1);
memcpy(buf, src__, len__);
buf[len__] = '\0';
} while (0);
editor_set_status("Unique match: %s%s", names[0], isdir[0] ? "/" : ""); editor_set_status("Unique match: %s%s", names[0], isdir[0] ? "/" : "");
} else { } else {
cur = strlen(base); cur = strlen(base);
@@ -318,8 +325,14 @@ file_open_prompt_cb(char *buf, const int16_t key)
strncat(newbuf, base, sizeof(newbuf) - strlen(newbuf) - 1); strncat(newbuf, base, sizeof(newbuf) - strlen(newbuf) - 1);
} }
strncpy(buf, newbuf, 127); /* copy to input buffer (max 127 chars + NUL) avoiding truncation warnings */
buf[127] = '\0'; do {
const char *src__ = newbuf;
size_t cap__ = 128u;
size_t len__ = strnlen(src__, cap__ - 1);
memcpy(buf, src__, len__);
buf[len__] = '\0';
} while (0);
size_t used = 0; size_t used = 0;
used += snprintf(msg + used, sizeof(msg) - used, "%d matches: ", n); used += snprintf(msg + used, sizeof(msg) - used, "%d matches: ", n);
@@ -842,22 +855,35 @@ delete_region(void)
void void
jump_to_position(int col, int row) jump_to_position(int col, int row)
{ {
/* clamp position */ if (ENROWS <= 0) {
ECURX = 0;
ECURY = 0;
editor.curx = ECURX;
editor.cury = ECURY;
display_refresh();
return;
}
if (row < 0) { if (row < 0) {
row = 0; row = 0;
} else if (row > editor.nrows) { } else if (row >= ENROWS) {
row = editor.nrows - 1; row = ENROWS - 1;
} }
if (col < 0) { if (col < 0) {
col = 0; col = 0;
} else if (row >= 0 && row < ENROWS && col > (int) EROW[row].size) { } else if (col > (int) EROW[row].size) {
col = (int) EROW[row].size; col = (int) EROW[row].size;
} }
ECURX = col; ECURX = col;
ECURY = row; ECURY = row;
editor.curx = ECURX;
editor.cury = ECURY;
display_refresh(); display_refresh();
} }
@@ -873,7 +899,7 @@ goto_line(void)
} }
lineno = atoi(query); lineno = atoi(query);
if (lineno < 1 || lineno >= ENROWS) { if (lineno < 1 || lineno > ENROWS) {
editor_set_status("Line number must be between 1 and %d.", editor_set_status("Line number must be between 1 and %d.",
ENROWS); ENROWS);
free(query); free(query);
@@ -1684,26 +1710,26 @@ editor_find(void)
void void
editor_openfile(void) editor_openfile(void)
{ {
char *filename; char *filename = NULL;
buffer *cur = NULL;
int nb = NULL;
/* Add TAB completion for path input */
filename = editor_prompt("Load file: %s", file_open_prompt_cb); filename = editor_prompt("Load file: %s", file_open_prompt_cb);
if (filename == NULL) { if (filename == NULL) {
return; return;
} }
/* If the only buffer is an unnamed, empty buffer, reuse it */ cur = buffer_current();
buffer *cur = buffer_current();
if (editor.bufcount == 1 && buffer_is_unnamed_and_empty(cur)) { if (editor.bufcount == 1 && buffer_is_unnamed_and_empty(cur)) {
open_file(filename); open_file(filename);
buffer_save_current(); buffer_save_current();
} else { } else {
/* Open into a new buffer */ nb = buffer_add_empty();
int nb = buffer_add_empty();
buffer_switch(nb); buffer_switch(nb);
open_file(filename); open_file(filename);
buffer_save_current(); buffer_save_current();
} }
free(filename); free(filename);
} }