comparison pidgin/gtkutils.c @ 29610:7819d3819f4c

propagate from branch 'im.pidgin.pidgin' (head 0d33eae1cfd57cb5f459518ad5db14230f13792b) to branch 'im.pidgin.pidgin.next.minor' (head b5b9f7898db2efebf9a130b493f8448adab61d20)
author maiku@pidgin.im
date Wed, 21 Oct 2009 18:09:47 +0000
parents 3fdad8b715c7 6e9917e067e6
children a78a44f0cdcd
comparison
equal deleted inserted replaced
28779:d1c18bd588e2 29610:7819d3819f4c
1259 gint *x, 1259 gint *x,
1260 gint *y, 1260 gint *y,
1261 gboolean *push_in, 1261 gboolean *push_in,
1262 gpointer data) 1262 gpointer data)
1263 { 1263 {
1264 #if GTK_CHECK_VERSION(2,2,0)
1265 GtkWidget *widget; 1264 GtkWidget *widget;
1266 GtkRequisition requisition; 1265 GtkRequisition requisition;
1267 GdkScreen *screen; 1266 GdkScreen *screen;
1268 GdkRectangle monitor; 1267 GdkRectangle monitor;
1269 gint monitor_num; 1268 gint monitor_num;
1400 } 1399 }
1401 else 1400 else
1402 { 1401 {
1403 *y = monitor.y; 1402 *y = monitor.y;
1404 } 1403 }
1405 #endif
1406 } 1404 }
1407 1405
1408 1406
1409 void 1407 void
1410 pidgin_treeview_popup_menu_position_func(GtkMenu *menu, 1408 pidgin_treeview_popup_menu_position_func(GtkMenu *menu,
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;
2110 -1); 2010 -1);
2111 } 2011 }
2112 2012
2113 g_free(normalized_buddyname); 2013 g_free(normalized_buddyname);
2114 } 2014 }
2115 #endif /* NEW_STYLE_COMPLETION */
2116 2015
2117 static void get_log_set_name(PurpleLogSet *set, gpointer value, PidginCompletionData *data) 2016 static void get_log_set_name(PurpleLogSet *set, gpointer value, PidginCompletionData *data)
2118 { 2017 {
2119 PidginFilterBuddyCompletionEntryFunc filter_func = data->filter_func; 2018 PidginFilterBuddyCompletionEntryFunc filter_func = data->filter_func;
2120 gpointer user_data = data->filter_func_user_data; 2019 gpointer user_data = data->filter_func_user_data;
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 {
2220 void 2092 void
2221 pidgin_setup_screenname_autocomplete_with_filter(GtkWidget *entry, GtkWidget *accountopt, PidginFilterBuddyCompletionEntryFunc filter_func, gpointer user_data) 2093 pidgin_setup_screenname_autocomplete_with_filter(GtkWidget *entry, GtkWidget *accountopt, PidginFilterBuddyCompletionEntryFunc filter_func, gpointer user_data)
2222 { 2094 {
2223 PidginCompletionData *data; 2095 PidginCompletionData *data;
2224 2096
2225 #ifdef NEW_STYLE_COMPLETION
2226 /* 2097 /*
2227 * Store the displayed completion value, the buddy name, the UTF-8 2098 * Store the displayed completion value, the buddy name, the UTF-8
2228 * normalized & casefolded buddy name, the UTF-8 normalized & 2099 * normalized & casefolded buddy name, the UTF-8 normalized &
2229 * casefolded value for comparison, and the account. 2100 * casefolded value for comparison, and the account.
2230 */ 2101 */
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
2334 2178
2335 cursor = gdk_cursor_new(cursor_type); 2179 cursor = gdk_cursor_new(cursor_type);
2336 gdk_window_set_cursor(widget->window, cursor); 2180 gdk_window_set_cursor(widget->window, cursor);
2337 gdk_cursor_unref(cursor); 2181 gdk_cursor_unref(cursor);
2338 2182
2339 #if GTK_CHECK_VERSION(2,4,0)
2340 gdk_display_flush(gdk_drawable_get_display(GDK_DRAWABLE(widget->window))); 2183 gdk_display_flush(gdk_drawable_get_display(GDK_DRAWABLE(widget->window)));
2341 #else
2342 gdk_flush();
2343 #endif
2344 } 2184 }
2345 2185
2346 void pidgin_clear_cursor(GtkWidget *widget) 2186 void pidgin_clear_cursor(GtkWidget *widget)
2347 { 2187 {
2348 g_return_if_fail(widget != NULL); 2188 g_return_if_fail(widget != NULL);
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 : "");
3468 return TRUE; 2991 return TRUE;
3469 } 2992 }
3470 return FALSE; 2993 return FALSE;
3471 #endif 2994 #endif
3472 #else 2995 #else
3473 #if GTK_CHECK_VERSION(2,4,0)
3474 /* This finds the currently active window and makes that the parent window. */ 2996 /* This finds the currently active window and makes that the parent window. */
3475 GList *windows = NULL; 2997 GList *windows = NULL;
3476 GtkWidget *parent = NULL; 2998 GtkWidget *parent = NULL;
3477 GdkEvent *event = gtk_get_current_event(); 2999 GdkEvent *event = gtk_get_current_event();
3478 GdkWindow *menu = NULL; 3000 GdkWindow *menu = NULL;
3511 g_list_free(windows); 3033 g_list_free(windows);
3512 if (parent) { 3034 if (parent) {
3513 gtk_window_set_transient_for(GTK_WINDOW(widget), GTK_WINDOW(parent)); 3035 gtk_window_set_transient_for(GTK_WINDOW(widget), GTK_WINDOW(parent));
3514 return TRUE; 3036 return TRUE;
3515 } 3037 }
3516 #endif
3517 return FALSE; 3038 return FALSE;
3518 #endif 3039 #endif
3519 } 3040 }
3520 3041
3521 GdkPixbuf * pidgin_pixbuf_from_imgstore(PurpleStoredImage *image) 3042 GdkPixbuf * pidgin_pixbuf_from_imgstore(PurpleStoredImage *image)
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);