Mercurial > pidgin
changeset 32043:b814c2878d12
merge of 'd74415beaf0f8e1ed4743514e1d90669676b8596'
and 'f21ba844464858c0ea853c940fd4433ce008cb07'
author | andrew.victor@mxit.com |
---|---|
date | Thu, 01 Sep 2011 18:26:08 +0000 |
parents | 01b832cc602a (current diff) 3340d322c8f8 (diff) |
children | d66ce874075a |
files | |
diffstat | 10 files changed, 492 insertions(+), 323 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog.API Wed Aug 31 21:26:02 2011 +0000 +++ b/ChangeLog.API Thu Sep 01 18:26:08 2011 +0000 @@ -8,6 +8,13 @@ * purple_notify_searchresult_column_is_visible * purple_notify_searchresult_column_set_visible * purple_notify_user_info_prepend_pair_plaintext + * purple_menu_action_get_callback + * purple_menu_action_get_children + * purple_menu_action_get_data + * purple_menu_action_set_label + * purple_menu_action_set_data + * purple_menu_action_set_callback + * purple_menu_action_set_children * purple_request_field_get_tooltip * purple_request_field_group_get_fields_list * purple_request_field_set_tooltip @@ -30,10 +37,16 @@ * purple_whiteboard_get_ui_data * purple_whiteboard_set_ui_data * purple_whiteboard_get_who + * purple_xfer_get_fd * purple_xfer_get_protocol_data * purple_xfer_get_ui_data + * purple_xfer_get_watcher + * purple_xfer_set_fd + * purple_Xfer_set_local_port * purple_xfer_set_protocol_data + * purple_xfer_set_status * purple_xfer_set_ui_data + * purple_xfer_set_watcher Changed: * purple_connection_error now takes a PurpleConnectionError @@ -69,6 +82,13 @@ * _XMLNodeType * GtkIMHtml.clipboard_html_string * GtkIMHtml.clipboard_text_string + * GtkIMHtmlFontDetail + * gtk_imhtml_animation_free + * gtk_imhtml_animation_new + * gtk_imhtml_image_add_to + * gtk_imhtml_image_free + * gtk_imhtml_image_new + * gtk_imhtml_image_scale * pidgin_blist_update_account_error_state * pidgin_check_if_dir * PIDGIN_DIALOG @@ -90,6 +110,7 @@ purple_util_fetch_url_request_len, insetad. * PurpleConnectionUiOps.report_disconnect_reason * struct _GtkIMHtmlFontDetail + * struct _PurpleMenuAction * struct _PurplePounce * struct _PurpleRequestField * struct _PurpleRoomlist
--- a/finch/gntblist.c Wed Aug 31 21:26:02 2011 +0000 +++ b/finch/gntblist.c Thu Sep 01 18:26:08 2011 +0000 @@ -1078,9 +1078,10 @@ PurpleBlistNode *node = ggblist->cnode; if (action) { void (*callback)(PurpleBlistNode *, gpointer); - callback = (void (*)(PurpleBlistNode *, gpointer))action->callback; + callback = (void (*)(PurpleBlistNode *, gpointer)) + purple_menu_action_get_callback(action); if (callback) - callback(node, action->data); + callback(node, purple_menu_action_get_data(action)); else return; } @@ -1095,15 +1096,17 @@ if (action == NULL) return; - item = gnt_menuitem_new(action->label); - if (action->callback) + item = gnt_menuitem_new(purple_menu_action_get_label(action)); + if (purple_menu_action_get_callback(action)) gnt_menuitem_set_callback(GNT_MENU_ITEM(item), context_menu_callback, action); gnt_menu_add_item(menu, GNT_MENU_ITEM(item)); - if (action->children) { + list = purple_menu_action_get_children(action); + + if (list) { GntWidget *sub = gnt_menu_new(GNT_MENU_POPUP); gnt_menuitem_set_submenu(item, GNT_MENU(sub)); - for (list = action->children; list; list = list->next) + for (; list; list = list->next) gnt_append_menu_action(GNT_MENU(sub), list->data, action); } } @@ -1123,7 +1126,7 @@ PurpleMenuAction *act = (PurpleMenuAction *) list->data; if (!act) continue; - act->data = node; + purple_menu_action_set_data(act, node); gnt_append_menu_action(menu, act, NULL); g_signal_connect_swapped(G_OBJECT(menu), "destroy", G_CALLBACK(purple_menu_action_free), act); @@ -1216,7 +1219,7 @@ autojoin_toggled(GntMenuItem *item, gpointer data) { PurpleMenuAction *action = data; - purple_blist_node_set_bool(action->data, "gnt-autojoin", + purple_blist_node_set_bool(purple_menu_action_get_data(action), "gnt-autojoin", gnt_menuitem_check_get_checked(GNT_MENU_ITEM_CHECK(item))); } @@ -1224,7 +1227,8 @@ create_chat_menu(GntMenu *menu, PurpleChat *chat) { PurpleMenuAction *action = purple_menu_action_new(_("Auto-join"), NULL, chat, NULL); - GntMenuItem *check = gnt_menuitem_check_new(action->label); + GntMenuItem *check = gnt_menuitem_check_new( + purple_menu_action_get_label(action)); gnt_menuitem_check_set_checked(GNT_MENU_ITEM_CHECK(check), purple_blist_node_get_bool((PurpleBlistNode*)chat, "gnt-autojoin")); gnt_menu_add_item(menu, check);
--- a/libpurple/ft.c Wed Aug 31 21:26:02 2011 +0000 +++ b/libpurple/ft.c Thu Sep 01 18:26:08 2011 +0000 @@ -220,7 +220,7 @@ purple_xfer_destroy(xfer); } -static void +void purple_xfer_set_status(PurpleXfer *xfer, PurpleXferStatusType status) { g_return_if_fail(xfer != NULL); @@ -720,6 +720,20 @@ purple_xfer_unref(xfer); } +int purple_xfer_get_fd(PurpleXfer *xfer) +{ + g_return_val_if_fail(xfer != NULL, 0); + + return xfer->fd; +} + +int purple_xfer_get_watcher(PurpleXfer *xfer) +{ + g_return_val_if_fail(xfer != NULL, 0); + + return xfer->watcher; +} + PurpleXferType purple_xfer_get_type(const PurpleXfer *xfer) { @@ -864,6 +878,20 @@ return xfer->end_time; } +void purple_xfer_set_fd(PurpleXfer *xfer, int fd) +{ + g_return_if_fail(xfer != NULL); + + xfer->fd = fd; +} + +void purple_xfer_set_watcher(PurpleXfer *xfer, int watcher) +{ + g_return_if_fail(xfer != NULL); + + xfer->watcher = watcher; +} + void purple_xfer_set_completed(PurpleXfer *xfer, gboolean completed) { @@ -947,6 +975,14 @@ } void +purple_xfer_set_local_port(PurpleXfer *xfer, unsigned int local_port) +{ + g_return_if_fail(xfer != NULL); + + xfer->local_port = local_port; +} + +void purple_xfer_set_bytes_sent(PurpleXfer *xfer, size_t bytes_sent) { g_return_if_fail(xfer != NULL);
--- a/libpurple/ft.h Wed Aug 31 21:26:02 2011 +0000 +++ b/libpurple/ft.h Thu Sep 01 18:26:08 2011 +0000 @@ -266,6 +266,24 @@ void purple_xfer_request_denied(PurpleXfer *xfer); /** + * Returns the socket file descriptor. + * + * @param xfer The file transfer. + * + * @return The socket file descriptor. + */ +int purple_xfer_get_fd(PurpleXfer *xfer); + +/** + * Returns the Watcher for the transfer. + * + * @param xfer The file transfer. + * + * @return The watcher. + */ +int purple_xfer_get_watcher(PurpleXfer *xfer); + +/** * Returns the type of file transfer. * * @param xfer The file transfer. @@ -426,6 +444,22 @@ time_t purple_xfer_get_end_time(const PurpleXfer *xfer); /** + * Sets the socket file descriptor. + * + * @param xfer The file transfer. + * @param fd The file descriptor. + */ +void purple_xfer_set_fd(PurpleXfer *xfer, int fd); + +/** + * Sets the watcher for the file transfer. + * + * @param xfer The file transfer. + * @param watcher The watcher. + */ +void purple_xfer_set_watcher(PurpleXfer *xfer, int watcher); + +/** * Sets the completed state for the file transfer. * * @param xfer The file transfer. @@ -434,6 +468,14 @@ void purple_xfer_set_completed(PurpleXfer *xfer, gboolean completed); /** + * Sets the current status for the file transfer. + * + * @param xfer The file transfer. + * @param status The current status. + */ +void purple_xfer_set_status(PurpleXfer *xfer, PurpleXferStatusType status); + +/** * Sets the filename for the file transfer. * * @param xfer The file transfer. @@ -466,6 +508,14 @@ void purple_xfer_set_size(PurpleXfer *xfer, size_t size); /** + * Sets the local port of the file transfer. + * + * @param xfer The file transfer. + * @param local_port The local port. + */ +void purple_xfer_set_local_port(PurpleXfer *xfer, unsigned int local_port); + +/** * Sets the current working position in the active file transfer. This * can be used to jump backward in the file if the protocol detects * that some bit of data needs to be resent or has been sent twice.
--- a/libpurple/util.c Wed Aug 31 21:26:02 2011 +0000 +++ b/libpurple/util.c Thu Sep 01 18:26:08 2011 +0000 @@ -73,6 +73,14 @@ PurpleAccount *account; }; +struct _PurpleMenuAction +{ + char *label; + PurpleCallback callback; + gpointer data; + GList *children; +}; + static char *custom_user_dir = NULL; static char *user_dir = NULL; @@ -98,6 +106,63 @@ g_free(act); } +char * purple_menu_action_get_label(const PurpleMenuAction *act) +{ + g_return_val_if_fail(act != NULL, NULL); + + return act->label; +} + +PurpleCallback * +purple_menu_action_get_callback(const PurpleMenuAction *act) +{ + g_return_val_if_fail(act != NULL, NULL); + + return act->callback; +} + +gpointer purple_menu_action_get_data(const PurpleMenuAction *act) +{ + g_return_val_if_fail(act != NULL, NULL); + + return act->data; +} + +GList* purple_menu_action_get_children(const PurpleMenuAction *act) +{ + g_return_val_if_fail(act != NULL, NULL); + + return act->children; +} + +void purple_menu_action_set_label(PurpleMenuAction *act, char *label) +{ + g_return_if_fail(act != NULL); + + act-> label = label; +} + +void purple_menu_action_set_callback(PurpleMenuAction *act, PurpleCallback callback) +{ + g_return_if_fail(act != NULL); + + act->callback = callback; +} + +void purple_menu_action_set_data(PurpleMenuAction *act, gpointer data) +{ + g_return_if_fail(act != NULL); + + act->data = data; +} + +void purple_menu_action_set_children(PurpleMenuAction *act, GList *children) +{ + g_return_if_fail(act != NULL); + + act->children = children; +} + void purple_util_init(void) {
--- a/libpurple/util.h Wed Aug 31 21:26:02 2011 +0000 +++ b/libpurple/util.h Thu Sep 01 18:26:08 2011 +0000 @@ -51,14 +51,6 @@ extern "C" { #endif -struct _PurpleMenuAction -{ - char *label; - PurpleCallback callback; - gpointer data; - GList *children; -}; - typedef char *(*PurpleInfoFieldFormatCallback)(const char *field, size_t len); /** @@ -96,12 +88,79 @@ void purple_menu_action_free(PurpleMenuAction *act); /** + * Returns the label of the PurpleMenuAction. + * + * @param act The PurpleMenuAction. + * + * @return The label string. + */ +char * purple_menu_action_get_label(const PurpleMenuAction *act); + +/** + * Returns the callback of the PurpleMenuAction. + * + * @param act The PurpleMenuAction. + * + * @return The callback function. + */ +PurpleCallback *purple_menu_action_get_callback(const PurpleMenuAction *act); + +/** + * Returns the data stored in the PurpleMenuAction. + * + * @param act The PurpleMenuAction. + * + * @return The data. + */ +gpointer purple_menu_action_get_data(const PurpleMenuAction *act); + +/** + * Returns the children of the PurpleMenuAction. + * + * @param act The PurpleMenuAction. + * + * @return The GList of children. + */ +GList* purple_menu_action_get_children(const PurpleMenuAction *act); + +/** + * Set the label to the PurpleMenuAction. + * + * @param act The menu action. + * @param label The label for the menu action. + */ +void purple_menu_action_set_label(PurpleMenuAction *act, char *label); + +/** + * Set the callback that will be used by the PurpleMenuAction. + * + * @param act The menu action. + * @param callback The callback. + */ +void purple_menu_action_set_callback(PurpleMenuAction *act, PurpleCallback callback); + +/** + * Set the label to the PurpleMenuAction. + * + * @param act The menu action. + * @param data The data used by this PurpleMenuAction + */ +void purple_menu_action_set_data(PurpleMenuAction *act, gpointer data); + +/** + * Set the children of the PurpleMenuAction. + * + * @param act The menu action. + * @param children The PurpleMenuAtion children + */ +void purple_menu_action_set_children(PurpleMenuAction *act, GList *children); + +/** * Set the appropriate presence values for the currently playing song. * * @param title The title of the song, @c NULL to unset the value. * @param artist The artist of the song, can be @c NULL. * @param album The album of the song, can be @c NULL. - * @since 2.4.0 */ void purple_util_set_current_song(const char *title, const char *artist, const char *album); @@ -115,7 +174,6 @@ * @param unused Currently unused, must be @c NULL. * * @return The formatted string. The caller must g_free the returned string. - * @since 2.4.0 */ char * purple_util_format_song_info(const char *title, const char *artist, const char *album, gpointer unused); @@ -127,15 +185,11 @@ /** * Initializes the utility subsystem. - * - * @since 2.3.0 */ void purple_util_init(void); /** * Uninitializes the util subsystem. - * - * @since 2.3.0 */ void purple_util_uninit(void); @@ -429,8 +483,6 @@ * This is exactly the same as g_markup_escape_text(), except that it * does not change ' to ' because ' is not a valid HTML 4 entity, * and is displayed literally in IE7. - * - * @since 2.6.0 */ gchar *purple_markup_escape_text(const gchar *text, gssize length); @@ -531,7 +583,6 @@ * this string when finished with it. * * @see purple_unescape_html() - * @since 2.7.0 */ char *purple_unescape_text(const char *text); @@ -624,8 +675,6 @@ * @param html The HTML text. * * @return TRUE if the text contains RTL text, FALSE otherwise. - * - * @since 2.6.0 */ gboolean purple_markup_is_rtl(const char *html); @@ -826,7 +875,6 @@ * * @return The address family of the socket (AF_INET, AF_INET6, etc) or -1 * on error. - * @since 2.7.0 */ int purple_socket_get_family(int fd); @@ -838,7 +886,6 @@ * * @param fd The socket file descriptor * @return TRUE if a socket can speak IPv4. - * @since 2.7.0 */ gboolean purple_socket_speaks_ipv4(int fd); @@ -860,8 +907,6 @@ * @param right A string to compare with left * * @return @c TRUE if the strings are the same, else @c FALSE. - * - * @since 2.6.0 */ gboolean purple_strequal(const gchar *left, const gchar *right); @@ -1242,7 +1287,6 @@ * @param ip The IP address to validate. * * @return True if the IP address is syntactically correct. - * @since 2.6.0 */ gboolean purple_ipv4_address_is_valid(const char *ip); @@ -1252,7 +1296,6 @@ * @param ip The IP address to validate. * * @return True if the IP address is syntactically correct. - * @since 2.6.0 */ gboolean purple_ipv6_address_is_valid(const char *ip); @@ -1320,7 +1363,6 @@ * @param str A valid UTF-8 string. * * @return A newly allocated UTF-8 string without the unprintable characters. - * @since 2.6.0 */ gchar *purple_utf8_strip_unprintables(const gchar *str); @@ -1332,7 +1374,6 @@ * @param errnum The error code. * * @return The UTF-8 error message. - * @since 2.4.0 */ G_CONST_RETURN gchar *purple_gai_strerror(gint errnum); @@ -1446,7 +1487,6 @@ * Returns a type 4 (random) UUID * * @return A UUID, caller is responsible for freeing it - * @since 2.7.0 */ gchar *purple_uuid_random(void);
--- a/pidgin/gtkimhtml.c Wed Aug 31 21:26:02 2011 +0000 +++ b/pidgin/gtkimhtml.c Thu Sep 01 18:26:08 2011 +0000 @@ -90,8 +90,7 @@ GtkTextTag *tag; }; -typedef struct _GtkIMHtmlProtocol -{ +typedef struct { char *name; int length; @@ -99,7 +98,8 @@ gboolean (*context_menu)(GtkIMHtml *imhtml, GtkIMHtmlLink *link, GtkWidget *menu); } GtkIMHtmlProtocol; -typedef struct _GtkIMHtmlFontDetail { +/* The five elements contained in a FONT tag */ +typedef struct { gushort size; gchar *face; gchar *fore; @@ -3593,125 +3593,38 @@ gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0); } -/* GtkIMHtmlScalable, gtk_imhtml_image, gtk_imhtml_hr */ -GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename, int id) -{ - GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage)); - - GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale; - GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to; - GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_image_free; - - im_image->pixbuf = img; - im_image->image = GTK_IMAGE(gtk_image_new_from_pixbuf(im_image->pixbuf)); - im_image->width = gdk_pixbuf_get_width(img); - im_image->height = gdk_pixbuf_get_height(img); - im_image->mark = NULL; - im_image->filename = g_strdup(filename); - im_image->id = id; - im_image->filesel = NULL; - - g_object_ref(img); - return GTK_IMHTML_SCALABLE(im_image); -} - -static gboolean -animate_image_cb(gpointer data) -{ - GtkIMHtmlImage *im_image; - int width, height; - int delay; - - im_image = data; - - /* Update the pointer to this GdkPixbuf frame of the animation */ - if (gdk_pixbuf_animation_iter_advance(GTK_IMHTML_ANIMATION(im_image)->iter, NULL)) { - GdkPixbuf *pb = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter); - g_object_unref(G_OBJECT(im_image->pixbuf)); - im_image->pixbuf = gdk_pixbuf_copy(pb); - - /* Update the displayed GtkImage */ - width = gdk_pixbuf_get_width(gtk_image_get_pixbuf(im_image->image)); - height = gdk_pixbuf_get_height(gtk_image_get_pixbuf(im_image->image)); - if (width > 0 && height > 0) - { - /* Need to scale the new frame to the same size as the old frame */ - GdkPixbuf *tmp; - tmp = gdk_pixbuf_scale_simple(im_image->pixbuf, width, height, GDK_INTERP_BILINEAR); - gtk_image_set_from_pixbuf(im_image->image, tmp); - g_object_unref(G_OBJECT(tmp)); - } else { - /* Display at full-size */ - gtk_image_set_from_pixbuf(im_image->image, im_image->pixbuf); - } - } - - delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100); - GTK_IMHTML_ANIMATION(im_image)->timer = g_timeout_add(delay, animate_image_cb, im_image); - - return FALSE; -} - -GtkIMHtmlScalable *gtk_imhtml_animation_new(GdkPixbufAnimation *anim, const gchar *filename, int id) -{ - GtkIMHtmlImage *im_image = (GtkIMHtmlImage *) g_new0(GtkIMHtmlAnimation, 1); - - GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale; - GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to; - GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_animation_free; - - GTK_IMHTML_ANIMATION(im_image)->anim = anim; - if (gdk_pixbuf_animation_is_static_image(anim)) { - im_image->pixbuf = gdk_pixbuf_animation_get_static_image(anim); - g_object_ref(im_image->pixbuf); - } else { - int delay; - GdkPixbuf *pb; - GTK_IMHTML_ANIMATION(im_image)->iter = gdk_pixbuf_animation_get_iter(anim, NULL); - pb = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter); - im_image->pixbuf = gdk_pixbuf_copy(pb); - delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100); - GTK_IMHTML_ANIMATION(im_image)->timer = g_timeout_add(delay, animate_image_cb, im_image); - } - im_image->image = GTK_IMAGE(gtk_image_new_from_pixbuf(im_image->pixbuf)); - im_image->width = gdk_pixbuf_animation_get_width(anim); - im_image->height = gdk_pixbuf_animation_get_height(anim); - im_image->filename = g_strdup(filename); - im_image->id = id; - - g_object_ref(anim); - - return GTK_IMHTML_SCALABLE(im_image); -} - -void gtk_imhtml_image_scale(GtkIMHtmlScalable *scale, int width, int height) -{ - GtkIMHtmlImage *im_image = (GtkIMHtmlImage *)scale; - - if (im_image->width > width || im_image->height > height) { - double ratio_w, ratio_h, ratio; - int new_h, new_w; - GdkPixbuf *new_image = NULL; - - ratio_w = ((double)width - 2) / im_image->width; - ratio_h = ((double)height - 2) / im_image->height; - - ratio = (ratio_w < ratio_h) ? ratio_w : ratio_h; - - new_w = (int)(im_image->width * ratio); - new_h = (int)(im_image->height * ratio); - - new_image = gdk_pixbuf_scale_simple(im_image->pixbuf, new_w, new_h, GDK_INTERP_BILINEAR); - gtk_image_set_from_pixbuf(im_image->image, new_image); - g_object_unref(G_OBJECT(new_image)); - } else if (gdk_pixbuf_get_width(gtk_image_get_pixbuf(im_image->image)) != im_image->width) { - /* Enough space to show the full-size of the image. */ - GdkPixbuf *new_image; - - new_image = gdk_pixbuf_scale_simple(im_image->pixbuf, im_image->width, im_image->height, GDK_INTERP_BILINEAR); - gtk_image_set_from_pixbuf(im_image->image, new_image); - g_object_unref(G_OBJECT(new_image)); - } +/** + * Destroys and frees a GTK+ IM/HTML scalable image. + * + * @param scale The GTK+ IM/HTML scalable. + */ +static void gtk_imhtml_image_free(GtkIMHtmlScalable *scale) +{ + GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; + + g_object_unref(image->pixbuf); + g_free(image->filename); + if (image->filesel) + gtk_widget_destroy(image->filesel); + g_free(scale); +} + +/** + * Destroys and frees a GTK+ IM/HTML scalable animation. + * + * @param scale The GTK+ IM/HTML scalable. + */ +static void gtk_imhtml_animation_free(GtkIMHtmlScalable *scale) +{ + GtkIMHtmlAnimation *animation = (GtkIMHtmlAnimation *)scale; + + if (animation->timer > 0) + g_source_remove(animation->timer); + if (animation->iter != NULL) + g_object_unref(animation->iter); + g_object_unref(animation->anim); + + gtk_imhtml_image_free(scale); } static void @@ -3918,55 +3831,51 @@ } -static gboolean gtk_imhtml_smiley_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlSmiley *smiley) -{ - GdkPixbufAnimation *anim = NULL; - GtkIMHtmlImageSave *save = NULL; - gboolean ret; - - if (event->type != GDK_BUTTON_RELEASE || ((GdkEventButton*)event)->button != 3) - return FALSE; - - anim = gtk_smiley_get_image(smiley); - if (!anim) - return FALSE; - - save = g_new0(GtkIMHtmlImageSave, 1); - save->image = (GtkIMHtmlScalable *)gtk_imhtml_animation_new(anim, smiley->smile, 0); - save->data = smiley->data; /* Do not need to memdup here, since the smiley is not - destroyed before this GtkIMHtmlImageSave */ - save->datasize = smiley->datasize; - ret = gtk_imhtml_image_clicked(w, event, save); - g_object_set_data_full(G_OBJECT(w), "image-data", save->image, (GDestroyNotify)gtk_imhtml_animation_free); - g_object_set_data_full(G_OBJECT(w), "image-save-data", save, (GDestroyNotify)g_free); - return ret; -} - -void gtk_imhtml_image_free(GtkIMHtmlScalable *scale) -{ - GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; - - g_object_unref(image->pixbuf); - g_free(image->filename); - if (image->filesel) - gtk_widget_destroy(image->filesel); - g_free(scale); -} - -void gtk_imhtml_animation_free(GtkIMHtmlScalable *scale) -{ - GtkIMHtmlAnimation *animation = (GtkIMHtmlAnimation *)scale; - - if (animation->timer > 0) - g_source_remove(animation->timer); - if (animation->iter != NULL) - g_object_unref(animation->iter); - g_object_unref(animation->anim); - - gtk_imhtml_image_free(scale); -} - -void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) +/** + * Rescales a GTK+ IM/HTML scalable image to a given size. + * + * @param scale The GTK+ IM/HTML scalable. + * @param width The new width. + * @param height The new height. + */ +static void gtk_imhtml_image_scale(GtkIMHtmlScalable *scale, int width, int height) +{ + GtkIMHtmlImage *im_image = (GtkIMHtmlImage *)scale; + + if (im_image->width > width || im_image->height > height) { + double ratio_w, ratio_h, ratio; + int new_h, new_w; + GdkPixbuf *new_image = NULL; + + ratio_w = ((double)width - 2) / im_image->width; + ratio_h = ((double)height - 2) / im_image->height; + + ratio = (ratio_w < ratio_h) ? ratio_w : ratio_h; + + new_w = (int)(im_image->width * ratio); + new_h = (int)(im_image->height * ratio); + + new_image = gdk_pixbuf_scale_simple(im_image->pixbuf, new_w, new_h, GDK_INTERP_BILINEAR); + gtk_image_set_from_pixbuf(im_image->image, new_image); + g_object_unref(G_OBJECT(new_image)); + } else if (gdk_pixbuf_get_width(gtk_image_get_pixbuf(im_image->image)) != im_image->width) { + /* Enough space to show the full-size of the image. */ + GdkPixbuf *new_image; + + new_image = gdk_pixbuf_scale_simple(im_image->pixbuf, im_image->width, im_image->height, GDK_INTERP_BILINEAR); + gtk_image_set_from_pixbuf(im_image->image, new_image); + g_object_unref(G_OBJECT(new_image)); + } +} + +/** + * Adds a GTK+ IM/HTML scalable image to a given GTK+ IM/HTML at a given iter. + * + * @param scale The GTK+ IM/HTML scalable. + * @param imhtml The GTK+ IM/HTML. + * @param iter The GtkTextIter at which to add the scalable. + */ +static void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) { GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; GtkWidget *box = gtk_event_box_new(); @@ -3994,6 +3903,123 @@ g_object_set_data_full(G_OBJECT(box), "image-save-data", save, (GDestroyNotify)g_free); } +/** + * Creates and returns a new GTK+ IM/HTML scalable object with an image. + * + * @param img A GdkPixbuf of the image to add. + * @param filename The filename to associate with the image. + * @param id The id to associate with the image. + * + * @return A new IM/HTML Scalable object with an image. + */ +static GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename, int id) +{ + GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage)); + + GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale; + GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to; + GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_image_free; + + im_image->pixbuf = img; + im_image->image = GTK_IMAGE(gtk_image_new_from_pixbuf(im_image->pixbuf)); + im_image->width = gdk_pixbuf_get_width(img); + im_image->height = gdk_pixbuf_get_height(img); + im_image->mark = NULL; + im_image->filename = g_strdup(filename); + im_image->id = id; + im_image->filesel = NULL; + + g_object_ref(img); + return GTK_IMHTML_SCALABLE(im_image); +} + +static gboolean +animate_image_cb(gpointer data) +{ + GtkIMHtmlImage *im_image; + int width, height; + int delay; + + im_image = data; + + /* Update the pointer to this GdkPixbuf frame of the animation */ + if (gdk_pixbuf_animation_iter_advance(GTK_IMHTML_ANIMATION(im_image)->iter, NULL)) { + GdkPixbuf *pb = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter); + g_object_unref(G_OBJECT(im_image->pixbuf)); + im_image->pixbuf = gdk_pixbuf_copy(pb); + + /* Update the displayed GtkImage */ + width = gdk_pixbuf_get_width(gtk_image_get_pixbuf(im_image->image)); + height = gdk_pixbuf_get_height(gtk_image_get_pixbuf(im_image->image)); + if (width > 0 && height > 0) + { + /* Need to scale the new frame to the same size as the old frame */ + GdkPixbuf *tmp; + tmp = gdk_pixbuf_scale_simple(im_image->pixbuf, width, height, GDK_INTERP_BILINEAR); + gtk_image_set_from_pixbuf(im_image->image, tmp); + g_object_unref(G_OBJECT(tmp)); + } else { + /* Display at full-size */ + gtk_image_set_from_pixbuf(im_image->image, im_image->pixbuf); + } + } + + delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100); + GTK_IMHTML_ANIMATION(im_image)->timer = g_timeout_add(delay, animate_image_cb, im_image); + + return FALSE; +} + +/** + * Creates and returns a new GTK+ IM/HTML scalable object with an + * animated image. + * + * @param img A GdkPixbufAnimation of the image to add. + * @param filename The filename to associate with the image. + * @param id The id to associate with the image. + * + * @return A new IM/HTML Scalable object with an image. + * + * @since 2.1.0 + */ +/* + * TODO: All this animation code could be combined much better with + * the image code. It couldn't be done when it was written + * because it requires breaking backward compatibility. It + * would be good to do it for 3.0.0. + */ +static GtkIMHtmlScalable *gtk_imhtml_animation_new(GdkPixbufAnimation *anim, const gchar *filename, int id) +{ + GtkIMHtmlImage *im_image = (GtkIMHtmlImage *) g_new0(GtkIMHtmlAnimation, 1); + + GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale; + GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to; + GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_animation_free; + + GTK_IMHTML_ANIMATION(im_image)->anim = anim; + if (gdk_pixbuf_animation_is_static_image(anim)) { + im_image->pixbuf = gdk_pixbuf_animation_get_static_image(anim); + g_object_ref(im_image->pixbuf); + } else { + int delay; + GdkPixbuf *pb; + GTK_IMHTML_ANIMATION(im_image)->iter = gdk_pixbuf_animation_get_iter(anim, NULL); + pb = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter); + im_image->pixbuf = gdk_pixbuf_copy(pb); + delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100); + GTK_IMHTML_ANIMATION(im_image)->timer = g_timeout_add(delay, animate_image_cb, im_image); + } + im_image->image = GTK_IMAGE(gtk_image_new_from_pixbuf(im_image->pixbuf)); + im_image->width = gdk_pixbuf_animation_get_width(anim); + im_image->height = gdk_pixbuf_animation_get_height(anim); + im_image->filename = g_strdup(filename); + im_image->id = id; + + g_object_ref(anim); + + return GTK_IMHTML_SCALABLE(im_image); +} + GtkIMHtmlScalable *gtk_imhtml_hr_new() { GtkIMHtmlHr *hr = g_malloc(sizeof(GtkIMHtmlHr)); @@ -4918,6 +4944,30 @@ } } +static gboolean gtk_imhtml_smiley_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlSmiley *smiley) +{ + GdkPixbufAnimation *anim = NULL; + GtkIMHtmlImageSave *save = NULL; + gboolean ret; + + if (event->type != GDK_BUTTON_RELEASE || ((GdkEventButton*)event)->button != 3) + return FALSE; + + anim = gtk_smiley_get_image(smiley); + if (!anim) + return FALSE; + + save = g_new0(GtkIMHtmlImageSave, 1); + save->image = (GtkIMHtmlScalable *)gtk_imhtml_animation_new(anim, smiley->smile, 0); + save->data = smiley->data; /* Do not need to memdup here, since the smiley is not + destroyed before this GtkIMHtmlImageSave */ + save->datasize = smiley->datasize; + ret = gtk_imhtml_image_clicked(w, event, save); + g_object_set_data_full(G_OBJECT(w), "image-data", save->image, (GDestroyNotify)gtk_imhtml_animation_free); + g_object_set_data_full(G_OBJECT(w), "image-save-data", save, (GDestroyNotify)g_free); + return ret; +} + void gtk_imhtml_insert_smiley_at_iter(GtkIMHtml *imhtml, const char *sml, char *smiley, GtkTextIter *iter) { GdkPixbuf *pixbuf = NULL;
--- a/pidgin/gtkimhtml.h Wed Aug 31 21:26:02 2011 +0000 +++ b/pidgin/gtkimhtml.h Thu Sep 01 18:26:08 2011 +0000 @@ -50,9 +50,6 @@ typedef struct _GtkIMHtml GtkIMHtml; typedef struct _GtkIMHtmlClass GtkIMHtmlClass; -#if !(defined PIDGIN_DISABLE_DEPRECATED) && !(defined _PIDGIN_GTKIMHTML_C_) -typedef struct _GtkIMHtmlFontDetail GtkIMHtmlFontDetail; /* The five elements contained in a FONT tag */ -#endif typedef struct _GtkSmileyTree GtkSmileyTree; typedef struct _GtkIMHtmlSmiley GtkIMHtmlSmiley; typedef struct _GtkIMHtmlScalable GtkIMHtmlScalable; @@ -419,73 +416,6 @@ GtkIMHtmlScalable *gtk_imhtml_scalable_new(void); /** - * Creates and returns a new GTK+ IM/HTML scalable object with an image. - * - * @param img A GdkPixbuf of the image to add. - * @param filename The filename to associate with the image. - * @param id The id to associate with the image. - * - * @return A new IM/HTML Scalable object with an image. - */ -GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename, int id); - -/** - * Creates and returns a new GTK+ IM/HTML scalable object with an - * animated image. - * - * @param img A GdkPixbufAnimation of the image to add. - * @param filename The filename to associate with the image. - * @param id The id to associate with the image. - * - * @return A new IM/HTML Scalable object with an image. - * - * @since 2.1.0 - */ -/* - * TODO: All this animation code could be combined much better with - * the image code. It couldn't be done when it was written - * because it requires breaking backward compatibility. It - * would be good to do it for 3.0.0. - */ -GtkIMHtmlScalable *gtk_imhtml_animation_new(GdkPixbufAnimation *img, const gchar *filename, int id); - -/** - * Destroys and frees a GTK+ IM/HTML scalable image. - * - * @param scale The GTK+ IM/HTML scalable. - */ -/* TODO: Is there any reason this isn't private? */ -void gtk_imhtml_image_free(GtkIMHtmlScalable *scale); - -/** - * Destroys and frees a GTK+ IM/HTML scalable animation. - * - * @param scale The GTK+ IM/HTML scalable. - */ -/* TODO: Is there any reason this isn't private? */ -void gtk_imhtml_animation_free(GtkIMHtmlScalable *scale); - -/** - * Rescales a GTK+ IM/HTML scalable image to a given size. - * - * @param scale The GTK+ IM/HTML scalable. - * @param width The new width. - * @param height The new height. - */ -/* TODO: Is there any reason this isn't private? */ -void gtk_imhtml_image_scale(GtkIMHtmlScalable *scale, int width, int height); - -/** - * Adds a GTK+ IM/HTML scalable image to a given GTK+ IM/HTML at a given iter. - * - * @param scale The GTK+ IM/HTML scalable. - * @param imhtml The GTK+ IM/HTML. - * @param iter The GtkTextIter at which to add the scalable. - */ -/* TODO: Is there any reason this isn't private? */ -void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter); - -/** * Creates and returns an new GTK+ IM/HTML scalable with a horizontal rule. * * @return A new IM/HTML Scalable object with an image.
--- a/pidgin/gtkutils.c Wed Aug 31 21:26:02 2011 +0000 +++ b/pidgin/gtkutils.c Thu Sep 01 18:26:08 2011 +0000 @@ -1816,21 +1816,27 @@ gpointer object) { GtkWidget *menuitem; + GList *list; if (act == NULL) { return pidgin_separator(menu); } - if (act->children == NULL) { - menuitem = gtk_menu_item_new_with_mnemonic(act->label); - - if (act->callback != NULL) { + list = purple_menu_action_get_children(act); + menuitem = gtk_menu_item_new_with_mnemonic(purple_menu_action_get_label(act)); + + if (list == NULL) { + PurpleCallback callback; + + callback = purple_menu_action_get_callback(act); + + if (callback != NULL) { g_object_set_data(G_OBJECT(menuitem), "purplecallback", - act->callback); + callback); g_object_set_data(G_OBJECT(menuitem), "purplecallbackdata", - act->data); + purple_menu_action_get_data(act)); g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(menu_action_cb), object); @@ -1844,7 +1850,6 @@ GtkWidget *submenu = NULL; GtkAccelGroup *group; - menuitem = gtk_menu_item_new_with_mnemonic(act->label); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); submenu = gtk_menu_new(); @@ -1852,19 +1857,20 @@ group = gtk_menu_get_accel_group(GTK_MENU(menu)); if (group) { - char *path = g_strdup_printf("%s/%s", GTK_MENU_ITEM(menuitem)->accel_path, act->label); + char *path = g_strdup_printf("%s/%s", GTK_MENU_ITEM(menuitem)->accel_path, + purple_menu_action_get_label(act)); gtk_menu_set_accel_path(GTK_MENU(submenu), path); g_free(path); gtk_menu_set_accel_group(GTK_MENU(submenu), group); } - for (l = act->children; l; l = l->next) { + for (l = list; l; l = l->next) { PurpleMenuAction *act = (PurpleMenuAction *)l->data; pidgin_append_menu_action(submenu, act, object); } - g_list_free(act->children); - act->children = NULL; + g_list_free(list); + purple_menu_action_set_children(act, NULL); } purple_menu_action_free(act); return menuitem;
--- a/pidgin/plugins/perl/common/GtkIMHtml.xs Wed Aug 31 21:26:02 2011 +0000 +++ b/pidgin/plugins/perl/common/GtkIMHtml.xs Thu Sep 01 18:26:08 2011 +0000 @@ -77,26 +77,6 @@ Gtk::TextIter end */ -/* This can't work at the moment since I don't have a typemap for Gdk::Pixbuf. - * I thought about using the one from libgtk2-perl but wasn't sure how to go - * about doing that. -Pidgin::IMHtml::Scalable -gtk_imhtml_image_new(img, filename, id) - Gdk::Pixbuf img - const gchar * filename - int id -*/ - -/* This can't work at the moment since I don't have a typemap for Gtk::Widget. - * I thought about using the one from libgtk2-perl but wasn't sure how to go - * about doing that. -void -gtk_imhtml_image_add_to(scale, imhtml, iter) - Pidgin::IMHtml::Scalable scale - Pidgin::IMHtml imhtml - Gtk::TextIter iter -*/ - /* This can't work at the moment since I don't have a typemap for Gtk::Widget. * I thought about using the one from libgtk2-perl but wasn't sure how to go * about doing that. @@ -323,19 +303,6 @@ } XPUSHs(sv_2mortal(newRV_noinc((SV *)lines))); -MODULE = Pidgin::IMHtml PACKAGE = Pidgin::IMHtml::Scalable PREFIX = gtk_imhtml_image_ -PROTOTYPES: ENABLE - -void -gtk_imhtml_image_free(scale) - Pidgin::IMHtml::Scalable scale - -void -gtk_imhtml_image_scale(scale, width, height) - Pidgin::IMHtml::Scalable scale - int width - int height - MODULE = Pidgin::IMHtml PACKAGE = Pidgin::IMHtml::Hr PREFIX = gtk_imhtml_hr_ PROTOTYPES: ENABLE