X-Git-Url: https://git.0d.be/?p=empathy.git;a=blobdiff_plain;f=libempathy-gtk%2Fempathy-smiley-manager.c;h=bc4b44d7364765504c3ee416f2934ca966fa6fa4;hp=0e78ee687a9b6ffa99387ce4117960bdbaf2ed43;hb=d53111417536194edd8bfd66f98630416de72e50;hpb=c2a7ae14574cd90f98f97cf84966152ab6023ace diff --git a/libempathy-gtk/empathy-smiley-manager.c b/libempathy-gtk/empathy-smiley-manager.c index 0e78ee68..bc4b44d7 100644 --- a/libempathy-gtk/empathy-smiley-manager.c +++ b/libempathy-gtk/empathy-smiley-manager.c @@ -20,13 +20,14 @@ * Xavier Claessens */ -#include +#include "config.h" +#include "empathy-smiley-manager.h" -#include +#include +#include -#include -#include "empathy-smiley-manager.h" #include "empathy-ui-utils.h" +#include "empathy-utils.h" typedef struct _SmileyManagerTree SmileyManagerTree; @@ -39,7 +40,7 @@ typedef struct { struct _SmileyManagerTree { gunichar c; GdkPixbuf *pixbuf; - const gchar *path; + gchar *path; GSList *childrens; }; @@ -78,35 +79,26 @@ smiley_manager_tree_free (SmileyManagerTree *tree) g_object_unref (tree->pixbuf); } g_slist_free (tree->childrens); + g_free (tree->path); g_slice_free (SmileyManagerTree, tree); } -/* Note: This function takes the ownership of str */ static EmpathySmiley * -smiley_new (GdkPixbuf *pixbuf, gchar *str, const gchar *path) +smiley_new (GdkPixbuf *pixbuf, const gchar *str) { EmpathySmiley *smiley; smiley = g_slice_new0 (EmpathySmiley); - if (pixbuf) { - smiley->pixbuf = g_object_ref (pixbuf); - } - smiley->str = str; - smiley->path = path; + smiley->pixbuf = g_object_ref (pixbuf); + smiley->str = g_strdup (str); return smiley; } -void -empathy_smiley_free (EmpathySmiley *smiley) +static void +smiley_free (EmpathySmiley *smiley) { - if (!smiley) { - return; - } - - if (smiley->pixbuf) { - g_object_unref (smiley->pixbuf); - } + g_object_unref (smiley->pixbuf); g_free (smiley->str); g_slice_free (EmpathySmiley, smiley); } @@ -115,16 +107,9 @@ static void smiley_manager_finalize (GObject *object) { EmpathySmileyManagerPriv *priv = GET_PRIV (object); - GSList *l; smiley_manager_tree_free (priv->tree); - for (l = priv->smileys; l; l = l->next) { - EmpathySmiley *smiley = l->data; - - /* The smiley got the ownership of the path */ - g_free ((gchar *) smiley->path); - empathy_smiley_free (smiley); - } + g_slist_foreach (priv->smileys, (GFunc) smiley_free, NULL); g_slist_free (priv->smileys); } @@ -226,13 +211,13 @@ smiley_manager_tree_insert (SmileyManagerTree *tree, } child->pixbuf = g_object_ref (pixbuf); - child->path = path; + child->path = g_strdup (path); } static void smiley_manager_add_valist (EmpathySmileyManager *manager, GdkPixbuf *pixbuf, - gchar *path, + const gchar *path, const gchar *first_str, va_list var_args) { @@ -244,10 +229,9 @@ smiley_manager_add_valist (EmpathySmileyManager *manager, smiley_manager_tree_insert (priv->tree, pixbuf, str, path); } - /* We give the ownership of path to the smiley */ g_object_set_data_full (G_OBJECT (pixbuf), "smiley_str", g_strdup (first_str), g_free); - smiley = smiley_new (pixbuf, g_strdup (first_str), path); + smiley = smiley_new (pixbuf, first_str); priv->smileys = g_slist_prepend (priv->smileys, smiley); } @@ -261,18 +245,19 @@ empathy_smiley_manager_add (EmpathySmileyManager *manager, va_list var_args; g_return_if_fail (EMPATHY_IS_SMILEY_MANAGER (manager)); - g_return_if_fail (!EMP_STR_EMPTY (icon_name)); - g_return_if_fail (!EMP_STR_EMPTY (first_str)); + g_return_if_fail (!TPAW_STR_EMPTY (icon_name)); + g_return_if_fail (!TPAW_STR_EMPTY (first_str)); - pixbuf = empathy_pixbuf_from_icon_name (icon_name, GTK_ICON_SIZE_MENU); + pixbuf = tpaw_pixbuf_from_icon_name (icon_name, GTK_ICON_SIZE_MENU); if (pixbuf) { gchar *path; va_start (var_args, first_str); - path = empathy_filename_from_icon_name (icon_name, GTK_ICON_SIZE_MENU); + path = tpaw_filename_from_icon_name (icon_name, GTK_ICON_SIZE_MENU); smiley_manager_add_valist (manager, pixbuf, path, first_str, var_args); va_end (var_args); g_object_unref (pixbuf); + g_free (path); } } @@ -282,93 +267,53 @@ empathy_smiley_manager_load (EmpathySmileyManager *manager) g_return_if_fail (EMPATHY_IS_SMILEY_MANAGER (manager)); /* From fd.o icon-naming spec */ - empathy_smiley_manager_add (manager, "face-angel", "O:-)", "O:)", NULL); - empathy_smiley_manager_add (manager, "face-angry", "X-(", ":@", NULL); - empathy_smiley_manager_add (manager, "face-cool", "B-)", "B)", NULL); - empathy_smiley_manager_add (manager, "face-crying", ":'(", NULL); - empathy_smiley_manager_add (manager, "face-devilish", ">:-)", ">:)", NULL); - empathy_smiley_manager_add (manager, "face-embarrassed",":-[", ":[", ":-$", ":$", NULL); - empathy_smiley_manager_add (manager, "face-kiss", ":-*", ":*", NULL); - empathy_smiley_manager_add (manager, "face-laugh", ":-))", ":))", NULL); - empathy_smiley_manager_add (manager, "face-monkey", ":-(|)", ":(|)", NULL); - empathy_smiley_manager_add (manager, "face-plain", ":-|", ":|", NULL); - empathy_smiley_manager_add (manager, "face-raspberry", ":-P", ":P", ":-p", ":p", NULL); - empathy_smiley_manager_add (manager, "face-sad", ":-(", ":(", NULL); - empathy_smiley_manager_add (manager, "face-sick", ":-&", ":&", NULL); - empathy_smiley_manager_add (manager, "face-smile", ":-)", ":)", NULL); - empathy_smiley_manager_add (manager, "face-smile-big", ":-D", ":D", ":-d", ":d", NULL); - empathy_smiley_manager_add (manager, "face-smirk", ":-!", ":!", NULL); - empathy_smiley_manager_add (manager, "face-surprise", ":-O", ":O", ":-o", ":o", NULL); - empathy_smiley_manager_add (manager, "face-tired", "|-)", "|)", NULL); - empathy_smiley_manager_add (manager, "face-uncertain", ":-/", ":/", NULL); - empathy_smiley_manager_add (manager, "face-wink", ";-)", ";)", NULL); - empathy_smiley_manager_add (manager, "face-worried", ":-S", ":S", ":-s", ":s", NULL); -} -GSList * -empathy_smiley_manager_parse (EmpathySmileyManager *manager, - const gchar *text) -{ - EmpathySmileyManagerPriv *priv = GET_PRIV (manager); - EmpathySmiley *smiley; - SmileyManagerTree *cur_tree = priv->tree; - const gchar *t; - const gchar *cur_str = text; - GSList *smileys = NULL; - - g_return_val_if_fail (EMPATHY_IS_SMILEY_MANAGER (manager), NULL); - g_return_val_if_fail (text != NULL, NULL); - - for (t = text; *t; t = g_utf8_next_char (t)) { - SmileyManagerTree *child; - gunichar c; - - c = g_utf8_get_char (t); - child = smiley_manager_tree_find_child (cur_tree, c); - - if (cur_tree == priv->tree) { - if (child) { - if (t > cur_str) { - smiley = smiley_new (NULL, - g_strndup (cur_str, t - cur_str), - NULL); - smileys = g_slist_prepend (smileys, smiley); - } - cur_str = t; - cur_tree = child; - } - - continue; - } - - if (child) { - cur_tree = child; - continue; - } - - smiley = smiley_new (cur_tree->pixbuf, - g_strndup (cur_str, t - cur_str), - cur_tree->path); - smileys = g_slist_prepend (smileys, smiley); - if (cur_tree->pixbuf) { - cur_str = t; - cur_tree = smiley_manager_tree_find_child (priv->tree, c); - - if (!cur_tree) { - cur_tree = priv->tree; - } - } else { - cur_str = t; - cur_tree = priv->tree; - } - } - - smiley = smiley_new (cur_tree->pixbuf, - g_strndup (cur_str, t - cur_str), - cur_tree->path); - smileys = g_slist_prepend (smileys, smiley); - - return g_slist_reverse (smileys); + /* U+1F47C BABY ANGEL */ + empathy_smiley_manager_add (manager, "face-angel", "👼", "O:-)", "O:)", NULL); + /* U+1F620 ANGRY FACE */ + empathy_smiley_manager_add (manager, "face-angry", "😠", "X-(", ":@", NULL); + /* U+1F60E SMILING FACE WITH SUNGLASSES */ + empathy_smiley_manager_add (manager, "face-cool", "😎", "B-)", "B-|", NULL); + /* U+1F62D LOUDLY CRYING FACE */ + empathy_smiley_manager_add (manager, "face-crying", "😭", ":'(", NULL); + /* U+1F608 SMILING FACE WITH HORNS */ + empathy_smiley_manager_add (manager, "face-devilish", "😈", ">:-)", ">:)", NULL); + /* U+1F633 FLUSHED FACE */ + empathy_smiley_manager_add (manager, "face-embarrassed","😳", ":-[", ":[", ":-$", ":$", NULL); + /* no suitable character in unicode */ + empathy_smiley_manager_add (manager, "face-glasses", "8-)", NULL); + /* U+1F618 FACE THROWING A KISS */ + empathy_smiley_manager_add (manager, "face-kiss", "😘", ":-*", ":*", NULL); + /* U+1F604 SMILING FACE WITH OPEN MOUTH AND SMILING EYES" */ + empathy_smiley_manager_add (manager, "face-laugh", "😄", ":-))", ":))", NULL); + /* U+1F435 MONKEY */ + empathy_smiley_manager_add (manager, "face-monkey", "🐵", ":-(|)", ":(|)", NULL); + /* U+1F610 NEUTRAL FACE */ + empathy_smiley_manager_add (manager, "face-plain", "😐", ":-|", ":|", NULL); + /* U+1F61B FACE WITH STUCK-OUT TONGUE */ + empathy_smiley_manager_add (manager, "face-raspberry", "😛", ":-P", ":P", ":-p", ":p", NULL); + /* U+1F626 FROWING FACE WITH OPEN MOUTH */ + empathy_smiley_manager_add (manager, "face-sad", "😦", ":-(", ":(", NULL); + /* U+1F635 DIZZY FACE */ + empathy_smiley_manager_add (manager, "face-sick", "😵", ":-&", ":&", NULL); + /* U+1F603 SMILING FACE WITH OPEN MOUTH */ + empathy_smiley_manager_add (manager, "face-smile", "😃", ":-)", ":)", ":]", "=)", NULL); + /* U+1F601 GRINNING FACE WITH SMILING EYES */ + empathy_smiley_manager_add (manager, "face-smile-big", "😁", ":-D", ":D", ":-d", ":d", NULL); + /* U+1F60F SMIRKING FACE */ + empathy_smiley_manager_add (manager, "face-smirk", "😏", ":-!", ":!", NULL); + /* U+1F632 ASTONISHED FACE */ + empathy_smiley_manager_add (manager, "face-surprise", "😲", ":-O", ":O", ":-o", ":o", NULL); + /* U+1F62A SLEEPY FACE */ + empathy_smiley_manager_add (manager, "face-tired", "😪", "|-)", "|)", NULL); + /* U+1F615 CONFUSED FACE */ + empathy_smiley_manager_add (manager, "face-uncertain", "😕", ":-/", ":/", ":-\\", ":\\", NULL); + /* U+1F609 WINKING FACE */ + empathy_smiley_manager_add (manager, "face-wink", "😉", ";-)", ";)", NULL); + /* U+1F61F WORRIED FACE */ + empathy_smiley_manager_add (manager, "face-worried", "😟", ":-S", ":S", ":-s", ":s", NULL); + /* U+2764 HEAVY BLACK HEART */ + empathy_smiley_manager_add (manager, "emblem-favorite", "❤", "<3", NULL); } static EmpathySmileyHit * @@ -390,6 +335,8 @@ smiley_hit_new (SmileyManagerTree *tree, void empathy_smiley_hit_free (EmpathySmileyHit *hit) { + g_return_if_fail (hit != NULL); + g_slice_free (EmpathySmileyHit, hit); } @@ -408,12 +355,22 @@ empathy_smiley_manager_parse_len (EmpathySmileyManager *manager, g_return_val_if_fail (EMPATHY_IS_SMILEY_MANAGER (manager), NULL); g_return_val_if_fail (text != NULL, NULL); + /* If len is negative, parse the string until we find '\0' */ if (len < 0) { len = G_MAXSSIZE; } + /* Parse the len first bytes of text to find smileys. Each time a smiley + * is detected, append a EmpathySmileyHit struct to the returned list, + * containing the smiley pixbuf and the position of the text to be + * replaced by it. + * cur_str is a pointer in the text showing the current position + * of the parsing. It is always at the begining of an UTF-8 character, + * because we support unicode smileys! For example we could want to + * replace ™ by an image. */ + for (cur_str = text; - *cur_str && cur_str - text < len; + *cur_str != '\0' && cur_str - text < len; cur_str = g_utf8_next_char (cur_str)) { SmileyManagerTree *child; gunichar c; @@ -421,19 +378,27 @@ empathy_smiley_manager_parse_len (EmpathySmileyManager *manager, c = g_utf8_get_char (cur_str); child = smiley_manager_tree_find_child (cur_tree, c); + /* If we have a child it means c is part of a smiley */ if (child) { if (cur_tree == priv->tree) { + /* c is the first char of some smileys, keep + * the begining position */ start = cur_str; } cur_tree = child; continue; } + /* c is not part of a smiley. let's check if we found a smiley + * before it. */ if (cur_tree->pixbuf != NULL) { + /* found! */ hit = smiley_hit_new (cur_tree, start - text, cur_str - text); hits = g_slist_prepend (hits, hit); + /* c was not part of this smiley, check if a new smiley + * start with it. */ cur_tree = smiley_manager_tree_find_child (priv->tree, c); if (cur_tree) { start = cur_str; @@ -441,11 +406,23 @@ empathy_smiley_manager_parse_len (EmpathySmileyManager *manager, cur_tree = priv->tree; } } else if (cur_tree != priv->tree) { + /* We searched a smiley starting at 'start' but we ended + * with no smiley. Look again starting from next char. + * + * For example ">:)" and ":(" are both valid smileys, + * when parsing text ">:(" we first see '>' which could + * be the start of a smiley. 'start' variable is set to + * that position and we parse next char which is ':' and + * is still potential smiley. Then we see '(' which is + * NOT part of the smiley, ">:(" does not exist, so we + * have to start again from ':' to find ":(" which is + * correct smiley. */ cur_str = start; cur_tree = priv->tree; } } + /* Check if last char of the text was the end of a smiley */ if (cur_tree->pixbuf != NULL) { hit = smiley_hit_new (cur_tree, start - text, cur_str - text); hits = g_slist_prepend (hits, hit);