]> git.ipfire.org Git - thirdparty/plymouth.git/commitdiff
ply-terminal-emulator: Require a fixed upfront column count
authornerdopolis <bluescreen_avenger@verizon.net>
Wed, 6 Dec 2023 02:12:37 +0000 (21:12 -0500)
committern3rdopolis <bluescreenavenger@gmail.com>
Wed, 6 Dec 2023 22:47:44 +0000 (22:47 +0000)
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

src/libply-splash-core/ply-rich-text.c
src/libply-splash-core/ply-rich-text.h
src/libply-splash-core/ply-terminal-emulator.c
src/libply-splash-core/ply-terminal-emulator.h
src/libply-splash-graphics/ply-console-viewer.c

index 13a9791fcddf4f010b6935f6950341cd94b50e5d..3905cd5842b313ec9ecb314a35539e84f3804f14 100644 (file)
@@ -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;
+}
index 6455158c74f34af4813b447a3e74d97f87751db8..632405bdf0316ba4d46e8757a389b4b4240bf16c 100644 (file)
@@ -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
index 5ce0a8db0fd9cb6beeb04ff2f083b189e87581ec..3f610d05dc1a81d3485d20b452b801334ecaf1d3 100644 (file)
 
 #include <stdio.h>
 
-#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;
                                 }
                         }
index 4fc93610a07891b9e355ff29a138d08a2261cf44..a189146def6cc5bd726a6e775e9a8c5f446054ba 100644 (file)
@@ -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,
index 274e389b11f225f32172ad95be261a592ba8093e..a41592df2e14c804fedd27a9608f71a3031e436f 100644 (file)
@@ -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)