Remove erow.
This commit is contained in:
459
main.c
459
main.c
@@ -77,26 +77,13 @@
|
||||
/* append buffer */
|
||||
typedef struct abuf {
|
||||
char *b;
|
||||
size_t len;
|
||||
size_t size;
|
||||
size_t cap;
|
||||
} abuf;
|
||||
|
||||
#define ABUF_INIT {NULL, 0, 0}
|
||||
|
||||
|
||||
/* editor row */
|
||||
typedef struct erow {
|
||||
char *line;
|
||||
char *render;
|
||||
|
||||
int size;
|
||||
int rsize;
|
||||
|
||||
int cap;
|
||||
int dirty;
|
||||
} erow;
|
||||
|
||||
|
||||
typedef enum undo_kind {
|
||||
UNDO_INSERT = 1 << 0,
|
||||
UNDO_UNKNOWN = 1 << 1,
|
||||
@@ -133,8 +120,8 @@ struct editor {
|
||||
int mode;
|
||||
int nrows;
|
||||
int rowoffs, coloffs;
|
||||
erow *row;
|
||||
erow *killring;
|
||||
abuf *row;
|
||||
abuf *killring;
|
||||
int kill; /* KILL CHAIN (sounds metal) */
|
||||
int no_kill; /* don't kill in delete_row */
|
||||
char *filename;
|
||||
@@ -175,8 +162,9 @@ void reset_editor(void);
|
||||
/* small tools, abufs, etc */
|
||||
int next_power_of_2(int n);
|
||||
int cap_growth(int cap, int sz);
|
||||
size_t kstrnlen(const char *buf, const size_t max);
|
||||
size_t kstrnlen(const char *buf, size_t max);
|
||||
void ab_init(abuf *buf);
|
||||
void ab_init_cap(abuf *buf, size_t cap);
|
||||
void ab_appendch(abuf *buf, char c);
|
||||
void ab_append(abuf *buf, const char *s, size_t len);
|
||||
void ab_prependch(abuf *buf, char c);
|
||||
@@ -185,15 +173,6 @@ void ab_free(abuf *buf);
|
||||
char nibble_to_hex(char c);
|
||||
void swap_int(int *a, int *b);
|
||||
|
||||
/* editor rows */
|
||||
int erow_render_to_cursor(erow *row, int cx);
|
||||
int erow_cursor_to_render(erow *row, int rx);
|
||||
int erow_init(erow *row, int len);
|
||||
void erow_update(erow *row);
|
||||
void erow_insert(int at, char *s, int len);
|
||||
void erow_free(erow *row);
|
||||
|
||||
|
||||
/* kill ring, marking, etc... */
|
||||
void killring_flush(void);
|
||||
void killring_yank(void);
|
||||
@@ -220,8 +199,8 @@ void delete_next_word(void);
|
||||
void find_prev_word(void);
|
||||
void delete_prev_word(void);
|
||||
void delete_row(int at);
|
||||
void row_insert_ch(erow *row, int at, int16_t c);
|
||||
void row_delete_ch(erow *row, int at);
|
||||
void row_insert_ch(abuf *row, int at, int16_t c);
|
||||
void row_delete_ch(abuf *row, int at);
|
||||
void insertch(int16_t c);
|
||||
void deletech(uint8_t op);
|
||||
void open_file(const char *filename);
|
||||
@@ -229,12 +208,11 @@ char *rows_to_buffer(int *buflen);
|
||||
int save_file(void);
|
||||
uint16_t is_arrow_key(int16_t c);
|
||||
int16_t get_keypress(void);
|
||||
void display_refresh(void);
|
||||
void editor_find_callback(char *query, int16_t c);
|
||||
void editor_find(void);
|
||||
char *editor_prompt(char*, void (*cb)(char*, int16_t));
|
||||
void editor_openfile(void);
|
||||
int first_nonwhitespace(erow *row);
|
||||
int first_nonwhitespace(abuf *row);
|
||||
void move_cursor_once(int16_t c, int interactive);
|
||||
void move_cursor(int16_t c, int interactive);
|
||||
void uarg_start(void);
|
||||
@@ -400,7 +378,7 @@ void
|
||||
reset_editor(void)
|
||||
{
|
||||
for (int i = 0; i < editor.nrows; i++) {
|
||||
erow_free(&editor.row[i]);
|
||||
ab_free(&editor.row[i]);
|
||||
}
|
||||
free(editor.row);
|
||||
|
||||
@@ -418,11 +396,30 @@ void
|
||||
ab_init(abuf *buf)
|
||||
{
|
||||
buf->b = NULL;
|
||||
buf->len = 0;
|
||||
buf->size = 0;
|
||||
buf->cap = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ab_init_cap(abuf *buf, const size_t cap)
|
||||
{
|
||||
buf->b = calloc1(cap);
|
||||
buf->size = 0;
|
||||
buf->cap = 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);
|
||||
buf->cap = cap;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ab_appendch(abuf *buf, char c)
|
||||
{
|
||||
@@ -434,7 +431,7 @@ void
|
||||
ab_append(abuf *buf, const char *s, size_t len)
|
||||
{
|
||||
char *nc = buf->b;
|
||||
size_t sz = buf->len + len;
|
||||
size_t sz = buf->size + len;
|
||||
|
||||
if (sz >= buf->cap) {
|
||||
while (sz > buf->cap) {
|
||||
@@ -448,9 +445,9 @@ ab_append(abuf *buf, const char *s, size_t len)
|
||||
assert(nc != NULL);
|
||||
}
|
||||
|
||||
memcpy(&nc[buf->len], s, len);
|
||||
memcpy(&nc[buf->size], s, len);
|
||||
buf->b = nc;
|
||||
buf->len += len;
|
||||
buf->size += len;
|
||||
}
|
||||
|
||||
|
||||
@@ -464,14 +461,14 @@ ab_prependch(abuf *buf, const char c)
|
||||
void
|
||||
ab_prepend(abuf *buf, const char *s, const size_t len)
|
||||
{
|
||||
char *nc = realloc(buf->b, buf->len + len);
|
||||
char *nc = realloc(buf->b, buf->size + len);
|
||||
assert(nc != NULL);
|
||||
|
||||
memmove(nc + len, nc, buf->len);
|
||||
memmove(nc + len, nc, buf->size);
|
||||
memcpy(nc, s, len);
|
||||
|
||||
buf->b = nc;
|
||||
buf->len += len;
|
||||
buf->size += len;
|
||||
}
|
||||
|
||||
|
||||
@@ -480,7 +477,7 @@ ab_free(abuf *buf)
|
||||
{
|
||||
free(buf->b);
|
||||
buf->b = NULL;
|
||||
buf->len = 0;
|
||||
buf->size = 0;
|
||||
buf->cap = 0;
|
||||
}
|
||||
|
||||
@@ -506,7 +503,7 @@ swap_int(int *a, int *b)
|
||||
|
||||
|
||||
int
|
||||
erow_render_to_cursor(erow *row, int cx)
|
||||
erow_render_to_cursor(abuf *row, int cx)
|
||||
{
|
||||
int rx = 0;
|
||||
size_t j = 0;
|
||||
@@ -516,7 +513,7 @@ erow_render_to_cursor(erow *row, int cx)
|
||||
memset(&st, 0, sizeof(st));
|
||||
|
||||
while (j < (size_t)cx && j < (size_t)row->size) {
|
||||
unsigned char b = (unsigned char)row->line[j];
|
||||
unsigned char b = (unsigned char)row->b[j];
|
||||
if (b == '\t') {
|
||||
rx += (TAB_STOP - 1) - (rx % TAB_STOP);
|
||||
rx++;
|
||||
@@ -537,7 +534,7 @@ erow_render_to_cursor(erow *row, int cx)
|
||||
}
|
||||
|
||||
size_t rem = (size_t)row->size - j;
|
||||
size_t n = mbrtowc(&wc, &row->line[j], rem, &st);
|
||||
size_t n = mbrtowc(&wc, &row->b[j], rem, &st);
|
||||
|
||||
if (n == (size_t)-2) {
|
||||
/* incomplete sequence at end; treat one byte */
|
||||
@@ -567,7 +564,7 @@ erow_render_to_cursor(erow *row, int cx)
|
||||
|
||||
|
||||
int
|
||||
erow_cursor_to_render(erow *row, int rx)
|
||||
erow_cursor_to_render(abuf *row, int rx)
|
||||
{
|
||||
int cur_rx = 0;
|
||||
size_t j = 0;
|
||||
@@ -580,7 +577,7 @@ erow_cursor_to_render(erow *row, int rx)
|
||||
int w = 0;
|
||||
size_t adv = 1;
|
||||
|
||||
unsigned char b = (unsigned char)row->line[j];
|
||||
unsigned char b = (unsigned char)row->b[j];
|
||||
if (b == '\t') {
|
||||
int add = (TAB_STOP - 1) - (cur_rx % TAB_STOP);
|
||||
w = add + 1;
|
||||
@@ -594,7 +591,7 @@ erow_cursor_to_render(erow *row, int rx)
|
||||
adv = 1;
|
||||
} else {
|
||||
size_t rem = (size_t)row->size - j;
|
||||
size_t n = mbrtowc(&wc, &row->line[j], rem, &st);
|
||||
size_t n = mbrtowc(&wc, &row->b[j], rem, &st);
|
||||
|
||||
if (n == (size_t)-2 || n == (size_t)-1) {
|
||||
/* invalid/incomplete */
|
||||
@@ -626,118 +623,38 @@ erow_cursor_to_render(erow *row, int rx)
|
||||
|
||||
|
||||
int
|
||||
erow_init(erow *row, int len)
|
||||
erow_init(abuf *row, int len)
|
||||
{
|
||||
row->size = len;
|
||||
row->rsize = 0;
|
||||
row->render = NULL;
|
||||
row->line = NULL;
|
||||
row->cap = cap_growth(0, len) + 1; /* extra byte for NUL end */
|
||||
row->dirty = 1;
|
||||
ab_init_cap(row, len);
|
||||
|
||||
row->line = malloc(row->cap);
|
||||
assert(row->line != NULL);
|
||||
if (row->line == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
row->line[len] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
erow_update(erow *row)
|
||||
{
|
||||
int i = 0, j;
|
||||
int tabs = 0;
|
||||
int ctrl = 0;
|
||||
|
||||
/*
|
||||
* TODO(kyle): I'm not thrilled with this double-render.
|
||||
*/
|
||||
for (j = 0; j < row->size; j++) {
|
||||
if (row->line[j] == '\t') {
|
||||
tabs++;
|
||||
} else if ((unsigned char)row->line[j] < 0x20) {
|
||||
/* treat only ASCII control characters as non-printable */
|
||||
ctrl++;
|
||||
}
|
||||
}
|
||||
|
||||
if (row->rsize || row->render != NULL) {
|
||||
free(row->render);
|
||||
row->rsize = 0;
|
||||
}
|
||||
row->render = NULL;
|
||||
row->render = malloc(
|
||||
row->size + (tabs * (TAB_STOP - 1)) + (ctrl * 3) + 1);
|
||||
assert(row->render != NULL);
|
||||
|
||||
for (j = 0; j < row->size; j++) {
|
||||
if (row->line[j] == '\t') {
|
||||
do {
|
||||
row->render[i++] = ' ';
|
||||
} while ((i % TAB_STOP) != 0) ;
|
||||
} else if ((unsigned char)row->line[j] < 0x20) {
|
||||
row->render[i++] = '\\';
|
||||
row->render[i++] = nibble_to_hex(row->line[j] >> 4);
|
||||
row->render[i++] = nibble_to_hex(row->line[j] & 0x0f);
|
||||
} else {
|
||||
/* leave UTF-8 multibyte bytes untouched so terminal can render */
|
||||
row->render[i++] = row->line[j];
|
||||
}
|
||||
}
|
||||
|
||||
row->render[i] = '\0';
|
||||
row->rsize = i;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
erow_insert(int at, char *s, int len)
|
||||
{
|
||||
erow row;
|
||||
abuf *row = realloc(editor.row, sizeof(abuf)*(editor.nrows+1));
|
||||
|
||||
if (at < 0 || at > editor.nrows) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(erow_init(&row, len) == 0);
|
||||
memcpy(row.line, s, len);
|
||||
row.line[len] = 0;
|
||||
|
||||
editor.row = realloc(editor.row,
|
||||
sizeof(erow) * (editor.nrows + 1));
|
||||
assert(editor.row != NULL);
|
||||
assert(row != NULL);
|
||||
editor.row = row;
|
||||
|
||||
if (at < editor.nrows) {
|
||||
memmove(&editor.row[at + 1],
|
||||
&editor.row[at],
|
||||
sizeof(erow) * (editor.nrows - at));
|
||||
memmove(&editor.row[at+1], &editor.row[at],
|
||||
sizeof(abuf)*(editor.nrows-at));
|
||||
}
|
||||
|
||||
editor.row[at] = row;
|
||||
erow_update(&editor.row[at]);
|
||||
ab_init(&editor.row[at]);
|
||||
ab_append(&editor.row[at], s, len);
|
||||
editor.nrows++;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
erow_free(erow *row)
|
||||
{
|
||||
free(row->render);
|
||||
free(row->line);
|
||||
row->render = NULL;
|
||||
row->line = NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
killring_flush(void)
|
||||
{
|
||||
if (editor.killring != NULL) {
|
||||
erow_free(editor.killring);
|
||||
ab_free(editor.killring);
|
||||
free(editor.killring);
|
||||
editor.killring = NULL;
|
||||
}
|
||||
@@ -755,8 +672,8 @@ killring_yank(void)
|
||||
* Interpret '\n' as an actual newline() rather than inserting a raw 0x0A
|
||||
* byte, so yanked content preserves lines correctly.
|
||||
*/
|
||||
for (int i = 0; i < editor.killring->size; i++) {
|
||||
unsigned char ch = (unsigned char)editor.killring->line[i];
|
||||
for (int i = 0; i < (int)editor.killring->size; i++) {
|
||||
unsigned char ch = (unsigned char)editor.killring->b[i];
|
||||
if (ch == '\n') {
|
||||
newline();
|
||||
} else {
|
||||
@@ -769,34 +686,33 @@ killring_yank(void)
|
||||
void
|
||||
killring_start_with_char(unsigned char ch)
|
||||
{
|
||||
erow *row = NULL;
|
||||
abuf *row = NULL;
|
||||
|
||||
if (editor.killring != NULL) {
|
||||
erow_free(editor.killring);
|
||||
ab_free(editor.killring);
|
||||
free(editor.killring);
|
||||
editor.killring = NULL;
|
||||
}
|
||||
|
||||
editor.killring = malloc(sizeof(erow));
|
||||
editor.killring = malloc(sizeof(abuf));
|
||||
assert(editor.killring != NULL);
|
||||
assert(erow_init(editor.killring, 0) == 0);
|
||||
|
||||
/* append one char to empty killring without affecting editor.dirty */
|
||||
row = editor.killring;
|
||||
|
||||
row->line = realloc(row->line, row->size + 2);
|
||||
assert(row->line != NULL);
|
||||
row->line[row->size] = ch;
|
||||
row->b = realloc(row->b, row->size + 2);
|
||||
assert(row->b != NULL);
|
||||
row->b[row->size] = ch;
|
||||
row->size++;
|
||||
row->line[row->size] = '\0';
|
||||
row->dirty = 1;
|
||||
row->b[row->size] = '\0';
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
killring_append_char(unsigned char ch)
|
||||
{
|
||||
erow *row = NULL;
|
||||
abuf *row = NULL;
|
||||
|
||||
if (editor.killring == NULL) {
|
||||
killring_start_with_char(ch);
|
||||
@@ -804,30 +720,30 @@ killring_append_char(unsigned char ch)
|
||||
}
|
||||
|
||||
row = editor.killring;
|
||||
row->line = realloc(row->line, row->size + 2);
|
||||
assert(row->line != NULL);
|
||||
row->line[row->size] = ch;
|
||||
row->b = realloc(row->b, row->size + 2);
|
||||
assert(row->b != NULL);
|
||||
row->b[row->size] = ch;
|
||||
row->size++;
|
||||
row->line[row->size] = '\0';
|
||||
row->dirty = 1;
|
||||
row->b[row->size] = '\0';
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
killring_prepend_char(unsigned char ch)
|
||||
{
|
||||
abuf *row = NULL;
|
||||
|
||||
if (editor.killring == NULL) {
|
||||
killring_start_with_char(ch);
|
||||
return;
|
||||
}
|
||||
|
||||
erow *row = editor.killring;
|
||||
row->line = realloc(row->line, row->size + 2);
|
||||
assert(row->line != NULL);
|
||||
memmove(&row->line[1], &row->line[0], row->size + 1);
|
||||
row->line[0] = ch;
|
||||
row = editor.killring;
|
||||
row->b = realloc(row->b, row->size + 2);
|
||||
assert(row->b != NULL);
|
||||
memmove(&row->b[1], &row->b[0], row->size + 1);
|
||||
row->b[0] = ch;
|
||||
row->size++;
|
||||
row->dirty = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -924,7 +840,7 @@ kill_region(void)
|
||||
|
||||
while (editor.cury != cury) {
|
||||
while (!cursor_at_eol()) {
|
||||
killring_append_char(editor.row[editor.cury].line[editor.curx]);
|
||||
killring_append_char(editor.row[editor.cury].b[editor.curx]);
|
||||
move_cursor(ARROW_RIGHT, 0);
|
||||
}
|
||||
killring_append_char('\n');
|
||||
@@ -932,7 +848,7 @@ kill_region(void)
|
||||
}
|
||||
|
||||
while (editor.curx != curx) {
|
||||
killring_append_char(editor.row[editor.cury].line[editor.curx]);
|
||||
killring_append_char(editor.row[editor.cury].b[editor.curx]);
|
||||
move_cursor(ARROW_RIGHT, 0);
|
||||
}
|
||||
|
||||
@@ -990,7 +906,7 @@ void
|
||||
unindent_region(void)
|
||||
{
|
||||
int start_row, end_row, i, del;
|
||||
erow *row;
|
||||
abuf *row;
|
||||
|
||||
if (!editor.mark_set) {
|
||||
editor_set_status("Mark not set.");
|
||||
@@ -1022,20 +938,19 @@ unindent_region(void)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (row->line[0] == '\t') {
|
||||
if (row->b[0] == '\t') {
|
||||
row_delete_ch(row, 0);
|
||||
} else if (row->line[0] == ' ') {
|
||||
} else if (row->b[0] == ' ') {
|
||||
del = 0;
|
||||
|
||||
while (del < TAB_STOP && del < row->size &&
|
||||
row->line[del] == ' ') {
|
||||
while (del < TAB_STOP && del < (int)row->size &&
|
||||
row->b[del] == ' ') {
|
||||
del++;
|
||||
}
|
||||
|
||||
if (del > 0) {
|
||||
memmove(row->line, row->line + del, row->size - del + 1); /* +1 for NUL */
|
||||
memmove(row->b, row->b + del, row->size - del + 1); /* +1 for NUL */
|
||||
row->size -= del;
|
||||
row->dirty = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1147,8 +1062,8 @@ jump_to_position(int col, int row)
|
||||
|
||||
if (col < 0) {
|
||||
col = 0;
|
||||
} else if (col > editor.row[row].size) {
|
||||
col = editor.row[row].size;
|
||||
} else if (col > (int)editor.row[row].size) {
|
||||
col = (int)editor.row[row].size;
|
||||
}
|
||||
|
||||
editor.curx = col;
|
||||
@@ -1187,9 +1102,9 @@ cursor_at_eol(void)
|
||||
assert(editor.curx >= 0);
|
||||
assert(editor.cury >= 0);
|
||||
assert(editor.cury <= editor.nrows);
|
||||
assert(editor.curx <= editor.row[editor.cury].size);
|
||||
assert(editor.curx <= (int)editor.row[editor.cury].size);
|
||||
|
||||
return editor.curx == editor.row[editor.cury].size;
|
||||
return editor.curx == (int)editor.row[editor.cury].size;
|
||||
}
|
||||
|
||||
|
||||
@@ -1207,8 +1122,8 @@ find_next_word(void)
|
||||
move_cursor(ARROW_RIGHT, 1);
|
||||
}
|
||||
|
||||
if (iswordchar(editor.row[editor.cury].line[editor.curx])) {
|
||||
while (!isspace(editor.row[editor.cury].line[editor.curx]) && !
|
||||
if (iswordchar(editor.row[editor.cury].b[editor.curx])) {
|
||||
while (!isspace(editor.row[editor.cury].b[editor.curx]) && !
|
||||
cursor_at_eol()) {
|
||||
move_cursor(ARROW_RIGHT, 1);
|
||||
}
|
||||
@@ -1216,8 +1131,8 @@ find_next_word(void)
|
||||
return;
|
||||
}
|
||||
|
||||
if (isspace(editor.row[editor.cury].line[editor.curx])) {
|
||||
while (isspace(editor.row[editor.cury].line[editor.curx])) {
|
||||
if (isspace(editor.row[editor.cury].b[editor.curx])) {
|
||||
while (isspace(editor.row[editor.cury].b[editor.curx])) {
|
||||
move_cursor(ARROW_RIGHT, 1);
|
||||
}
|
||||
|
||||
@@ -1234,8 +1149,8 @@ delete_next_word(void)
|
||||
deletech(KILLRING_APPEND);
|
||||
}
|
||||
|
||||
if (iswordchar(editor.row[editor.cury].line[editor.curx])) {
|
||||
while (!isspace(editor.row[editor.cury].line[editor.curx]) && !
|
||||
if (iswordchar(editor.row[editor.cury].b[editor.curx])) {
|
||||
while (!isspace(editor.row[editor.cury].b[editor.curx]) && !
|
||||
cursor_at_eol()) {
|
||||
move_cursor(ARROW_RIGHT, 1);
|
||||
deletech(KILLRING_APPEND);
|
||||
@@ -1244,8 +1159,8 @@ delete_next_word(void)
|
||||
return;
|
||||
}
|
||||
|
||||
if (isspace(editor.row[editor.cury].line[editor.curx])) {
|
||||
while (isspace(editor.row[editor.cury].line[editor.curx])) {
|
||||
if (isspace(editor.row[editor.cury].b[editor.curx])) {
|
||||
while (isspace(editor.row[editor.cury].b[editor.curx])) {
|
||||
move_cursor(ARROW_RIGHT, 1);
|
||||
deletech(KILLRING_APPEND);
|
||||
}
|
||||
@@ -1265,7 +1180,7 @@ find_prev_word(void)
|
||||
move_cursor(ARROW_LEFT, 1);
|
||||
|
||||
while (cursor_at_eol() || isspace(
|
||||
editor.row[editor.cury].line[editor.curx])) {
|
||||
editor.row[editor.cury].b[editor.curx])) {
|
||||
if (editor.cury == 0 && editor.curx == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -1274,7 +1189,7 @@ find_prev_word(void)
|
||||
}
|
||||
|
||||
while (editor.curx > 0 && !isspace(
|
||||
editor.row[editor.cury].line[editor.curx - 1])) {
|
||||
editor.row[editor.cury].b[editor.curx - 1])) {
|
||||
move_cursor(ARROW_LEFT, 1);
|
||||
}
|
||||
}
|
||||
@@ -1295,7 +1210,7 @@ delete_prev_word(void)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isspace(editor.row[editor.cury].line[editor.curx - 1])) {
|
||||
if (!isspace(editor.row[editor.cury].b[editor.curx - 1])) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1303,7 +1218,7 @@ delete_prev_word(void)
|
||||
}
|
||||
|
||||
while (editor.curx > 0) {
|
||||
if (isspace(editor.row[editor.cury].line[editor.curx - 1])) {
|
||||
if (isspace(editor.row[editor.cury].b[editor.curx - 1])) {
|
||||
break;
|
||||
}
|
||||
deletech(KILLRING_PREPEND);
|
||||
@@ -1314,7 +1229,7 @@ delete_prev_word(void)
|
||||
void
|
||||
delete_row(int at)
|
||||
{
|
||||
erow *row = NULL;
|
||||
abuf *row = NULL;
|
||||
|
||||
if (at < 0 || at >= editor.nrows) {
|
||||
return;
|
||||
@@ -1333,15 +1248,15 @@ delete_row(int at)
|
||||
/* push raw bytes of the line */
|
||||
if (!editor.kill) {
|
||||
killring_start_with_char(
|
||||
(unsigned char)row->line[0]);
|
||||
for (int i = 1; i < row->size; i++) {
|
||||
(unsigned char)row->b[0]);
|
||||
for (int i = 1; i < (int)row->size; i++) {
|
||||
killring_append_char(
|
||||
(unsigned char)row->line[i]);
|
||||
(unsigned char)row->b[i]);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < row->size; i++) {
|
||||
for (int i = 0; i < (int)row->size; i++) {
|
||||
killring_append_char(
|
||||
(unsigned char)row->line[i]);
|
||||
(unsigned char)row->b[i]);
|
||||
}
|
||||
}
|
||||
killring_append_char('\n');
|
||||
@@ -1356,59 +1271,52 @@ delete_row(int at)
|
||||
}
|
||||
}
|
||||
|
||||
erow_free(&editor.row[at]);
|
||||
ab_free(&editor.row[at]);
|
||||
memmove(&editor.row[at],
|
||||
&editor.row[at + 1],
|
||||
sizeof(erow) * (editor.nrows - at - 1));
|
||||
sizeof(abuf) * (editor.nrows - at - 1));
|
||||
editor.nrows--;
|
||||
editor.dirty++;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
row_append_row(erow *row, char *s, int len)
|
||||
row_append_row(abuf *row, char *s, int len)
|
||||
{
|
||||
row->line = realloc(row->line, row->size + len + 1);
|
||||
assert(row->line != NULL);
|
||||
memcpy(&row->line[row->size], s, len);
|
||||
row->size += len;
|
||||
row->line[row->size] = '\0';
|
||||
row->dirty = 1;
|
||||
ab_append(row, s, len);
|
||||
editor.dirty++;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
row_insert_ch(erow *row, int at, int16_t c)
|
||||
row_insert_ch(abuf *row, int at, int16_t c)
|
||||
{
|
||||
/*
|
||||
* row_insert_ch just concerns itself with how to update a row.
|
||||
*/
|
||||
if ((at < 0) || (at > row->size)) {
|
||||
at = row->size;
|
||||
if ((at < 0) || (at > (int)row->size)) {
|
||||
at = (int)row->size;
|
||||
}
|
||||
assert(c > 0);
|
||||
|
||||
row->line = realloc(row->line, row->size + 2);
|
||||
assert(row->line != NULL);
|
||||
memmove(&row->line[at + 1], &row->line[at], row->size - at + 1);
|
||||
ab_resize(row, row->size + 2);
|
||||
memmove(&row->b[at + 1], &row->b[at], row->size - at + 1);
|
||||
row->b[at] = c & 0xff;
|
||||
row->size++;
|
||||
row->line[at] = c & 0xff;
|
||||
|
||||
row->dirty = 1;
|
||||
row->b[row->size] = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
row_delete_ch(erow *row, int at)
|
||||
row_delete_ch(abuf *row, int at)
|
||||
{
|
||||
if (at < 0 || at >= row->size) {
|
||||
if (at < 0 || at >= (int)row->size) {
|
||||
return;
|
||||
}
|
||||
|
||||
memmove(&row->line[at], &row->line[at + 1], row->size - at);
|
||||
memmove(&row->b[at], &row->b[at + 1], row->size - at);
|
||||
row->size--;
|
||||
row->dirty = 1;
|
||||
row->b[row->size] = 0;
|
||||
editor.dirty++;
|
||||
}
|
||||
|
||||
@@ -1428,7 +1336,6 @@ insertch(int16_t c)
|
||||
/* Inserting ends kill ring chaining. */
|
||||
editor.kill = 0;
|
||||
|
||||
/* Ensure we pass a non-negative byte value to avoid assert(c > 0). */
|
||||
row_insert_ch(&editor.row[editor.cury],
|
||||
editor.curx,
|
||||
(int16_t)(c & 0xff));
|
||||
@@ -1440,7 +1347,7 @@ insertch(int16_t c)
|
||||
void
|
||||
deletech(uint8_t op)
|
||||
{
|
||||
erow *row = NULL;
|
||||
abuf *row = NULL;
|
||||
unsigned char dch = 0;
|
||||
int prev = 0;
|
||||
|
||||
@@ -1454,7 +1361,7 @@ deletech(uint8_t op)
|
||||
|
||||
row = &editor.row[editor.cury];
|
||||
if (editor.curx > 0) {
|
||||
dch = (unsigned char)row->line[editor.curx - 1];
|
||||
dch = (unsigned char)row->b[editor.curx - 1];
|
||||
} else {
|
||||
dch = '\n';
|
||||
}
|
||||
@@ -1465,7 +1372,7 @@ deletech(uint8_t op)
|
||||
} else {
|
||||
editor.curx = editor.row[editor.cury - 1].size;
|
||||
row_append_row(&editor.row[editor.cury - 1],
|
||||
row->line,
|
||||
row->b,
|
||||
row->size);
|
||||
|
||||
prev = editor.no_kill;
|
||||
@@ -1572,7 +1479,7 @@ char
|
||||
p = buf;
|
||||
|
||||
for (j = 0; j < editor.nrows; j++) {
|
||||
memcpy(p, editor.row[j].line, editor.row[j].size);
|
||||
memcpy(p, editor.row[j].b, editor.row[j].size);
|
||||
p += editor.row[j].size;
|
||||
*p++ = '\n';
|
||||
}
|
||||
@@ -1816,12 +1723,12 @@ editor_find_callback(char* query, int16_t c)
|
||||
static int last_match = -1; /* row index of last match */
|
||||
static int direction = 1; /* 1 = forward, -1 = backward */
|
||||
static char last_query[128] = {0}; /* remember last successful query */
|
||||
erow *row;
|
||||
abuf *row;
|
||||
int saved_cx = editor.curx;
|
||||
int saved_cy = editor.cury;
|
||||
size_t qlen = strlen(query);
|
||||
char *match;
|
||||
int i;
|
||||
int i, skip;
|
||||
|
||||
if (c == '\r' || c == ESC_KEY || c == CTRL_KEY('g')) {
|
||||
last_match = -1;
|
||||
@@ -1851,7 +1758,7 @@ editor_find_callback(char* query, int16_t c)
|
||||
last_match = editor.cury;
|
||||
}
|
||||
|
||||
int current = last_match;
|
||||
int current = last_match - direction;
|
||||
int wrapped = 0;
|
||||
|
||||
for (i = 0; i < editor.nrows; i++) {
|
||||
@@ -1859,30 +1766,33 @@ editor_find_callback(char* query, int16_t c)
|
||||
|
||||
if (current >= editor.nrows) {
|
||||
current = 0;
|
||||
if (wrapped++) break;
|
||||
if (wrapped++) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (current < 0) {
|
||||
current = editor.nrows - 1;
|
||||
if (wrapped++) break;
|
||||
if (wrapped++) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
row = &editor.row[current];
|
||||
|
||||
/* Skip rendering search on raw bytes — use line[] but respect render offsets */
|
||||
row->dirty = 1;
|
||||
|
||||
char* search_start = row->render;
|
||||
if (current == start_row && direction == 1 && last_match == -1) {
|
||||
/* On first search forward: skip text before cursor */
|
||||
int skip = erow_render_to_cursor(row, start_col);
|
||||
char* search_start = row->b;
|
||||
if (current == start_row && direction == 1 && wrapped == 0) {
|
||||
skip = start_col;
|
||||
if (skip > (int)row->size) {
|
||||
skip = (int)row->size;
|
||||
}
|
||||
search_start += skip;
|
||||
}
|
||||
|
||||
match = strnstr(search_start, query, row->rsize - (search_start - row->render));
|
||||
match = strnstr(search_start, query, row->size - (search_start - row->b));
|
||||
if (match) {
|
||||
last_match = current;
|
||||
editor.cury = current;
|
||||
editor.curx = erow_cursor_to_render(row, match - row->render);
|
||||
editor.curx = erow_cursor_to_render(row, match - row->b);
|
||||
if (current == start_row && direction == 1 && last_match == -1) {
|
||||
editor.curx += start_col; /* adjust if we skipped prefix */
|
||||
}
|
||||
@@ -1945,7 +1855,7 @@ editor_openfile(void)
|
||||
|
||||
|
||||
int
|
||||
first_nonwhitespace(erow *row)
|
||||
first_nonwhitespace(abuf *row)
|
||||
{
|
||||
int pos;
|
||||
wchar_t wc;
|
||||
@@ -1958,20 +1868,20 @@ first_nonwhitespace(erow *row)
|
||||
|
||||
memset(&state, 0, sizeof(state));
|
||||
pos = editor.curx;
|
||||
if (pos > row->size) {
|
||||
if (pos > (int)row->size) {
|
||||
pos = row->size;
|
||||
}
|
||||
|
||||
while (pos < row->size) {
|
||||
if ((unsigned char)row->line[pos] < 0x80) {
|
||||
if (!isspace((unsigned char)row->line[pos])) {
|
||||
while (pos < (int)row->size) {
|
||||
if ((unsigned char)row->b[pos] < 0x80) {
|
||||
if (!isspace((unsigned char)row->b[pos])) {
|
||||
return pos;
|
||||
}
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
len = mbrtowc(&wc, &row->line[pos], row->size - pos, &state);
|
||||
len = mbrtowc(&wc, &row->b[pos], row->size - pos, &state);
|
||||
if (len == (size_t)-1 || len == (size_t)-2) {
|
||||
break;
|
||||
}
|
||||
@@ -1994,7 +1904,7 @@ first_nonwhitespace(erow *row)
|
||||
void
|
||||
move_cursor_once(int16_t c, int interactive)
|
||||
{
|
||||
erow *row;
|
||||
abuf *row;
|
||||
int reps = 0;
|
||||
|
||||
row = (editor.cury >= editor.nrows) ? NULL : &editor.row[editor.cury];
|
||||
@@ -2031,15 +1941,15 @@ move_cursor_once(int16_t c, int interactive)
|
||||
break;
|
||||
}
|
||||
|
||||
if (editor.curx < row->size) {
|
||||
if (editor.curx < (int)row->size) {
|
||||
editor.curx++;
|
||||
/* skip over UTF-8 continuation bytes */
|
||||
while (editor.curx < row->size &&
|
||||
((unsigned char)row->line[editor.curx] &
|
||||
while (editor.curx < (int)row->size &&
|
||||
((unsigned char)row->b[editor.curx] &
|
||||
0xC0) == 0x80) {
|
||||
editor.curx++;
|
||||
}
|
||||
} else if (editor.curx == row->size && editor.cury < editor.nrows - 1) {
|
||||
} else if (editor.curx == (int)row->size && editor.cury < editor.nrows - 1) {
|
||||
editor.cury++;
|
||||
editor.curx = 0;
|
||||
}
|
||||
@@ -2049,7 +1959,7 @@ move_cursor_once(int16_t c, int interactive)
|
||||
if (editor.curx > 0) {
|
||||
editor.curx--;
|
||||
while (editor.curx > 0 &&
|
||||
((unsigned char)row->line[editor.curx] &
|
||||
((unsigned char)row->b[editor.curx] &
|
||||
0xC0) == 0x80) {
|
||||
editor.curx--;
|
||||
}
|
||||
@@ -2059,7 +1969,7 @@ move_cursor_once(int16_t c, int interactive)
|
||||
|
||||
row = &editor.row[editor.cury];
|
||||
while (editor.curx > 0 &&
|
||||
((unsigned char)row->line[editor.curx] &
|
||||
((unsigned char)row->b[editor.curx] &
|
||||
0xC0) == 0x80) {
|
||||
editor.curx--;
|
||||
}
|
||||
@@ -2114,7 +2024,7 @@ move_cursor(int16_t c, int interactive)
|
||||
void
|
||||
newline(void)
|
||||
{
|
||||
erow *row = NULL;
|
||||
abuf *row = NULL;
|
||||
|
||||
if (editor.cury >= editor.nrows) {
|
||||
erow_insert(editor.cury, "", 0);
|
||||
@@ -2127,12 +2037,11 @@ newline(void)
|
||||
} else {
|
||||
row = &editor.row[editor.cury];
|
||||
erow_insert(editor.cury + 1,
|
||||
&row->line[editor.curx],
|
||||
&row->b[editor.curx],
|
||||
row->size - editor.curx);
|
||||
row = &editor.row[editor.cury];
|
||||
row->size = editor.curx;
|
||||
row->line[row->size] = '\0';
|
||||
row->dirty = 1;
|
||||
row->b[row->size] = '\0';
|
||||
editor.cury++;
|
||||
editor.curx = 0;
|
||||
}
|
||||
@@ -2760,9 +2669,12 @@ draw_rows(abuf *ab)
|
||||
{
|
||||
assert(editor.cols >= 0);
|
||||
|
||||
erow *row;
|
||||
abuf *row;
|
||||
char buf[editor.cols];
|
||||
char c;
|
||||
size_t j;
|
||||
int len, filerow, padding;
|
||||
int printed, rx;
|
||||
int y;
|
||||
|
||||
for (y = 0; y < editor.rows; y++) {
|
||||
@@ -2788,22 +2700,41 @@ draw_rows(abuf *ab)
|
||||
}
|
||||
} else {
|
||||
row = &editor.row[filerow];
|
||||
if (row->dirty) {
|
||||
erow_update(row);
|
||||
row->dirty = 0;
|
||||
j = 0;
|
||||
rx = printed = 0;
|
||||
|
||||
while (j < row->size && printed < editor.cols) {
|
||||
c = row->b[j];
|
||||
|
||||
if (rx < editor.coloffs) {
|
||||
if (c == '\t') rx += (TAB_STOP - (rx % TAB_STOP));
|
||||
else if (c < 0x20) rx += 3;
|
||||
else rx++;
|
||||
j++;
|
||||
continue;
|
||||
}
|
||||
|
||||
len = row->rsize - editor.coloffs;
|
||||
if (len < 0) {
|
||||
len = 0;
|
||||
if (c == '\t') {
|
||||
int sp = TAB_STOP - (rx % TAB_STOP);
|
||||
for (int k = 0; k < sp && printed < editor.cols; k++) {
|
||||
ab_appendch(ab, ' ');
|
||||
printed++;
|
||||
rx++;
|
||||
}
|
||||
|
||||
if (len > editor.cols) {
|
||||
len = editor.cols;
|
||||
} else if (c < 0x20) {
|
||||
char seq[4];
|
||||
snprintf(seq, sizeof(seq), "\\%02x", c);
|
||||
ab_append(ab, seq, 3);
|
||||
printed += 3;
|
||||
rx += 3;
|
||||
} else {
|
||||
ab_appendch(ab, c);
|
||||
printed++;
|
||||
rx++;
|
||||
}
|
||||
ab_append(ab,
|
||||
editor.row[filerow].render + editor.coloffs,
|
||||
len);
|
||||
j++;
|
||||
}
|
||||
len = printed;
|
||||
}
|
||||
ab_append(ab, ESCSEQ "K", 3);
|
||||
ab_append(ab, "\r\n", 2);
|
||||
@@ -2896,15 +2827,11 @@ draw_message_line(abuf *ab)
|
||||
void
|
||||
scroll(void)
|
||||
{
|
||||
erow *row = NULL;
|
||||
abuf *row = NULL;
|
||||
|
||||
editor.rx = 0;
|
||||
if (editor.cury < editor.nrows) {
|
||||
row = &editor.row[editor.cury];
|
||||
if (row->dirty == 1) {
|
||||
erow_update(row);
|
||||
}
|
||||
|
||||
editor.rx = erow_render_to_cursor(row, editor.curx);
|
||||
}
|
||||
|
||||
@@ -2951,7 +2878,7 @@ display_refresh(void)
|
||||
/* ab_append(&ab, ESCSEQ "1;2H", 7); */
|
||||
ab_append(&ab, ESCSEQ "?25h", 6);
|
||||
|
||||
kwrite(STDOUT_FILENO, ab.b, ab.len);
|
||||
kwrite(STDOUT_FILENO, ab.b, ab.size);
|
||||
ab_free(&ab);
|
||||
}
|
||||
|
||||
@@ -3031,7 +2958,7 @@ deathknell(void)
|
||||
fflush(stderr);
|
||||
|
||||
if (editor.killring != NULL) {
|
||||
erow_free(editor.killring);
|
||||
ab_free(editor.killring);
|
||||
free(editor.killring);
|
||||
editor.killring = NULL;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user