| 1642 else if (purple_str_has_suffix(basename, ".desktop") && (item = purple_desktop_item_new_from_file(filename))) { |
1640 else if (purple_str_has_suffix(basename, ".desktop") && (item = purple_desktop_item_new_from_file(filename))) { |
| 1643 PurpleDesktopItemType dtype; |
1641 PurpleDesktopItemType dtype; |
| 1644 char key[64]; |
1642 char key[64]; |
| 1645 const char *itemname = NULL; |
1643 const char *itemname = NULL; |
| 1646 |
1644 |
| 1647 #if GTK_CHECK_VERSION(2,6,0) |
|
| 1648 const char * const *langs; |
1645 const char * const *langs; |
| 1649 int i; |
1646 int i; |
| 1650 langs = g_get_language_names(); |
1647 langs = g_get_language_names(); |
| 1651 for (i = 0; langs[i]; i++) { |
1648 for (i = 0; langs[i]; i++) { |
| 1652 g_snprintf(key, sizeof(key), "Name[%s]", langs[i]); |
1649 g_snprintf(key, sizeof(key), "Name[%s]", langs[i]); |
| 1653 itemname = purple_desktop_item_get_string(item, key); |
1650 itemname = purple_desktop_item_get_string(item, key); |
| 1654 break; |
1651 break; |
| 1655 } |
1652 } |
| 1656 #else |
1653 |
| 1657 const char *lang = g_getenv("LANG"); |
|
| 1658 char *dot; |
|
| 1659 dot = strchr(lang, '.'); |
|
| 1660 if (dot) |
|
| 1661 *dot = '\0'; |
|
| 1662 g_snprintf(key, sizeof(key), "Name[%s]", lang); |
|
| 1663 itemname = purple_desktop_item_get_string(item, key); |
|
| 1664 #endif |
|
| 1665 if (!itemname) |
1654 if (!itemname) |
| 1666 itemname = purple_desktop_item_get_string(item, "Name"); |
1655 itemname = purple_desktop_item_get_string(item, "Name"); |
| 1667 |
1656 |
| 1668 dtype = purple_desktop_item_get_entry_type(item); |
1657 dtype = purple_desktop_item_get_entry_type(item); |
| 1669 switch (dtype) { |
1658 switch (dtype) { |
| 1676 gtk_imhtml_insert_link(GTK_IMHTML(gtkconv->entry), |
1665 gtk_imhtml_insert_link(GTK_IMHTML(gtkconv->entry), |
| 1677 gtk_text_buffer_get_insert(GTK_IMHTML(gtkconv->entry)->text_buffer), |
1666 gtk_text_buffer_get_insert(GTK_IMHTML(gtkconv->entry)->text_buffer), |
| 1678 purple_desktop_item_get_string(item, "URL"), itemname); |
1667 purple_desktop_item_get_string(item, "URL"), itemname); |
| 1679 break; |
1668 break; |
| 1680 default: |
1669 default: |
| 1681 /* I don't know if we really want to do anything here. Most of the desktop item types are crap like |
1670 /* I don't know if we really want to do anything here. Most of |
| 1682 * "MIME Type" (I have no clue how that would be a desktop item) and "Comment"... nothing we can really |
1671 * the desktop item types are crap like "MIME Type" (I have no |
| 1683 * send. The only logical one is "Application," but do we really want to send a binary and nothing else? |
1672 * clue how that would be a desktop item) and "Comment"... |
| 1684 * Probably not. I'll just give an error and return. */ |
1673 * nothing we can really send. The only logical one is |
| |
1674 * "Application," but do we really want to send a binary and |
| |
1675 * nothing else? Probably not. I'll just give an error and |
| |
1676 * return. */ |
| 1685 /* The original patch sent the icon used by the launcher. That's probably wrong */ |
1677 /* The original patch sent the icon used by the launcher. That's probably wrong */ |
| 1686 purple_notify_error(NULL, NULL, _("Cannot send launcher"), |
1678 purple_notify_error(NULL, NULL, _("Cannot send launcher"), |
| 1687 _("You dragged a desktop launcher. Most " |
1679 _("You dragged a desktop launcher. Most " |
| 1688 "likely you wanted to send the target " |
1680 "likely you wanted to send the target " |
| 1689 "of this launcher instead of this " |
1681 "of this launcher instead of this " |
| 1874 } |
1866 } |
| 1875 purple_menu_action_free(act); |
1867 purple_menu_action_free(act); |
| 1876 return menuitem; |
1868 return menuitem; |
| 1877 } |
1869 } |
| 1878 |
1870 |
| 1879 #if GTK_CHECK_VERSION(2,3,0) |
|
| 1880 # define NEW_STYLE_COMPLETION |
|
| 1881 #endif |
|
| 1882 |
|
| 1883 typedef struct |
1871 typedef struct |
| 1884 { |
1872 { |
| 1885 GtkWidget *entry; |
1873 GtkWidget *entry; |
| 1886 GtkWidget *accountopt; |
1874 GtkWidget *accountopt; |
| 1887 |
1875 |
| 1888 PidginFilterBuddyCompletionEntryFunc filter_func; |
1876 PidginFilterBuddyCompletionEntryFunc filter_func; |
| 1889 gpointer filter_func_user_data; |
1877 gpointer filter_func_user_data; |
| 1890 |
1878 |
| 1891 #ifdef NEW_STYLE_COMPLETION |
|
| 1892 GtkListStore *store; |
1879 GtkListStore *store; |
| 1893 #else |
|
| 1894 GCompletion *completion; |
|
| 1895 gboolean completion_started; |
|
| 1896 GList *log_items; |
|
| 1897 #endif /* NEW_STYLE_COMPLETION */ |
|
| 1898 } PidginCompletionData; |
1880 } PidginCompletionData; |
| 1899 |
1881 |
| 1900 #ifndef NEW_STYLE_COMPLETION |
|
| 1901 static gboolean |
|
| 1902 completion_entry_event(GtkEditable *entry, GdkEventKey *event, |
|
| 1903 PidginCompletionData *data) |
|
| 1904 { |
|
| 1905 int pos, end_pos; |
|
| 1906 |
|
| 1907 if (event->type == GDK_KEY_PRESS && event->keyval == GDK_Tab) |
|
| 1908 { |
|
| 1909 gtk_editable_get_selection_bounds(entry, &pos, &end_pos); |
|
| 1910 |
|
| 1911 if (data->completion_started && |
|
| 1912 pos != end_pos && pos > 1 && |
|
| 1913 end_pos == strlen(gtk_entry_get_text(GTK_ENTRY(entry)))) |
|
| 1914 { |
|
| 1915 gtk_editable_select_region(entry, 0, 0); |
|
| 1916 gtk_editable_set_position(entry, -1); |
|
| 1917 |
|
| 1918 return TRUE; |
|
| 1919 } |
|
| 1920 } |
|
| 1921 else if (event->type == GDK_KEY_PRESS && event->length > 0) |
|
| 1922 { |
|
| 1923 char *prefix, *nprefix; |
|
| 1924 |
|
| 1925 gtk_editable_get_selection_bounds(entry, &pos, &end_pos); |
|
| 1926 |
|
| 1927 if (data->completion_started && |
|
| 1928 pos != end_pos && pos > 1 && |
|
| 1929 end_pos == strlen(gtk_entry_get_text(GTK_ENTRY(entry)))) |
|
| 1930 { |
|
| 1931 char *temp; |
|
| 1932 |
|
| 1933 temp = gtk_editable_get_chars(entry, 0, pos); |
|
| 1934 prefix = g_strconcat(temp, event->string, NULL); |
|
| 1935 g_free(temp); |
|
| 1936 } |
|
| 1937 else if (pos == end_pos && pos > 1 && |
|
| 1938 end_pos == strlen(gtk_entry_get_text(GTK_ENTRY(entry)))) |
|
| 1939 { |
|
| 1940 prefix = g_strconcat(gtk_entry_get_text(GTK_ENTRY(entry)), |
|
| 1941 event->string, NULL); |
|
| 1942 } |
|
| 1943 else |
|
| 1944 return FALSE; |
|
| 1945 |
|
| 1946 pos = strlen(prefix); |
|
| 1947 nprefix = NULL; |
|
| 1948 |
|
| 1949 g_completion_complete(data->completion, prefix, &nprefix); |
|
| 1950 |
|
| 1951 if (nprefix != NULL) |
|
| 1952 { |
|
| 1953 gtk_entry_set_text(GTK_ENTRY(entry), nprefix); |
|
| 1954 gtk_editable_set_position(entry, pos); |
|
| 1955 gtk_editable_select_region(entry, pos, -1); |
|
| 1956 |
|
| 1957 data->completion_started = TRUE; |
|
| 1958 |
|
| 1959 g_free(nprefix); |
|
| 1960 g_free(prefix); |
|
| 1961 |
|
| 1962 return TRUE; |
|
| 1963 } |
|
| 1964 |
|
| 1965 g_free(prefix); |
|
| 1966 } |
|
| 1967 |
|
| 1968 return FALSE; |
|
| 1969 } |
|
| 1970 |
|
| 1971 static void |
|
| 1972 destroy_completion_data(GtkWidget *w, PidginCompletionData *data) |
|
| 1973 { |
|
| 1974 g_list_foreach(data->completion->items, (GFunc)g_free, NULL); |
|
| 1975 g_completion_free(data->completion); |
|
| 1976 |
|
| 1977 g_free(data); |
|
| 1978 } |
|
| 1979 #endif /* !NEW_STYLE_COMPLETION */ |
|
| 1980 |
|
| 1981 #ifdef NEW_STYLE_COMPLETION |
|
| 1982 static gboolean buddyname_completion_match_func(GtkEntryCompletion *completion, |
1882 static gboolean buddyname_completion_match_func(GtkEntryCompletion *completion, |
| 1983 const gchar *key, GtkTreeIter *iter, gpointer user_data) |
1883 const gchar *key, GtkTreeIter *iter, gpointer user_data) |
| 1984 { |
1884 { |
| 1985 GtkTreeModel *model; |
1885 GtkTreeModel *model; |
| 1986 GValue val1; |
1886 GValue val1; |
| 2125 PidginBuddyCompletionEntry entry; |
2024 PidginBuddyCompletionEntry entry; |
| 2126 entry.is_buddy = FALSE; |
2025 entry.is_buddy = FALSE; |
| 2127 entry.entry.logged_buddy = set; |
2026 entry.entry.logged_buddy = set; |
| 2128 |
2027 |
| 2129 if (filter_func(&entry, user_data)) { |
2028 if (filter_func(&entry, user_data)) { |
| 2130 #ifdef NEW_STYLE_COMPLETION |
|
| 2131 add_buddyname_autocomplete_entry(data->store, |
2029 add_buddyname_autocomplete_entry(data->store, |
| 2132 NULL, NULL, set->account, set->name); |
2030 NULL, NULL, set->account, set->name); |
| 2133 #else |
|
| 2134 /* Steal the name for the GCompletion. */ |
|
| 2135 data->log_items = g_list_append(data->log_items, set->name); |
|
| 2136 set->name = set->normalized_name = NULL; |
|
| 2137 #endif /* NEW_STYLE_COMPLETION */ |
|
| 2138 } |
2031 } |
| 2139 } |
2032 } |
| 2140 } |
2033 } |
| 2141 |
2034 |
| 2142 static void |
2035 static void |
| 2145 PurpleBlistNode *gnode, *cnode, *bnode; |
2038 PurpleBlistNode *gnode, *cnode, *bnode; |
| 2146 PidginFilterBuddyCompletionEntryFunc filter_func = data->filter_func; |
2039 PidginFilterBuddyCompletionEntryFunc filter_func = data->filter_func; |
| 2147 gpointer user_data = data->filter_func_user_data; |
2040 gpointer user_data = data->filter_func_user_data; |
| 2148 GHashTable *sets; |
2041 GHashTable *sets; |
| 2149 |
2042 |
| 2150 #ifdef NEW_STYLE_COMPLETION |
|
| 2151 gtk_list_store_clear(data->store); |
2043 gtk_list_store_clear(data->store); |
| 2152 #else |
|
| 2153 GList *item = g_list_append(NULL, NULL); |
|
| 2154 |
|
| 2155 g_list_foreach(data->completion->items, (GFunc)g_free, NULL); |
|
| 2156 g_completion_clear_items(data->completion); |
|
| 2157 #endif /* NEW_STYLE_COMPLETION */ |
|
| 2158 |
2044 |
| 2159 for (gnode = purple_get_blist()->root; gnode != NULL; gnode = gnode->next) |
2045 for (gnode = purple_get_blist()->root; gnode != NULL; gnode = gnode->next) |
| 2160 { |
2046 { |
| 2161 if (!PURPLE_BLIST_NODE_IS_GROUP(gnode)) |
2047 if (!PURPLE_BLIST_NODE_IS_GROUP(gnode)) |
| 2162 continue; |
2048 continue; |
| 2171 PidginBuddyCompletionEntry entry; |
2057 PidginBuddyCompletionEntry entry; |
| 2172 entry.is_buddy = TRUE; |
2058 entry.is_buddy = TRUE; |
| 2173 entry.entry.buddy = (PurpleBuddy *) bnode; |
2059 entry.entry.buddy = (PurpleBuddy *) bnode; |
| 2174 |
2060 |
| 2175 if (filter_func(&entry, user_data)) { |
2061 if (filter_func(&entry, user_data)) { |
| 2176 #ifdef NEW_STYLE_COMPLETION |
|
| 2177 add_buddyname_autocomplete_entry(data->store, |
2062 add_buddyname_autocomplete_entry(data->store, |
| 2178 ((PurpleContact *)cnode)->alias, |
2063 ((PurpleContact *)cnode)->alias, |
| 2179 purple_buddy_get_contact_alias(entry.entry.buddy), |
2064 purple_buddy_get_contact_alias(entry.entry.buddy), |
| 2180 entry.entry.buddy->account, |
2065 entry.entry.buddy->account, |
| 2181 entry.entry.buddy->name |
2066 entry.entry.buddy->name |
| 2182 ); |
2067 ); |
| 2183 #else |
|
| 2184 item->data = g_strdup(entry.entry.buddy->name); |
|
| 2185 g_completion_add_items(data->completion, item); |
|
| 2186 #endif /* NEW_STYLE_COMPLETION */ |
|
| 2187 } |
2068 } |
| 2188 } |
2069 } |
| 2189 } |
2070 } |
| 2190 } |
2071 } |
| 2191 |
|
| 2192 #ifndef NEW_STYLE_COMPLETION |
|
| 2193 g_list_free(item); |
|
| 2194 data->log_items = NULL; |
|
| 2195 #endif /* NEW_STYLE_COMPLETION */ |
|
| 2196 |
2072 |
| 2197 sets = purple_log_get_log_sets(); |
2073 sets = purple_log_get_log_sets(); |
| 2198 g_hash_table_foreach(sets, (GHFunc)get_log_set_name, data); |
2074 g_hash_table_foreach(sets, (GHFunc)get_log_set_name, data); |
| 2199 g_hash_table_destroy(sets); |
2075 g_hash_table_destroy(sets); |
| 2200 |
2076 |
| 2201 #ifndef NEW_STYLE_COMPLETION |
|
| 2202 g_completion_add_items(data->completion, data->log_items); |
|
| 2203 g_list_free(data->log_items); |
|
| 2204 #endif /* NEW_STYLE_COMPLETION */ |
|
| 2205 } |
2077 } |
| 2206 |
2078 |
| 2207 static void |
2079 static void |
| 2208 buddyname_autocomplete_destroyed_cb(GtkWidget *widget, gpointer data) |
2080 buddyname_autocomplete_destroyed_cb(GtkWidget *widget, gpointer data) |
| 2209 { |
2081 { |
| 2264 gtk_entry_completion_set_model(completion, GTK_TREE_MODEL(store)); |
2135 gtk_entry_completion_set_model(completion, GTK_TREE_MODEL(store)); |
| 2265 g_object_unref(store); |
2136 g_object_unref(store); |
| 2266 |
2137 |
| 2267 gtk_entry_completion_set_text_column(completion, 0); |
2138 gtk_entry_completion_set_text_column(completion, 0); |
| 2268 |
2139 |
| 2269 #else /* !NEW_STYLE_COMPLETION */ |
|
| 2270 |
|
| 2271 data = g_new0(PidginCompletionData, 1); |
|
| 2272 |
|
| 2273 data->entry = entry; |
|
| 2274 data->accountopt = accountopt; |
|
| 2275 if (filter_func == NULL) { |
|
| 2276 data->filter_func = pidgin_screenname_autocomplete_default_filter; |
|
| 2277 data->filter_func_user_data = NULL; |
|
| 2278 } else { |
|
| 2279 data->filter_func = filter_func; |
|
| 2280 data->filter_func_user_data = user_data; |
|
| 2281 } |
|
| 2282 data->completion = g_completion_new(NULL); |
|
| 2283 data->completion_started = FALSE; |
|
| 2284 |
|
| 2285 add_completion_list(data); |
|
| 2286 |
|
| 2287 g_completion_set_compare(data->completion, g_ascii_strncasecmp); |
|
| 2288 |
|
| 2289 g_signal_connect(G_OBJECT(entry), "event", |
|
| 2290 G_CALLBACK(completion_entry_event), data); |
|
| 2291 g_signal_connect(G_OBJECT(entry), "destroy", |
|
| 2292 G_CALLBACK(destroy_completion_data), data); |
|
| 2293 |
|
| 2294 #endif /* !NEW_STYLE_COMPLETION */ |
|
| 2295 |
|
| 2296 purple_signal_connect(purple_connections_get_handle(), "signed-on", entry, |
2140 purple_signal_connect(purple_connections_get_handle(), "signed-on", entry, |
| 2297 PURPLE_CALLBACK(repopulate_autocomplete), data); |
2141 PURPLE_CALLBACK(repopulate_autocomplete), data); |
| 2298 purple_signal_connect(purple_connections_get_handle(), "signed-off", entry, |
2142 purple_signal_connect(purple_connections_get_handle(), "signed-off", entry, |
| 2299 PURPLE_CALLBACK(repopulate_autocomplete), data); |
2143 PURPLE_CALLBACK(repopulate_autocomplete), data); |
| 2300 |
2144 |
| 2359 |
2199 |
| 2360 void (*callback)(const char*,gpointer); |
2200 void (*callback)(const char*,gpointer); |
| 2361 gpointer data; |
2201 gpointer data; |
| 2362 }; |
2202 }; |
| 2363 |
2203 |
| 2364 #if !GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ |
|
| 2365 static void |
|
| 2366 icon_filesel_delete_cb(GtkWidget *w, struct _icon_chooser *dialog) |
|
| 2367 { |
|
| 2368 if (dialog->icon_filesel != NULL) |
|
| 2369 gtk_widget_destroy(dialog->icon_filesel); |
|
| 2370 |
|
| 2371 if (dialog->callback) |
|
| 2372 dialog->callback(NULL, dialog->data); |
|
| 2373 |
|
| 2374 g_free(dialog); |
|
| 2375 } |
|
| 2376 #endif /* FILECHOOSER */ |
|
| 2377 |
|
| 2378 |
|
| 2379 |
|
| 2380 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ |
|
| 2381 static void |
2204 static void |
| 2382 icon_filesel_choose_cb(GtkWidget *widget, gint response, struct _icon_chooser *dialog) |
2205 icon_filesel_choose_cb(GtkWidget *widget, gint response, struct _icon_chooser *dialog) |
| 2383 { |
2206 { |
| 2384 char *filename, *current_folder; |
2207 char *filename, *current_folder; |
| 2385 |
2208 |
| 2399 if (current_folder != NULL) { |
2222 if (current_folder != NULL) { |
| 2400 purple_prefs_set_path(PIDGIN_PREFS_ROOT "/filelocations/last_icon_folder", current_folder); |
2223 purple_prefs_set_path(PIDGIN_PREFS_ROOT "/filelocations/last_icon_folder", current_folder); |
| 2401 g_free(current_folder); |
2224 g_free(current_folder); |
| 2402 } |
2225 } |
| 2403 |
2226 |
| 2404 #else /* FILECHOOSER */ |
2227 |
| 2405 static void |
|
| 2406 icon_filesel_choose_cb(GtkWidget *w, struct _icon_chooser *dialog) |
|
| 2407 { |
|
| 2408 char *filename, *current_folder; |
|
| 2409 |
|
| 2410 filename = g_strdup(gtk_file_selection_get_filename( |
|
| 2411 GTK_FILE_SELECTION(dialog->icon_filesel))); |
|
| 2412 |
|
| 2413 /* If they typed in a directory, change there */ |
|
| 2414 if (pidgin_check_if_dir(filename, |
|
| 2415 GTK_FILE_SELECTION(dialog->icon_filesel))) |
|
| 2416 { |
|
| 2417 g_free(filename); |
|
| 2418 return; |
|
| 2419 } |
|
| 2420 |
|
| 2421 current_folder = g_path_get_dirname(filename); |
|
| 2422 if (current_folder != NULL) { |
|
| 2423 purple_prefs_set_path(PIDGIN_PREFS_ROOT "/filelocations/last_icon_folder", current_folder); |
|
| 2424 g_free(current_folder); |
|
| 2425 } |
|
| 2426 |
|
| 2427 #endif /* FILECHOOSER */ |
|
| 2428 #if 0 /* mismatched curly braces */ |
|
| 2429 } |
|
| 2430 #endif |
|
| 2431 if (dialog->callback) |
2228 if (dialog->callback) |
| 2432 dialog->callback(filename, dialog->data); |
2229 dialog->callback(filename, dialog->data); |
| 2433 gtk_widget_destroy(dialog->icon_filesel); |
2230 gtk_widget_destroy(dialog->icon_filesel); |
| 2434 g_free(filename); |
2231 g_free(filename); |
| 2435 g_free(dialog); |
2232 g_free(dialog); |
| 2436 } |
2233 } |
| 2437 |
2234 |
| 2438 |
2235 |
| 2439 static void |
2236 static void |
| 2440 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ |
|
| 2441 icon_preview_change_cb(GtkFileChooser *widget, struct _icon_chooser *dialog) |
2237 icon_preview_change_cb(GtkFileChooser *widget, struct _icon_chooser *dialog) |
| 2442 #else /* FILECHOOSER */ |
|
| 2443 icon_preview_change_cb(GtkTreeSelection *sel, struct _icon_chooser *dialog) |
|
| 2444 #endif /* FILECHOOSER */ |
|
| 2445 { |
2238 { |
| 2446 GdkPixbuf *pixbuf, *scale; |
2239 GdkPixbuf *pixbuf, *scale; |
| 2447 int height, width; |
2240 int height, width; |
| 2448 char *basename, *markup, *size; |
2241 char *basename, *markup, *size; |
| 2449 struct stat st; |
2242 struct stat st; |
| 2450 char *filename; |
2243 char *filename; |
| 2451 |
2244 |
| 2452 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ |
|
| 2453 filename = gtk_file_chooser_get_preview_filename( |
2245 filename = gtk_file_chooser_get_preview_filename( |
| 2454 GTK_FILE_CHOOSER(dialog->icon_filesel)); |
2246 GTK_FILE_CHOOSER(dialog->icon_filesel)); |
| 2455 #else /* FILECHOOSER */ |
|
| 2456 filename = g_strdup(gtk_file_selection_get_filename( |
|
| 2457 GTK_FILE_SELECTION(dialog->icon_filesel))); |
|
| 2458 #endif /* FILECHOOSER */ |
|
| 2459 |
2247 |
| 2460 if (!filename || g_stat(filename, &st) || !(pixbuf = gdk_pixbuf_new_from_file(filename, NULL))) |
2248 if (!filename || g_stat(filename, &st) || !(pixbuf = gdk_pixbuf_new_from_file(filename, NULL))) |
| 2461 { |
2249 { |
| 2462 gtk_image_set_from_pixbuf(GTK_IMAGE(dialog->icon_preview), NULL); |
2250 gtk_image_set_from_pixbuf(GTK_IMAGE(dialog->icon_preview), NULL); |
| 2463 gtk_label_set_markup(GTK_LABEL(dialog->icon_text), ""); |
2251 gtk_label_set_markup(GTK_LABEL(dialog->icon_text), ""); |
| 2489 |
2277 |
| 2490 |
2278 |
| 2491 GtkWidget *pidgin_buddy_icon_chooser_new(GtkWindow *parent, void(*callback)(const char *, gpointer), gpointer data) { |
2279 GtkWidget *pidgin_buddy_icon_chooser_new(GtkWindow *parent, void(*callback)(const char *, gpointer), gpointer data) { |
| 2492 struct _icon_chooser *dialog = g_new0(struct _icon_chooser, 1); |
2280 struct _icon_chooser *dialog = g_new0(struct _icon_chooser, 1); |
| 2493 |
2281 |
| 2494 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ |
|
| 2495 GtkWidget *vbox; |
2282 GtkWidget *vbox; |
| 2496 #else |
|
| 2497 GtkWidget *hbox; |
|
| 2498 GtkWidget *tv; |
|
| 2499 GtkTreeSelection *sel; |
|
| 2500 #endif /* FILECHOOSER */ |
|
| 2501 const char *current_folder; |
2283 const char *current_folder; |
| 2502 |
2284 |
| 2503 dialog->callback = callback; |
2285 dialog->callback = callback; |
| 2504 dialog->data = data; |
2286 dialog->data = data; |
| 2505 |
2287 |
| 2506 current_folder = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/filelocations/last_icon_folder"); |
2288 current_folder = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/filelocations/last_icon_folder"); |
| 2507 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ |
|
| 2508 |
2289 |
| 2509 dialog->icon_filesel = gtk_file_chooser_dialog_new(_("Buddy Icon"), |
2290 dialog->icon_filesel = gtk_file_chooser_dialog_new(_("Buddy Icon"), |
| 2510 parent, |
2291 parent, |
| 2511 GTK_FILE_CHOOSER_ACTION_OPEN, |
2292 GTK_FILE_CHOOSER_ACTION_OPEN, |
| 2512 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
2293 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
| 2533 g_signal_connect(G_OBJECT(dialog->icon_filesel), "update-preview", |
2314 g_signal_connect(G_OBJECT(dialog->icon_filesel), "update-preview", |
| 2534 G_CALLBACK(icon_preview_change_cb), dialog); |
2315 G_CALLBACK(icon_preview_change_cb), dialog); |
| 2535 g_signal_connect(G_OBJECT(dialog->icon_filesel), "response", |
2316 g_signal_connect(G_OBJECT(dialog->icon_filesel), "response", |
| 2536 G_CALLBACK(icon_filesel_choose_cb), dialog); |
2317 G_CALLBACK(icon_filesel_choose_cb), dialog); |
| 2537 icon_preview_change_cb(NULL, dialog); |
2318 icon_preview_change_cb(NULL, dialog); |
| 2538 #else /* FILECHOOSER */ |
|
| 2539 dialog->icon_filesel = gtk_file_selection_new(_("Buddy Icon")); |
|
| 2540 dialog->icon_preview = gtk_image_new(); |
|
| 2541 dialog->icon_text = gtk_label_new(NULL); |
|
| 2542 if ((current_folder != NULL) && (*current_folder != '\0')) |
|
| 2543 gtk_file_selection_set_filename(GTK_FILE_SELECTION(dialog->icon_filesel), |
|
| 2544 current_folder); |
|
| 2545 |
|
| 2546 gtk_widget_set_size_request(GTK_WIDGET(dialog->icon_preview),-1, 50); |
|
| 2547 hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); |
|
| 2548 gtk_box_pack_start( |
|
| 2549 GTK_BOX(GTK_FILE_SELECTION(dialog->icon_filesel)->main_vbox), |
|
| 2550 hbox, FALSE, FALSE, 0); |
|
| 2551 gtk_box_pack_end(GTK_BOX(hbox), dialog->icon_preview, |
|
| 2552 FALSE, FALSE, 0); |
|
| 2553 gtk_box_pack_end(GTK_BOX(hbox), dialog->icon_text, FALSE, FALSE, 0); |
|
| 2554 |
|
| 2555 tv = GTK_FILE_SELECTION(dialog->icon_filesel)->file_list; |
|
| 2556 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv)); |
|
| 2557 |
|
| 2558 g_signal_connect(G_OBJECT(sel), "changed", |
|
| 2559 G_CALLBACK(icon_preview_change_cb), dialog); |
|
| 2560 g_signal_connect( |
|
| 2561 G_OBJECT(GTK_FILE_SELECTION(dialog->icon_filesel)->ok_button), |
|
| 2562 "clicked", |
|
| 2563 G_CALLBACK(icon_filesel_choose_cb), dialog); |
|
| 2564 g_signal_connect( |
|
| 2565 G_OBJECT(GTK_FILE_SELECTION(dialog->icon_filesel)->cancel_button), |
|
| 2566 "clicked", |
|
| 2567 G_CALLBACK(icon_filesel_delete_cb), dialog); |
|
| 2568 g_signal_connect(G_OBJECT(dialog->icon_filesel), "destroy", |
|
| 2569 G_CALLBACK(icon_filesel_delete_cb), dialog); |
|
| 2570 #endif /* FILECHOOSER */ |
|
| 2571 |
2319 |
| 2572 #ifdef _WIN32 |
2320 #ifdef _WIN32 |
| 2573 g_signal_connect(G_OBJECT(dialog->icon_filesel), "show", |
2321 g_signal_connect(G_OBJECT(dialog->icon_filesel), "show", |
| 2574 G_CALLBACK(winpidgin_ensure_onscreen), dialog->icon_filesel); |
2322 G_CALLBACK(winpidgin_ensure_onscreen), dialog->icon_filesel); |
| 2575 #endif |
2323 #endif |
| 2576 |
2324 |
| 2577 return dialog->icon_filesel; |
2325 return dialog->icon_filesel; |
| 2578 } |
2326 } |
| 2579 |
2327 |
| 2580 |
2328 |
| 2581 #if GTK_CHECK_VERSION(2,2,0) |
|
| 2582 static gboolean |
2329 static gboolean |
| 2583 str_array_match(char **a, char **b) |
2330 str_array_match(char **a, char **b) |
| 2584 { |
2331 { |
| 2585 int i, j; |
2332 int i, j; |
| 2586 |
2333 |
| 2590 for (j = 0; b[j] != NULL; j++) |
2337 for (j = 0; b[j] != NULL; j++) |
| 2591 if (!g_ascii_strcasecmp(a[i], b[j])) |
2338 if (!g_ascii_strcasecmp(a[i], b[j])) |
| 2592 return TRUE; |
2339 return TRUE; |
| 2593 return FALSE; |
2340 return FALSE; |
| 2594 } |
2341 } |
| 2595 #endif |
|
| 2596 |
2342 |
| 2597 gpointer |
2343 gpointer |
| 2598 pidgin_convert_buddy_icon(PurplePlugin *plugin, const char *path, size_t *len) |
2344 pidgin_convert_buddy_icon(PurplePlugin *plugin, const char *path, size_t *len) |
| 2599 { |
2345 { |
| 2600 PurplePluginProtocolInfo *prpl_info; |
2346 PurplePluginProtocolInfo *prpl_info; |
| 2601 #if GTK_CHECK_VERSION(2,2,0) |
|
| 2602 char **prpl_formats; |
2347 char **prpl_formats; |
| 2603 int width, height; |
2348 int width, height; |
| 2604 char **pixbuf_formats = NULL; |
2349 char **pixbuf_formats = NULL; |
| 2605 GdkPixbufFormat *format; |
2350 GdkPixbufFormat *format; |
| 2606 GdkPixbuf *pixbuf; |
2351 GdkPixbuf *pixbuf; |
| 2607 #if !GTK_CHECK_VERSION(2,4,0) |
|
| 2608 GdkPixbufLoader *loader; |
|
| 2609 #endif |
|
| 2610 #endif |
|
| 2611 gchar *contents; |
2352 gchar *contents; |
| 2612 gsize length; |
2353 gsize length; |
| 2613 |
2354 |
| 2614 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); |
2355 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); |
| 2615 |
2356 |
| 2616 g_return_val_if_fail(prpl_info->icon_spec.format != NULL, NULL); |
2357 g_return_val_if_fail(prpl_info->icon_spec.format != NULL, NULL); |
| 2617 |
2358 |
| 2618 |
2359 |
| 2619 #if GTK_CHECK_VERSION(2,2,0) |
|
| 2620 #if GTK_CHECK_VERSION(2,4,0) |
|
| 2621 format = gdk_pixbuf_get_file_info(path, &width, &height); |
2360 format = gdk_pixbuf_get_file_info(path, &width, &height); |
| 2622 #else |
2361 |
| 2623 loader = gdk_pixbuf_loader_new(); |
|
| 2624 if (g_file_get_contents(path, &contents, &length, NULL)) { |
|
| 2625 gdk_pixbuf_loader_write(loader, contents, length, NULL); |
|
| 2626 g_free(contents); |
|
| 2627 } |
|
| 2628 gdk_pixbuf_loader_close(loader, NULL); |
|
| 2629 pixbuf = gdk_pixbuf_loader_get_pixbuf(loader); |
|
| 2630 width = gdk_pixbuf_get_width(pixbuf); |
|
| 2631 height = gdk_pixbuf_get_height(pixbuf); |
|
| 2632 format = gdk_pixbuf_loader_get_format(loader); |
|
| 2633 g_object_unref(G_OBJECT(loader)); |
|
| 2634 #endif |
|
| 2635 if (format == NULL) |
2362 if (format == NULL) |
| 2636 return NULL; |
2363 return NULL; |
| 2637 |
2364 |
| 2638 pixbuf_formats = gdk_pixbuf_format_get_extensions(format); |
2365 pixbuf_formats = gdk_pixbuf_format_get_extensions(format); |
| 2639 prpl_formats = g_strsplit(prpl_info->icon_spec.format,",",0); |
2366 prpl_formats = g_strsplit(prpl_info->icon_spec.format,",",0); |
| 2641 (!(prpl_info->icon_spec.scale_rules & PURPLE_ICON_SCALE_SEND) || /* The prpl doesn't scale before it sends OR */ |
2368 (!(prpl_info->icon_spec.scale_rules & PURPLE_ICON_SCALE_SEND) || /* The prpl doesn't scale before it sends OR */ |
| 2642 (prpl_info->icon_spec.min_width <= width && |
2369 (prpl_info->icon_spec.min_width <= width && |
| 2643 prpl_info->icon_spec.max_width >= width && |
2370 prpl_info->icon_spec.max_width >= width && |
| 2644 prpl_info->icon_spec.min_height <= height && |
2371 prpl_info->icon_spec.min_height <= height && |
| 2645 prpl_info->icon_spec.max_height >= height))) /* The icon is the correct size */ |
2372 prpl_info->icon_spec.max_height >= height))) /* The icon is the correct size */ |
| 2646 #endif |
|
| 2647 { |
2373 { |
| 2648 #if GTK_CHECK_VERSION(2,2,0) |
|
| 2649 g_strfreev(prpl_formats); |
2374 g_strfreev(prpl_formats); |
| 2650 g_strfreev(pixbuf_formats); |
2375 g_strfreev(pixbuf_formats); |
| 2651 #endif |
2376 |
| 2652 /* We don't need to scale the image. */ |
2377 /* We don't need to scale the image. */ |
| 2653 |
|
| 2654 contents = NULL; |
2378 contents = NULL; |
| 2655 if (!g_file_get_contents(path, &contents, &length, NULL)) |
2379 if (!g_file_get_contents(path, &contents, &length, NULL)) |
| 2656 { |
2380 { |
| 2657 g_free(contents); |
2381 g_free(contents); |
| 2658 #if GTK_CHECK_VERSION(2,2,0) && !GTK_CHECK_VERSION(2,4,0) |
|
| 2659 g_object_unref(G_OBJECT(pixbuf)); |
|
| 2660 #endif |
|
| 2661 return NULL; |
2382 return NULL; |
| 2662 } |
2383 } |
| 2663 } |
2384 } |
| 2664 #if GTK_CHECK_VERSION(2,2,0) |
|
| 2665 else |
2385 else |
| 2666 { |
2386 { |
| 2667 int i; |
2387 int i; |
| 2668 GError *error = NULL; |
2388 GError *error = NULL; |
| 2669 GdkPixbuf *scale; |
2389 GdkPixbuf *scale; |
| 2780 } |
2500 } |
| 2781 |
2501 |
| 2782 if (len) |
2502 if (len) |
| 2783 *len = length; |
2503 *len = length; |
| 2784 return contents; |
2504 return contents; |
| 2785 #else |
2505 } |
| 2786 /* |
|
| 2787 * The chosen icon wasn't the right size, and we're using |
|
| 2788 * GTK+ 2.0 so we can't scale it. |
|
| 2789 */ |
|
| 2790 return NULL; |
|
| 2791 #endif |
|
| 2792 } |
|
| 2793 |
|
| 2794 #if !GTK_CHECK_VERSION(2,6,0) |
|
| 2795 static void |
|
| 2796 _gdk_file_scale_size_prepared_cb (GdkPixbufLoader *loader, |
|
| 2797 int width, |
|
| 2798 int height, |
|
| 2799 gpointer data) |
|
| 2800 { |
|
| 2801 struct { |
|
| 2802 gint width; |
|
| 2803 gint height; |
|
| 2804 gboolean preserve_aspect_ratio; |
|
| 2805 } *info = data; |
|
| 2806 |
|
| 2807 g_return_if_fail (width > 0 && height > 0); |
|
| 2808 |
|
| 2809 if (info->preserve_aspect_ratio && |
|
| 2810 (info->width > 0 || info->height > 0)) { |
|
| 2811 if (info->width < 0) |
|
| 2812 { |
|
| 2813 width = width * (double)info->height/(double)height; |
|
| 2814 height = info->height; |
|
| 2815 } |
|
| 2816 else if (info->height < 0) |
|
| 2817 { |
|
| 2818 height = height * (double)info->width/(double)width; |
|
| 2819 width = info->width; |
|
| 2820 } |
|
| 2821 else if ((double)height * (double)info->width > |
|
| 2822 (double)width * (double)info->height) { |
|
| 2823 width = 0.5 + (double)width * (double)info->height / (double)height; |
|
| 2824 height = info->height; |
|
| 2825 } else { |
|
| 2826 height = 0.5 + (double)height * (double)info->width / (double)width; |
|
| 2827 width = info->width; |
|
| 2828 } |
|
| 2829 } else { |
|
| 2830 if (info->width > 0) |
|
| 2831 width = info->width; |
|
| 2832 if (info->height > 0) |
|
| 2833 height = info->height; |
|
| 2834 } |
|
| 2835 |
|
| 2836 #if GTK_CHECK_VERSION(2,2,0) /* 2.0 users are going to have very strangely sized things */ |
|
| 2837 gdk_pixbuf_loader_set_size (loader, width, height); |
|
| 2838 #else |
|
| 2839 #warning nosnilmot could not be bothered to fix this properly for you |
|
| 2840 #warning ... good luck ... your images may end up strange sizes |
|
| 2841 #endif |
|
| 2842 } |
|
| 2843 |
|
| 2844 GdkPixbuf * |
|
| 2845 gdk_pixbuf_new_from_file_at_scale(const char *filename, int width, int height, |
|
| 2846 gboolean preserve_aspect_ratio, |
|
| 2847 GError **error) |
|
| 2848 { |
|
| 2849 GdkPixbufLoader *loader; |
|
| 2850 GdkPixbuf *pixbuf; |
|
| 2851 guchar buffer [4096]; |
|
| 2852 int length; |
|
| 2853 FILE *f; |
|
| 2854 struct { |
|
| 2855 gint width; |
|
| 2856 gint height; |
|
| 2857 gboolean preserve_aspect_ratio; |
|
| 2858 } info; |
|
| 2859 GdkPixbufAnimation *animation; |
|
| 2860 GdkPixbufAnimationIter *iter; |
|
| 2861 gboolean has_frame; |
|
| 2862 |
|
| 2863 g_return_val_if_fail (filename != NULL, NULL); |
|
| 2864 g_return_val_if_fail (width > 0 || width == -1, NULL); |
|
| 2865 g_return_val_if_fail (height > 0 || height == -1, NULL); |
|
| 2866 |
|
| 2867 f = g_fopen (filename, "rb"); |
|
| 2868 if (!f) { |
|
| 2869 gint save_errno = errno; |
|
| 2870 gchar *display_name = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL); |
|
| 2871 g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (save_errno), |
|
| 2872 _("Failed to open file '%s': %s"), |
|
| 2873 display_name ? display_name : "(unknown)", |
|
| 2874 g_strerror (save_errno)); |
|
| 2875 g_free (display_name); |
|
| 2876 return NULL; |
|
| 2877 } |
|
| 2878 |
|
| 2879 loader = gdk_pixbuf_loader_new (); |
|
| 2880 |
|
| 2881 info.width = width; |
|
| 2882 info.height = height; |
|
| 2883 info.preserve_aspect_ratio = preserve_aspect_ratio; |
|
| 2884 |
|
| 2885 g_signal_connect (loader, "size-prepared", G_CALLBACK (_gdk_file_scale_size_prepared_cb), &info); |
|
| 2886 |
|
| 2887 has_frame = FALSE; |
|
| 2888 while (!has_frame && !feof (f) && !ferror (f)) { |
|
| 2889 length = fread (buffer, 1, sizeof (buffer), f); |
|
| 2890 if (length > 0) |
|
| 2891 if (!gdk_pixbuf_loader_write (loader, buffer, length, error)) { |
|
| 2892 gdk_pixbuf_loader_close (loader, NULL); |
|
| 2893 fclose (f); |
|
| 2894 g_object_unref (loader); |
|
| 2895 return NULL; |
|
| 2896 } |
|
| 2897 |
|
| 2898 animation = gdk_pixbuf_loader_get_animation (loader); |
|
| 2899 if (animation) { |
|
| 2900 iter = gdk_pixbuf_animation_get_iter (animation, 0); |
|
| 2901 if (!gdk_pixbuf_animation_iter_on_currently_loading_frame (iter)) { |
|
| 2902 has_frame = TRUE; |
|
| 2903 } |
|
| 2904 g_object_unref (iter); |
|
| 2905 } |
|
| 2906 } |
|
| 2907 |
|
| 2908 fclose (f); |
|
| 2909 |
|
| 2910 if (!gdk_pixbuf_loader_close (loader, error) && !has_frame) { |
|
| 2911 g_object_unref (loader); |
|
| 2912 return NULL; |
|
| 2913 } |
|
| 2914 |
|
| 2915 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); |
|
| 2916 |
|
| 2917 if (!pixbuf) { |
|
| 2918 gchar *display_name = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL); |
|
| 2919 g_object_unref (loader); |
|
| 2920 g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_FAILED, |
|
| 2921 _("Failed to load image '%s': reason not known, probably a corrupt image file"), |
|
| 2922 display_name ? display_name : "(unknown)"); |
|
| 2923 g_free (display_name); |
|
| 2924 return NULL; |
|
| 2925 } |
|
| 2926 |
|
| 2927 g_object_ref (pixbuf); |
|
| 2928 |
|
| 2929 g_object_unref (loader); |
|
| 2930 |
|
| 2931 return pixbuf; |
|
| 2932 } |
|
| 2933 #endif /* ! Gtk 2.6.0 */ |
|
| 2934 |
2506 |
| 2935 void pidgin_set_custom_buddy_icon(PurpleAccount *account, const char *who, const char *filename) |
2507 void pidgin_set_custom_buddy_icon(PurpleAccount *account, const char *who, const char *filename) |
| 2936 { |
2508 { |
| 2937 PurpleBuddy *buddy; |
2509 PurpleBuddy *buddy; |
| 2938 PurpleContact *contact; |
2510 PurpleContact *contact; |
| 2962 return ret; |
2534 return ret; |
| 2963 } |
2535 } |
| 2964 |
2536 |
| 2965 void pidgin_set_urgent(GtkWindow *window, gboolean urgent) |
2537 void pidgin_set_urgent(GtkWindow *window, gboolean urgent) |
| 2966 { |
2538 { |
| 2967 #if GTK_CHECK_VERSION(2,8,0) |
2539 #if defined _WIN32 |
| |
2540 winpidgin_window_flash(window, urgent); |
| |
2541 #else |
| 2968 gtk_window_set_urgency_hint(window, urgent); |
2542 gtk_window_set_urgency_hint(window, urgent); |
| 2969 #elif defined _WIN32 |
|
| 2970 winpidgin_window_flash(window, urgent); |
|
| 2971 #elif defined GDK_WINDOWING_X11 |
|
| 2972 GdkWindow *gdkwin; |
|
| 2973 XWMHints *hints; |
|
| 2974 |
|
| 2975 g_return_if_fail(window != NULL); |
|
| 2976 |
|
| 2977 gdkwin = GTK_WIDGET(window)->window; |
|
| 2978 |
|
| 2979 g_return_if_fail(gdkwin != NULL); |
|
| 2980 |
|
| 2981 hints = XGetWMHints(GDK_WINDOW_XDISPLAY(gdkwin), |
|
| 2982 GDK_WINDOW_XWINDOW(gdkwin)); |
|
| 2983 if(!hints) |
|
| 2984 hints = XAllocWMHints(); |
|
| 2985 |
|
| 2986 if (urgent) |
|
| 2987 hints->flags |= XUrgencyHint; |
|
| 2988 else |
|
| 2989 hints->flags &= ~XUrgencyHint; |
|
| 2990 XSetWMHints(GDK_WINDOW_XDISPLAY(gdkwin), |
|
| 2991 GDK_WINDOW_XWINDOW(gdkwin), hints); |
|
| 2992 XFree(hints); |
|
| 2993 #else |
|
| 2994 /* do something else? */ |
|
| 2995 #endif |
2543 #endif |
| 2996 } |
2544 } |
| 2997 |
2545 |
| 2998 static GSList *minidialogs = NULL; |
2546 static GSList *minidialogs = NULL; |
| 2999 |
2547 |
| 3298 style->text_aa[GTK_STATE_NORMAL].green >> 8, |
2846 style->text_aa[GTK_STATE_NORMAL].green >> 8, |
| 3299 style->text_aa[GTK_STATE_NORMAL].blue >> 8); |
2847 style->text_aa[GTK_STATE_NORMAL].blue >> 8); |
| 3300 return dim_grey_string; |
2848 return dim_grey_string; |
| 3301 } |
2849 } |
| 3302 |
2850 |
| 3303 #if !GTK_CHECK_VERSION(2,2,0) |
|
| 3304 GtkTreePath * |
|
| 3305 gtk_tree_path_new_from_indices (gint first_index, ...) |
|
| 3306 { |
|
| 3307 int arg; |
|
| 3308 va_list args; |
|
| 3309 GtkTreePath *path; |
|
| 3310 |
|
| 3311 path = gtk_tree_path_new (); |
|
| 3312 |
|
| 3313 va_start (args, first_index); |
|
| 3314 arg = first_index; |
|
| 3315 |
|
| 3316 while (arg != -1) |
|
| 3317 { |
|
| 3318 gtk_tree_path_append_index (path, arg); |
|
| 3319 arg = va_arg (args, gint); |
|
| 3320 } |
|
| 3321 |
|
| 3322 va_end (args); |
|
| 3323 |
|
| 3324 return path; |
|
| 3325 } |
|
| 3326 #endif |
|
| 3327 |
|
| 3328 static void |
2851 static void |
| 3329 combo_box_changed_cb(GtkComboBox *combo_box, GtkEntry *entry) |
2852 combo_box_changed_cb(GtkComboBox *combo_box, GtkEntry *entry) |
| 3330 { |
2853 { |
| 3331 char *text = gtk_combo_box_get_active_text(combo_box); |
2854 char *text = gtk_combo_box_get_active_text(combo_box); |
| 3332 gtk_entry_set_text(entry, text ? text : ""); |
2855 gtk_entry_set_text(entry, text ? text : ""); |
| 3595 { |
3116 { |
| 3596 /* Copied from gtkft.c:open_button_cb */ |
3117 /* Copied from gtkft.c:open_button_cb */ |
| 3597 #ifdef _WIN32 |
3118 #ifdef _WIN32 |
| 3598 /* If using Win32... */ |
3119 /* If using Win32... */ |
| 3599 int code; |
3120 int code; |
| 3600 if (G_WIN32_HAVE_WIDECHAR_API()) { |
3121 wchar_t *wc_filename = g_utf8_to_utf16( |
| 3601 wchar_t *wc_filename = g_utf8_to_utf16( |
3122 uri, -1, NULL, NULL, NULL); |
| 3602 uri, -1, NULL, NULL, NULL); |
3123 |
| 3603 |
3124 code = (int)ShellExecuteW(NULL, NULL, wc_filename, NULL, NULL, |
| 3604 code = (int)ShellExecuteW(NULL, NULL, wc_filename, NULL, NULL, |
3125 SW_SHOW); |
| 3605 SW_SHOW); |
3126 |
| 3606 |
3127 g_free(wc_filename); |
| 3607 g_free(wc_filename); |
|
| 3608 } else { |
|
| 3609 char *l_filename = g_locale_from_utf8( |
|
| 3610 uri, -1, NULL, NULL, NULL); |
|
| 3611 |
|
| 3612 code = (int)ShellExecuteA(NULL, NULL, l_filename, NULL, NULL, |
|
| 3613 SW_SHOW); |
|
| 3614 |
|
| 3615 g_free(l_filename); |
|
| 3616 } |
|
| 3617 |
3128 |
| 3618 if (code == SE_ERR_ASSOCINCOMPLETE || code == SE_ERR_NOASSOC) |
3129 if (code == SE_ERR_ASSOCINCOMPLETE || code == SE_ERR_NOASSOC) |
| 3619 { |
3130 { |
| 3620 purple_notify_error(imhtml, NULL, |
3131 purple_notify_error(imhtml, NULL, |
| 3621 _("There is no application configured to open this type of file."), NULL); |
3132 _("There is no application configured to open this type of file."), NULL); |
| 3708 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); |
3219 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); |
| 3709 g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_link_activate), link); |
3220 g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_link_activate), link); |
| 3710 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
3221 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
| 3711 |
3222 |
| 3712 /* Open Containing Directory */ |
3223 /* Open Containing Directory */ |
| 3713 #if GTK_CHECK_VERSION(2,6,0) |
|
| 3714 img = gtk_image_new_from_stock(GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU); |
3224 img = gtk_image_new_from_stock(GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU); |
| 3715 item = gtk_image_menu_item_new_with_mnemonic(_("Open _Containing Directory")); |
3225 item = gtk_image_menu_item_new_with_mnemonic(_("Open _Containing Directory")); |
| 3716 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); |
3226 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); |
| 3717 #else |
3227 |
| 3718 item = gtk_menu_item_new_with_mnemonic(_("Open _Containing Directory")); |
|
| 3719 #endif |
|
| 3720 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(open_containing_cb), (gpointer)url); |
3228 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(open_containing_cb), (gpointer)url); |
| 3721 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
3229 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
| 3722 |
3230 |
| 3723 return TRUE; |
3231 return TRUE; |
| 3724 } |
3232 } |
| 3780 return TRUE; |
3288 return TRUE; |
| 3781 |
3289 |
| 3782 url = gtk_imhtml_link_get_url(link); |
3290 url = gtk_imhtml_link_get_url(link); |
| 3783 |
3291 |
| 3784 /* Play Sound */ |
3292 /* Play Sound */ |
| 3785 #if GTK_CHECK_VERSION(2,6,0) |
|
| 3786 img = gtk_image_new_from_stock(GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_MENU); |
3293 img = gtk_image_new_from_stock(GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_MENU); |
| 3787 item = gtk_image_menu_item_new_with_mnemonic(_("_Play Sound")); |
3294 item = gtk_image_menu_item_new_with_mnemonic(_("_Play Sound")); |
| 3788 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); |
3295 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); |
| 3789 #else |
3296 |
| 3790 item = gtk_menu_item_new_with_mnemonic(_("_Play Sound")); |
|
| 3791 #endif |
|
| 3792 g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_link_activate), link); |
3297 g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_link_activate), link); |
| 3793 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
3298 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
| 3794 |
3299 |
| 3795 /* Save File */ |
3300 /* Save File */ |
| 3796 img = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_MENU); |
3301 img = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_MENU); |