Mercurial > pidgin.yaz
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); |