Fix segfault.
This commit is contained in:
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.15)
|
||||
project(ke C) # Specify C language explicitly
|
||||
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(KE_VERSION "2.0.1")
|
||||
set(KE_VERSION "2.0.3")
|
||||
|
||||
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")
|
||||
|
||||
17
abuf.c
17
abuf.c
@@ -28,19 +28,24 @@ ab_init(abuf *buf)
|
||||
void
|
||||
ab_init_cap(abuf *buf, const size_t cap)
|
||||
{
|
||||
buf->b = calloc(cap, 1);
|
||||
buf->size = 0;
|
||||
buf->cap = cap;
|
||||
ab_init(buf);
|
||||
|
||||
if (cap > 0) {
|
||||
ab_resize(buf, cap);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ab_resize(abuf *buf, size_t cap)
|
||||
{
|
||||
cap = cap_growth(buf->cap, cap);
|
||||
buf->b = realloc(buf->b, cap);
|
||||
assert(buf->b != NULL);
|
||||
char *newbuf = NULL;
|
||||
|
||||
cap = cap_growth(buf->cap, cap) + 1;
|
||||
newbuf = realloc(buf->b, cap);
|
||||
assert(newbuf != NULL);
|
||||
buf->cap = cap;
|
||||
buf->b = newbuf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
252
main.c
252
main.c
@@ -1144,18 +1144,18 @@ insertch(const int16_t c)
|
||||
* a row; it can just figure out where the cursor is
|
||||
* at and what to do.
|
||||
*/
|
||||
if (editor.cury == editor.nrows) {
|
||||
erow_insert(editor.nrows, "", 0);
|
||||
if (ECURY == ENROWS) {
|
||||
erow_insert(ENROWS, "", 0);
|
||||
}
|
||||
|
||||
/* Inserting ends kill ring chaining. */
|
||||
editor.kill = 0;
|
||||
|
||||
row_insert_ch(&editor.row[editor.cury],
|
||||
editor.curx,
|
||||
row_insert_ch(&EROW[ECURY],
|
||||
ECURX,
|
||||
(int16_t)(c & 0xff));
|
||||
editor.curx++;
|
||||
editor.dirty++;
|
||||
ECURX++;
|
||||
EDIRTY++;
|
||||
}
|
||||
|
||||
|
||||
@@ -1166,36 +1166,36 @@ deletech(uint8_t op)
|
||||
unsigned char dch = 0;
|
||||
int prev = 0;
|
||||
|
||||
if (editor.cury >= editor.nrows) {
|
||||
if (ECURY >= ENROWS) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (editor.cury == 0 && editor.curx == 0) {
|
||||
if (ECURY == 0 && ECURX == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
row = &editor.row[editor.cury];
|
||||
if (editor.curx > 0) {
|
||||
dch = (unsigned char)row->b[editor.curx - 1];
|
||||
row = &EROW[ECURY];
|
||||
if (ECURX > 0) {
|
||||
dch = (unsigned char)row->b[ECURX - 1];
|
||||
} else {
|
||||
dch = '\n';
|
||||
}
|
||||
|
||||
if (editor.curx > 0) {
|
||||
row_delete_ch(row, editor.curx - 1);
|
||||
editor.curx--;
|
||||
if (ECURX > 0) {
|
||||
row_delete_ch(row, ECURX - 1);
|
||||
ECURX--;
|
||||
} else {
|
||||
editor.curx = editor.row[editor.cury - 1].size;
|
||||
row_append_row(&editor.row[editor.cury - 1],
|
||||
ECURX = (int)EROW[ECURY - 1].size;
|
||||
row_append_row(&EROW[ECURY - 1],
|
||||
row->b,
|
||||
row->size);
|
||||
(int)row->size);
|
||||
|
||||
prev = editor.no_kill;
|
||||
editor.no_kill = 1;
|
||||
|
||||
delete_row(editor.cury);
|
||||
delete_row(ECURY);
|
||||
editor.no_kill = prev;
|
||||
editor.cury--;
|
||||
ECURY--;
|
||||
}
|
||||
|
||||
if (op == KILLRING_FLUSH) {
|
||||
@@ -1711,8 +1711,8 @@ void
|
||||
editor_openfile(void)
|
||||
{
|
||||
char *filename = NULL;
|
||||
buffer *cur = NULL;
|
||||
int nb = NULL;
|
||||
const buffer *cur = NULL;
|
||||
int nb = 0;
|
||||
|
||||
filename = editor_prompt("Load file: %s", file_open_prompt_cb);
|
||||
if (filename == NULL) {
|
||||
@@ -1787,31 +1787,37 @@ move_cursor_once(const int16_t c, int interactive)
|
||||
abuf *row = NULL;
|
||||
int reps = 0;
|
||||
|
||||
row = editor.cury >= editor.nrows ? NULL : &editor.row[editor.cury];
|
||||
/* Helper lambdas (as static inline functions would also work) */
|
||||
/* clamp ECURX within current row bounds */
|
||||
{
|
||||
/* no-op block, kept for patch context */
|
||||
}
|
||||
|
||||
row = (ECURY >= ENROWS) ? NULL : &EROW[ECURY];
|
||||
|
||||
switch (c) {
|
||||
case ARROW_UP:
|
||||
case CTRL_KEY('p'):
|
||||
if (editor.cury > 0) {
|
||||
editor.cury--;
|
||||
row = (editor.cury >= editor.nrows)
|
||||
? NULL
|
||||
: &editor.row[editor.cury];
|
||||
if (ECURY > 0) {
|
||||
ECURY--;
|
||||
row = (ECURY >= ENROWS) ? NULL : &EROW[ECURY];
|
||||
if (interactive) {
|
||||
editor.curx = first_nonwhitespace(row);
|
||||
ECURX = first_nonwhitespace(row);
|
||||
} else if (row) {
|
||||
if (ECURX > (int)row->size) ECURX = (int)row->size;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ARROW_DOWN:
|
||||
case CTRL_KEY('n'):
|
||||
if (editor.cury < editor.nrows - 1) {
|
||||
editor.cury++;
|
||||
row = editor.cury >= editor.nrows
|
||||
? NULL
|
||||
: &editor.row[editor.cury];
|
||||
if (ECURY < ENROWS - 1) {
|
||||
ECURY++;
|
||||
row = (ECURY >= ENROWS) ? NULL : &EROW[ECURY];
|
||||
|
||||
if (interactive) {
|
||||
editor.curx = first_nonwhitespace(row);
|
||||
ECURX = first_nonwhitespace(row);
|
||||
} else if (row) {
|
||||
if (ECURX > (int)row->size) ECURX = (int)row->size;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1821,48 +1827,48 @@ move_cursor_once(const int16_t c, int interactive)
|
||||
break;
|
||||
}
|
||||
|
||||
if (editor.curx < (int)row->size) {
|
||||
editor.curx++;
|
||||
if (ECURX < (int)row->size) {
|
||||
ECURX++;
|
||||
/* skip over UTF-8 continuation bytes */
|
||||
while (editor.curx < (int)row->size &&
|
||||
((unsigned char)row->b[editor.curx] &
|
||||
while (ECURX < (int)row->size &&
|
||||
((unsigned char)row->b[ECURX] &
|
||||
0xC0) == 0x80) {
|
||||
editor.curx++;
|
||||
ECURX++;
|
||||
}
|
||||
} else if (editor.curx == (int)row->size && editor.cury < editor.nrows - 1) {
|
||||
editor.cury++;
|
||||
editor.curx = 0;
|
||||
} else if (ECURX == (int)row->size && ECURY < ENROWS - 1) {
|
||||
ECURY++;
|
||||
ECURX = 0;
|
||||
}
|
||||
break;
|
||||
case ARROW_LEFT:
|
||||
case CTRL_KEY('b'):
|
||||
if (editor.curx > 0) {
|
||||
editor.curx--;
|
||||
while (editor.curx > 0 &&
|
||||
((unsigned char)row->b[editor.curx] &
|
||||
if (ECURX > 0) {
|
||||
ECURX--;
|
||||
while (ECURX > 0 &&
|
||||
((unsigned char)row->b[ECURX] &
|
||||
0xC0) == 0x80) {
|
||||
editor.curx--;
|
||||
ECURX--;
|
||||
}
|
||||
} else if (editor.cury > 0) {
|
||||
editor.cury--;
|
||||
editor.curx = (int)editor.row[editor.cury].size;
|
||||
} else if (ECURY > 0) {
|
||||
ECURY--;
|
||||
ECURX = (int)EROW[ECURY].size;
|
||||
|
||||
row = &editor.row[editor.cury];
|
||||
while (editor.curx > 0 &&
|
||||
((unsigned char)row->b[editor.curx] &
|
||||
row = &EROW[ECURY];
|
||||
while (ECURX > 0 &&
|
||||
((unsigned char)row->b[ECURX] &
|
||||
0xC0) == 0x80) {
|
||||
editor.curx--;
|
||||
ECURX--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PG_UP:
|
||||
case PG_DN:
|
||||
if (c == PG_UP) {
|
||||
editor.cury = editor.rowoffs;
|
||||
ECURY = EROWOFFS;
|
||||
} else if (c == PG_DN) {
|
||||
editor.cury = editor.rowoffs + editor.rows - 1;
|
||||
if (editor.cury > editor.nrows) {
|
||||
editor.cury = editor.nrows;
|
||||
ECURY = EROWOFFS + editor.rows - 1;
|
||||
if (ECURY > ENROWS) {
|
||||
ECURY = ENROWS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1875,14 +1881,14 @@ move_cursor_once(const int16_t c, int interactive)
|
||||
|
||||
case HOME_KEY:
|
||||
case CTRL_KEY('a'):
|
||||
editor.curx = 0;
|
||||
ECURX = 0;
|
||||
break;
|
||||
case END_KEY:
|
||||
case CTRL_KEY('e'):
|
||||
if (editor.cury >= editor.nrows) {
|
||||
if (ECURY >= ENROWS) {
|
||||
break;
|
||||
}
|
||||
editor.curx = (int)editor.row[editor.cury].size;
|
||||
ECURX = (int)EROW[ECURY].size;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -1906,28 +1912,47 @@ newline(void)
|
||||
{
|
||||
abuf *row = NULL;
|
||||
|
||||
if (editor.cury >= editor.nrows) {
|
||||
erow_insert(editor.cury, "", 0);
|
||||
editor.cury++;
|
||||
editor.curx = 0;
|
||||
} else if (editor.curx == 0) {
|
||||
erow_insert(editor.cury, "", 0);
|
||||
editor.cury++;
|
||||
editor.curx = 0;
|
||||
if (ECURY >= ENROWS) {
|
||||
erow_insert(ECURY, "", 0);
|
||||
ECURY++;
|
||||
ECURX = 0;
|
||||
} else if (ECURX == 0) {
|
||||
erow_insert(ECURY, "", 0);
|
||||
ECURY++;
|
||||
ECURX = 0;
|
||||
} else {
|
||||
row = &editor.row[editor.cury];
|
||||
erow_insert(editor.cury + 1,
|
||||
&row->b[editor.curx],
|
||||
row->size - editor.curx);
|
||||
row = &editor.row[editor.cury];
|
||||
row->size = editor.curx;
|
||||
size_t rhs_len;
|
||||
char *tmp = NULL;
|
||||
|
||||
row = &EROW[ECURY];
|
||||
/* Snapshot RHS into a temporary buffer BEFORE we mutate rows array. */
|
||||
rhs_len = row->size - (size_t)ECURX;
|
||||
if (rhs_len > 0) {
|
||||
tmp = malloc(rhs_len);
|
||||
assert(tmp != NULL);
|
||||
memcpy(tmp, &row->b[ECURX], rhs_len);
|
||||
}
|
||||
|
||||
/* Trim the current (LHS) row BEFORE inserting the new row. */
|
||||
row->size = ECURX;
|
||||
if (row->cap <= row->size) {
|
||||
ab_resize(row, row->size + 1);
|
||||
}
|
||||
row->b[row->size] = '\0';
|
||||
editor.cury++;
|
||||
editor.curx = 0;
|
||||
|
||||
/* Now insert the RHS as a new row; this may realloc/move EROW. */
|
||||
erow_insert(ECURY + 1, tmp ? tmp : "", (int)rhs_len);
|
||||
if (tmp) {
|
||||
free(tmp);
|
||||
}
|
||||
ECURY++;
|
||||
ECURX = 0;
|
||||
}
|
||||
|
||||
/* BREAK THE KILL CHAIN \m/ */
|
||||
editor.kill = 0;
|
||||
/* Buffer modified */
|
||||
EDIRTY++;
|
||||
}
|
||||
|
||||
|
||||
@@ -2501,9 +2526,9 @@ draw_rows(abuf *ab)
|
||||
int y = 0;
|
||||
|
||||
for (y = 0; y < editor.rows; y++) {
|
||||
filerow = y + editor.rowoffs;
|
||||
if (filerow >= editor.nrows) {
|
||||
if ((editor.nrows == 0) && (y == editor.rows / 3)) {
|
||||
filerow = y + EROWOFFS;
|
||||
if (filerow >= ENROWS) {
|
||||
if ((ENROWS == 0) && (y == editor.rows / 3)) {
|
||||
len = snprintf(buf,
|
||||
sizeof(buf),
|
||||
"%s",
|
||||
@@ -2529,7 +2554,7 @@ draw_rows(abuf *ab)
|
||||
while (j < row->size && printed < editor.cols) {
|
||||
c = row->b[j];
|
||||
|
||||
if (rx < editor.coloffs) {
|
||||
if (rx < ECOLOFFS) {
|
||||
if (c == '\t') rx += (TAB_STOP - (rx % TAB_STOP));
|
||||
else if (c < 0x20) rx += 3;
|
||||
else rx++;
|
||||
@@ -2595,16 +2620,16 @@ draw_status_bar(abuf *ab)
|
||||
sizeof(status),
|
||||
"%c%cke: %.20s - %d lines",
|
||||
status_mode_char(),
|
||||
editor.dirty ? '!' : '-',
|
||||
editor.filename ? editor.filename : "[no file]",
|
||||
editor.nrows);
|
||||
EDIRTY ? '!' : '-',
|
||||
EFILENAME ? EFILENAME : "[no file]",
|
||||
ENROWS);
|
||||
|
||||
if (editor.mark_set) {
|
||||
if (EMARK_SET) {
|
||||
snprintf(mstatus,
|
||||
sizeof(mstatus),
|
||||
" | M: %d, %d ",
|
||||
editor.mark_curx + 1,
|
||||
editor.mark_cury + 1);
|
||||
EMARK_CURX + 1,
|
||||
EMARK_CURY + 1);
|
||||
} else {
|
||||
snprintf(mstatus, sizeof(mstatus), " | M:clear ");
|
||||
}
|
||||
@@ -2612,9 +2637,9 @@ draw_status_bar(abuf *ab)
|
||||
rlen = snprintf(rstatus,
|
||||
sizeof(rstatus),
|
||||
"L%d/%d C%d %s",
|
||||
editor.cury + 1,
|
||||
editor.nrows,
|
||||
editor.curx + 1,
|
||||
ECURY + 1,
|
||||
ENROWS,
|
||||
ECURX + 1,
|
||||
mstatus);
|
||||
|
||||
ab_append(ab, ESCSEQ "7m", 4);
|
||||
@@ -2653,26 +2678,26 @@ scroll(void)
|
||||
{
|
||||
const abuf *row = NULL;
|
||||
|
||||
editor.rx = 0;
|
||||
if (editor.cury < editor.nrows) {
|
||||
row = &editor.row[editor.cury];
|
||||
editor.rx = erow_render_to_cursor(row, editor.curx);
|
||||
ERX = 0;
|
||||
if (ECURY < ENROWS) {
|
||||
row = &EROW[ECURY];
|
||||
ERX = erow_render_to_cursor(row, ECURX);
|
||||
}
|
||||
|
||||
if (editor.cury < editor.rowoffs) {
|
||||
editor.rowoffs = editor.cury;
|
||||
if (ECURY < EROWOFFS) {
|
||||
EROWOFFS = ECURY;
|
||||
}
|
||||
|
||||
if (editor.cury >= editor.rowoffs + editor.rows) {
|
||||
editor.rowoffs = editor.cury - editor.rows + 1;
|
||||
if (ECURY >= EROWOFFS + editor.rows) {
|
||||
EROWOFFS = ECURY - editor.rows + 1;
|
||||
}
|
||||
|
||||
if (editor.rx < editor.coloffs) {
|
||||
editor.coloffs = editor.rx;
|
||||
if (ERX < ECOLOFFS) {
|
||||
ECOLOFFS = ERX;
|
||||
}
|
||||
|
||||
if (editor.rx >= editor.coloffs + editor.cols) {
|
||||
editor.coloffs = editor.rx - editor.cols + 1;
|
||||
if (ERX >= ECOLOFFS + editor.cols) {
|
||||
ECOLOFFS = ERX - editor.cols + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2696,8 +2721,8 @@ display_refresh(void)
|
||||
snprintf(buf,
|
||||
sizeof(buf),
|
||||
ESCSEQ "%d;%dH",
|
||||
(editor.cury - editor.rowoffs) + 1,
|
||||
(editor.rx - editor.coloffs) + 1);
|
||||
(ECURY - EROWOFFS) + 1,
|
||||
(ERX - ECOLOFFS) + 1);
|
||||
ab_append(&ab, buf, kstrnlen(buf, 32));
|
||||
/* ab_append(&ab, ESCSEQ "1;2H", 7); */
|
||||
ab_append(&ab, ESCSEQ "?25h", 6);
|
||||
@@ -2897,3 +2922,22 @@ main(int argc, char *argv[])
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Cursor helpers: keep per-buffer cursor consistent and clamped */
|
||||
static inline void clamp_curx_to_row(void)
|
||||
{
|
||||
if (ECURY >= ENROWS) return;
|
||||
abuf *row = &EROW[ECURY];
|
||||
if (ECURX < 0) ECURX = 0;
|
||||
int maxx = (int)row->size;
|
||||
if (ECURX > maxx) ECURX = maxx;
|
||||
}
|
||||
|
||||
static inline void set_cursor(int x, int y)
|
||||
{
|
||||
if (y < 0) y = 0;
|
||||
if (y > ENROWS) y = ENROWS;
|
||||
ECURY = y;
|
||||
ECURX = x;
|
||||
clamp_curx_to_row();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user