sled

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

чување 8b6662d7a94f3114542dc1ca40824aa0cb2da23f
родитељ 3c86365a3ce4610d63d4d58eda98ce3fc31bffe7
Аутор: Страхиња Радић <sr@strahinja.org>
Датум:   Wed, 10 Jul 2024 23:51:42 +0200

Dynamically compute max line number width at runtime

Diffstat:
MTODO | 2+-
Mconfig.def.h | 1-
Mdraw.c | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Mdraw.h | 3+++
Msled.c | 17+++++++++++++----
измењених датотека: 5, додавања: 78(+), брисања: 29(-)

diff --git a/TODO b/TODO @@ -6,7 +6,7 @@ TODO [ ] Add shortcut key which toggles showing line numbers at runtime (default state still configured in config.h) -[ ] (vis-like:) Dynamically compute max line number at runtime (number +[x] (vis-like:) Dynamically compute max line number at runtime (number of digits in the number of the last line drawn on screen) [~] Code optimization (struct coord...) diff --git a/config.def.h b/config.def.h @@ -54,7 +54,6 @@ const char* backup_suffix = "~"; const int create_backups = 1; const int enable_wrap = 1; const int line_numbers = 0; /* draw line numbers? */ -const int line_numbers_width = 6; /* number of glyphs for line numbers */ /* - ideally, wrap_width + line_numbers_width <= 80 */ /* - wrap width of 72 is recommended on https://useplaintext.email/ */ const int wrap_width = 72; diff --git a/draw.c b/draw.c @@ -75,6 +75,18 @@ const char* actions[] = { [ACT_READING] = "Reading...", [ACT_WRAPPING] = "Wrapping..." }; +const struct { + ssize_t boundary; + int width; +} number_widths[] = { + { .boundary = 9999999, .width = 8 }, + { .boundary = 999999, .width = 7 }, + { .boundary = 99999, .width = 6 }, + { .boundary = 9999, .width = 5 }, + { .boundary = 999, .width = 4 }, + { .boundary = 99, .width = 3 }, + { .boundary = 9, .width = 2 } +}; const char* go_to_dialog_title = "Go to line"; const char* replace_dialog_title = "Replace with"; const char* search_dialog_title = "Search text"; @@ -130,6 +142,23 @@ calculate_input_dialog_width(const struct DrawState* state) : state->maxx - 2; } +int +calculate_line_numbers_width(const struct DrawState* state) +{ + ssize_t last_row; + int i; + last_row = MIN(state->rows_count, + state->first_shown.row + state->maxy - 1); + i = 0; + while ((size_t)i < LEN(number_widths)) + { + if (last_row > number_widths[i].boundary) + return number_widths[i].width; + i++; + } + return 1; +} + /* Calculates display length of a buffer line. * max_index = the buffer index up to which the length is calculated */ @@ -292,6 +321,25 @@ draw_input_dialog(const struct DrawState* state) } void +draw_line_number(const struct DrawState* state, const int i, const int cy) +{ + char numbuf[LINE_DEFAULT]; + char* numbuf_end = NULL; + char* pnumbuf = NULL; + snprintf(numbuf, LINE_DEFAULT, "%d", i + 1); + numbuf_end = strchr(numbuf, 0); + if (numbuf_end) + { + pnumbuf = numbuf_end - numbuf > state->line_numbers_width + ? numbuf_end - state->line_numbers_width + : numbuf; + draw_string(0, cy, LINENO_FG, LINENO_BG, pnumbuf, + numbuf_end - numbuf + 1, state->line_numbers_width, 0, + 0, RIGHT, 0, 1, NULL, 0, 0, 0, 0, 0, 0); + } +} + +void draw_rect(const int startx, const int endx, const int starty, const int endy, const uint16_t fg, const uint16_t bg) { @@ -323,7 +371,7 @@ draw_screen(const struct DrawState* state) maxx = state->maxx; if (line_numbers) - maxx -= line_numbers_width; + maxx -= state->line_numbers_width; if (state->rows_count == 0) return 0; @@ -357,29 +405,12 @@ draw_screen(const struct DrawState* state) sei = sec; } } - if (line_numbers) - { - char numbuf[LINE_DEFAULT]; - char* numbuf_end = NULL; - char* pnumbuf = NULL; - snprintf(numbuf, LINE_DEFAULT, "%d", i + 1); - numbuf_end = strchr(numbuf, 0); - if (numbuf_end) - { - pnumbuf = numbuf_end - numbuf - > line_numbers_width - ? numbuf_end - line_numbers_width - : numbuf; - draw_string(0, cy, LINENO_FG, LINENO_BG, - pnumbuf, numbuf_end - numbuf + 1, - line_numbers_width, 0, 0, RIGHT, 0, 1, - NULL, 0, 0, 0, 0, 0, 0); - } - } + draw_line_number(state, i, cy); if (current->text) - u32_draw_string(line_numbers ? line_numbers_width + 2 - : 0, + u32_draw_string(line_numbers + ? state->line_numbers_width + 2 + : 0, cy, TEXT_FG, TEXT_BG, current->text, maxx, maxx, 0, 0, CENTER, state->first_shown.col, 0, state->search, SEARCH_FG, SEARCH_BG, ssi, sei, @@ -389,7 +420,7 @@ draw_screen(const struct DrawState* state) } tb_set_cursor(line_numbers - ? line_numbers_width + 2 + state->display_column + ? state->line_numbers_width + 2 + state->display_column - state->first_shown.col : state->display_column - state->first_shown.col, state->coord.row - state->first_shown.row); @@ -683,12 +714,19 @@ init_drawstate(struct DrawState* state, char* error, char* action, } void +recalculate_line_numbers(struct DrawState* state) +{ + state->line_numbers_width = calculate_line_numbers_width(state); +} + +void recalculate_size(struct DrawState* state) { state->maxx = tb_width(); state->help_width = calculate_help_width(state); state->input_dialog_width = calculate_input_dialog_width(state); state->maxy = tb_height(); + recalculate_line_numbers(state); } void diff --git a/draw.h b/draw.h @@ -77,6 +77,7 @@ struct DrawState { int saved_column; /* display coordinate */ int help_width; /* display parameter */ int input_dialog_width; /* display parameter */ + int line_numbers_width; struct BufferLine* paste; ssize_t paste_count; ssize_t paste_size; @@ -119,6 +120,7 @@ void draw_box(const int startx, const int endx, const int starty, const int endy, const uint16_t fg, const uint16_t bg); int draw_help(const struct DrawState* state); int draw_input_dialog(const struct DrawState* state); +void draw_line_numbers(const struct DrawState* state); void draw_rect(const int startx, const int endx, const int starty, const int endy, const uint16_t fg, const uint16_t bg); int draw_screen(const struct DrawState* state); @@ -143,6 +145,7 @@ void init_coord(struct Coord* c, const int col, const int row); void init_drawstate(struct DrawState* state, char* error, char* action, char* filename, char* prompt, const int skip_paste_and_mode_init, const int skip_filenames_init); +void recalculate_line_numbers(struct DrawState* state); void recalculate_size(struct DrawState* state); void redraw_status(struct DrawState* state); void u32_draw_string(const int x, const int y, const uint16_t fg, diff --git a/sled.c b/sled.c @@ -189,8 +189,9 @@ create_file(struct DrawState* state) state->buffer = newchunk; state->buffer_size = ALLOC_DELTA; state->rows_count = 1; - state->coord.row = 0; - state->dirty = 1; + recalculate_line_numbers(state); + state->coord.row = 0; + state->dirty = 1; return LOAD_ERR_NONE; } @@ -431,6 +432,7 @@ erase_line(struct DrawState* state) position_to(state, state->coord.row, 0); state->rows_count--; state->dirty = 1; + recalculate_line_numbers(state); return 0; erase_line_error: @@ -515,6 +517,7 @@ erase_selection(struct DrawState* state) state->buffer[row].length = 0; } state->rows_count -= ser - ssr; + recalculate_line_numbers(state); } free(buf); state->dirty = 1; @@ -1330,6 +1333,7 @@ load_file(struct DrawState* state) state->rows_count++; free(input_line); + recalculate_line_numbers(state); return LOAD_ERR_NONE; load_file_alloc_error: @@ -1675,7 +1679,8 @@ static void position_to(struct DrawState* state, const int row, const int column) { ssize_t dlen; - + int old_first_shown_row; + old_first_shown_row = state->first_shown.row; if (row != state->coord.row) { state->coord.row = row; @@ -1746,6 +1751,8 @@ position_to(struct DrawState* state, const int row, const int column) if (state->first_shown.col + (state->maxx - 1) < state->display_column) state->first_shown.col = state->display_column - (state->maxx - 1); + if (old_first_shown_row != state->first_shown.row) + recalculate_line_numbers(state); if (IN(state->mode, M_SELECTION)) assign_coord(&state->sel_end, state->coord); @@ -2263,6 +2270,7 @@ simple_insert_line(struct DrawState* state) state->buffer[state->coord.row].length = state->coord.col; state->dirty = 1; + recalculate_line_numbers(state); return; simple_insert_line_error: @@ -2302,6 +2310,7 @@ simple_join_lines(struct DrawState* state) free_bufferline(&state->buffer[state->rows_count - 1]); state->rows_count--; state->dirty = 1; + recalculate_line_numbers(state); return; simple_join_lines_error: @@ -2688,6 +2697,7 @@ wrap_not_enabled: MEMCCPY(state->error, errors[ERR_NOT_IMP], LINE_DEFAULT, temp); wrap_success: + recalculate_line_numbers(state); return 0; wrap_alloc_error: @@ -2805,7 +2815,6 @@ main(int argc, char** argv) printf(" enable_wrap:\t\t%s\n", enable_wrap ? "set" : "unset"); printf(" line_numbers:\t\t%s\n", line_numbers ? "set" : "unset"); - printf(" line_numbers_width:\t%d\n", line_numbers_width); printf(" wrap_width:\t\t%d\n", wrap_width); return 0; }