diff options
author | Marvin W <git@larma.de> | 2025-01-02 14:22:41 +0100 |
---|---|---|
committer | Marvin W <git@larma.de> | 2025-01-03 17:44:43 +0100 |
commit | 398c52e1b9a5c91cd99277463080819ebdedfe1d (patch) | |
tree | dc8aef72d3bdd27a75b14608af4f174a0548c670 /main | |
parent | b490eb662fb8fb9ddbc8bbaea2b5608e7a511158 (diff) | |
download | dino-398c52e1b9a5c91cd99277463080819ebdedfe1d.tar.gz dino-398c52e1b9a5c91cd99277463080819ebdedfe1d.zip |
Work around pango bug
See https://gitlab.gnome.org/GNOME/pango/-/issues/798 and https://gitlab.gnome.org/GNOME/pango/-/issues/832
Diffstat (limited to 'main')
-rw-r--r-- | main/src/ui/call_window/call_bottom_bar.vala | 2 | ||||
-rw-r--r-- | main/src/ui/conversation_content_view/message_widget.vala | 3 | ||||
-rw-r--r-- | main/src/ui/global_search.vala | 2 | ||||
-rw-r--r-- | main/src/ui/util/helper.vala | 35 | ||||
-rw-r--r-- | main/src/windows/preferences_window/add_account_dialog.vala | 2 | ||||
-rw-r--r-- | main/vapi/icu-uc.vapi | 11 |
6 files changed, 51 insertions, 4 deletions
diff --git a/main/src/ui/call_window/call_bottom_bar.vala b/main/src/ui/call_window/call_bottom_bar.vala index 641a4def..e0848cc9 100644 --- a/main/src/ui/call_window/call_bottom_bar.vala +++ b/main/src/ui/call_window/call_bottom_bar.vala @@ -138,7 +138,7 @@ public class Dino.Ui.CallBottomBar : Gtk.Box { public void show_counterpart_ended(string text) { stack.set_visible_child_name("label"); - label.label = text; + label.label = Util.unbreak_space_around_non_spacing_mark(text); } public bool is_menu_active() { diff --git a/main/src/ui/conversation_content_view/message_widget.vala b/main/src/ui/conversation_content_view/message_widget.vala index 376ef4bd..d116e7de 100644 --- a/main/src/ui/conversation_content_view/message_widget.vala +++ b/main/src/ui/conversation_content_view/message_widget.vala @@ -140,6 +140,9 @@ public class MessageMetaItem : ContentMetaItem { } } + // Work around pango bug + markup_text = Util.unbreak_space_around_non_spacing_mark((owned) markup_text); + if (conversation.type_ == Conversation.Type.GROUPCHAT) { markup_text = Util.parse_add_markup_theme(markup_text, conversation.nickname, true, true, true, Util.is_dark_theme(this.label), ref theme_dependent); } else { diff --git a/main/src/ui/global_search.vala b/main/src/ui/global_search.vala index 2fb31a90..a63aaed1 100644 --- a/main/src/ui/global_search.vala +++ b/main/src/ui/global_search.vala @@ -223,7 +223,7 @@ public class GlobalSearch { grid.margin_top = 3; grid.margin_bottom = 3; - string text = item.message.body.replace("\n", "").replace("\r", ""); + string text = Util.unbreak_space_around_non_spacing_mark(item.message.body.replace("\n", "").replace("\r", "")); if (text.length > 200) { int index = text.index_of(search); if (index + search.length <= 100) { diff --git a/main/src/ui/util/helper.vala b/main/src/ui/util/helper.vala index e12dfe20..578e313a 100644 --- a/main/src/ui/util/helper.vala +++ b/main/src/ui/util/helper.vala @@ -170,6 +170,41 @@ public static Map<unichar, unichar> get_matching_chars() { return MATCHING_CHARS; } +/** + * This replaces spaces with non-breaking spaces when they are adjacent to a non-spacing mark. + * + * We do this to work-around a bug in Pango. See https://gitlab.gnome.org/GNOME/pango/-/issues/798 and + * https://gitlab.gnome.org/GNOME/pango/-/issues/832 + * + * This is zero-copy iff no space is adjacent to a non-spacing mark, otherwise the provided string will be destroyed + * and the returned string should be used instead. + */ +public static string unbreak_space_around_non_spacing_mark(owned string s) { + int current_index = 0; + unichar current_char = 0; + int prev_index = 0; + unichar prev_char = 0; + bool is_non_spacing_mark = false; + while (s.get_next_char(ref current_index, out current_char)) { + int replace_index = -1; + if (is_non_spacing_mark && current_char == ' ') { + replace_index = prev_index; + current_char = ' '; + } + is_non_spacing_mark = ICU.get_int_property_value(current_char, ICU.Property.BIDI_CLASS) == ICU.CharDirection.DIR_NON_SPACING_MARK; + if (prev_char == ' ' && is_non_spacing_mark) { + replace_index = prev_index - 1; + } + if (replace_index != -1) { + s = s[0:replace_index] + " " + s[(replace_index + 1):s.length]; + current_index += 1; + } + prev_index = current_index; + prev_char = current_char; + } + return (owned) s; +} + public static string parse_add_markup(string s_, string? highlight_word, bool parse_links, bool parse_text_markup) { bool ignore_out_var = false; return parse_add_markup_theme(s_, highlight_word, parse_links, parse_text_markup, parse_text_markup, false, ref ignore_out_var); diff --git a/main/src/windows/preferences_window/add_account_dialog.vala b/main/src/windows/preferences_window/add_account_dialog.vala index bfa98103..3ca183e1 100644 --- a/main/src/windows/preferences_window/add_account_dialog.vala +++ b/main/src/windows/preferences_window/add_account_dialog.vala @@ -311,7 +311,7 @@ public class AddAccountDialog : Adw.Window { register_form_continue.grab_focus(); } else if (form.fields.size > 0) { if (form.instructions != null && form.instructions != "") { - string markup_instructions = Util.parse_add_markup(form.instructions, null, true, false); + string markup_instructions = Util.parse_add_markup(Util.unbreak_space_around_non_spacing_mark(form.instructions), null, true, false); form_box.append(new Label(markup_instructions) { use_markup=true, xalign=0, margin_top=7, wrap=true, wrap_mode=Pango.WrapMode.WORD_CHAR }); } diff --git a/main/vapi/icu-uc.vapi b/main/vapi/icu-uc.vapi index db1609ad..9eb3d274 100644 --- a/main/vapi/icu-uc.vapi +++ b/main/vapi/icu-uc.vapi @@ -1,14 +1,23 @@ namespace ICU { -[CCode (cprefix = "UCHAR_", cheader_filename = "unicode/uchar.h")] +[CCode (cname = "UProperty", cprefix = "UCHAR_", has_type_id = false, cheader_filename = "unicode/uchar.h")] public enum Property { EMOJI, EMOJI_PRESENTATION, EMOJI_MODIFIER, EMOJI_MODIFIER_BASE, + BIDI_CLASS, +} + +[CCode (cname = "UCharDirection", cprefix = "U_", has_type_id = false, cheader_filename = "unicode/uchar.h")] +public enum CharDirection { + DIR_NON_SPACING_MARK, } [CCode (cname = "u_hasBinaryProperty", cheader_filename = "unicode/uchar.h")] public bool has_binary_property(unichar c, Property p); +[CCode (cname = "u_getIntPropertyValue", cheader_filename = "unicode/uchar.h")] +public int32 get_int_property_value(unichar c, Property p); + } |