Mercurial > pidgin.yaz
comparison pidgin/gtkconv.c @ 16083:f2a4b05407d7
Patch from shlomil in ticket #78.
This fixes RTL text support in MSN, and lays the framework so it could be
supported in other prpls as well. As added pluses, shlomil removed some
duplicate code and fixed some small related bugs.
committer: Richard Laager <rlaager@wiktel.com>
author | Shlomi Loubaton <shlomister@gmail.com> |
---|---|
date | Fri, 13 Apr 2007 04:13:24 +0000 |
parents | 07554cc5d090 |
children | a5a831a5f186 |
comparison
equal
deleted
inserted
replaced
16082:7a7377a86ad1 | 16083:f2a4b05407d7 |
---|---|
4893 tm->tm_mday++; | 4893 tm->tm_mday++; |
4894 | 4894 |
4895 gtkconv->newday = mktime(tm); | 4895 gtkconv->newday = mktime(tm); |
4896 } | 4896 } |
4897 | 4897 |
4898 /* Detect string direction and encapsulate the string in a RLE/LRE/PDF unicode characters | |
4899 str - pointer to string (string is realocated and new pointer is returned) */ | |
4900 static void | |
4901 str_embed_direction_chars(char **str) | |
4902 { | |
4903 char pre_str[4]; | |
4904 char post_str[10]; | |
4905 char* ret = g_malloc(strlen(*str)+13); | |
4906 | |
4907 if (PANGO_DIRECTION_RTL == pango_find_base_dir(*str, strlen(*str))) | |
4908 { | |
4909 g_sprintf(pre_str, "%c%c%c", | |
4910 0xE2, 0x80, 0xAB); /* RLE */ | |
4911 g_sprintf(post_str, "%c%c%c%c%c%c%c%c%c", | |
4912 0xE2, 0x80, 0xAC, /* PDF */ | |
4913 0xE2, 0x80, 0x8E, /* LRM */ | |
4914 0xE2, 0x80, 0xAC); /* PDF */ | |
4915 } | |
4916 else | |
4917 { | |
4918 g_sprintf(pre_str, "%c%c%c", | |
4919 0xE2, 0x80, 0xAA); /* LRE */ | |
4920 g_sprintf(post_str, "%c%c%c%c%c%c%c%c%c", | |
4921 0xE2, 0x80, 0xAC, /* PDF */ | |
4922 0xE2, 0x80, 0x8F, /* RLM */ | |
4923 0xE2, 0x80, 0xAC); /* PDF */ | |
4924 } | |
4925 | |
4926 g_sprintf(ret, "%s%s%s", pre_str, *str, post_str); | |
4927 | |
4928 g_free(*str); | |
4929 *str = ret; | |
4930 return; | |
4931 } | |
4932 | |
4933 /* Returns true if the given HTML contains RTL text */ | |
4934 static gboolean | |
4935 html_is_rtl(const char *html) | |
4936 { | |
4937 GData *attributes; | |
4938 const gchar *start, *end; | |
4939 gboolean res = FALSE; | |
4940 | |
4941 if(purple_markup_find_tag("span", html, &start, &end, &attributes)) | |
4942 { | |
4943 /* tmp is a member of attributes and is free with g_datalist_clear call */ | |
4944 const char *tmp = g_datalist_get_data(&attributes, "dir"); | |
4945 if(tmp && !g_ascii_strcasecmp(tmp, "RTL")) | |
4946 res = TRUE; | |
4947 if(!res) | |
4948 { | |
4949 char *tmp2 = NULL; | |
4950 tmp = g_datalist_get_data(&attributes, "style"); | |
4951 if(tmp) | |
4952 tmp2 = purple_markup_get_css_property(tmp, "direction"); | |
4953 if(tmp2 && !g_ascii_strcasecmp(tmp2, "RTL")) | |
4954 res = TRUE; | |
4955 if(tmp2) | |
4956 g_free(tmp2); | |
4957 | |
4958 } | |
4959 g_datalist_clear(&attributes); | |
4960 } | |
4961 return res; | |
4962 } | |
4963 | |
4964 | |
4898 static void | 4965 static void |
4899 pidgin_conv_write_conv(PurpleConversation *conv, const char *name, const char *alias, | 4966 pidgin_conv_write_conv(PurpleConversation *conv, const char *name, const char *alias, |
4900 const char *message, PurpleMessageFlags flags, | 4967 const char *message, PurpleMessageFlags flags, |
4901 time_t mtime) | 4968 time_t mtime) |
4902 { | 4969 { |
4920 PurpleConversationType type; | 4987 PurpleConversationType type; |
4921 char *displaying; | 4988 char *displaying; |
4922 gboolean plugin_return; | 4989 gboolean plugin_return; |
4923 char *bracket; | 4990 char *bracket; |
4924 int tag_count = 0; | 4991 int tag_count = 0; |
4992 gboolean is_rtl_message = FALSE; | |
4925 | 4993 |
4926 g_return_if_fail(conv != NULL); | 4994 g_return_if_fail(conv != NULL); |
4927 gtkconv = PIDGIN_CONVERSATION(conv); | 4995 gtkconv = PIDGIN_CONVERSATION(conv); |
4928 g_return_if_fail(gtkconv != NULL); | 4996 g_return_if_fail(gtkconv != NULL); |
4929 | 4997 |
5032 conv, mtime, show_date); | 5100 conv, mtime, show_date); |
5033 | 5101 |
5034 if (mdate == NULL) | 5102 if (mdate == NULL) |
5035 { | 5103 { |
5036 struct tm *tm = localtime(&mtime); | 5104 struct tm *tm = localtime(&mtime); |
5105 const char *tmp; | |
5037 if (show_date) | 5106 if (show_date) |
5038 mdate = g_strdup(purple_date_format_long(tm)); | 5107 tmp = purple_date_format_long(tm); |
5039 else | 5108 else |
5040 mdate = g_strdup(purple_time_format(tm)); | 5109 tmp = purple_time_format(tm); |
5041 } | 5110 mdate = g_strdup_printf("(%s)", tmp); |
5111 } | |
5112 | |
5113 /* Bi-Directional support - set timestamp direction using unicode characters */ | |
5114 is_rtl_message = html_is_rtl(message); | |
5115 /* Enforce direction only if message is RTL - donesn't effect LTR users */ | |
5116 if(is_rtl_message) | |
5117 str_embed_direction_chars(&mdate); | |
5042 | 5118 |
5043 if (mtime >= gtkconv->newday) | 5119 if (mtime >= gtkconv->newday) |
5044 pidgin_conv_calculate_newday(gtkconv, mtime); | 5120 pidgin_conv_calculate_newday(gtkconv, mtime); |
5045 | 5121 |
5046 sml_attrib = g_strdup_printf("sml=\"%s\"", purple_account_get_protocol_name(account)); | 5122 sml_attrib = g_strdup_printf("sml=\"%s\"", purple_account_get_protocol_name(account)); |
5061 /* TODO: These colors should not be hardcoded so log.c can use them */ | 5137 /* TODO: These colors should not be hardcoded so log.c can use them */ |
5062 if (flags & PURPLE_MESSAGE_RAW) { | 5138 if (flags & PURPLE_MESSAGE_RAW) { |
5063 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), message, gtk_font_options_all); | 5139 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), message, gtk_font_options_all); |
5064 } else if (flags & PURPLE_MESSAGE_SYSTEM) { | 5140 } else if (flags & PURPLE_MESSAGE_SYSTEM) { |
5065 g_snprintf(buf2, sizeof(buf2), | 5141 g_snprintf(buf2, sizeof(buf2), |
5066 "<FONT %s><FONT SIZE=\"2\"><!--(%s) --></FONT><B>%s</B></FONT>", | 5142 "<FONT %s><FONT SIZE=\"2\"><!--%s --></FONT><B>%s</B></FONT>", |
5067 sml_attrib ? sml_attrib : "", mdate, displaying); | 5143 sml_attrib ? sml_attrib : "", mdate, displaying); |
5068 | 5144 |
5069 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all); | 5145 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all); |
5070 | 5146 |
5071 } else if (flags & PURPLE_MESSAGE_ERROR) { | 5147 } else if (flags & PURPLE_MESSAGE_ERROR) { |
5072 g_snprintf(buf2, sizeof(buf2), | 5148 g_snprintf(buf2, sizeof(buf2), |
5073 "<FONT COLOR=\"#ff0000\"><FONT %s><FONT SIZE=\"2\"><!--(%s) --></FONT><B>%s</B></FONT></FONT>", | 5149 "<FONT COLOR=\"#ff0000\"><FONT %s><FONT SIZE=\"2\"><!--%s --></FONT><B>%s</B></FONT></FONT>", |
5074 sml_attrib ? sml_attrib : "", mdate, displaying); | 5150 sml_attrib ? sml_attrib : "", mdate, displaying); |
5075 | 5151 |
5076 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all); | 5152 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all); |
5077 | 5153 |
5078 } else if (flags & PURPLE_MESSAGE_NO_LOG) { | 5154 } else if (flags & PURPLE_MESSAGE_NO_LOG) { |
5088 * escaped entities making the string longer */ | 5164 * escaped entities making the string longer */ |
5089 int tag_start_offset = alias ? (strlen(alias_escaped) - strlen(alias)) : 0; | 5165 int tag_start_offset = alias ? (strlen(alias_escaped) - strlen(alias)) : 0; |
5090 int tag_end_offset = 0; | 5166 int tag_end_offset = 0; |
5091 GtkSmileyTree *tree = NULL; | 5167 GtkSmileyTree *tree = NULL; |
5092 GHashTable *smiley_data = NULL; | 5168 GHashTable *smiley_data = NULL; |
5169 | |
5170 /* Enforce direction on alias */ | |
5171 if(is_rtl_message) | |
5172 str_embed_direction_chars(&alias_escaped); | |
5093 | 5173 |
5094 if (flags & PURPLE_MESSAGE_SEND) | 5174 if (flags & PURPLE_MESSAGE_SEND) |
5095 { | 5175 { |
5096 /* Temporarily revert to the original smiley-data to avoid showing up | 5176 /* Temporarily revert to the original smiley-data to avoid showing up |
5097 * custom smileys of the buddy when sending message | 5177 * custom smileys of the buddy when sending message |
5176 /* Bold buddies to make them stand out from non-buddies. */ | 5256 /* Bold buddies to make them stand out from non-buddies. */ |
5177 if (flags & PURPLE_MESSAGE_SEND || | 5257 if (flags & PURPLE_MESSAGE_SEND || |
5178 flags & PURPLE_MESSAGE_NICK || | 5258 flags & PURPLE_MESSAGE_NICK || |
5179 purple_find_buddy(account, name) != NULL) { | 5259 purple_find_buddy(account, name) != NULL) { |
5180 g_snprintf(buf2, BUF_LONG, | 5260 g_snprintf(buf2, BUF_LONG, |
5181 "<FONT COLOR=\"%s\" %s><FONT SIZE=\"2\"><!--(%s) --></FONT>" | 5261 "<FONT COLOR=\"%s\" %s><FONT SIZE=\"2\"><!--%s --></FONT>" |
5182 "<B>%s</B></FONT> ", | 5262 "<B>%s</B></FONT> ", |
5183 color, sml_attrib ? sml_attrib : "", mdate, str); | 5263 color, sml_attrib ? sml_attrib : "", mdate, str); |
5184 } else { | 5264 } else { |
5185 g_snprintf(buf2, BUF_LONG, | 5265 g_snprintf(buf2, BUF_LONG, |
5186 "<FONT COLOR=\"%s\" %s><FONT SIZE=\"2\"><!--(%s) --></FONT>" | 5266 "<FONT COLOR=\"%s\" %s><FONT SIZE=\"2\"><!--%s --></FONT>" |
5187 "%s</FONT> ", | 5267 "%s</FONT> ", |
5188 color, sml_attrib ? sml_attrib : "", mdate, str); | 5268 color, sml_attrib ? sml_attrib : "", mdate, str); |
5189 | 5269 |
5190 } | 5270 } |
5191 } else { | 5271 } else { |
5192 /* Bold everyone's name to make the name stand out from the message. */ | 5272 /* Bold everyone's name to make the name stand out from the message. */ |
5193 g_snprintf(buf2, BUF_LONG, | 5273 g_snprintf(buf2, BUF_LONG, |
5194 "<FONT COLOR=\"%s\" %s><FONT SIZE=\"2\"><!--(%s) --></FONT>" | 5274 "<FONT COLOR=\"%s\" %s><FONT SIZE=\"2\"><!--%s --></FONT>" |
5195 "<B>%s</B></FONT> ", | 5275 "<B>%s</B></FONT> ", |
5196 color, sml_attrib ? sml_attrib : "", mdate, str); | 5276 color, sml_attrib ? sml_attrib : "", mdate, str); |
5197 } | 5277 } |
5198 | 5278 |
5199 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all); | 5279 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all); |