pidgin/gtkutils.c

branch
next.minor
changeset 29701
6c95c4bd2241
parent 29361
c73b60e914bb
parent 29686
f9dee36112d0
child 29744
c1ae9f0f57ee
child 32375
9ccb07c70f2a
equal deleted inserted replaced
29370:9ff8f3bdd0f5 29701:6c95c4bd2241
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;
2767 } 2487 }
2768 2488
2769 if (len) 2489 if (len)
2770 *len = length; 2490 *len = length;
2771 return contents; 2491 return contents;
2772 #else 2492 }
2773 /*
2774 * The chosen icon wasn't the right size, and we're using
2775 * GTK+ 2.0 so we can't scale it.
2776 */
2777 return NULL;
2778 #endif
2779 }
2780
2781 #if !GTK_CHECK_VERSION(2,6,0)
2782 static void
2783 _gdk_file_scale_size_prepared_cb (GdkPixbufLoader *loader,
2784 int width,
2785 int height,
2786 gpointer data)
2787 {
2788 struct {
2789 gint width;
2790 gint height;
2791 gboolean preserve_aspect_ratio;
2792 } *info = data;
2793
2794 g_return_if_fail (width > 0 && height > 0);
2795
2796 if (info->preserve_aspect_ratio &&
2797 (info->width > 0 || info->height > 0)) {
2798 if (info->width < 0)
2799 {
2800 width = width * (double)info->height/(double)height;
2801 height = info->height;
2802 }
2803 else if (info->height < 0)
2804 {
2805 height = height * (double)info->width/(double)width;
2806 width = info->width;
2807 }
2808 else if ((double)height * (double)info->width >
2809 (double)width * (double)info->height) {
2810 width = 0.5 + (double)width * (double)info->height / (double)height;
2811 height = info->height;
2812 } else {
2813 height = 0.5 + (double)height * (double)info->width / (double)width;
2814 width = info->width;
2815 }
2816 } else {
2817 if (info->width > 0)
2818 width = info->width;
2819 if (info->height > 0)
2820 height = info->height;
2821 }
2822
2823 #if GTK_CHECK_VERSION(2,2,0) /* 2.0 users are going to have very strangely sized things */
2824 gdk_pixbuf_loader_set_size (loader, width, height);
2825 #else
2826 #warning nosnilmot could not be bothered to fix this properly for you
2827 #warning ... good luck ... your images may end up strange sizes
2828 #endif
2829 }
2830
2831 GdkPixbuf *
2832 gdk_pixbuf_new_from_file_at_scale(const char *filename, int width, int height,
2833 gboolean preserve_aspect_ratio,
2834 GError **error)
2835 {
2836 GdkPixbufLoader *loader;
2837 GdkPixbuf *pixbuf;
2838 guchar buffer [4096];
2839 int length;
2840 FILE *f;
2841 struct {
2842 gint width;
2843 gint height;
2844 gboolean preserve_aspect_ratio;
2845 } info;
2846 GdkPixbufAnimation *animation;
2847 GdkPixbufAnimationIter *iter;
2848 gboolean has_frame;
2849
2850 g_return_val_if_fail (filename != NULL, NULL);
2851 g_return_val_if_fail (width > 0 || width == -1, NULL);
2852 g_return_val_if_fail (height > 0 || height == -1, NULL);
2853
2854 f = g_fopen (filename, "rb");
2855 if (!f) {
2856 gint save_errno = errno;
2857 gchar *display_name = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
2858 g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (save_errno),
2859 _("Failed to open file '%s': %s"),
2860 display_name ? display_name : "(unknown)",
2861 g_strerror (save_errno));
2862 g_free (display_name);
2863 return NULL;
2864 }
2865
2866 loader = gdk_pixbuf_loader_new ();
2867
2868 info.width = width;
2869 info.height = height;
2870 info.preserve_aspect_ratio = preserve_aspect_ratio;
2871
2872 g_signal_connect (loader, "size-prepared", G_CALLBACK (_gdk_file_scale_size_prepared_cb), &info);
2873
2874 has_frame = FALSE;
2875 while (!has_frame && !feof (f) && !ferror (f)) {
2876 length = fread (buffer, 1, sizeof (buffer), f);
2877 if (length > 0)
2878 if (!gdk_pixbuf_loader_write (loader, buffer, length, error)) {
2879 gdk_pixbuf_loader_close (loader, NULL);
2880 fclose (f);
2881 g_object_unref (loader);
2882 return NULL;
2883 }
2884
2885 animation = gdk_pixbuf_loader_get_animation (loader);
2886 if (animation) {
2887 iter = gdk_pixbuf_animation_get_iter (animation, 0);
2888 if (!gdk_pixbuf_animation_iter_on_currently_loading_frame (iter)) {
2889 has_frame = TRUE;
2890 }
2891 g_object_unref (iter);
2892 }
2893 }
2894
2895 fclose (f);
2896
2897 if (!gdk_pixbuf_loader_close (loader, error) && !has_frame) {
2898 g_object_unref (loader);
2899 return NULL;
2900 }
2901
2902 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
2903
2904 if (!pixbuf) {
2905 gchar *display_name = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
2906 g_object_unref (loader);
2907 g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_FAILED,
2908 _("Failed to load image '%s': reason not known, probably a corrupt image file"),
2909 display_name ? display_name : "(unknown)");
2910 g_free (display_name);
2911 return NULL;
2912 }
2913
2914 g_object_ref (pixbuf);
2915
2916 g_object_unref (loader);
2917
2918 return pixbuf;
2919 }
2920 #endif /* ! Gtk 2.6.0 */
2921 2493
2922 void pidgin_set_custom_buddy_icon(PurpleAccount *account, const char *who, const char *filename) 2494 void pidgin_set_custom_buddy_icon(PurpleAccount *account, const char *who, const char *filename)
2923 { 2495 {
2924 PurpleBuddy *buddy; 2496 PurpleBuddy *buddy;
2925 PurpleContact *contact; 2497 PurpleContact *contact;
2949 return ret; 2521 return ret;
2950 } 2522 }
2951 2523
2952 void pidgin_set_urgent(GtkWindow *window, gboolean urgent) 2524 void pidgin_set_urgent(GtkWindow *window, gboolean urgent)
2953 { 2525 {
2954 #if GTK_CHECK_VERSION(2,8,0) 2526 #if defined _WIN32
2527 winpidgin_window_flash(window, urgent);
2528 #else
2955 gtk_window_set_urgency_hint(window, urgent); 2529 gtk_window_set_urgency_hint(window, urgent);
2956 #elif defined _WIN32
2957 winpidgin_window_flash(window, urgent);
2958 #elif defined GDK_WINDOWING_X11
2959 GdkWindow *gdkwin;
2960 XWMHints *hints;
2961
2962 g_return_if_fail(window != NULL);
2963
2964 gdkwin = GTK_WIDGET(window)->window;
2965
2966 g_return_if_fail(gdkwin != NULL);
2967
2968 hints = XGetWMHints(GDK_WINDOW_XDISPLAY(gdkwin),
2969 GDK_WINDOW_XWINDOW(gdkwin));
2970 if(!hints)
2971 hints = XAllocWMHints();
2972
2973 if (urgent)
2974 hints->flags |= XUrgencyHint;
2975 else
2976 hints->flags &= ~XUrgencyHint;
2977 XSetWMHints(GDK_WINDOW_XDISPLAY(gdkwin),
2978 GDK_WINDOW_XWINDOW(gdkwin), hints);
2979 XFree(hints);
2980 #else
2981 /* do something else? */
2982 #endif 2530 #endif
2983 } 2531 }
2984 2532
2985 static GSList *minidialogs = NULL; 2533 static GSList *minidialogs = NULL;
2986 2534
3285 style->text_aa[GTK_STATE_NORMAL].green >> 8, 2833 style->text_aa[GTK_STATE_NORMAL].green >> 8,
3286 style->text_aa[GTK_STATE_NORMAL].blue >> 8); 2834 style->text_aa[GTK_STATE_NORMAL].blue >> 8);
3287 return dim_grey_string; 2835 return dim_grey_string;
3288 } 2836 }
3289 2837
3290 #if !GTK_CHECK_VERSION(2,2,0)
3291 GtkTreePath *
3292 gtk_tree_path_new_from_indices (gint first_index, ...)
3293 {
3294 int arg;
3295 va_list args;
3296 GtkTreePath *path;
3297
3298 path = gtk_tree_path_new ();
3299
3300 va_start (args, first_index);
3301 arg = first_index;
3302
3303 while (arg != -1)
3304 {
3305 gtk_tree_path_append_index (path, arg);
3306 arg = va_arg (args, gint);
3307 }
3308
3309 va_end (args);
3310
3311 return path;
3312 }
3313 #endif
3314
3315 static void 2838 static void
3316 combo_box_changed_cb(GtkComboBox *combo_box, GtkEntry *entry) 2839 combo_box_changed_cb(GtkComboBox *combo_box, GtkEntry *entry)
3317 { 2840 {
3318 char *text = gtk_combo_box_get_active_text(combo_box); 2841 char *text = gtk_combo_box_get_active_text(combo_box);
3319 gtk_entry_set_text(entry, text ? text : ""); 2842 gtk_entry_set_text(entry, text ? text : "");
3455 return TRUE; 2978 return TRUE;
3456 } 2979 }
3457 return FALSE; 2980 return FALSE;
3458 #endif 2981 #endif
3459 #else 2982 #else
3460 #if GTK_CHECK_VERSION(2,4,0)
3461 /* This finds the currently active window and makes that the parent window. */ 2983 /* This finds the currently active window and makes that the parent window. */
3462 GList *windows = NULL; 2984 GList *windows = NULL;
3463 GtkWidget *parent = NULL; 2985 GtkWidget *parent = NULL;
3464 GdkEvent *event = gtk_get_current_event(); 2986 GdkEvent *event = gtk_get_current_event();
3465 GdkWindow *menu = NULL; 2987 GdkWindow *menu = NULL;
3498 g_list_free(windows); 3020 g_list_free(windows);
3499 if (parent) { 3021 if (parent) {
3500 gtk_window_set_transient_for(GTK_WINDOW(widget), GTK_WINDOW(parent)); 3022 gtk_window_set_transient_for(GTK_WINDOW(widget), GTK_WINDOW(parent));
3501 return TRUE; 3023 return TRUE;
3502 } 3024 }
3503 #endif
3504 return FALSE; 3025 return FALSE;
3505 #endif 3026 #endif
3506 } 3027 }
3507 3028
3508 GdkPixbuf * pidgin_pixbuf_from_imgstore(PurpleStoredImage *image) 3029 GdkPixbuf * pidgin_pixbuf_from_imgstore(PurpleStoredImage *image)
3582 { 3103 {
3583 /* Copied from gtkft.c:open_button_cb */ 3104 /* Copied from gtkft.c:open_button_cb */
3584 #ifdef _WIN32 3105 #ifdef _WIN32
3585 /* If using Win32... */ 3106 /* If using Win32... */
3586 int code; 3107 int code;
3587 if (G_WIN32_HAVE_WIDECHAR_API()) { 3108 wchar_t *wc_filename = g_utf8_to_utf16(
3588 wchar_t *wc_filename = g_utf8_to_utf16( 3109 uri, -1, NULL, NULL, NULL);
3589 uri, -1, NULL, NULL, NULL); 3110
3590 3111 code = (int)ShellExecuteW(NULL, NULL, wc_filename, NULL, NULL,
3591 code = (int)ShellExecuteW(NULL, NULL, wc_filename, NULL, NULL, 3112 SW_SHOW);
3592 SW_SHOW); 3113
3593 3114 g_free(wc_filename);
3594 g_free(wc_filename);
3595 } else {
3596 char *l_filename = g_locale_from_utf8(
3597 uri, -1, NULL, NULL, NULL);
3598
3599 code = (int)ShellExecuteA(NULL, NULL, l_filename, NULL, NULL,
3600 SW_SHOW);
3601
3602 g_free(l_filename);
3603 }
3604 3115
3605 if (code == SE_ERR_ASSOCINCOMPLETE || code == SE_ERR_NOASSOC) 3116 if (code == SE_ERR_ASSOCINCOMPLETE || code == SE_ERR_NOASSOC)
3606 { 3117 {
3607 purple_notify_error(imhtml, NULL, 3118 purple_notify_error(imhtml, NULL,
3608 _("There is no application configured to open this type of file."), NULL); 3119 _("There is no application configured to open this type of file."), NULL);
3695 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); 3206 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img);
3696 g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_link_activate), link); 3207 g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_link_activate), link);
3697 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); 3208 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
3698 3209
3699 /* Open Containing Directory */ 3210 /* Open Containing Directory */
3700 #if GTK_CHECK_VERSION(2,6,0)
3701 img = gtk_image_new_from_stock(GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU); 3211 img = gtk_image_new_from_stock(GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU);
3702 item = gtk_image_menu_item_new_with_mnemonic(_("Open _Containing Directory")); 3212 item = gtk_image_menu_item_new_with_mnemonic(_("Open _Containing Directory"));
3703 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); 3213 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img);
3704 #else 3214
3705 item = gtk_menu_item_new_with_mnemonic(_("Open _Containing Directory"));
3706 #endif
3707 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(open_containing_cb), (gpointer)url); 3215 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(open_containing_cb), (gpointer)url);
3708 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); 3216 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
3709 3217
3710 return TRUE; 3218 return TRUE;
3711 } 3219 }
3767 return TRUE; 3275 return TRUE;
3768 3276
3769 url = gtk_imhtml_link_get_url(link); 3277 url = gtk_imhtml_link_get_url(link);
3770 3278
3771 /* Play Sound */ 3279 /* Play Sound */
3772 #if GTK_CHECK_VERSION(2,6,0)
3773 img = gtk_image_new_from_stock(GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_MENU); 3280 img = gtk_image_new_from_stock(GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_MENU);
3774 item = gtk_image_menu_item_new_with_mnemonic(_("_Play Sound")); 3281 item = gtk_image_menu_item_new_with_mnemonic(_("_Play Sound"));
3775 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); 3282 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img);
3776 #else 3283
3777 item = gtk_menu_item_new_with_mnemonic(_("_Play Sound"));
3778 #endif
3779 g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_link_activate), link); 3284 g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_link_activate), link);
3780 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); 3285 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
3781 3286
3782 /* Save File */ 3287 /* Save File */
3783 img = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_MENU); 3288 img = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_MENU);
3895 int idx = 0; 3400 int idx = 0;
3896 LONG ret = ERROR_SUCCESS; 3401 LONG ret = ERROR_SUCCESS;
3897 3402
3898 do { 3403 do {
3899 DWORD nameSize = 256; 3404 DWORD nameSize = 256;
3900 char start[256]; 3405 wchar_t start[256];
3901 /* I don't think we need to worry about non-ASCII protocol names */ 3406 ret = RegEnumKeyExW(HKEY_CLASSES_ROOT, idx++, start, &nameSize,
3902 ret = RegEnumKeyExA(HKEY_CLASSES_ROOT, idx++, start, &nameSize,
3903 NULL, NULL, NULL, NULL); 3407 NULL, NULL, NULL, NULL);
3904 if (ret == ERROR_SUCCESS) { 3408 if (ret == ERROR_SUCCESS) {
3905 HKEY reg_key = NULL; 3409 HKEY reg_key = NULL;
3906 ret = RegOpenKeyExA(HKEY_CLASSES_ROOT, start, 0, KEY_READ, &reg_key); 3410 ret = RegOpenKeyExW(HKEY_CLASSES_ROOT, start, 0, KEY_READ, &reg_key);
3907 if (ret == ERROR_SUCCESS) { 3411 if (ret == ERROR_SUCCESS) {
3908 ret = RegQueryValueExA(reg_key, "URL Protocol", NULL, NULL, NULL, NULL); 3412 ret = RegQueryValueExW(reg_key, L"URL Protocol", NULL, NULL, NULL, NULL);
3909 if (ret == ERROR_SUCCESS) { 3413 if (ret == ERROR_SUCCESS) {
3910 gchar *protocol = g_strdup_printf("%s:", start); 3414 gchar *utf8 = g_utf16_to_utf8(start, -1, NULL, NULL, NULL);
3415 gchar *protocol = g_strdup_printf("%s:", utf8);
3416 g_free(utf8);
3911 registered_url_handlers = g_slist_prepend(registered_url_handlers, protocol); 3417 registered_url_handlers = g_slist_prepend(registered_url_handlers, protocol);
3912 /* We still pass everything to the "http" "open" handler for security reasons */ 3418 /* We still pass everything to the "http" "open" handler for security reasons */
3913 gtk_imhtml_class_register_protocol(protocol, url_clicked_cb, link_context_menu); 3419 gtk_imhtml_class_register_protocol(protocol, url_clicked_cb, link_context_menu);
3914 } 3420 }
3915 RegCloseKey(reg_key); 3421 RegCloseKey(reg_key);

mercurial