From: nerdopolis Date: Wed, 6 Dec 2023 02:12:37 +0000 (-0500) Subject: ply-terminal-emulator: Require a fixed upfront column count X-Git-Tag: 23.51.283~8^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=149a1ce3e7fd09d7f37da5d82fb7b4eafaf9e871;p=thirdparty%2Fplymouth.git ply-terminal-emulator: Require a fixed upfront column count Some commands really do need to know how wide the terminal is to operate correctly. Without it long lines don't wrap right and other badness can happen. This commit addresses the problem by changing the terminal to take both a `number_of_rows` and `number_of_columns` argument at construct time instead of just a `maximum_line_count`. In order to properly implement that change, this commit also adds new api to `ply_rich_text_t` to specify which parts of a run of rich text is read-only and which parts of the run can be modified. Changes in this commit were made with assistance from Ray Strode --- diff --git a/src/libply-splash-core/ply-rich-text.c b/src/libply-splash-core/ply-rich-text.c index 13a9791f..3905cd58 100644 --- a/src/libply-splash-core/ply-rich-text.c +++ b/src/libply-splash-core/ply-rich-text.c @@ -29,8 +29,9 @@ struct _ply_rich_text_t { - ply_array_t *characters; - size_t reference_count; + ply_array_t *characters; + ply_rich_text_span_t span; + size_t reference_count; }; ply_rich_text_t * @@ -152,6 +153,9 @@ ply_rich_text_character_new (void) void ply_rich_text_character_free (ply_rich_text_character_t *character) { + if (character == NULL) + return; + free (character->bytes); free (character); } @@ -173,6 +177,13 @@ ply_rich_text_remove_character (ply_rich_text_t *rich_text, characters = ply_rich_text_get_characters (rich_text); + if (character_index < rich_text->span.offset) + return; + + if (character_index >= rich_text->span.offset + rich_text->span.range) + return; + + if (characters[character_index] == NULL) return; @@ -186,6 +197,20 @@ ply_rich_text_move_character (ply_rich_text_t *rich_text, size_t new_index) { ply_rich_text_character_t **characters = ply_rich_text_get_characters (rich_text); + + if (old_index < rich_text->span.offset) + return; + + if (new_index < rich_text->span.offset) + return; + + if (old_index >= rich_text->span.offset + rich_text->span.range) + return; + + if (new_index >= rich_text->span.offset + rich_text->span.range) + return; + + characters[new_index] = characters[old_index]; characters[old_index] = NULL; } @@ -200,12 +225,22 @@ ply_rich_text_set_character (ply_rich_text_t *rich_text, ply_rich_text_character_t **characters; ply_rich_text_character_t *character; + while (ply_array_get_size (rich_text->characters) <= character_index) { + ply_array_add_pointer_element (rich_text->characters, NULL); + } + + + if (character_index < rich_text->span.offset) + return; + + if (character_index >= rich_text->span.offset + rich_text->span.range) + return; + + characters = ply_rich_text_get_characters (rich_text); if (characters[character_index] == NULL) { character = ply_rich_text_character_new (); - ply_array_add_pointer_element (rich_text->characters, character); - characters = (ply_rich_text_character_t **) ply_array_get_pointer_elements (rich_text->characters); } else { character = characters[character_index]; if (character->bytes) { @@ -252,3 +287,17 @@ ply_rich_text_iterator_next (ply_rich_text_iterator_t *iterator, return true; } + +void +ply_rich_text_set_mutable_span (ply_rich_text_t *rich_text, + ply_rich_text_span_t *span) +{ + rich_text->span = *span; +} + +void +ply_rich_text_get_mutable_span (ply_rich_text_t *rich_text, + ply_rich_text_span_t *span) +{ + *span = rich_text->span; +} diff --git a/src/libply-splash-core/ply-rich-text.h b/src/libply-splash-core/ply-rich-text.h index 6455158c..632405bd 100644 --- a/src/libply-splash-core/ply-rich-text.h +++ b/src/libply-splash-core/ply-rich-text.h @@ -90,5 +90,10 @@ void ply_rich_text_iterator_init (ply_rich_text_iterator_t *iterator, bool ply_rich_text_iterator_next (ply_rich_text_iterator_t *iterator, ply_rich_text_character_t **character); +void ply_rich_text_set_mutable_span (ply_rich_text_t *rich_text, + ply_rich_text_span_t *span); +void ply_rich_text_get_mutable_span (ply_rich_text_t *rich_text, + ply_rich_text_span_t *span); + #endif //PLY_HIDE_FUNCTION_DECLARATIONS #endif //PLY_RICH_TEXT_H diff --git a/src/libply-splash-core/ply-terminal-emulator.c b/src/libply-splash-core/ply-terminal-emulator.c index 5ce0a8db..3f610d05 100644 --- a/src/libply-splash-core/ply-terminal-emulator.c +++ b/src/libply-splash-core/ply-terminal-emulator.c @@ -27,10 +27,6 @@ #include -#ifndef PLY_TERMINAL_LINE_MAX -#define PLY_TERMINAL_LINE_MAX 4096 -#endif - #define PLY_TERMINAL_SPACES_PER_TAB 8 /* Characters between 64 to 157 end the escape sequence strings (in testing) @@ -94,7 +90,9 @@ struct _ply_terminal_emulator { ply_terminal_emulator_parse_state_t state; - size_t maximum_line_count; + size_t number_of_rows; + size_t number_of_columns; + size_t line_count; ply_array_t *lines; @@ -127,17 +125,27 @@ static ply_terminal_emulator_command_t *ply_terminal_emulator_command_new (void) static void ply_terminal_emulator_command_free (ply_terminal_emulator_command_t *command); ply_terminal_emulator_t * -ply_terminal_emulator_new (size_t maximum_line_count) +ply_terminal_emulator_new (size_t number_of_rows, + size_t number_of_columns) { ply_terminal_emulator_t *terminal_emulator; + ply_rich_text_t *terminal_emulator_line; + ply_rich_text_span_t span; terminal_emulator = calloc (1, sizeof(struct _ply_terminal_emulator)); terminal_emulator->line_count = 1; - terminal_emulator->maximum_line_count = maximum_line_count; + terminal_emulator->number_of_rows = number_of_rows; + terminal_emulator->number_of_columns = number_of_columns; terminal_emulator->lines = ply_array_new (PLY_ARRAY_ELEMENT_TYPE_POINTER); - for (int i = 0; i < terminal_emulator->maximum_line_count; i++) { - ply_array_add_pointer_element (terminal_emulator->lines, ply_rich_text_new ()); + + span.offset = 0; + span.range = terminal_emulator->number_of_columns; + + for (int i = 0; i < terminal_emulator->number_of_rows; i++) { + terminal_emulator_line = ply_rich_text_new (); + ply_rich_text_set_mutable_span (terminal_emulator_line, &span); + ply_array_add_pointer_element (terminal_emulator->lines, terminal_emulator_line); } terminal_emulator->cursor_row_offset = 0; @@ -273,6 +281,8 @@ on_control_sequence_insert_blank_characters (ply_terminal_emulator_t *terminal_e size_t new_string_length; size_t append_count; size_t string_move_end_offset; + ply_rich_text_span_t span; + size_t maximum_characters; ply_trace ("terminal control sequence: insert blank characters"); @@ -293,17 +303,20 @@ on_control_sequence_insert_blank_characters (ply_terminal_emulator_t *terminal_e parameter = 1; } + ply_rich_text_get_mutable_span (terminal_emulator->current_line, &span); + maximum_characters = span.offset + span.range; + new_string_length = string_length + parameter; - if (new_string_length >= PLY_TERMINAL_LINE_MAX) { - append_count = PLY_TERMINAL_LINE_MAX - string_length - 1; - new_string_length = PLY_TERMINAL_LINE_MAX - 1; + if (new_string_length >= maximum_characters) { + append_count = maximum_characters - string_length - 1; + new_string_length = maximum_characters - 1; } else { append_count = parameter; } string_move_end_offset = string_length - 1; - if (string_move_end_offset >= PLY_TERMINAL_LINE_MAX) - string_move_end_offset = PLY_TERMINAL_LINE_MAX - 1; + if (string_move_end_offset >= maximum_characters) + string_move_end_offset = maximum_characters - 1; if (new_string_length <= 0) return PLY_TERMINAL_EMULATOR_BREAK_STRING_NONE; @@ -400,6 +413,8 @@ on_control_sequence_move_cursor_right (ply_terminal_emulator_t *terminal_emulato { int parameter; size_t string_length = ply_rich_text_get_length (terminal_emulator->current_line); + ply_rich_text_span_t span; + size_t maximum_characters; ply_trace ("terminal control sequence: move cursor right"); @@ -422,7 +437,10 @@ on_control_sequence_move_cursor_right (ply_terminal_emulator_t *terminal_emulato terminal_emulator->cursor_column += parameter; - if (terminal_emulator->cursor_column >= PLY_TERMINAL_LINE_MAX) + ply_rich_text_get_mutable_span (terminal_emulator->current_line, &span); + maximum_characters = span.offset + span.range; + + if (terminal_emulator->cursor_column >= maximum_characters) return PLY_TERMINAL_EMULATOR_BREAK_STRING; fill_offsets_with_padding (terminal_emulator, string_length, terminal_emulator->cursor_column); @@ -547,6 +565,8 @@ on_control_sequence_move_cursor_to_column (ply_terminal_emulator_t *terminal_emu bool paramaters_valid) { int parameter; + ply_rich_text_span_t span; + size_t maximum_characters; size_t string_length = ply_rich_text_get_length (terminal_emulator->current_line); @@ -569,7 +589,10 @@ on_control_sequence_move_cursor_to_column (ply_terminal_emulator_t *terminal_emu parameter = 1; } - if (parameter > PLY_TERMINAL_LINE_MAX) { + ply_rich_text_get_mutable_span (terminal_emulator->current_line, &span); + maximum_characters = span.offset + span.range; + + if (parameter > maximum_characters) { terminal_emulator->cursor_column = 1; } else { /* parameter is never 0. the column '1' represents the 0 index on the string */ @@ -596,6 +619,8 @@ on_control_sequence_erase_line (ply_terminal_emulator_t *terminal_emulator, size_t starting_offset = terminal_emulator->cursor_column; size_t string_length = ply_rich_text_get_length (terminal_emulator->current_line); size_t i; + ply_rich_text_span_t span; + size_t maximum_characters; ply_trace ("terminal control sequence: erase line"); @@ -617,8 +642,11 @@ on_control_sequence_erase_line (ply_terminal_emulator_t *terminal_emulator, erase_line_type = PLY_TERMINAL_EMULATOR_ERASE_LINE_TYPE_CURSOR_TO_RIGHT; } - if (starting_offset >= PLY_TERMINAL_LINE_MAX) - starting_offset = PLY_TERMINAL_LINE_MAX - 1; + ply_rich_text_get_mutable_span (terminal_emulator->current_line, &span); + maximum_characters = span.offset + span.range; + + if (starting_offset >= maximum_characters) + starting_offset = maximum_characters - 1; if (erase_line_type == PLY_TERMINAL_EMULATOR_ERASE_LINE_TYPE_CURSOR_TO_LEFT || erase_line_type == PLY_TERMINAL_EMULATOR_ERASE_LINE_TYPE_WHOLE_LINE) { /* Ensure that all characters from the start of the string to the cursor are spaces */ @@ -868,6 +896,8 @@ on_escape_character_tab (ply_terminal_emulator_t *terminal_emulator, size_t string_length = ply_rich_text_get_length (terminal_emulator->current_line); size_t new_cursor_position; size_t new_string_length; + ply_rich_text_span_t span; + size_t maximum_characters; ply_trace ("terminal escape character: tab"); @@ -881,9 +911,12 @@ on_escape_character_tab (ply_terminal_emulator_t *terminal_emulator, pad_character_count = PLY_TERMINAL_SPACES_PER_TAB - (terminal_emulator->cursor_column % PLY_TERMINAL_SPACES_PER_TAB); } + ply_rich_text_get_mutable_span (terminal_emulator->current_line, &span); + maximum_characters = span.offset + span.range; + new_cursor_position = terminal_emulator->cursor_column + pad_character_count; - if (new_cursor_position >= PLY_TERMINAL_LINE_MAX - 1) - new_cursor_position = PLY_TERMINAL_LINE_MAX - 1; + if (new_cursor_position >= maximum_characters - 1) + new_cursor_position = maximum_characters - 1; terminal_emulator->cursor_column = new_cursor_position; @@ -898,8 +931,8 @@ on_escape_character_tab (ply_terminal_emulator_t *terminal_emulator, new_string_length = string_length + pad_character_count; - if (new_string_length >= PLY_TERMINAL_LINE_MAX - 1) - new_string_length = PLY_TERMINAL_LINE_MAX - 1; + if (new_string_length >= maximum_characters - 1) + new_string_length = maximum_characters - 1; for (size_t i = string_length; i < new_string_length; i++) { ply_rich_text_set_character (terminal_emulator->current_line, terminal_emulator->current_style, i, " ", 1); @@ -1007,7 +1040,7 @@ ply_terminal_emulator_get_nth_line (ply_terminal_emulator_t *terminal_emulator, int line_number) { ply_rich_text_t *const *console_lines = (ply_rich_text_t *const *) ply_array_get_pointer_elements (terminal_emulator->lines); - return console_lines[line_number % terminal_emulator->maximum_line_count]; + return console_lines[line_number % terminal_emulator->number_of_rows]; } int @@ -1031,6 +1064,8 @@ ply_terminal_emulator_parse_substring (ply_terminal_emulator_t *terminal_emulato ply_terminal_emulator_break_string_t break_string = PLY_TERMINAL_EMULATOR_BREAK_STRING_NONE; int parameter_value; ply_terminal_emulator_command_t *command; + ply_rich_text_span_t span; + size_t maximum_characters; int character_length; ply_list_node_t *node; @@ -1044,7 +1079,10 @@ ply_terminal_emulator_parse_substring (ply_terminal_emulator_t *terminal_emulato return; } - if (terminal_emulator->cursor_column >= PLY_TERMINAL_LINE_MAX) + ply_rich_text_get_mutable_span (terminal_emulator->current_line, &span); + maximum_characters = span.offset + span.range; + + if (terminal_emulator->cursor_column >= maximum_characters) terminal_emulator->cursor_column = 0; new_length = ply_rich_text_get_length (terminal_emulator->current_line); @@ -1078,7 +1116,7 @@ ply_terminal_emulator_parse_substring (ply_terminal_emulator_t *terminal_emulato i++; - if (i >= PLY_TERMINAL_LINE_MAX) + if (i >= maximum_characters) break; } ply_rich_text_set_character (terminal_emulator->current_line, terminal_emulator->current_style, terminal_emulator->cursor_column, character_string, character_length); @@ -1103,8 +1141,9 @@ ply_terminal_emulator_parse_substring (ply_terminal_emulator_t *terminal_emulato ply_rich_text_set_character (terminal_emulator->current_line, terminal_emulator->current_style, terminal_emulator->cursor_column, character_string, 1); terminal_emulator->cursor_column++; - if (terminal_emulator->cursor_column >= PLY_TERMINAL_LINE_MAX) { - terminal_emulator->cursor_column = 0; + if (terminal_emulator->cursor_column >= maximum_characters) { + terminal_emulator->cursor_row_offset++; + terminal_emulator->break_action = PLY_TERMINAL_EMULATOR_BREAK_STRING_ACTION_RESET_CURSOR_COLUMN; break_string = PLY_TERMINAL_EMULATOR_BREAK_STRING; } } diff --git a/src/libply-splash-core/ply-terminal-emulator.h b/src/libply-splash-core/ply-terminal-emulator.h index 4fc93610..a189146d 100644 --- a/src/libply-splash-core/ply-terminal-emulator.h +++ b/src/libply-splash-core/ply-terminal-emulator.h @@ -52,7 +52,8 @@ typedef void (*ply_terminal_emulator_output_handler_t) (void *user_data, const char *output); #ifndef PLY_HIDE_FUNCTION_DECLARATIONS -ply_terminal_emulator_t *ply_terminal_emulator_new (size_t maximum_line_count); +ply_terminal_emulator_t *ply_terminal_emulator_new (size_t number_of_rows, + size_t number_of_columns); void ply_terminal_emulator_free (ply_terminal_emulator_t *terminal_emulator); void ply_terminal_emulator_parse_lines (ply_terminal_emulator_t *terminal_emulator, const char *text, diff --git a/src/libply-splash-graphics/ply-console-viewer.c b/src/libply-splash-graphics/ply-console-viewer.c index 274e389b..a41592df 100644 --- a/src/libply-splash-graphics/ply-console-viewer.c +++ b/src/libply-splash-graphics/ply-console-viewer.c @@ -100,7 +100,7 @@ ply_console_viewer_new (ply_pixel_display_t *display, ply_list_append_data (console_viewer->message_labels, console_message_label); } - console_viewer->terminal_emulator = ply_terminal_emulator_new (line_count); + console_viewer->terminal_emulator = ply_terminal_emulator_new (line_count, console_viewer->line_max_chars); ply_terminal_emulator_watch_for_output (console_viewer->terminal_emulator, (ply_terminal_emulator_output_handler_t)