diff --git a/src/common/cfgfiles.c b/src/common/cfgfiles.c index 42cf4849..d91f30b0 100644 --- a/src/common/cfgfiles.c +++ b/src/common/cfgfiles.c @@ -39,11 +39,7 @@ #endif #define DEF_FONT "Monospace 9" -#ifdef WIN32 -#define DEF_FONT_ALTER "Segoe UI Emoji,Arial Unicode MS,Lucida Sans Unicode,Meiryo,Symbola,Unifont" -#else -#define DEF_FONT_ALTER "Arial Unicode MS,Segoe UI Emoji,Lucida Sans Unicode,Meiryo,Symbola,Unifont" -#endif +#define DEF_FONT_ALTER "Noto Color Emoji,Segoe UI Emoji,Apple Color Emoji,Twemoji Mozilla,Twitter Color Emoji,EmojiOne Color,EmojiOne Mozilla,Noto Emoji,Segoe UI Symbol" const char * const languages[LANGUAGES_LENGTH] = { "af", "sq", "am", "ast", "az", "eu", "be", "bg", "ca", "zh_CN", /* 0 .. 9 */ diff --git a/src/fe-gtk/maingui.c b/src/fe-gtk/maingui.c index 6bdb618d..7766e736 100644 --- a/src/fe-gtk/maingui.c +++ b/src/fe-gtk/maingui.c @@ -3511,11 +3511,15 @@ mg_apply_session_font_prefs (session_gui *gui) if (gui->topic_entry) { theme_manager_apply_entry_palette (gui->topic_entry, font); + mg_apply_emoji_fallback_widget (gui->topic_entry); mg_topicbar_update_height (gui->topic_entry); } if (gui->input_box && prefs.hex_gui_input_style) + { theme_manager_apply_entry_palette (gui->input_box, font); + mg_apply_emoji_fallback_widget (gui->input_box); + } if (gui->chanview) chanview_apply_theme (gui->chanview); @@ -3543,6 +3547,7 @@ mg_create_topicbar (session *sess, GtkWidget *box) gui->topic_entry = topic = gtk_text_view_new (); gtk_widget_set_name (topic, "zoitechat-topicbox"); + mg_apply_emoji_fallback_widget (topic); gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (topic), prefs.hex_gui_topicbar_multiline && !prefs.hex_gui_mode_buttons_inline ? GTK_WRAP_WORD_CHAR : GTK_WRAP_NONE); @@ -4363,11 +4368,7 @@ mg_inputbox_rightclick (GtkEntry *entry, GtkWidget *menu) * ------------------------------------------------------------------------- */ static const char *mg_emoji_family_fallback = -#ifdef G_OS_WIN32 - "Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji, Apple Color Emoji, Twemoji Mozilla, EmojiOne Color"; -#else - "Noto Color Emoji, Segoe UI Emoji, Apple Color Emoji, Twemoji Mozilla, EmojiOne Color"; -#endif + "Noto Color Emoji, Segoe UI Emoji, Apple Color Emoji, Twemoji Mozilla, Twitter Color Emoji, EmojiOne Color, EmojiOne Mozilla, Noto Emoji, Segoe UI Symbol"; static const char * mg_find_available_icon_name (const char *const *icon_names) @@ -4412,7 +4413,9 @@ mg_family_already_has_emoji (const gchar *family) (strstr (family, "Segoe UI Emoji") != NULL) || (strstr (family, "Apple Color Emoji") != NULL) || (strstr (family, "Twemoji") != NULL) || - (strstr (family, "EmojiOne") != NULL); + (strstr (family, "Twitter Color Emoji") != NULL) || + (strstr (family, "EmojiOne") != NULL) || + (strstr (family, "Noto Emoji") != NULL); } static PangoFontDescription * @@ -4788,6 +4791,7 @@ mg_create_entry (session *sess, GtkWidget *box) if (prefs.hex_gui_input_style) mg_apply_entry_style (entry); + mg_apply_emoji_fallback_widget (entry); mg_apply_entry_scroll_artifact_fix (entry); g_object_set (G_OBJECT (entry), "show-emoji-icon", TRUE, NULL); diff --git a/src/fe-gtk/xtext.c b/src/fe-gtk/xtext.c index 296848ea..f7916179 100644 --- a/src/fe-gtk/xtext.c +++ b/src/fe-gtk/xtext.c @@ -601,6 +601,8 @@ static PangoFontDescription * backend_font_open_real (char *name) { PangoFontDescription *font; + const char *family; + char *family_list; font = pango_font_description_from_string (name); if (font && pango_font_description_get_size (font) == 0) @@ -611,6 +613,12 @@ backend_font_open_real (char *name) if (!font) font = pango_font_description_from_string ("sans 11"); + family = pango_font_description_get_family (font); + family_list = g_strdup_printf ("%s, Noto Color Emoji, Segoe UI Emoji, Apple Color Emoji, Twemoji Mozilla, Twitter Color Emoji, EmojiOne Color, EmojiOne Mozilla, Noto Emoji, Segoe UI Symbol", + family && *family ? family : "Sans"); + pango_font_description_set_family (font, family_list); + g_free (family_list); + return font; } @@ -661,36 +669,85 @@ static int backend_get_text_width_emph (GtkXText *xtext, guchar *str, int len, int emphasis) { int width; - int deltaw; - int mbl; - if (*str == 0) + if (*str == 0 || len <= 0) return 0; if ((emphasis & EMPH_HIDDEN)) return 0; emphasis &= (EMPH_ITAL | EMPH_BOLD); - width = 0; pango_layout_set_attributes (xtext->layout, attr_lists[emphasis]); - while (len > 0) - { - mbl = charlen(str); - if (*str < 128) - deltaw = fontwidths[emphasis][*str]; - else - { - pango_layout_set_text (xtext->layout, str, mbl); - pango_layout_get_pixel_size (xtext->layout, &deltaw, NULL); - } - width += deltaw; - str += mbl; - len -= mbl; - } + pango_layout_set_text (xtext->layout, str, len); + pango_layout_get_pixel_size (xtext->layout, &width, NULL); return width; } +static int +backend_get_text_offset_emph (GtkXText *xtext, guchar *str, int len, int x, int emphasis) +{ + PangoLayoutLine *line; + int index = 0; + int trailing = 0; + gchar *pos; + + if (*str == 0 || len <= 0 || x <= 0) + return 0; + + if ((emphasis & EMPH_HIDDEN)) + return len; + emphasis &= (EMPH_ITAL | EMPH_BOLD); + + pango_layout_set_attributes (xtext->layout, attr_lists[emphasis]); + pango_layout_set_text (xtext->layout, str, len); + line = pango_layout_get_line_readonly (xtext->layout, 0); + if (!line) + return 0; + + pango_layout_line_x_to_index (line, x * PANGO_SCALE, &index, &trailing); + if (index < 0) + return 0; + if (index >= len) + return len; + + pos = g_utf8_offset_to_pointer ((gchar *)str + index, trailing); + index = pos - (gchar *)str; + if (index > len) + return len; + + return index; +} + +static int +backend_get_text_cluster_len (GtkXText *xtext, guchar *str, int len, int emphasis) +{ + const PangoLogAttr *attrs; + int n_attrs; + int i; + gchar *pos; + + if (*str == 0 || len <= 0) + return 0; + + emphasis &= (EMPH_ITAL | EMPH_BOLD); + pango_layout_set_attributes (xtext->layout, attr_lists[emphasis]); + pango_layout_set_text (xtext->layout, str, len); + attrs = pango_layout_get_log_attrs_readonly (xtext->layout, &n_attrs); + for (i = 1; i < n_attrs; i++) + { + if (attrs[i].is_cursor_position) + { + pos = g_utf8_offset_to_pointer ((gchar *)str, i); + if (pos - (gchar *)str > len) + return len; + return pos - (gchar *)str; + } + } + + return len; +} + static int backend_get_text_width_slp (GtkXText *xtext, guchar *str, GSList *slp) { @@ -1386,19 +1443,17 @@ find_x (GtkXText *xtext, textentry *ent, int x, int subline, int indent) if (len < 0) return ent->str_len; /* Bad char -- return max offset. */ - /* Step through characters to find the one at the x position */ wid = x - indent; len = meta->len - (off - meta->off); while (wid > 0) { - mbl = charlen (ent->str + off); - mbw = backend_get_text_width_emph (xtext, ent->str + off, mbl, meta->emph); + mbw = backend_get_text_width_emph (xtext, ent->str + off, len, meta->emph); + if (xx + mbw >= x) + return off + backend_get_text_offset_emph (xtext, ent->str + off, len, x - xx, meta->emph); wid -= mbw; xx += mbw; - if (xx >= x) - return off; - len -= mbl; - off += mbl; + off += len; + len = 0; if (len <= 0) { if (meta->emph & EMPH_HIDDEN) @@ -3968,7 +4023,7 @@ find_next_wrap (GtkXText * xtext, textentry * ent, unsigned char *str, break; default: def: - mbl = charlen (str); + mbl = backend_get_text_cluster_len (xtext, str, ent->str + ent->str_len - str, emphasis); char_width = backend_get_text_width_emph (xtext, str, mbl, emphasis); if (!hidden) str_width += char_width; if (str_width > win_width)