comparison libpurple/protocols/myspace/myspace.c @ 19434:1e00b684c46f

In msimprpl, move formatting functions to a markup module. It only exposes two functions to convert between MySpaceIM markup and Purple HTML markup.
author Jeffrey Connelly <jaconnel@calpoly.edu>
date Sun, 26 Aug 2007 06:51:17 +0000
parents 9a1b28a10c95
children bddc6a6fddf0
comparison
equal deleted inserted replaced
19433:9a1b28a10c95 19434:1e00b684c46f
34 #define PURPLE_PLUGIN 34 #define PURPLE_PLUGIN
35 35
36 #include "message.h" 36 #include "message.h"
37 #include "persist.h" 37 #include "persist.h"
38 #include "myspace.h" 38 #include "myspace.h"
39
40 /* Globals */
41
42 /* The names in in emoticon_names (for <i n=whatever>) map to corresponding
43 * entries in emoticon_symbols (for the ASCII representation of the emoticon).
44 *
45 * Multiple emoticon symbols in Pidgin can map to one name. List the
46 * canonical form, as inserted by the "Smile!" dialog, first. For example,
47 * :) comes before :-), because although both are recognized as 'happy',
48 * the first is inserted by the smiley button (first symbol in theme).
49 *
50 * Note that symbols are case-sensitive in Pidgin -- :-X is not :-x. */
51 static struct MSIM_EMOTICON
52 {
53 gchar *name;
54 gchar *symbol;
55 } msim_emoticons[] = {
56 /* Unfortunately, this list duplicates much of the file
57 * pidgin/pidgin/pixmaps/emotes/default/22/default.theme.in, because
58 * that file is part of Pidgin, but we're part of libpurple.
59 */
60 { "bigsmile", ":D" },
61 { "bigsmile", ":-D" },
62 { "devil", "}:)" },
63 { "frazzled", ":Z" },
64 { "geek", "B)" },
65 { "googles", "%)" },
66 { "growl", ":E" },
67 { "laugh", ":))" }, /* Must be before ':)' */
68 { "happy", ":)" },
69 { "happy", ":-)" },
70 { "happi", ":)" },
71 { "heart", ":X" },
72 { "mohawk", "-:" },
73 { "mad", "X(" },
74 { "messed", "X)" },
75 { "nerd", "Q)" },
76 { "oops", ":G" },
77 { "pirate", "P)" },
78 { "scared", ":O" },
79 { "sidefrown", ":{" },
80 { "sinister", ":B" },
81 { "smirk", ":," },
82 { "straight", ":|" },
83 { "tongue", ":P" },
84 { "tongue", ":p" },
85 { "tongy", ":P" },
86 { "upset", "B|" },
87 { "wink", ";-)" },
88 { "wink", ";)" },
89 { "winc", ";)" },
90 { "worried", ":[" },
91 { "kiss", ":x" },
92 { NULL, NULL }
93 };
94 39
95 /* Internal functions */ 40 /* Internal functions */
96 41
97 #ifdef MSIM_DEBUG_MSG 42 #ifdef MSIM_DEBUG_MSG
98 static void print_hash_item(gpointer key, gpointer value, gpointer user_data); 43 static void print_hash_item(gpointer key, gpointer value, gpointer user_data);
103 static gboolean msim_login_challenge(MsimSession *session, MsimMessage *msg); 48 static gboolean msim_login_challenge(MsimSession *session, MsimMessage *msg);
104 static const gchar *msim_compute_login_response( 49 static const gchar *msim_compute_login_response(
105 const gchar nonce[2 * NONCE_SIZE], const gchar *email, 50 const gchar nonce[2 * NONCE_SIZE], const gchar *email,
106 const gchar *password, guint *response_len); 51 const gchar *password, guint *response_len);
107 52
108 static guint msim_point_to_purple_size(MsimSession *session, guint point);
109 static guint msim_purple_size_to_point(MsimSession *session, guint size);
110 static guint msim_height_to_point(MsimSession *session, guint height);
111 static guint msim_point_to_height(MsimSession *session, guint point);
112
113 static void msim_unrecognized(MsimSession *session, MsimMessage *msg, gchar *note); 53 static void msim_unrecognized(MsimSession *session, MsimMessage *msg, gchar *note);
114
115 static void msim_markup_tag_to_html(MsimSession *, xmlnode *root,
116 gchar **begin, gchar **end);
117 static void html_tag_to_msim_markup(MsimSession *, xmlnode *root,
118 gchar **begin, gchar **end);
119 static gchar *msim_convert_xml(MsimSession *, const gchar *raw,
120 MSIM_XMLNODE_CONVERT f);
121 static gchar *msim_convert_smileys_to_markup(gchar *before);
122
123 /* High-level msim markup <=> html conversion functions. */
124 static gchar *msim_markup_to_html(MsimSession *, const gchar *raw);
125 static gchar *html_to_msim_markup(MsimSession *, const gchar *raw);
126 54
127 static MsimUser *msim_get_user_from_buddy(PurpleBuddy *buddy); 55 static MsimUser *msim_get_user_from_buddy(PurpleBuddy *buddy);
128 static MsimUser *msim_find_user(MsimSession *session, const gchar *username); 56 static MsimUser *msim_find_user(MsimSession *session, const gchar *username);
129 57
130 static gboolean msim_incoming_bm_record_cv(MsimSession *session, 58 static gboolean msim_incoming_bm_record_cv(MsimSession *session,
199 127
200 static void msim_lookup_user(MsimSession *session, const gchar *user, 128 static void msim_lookup_user(MsimSession *session, const gchar *user,
201 MSIM_USER_LOOKUP_CB cb, gpointer data); 129 MSIM_USER_LOOKUP_CB cb, gpointer data);
202 130
203 static void msim_import_friends(PurplePluginAction *action); 131 static void msim_import_friends(PurplePluginAction *action);
204
205 double msim_round(double round);
206
207 /* round is part of C99, but sometimes is unavailable before then.
208 * Based on http://forums.belution.com/en/cpp/000/050/13.shtml
209 */
210 double msim_round(double value)
211 {
212 if (value < 0) {
213 return -(floor(-value + 0.5));
214 } else {
215 return floor( value + 0.5);
216 }
217 }
218 132
219 /** 133 /**
220 * Load the plugin. 134 * Load the plugin.
221 */ 135 */
222 gboolean 136 gboolean
748 rc = msim_postprocess_outgoing(session, msg, who, "t", "cv"); 662 rc = msim_postprocess_outgoing(session, msg, who, "t", "cv");
749 663
750 msim_msg_free(msg); 664 msim_msg_free(msg);
751 665
752 return rc; 666 return rc;
753 }
754
755 /* Indexes of this array + 1 map HTML font size to scale of normal font size. *
756 * Based on _point_sizes from libpurple/gtkimhtml.c
757 * 1 2 3 4 5 6 7 */
758 static gdouble _font_scale[] = { .85, .95, 1, 1.2, 1.44, 1.728, 2.0736 };
759
760 #define MAX_FONT_SIZE 7 /* Purple maximum font size */
761 #define POINTS_PER_INCH 72 /* How many pt's in an inch */
762
763 /** Convert typographical font point size to HTML font size.
764 * Based on libpurple/gtkimhtml.c */
765 static guint
766 msim_point_to_purple_size(MsimSession *session, guint point)
767 {
768 guint size, this_point, base;
769 gdouble scale;
770
771 base = purple_account_get_int(session->account, "base_font_size", MSIM_BASE_FONT_POINT_SIZE);
772
773 for (size = 0;
774 size < sizeof(_font_scale) / sizeof(_font_scale[0]);
775 ++size) {
776 scale = _font_scale[CLAMP(size, 1, MAX_FONT_SIZE) - 1];
777 this_point = (guint)msim_round(scale * base);
778
779 if (this_point >= point) {
780 purple_debug_info("msim", "msim_point_to_purple_size: %d pt -> size=%d\n",
781 point, size);
782 return size;
783 }
784 }
785
786 /* No HTML font size was this big; return largest possible. */
787 return this_point;
788 }
789
790 /** Convert HTML font size to point size. */
791 static guint
792 msim_purple_size_to_point(MsimSession *session, guint size)
793 {
794 gdouble scale;
795 guint point;
796 guint base;
797
798 scale = _font_scale[CLAMP(size, 1, MAX_FONT_SIZE) - 1];
799
800 base = purple_account_get_int(session->account, "base_font_size", MSIM_BASE_FONT_POINT_SIZE);
801
802 point = (guint)msim_round(scale * base);
803
804 purple_debug_info("msim", "msim_purple_size_to_point: size=%d -> %d pt\n",
805 size, point);
806
807 return point;
808 }
809
810 /** Convert a msim markup font pixel height to the more usual point size, for incoming messages. */
811 static guint
812 msim_height_to_point(MsimSession *session, guint height)
813 {
814 guint dpi;
815
816 dpi = purple_account_get_int(session->account, "port", MSIM_DEFAULT_DPI);
817
818 return (guint)msim_round((POINTS_PER_INCH * 1. / dpi) * height);
819
820 /* See also: libpurple/protocols/bonjour/jabber.c
821 * _font_size_ichat_to_purple */
822 }
823
824 /** Convert point size to msim pixel height font size specification, for outgoing messages. */
825 static guint
826 msim_point_to_height(MsimSession *session, guint point)
827 {
828 guint dpi;
829
830 dpi = purple_account_get_int(session->account, "port", MSIM_DEFAULT_DPI);
831
832 return (guint)msim_round((dpi * 1. / POINTS_PER_INCH) * point);
833 }
834
835 /** Convert the msim markup <f> (font) tag into HTML. */
836 static void
837 msim_markup_f_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
838 {
839 const gchar *face, *height_str, *decor_str;
840 GString *gs_end, *gs_begin;
841 guint decor, height;
842
843 face = xmlnode_get_attrib(root, "f");
844 height_str = xmlnode_get_attrib(root, "h");
845 decor_str = xmlnode_get_attrib(root, "s");
846
847 if (height_str) {
848 height = atol(height_str);
849 } else {
850 height = 12;
851 }
852
853 if (decor_str) {
854 decor = atol(decor_str);
855 } else {
856 decor = 0;
857 }
858
859 gs_begin = g_string_new("");
860 /* TODO: get font size working */
861 if (height && !face) {
862 g_string_printf(gs_begin, "<font size='%d'>",
863 msim_point_to_purple_size(session, msim_height_to_point(session, height)));
864 } else if (height && face) {
865 g_string_printf(gs_begin, "<font face='%s' size='%d'>", face,
866 msim_point_to_purple_size(session, msim_height_to_point(session, height)));
867 } else {
868 g_string_printf(gs_begin, "<font>");
869 }
870
871 /* No support for font-size CSS? */
872 /* g_string_printf(gs_begin, "<span style='font-family: %s; font-size: %dpt'>", face,
873 msim_height_to_point(height)); */
874
875 gs_end = g_string_new("</font>");
876
877 if (decor & MSIM_TEXT_BOLD) {
878 g_string_append(gs_begin, "<b>");
879 g_string_prepend(gs_end, "</b>");
880 }
881
882 if (decor & MSIM_TEXT_ITALIC) {
883 g_string_append(gs_begin, "<i>");
884 g_string_append(gs_end, "</i>");
885 }
886
887 if (decor & MSIM_TEXT_UNDERLINE) {
888 g_string_append(gs_begin, "<u>");
889 g_string_append(gs_end, "</u>");
890 }
891
892
893 *begin = gs_begin->str;
894 *end = gs_end->str;
895 }
896
897 /** Convert a msim markup color to a color suitable for libpurple.
898 *
899 * @param msim Either a color name, or an rgb(x,y,z) code.
900 *
901 * @return A new string, either a color name or #rrggbb code. Must g_free().
902 */
903 static char *
904 msim_color_to_purple(const char *msim)
905 {
906 guint red, green, blue;
907
908 if (!msim) {
909 return g_strdup("black");
910 }
911
912 if (sscanf(msim, "rgb(%d,%d,%d)", &red, &green, &blue) != 3) {
913 /* Color name. */
914 return g_strdup(msim);
915 }
916 /* TODO: rgba (alpha). */
917
918 return g_strdup_printf("#%.2x%.2x%.2x", red, green, blue);
919 }
920
921 /** Convert the msim markup <a> (anchor) tag into HTML. */
922 static void
923 msim_markup_a_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
924 {
925 const gchar *href;
926
927 href = xmlnode_get_attrib(root, "h");
928 if (!href) {
929 href = "";
930 }
931
932 *begin = g_strdup_printf("<a href=\"%s\">%s", href, href);
933 *end = g_strdup("</a>");
934 }
935
936 /** Convert the msim markup <p> (paragraph) tag into HTML. */
937 static void
938 msim_markup_p_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
939 {
940 /* Just pass through unchanged.
941 *
942 * Note: attributes currently aren't passed, if there are any. */
943 *begin = g_strdup("<p>");
944 *end = g_strdup("</p>");
945 }
946
947 /** Convert the msim markup <c> tag (text color) into HTML. TODO: Test */
948 static void
949 msim_markup_c_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
950 {
951 const gchar *color;
952 gchar *purple_color;
953
954 color = xmlnode_get_attrib(root, "v");
955 if (!color) {
956 purple_debug_info("msim", "msim_markup_c_to_html: <c> tag w/o v attr");
957 *begin = g_strdup("");
958 *end = g_strdup("");
959 /* TODO: log as unrecognized */
960 return;
961 }
962
963 purple_color = msim_color_to_purple(color);
964
965 *begin = g_strdup_printf("<font color='%s'>", purple_color);
966
967 g_free(purple_color);
968
969 /* *begin = g_strdup_printf("<span style='color: %s'>", color); */
970 *end = g_strdup("</font>");
971 }
972
973 /** Convert the msim markup <b> tag (background color) into HTML. TODO: Test */
974 static void
975 msim_markup_b_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
976 {
977 const gchar *color;
978 gchar *purple_color;
979
980 color = xmlnode_get_attrib(root, "v");
981 if (!color) {
982 *begin = g_strdup("");
983 *end = g_strdup("");
984 purple_debug_info("msim", "msim_markup_b_to_html: <b> w/o v attr");
985 /* TODO: log as unrecognized. */
986 return;
987 }
988
989 purple_color = msim_color_to_purple(color);
990
991 /* TODO: find out how to set background color. */
992 *begin = g_strdup_printf("<span style='background-color: %s'>",
993 purple_color);
994 g_free(purple_color);
995
996 *end = g_strdup("</p>");
997 }
998
999 /** Convert the msim markup <i> tag (emoticon image) into HTML. */
1000 static void
1001 msim_markup_i_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
1002 {
1003 const gchar *name;
1004 guint i;
1005 struct MSIM_EMOTICON *emote;
1006
1007 name = xmlnode_get_attrib(root, "n");
1008 if (!name) {
1009 purple_debug_info("msim", "msim_markup_i_to_html: <i> w/o n");
1010 *begin = g_strdup("");
1011 *end = g_strdup("");
1012 /* TODO: log as unrecognized */
1013 return;
1014 }
1015
1016 /* Find and use canonical form of smiley symbol. */
1017 for (i = 0; (emote = &msim_emoticons[i]) && emote->name != NULL; ++i) {
1018 if (g_str_equal(name, emote->name)) {
1019 *begin = g_strdup(emote->symbol);
1020 *end = g_strdup("");
1021 return;
1022 }
1023 }
1024
1025 /* Couldn't find it, sorry. Try to degrade gracefully. */
1026 *begin = g_strdup_printf("**%s**", name);
1027 *end = g_strdup("");
1028 }
1029
1030 /** Convert an individual msim markup tag to HTML. */
1031 static void
1032 msim_markup_tag_to_html(MsimSession *session, xmlnode *root, gchar **begin,
1033 gchar **end)
1034 {
1035 if (g_str_equal(root->name, "f")) {
1036 msim_markup_f_to_html(session, root, begin, end);
1037 } else if (g_str_equal(root->name, "a")) {
1038 msim_markup_a_to_html(session, root, begin, end);
1039 } else if (g_str_equal(root->name, "p")) {
1040 msim_markup_p_to_html(session, root, begin, end);
1041 } else if (g_str_equal(root->name, "c")) {
1042 msim_markup_c_to_html(session, root, begin, end);
1043 } else if (g_str_equal(root->name, "b")) {
1044 msim_markup_b_to_html(session, root, begin, end);
1045 } else if (g_str_equal(root->name, "i")) {
1046 msim_markup_i_to_html(session, root, begin, end);
1047 } else {
1048 purple_debug_info("msim", "msim_markup_tag_to_html: "
1049 "unknown tag name=%s, ignoring",
1050 (root && root->name) ? root->name : "(NULL)");
1051 *begin = g_strdup("");
1052 *end = g_strdup("");
1053 }
1054 }
1055
1056 /** Convert an individual HTML tag to msim markup. */
1057 static void
1058 html_tag_to_msim_markup(MsimSession *session, xmlnode *root, gchar **begin,
1059 gchar **end)
1060 {
1061 /* TODO: Coalesce nested tags into one <f> tag!
1062 * Currently, the 's' value will be overwritten when b/i/u is nested
1063 * within another one, and only the inner-most formatting will be
1064 * applied to the text. */
1065 if (!purple_utf8_strcasecmp(root->name, "root")) {
1066 *begin = g_strdup("");
1067 *end = g_strdup("");
1068 } else if (!purple_utf8_strcasecmp(root->name, "b")) {
1069 *begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_BOLD);
1070 *end = g_strdup("</f>");
1071 } else if (!purple_utf8_strcasecmp(root->name, "i")) {
1072 *begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_ITALIC);
1073 *end = g_strdup("</f>");
1074 } else if (!purple_utf8_strcasecmp(root->name, "u")) {
1075 *begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_UNDERLINE);
1076 *end = g_strdup("</f>");
1077 } else if (!purple_utf8_strcasecmp(root->name, "a")) {
1078 const gchar *href, *link_text;
1079
1080 href = xmlnode_get_attrib(root, "href");
1081
1082 if (!href) {
1083 href = xmlnode_get_attrib(root, "HREF");
1084 }
1085
1086 link_text = xmlnode_get_data(root);
1087
1088 if (href) {
1089 if (g_str_equal(link_text, href)) {
1090 /* Purple gives us: <a href="URL">URL</a>
1091 * Translate to <a h='URL' />
1092 * Displayed as text of URL with link to URL
1093 */
1094 *begin = g_strdup_printf("<a h='%s' />", href);
1095 } else {
1096 /* But if we get: <a href="URL">text</a>
1097 * Translate to: text: <a h='URL' />
1098 *
1099 * Because official client only supports self-closed <a>
1100 * tags; you can't change the link text.
1101 */
1102 *begin = g_strdup_printf("%s: <a h='%s' />", link_text, href);
1103 }
1104 } else {
1105 *begin = g_strdup("<a />");
1106 }
1107
1108 /* Sorry, kid. MySpace doesn't support you within <a> tags. */
1109 xmlnode_free(root->child);
1110 root->child = NULL;
1111
1112 *end = g_strdup("");
1113 } else if (!purple_utf8_strcasecmp(root->name, "font")) {
1114 const gchar *size;
1115 const gchar *face;
1116
1117 size = xmlnode_get_attrib(root, "size");
1118 face = xmlnode_get_attrib(root, "face");
1119
1120 if (face && size) {
1121 *begin = g_strdup_printf("<f f='%s' h='%d'>", face,
1122 msim_point_to_height(session,
1123 msim_purple_size_to_point(session, atoi(size))));
1124 } else if (face) {
1125 *begin = g_strdup_printf("<f f='%s'>", face);
1126 } else if (size) {
1127 *begin = g_strdup_printf("<f h='%d'>",
1128 msim_point_to_height(session,
1129 msim_purple_size_to_point(session, atoi(size))));
1130 } else {
1131 *begin = g_strdup("<f>");
1132 }
1133
1134 *end = g_strdup("</f>");
1135
1136 /* TODO: color (bg uses <body>), emoticons */
1137 } else {
1138 *begin = g_strdup_printf("[%s]", root->name);
1139 *end = g_strdup_printf("[/%s]", root->name);
1140 }
1141 }
1142
1143 /** Convert an xmlnode of msim markup or HTML to an HTML string or msim markup.
1144 *
1145 * @param f Function to convert tags.
1146 *
1147 * @return An HTML string. Caller frees.
1148 */
1149 static gchar *
1150 msim_convert_xmlnode(MsimSession *session, xmlnode *root, MSIM_XMLNODE_CONVERT f)
1151 {
1152 xmlnode *node;
1153 gchar *begin, *inner, *end;
1154 GString *final;
1155
1156 if (!root || !root->name) {
1157 return g_strdup("");
1158 }
1159
1160 purple_debug_info("msim", "msim_convert_xmlnode: got root=%s\n",
1161 root->name);
1162
1163 begin = inner = end = NULL;
1164
1165 final = g_string_new("");
1166
1167 f(session, root, &begin, &end);
1168
1169 g_string_append(final, begin);
1170
1171 /* Loop over all child nodes. */
1172 for (node = root->child; node != NULL; node = node->next) {
1173 switch (node->type) {
1174 case XMLNODE_TYPE_ATTRIB:
1175 /* Attributes handled above. */
1176 break;
1177
1178 case XMLNODE_TYPE_TAG:
1179 /* A tag or tag with attributes. Recursively descend. */
1180 inner = msim_convert_xmlnode(session, node, f);
1181 g_return_val_if_fail(inner != NULL, NULL);
1182
1183 purple_debug_info("msim", " ** node name=%s\n",
1184 (node && node->name) ? node->name : "(NULL)");
1185 break;
1186
1187 case XMLNODE_TYPE_DATA:
1188 /* Literal text. */
1189 inner = g_new0(char, node->data_sz + 1);
1190 strncpy(inner, node->data, node->data_sz);
1191 inner[node->data_sz] = 0;
1192
1193 purple_debug_info("msim", " ** node data=%s\n",
1194 inner ? inner : "(NULL)");
1195 break;
1196
1197 default:
1198 purple_debug_info("msim",
1199 "msim_convert_xmlnode: strange node\n");
1200 inner = g_strdup("");
1201 }
1202
1203 if (inner) {
1204 g_string_append(final, inner);
1205 }
1206 }
1207
1208 /* TODO: Note that msim counts each piece of text enclosed by <f> as
1209 * a paragraph and will display each on its own line. You actually have
1210 * to _nest_ <f> tags to intersperse different text in one paragraph!
1211 * Comment out this line below to see. */
1212 g_string_append(final, end);
1213
1214 purple_debug_info("msim", "msim_markup_xmlnode_to_gtkhtml: RETURNING %s\n",
1215 (final && final->str) ? final->str : "(NULL)");
1216
1217 return final->str;
1218 }
1219
1220 /** Convert XML to something based on MSIM_XMLNODE_CONVERT. */
1221 static gchar *
1222 msim_convert_xml(MsimSession *session, const gchar *raw, MSIM_XMLNODE_CONVERT f)
1223 {
1224 xmlnode *root;
1225 gchar *str;
1226 gchar *enclosed_raw;
1227
1228 g_return_val_if_fail(raw != NULL, NULL);
1229
1230 /* Enclose text in one root tag, to try to make it valid XML for parsing. */
1231 enclosed_raw = g_strconcat("<root>", raw, "</root>", NULL);
1232
1233 root = xmlnode_from_str(enclosed_raw, -1);
1234
1235 if (!root) {
1236 purple_debug_info("msim", "msim_markup_to_html: couldn't parse "
1237 "%s as XML, returning raw: %s\n", enclosed_raw, raw);
1238 /* TODO: msim_unrecognized */
1239 g_free(enclosed_raw);
1240 return g_strdup(raw);
1241 }
1242
1243 g_free(enclosed_raw);
1244
1245 str = msim_convert_xmlnode(session, root, f);
1246 g_return_val_if_fail(str != NULL, NULL);
1247 purple_debug_info("msim", "msim_markup_to_html: returning %s\n", str);
1248
1249 xmlnode_free(root);
1250
1251 return str;
1252 }
1253
1254 /** Convert plaintext smileys to <i> markup tags.
1255 *
1256 * @param before Original text with ASCII smileys. Will be freed.
1257 * @return A new string with <i> tags, if applicable. Must be g_free()'d.
1258 */
1259 static gchar *
1260 msim_convert_smileys_to_markup(gchar *before)
1261 {
1262 gchar *old, *new, *replacement;
1263 guint i;
1264 struct MSIM_EMOTICON *emote;
1265
1266 old = before;
1267 new = NULL;
1268
1269 for (i = 0; (emote = &msim_emoticons[i]) && emote->name != NULL; ++i) {
1270 gchar *name, *symbol;
1271
1272 name = emote->name;
1273 symbol = emote->symbol;
1274
1275 replacement = g_strdup_printf("<i n=\"%s\"/>", name);
1276
1277 purple_debug_info("msim", "msim_convert_smileys_to_markup: %s->%s\n",
1278 symbol ? symbol : "(NULL)",
1279 replacement ? replacement : "(NULL)");
1280 new = str_replace(old, symbol, replacement);
1281
1282 g_free(replacement);
1283 g_free(old);
1284
1285 old = new;
1286 }
1287
1288 return new;
1289 }
1290
1291
1292 /** High-level function to convert MySpaceIM markup to Purple (HTML) markup.
1293 *
1294 * @return Purple markup string, must be g_free()'d. */
1295 static gchar *
1296 msim_markup_to_html(MsimSession *session, const gchar *raw)
1297 {
1298 return msim_convert_xml(session, raw,
1299 (MSIM_XMLNODE_CONVERT)(msim_markup_tag_to_html));
1300 }
1301
1302 /** High-level function to convert Purple (HTML) to MySpaceIM markup.
1303 *
1304 * @return HTML markup string, must be g_free()'d. */
1305 static gchar *
1306 html_to_msim_markup(MsimSession *session, const gchar *raw)
1307 {
1308 gchar *markup;
1309
1310 markup = msim_convert_xml(session, raw,
1311 (MSIM_XMLNODE_CONVERT)(html_tag_to_msim_markup));
1312
1313 if (purple_account_get_bool(session->account, "emoticons", TRUE)) {
1314 /* Frees markup and allocates a new one. */
1315 markup = msim_convert_smileys_to_markup(markup);
1316 }
1317
1318 return markup;
1319 } 667 }
1320 668
1321 /** Get the MsimUser from a PurpleBuddy, creating it if needed. */ 669 /** Get the MsimUser from a PurpleBuddy, creating it if needed. */
1322 static MsimUser * 670 static MsimUser *
1323 msim_get_user_from_buddy(PurpleBuddy *buddy) 671 msim_get_user_from_buddy(PurpleBuddy *buddy)