From b9cad7cc545cd82dca4c9d11085d6b7026b22038 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 24 Aug 2021 12:47:12 -0400 Subject: [PATCH] textview: Implement new pango attributes Implement the word and sentence attributes. --- demos/gtk-demo/fontify.c | 21 ++++++++++ gtk/gtktextattributes.c | 6 +++ gtk/gtktextattributes.h | 2 + gtk/gtktextbuffer.c | 22 ++++++++++- gtk/gtktextlayout.c | 18 +++++++++ gtk/gtktexttag.c | 82 ++++++++++++++++++++++++++++++++++++++++ gtk/gtktexttagprivate.h | 2 + 7 files changed, 152 insertions(+), 1 deletion(-) diff --git a/demos/gtk-demo/fontify.c b/demos/gtk-demo/fontify.c index b39c3ffee6..34b5063b46 100644 --- a/demos/gtk-demo/fontify.c +++ b/demos/gtk-demo/fontify.c @@ -131,6 +131,19 @@ insert_tags_for_attributes (GtkTextBuffer *buffer, gtk_text_buffer_apply_tag (buffer, tag, start, end); \ } +#define VOID_ATTR(attr_name) \ + { \ + tag = gtk_text_tag_table_lookup (table, #attr_name); \ + if (!tag) \ + { \ + tag = gtk_text_tag_new (#attr_name); \ + g_object_set (tag, #attr_name, TRUE, NULL); \ + gtk_text_tag_table_add (table, tag); \ + g_object_unref (tag); \ + } \ + gtk_text_buffer_apply_tag (buffer, tag, start, end); \ + } + fg_alpha = bg_alpha = 1.; attrs = pango_attr_iterator_get_attrs (iter); @@ -262,6 +275,14 @@ insert_tags_for_attributes (GtkTextBuffer *buffer, case PANGO_ATTR_ABSOLUTE_LINE_HEIGHT: break; + case PANGO_ATTR_WORD: + VOID_ATTR (word); + break; + + case PANGO_ATTR_SENTENCE: + VOID_ATTR (sentence); + break; + case PANGO_ATTR_SHAPE: case PANGO_ATTR_ABSOLUTE_SIZE: case PANGO_ATTR_GRAVITY: diff --git a/gtk/gtktextattributes.c b/gtk/gtktextattributes.c index 87208a8100..856b4f3310 100644 --- a/gtk/gtktextattributes.c +++ b/gtk/gtktextattributes.c @@ -441,6 +441,12 @@ _gtk_text_attributes_fill_from_tags (GtkTextAttributes *dest, if (tag->priv->text_transform_set) dest->text_transform = vals->text_transform; + + if (tag->priv->word_set) + dest->word = vals->word; + + if (tag->priv->sentence_set) + dest->sentence = vals->sentence; } dest->left_margin += left_margin_accumulative; diff --git a/gtk/gtktextattributes.h b/gtk/gtktextattributes.h index f1ebc857db..3aa01c8690 100644 --- a/gtk/gtktextattributes.h +++ b/gtk/gtktextattributes.h @@ -160,6 +160,8 @@ struct _GtkTextAttributes guint no_hyphens : 1; guint line_height_is_absolute : 1; guint text_transform : 3; /* PangoTextTransform */ + guint word : 1; + guint sentence : 1; }; GtkTextAttributes* gtk_text_attributes_new (void); diff --git a/gtk/gtktextbuffer.c b/gtk/gtktextbuffer.c index fd457df699..67d1e47056 100644 --- a/gtk/gtktextbuffer.c +++ b/gtk/gtktextbuffer.c @@ -4581,8 +4581,20 @@ insert_tags_for_attributes (GtkTextBuffer *buffer, gtk_text_buffer_apply_tag (buffer, tag, start, end); \ } - fg_alpha = bg_alpha = 1.; +#define VOID_ATTR(attr_name) \ + { \ + tag = gtk_text_tag_table_lookup (table, #attr_name); \ + if (!tag) \ + { \ + tag = gtk_text_tag_new (#attr_name); \ + g_object_set (tag, #attr_name, TRUE, NULL); \ + gtk_text_tag_table_add (table, tag); \ + g_object_unref (tag); \ + } \ + gtk_text_buffer_apply_tag (buffer, tag, start, end); \ + } + fg_alpha = bg_alpha = 1.; attrs = pango_attr_iterator_get_attrs (iter); for (l = attrs; l; l = l->next) { @@ -4716,6 +4728,14 @@ insert_tags_for_attributes (GtkTextBuffer *buffer, INT_ATTR (text_transform); break; + case PANGO_ATTR_WORD: + VOID_ATTR (word); + break; + + case PANGO_ATTR_SENTENCE: + VOID_ATTR (sentence); + break; + case PANGO_ATTR_SHAPE: case PANGO_ATTR_ABSOLUTE_SIZE: case PANGO_ATTR_GRAVITY: diff --git a/gtk/gtktextlayout.c b/gtk/gtktextlayout.c index 88d4c409b4..1873b03d74 100644 --- a/gtk/gtktextlayout.c +++ b/gtk/gtktextlayout.c @@ -1692,6 +1692,24 @@ add_text_attrs (GtkTextLayout *layout, attr->start_index = start; attr->end_index = start + byte_count; + pango_attr_list_insert (attrs, attr); + } + + if (style->word) + { + attr = pango_attr_word_new (); + attr->start_index = start; + attr->end_index = start + byte_count; + + pango_attr_list_insert (attrs, attr); + } + + if (style->sentence) + { + attr = pango_attr_sentence_new (); + attr->start_index = start; + attr->end_index = start + byte_count; + pango_attr_list_insert (attrs, attr); } } diff --git a/gtk/gtktexttag.c b/gtk/gtktexttag.c index f998ad9a40..8b252fb725 100644 --- a/gtk/gtktexttag.c +++ b/gtk/gtktexttag.c @@ -135,6 +135,8 @@ enum { PROP_SHOW_SPACES, PROP_INSERT_HYPHENS, PROP_TEXT_TRANSFORM, + PROP_WORD, + PROP_SENTENCE, /* Behavior args */ PROP_ACCUMULATIVE_MARGIN, @@ -178,6 +180,8 @@ enum { PROP_SHOW_SPACES_SET, PROP_INSERT_HYPHENS_SET, PROP_TEXT_TRANSFORM_SET, + PROP_WORD_SET, + PROP_SENTENCE_SET, LAST_ARG }; @@ -874,6 +878,40 @@ gtk_text_tag_class_init (GtkTextTagClass *klass) PANGO_TEXT_TRANSFORM_NONE, GTK_PARAM_READWRITE)); + /** + * GtkTextTag:word: + * + * Whether this tag represents a single word. + * + * This affects line breaks and cursor movement. + * + * Since: 4.6 + */ + g_object_class_install_property (object_class, + PROP_WORD, + g_param_spec_boolean ("word", + P_("Word"), + P_("Whether this is a word."), + FALSE, + GTK_PARAM_READWRITE)); + + /** + * GtkTextTag:sentence: + * + * Whether this tag represents a single sentence. + * + * This affects cursor movement. + * + * Since: 4.6 + */ + g_object_class_install_property (object_class, + PROP_SENTENCE, + g_param_spec_boolean ("sentence", + P_("Sentence"), + P_("Whether this is a sentence."), + FALSE, + GTK_PARAM_READWRITE)); + /** * GtkTextTag:accumulative-margin: * @@ -1056,6 +1094,14 @@ gtk_text_tag_class_init (GtkTextTagClass *klass) ADD_SET_PROP ("text-transform-set", PROP_TEXT_TRANSFORM_SET, P_("Text transform set"), P_("Whether this tag affects text transformation")); + + ADD_SET_PROP ("word-set", PROP_WORD_SET, + P_("Word set"), + P_("Whether this tag represents a single word")); + + ADD_SET_PROP ("sentence-set", PROP_WORD_SET, + P_("Sentence set"), + P_("Whether this tag represents a single sentence")); } static void @@ -1811,6 +1857,18 @@ gtk_text_tag_set_property (GObject *object, g_object_notify (object, "text-transform-set"); break; + case PROP_WORD: + priv->word_set = TRUE; + priv->values->word = g_value_get_boolean (value); + g_object_notify (object, "word-set"); + break; + + case PROP_SENTENCE: + priv->sentence_set = TRUE; + priv->values->sentence = g_value_get_boolean (value); + g_object_notify (object, "sentence-set"); + break; + case PROP_ACCUMULATIVE_MARGIN: priv->accumulative_margin = g_value_get_boolean (value); g_object_notify (object, "accumulative-margin"); @@ -1979,6 +2037,14 @@ gtk_text_tag_set_property (GObject *object, priv->text_transform_set = g_value_get_boolean (value); break; + case PROP_WORD_SET: + priv->word_set = g_value_get_boolean (value); + break; + + case PROP_SENTENCE_SET: + priv->sentence_set = g_value_get_boolean (value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -2195,6 +2261,14 @@ gtk_text_tag_get_property (GObject *object, g_value_set_enum (value, priv->values->text_transform); break; + case PROP_WORD: + g_value_set_boolean (value, priv->values->word); + break; + + case PROP_SENTENCE: + g_value_set_boolean (value, priv->values->sentence); + break; + case PROP_ACCUMULATIVE_MARGIN: g_value_set_boolean (value, priv->accumulative_margin); break; @@ -2341,6 +2415,14 @@ gtk_text_tag_get_property (GObject *object, g_value_set_boolean (value, priv->text_transform_set); break; + case PROP_WORD_SET: + g_value_set_boolean (value, priv->word_set); + break; + + case PROP_SENTENCE_SET: + g_value_set_boolean (value, priv->sentence_set); + break; + case PROP_BACKGROUND: case PROP_FOREGROUND: case PROP_PARAGRAPH_BACKGROUND: diff --git a/gtk/gtktexttagprivate.h b/gtk/gtktexttagprivate.h index ee6a5fa591..57ce42c2c6 100644 --- a/gtk/gtktexttagprivate.h +++ b/gtk/gtktexttagprivate.h @@ -88,6 +88,8 @@ struct _GtkTextTagPrivate guint show_spaces_set : 1; guint insert_hyphens_set : 1; guint text_transform_set : 1; + guint word_set : 1; + guint sentence_set : 1; /* Whether these margins accumulate or override */ guint accumulative_margin : 1;