pidgin/gtkutils.c

branch
next.minor
changeset 29655
c24e3b7f75fb
parent 28908
d8538334b167
parent 29632
714456337da2
child 29686
f9dee36112d0
equal deleted inserted replaced
28915:5e2ecb0915f0 29655:c24e3b7f75fb
1245 gint *x, 1245 gint *x,
1246 gint *y, 1246 gint *y,
1247 gboolean *push_in, 1247 gboolean *push_in,
1248 gpointer data) 1248 gpointer data)
1249 { 1249 {
1250 #if GTK_CHECK_VERSION(2,2,0)
1251 GtkWidget *widget; 1250 GtkWidget *widget;
1252 GtkRequisition requisition; 1251 GtkRequisition requisition;
1253 GdkScreen *screen; 1252 GdkScreen *screen;
1254 GdkRectangle monitor; 1253 GdkRectangle monitor;
1255 gint monitor_num; 1254 gint monitor_num;
1386 } 1385 }
1387 else 1386 else
1388 { 1387 {
1389 *y = monitor.y; 1388 *y = monitor.y;
1390 } 1389 }
1391 #endif
1392 } 1390 }
1393 1391
1394 1392
1395 void 1393 void
1396 pidgin_treeview_popup_menu_position_func(GtkMenu *menu, 1394 pidgin_treeview_popup_menu_position_func(GtkMenu *menu,
1628 else if (purple_str_has_suffix(basename, ".desktop") && (item = purple_desktop_item_new_from_file(filename))) { 1626 else if (purple_str_has_suffix(basename, ".desktop") && (item = purple_desktop_item_new_from_file(filename))) {
1629 PurpleDesktopItemType dtype; 1627 PurpleDesktopItemType dtype;
1630 char key[64]; 1628 char key[64];
1631 const char *itemname = NULL; 1629 const char *itemname = NULL;
1632 1630
1633 #if GTK_CHECK_VERSION(2,6,0)
1634 const char * const *langs; 1631 const char * const *langs;
1635 int i; 1632 int i;
1636 langs = g_get_language_names(); 1633 langs = g_get_language_names();
1637 for (i = 0; langs[i]; i++) { 1634 for (i = 0; langs[i]; i++) {
1638 g_snprintf(key, sizeof(key), "Name[%s]", langs[i]); 1635 g_snprintf(key, sizeof(key), "Name[%s]", langs[i]);
1639 itemname = purple_desktop_item_get_string(item, key); 1636 itemname = purple_desktop_item_get_string(item, key);
1640 break; 1637 break;
1641 } 1638 }
1642 #else 1639
1643 const char *lang = g_getenv("LANG");
1644 char *dot;
1645 dot = strchr(lang, '.');
1646 if (dot)
1647 *dot = '\0';
1648 g_snprintf(key, sizeof(key), "Name[%s]", lang);
1649 itemname = purple_desktop_item_get_string(item, key);
1650 #endif
1651 if (!itemname) 1640 if (!itemname)
1652 itemname = purple_desktop_item_get_string(item, "Name"); 1641 itemname = purple_desktop_item_get_string(item, "Name");
1653 1642
1654 dtype = purple_desktop_item_get_entry_type(item); 1643 dtype = purple_desktop_item_get_entry_type(item);
1655 switch (dtype) { 1644 switch (dtype) {
1662 gtk_imhtml_insert_link(GTK_IMHTML(gtkconv->entry), 1651 gtk_imhtml_insert_link(GTK_IMHTML(gtkconv->entry),
1663 gtk_text_buffer_get_insert(GTK_IMHTML(gtkconv->entry)->text_buffer), 1652 gtk_text_buffer_get_insert(GTK_IMHTML(gtkconv->entry)->text_buffer),
1664 purple_desktop_item_get_string(item, "URL"), itemname); 1653 purple_desktop_item_get_string(item, "URL"), itemname);
1665 break; 1654 break;
1666 default: 1655 default:
1667 /* I don't know if we really want to do anything here. Most of the desktop item types are crap like 1656 /* I don't know if we really want to do anything here. Most of
1668 * "MIME Type" (I have no clue how that would be a desktop item) and "Comment"... nothing we can really 1657 * the desktop item types are crap like "MIME Type" (I have no
1669 * send. The only logical one is "Application," but do we really want to send a binary and nothing else? 1658 * clue how that would be a desktop item) and "Comment"...
1670 * Probably not. I'll just give an error and return. */ 1659 * nothing we can really send. The only logical one is
1660 * "Application," but do we really want to send a binary and
1661 * nothing else? Probably not. I'll just give an error and
1662 * return. */
1671 /* The original patch sent the icon used by the launcher. That's probably wrong */ 1663 /* The original patch sent the icon used by the launcher. That's probably wrong */
1672 purple_notify_error(NULL, NULL, _("Cannot send launcher"), 1664 purple_notify_error(NULL, NULL, _("Cannot send launcher"),
1673 _("You dragged a desktop launcher. Most " 1665 _("You dragged a desktop launcher. Most "
1674 "likely you wanted to send the target " 1666 "likely you wanted to send the target "
1675 "of this launcher instead of this " 1667 "of this launcher instead of this "
1860 } 1852 }
1861 purple_menu_action_free(act); 1853 purple_menu_action_free(act);
1862 return menuitem; 1854 return menuitem;
1863 } 1855 }
1864 1856
1865 #if GTK_CHECK_VERSION(2,3,0)
1866 # define NEW_STYLE_COMPLETION
1867 #endif
1868
1869 typedef struct 1857 typedef struct
1870 { 1858 {
1871 GtkWidget *entry; 1859 GtkWidget *entry;
1872 GtkWidget *accountopt; 1860 GtkWidget *accountopt;
1873 1861
1874 PidginFilterBuddyCompletionEntryFunc filter_func; 1862 PidginFilterBuddyCompletionEntryFunc filter_func;
1875 gpointer filter_func_user_data; 1863 gpointer filter_func_user_data;
1876 1864
1877 #ifdef NEW_STYLE_COMPLETION
1878 GtkListStore *store; 1865 GtkListStore *store;
1879 #else
1880 GCompletion *completion;
1881 gboolean completion_started;
1882 GList *log_items;
1883 #endif /* NEW_STYLE_COMPLETION */
1884 } PidginCompletionData; 1866 } PidginCompletionData;
1885 1867
1886 #ifndef NEW_STYLE_COMPLETION
1887 static gboolean
1888 completion_entry_event(GtkEditable *entry, GdkEventKey *event,
1889 PidginCompletionData *data)
1890 {
1891 int pos, end_pos;
1892
1893 if (event->type == GDK_KEY_PRESS && event->keyval == GDK_Tab)
1894 {
1895 gtk_editable_get_selection_bounds(entry, &pos, &end_pos);
1896
1897 if (data->completion_started &&
1898 pos != end_pos && pos > 1 &&
1899 end_pos == strlen(gtk_entry_get_text(GTK_ENTRY(entry))))
1900 {
1901 gtk_editable_select_region(entry, 0, 0);
1902 gtk_editable_set_position(entry, -1);
1903
1904 return TRUE;
1905 }
1906 }
1907 else if (event->type == GDK_KEY_PRESS && event->length > 0)
1908 {
1909 char *prefix, *nprefix;
1910
1911 gtk_editable_get_selection_bounds(entry, &pos, &end_pos);
1912
1913 if (data->completion_started &&
1914 pos != end_pos && pos > 1 &&
1915 end_pos == strlen(gtk_entry_get_text(GTK_ENTRY(entry))))
1916 {
1917 char *temp;
1918
1919 temp = gtk_editable_get_chars(entry, 0, pos);
1920 prefix = g_strconcat(temp, event->string, NULL);
1921 g_free(temp);
1922 }
1923 else if (pos == end_pos && pos > 1 &&
1924 end_pos == strlen(gtk_entry_get_text(GTK_ENTRY(entry))))
1925 {
1926 prefix = g_strconcat(gtk_entry_get_text(GTK_ENTRY(entry)),
1927 event->string, NULL);
1928 }
1929 else
1930 return FALSE;
1931
1932 pos = strlen(prefix);
1933 nprefix = NULL;
1934
1935 g_completion_complete(data->completion, prefix, &nprefix);
1936
1937 if (nprefix != NULL)
1938 {
1939 gtk_entry_set_text(GTK_ENTRY(entry), nprefix);
1940 gtk_editable_set_position(entry, pos);
1941 gtk_editable_select_region(entry, pos, -1);
1942
1943 data->completion_started = TRUE;
1944
1945 g_free(nprefix);
1946 g_free(prefix);
1947
1948 return TRUE;
1949 }
1950
1951 g_free(prefix);
1952 }
1953
1954 return FALSE;
1955 }
1956
1957 static void
1958 destroy_completion_data(GtkWidget *w, PidginCompletionData *data)
1959 {
1960 g_list_foreach(data->completion->items, (GFunc)g_free, NULL);
1961 g_completion_free(data->completion);
1962
1963 g_free(data);
1964 }
1965 #endif /* !NEW_STYLE_COMPLETION */
1966
1967 #ifdef NEW_STYLE_COMPLETION
1968 static gboolean buddyname_completion_match_func(GtkEntryCompletion *completion, 1868 static gboolean buddyname_completion_match_func(GtkEntryCompletion *completion,
1969 const gchar *key, GtkTreeIter *iter, gpointer user_data) 1869 const gchar *key, GtkTreeIter *iter, gpointer user_data)
1970 { 1870 {
1971 GtkTreeModel *model; 1871 GtkTreeModel *model;
1972 GValue val1; 1872 GValue val1;
2096 -1); 1996 -1);
2097 } 1997 }
2098 1998
2099 g_free(normalized_buddyname); 1999 g_free(normalized_buddyname);
2100 } 2000 }
2101 #endif /* NEW_STYLE_COMPLETION */
2102 2001
2103 static void get_log_set_name(PurpleLogSet *set, gpointer value, PidginCompletionData *data) 2002 static void get_log_set_name(PurpleLogSet *set, gpointer value, PidginCompletionData *data)
2104 { 2003 {
2105 PidginFilterBuddyCompletionEntryFunc filter_func = data->filter_func; 2004 PidginFilterBuddyCompletionEntryFunc filter_func = data->filter_func;
2106 gpointer user_data = data->filter_func_user_data; 2005 gpointer user_data = data->filter_func_user_data;
2111 PidginBuddyCompletionEntry entry; 2010 PidginBuddyCompletionEntry entry;
2112 entry.is_buddy = FALSE; 2011 entry.is_buddy = FALSE;
2113 entry.entry.logged_buddy = set; 2012 entry.entry.logged_buddy = set;
2114 2013
2115 if (filter_func(&entry, user_data)) { 2014 if (filter_func(&entry, user_data)) {
2116 #ifdef NEW_STYLE_COMPLETION
2117 add_buddyname_autocomplete_entry(data->store, 2015 add_buddyname_autocomplete_entry(data->store,
2118 NULL, NULL, set->account, set->name); 2016 NULL, NULL, set->account, set->name);
2119 #else
2120 /* Steal the name for the GCompletion. */
2121 data->log_items = g_list_append(data->log_items, set->name);
2122 set->name = set->normalized_name = NULL;
2123 #endif /* NEW_STYLE_COMPLETION */
2124 } 2017 }
2125 } 2018 }
2126 } 2019 }
2127 2020
2128 static void 2021 static void
2131 PurpleBlistNode *gnode, *cnode, *bnode; 2024 PurpleBlistNode *gnode, *cnode, *bnode;
2132 PidginFilterBuddyCompletionEntryFunc filter_func = data->filter_func; 2025 PidginFilterBuddyCompletionEntryFunc filter_func = data->filter_func;
2133 gpointer user_data = data->filter_func_user_data; 2026 gpointer user_data = data->filter_func_user_data;
2134 GHashTable *sets; 2027 GHashTable *sets;
2135 2028
2136 #ifdef NEW_STYLE_COMPLETION
2137 gtk_list_store_clear(data->store); 2029 gtk_list_store_clear(data->store);
2138 #else
2139 GList *item = g_list_append(NULL, NULL);
2140
2141 g_list_foreach(data->completion->items, (GFunc)g_free, NULL);
2142 g_completion_clear_items(data->completion);
2143 #endif /* NEW_STYLE_COMPLETION */
2144 2030
2145 for (gnode = purple_get_blist()->root; gnode != NULL; gnode = gnode->next) 2031 for (gnode = purple_get_blist()->root; gnode != NULL; gnode = gnode->next)
2146 { 2032 {
2147 if (!PURPLE_BLIST_NODE_IS_GROUP(gnode)) 2033 if (!PURPLE_BLIST_NODE_IS_GROUP(gnode))
2148 continue; 2034 continue;
2157 PidginBuddyCompletionEntry entry; 2043 PidginBuddyCompletionEntry entry;
2158 entry.is_buddy = TRUE; 2044 entry.is_buddy = TRUE;
2159 entry.entry.buddy = (PurpleBuddy *) bnode; 2045 entry.entry.buddy = (PurpleBuddy *) bnode;
2160 2046
2161 if (filter_func(&entry, user_data)) { 2047 if (filter_func(&entry, user_data)) {
2162 #ifdef NEW_STYLE_COMPLETION
2163 add_buddyname_autocomplete_entry(data->store, 2048 add_buddyname_autocomplete_entry(data->store,
2164 ((PurpleContact *)cnode)->alias, 2049 ((PurpleContact *)cnode)->alias,
2165 purple_buddy_get_contact_alias(entry.entry.buddy), 2050 purple_buddy_get_contact_alias(entry.entry.buddy),
2166 entry.entry.buddy->account, 2051 entry.entry.buddy->account,
2167 entry.entry.buddy->name 2052 entry.entry.buddy->name
2168 ); 2053 );
2169 #else
2170 item->data = g_strdup(entry.entry.buddy->name);
2171 g_completion_add_items(data->completion, item);
2172 #endif /* NEW_STYLE_COMPLETION */
2173 } 2054 }
2174 } 2055 }
2175 } 2056 }
2176 } 2057 }
2177
2178 #ifndef NEW_STYLE_COMPLETION
2179 g_list_free(item);
2180 data->log_items = NULL;
2181 #endif /* NEW_STYLE_COMPLETION */
2182 2058
2183 sets = purple_log_get_log_sets(); 2059 sets = purple_log_get_log_sets();
2184 g_hash_table_foreach(sets, (GHFunc)get_log_set_name, data); 2060 g_hash_table_foreach(sets, (GHFunc)get_log_set_name, data);
2185 g_hash_table_destroy(sets); 2061 g_hash_table_destroy(sets);
2186 2062
2187 #ifndef NEW_STYLE_COMPLETION
2188 g_completion_add_items(data->completion, data->log_items);
2189 g_list_free(data->log_items);
2190 #endif /* NEW_STYLE_COMPLETION */
2191 } 2063 }
2192 2064
2193 static void 2065 static void
2194 buddyname_autocomplete_destroyed_cb(GtkWidget *widget, gpointer data) 2066 buddyname_autocomplete_destroyed_cb(GtkWidget *widget, gpointer data)
2195 { 2067 {
2206 void 2078 void
2207 pidgin_setup_screenname_autocomplete_with_filter(GtkWidget *entry, GtkWidget *accountopt, PidginFilterBuddyCompletionEntryFunc filter_func, gpointer user_data) 2079 pidgin_setup_screenname_autocomplete_with_filter(GtkWidget *entry, GtkWidget *accountopt, PidginFilterBuddyCompletionEntryFunc filter_func, gpointer user_data)
2208 { 2080 {
2209 PidginCompletionData *data; 2081 PidginCompletionData *data;
2210 2082
2211 #ifdef NEW_STYLE_COMPLETION
2212 /* 2083 /*
2213 * Store the displayed completion value, the buddy name, the UTF-8 2084 * Store the displayed completion value, the buddy name, the UTF-8
2214 * normalized & casefolded buddy name, the UTF-8 normalized & 2085 * normalized & casefolded buddy name, the UTF-8 normalized &
2215 * casefolded value for comparison, and the account. 2086 * casefolded value for comparison, and the account.
2216 */ 2087 */
2250 gtk_entry_completion_set_model(completion, GTK_TREE_MODEL(store)); 2121 gtk_entry_completion_set_model(completion, GTK_TREE_MODEL(store));
2251 g_object_unref(store); 2122 g_object_unref(store);
2252 2123
2253 gtk_entry_completion_set_text_column(completion, 0); 2124 gtk_entry_completion_set_text_column(completion, 0);
2254 2125
2255 #else /* !NEW_STYLE_COMPLETION */
2256
2257 data = g_new0(PidginCompletionData, 1);
2258
2259 data->entry = entry;
2260 data->accountopt = accountopt;
2261 if (filter_func == NULL) {
2262 data->filter_func = pidgin_screenname_autocomplete_default_filter;
2263 data->filter_func_user_data = NULL;
2264 } else {
2265 data->filter_func = filter_func;
2266 data->filter_func_user_data = user_data;
2267 }
2268 data->completion = g_completion_new(NULL);
2269 data->completion_started = FALSE;
2270
2271 add_completion_list(data);
2272
2273 g_completion_set_compare(data->completion, g_ascii_strncasecmp);
2274
2275 g_signal_connect(G_OBJECT(entry), "event",
2276 G_CALLBACK(completion_entry_event), data);
2277 g_signal_connect(G_OBJECT(entry), "destroy",
2278 G_CALLBACK(destroy_completion_data), data);
2279
2280 #endif /* !NEW_STYLE_COMPLETION */
2281
2282 purple_signal_connect(purple_connections_get_handle(), "signed-on", entry, 2126 purple_signal_connect(purple_connections_get_handle(), "signed-on", entry,
2283 PURPLE_CALLBACK(repopulate_autocomplete), data); 2127 PURPLE_CALLBACK(repopulate_autocomplete), data);
2284 purple_signal_connect(purple_connections_get_handle(), "signed-off", entry, 2128 purple_signal_connect(purple_connections_get_handle(), "signed-off", entry,
2285 PURPLE_CALLBACK(repopulate_autocomplete), data); 2129 PURPLE_CALLBACK(repopulate_autocomplete), data);
2286 2130
2320 2164
2321 cursor = gdk_cursor_new(cursor_type); 2165 cursor = gdk_cursor_new(cursor_type);
2322 gdk_window_set_cursor(widget->window, cursor); 2166 gdk_window_set_cursor(widget->window, cursor);
2323 gdk_cursor_unref(cursor); 2167 gdk_cursor_unref(cursor);
2324 2168
2325 #if GTK_CHECK_VERSION(2,4,0)
2326 gdk_display_flush(gdk_drawable_get_display(GDK_DRAWABLE(widget->window))); 2169 gdk_display_flush(gdk_drawable_get_display(GDK_DRAWABLE(widget->window)));
2327 #else
2328 gdk_flush();
2329 #endif
2330 } 2170 }
2331 2171
2332 void pidgin_clear_cursor(GtkWidget *widget) 2172 void pidgin_clear_cursor(GtkWidget *widget)
2333 { 2173 {
2334 g_return_if_fail(widget != NULL); 2174 g_return_if_fail(widget != NULL);
2345 2185
2346 void (*callback)(const char*,gpointer); 2186 void (*callback)(const char*,gpointer);
2347 gpointer data; 2187 gpointer data;
2348 }; 2188 };
2349 2189
2350 #if !GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */
2351 static void
2352 icon_filesel_delete_cb(GtkWidget *w, struct _icon_chooser *dialog)
2353 {
2354 if (dialog->icon_filesel != NULL)
2355 gtk_widget_destroy(dialog->icon_filesel);
2356
2357 if (dialog->callback)
2358 dialog->callback(NULL, dialog->data);
2359
2360 g_free(dialog);
2361 }
2362 #endif /* FILECHOOSER */
2363
2364
2365
2366 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */
2367 static void 2190 static void
2368 icon_filesel_choose_cb(GtkWidget *widget, gint response, struct _icon_chooser *dialog) 2191 icon_filesel_choose_cb(GtkWidget *widget, gint response, struct _icon_chooser *dialog)
2369 { 2192 {
2370 char *filename, *current_folder; 2193 char *filename, *current_folder;
2371 2194
2385 if (current_folder != NULL) { 2208 if (current_folder != NULL) {
2386 purple_prefs_set_path(PIDGIN_PREFS_ROOT "/filelocations/last_icon_folder", current_folder); 2209 purple_prefs_set_path(PIDGIN_PREFS_ROOT "/filelocations/last_icon_folder", current_folder);
2387 g_free(current_folder); 2210 g_free(current_folder);
2388 } 2211 }
2389 2212
2390 #else /* FILECHOOSER */ 2213
2391 static void
2392 icon_filesel_choose_cb(GtkWidget *w, struct _icon_chooser *dialog)
2393 {
2394 char *filename, *current_folder;
2395
2396 filename = g_strdup(gtk_file_selection_get_filename(
2397 GTK_FILE_SELECTION(dialog->icon_filesel)));
2398
2399 /* If they typed in a directory, change there */
2400 if (pidgin_check_if_dir(filename,
2401 GTK_FILE_SELECTION(dialog->icon_filesel)))
2402 {
2403 g_free(filename);
2404 return;
2405 }
2406
2407 current_folder = g_path_get_dirname(filename);
2408 if (current_folder != NULL) {
2409 purple_prefs_set_path(PIDGIN_PREFS_ROOT "/filelocations/last_icon_folder", current_folder);
2410 g_free(current_folder);
2411 }
2412
2413 #endif /* FILECHOOSER */
2414 #if 0 /* mismatched curly braces */
2415 }
2416 #endif
2417 if (dialog->callback) 2214 if (dialog->callback)
2418 dialog->callback(filename, dialog->data); 2215 dialog->callback(filename, dialog->data);
2419 gtk_widget_destroy(dialog->icon_filesel); 2216 gtk_widget_destroy(dialog->icon_filesel);
2420 g_free(filename); 2217 g_free(filename);
2421 g_free(dialog); 2218 g_free(dialog);
2422 } 2219 }
2423 2220
2424 2221
2425 static void 2222 static void
2426 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */
2427 icon_preview_change_cb(GtkFileChooser *widget, struct _icon_chooser *dialog) 2223 icon_preview_change_cb(GtkFileChooser *widget, struct _icon_chooser *dialog)
2428 #else /* FILECHOOSER */
2429 icon_preview_change_cb(GtkTreeSelection *sel, struct _icon_chooser *dialog)
2430 #endif /* FILECHOOSER */
2431 { 2224 {
2432 GdkPixbuf *pixbuf, *scale; 2225 GdkPixbuf *pixbuf, *scale;
2433 int height, width; 2226 int height, width;
2434 char *basename, *markup, *size; 2227 char *basename, *markup, *size;
2435 struct stat st; 2228 struct stat st;
2436 char *filename; 2229 char *filename;
2437 2230
2438 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */
2439 filename = gtk_file_chooser_get_preview_filename( 2231 filename = gtk_file_chooser_get_preview_filename(
2440 GTK_FILE_CHOOSER(dialog->icon_filesel)); 2232 GTK_FILE_CHOOSER(dialog->icon_filesel));
2441 #else /* FILECHOOSER */
2442 filename = g_strdup(gtk_file_selection_get_filename(
2443 GTK_FILE_SELECTION(dialog->icon_filesel)));
2444 #endif /* FILECHOOSER */
2445 2233
2446 if (!filename || g_stat(filename, &st) || !(pixbuf = gdk_pixbuf_new_from_file(filename, NULL))) 2234 if (!filename || g_stat(filename, &st) || !(pixbuf = gdk_pixbuf_new_from_file(filename, NULL)))
2447 { 2235 {
2448 gtk_image_set_from_pixbuf(GTK_IMAGE(dialog->icon_preview), NULL); 2236 gtk_image_set_from_pixbuf(GTK_IMAGE(dialog->icon_preview), NULL);
2449 gtk_label_set_markup(GTK_LABEL(dialog->icon_text), ""); 2237 gtk_label_set_markup(GTK_LABEL(dialog->icon_text), "");
2475 2263
2476 2264
2477 GtkWidget *pidgin_buddy_icon_chooser_new(GtkWindow *parent, void(*callback)(const char *, gpointer), gpointer data) { 2265 GtkWidget *pidgin_buddy_icon_chooser_new(GtkWindow *parent, void(*callback)(const char *, gpointer), gpointer data) {
2478 struct _icon_chooser *dialog = g_new0(struct _icon_chooser, 1); 2266 struct _icon_chooser *dialog = g_new0(struct _icon_chooser, 1);
2479 2267
2480 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */
2481 GtkWidget *vbox; 2268 GtkWidget *vbox;
2482 #else
2483 GtkWidget *hbox;
2484 GtkWidget *tv;
2485 GtkTreeSelection *sel;
2486 #endif /* FILECHOOSER */
2487 const char *current_folder; 2269 const char *current_folder;
2488 2270
2489 dialog->callback = callback; 2271 dialog->callback = callback;
2490 dialog->data = data; 2272 dialog->data = data;
2491 2273
2492 current_folder = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/filelocations/last_icon_folder"); 2274 current_folder = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/filelocations/last_icon_folder");
2493 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */
2494 2275
2495 dialog->icon_filesel = gtk_file_chooser_dialog_new(_("Buddy Icon"), 2276 dialog->icon_filesel = gtk_file_chooser_dialog_new(_("Buddy Icon"),
2496 parent, 2277 parent,
2497 GTK_FILE_CHOOSER_ACTION_OPEN, 2278 GTK_FILE_CHOOSER_ACTION_OPEN,
2498 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, 2279 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
2519 g_signal_connect(G_OBJECT(dialog->icon_filesel), "update-preview", 2300 g_signal_connect(G_OBJECT(dialog->icon_filesel), "update-preview",
2520 G_CALLBACK(icon_preview_change_cb), dialog); 2301 G_CALLBACK(icon_preview_change_cb), dialog);
2521 g_signal_connect(G_OBJECT(dialog->icon_filesel), "response", 2302 g_signal_connect(G_OBJECT(dialog->icon_filesel), "response",
2522 G_CALLBACK(icon_filesel_choose_cb), dialog); 2303 G_CALLBACK(icon_filesel_choose_cb), dialog);
2523 icon_preview_change_cb(NULL, dialog); 2304 icon_preview_change_cb(NULL, dialog);
2524 #else /* FILECHOOSER */
2525 dialog->icon_filesel = gtk_file_selection_new(_("Buddy Icon"));
2526 dialog->icon_preview = gtk_image_new();
2527 dialog->icon_text = gtk_label_new(NULL);
2528 if ((current_folder != NULL) && (*current_folder != '\0'))
2529 gtk_file_selection_set_filename(GTK_FILE_SELECTION(dialog->icon_filesel),
2530 current_folder);
2531
2532 gtk_widget_set_size_request(GTK_WIDGET(dialog->icon_preview),-1, 50);
2533 hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
2534 gtk_box_pack_start(
2535 GTK_BOX(GTK_FILE_SELECTION(dialog->icon_filesel)->main_vbox),
2536 hbox, FALSE, FALSE, 0);
2537 gtk_box_pack_end(GTK_BOX(hbox), dialog->icon_preview,
2538 FALSE, FALSE, 0);
2539 gtk_box_pack_end(GTK_BOX(hbox), dialog->icon_text, FALSE, FALSE, 0);
2540
2541 tv = GTK_FILE_SELECTION(dialog->icon_filesel)->file_list;
2542 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv));
2543
2544 g_signal_connect(G_OBJECT(sel), "changed",
2545 G_CALLBACK(icon_preview_change_cb), dialog);
2546 g_signal_connect(
2547 G_OBJECT(GTK_FILE_SELECTION(dialog->icon_filesel)->ok_button),
2548 "clicked",
2549 G_CALLBACK(icon_filesel_choose_cb), dialog);
2550 g_signal_connect(
2551 G_OBJECT(GTK_FILE_SELECTION(dialog->icon_filesel)->cancel_button),
2552 "clicked",
2553 G_CALLBACK(icon_filesel_delete_cb), dialog);
2554 g_signal_connect(G_OBJECT(dialog->icon_filesel), "destroy",
2555 G_CALLBACK(icon_filesel_delete_cb), dialog);
2556 #endif /* FILECHOOSER */
2557 2305
2558 #ifdef _WIN32 2306 #ifdef _WIN32
2559 g_signal_connect(G_OBJECT(dialog->icon_filesel), "show", 2307 g_signal_connect(G_OBJECT(dialog->icon_filesel), "show",
2560 G_CALLBACK(winpidgin_ensure_onscreen), dialog->icon_filesel); 2308 G_CALLBACK(winpidgin_ensure_onscreen), dialog->icon_filesel);
2561 #endif 2309 #endif
2562 2310
2563 return dialog->icon_filesel; 2311 return dialog->icon_filesel;
2564 } 2312 }
2565 2313
2566 2314
2567 #if GTK_CHECK_VERSION(2,2,0)
2568 static gboolean 2315 static gboolean
2569 str_array_match(char **a, char **b) 2316 str_array_match(char **a, char **b)
2570 { 2317 {
2571 int i, j; 2318 int i, j;
2572 2319
2576 for (j = 0; b[j] != NULL; j++) 2323 for (j = 0; b[j] != NULL; j++)
2577 if (!g_ascii_strcasecmp(a[i], b[j])) 2324 if (!g_ascii_strcasecmp(a[i], b[j]))
2578 return TRUE; 2325 return TRUE;
2579 return FALSE; 2326 return FALSE;
2580 } 2327 }
2581 #endif
2582 2328
2583 gpointer 2329 gpointer
2584 pidgin_convert_buddy_icon(PurplePlugin *plugin, const char *path, size_t *len) 2330 pidgin_convert_buddy_icon(PurplePlugin *plugin, const char *path, size_t *len)
2585 { 2331 {
2586 PurplePluginProtocolInfo *prpl_info; 2332 PurplePluginProtocolInfo *prpl_info;
2587 #if GTK_CHECK_VERSION(2,2,0)
2588 char **prpl_formats; 2333 char **prpl_formats;
2589 int width, height; 2334 int width, height;
2590 char **pixbuf_formats = NULL; 2335 char **pixbuf_formats = NULL;
2591 GdkPixbufFormat *format; 2336 GdkPixbufFormat *format;
2592 GdkPixbuf *pixbuf; 2337 GdkPixbuf *pixbuf;
2593 #if !GTK_CHECK_VERSION(2,4,0)
2594 GdkPixbufLoader *loader;
2595 #endif
2596 #endif
2597 gchar *contents; 2338 gchar *contents;
2598 gsize length; 2339 gsize length;
2599 2340
2600 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); 2341 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
2601 2342
2602 g_return_val_if_fail(prpl_info->icon_spec.format != NULL, NULL); 2343 g_return_val_if_fail(prpl_info->icon_spec.format != NULL, NULL);
2603 2344
2604 2345
2605 #if GTK_CHECK_VERSION(2,2,0)
2606 #if GTK_CHECK_VERSION(2,4,0)
2607 format = gdk_pixbuf_get_file_info(path, &width, &height); 2346 format = gdk_pixbuf_get_file_info(path, &width, &height);
2608 #else 2347
2609 loader = gdk_pixbuf_loader_new();
2610 if (g_file_get_contents(path, &contents, &length, NULL)) {
2611 gdk_pixbuf_loader_write(loader, contents, length, NULL);
2612 g_free(contents);
2613 }
2614 gdk_pixbuf_loader_close(loader, NULL);
2615 pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
2616 width = gdk_pixbuf_get_width(pixbuf);
2617 height = gdk_pixbuf_get_height(pixbuf);
2618 format = gdk_pixbuf_loader_get_format(loader);
2619 g_object_unref(G_OBJECT(loader));
2620 #endif
2621 if (format == NULL) 2348 if (format == NULL)
2622 return NULL; 2349 return NULL;
2623 2350
2624 pixbuf_formats = gdk_pixbuf_format_get_extensions(format); 2351 pixbuf_formats = gdk_pixbuf_format_get_extensions(format);
2625 prpl_formats = g_strsplit(prpl_info->icon_spec.format,",",0); 2352 prpl_formats = g_strsplit(prpl_info->icon_spec.format,",",0);
2627 (!(prpl_info->icon_spec.scale_rules & PURPLE_ICON_SCALE_SEND) || /* The prpl doesn't scale before it sends OR */ 2354 (!(prpl_info->icon_spec.scale_rules & PURPLE_ICON_SCALE_SEND) || /* The prpl doesn't scale before it sends OR */
2628 (prpl_info->icon_spec.min_width <= width && 2355 (prpl_info->icon_spec.min_width <= width &&
2629 prpl_info->icon_spec.max_width >= width && 2356 prpl_info->icon_spec.max_width >= width &&
2630 prpl_info->icon_spec.min_height <= height && 2357 prpl_info->icon_spec.min_height <= height &&
2631 prpl_info->icon_spec.max_height >= height))) /* The icon is the correct size */ 2358 prpl_info->icon_spec.max_height >= height))) /* The icon is the correct size */
2632 #endif
2633 { 2359 {
2634 #if GTK_CHECK_VERSION(2,2,0)
2635 g_strfreev(prpl_formats); 2360 g_strfreev(prpl_formats);
2636 g_strfreev(pixbuf_formats); 2361 g_strfreev(pixbuf_formats);
2637 #endif 2362
2638 /* We don't need to scale the image. */ 2363 /* We don't need to scale the image. */
2639
2640 contents = NULL; 2364 contents = NULL;
2641 if (!g_file_get_contents(path, &contents, &length, NULL)) 2365 if (!g_file_get_contents(path, &contents, &length, NULL))
2642 { 2366 {
2643 g_free(contents); 2367 g_free(contents);
2644 #if GTK_CHECK_VERSION(2,2,0) && !GTK_CHECK_VERSION(2,4,0)
2645 g_object_unref(G_OBJECT(pixbuf));
2646 #endif
2647 return NULL; 2368 return NULL;
2648 } 2369 }
2649 } 2370 }
2650 #if GTK_CHECK_VERSION(2,2,0)
2651 else 2371 else
2652 { 2372 {
2653 int i; 2373 int i;
2654 GError *error = NULL; 2374 GError *error = NULL;
2655 GdkPixbuf *scale; 2375 GdkPixbuf *scale;
2766 } 2486 }
2767 2487
2768 if (len) 2488 if (len)
2769 *len = length; 2489 *len = length;
2770 return contents; 2490 return contents;
2771 #else 2491 }
2772 /*
2773 * The chosen icon wasn't the right size, and we're using
2774 * GTK+ 2.0 so we can't scale it.
2775 */
2776 return NULL;
2777 #endif
2778 }
2779
2780 #if !GTK_CHECK_VERSION(2,6,0)
2781 static void
2782 _gdk_file_scale_size_prepared_cb (GdkPixbufLoader *loader,
2783 int width,
2784 int height,
2785 gpointer data)
2786 {
2787 struct {
2788 gint width;
2789 gint height;
2790 gboolean preserve_aspect_ratio;
2791 } *info = data;
2792
2793 g_return_if_fail (width > 0 && height > 0);
2794
2795 if (info->preserve_aspect_ratio &&
2796 (info->width > 0 || info->height > 0)) {
2797 if (info->width < 0)
2798 {
2799 width = width * (double)info->height/(double)height;
2800 height = info->height;
2801 }
2802 else if (info->height < 0)
2803 {
2804 height = height * (double)info->width/(double)width;
2805 width = info->width;
2806 }
2807 else if ((double)height * (double)info->width >
2808 (double)width * (double)info->height) {
2809 width = 0.5 + (double)width * (double)info->height / (double)height;
2810 height = info->height;
2811 } else {
2812 height = 0.5 + (double)height * (double)info->width / (double)width;
2813 width = info->width;
2814 }
2815 } else {
2816 if (info->width > 0)
2817 width = info->width;
2818 if (info->height > 0)
2819 height = info->height;
2820 }
2821
2822 #if GTK_CHECK_VERSION(2,2,0) /* 2.0 users are going to have very strangely sized things */
2823 gdk_pixbuf_loader_set_size (loader, width, height);
2824 #else
2825 #warning nosnilmot could not be bothered to fix this properly for you
2826 #warning ... good luck ... your images may end up strange sizes
2827 #endif
2828 }
2829
2830 GdkPixbuf *
2831 gdk_pixbuf_new_from_file_at_scale(const char *filename, int width, int height,
2832 gboolean preserve_aspect_ratio,
2833 GError **error)
2834 {
2835 GdkPixbufLoader *loader;
2836 GdkPixbuf *pixbuf;
2837 guchar buffer [4096];
2838 int length;
2839 FILE *f;
2840 struct {
2841 gint width;
2842 gint height;
2843 gboolean preserve_aspect_ratio;
2844 } info;
2845 GdkPixbufAnimation *animation;
2846 GdkPixbufAnimationIter *iter;
2847 gboolean has_frame;
2848
2849 g_return_val_if_fail (filename != NULL, NULL);
2850 g_return_val_if_fail (width > 0 || width == -1, NULL);
2851 g_return_val_if_fail (height > 0 || height == -1, NULL);
2852
2853 f = g_fopen (filename, "rb");
2854 if (!f) {
2855 gint save_errno = errno;
2856 gchar *display_name = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
2857 g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (save_errno),
2858 _("Failed to open file '%s': %s"),
2859 display_name ? display_name : "(unknown)",
2860 g_strerror (save_errno));
2861 g_free (display_name);
2862 return NULL;
2863 }
2864
2865 loader = gdk_pixbuf_loader_new ();
2866
2867 info.width = width;
2868 info.height = height;
2869 info.preserve_aspect_ratio = preserve_aspect_ratio;
2870
2871 g_signal_connect (loader, "size-prepared", G_CALLBACK (_gdk_file_scale_size_prepared_cb), &info);
2872
2873 has_frame = FALSE;
2874 while (!has_frame && !feof (f) && !ferror (f)) {
2875 length = fread (buffer, 1, sizeof (buffer), f);
2876 if (length > 0)
2877 if (!gdk_pixbuf_loader_write (loader, buffer, length, error)) {
2878 gdk_pixbuf_loader_close (loader, NULL);
2879 fclose (f);
2880 g_object_unref (loader);
2881 return NULL;
2882 }
2883
2884 animation = gdk_pixbuf_loader_get_animation (loader);
2885 if (animation) {
2886 iter = gdk_pixbuf_animation_get_iter (animation, 0);
2887 if (!gdk_pixbuf_animation_iter_on_currently_loading_frame (iter)) {
2888 has_frame = TRUE;
2889 }
2890 g_object_unref (iter);
2891 }
2892 }
2893
2894 fclose (f);
2895
2896 if (!gdk_pixbuf_loader_close (loader, error) && !has_frame) {
2897 g_object_unref (loader);
2898 return NULL;
2899 }
2900
2901 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
2902
2903 if (!pixbuf) {
2904 gchar *display_name = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
2905 g_object_unref (loader);
2906 g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_FAILED,
2907 _("Failed to load image '%s': reason not known, probably a corrupt image file"),
2908 display_name ? display_name : "(unknown)");
2909 g_free (display_name);
2910 return NULL;
2911 }
2912
2913 g_object_ref (pixbuf);
2914
2915 g_object_unref (loader);
2916
2917 return pixbuf;
2918 }
2919 #endif /* ! Gtk 2.6.0 */
2920 2492
2921 void pidgin_set_custom_buddy_icon(PurpleAccount *account, const char *who, const char *filename) 2493 void pidgin_set_custom_buddy_icon(PurpleAccount *account, const char *who, const char *filename)
2922 { 2494 {
2923 PurpleBuddy *buddy; 2495 PurpleBuddy *buddy;
2924 PurpleContact *contact; 2496 PurpleContact *contact;
2948 return ret; 2520 return ret;
2949 } 2521 }
2950 2522
2951 void pidgin_set_urgent(GtkWindow *window, gboolean urgent) 2523 void pidgin_set_urgent(GtkWindow *window, gboolean urgent)
2952 { 2524 {
2953 #if GTK_CHECK_VERSION(2,8,0) 2525 #if defined _WIN32
2526 winpidgin_window_flash(window, urgent);
2527 #else
2954 gtk_window_set_urgency_hint(window, urgent); 2528 gtk_window_set_urgency_hint(window, urgent);
2955 #elif defined _WIN32
2956 winpidgin_window_flash(window, urgent);
2957 #elif defined GDK_WINDOWING_X11
2958 GdkWindow *gdkwin;
2959 XWMHints *hints;
2960
2961 g_return_if_fail(window != NULL);
2962
2963 gdkwin = GTK_WIDGET(window)->window;
2964
2965 g_return_if_fail(gdkwin != NULL);
2966
2967 hints = XGetWMHints(GDK_WINDOW_XDISPLAY(gdkwin),
2968 GDK_WINDOW_XWINDOW(gdkwin));
2969 if(!hints)
2970 hints = XAllocWMHints();
2971
2972 if (urgent)
2973 hints->flags |= XUrgencyHint;
2974 else
2975 hints->flags &= ~XUrgencyHint;
2976 XSetWMHints(GDK_WINDOW_XDISPLAY(gdkwin),
2977 GDK_WINDOW_XWINDOW(gdkwin), hints);
2978 XFree(hints);
2979 #else
2980 /* do something else? */
2981 #endif 2529 #endif
2982 } 2530 }
2983 2531
2984 static GSList *minidialogs = NULL; 2532 static GSList *minidialogs = NULL;
2985 2533
3284 style->text_aa[GTK_STATE_NORMAL].green >> 8, 2832 style->text_aa[GTK_STATE_NORMAL].green >> 8,
3285 style->text_aa[GTK_STATE_NORMAL].blue >> 8); 2833 style->text_aa[GTK_STATE_NORMAL].blue >> 8);
3286 return dim_grey_string; 2834 return dim_grey_string;
3287 } 2835 }
3288 2836
3289 #if !GTK_CHECK_VERSION(2,2,0)
3290 GtkTreePath *
3291 gtk_tree_path_new_from_indices (gint first_index, ...)
3292 {
3293 int arg;
3294 va_list args;
3295 GtkTreePath *path;
3296
3297 path = gtk_tree_path_new ();
3298
3299 va_start (args, first_index);
3300 arg = first_index;
3301
3302 while (arg != -1)
3303 {
3304 gtk_tree_path_append_index (path, arg);
3305 arg = va_arg (args, gint);
3306 }
3307
3308 va_end (args);
3309
3310 return path;
3311 }
3312 #endif
3313
3314 static void 2837 static void
3315 combo_box_changed_cb(GtkComboBox *combo_box, GtkEntry *entry) 2838 combo_box_changed_cb(GtkComboBox *combo_box, GtkEntry *entry)
3316 { 2839 {
3317 char *text = gtk_combo_box_get_active_text(combo_box); 2840 char *text = gtk_combo_box_get_active_text(combo_box);
3318 gtk_entry_set_text(entry, text ? text : ""); 2841 gtk_entry_set_text(entry, text ? text : "");
3454 return TRUE; 2977 return TRUE;
3455 } 2978 }
3456 return FALSE; 2979 return FALSE;
3457 #endif 2980 #endif
3458 #else 2981 #else
3459 #if GTK_CHECK_VERSION(2,4,0)
3460 /* This finds the currently active window and makes that the parent window. */ 2982 /* This finds the currently active window and makes that the parent window. */
3461 GList *windows = NULL; 2983 GList *windows = NULL;
3462 GtkWidget *parent = NULL; 2984 GtkWidget *parent = NULL;
3463 GdkEvent *event = gtk_get_current_event(); 2985 GdkEvent *event = gtk_get_current_event();
3464 GdkWindow *menu = NULL; 2986 GdkWindow *menu = NULL;
3497 g_list_free(windows); 3019 g_list_free(windows);
3498 if (parent) { 3020 if (parent) {
3499 gtk_window_set_transient_for(GTK_WINDOW(widget), GTK_WINDOW(parent)); 3021 gtk_window_set_transient_for(GTK_WINDOW(widget), GTK_WINDOW(parent));
3500 return TRUE; 3022 return TRUE;
3501 } 3023 }
3502 #endif
3503 return FALSE; 3024 return FALSE;
3504 #endif 3025 #endif
3505 } 3026 }
3506 3027
3507 GdkPixbuf * pidgin_pixbuf_from_imgstore(PurpleStoredImage *image) 3028 GdkPixbuf * pidgin_pixbuf_from_imgstore(PurpleStoredImage *image)
3581 { 3102 {
3582 /* Copied from gtkft.c:open_button_cb */ 3103 /* Copied from gtkft.c:open_button_cb */
3583 #ifdef _WIN32 3104 #ifdef _WIN32
3584 /* If using Win32... */ 3105 /* If using Win32... */
3585 int code; 3106 int code;
3586 if (G_WIN32_HAVE_WIDECHAR_API()) { 3107 wchar_t *wc_filename = g_utf8_to_utf16(
3587 wchar_t *wc_filename = g_utf8_to_utf16( 3108 uri, -1, NULL, NULL, NULL);
3588 uri, -1, NULL, NULL, NULL); 3109
3589 3110 code = (int)ShellExecuteW(NULL, NULL, wc_filename, NULL, NULL,
3590 code = (int)ShellExecuteW(NULL, NULL, wc_filename, NULL, NULL, 3111 SW_SHOW);
3591 SW_SHOW); 3112
3592 3113 g_free(wc_filename);
3593 g_free(wc_filename);
3594 } else {
3595 char *l_filename = g_locale_from_utf8(
3596 uri, -1, NULL, NULL, NULL);
3597
3598 code = (int)ShellExecuteA(NULL, NULL, l_filename, NULL, NULL,
3599 SW_SHOW);
3600
3601 g_free(l_filename);
3602 }
3603 3114
3604 if (code == SE_ERR_ASSOCINCOMPLETE || code == SE_ERR_NOASSOC) 3115 if (code == SE_ERR_ASSOCINCOMPLETE || code == SE_ERR_NOASSOC)
3605 { 3116 {
3606 purple_notify_error(imhtml, NULL, 3117 purple_notify_error(imhtml, NULL,
3607 _("There is no application configured to open this type of file."), NULL); 3118 _("There is no application configured to open this type of file."), NULL);
3694 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); 3205 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img);
3695 g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_link_activate), link); 3206 g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_link_activate), link);
3696 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); 3207 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
3697 3208
3698 /* Open Containing Directory */ 3209 /* Open Containing Directory */
3699 #if GTK_CHECK_VERSION(2,6,0)
3700 img = gtk_image_new_from_stock(GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU); 3210 img = gtk_image_new_from_stock(GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU);
3701 item = gtk_image_menu_item_new_with_mnemonic(_("Open _Containing Directory")); 3211 item = gtk_image_menu_item_new_with_mnemonic(_("Open _Containing Directory"));
3702 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); 3212 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img);
3703 #else 3213
3704 item = gtk_menu_item_new_with_mnemonic(_("Open _Containing Directory"));
3705 #endif
3706 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(open_containing_cb), (gpointer)url); 3214 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(open_containing_cb), (gpointer)url);
3707 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); 3215 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
3708 3216
3709 return TRUE; 3217 return TRUE;
3710 } 3218 }
3766 return TRUE; 3274 return TRUE;
3767 3275
3768 url = gtk_imhtml_link_get_url(link); 3276 url = gtk_imhtml_link_get_url(link);
3769 3277
3770 /* Play Sound */ 3278 /* Play Sound */
3771 #if GTK_CHECK_VERSION(2,6,0)
3772 img = gtk_image_new_from_stock(GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_MENU); 3279 img = gtk_image_new_from_stock(GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_MENU);
3773 item = gtk_image_menu_item_new_with_mnemonic(_("_Play Sound")); 3280 item = gtk_image_menu_item_new_with_mnemonic(_("_Play Sound"));
3774 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); 3281 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img);
3775 #else 3282
3776 item = gtk_menu_item_new_with_mnemonic(_("_Play Sound"));
3777 #endif
3778 g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_link_activate), link); 3283 g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_link_activate), link);
3779 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); 3284 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
3780 3285
3781 /* Save File */ 3286 /* Save File */
3782 img = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_MENU); 3287 img = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_MENU);
3894 int idx = 0; 3399 int idx = 0;
3895 LONG ret = ERROR_SUCCESS; 3400 LONG ret = ERROR_SUCCESS;
3896 3401
3897 do { 3402 do {
3898 DWORD nameSize = 256; 3403 DWORD nameSize = 256;
3899 char start[256]; 3404 wchar_t start[256];
3900 /* I don't think we need to worry about non-ASCII protocol names */ 3405 ret = RegEnumKeyExW(HKEY_CLASSES_ROOT, idx++, start, &nameSize,
3901 ret = RegEnumKeyExA(HKEY_CLASSES_ROOT, idx++, start, &nameSize,
3902 NULL, NULL, NULL, NULL); 3406 NULL, NULL, NULL, NULL);
3903 if (ret == ERROR_SUCCESS) { 3407 if (ret == ERROR_SUCCESS) {
3904 HKEY reg_key = NULL; 3408 HKEY reg_key = NULL;
3905 ret = RegOpenKeyExA(HKEY_CLASSES_ROOT, start, 0, KEY_READ, &reg_key); 3409 ret = RegOpenKeyExW(HKEY_CLASSES_ROOT, start, 0, KEY_READ, &reg_key);
3906 if (ret == ERROR_SUCCESS) { 3410 if (ret == ERROR_SUCCESS) {
3907 ret = RegQueryValueExA(reg_key, "URL Protocol", NULL, NULL, NULL, NULL); 3411 ret = RegQueryValueExW(reg_key, L"URL Protocol", NULL, NULL, NULL, NULL);
3908 if (ret == ERROR_SUCCESS) { 3412 if (ret == ERROR_SUCCESS) {
3909 gchar *protocol = g_strdup_printf("%s:", start); 3413 gchar *utf8 = g_utf16_to_utf8(start, -1, NULL, NULL, NULL);
3414 gchar *protocol = g_strdup_printf("%s:", utf8);
3415 g_free(utf8);
3910 registered_url_handlers = g_slist_prepend(registered_url_handlers, protocol); 3416 registered_url_handlers = g_slist_prepend(registered_url_handlers, protocol);
3911 /* We still pass everything to the "http" "open" handler for security reasons */ 3417 /* We still pass everything to the "http" "open" handler for security reasons */
3912 gtk_imhtml_class_register_protocol(protocol, url_clicked_cb, link_context_menu); 3418 gtk_imhtml_class_register_protocol(protocol, url_clicked_cb, link_context_menu);
3913 } 3419 }
3914 RegCloseKey(reg_key); 3420 RegCloseKey(reg_key);

mercurial