чување 2272c3e076174c2187013a283fa3a8a651b76135
родитељ 212c1fe559648a52b6c209adff3813d4285fdaad
Аутор: Страхиња Радић <contact@strahinja.org>
Датум: Mon, 1 Jul 2024 14:16:54 +0200
Wrapping, allocation and line number drawing bugfixes
Diffstat:
| M | draw.c | | | 32 | +++++++++++++++++++------------- |
| M | draw.h | | | 5 | +++-- |
| M | sled.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);