From 53d6e5a8447764756d0f065945d884c63da85b6c Mon Sep 17 00:00:00 2001 From: n3rdopolis Date: Sun, 26 Nov 2023 11:37:30 -0500 Subject: [PATCH] libply-splash-core: Add class to handle rich text In order to implement a terminal that supports colors and styles, we need some way assign colors and styles to text. This commit adds a new class ply_rich_text_t to handle that. Code split out of ply-terminal-emulator.c by Ray Strode. --- src/libply-splash-core/meson.build | 2 + src/libply-splash-core/ply-rich-text.c | 221 +++++++++++++++++++++++++ src/libply-splash-core/ply-rich-text.h | 81 +++++++++ 3 files changed, 304 insertions(+) create mode 100644 src/libply-splash-core/ply-rich-text.c create mode 100644 src/libply-splash-core/ply-rich-text.h diff --git a/src/libply-splash-core/meson.build b/src/libply-splash-core/meson.build index 69636b13..4d846975 100644 --- a/src/libply-splash-core/meson.build +++ b/src/libply-splash-core/meson.build @@ -6,6 +6,7 @@ libply_splash_core_sources = files( 'ply-pixel-buffer.c', 'ply-pixel-display.c', 'ply-renderer.c', + 'ply-rich-text.c', 'ply-terminal.c', 'ply-text-display.c', 'ply-text-progress-bar.c', @@ -59,6 +60,7 @@ libply_splash_core_headers = files( 'ply-pixel-display.h', 'ply-renderer-plugin.h', 'ply-renderer.h', + 'ply-rich-text.h', 'ply-terminal.h', 'ply-text-display.h', 'ply-text-progress-bar.h', diff --git a/src/libply-splash-core/ply-rich-text.c b/src/libply-splash-core/ply-rich-text.c new file mode 100644 index 00000000..0cc87893 --- /dev/null +++ b/src/libply-splash-core/ply-rich-text.c @@ -0,0 +1,221 @@ +/* ply-rich-text.c - Text with colors and styles + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + */ + +#include "ply-array.h" +#include "ply-rich-text.h" +#include "ply-logger.h" +#include +#include +#include +#include + +#include + +struct _ply_rich_text_t +{ + ply_array_t *characters; + size_t reference_count; +}; + +ply_rich_text_t * +ply_rich_text_new (void) +{ + ply_rich_text_t *rich_text; + + rich_text = calloc (1, sizeof(ply_rich_text_t)); + rich_text->characters = ply_array_new (PLY_ARRAY_ELEMENT_TYPE_POINTER); + rich_text->reference_count = 1; + + return rich_text; +} + +void +ply_rich_text_take_reference (ply_rich_text_t *rich_text) +{ + rich_text->reference_count++; +} + +void +ply_rich_text_drop_reference (ply_rich_text_t *rich_text) +{ + rich_text->reference_count--; + + if (rich_text->reference_count == 0) + ply_rich_text_free (rich_text); +} + +void +ply_rich_text_free (ply_rich_text_t *rich_text) +{ + ply_rich_text_character_t **characters; + + if (rich_text == NULL) + return; + + characters = ply_rich_text_get_characters (rich_text); + characters = (ply_rich_text_character_t **) ply_array_get_pointer_elements (rich_text->characters); + for (size_t i = 0; characters[i] != NULL; i++) { + ply_rich_text_character_free (characters[i]); + } + + ply_array_free (rich_text->characters); + free (rich_text); +} + +char * +ply_rich_text_get_string (ply_rich_text_t *rich_text, + ply_rich_text_span_t *span) +{ + char *string = NULL; + ply_buffer_t *buffer; + ply_rich_text_character_t **characters; + + characters = ply_rich_text_get_characters (rich_text); + + buffer = ply_buffer_new (); + for (size_t i = span->offset; characters[i] != NULL; i++) { + if (span->range >= 0) { + if (i >= span->offset + span->range) + break; + } + + ply_buffer_append_bytes (buffer, + characters[i]->bytes, + characters[i]->length); + } + + string = ply_buffer_steal_bytes (buffer); + + ply_buffer_free (buffer); + + return string; +} + +void +ply_rich_text_remove_characters (ply_rich_text_t *rich_text) +{ + ply_rich_text_character_t **characters; + + if (rich_text == NULL) + return; + + characters = ply_rich_text_get_characters (rich_text); + characters = (ply_rich_text_character_t **) ply_array_get_pointer_elements (rich_text->characters); + for (size_t i = 0; characters[i] != NULL; i++) { + ply_rich_text_character_free (characters[i]); + } + + ply_array_free (rich_text->characters); + rich_text->characters = ply_array_new (PLY_ARRAY_ELEMENT_TYPE_POINTER); +} + +size_t +ply_rich_text_get_length (ply_rich_text_t *rich_text) +{ + ply_rich_text_character_t **characters; + size_t length = 0; + + characters = ply_rich_text_get_characters (rich_text); + + for (length = 0; characters[length] != NULL; length++) { + } + + return length; +} + +ply_rich_text_character_t * +ply_rich_text_character_new (void) +{ + ply_rich_text_character_t *character = calloc (1, sizeof(ply_rich_text_character_t)); + character->bytes = NULL; + character->length = 0; + + return character; +} + +void +ply_rich_text_character_free (ply_rich_text_character_t *character) +{ + free (character->bytes); + free (character); +} + +ply_rich_text_character_t ** +ply_rich_text_get_characters (ply_rich_text_t *rich_text) +{ + ply_rich_text_character_t **characters; + + characters = (ply_rich_text_character_t **) ply_array_get_pointer_elements (rich_text->characters); + return characters; +} + +void +ply_rich_text_remove_character (ply_rich_text_t *rich_text, + size_t character_index) +{ + ply_rich_text_character_t **characters; + + characters = ply_rich_text_get_characters (rich_text); + + if (characters[character_index] == NULL) + return; + + ply_rich_text_character_free (characters[character_index]); + characters[character_index] = NULL; +} + +void +ply_rich_text_move_character (ply_rich_text_t *rich_text, + size_t old_index, + size_t new_index) +{ + ply_rich_text_character_t **characters = ply_rich_text_get_characters (rich_text); + characters[new_index] = characters[old_index]; + characters[old_index] = NULL; +} + +void +ply_rich_text_set_character (ply_rich_text_t *rich_text, + ply_rich_text_character_style_t style, + size_t character_index, + const char *character_string, + size_t length) +{ + ply_rich_text_character_t **characters; + ply_rich_text_character_t *character; + + 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) { + free (character->bytes); + character->bytes = NULL; + } + } + + characters[character_index] = character; + character->bytes = strdup (character_string); + character->length = length; + character->style = style; +} diff --git a/src/libply-splash-core/ply-rich-text.h b/src/libply-splash-core/ply-rich-text.h new file mode 100644 index 00000000..27692deb --- /dev/null +++ b/src/libply-splash-core/ply-rich-text.h @@ -0,0 +1,81 @@ +/* ply-rich-text.h - Text with colors and styles + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + */ +#ifndef PLY_RICH_TEXT_H +#define PLY_RICH_TEXT_H + +#include "ply-array.h" +#include "ply-terminal.h" +#include + +#define PLY_UTF8_CHARACTER_MAX_SIZE 5 + +typedef struct _ply_rich_text_t ply_rich_text_t; + +typedef struct +{ + ply_terminal_color_t foreground_color; + ply_terminal_color_t background_color; + uint32_t bold_enabled : 1; + uint32_t dim_enabled : 1; + uint32_t italic_enabled : 1; + uint32_t underline_enabled : 1; + uint32_t reverse_enabled : 1; +} ply_rich_text_character_style_t; + +typedef struct +{ + char *bytes; + size_t length; + + ply_rich_text_character_style_t style; +} ply_rich_text_character_t; + +typedef struct +{ + ssize_t offset; + ssize_t range; +} ply_rich_text_span_t; + +#ifndef PLY_HIDE_FUNCTION_DECLARATIONS +ply_rich_text_t *ply_rich_text_new (void); +void ply_rich_text_take_reference (ply_rich_text_t *rich_text); +void ply_rich_text_drop_reference (ply_rich_text_t *rich_text); +char *ply_rich_text_get_string (ply_rich_text_t *rich_text, + ply_rich_text_span_t *span); +size_t ply_rich_text_get_length (ply_rich_text_t *rich_text); +void ply_rich_text_set_character (ply_rich_text_t *rich_text, + ply_rich_text_character_style_t style, + size_t index, + const char *bytes, + size_t length); +void ply_rich_text_move_character (ply_rich_text_t *rich_text, + size_t old_index, + size_t new_index); +void ply_rich_text_remove_character (ply_rich_text_t *rich_text, + size_t character_index); + +void ply_rich_text_remove_characters (ply_rich_text_t *rich_text); +ply_rich_text_character_t **ply_rich_text_get_characters (ply_rich_text_t *rich_text); +void ply_rich_text_free (ply_rich_text_t *rich_text); + +ply_rich_text_character_t *ply_rich_text_character_new (void); +void ply_rich_text_character_free (ply_rich_text_character_t *character); + +#endif //PLY_HIDE_FUNCTION_DECLARATIONS +#endif //PLY_RICH_TEXT_H -- 2.47.3