sled

Једноставни уређивач текста
git clone https://git.sr.ht/~strahinja/sled
Дневник | Датотеке | Референце | ПРОЧИТАЈМЕ | ЛИЦЕНЦА

чување 2272c3e076174c2187013a283fa3a8a651b76135
родитељ 212c1fe559648a52b6c209adff3813d4285fdaad
Аутор: Страхиња Радић <contact@strahinja.org>
Датум:   Mon,  1 Jul 2024 14:16:54 +0200

Wrapping, allocation and line number drawing bugfixes

Diffstat:
Mdraw.c | 32+++++++++++++++++++-------------
Mdraw.h | 5+++--
Msled.c | 137++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
измењених датотека: 3, додавања: 120(+), брисања: 54(-)

diff --git a/draw.c b/draw.c @@ -372,7 +372,7 @@ draw_screen(const struct DrawState* state) ? numbuf_end - line_numbers_width : numbuf; draw_string(0, cy, LINENO_FG, LINENO_BG, - pnumbuf, numbuf_end - numbuf, + pnumbuf, numbuf_end - numbuf + 1, line_numbers_width, 0, 0, RIGHT, 0, 1, NULL, 0, 0, 0, 0, 0, 0); } @@ -507,11 +507,13 @@ void format_filename(char* result, ssize_t result_size, const char* format, const ssize_t seg_size, const struct DrawState* state) { - char* basename = NULL; + char* basename = NULL; + const char* pbase = NULL; if (!result || seg_size < 4) return; - basename = strdup(u8_basename(state->filename)); + pbase = u8_basename(state->filename); + basename = strndup(pbase, strlen(pbase) + 1); if ((ssize_t)(u8_strlen(basename) + 2) >= seg_size) { @@ -572,33 +574,37 @@ format_position(char* result, ssize_t result_size, const char* format, } void -free_bufferline(struct BufferLine* bl, const int free_text) +free_bufferline(struct BufferLine* bl) { if (!bl) return; - if (free_text) - free(bl->text); + free(bl->text); bl->text = NULL; + bl->size = 0; bl->length = 0; bl->fg = 0; bl->bg = 0; } void -free_drawstate(struct DrawState* state, int skip_paste_free) +free_drawstate(struct DrawState* state, const int skip_paste_free, + const int skip_filename_free) { ssize_t row = 0; for (row = 0; row < state->buffer_size; row++) - free_bufferline(state->buffer + row, 1); - free(state->backup_filename); - free(state->real_filename); - free(state->filename); - free(state->orig_real_filename); + free_bufferline(state->buffer + row); + if (!skip_filename_free) + { + free(state->backup_filename); + free(state->real_filename); + free(state->filename); + free(state->orig_real_filename); + } free(state->buffer); if (!skip_paste_free) { for (row = 0; row < state->paste_size; row++) - free_bufferline(state->paste + row, 1); + free_bufferline(state->paste + row); free(state->paste); } free(state->input); diff --git a/draw.h b/draw.h @@ -132,8 +132,9 @@ void format_mode(char* result, ssize_t result_size, const char* format, const ssize_t seg_size, const struct DrawState* state); void format_position(char* result, ssize_t result_size, const char* format, const ssize_t seg_size, const struct DrawState* state); -void free_bufferline(struct BufferLine* bl, const int free_text); -void free_drawstate(struct DrawState* state, int skip_paste_free); +void free_bufferline(struct BufferLine* bl); +void free_drawstate(struct DrawState* state, const int skip_paste_free, + const int skip_filename_free); void init_bufferline(struct BufferLine* bl); void init_coord(struct Coord* c, const int col, const int row); void init_drawstate(struct DrawState* state, char* error, char* action, diff --git a/sled.c b/sled.c @@ -419,6 +419,7 @@ erase_line(struct DrawState* state) return 0; } free(state->buffer[state->coord.row].text); + state->buffer[state->coord.row].text = NULL; for (ssize_t row = state->coord.row; row < state->rows_count - 1; row++) { current = state->buffer + row; @@ -426,7 +427,7 @@ erase_line(struct DrawState* state) current->size = state->buffer[row + 1].size; current->length = state->buffer[row + 1].length; } - free_bufferline(&state->buffer[state->rows_count - 1], 0); + free_bufferline(&state->buffer[state->rows_count - 1]); if ((state->coord.row + 1) == state->rows_count) state->coord.row--; position_to(state, state->coord.row, 0); @@ -1278,7 +1279,7 @@ load_file(struct DrawState* state) if (eol) *eol = 0; - if (state->rows_count == state->buffer_size) + if (state->rows_count + 1 == state->buffer_size) { state->buffer_size += ALLOC_DELTA; newchunk = realloc(state->buffer, @@ -1874,9 +1875,9 @@ reread_file(struct DrawState* state) int result; char* temp = NULL; - free_drawstate(state, 1); + free_drawstate(state, 1, 1); init_drawstate(state, state->error, state->action, state->filename, - state->prompt, 1); + state->prompt, 1, 1); result = load_file(state); switch (result) @@ -2204,7 +2205,7 @@ simple_insert_line(struct DrawState* state) uint32_t* ptext = NULL; char* temp = NULL; - if (state->rows_count == state->buffer_size) + if (state->rows_count + 1 == state->buffer_size) { state->buffer_size += ALLOC_DELTA; newchunk = realloc(state->buffer, @@ -2235,10 +2236,16 @@ simple_insert_line(struct DrawState* state) state->buffer[i - 1].size, simple_insert_line_error); state->buffer[i].length = state->buffer[i - 1].length; } - U32_SAFE_COPY(state->buffer[state->coord.row + 1].text, ptext, - state->buffer[state->coord.row + 1].size, - state->buffer[state->coord.row].text + state->coord.col, - state->buffer[state->coord.row].size, simple_insert_line_error); + ENSURE_SIZE(state->buffer[state->coord.row + 1].text, ptext, + state->buffer[state->coord.row + 1].size, LINE_DEFAULT, + LINE_DEFAULT, simple_insert_line_error, uint32_t); + *state->buffer[state->coord.row + 1].text = 0; + if (state->coord.col < state->buffer[state->coord.row].length) + U32_SAFE_COPY(state->buffer[state->coord.row + 1].text, ptext, + state->buffer[state->coord.row + 1].size, + state->buffer[state->coord.row].text + state->coord.col, + state->buffer[state->coord.row].size, + simple_insert_line_error); state->buffer[state->coord.row + 1].length = state->buffer[state->coord.row].length - state->coord.col; @@ -2280,7 +2287,7 @@ simple_join_lines(struct DrawState* state) state->buffer[i + 1].size, simple_join_lines_error); state->buffer[i].length = state->buffer[i + 1].length; } - free_bufferline(&state->buffer[state->rows_count - 1], 1); + free_bufferline(&state->buffer[state->rows_count - 1]); state->rows_count--; state->dirty = 1; return; @@ -2444,6 +2451,7 @@ wrap_para(struct DrawState* state) int bcol; int dlen; int col; + int added_blank = 0; if (!enable_wrap) goto wrap_not_enabled; @@ -2469,8 +2477,8 @@ wrap_para(struct DrawState* state) } if (cur_row == 0) start_row = cur_row; - for (cur_row = state->coord.row; cur_row < state->rows_count; - cur_row++) + for (cur_row = state->coord.row; + cur_row + 1 < state->rows_count; cur_row++) if (state->buffer[cur_row].length == 0 || !u32_has_nonblanks( state->buffer[cur_row].text)) @@ -2478,6 +2486,8 @@ wrap_para(struct DrawState* state) end_row = cur_row - 1; break; } + if (cur_row + 1 == state->rows_count) + end_row = cur_row - 1; } cur_row = start_row; @@ -2488,10 +2498,14 @@ wrap_next_line: state->coord.row = cur_row; dlen = display_length(current->text, current->length); - while (dlen < wrap_width && u32_has_nonblanks(next->text)) + while (cur_row + 1 < state->rows_count && dlen < wrap_width + && u32_has_nonblanks(next->text)) { /* Insert space to avoid joining ending and beginning words */ - if (!u32_is_word_boundary(current->text[current->length - 1], 1)) + if (current->length > 0 + && !u32_is_word_boundary(current->text[current->length + - 1], + 1)) { ENSURE_SIZE(current->text, ptext, current->size, current->length + 2, current->length + 2, @@ -2502,6 +2516,8 @@ wrap_next_line: } simple_join_lines(state); + current = &state->buffer[cur_row]; + next = &state->buffer[cur_row + 1]; if (sel) { @@ -2515,6 +2531,7 @@ wrap_next_line: while (dlen >= wrap_width) { + int tdlen; bcol = buffer_length(current->text, wrap_width); while (bcol > 0 && !u32_is_word_boundary(current->text[bcol - 1], 1)) @@ -2531,8 +2548,11 @@ wrap_next_line: cur_row++; state->coord.row++; current = &state->buffer[cur_row]; + next = &state->buffer[cur_row + 1]; - /* Remove the space between the two words at split */ + /* - Remove the space between the two words at split + * - current is the new current (the rest of the line + * after split) */ if (u32_is_word_boundary(current->text[0], 1)) { *current->text = 0; @@ -2548,20 +2568,20 @@ wrap_next_line: = state->buffer[state->sel_end.row].length; } end_row++; - if (cur_row == state->rows_count) + if (cur_row + 1 == state->rows_count) break; - /* If the line in block is < wrap_width, join it with next */ - next = &state->buffer[cur_row + 1]; - if (u32_has_nonblanks(next->text) - && display_length(current->text, current->length) - < wrap_width) + /* If the rest of the line is still in block and is + * < wrap_width, join it with next (the new next) */ + tdlen = display_length(current->text, current->length); + if (u32_has_nonblanks(next->text) && tdlen < wrap_width) { /* Add space if needed to avoid joining words */ - if (!u32_is_word_boundary(current->text[current->length - - 1], - 1)) + /* clang-format off */ + if (!u32_is_word_boundary( + current->text[current->length - 1], 1)) { + /* clang-format on */ ENSURE_SIZE(current->text, ptext, current->size, current->length + 2, current->length + 2, wrap_alloc_error, @@ -2581,22 +2601,63 @@ wrap_next_line: .length; } end_row--; + + dlen = display_length(current->text, current->length); + if (dlen < wrap_width) + continue; + + /* One more split needed for the rest of the line (new + * current) */ + bcol = buffer_length(current->text, wrap_width); + while (bcol > 0 + && !u32_is_word_boundary(current->text[bcol - 1], + 1)) + bcol--; + if (bcol == 0) + break; + ENSURE_SIZE(current->text, ptext, current->size, + current->length + 1, + current->length + LINE_ALLOC_DELTA, + wrap_alloc_error, uint32_t); + state->coord.col = bcol - 1; + + simple_insert_line(state); + end_row++; + + /* Remove the space between the two words at split */ + if (u32_is_word_boundary(next->text[0], 1)) + { + *next->text = 0; + for (col = 0; col < next->length; col++) + next->text[col] = next->text[col + 1]; + next->length--; + } } - if (cur_row == MIN((end_row + 1), state->rows_count)) + if (cur_row == MIN((end_row), state->rows_count)) break; - bcol = buffer_length(current->text, wrap_width); - while (bcol > 0 - && !u32_is_word_boundary(current->text[bcol - 1], 1)) - bcol--; - if (bcol == 0) - break; dlen = display_length(current->text, current->length); } cur_row++; - if (cur_row < MIN((end_row + 1), state->rows_count)) + if (added_blank) + goto wrap_finish; + if (cur_row == state->rows_count) + { + added_blank = 1; + move_end(state); + simple_insert_line(state); + move_up(state); goto wrap_next_line; + } + else if (cur_row < MIN((end_row + 1), state->rows_count)) + goto wrap_next_line; + +wrap_finish: + if (added_blank) + { + erase_line(state); + } if (sel) position_to_selection_end(state); @@ -2764,7 +2825,7 @@ main(int argc, char** argv) return print_error(EINVAL, "No filename given"); } - init_drawstate(&state, error, action, filename, prompt, 0); + init_drawstate(&state, error, action, filename, prompt, 0, 0); #ifdef __OpenBSD__ if (unveil(state.filename, "rwc") < 0) @@ -2874,9 +2935,9 @@ main(int argc, char** argv) else goto errno_set; - if (!(state.backup_filename = calloc(limits[L_PATH_MAX], 1))) + if (!(state.backup_filename = malloc(limits[L_PATH_MAX]))) { - perror(PROGRAM_NAME ": calloc"); + perror(PROGRAM_NAME ": malloc"); goto main_cleanup; } @@ -3015,10 +3076,8 @@ init_termbox: tb_shutdown(); if (state.error && *state.error) { - if (errno != 0) - perror(PROGRAM_NAME); print_error(1, state.error); - result = 1; + goto errno_set; } goto main_cleanup; @@ -3028,7 +3087,7 @@ errno_set: /* FALLTHROUGH */ main_cleanup: - free_drawstate(&state, 0); + free_drawstate(&state, 0, 0); free(wd); free(dir); free(rfn);