sled

Једноставни уређивач текста
Дневник | Датотеке | Референце | ПРОЧИТАЈМЕ | ЛИЦЕНЦА

чување 137a5bc48e28f2d2877a34b833e42d2260f8c9c7
родитељ fdf233f7a344430928fbdf6231ede94c9a1f654e
Аутор: Страхиња Радић <contact@strahinja.org>
Датум:   Mon, 21 Feb 2022 15:06:48 +0100

Fix goto line #0, moving up in empty file; only recalculate screen sizes on resize event; allow creating files

Signed-off-by: Страхиња Радић <contact@strahinja.org>

Diffstat:
MTODO | 16++++++++--------
Abuild-command.sh | 1+
Msled.c | 152++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
измењених датотека: 3, додавања: 125(+), брисања: 44(-)

diff --git a/TODO b/TODO @@ -1,22 +1,22 @@ TODO ==== - [ ] Fix goto line #0 + [ ] Copy/paste? - [ ] Fix moving up in empty file + [ ] Add vi H/L - [ ] Copy/paste? + [ ] Add vi V - [ ] Allow creating files (error out if directory not writeable, only + [x] Allow creating files (error out if directory not writeable, only create file when saving) - [ ] Add handling of terminal resize event + [x] Add handling of terminal resize event - [ ] Add vi H/L + [/] Test for binary when opening? (Why?) - [ ] Add vi V + [x] Fix goto line #0 - [ ] Test for binary when opening? + [x] Fix moving up in empty file [x] Write operation; create backup files diff --git a/build-command.sh b/build-command.sh @@ -0,0 +1 @@ +SLED_CC='gcc -ggdb -fsanitize=address -fno-omit-frame-pointer -lrt -static-libgcc' redo rebuild -j10 diff --git a/sled.c b/sled.c @@ -131,6 +131,8 @@ go_to_line_callback(struct DrawState* state) strcpy(state->error, errors[ERR_INVALID_NUM]); else if (lineno + 1 > state->rows_count) move_bottom(state); + else if (lineno < 1) + move_top(state); else { state->row = lineno - 1; @@ -173,6 +175,25 @@ quit_callback(struct DrawState* state, struct tb_event* ev) } int +create_file(struct DrawState* state) +{ + struct BufferLine* newchunk = NULL; + + newchunk = calloc(ALLOC_DELTA, sizeof(struct BufferLine)); + if (!newchunk) + return LOAD_ERR_CANT_ALLOC; + for (size_t row = 0; row < ALLOC_DELTA; row++) + init_bufferline(newchunk + row); + state->buffer = newchunk; + state->buffer_size = ALLOC_DELTA; + state->rows_count = 1; + state->row = 0; + state->dirty = 1; + + return LOAD_ERR_NONE; +} + +int load_file(struct DrawState* state, long* lineno, long* col) { struct BufferLine* newchunk = NULL; @@ -183,6 +204,8 @@ load_file(struct DrawState* state, long* lineno, long* col) newchunk = calloc(ALLOC_DELTA, sizeof(struct BufferLine)); if (!newchunk) return LOAD_ERR_CANT_ALLOC; + for (size_t row = 0; row < ALLOC_DELTA; row++) + init_bufferline(newchunk + row); strcpy(state->action, actions[ACT_READING]); redraw_status(state); @@ -233,6 +256,21 @@ load_file(struct DrawState* state, long* lineno, long* col) fclose(input); *state->action = 0; + if (state->rows_count == 0) + { + line = state->buffer; + if (!line->text) + { + uint32_t* newtext = NULL; + newtext = calloc(MAXBUFLINE, sizeof(uint32_t)); + if (!newtext) + return LOAD_ERR_CANT_ALLOC; + line->length = 0; + line->text = newtext; + } + state->rows_count++; + } + return LOAD_ERR_NONE; } @@ -242,6 +280,7 @@ save_file(struct DrawState* state) FILE* output = NULL; char* buf = NULL; char* backup_filename = NULL; + struct stat st; if (!(buf = calloc(MAXBUFLINE, 1))) return SAVE_ERR_CANT_ALLOC; @@ -251,19 +290,26 @@ save_file(struct DrawState* state) strcpy(state->action, actions[ACT_WRITING]); redraw_status(state); - strcpy(backup_filename, state->filename); - strcat(backup_filename, "~"); - rename(state->filename, backup_filename); + if (stat(state->filename, &st) != -1) + { + strcpy(backup_filename, state->filename); + strcat(backup_filename, "~"); + rename(state->filename, backup_filename); + } if (!(output = fopen(state->filename, "wt"))) return SAVE_ERR_CANT_OPEN_FILE; + if (state->rows_count == 1 && state->buffer[0].length == 0) + goto save_file_cleanup; + for (size_t row = 0; row < state->rows_count; row++) { unicode_string_to_u8(buf, state->buffer[row].text, MAXBUFLINE); fprintf(output, "%s\n", buf); } +save_file_cleanup: fclose(output); free(backup_filename); free(buf); @@ -364,8 +410,9 @@ paste_paste_buffer_to_input(struct DrawState* state) int move_up(struct DrawState* state) { - if (state->row > 0) - state->row--; + if (state->row == 0) + return 0; + state->row--; if (state->first_shown_row > state->row) state->first_shown_row = state->row; if (state->saved_column == -1) @@ -600,9 +647,10 @@ move_bottom(struct DrawState* state) int move_end(struct DrawState* state) { - size_t len = state->buffer[state->row].length; + size_t len; size_t dlen; + len = state->buffer[state->row].length; state->column = len; dlen = display_length(state, state->buffer[state->row].text, state->column); @@ -622,7 +670,6 @@ move_end(struct DrawState* state) int move_page_up(struct DrawState* state) { - *state->error = 0; if (state->row > state->maxy - 2) { state->row -= state->maxy - 2; @@ -642,11 +689,10 @@ move_page_up(struct DrawState* state) int move_page_down(struct DrawState* state) { - *state->error = 0; - if (state->row < state->rows_count - state->maxy - 2) + if (state->row + state->maxy - 2 < state->rows_count) { state->row += state->maxy - 2; - if (state->row - state->first_shown_row > state->maxy - 2) + if (state->row > state->first_shown_row + state->maxy - 2) state->first_shown_row = state->row - (state->maxy - 2); } else @@ -914,8 +960,10 @@ insert_line(struct DrawState* state) return 0; } state->buffer = newchunk; + for (size_t row = state->buffer_size - ALLOC_DELTA; + row < state->buffer_size; row++) + init_bufferline(line); line = state->buffer + state->buffer_size - ALLOC_DELTA; - init_bufferline(line); } if (!line->text) { @@ -930,12 +978,11 @@ insert_line(struct DrawState* state) state->rows_count++; for (size_t i = state->rows_count - 1; i > state->row + 1; i--) { - u32_strncpy(state->buffer[i].text, state->buffer[i - 1].text, - MAXBUFLINE); + u32_strcpy(state->buffer[i].text, state->buffer[i - 1].text); state->buffer[i].length = state->buffer[i - 1].length; } - u32_strncpy(state->buffer[state->row + 1].text, - state->buffer[state->row].text + state->column, MAXBUFLINE); + u32_strcpy(state->buffer[state->row + 1].text, + state->buffer[state->row].text + state->column); state->buffer[state->row + 1].length = u32_strlen(state->buffer[state->row + 1].text); state->buffer[state->row].text[state->column] = 0; @@ -1564,6 +1611,10 @@ main(int argc, char** argv) struct DrawState state; char filename[MAXPATH]; struct stat st; + long lineno = 1; + long col = 1; + int result; + int recalculate_size = 1; *error = 0; *action = 0; @@ -1592,35 +1643,63 @@ main(int argc, char** argv) return print_error(EINVAL, "No filename given"); } - if (stat(filename, &st) == -1 - || access(filename, F_OK | R_OK | W_OK) == -1) + init_drawstate(&state, error, action, filename, prompt); + + result = stat(filename, &st); + if (result == -1) { - perror(program_name); - return errno; + char dirname[MAXPATH]; + char* slash = NULL; + + if (errno != ENOENT) + goto file_error; + + strcpy(dirname, filename); + if ((slash = strrchr(dirname, '/'))) + *slash = 0; + else + { + *dirname = '.'; + *(dirname + 1) = 0; + } + + result = access(dirname, F_OK | R_OK | W_OK); + if (result == -1) + goto file_error; + + result = create_file(&state); + switch (result) + { + case LOAD_ERR_CANT_ALLOC: + return print_error(result, + "Allocation failed (out of memory?)"); + default:; + } + goto init_termbox; } + if (access(filename, F_OK | R_OK | W_OK) == -1) + goto file_error; + if (!S_ISREG(st.st_mode)) return print_error(EINVAL, "Is not a regular file"); - init_drawstate(&state, error, action, filename, prompt); - - long lineno = 1; - long col = 1; - int result = load_file(&state, &lineno, &col); + result = load_file(&state, &lineno, &col); switch (result) { case LOAD_ERR_CANT_ALLOC: return print_error(result, "Allocation failed (out of memory?)"); case LOAD_ERR_CANT_OPEN_FILE: return print_error(result, "Cannot open file `%s'", filename); - case LOAD_ERR_NONE: - if (*error) - return print_error(1, error); - break; - default: - return print_error(1, "Unknown error (%d)", result); + default:; } + goto init_termbox; + +file_error: + perror(program_name); + return errno; +init_termbox: tb_init(); *error = 0; state.maxx = 0; @@ -1629,20 +1708,21 @@ main(int argc, char** argv) { tb_clear(); - int maxx = tb_width(); - if (maxx != state.maxx) + if (recalculate_size) { - state.maxx = maxx; + state.maxx = tb_width(); state.help_width = calculate_help_width(&state); state.input_dialog_width = calculate_input_dialog_width(&state); + state.maxy = tb_height(); } - state.maxy = tb_height(); - if (!draw(&state)) strcpy(state.error, errors[ERR_CANT_ALLOC]); tb_present(); - if (tb_poll_event(&ev) == TB_OK && ev.type == TB_EVENT_KEY) + result = tb_poll_event(&ev); + if (result == TB_OK && ev.type == TB_EVENT_RESIZE) + recalculate_size = 1; + else if (result == TB_OK && ev.type == TB_EVENT_KEY) handle_key_event(&ev, &state); } tb_shutdown();