Mercurial > pidgin.yaz
changeset 22222:433233d3db10
merge of '2e288b76540410af9b0ca21669ffb7e085633d59'
and '5cfc19787cb16932e5e50c4034a7c46699fe1c51'
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Sun, 27 Jan 2008 10:03:26 +0000 |
parents | ef0e82b8bc2e (diff) c0ad8b41ce09 (current diff) |
children | 19ace070f0e5 |
files | libpurple/protocols/myspace/myspace.c |
diffstat | 54 files changed, 1438 insertions(+), 492 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Sun Jan 27 04:26:38 2008 +0000 +++ b/ChangeLog Sun Jan 27 10:03:26 2008 +0000 @@ -35,6 +35,9 @@ * Recently signed on (or off) buddies blink in the buddy list. * New action 'Room List' in the action list can be used to get the list of available chat rooms for an online account. + * The 'Grouping' plugin can be used for alternate grouping in the + buddylist. The current options are 'Group Online/Offline' and 'No + Group'. version 2.3.1 (12/7/2007): http://developer.pidgin.im/query?status=closed&milestone=2.3.1
--- a/ChangeLog.API Sun Jan 27 04:26:38 2008 +0000 +++ b/ChangeLog.API Sun Jan 27 10:03:26 2008 +0000 @@ -30,6 +30,19 @@ * purple_attention_type_get_outgoing_desc * purple_attention_type_get_icon_name * purple_attention_type_get_unlocalized_name + * Add some PurpleBuddyListNode accessor functions: + * purple_blist_node_get_parent + * purple_blist_node_get_first_child + * purple_blist_node_get_sibling_next + * purple_blist_node_get_sibling_prev + * Added last_received to PurpleConnection, the time_t of the + last received packet. + * Added some more accessor functions: + * purple_chat_get_account + * purple_chat_get_components + * purple_connection_get_prpl + * purple_xfer_get_start_time + * purple_xfer_get_end_time Pidgin: Added: @@ -56,6 +69,12 @@ * finch_roomlist_get_ui_ops and finch_roomlist_show_all * finch_request_field_get_widget to get the widget for a request field. + * finch_blist_get_tree to get the GntTree widget representing the + buddy list. + * FinchBlistManager structure to manage the buddylist view, and some + util functions finch_blist_install_manager, + finch_blist_uninstall_manager, finch_blist_manager_find and + finch_blist_manager_add_node. libgnt: * Added gnt_tree_set_row_color to set the color for a row in a tree. @@ -65,6 +84,7 @@ string. * Added gnt_style_get_color to get a color pair from an entry in ~/.gntrc + * Added gnt_tree_get_parent_key to get the key for the parent row. version 2.3.0 (11/24/2007): libpurple:
--- a/autogen.sh Sun Jan 27 04:26:38 2008 +0000 +++ b/autogen.sh Sun Jan 27 10:03:26 2008 +0000 @@ -9,42 +9,42 @@ echo; echo "You must have glib-gettextize installed to compile Pidgin."; echo; - exit; + exit 1; } (intltoolize --version) < /dev/null > /dev/null 2>&1 || { echo; echo "You must have intltool installed to compile Pidgin."; echo; - exit; + exit 1; } (libtoolize --version) < /dev/null > /dev/null 2>&1 || { echo; echo "You must have libtool installed to compile Pidgin."; echo; - exit; + exit 1; } (automake --version) < /dev/null > /dev/null 2>&1 || { echo; echo "You must have automake installed to compile Pidgin."; echo; - exit; + exit 1; } (autoconf --version) < /dev/null > /dev/null 2>&1 || { echo; echo "You must have autoconf installed to compile Pidgin."; echo; - exit; + exit 1; } echo "Generating configuration files for Pidgin, please wait...." echo; echo "Running libtoolize, please ignore non-fatal messages...." -echo n | libtoolize --copy --force || exit; +echo n | libtoolize --copy --force || exit 1; # Add other directories to this list if people continue to experience # brokennesses ... Obviously the real answer is for them to fix it @@ -60,11 +60,11 @@ libtoolize -c -f --automake glib-gettextize --force --copy intltoolize --force --copy -aclocal $ACLOCAL_FLAGS || exit; -autoheader || exit; +aclocal $ACLOCAL_FLAGS || exit 1; +autoheader || exit 1; automake --add-missing --copy; -autoconf || exit; -automake || exit; +autoconf || exit 1; +automake || exit 1; echo; echo "Running ./configure ${CONFIGURE_ARGS} $@"
--- a/finch/finch.h Sun Jan 27 04:26:38 2008 +0000 +++ b/finch/finch.h Sun Jan 27 10:03:26 2008 +0000 @@ -29,3 +29,7 @@ #define FINCH_UI "gnt-purple" #define FINCH_PREFS_ROOT "/finch" + +#define FINCH_GET_DATA(obj) (obj)->ui_data +#define FINCH_SET_DATA(obj, data) (obj)->ui_data = data +
--- a/finch/gntaccount.c Sun Jan 27 04:26:38 2008 +0000 +++ b/finch/gntaccount.c Sun Jan 27 10:03:26 2008 +0000 @@ -686,7 +686,7 @@ } g_signal_connect(G_OBJECT(accounts.tree), "toggled", G_CALLBACK(account_toggled), NULL); - + gnt_tree_set_col_width(GNT_TREE(accounts.tree), 0, 40); gnt_tree_set_col_width(GNT_TREE(accounts.tree), 1, 10); gnt_box_add_widget(GNT_BOX(accounts.window), accounts.tree); @@ -708,11 +708,11 @@ gnt_box_add_widget(GNT_BOX(box), button); gnt_util_set_trigger_widget(GNT_WIDGET(accounts.tree), GNT_KEY_DEL, button); g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(delete_account_cb), accounts.tree); - + gnt_box_add_widget(GNT_BOX(accounts.window), box); g_signal_connect(G_OBJECT(accounts.window), "destroy", G_CALLBACK(reset_accounts_win), NULL); - + gnt_widget_show(accounts.window); } @@ -981,7 +981,7 @@ gnt_box_add_widget(GNT_BOX(uihandle), gnt_hline_new()); - widget = finch_retrieve_user_info(account->gc, remote_user); + widget = finch_retrieve_user_info(purple_account_get_connection(account), remote_user); for (iter = GNT_BOX(widget)->list; iter; iter = iter->next) { if (GNT_IS_BUTTON(iter->data)) { gnt_widget_destroy(iter->data);
--- a/finch/gntblist.c Sun Jan 27 04:26:38 2008 +0000 +++ b/finch/gntblist.c Sun Jan 27 10:03:26 2008 +0000 @@ -81,6 +81,9 @@ /* These are the menuitems that get regenerated */ GntMenuItem *accounts; GntMenuItem *plugins; + GntMenuItem *grouping; + + FinchBlistManager *manager; } FinchBlist; typedef struct @@ -115,7 +118,12 @@ static void add_chat(PurpleChat *chat, FinchBlist *ggblist); static void add_node(PurpleBlistNode *node, FinchBlist *ggblist); static void node_update(PurpleBuddyList *list, PurpleBlistNode *node); +#if 0 +static gboolean is_contact_online(PurpleContact *contact); +static gboolean is_group_online(PurpleGroup *group); +#endif static void draw_tooltip(FinchBlist *ggblist); +static void tooltip_for_buddy(PurpleBuddy *buddy, GString *str, gboolean full); static gboolean remove_typing_cb(gpointer null); static void remove_peripherals(FinchBlist *ggblist); static const char * get_display_name(PurpleBlistNode *node); @@ -125,6 +133,7 @@ static void update_buddy_display(PurpleBuddy *buddy, FinchBlist *ggblist); static void account_signed_on_cb(PurpleConnection *pc, gpointer null); static void finch_request_add_buddy(PurpleAccount *account, const char *username, const char *grp, const char *alias); +static void menu_group_set_cb(GntMenuItem *item, gpointer null); /* Sort functions */ static int blist_node_compare_position(PurpleBlistNode *n1, PurpleBlistNode *n2); @@ -137,14 +146,178 @@ static int color_offline; static int color_idle; +/** + * Buddy List Manager functions. + */ + +static gboolean default_can_add_node(PurpleBlistNode *node) +{ + gboolean offline = purple_prefs_get_bool(PREF_ROOT "/showoffline"); + + if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + PurpleBuddy *buddy = (PurpleBuddy*)node; + FinchBlistNode *fnode = FINCH_GET_DATA(node); + if (!purple_buddy_get_contact(buddy)) + return FALSE; /* When a new buddy is added and show-offline is set */ + if (PURPLE_BUDDY_IS_ONLINE(buddy)) + return TRUE; /* The buddy is online */ + if (!purple_account_is_connected(purple_buddy_get_account(buddy))) + return FALSE; /* The account is disconnected. Do not show */ + if (offline) + return TRUE; /* We want to see offline buddies too */ + if (fnode && fnode->signed_timer) + return TRUE; /* Show if the buddy just signed off */ + if (purple_blist_node_get_bool(node, "show_offline")) + return TRUE; + } else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + PurpleBlistNode *nd; + for (nd = purple_blist_node_get_first_child(node); + nd; nd = purple_blist_node_get_sibling_next(nd)) { + if (default_can_add_node(nd)) + return TRUE; + } + } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { + PurpleChat *chat = (PurpleChat*)node; + if (purple_account_is_connected(purple_chat_get_account(chat))) + return TRUE; /* Show whenever the account is online */ + } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + PurpleBlistNode *nd; + gboolean empty = purple_prefs_get_bool(PREF_ROOT "/emptygroups"); + if (empty) + return TRUE; /* If we want to see empty groups, we can show any group */ + + for (nd = purple_blist_node_get_first_child(node); + nd; nd = purple_blist_node_get_sibling_next(nd)) { + if (default_can_add_node(nd)) + return TRUE; + } + } + + return FALSE; +} + +static gpointer default_find_parent(PurpleBlistNode *node) +{ + gpointer ret = NULL; + switch (purple_blist_node_get_type(node)) { + case PURPLE_BLIST_BUDDY_NODE: + case PURPLE_BLIST_CONTACT_NODE: + case PURPLE_BLIST_CHAT_NODE: + ret = purple_blist_node_get_parent(node); + break; + default: + break; + } + if (ret) + add_node(ret, ggblist); + return ret; +} + +static gboolean default_create_tooltip(gpointer selected_row, GString **body, char **tool_title) +{ + GString *str; + PurpleBlistNode *node = selected_row; + int lastseen = 0; + char *title; + + if (!node || + purple_blist_node_get_type(node) == PURPLE_BLIST_OTHER_NODE) + return FALSE; + + str = g_string_new(""); + + if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + PurpleBuddy *pr = purple_contact_get_priority_buddy((PurpleContact*)node); + gboolean offline = !PURPLE_BUDDY_IS_ONLINE(pr); + gboolean showoffline = purple_prefs_get_bool(PREF_ROOT "/showoffline"); + const char *name = purple_buddy_get_name(pr); + + title = g_strdup(name); + tooltip_for_buddy(pr, str, TRUE); + for (node = purple_blist_node_get_first_child(node); node; node = purple_blist_node_get_sibling_next(node)) { + PurpleBuddy *buddy = (PurpleBuddy*)node; + if (offline) { + int value = purple_blist_node_get_int(node, "last_seen"); + if (value > lastseen) + lastseen = value; + } + if (node == (PurpleBlistNode*)pr) + continue; + if (!purple_account_is_connected(purple_buddy_get_account(buddy))) + continue; + if (!showoffline && !PURPLE_BUDDY_IS_ONLINE(buddy)) + continue; + str = g_string_append(str, "\n----------\n"); + tooltip_for_buddy(buddy, str, FALSE); + } + } else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + PurpleBuddy *buddy = (PurpleBuddy *)node; + tooltip_for_buddy(buddy, str, TRUE); + title = g_strdup(purple_buddy_get_name(buddy)); + if (!PURPLE_BUDDY_IS_ONLINE((PurpleBuddy*)node)) + lastseen = purple_blist_node_get_int(node, "last_seen"); + } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + PurpleGroup *group = (PurpleGroup *)node; + + g_string_append_printf(str, _("Online: %d\nTotal: %d"), + purple_blist_get_group_online_count(group), + purple_blist_get_group_size(group, FALSE)); + + title = g_strdup(purple_group_get_name(group)); + } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { + PurpleChat *chat = (PurpleChat *)node; + PurpleAccount *account = purple_chat_get_account(chat); + + g_string_append_printf(str, _("Account: %s (%s)"), + purple_account_get_username(account), + purple_account_get_protocol_name(account)); + + title = g_strdup(purple_chat_get_name(chat)); + } else { + g_string_free(str, TRUE); + return FALSE; + } + + if (lastseen > 0) { + char *tmp = purple_str_seconds_to_string(time(NULL) - lastseen); + g_string_append_printf(str, _("\nLast Seen: %s ago"), tmp); + g_free(tmp); + } + + if (tool_title) + *tool_title = title; + else + g_free(title); + + if (body) + *body = str; + else + g_string_free(str, TRUE); + + return TRUE; +} + +static FinchBlistManager default_manager = +{ + "default", + N_("Default"), + NULL, + NULL, + default_can_add_node, + default_find_parent, + default_create_tooltip, + {NULL, NULL, NULL, NULL} +}; +static GList *managers; + static FinchBlistNode * create_finch_blist_node(PurpleBlistNode *node, gpointer row) { - FinchBlistNode *fnode = node->ui_data; + FinchBlistNode *fnode = FINCH_GET_DATA(node); if (!fnode) { fnode = g_new0(FinchBlistNode, 1); fnode->signed_timer = 0; - node->ui_data = fnode; + FINCH_SET_DATA(node, fnode); } fnode->row = row; return fnode; @@ -153,13 +326,13 @@ static void reset_blist_node_ui_data(PurpleBlistNode *node) { - FinchBlistNode *fnode = node->ui_data; + FinchBlistNode *fnode = FINCH_GET_DATA(node); if (fnode == NULL) return; if (fnode->signed_timer) purple_timeout_remove(fnode->signed_timer); g_free(fnode); - node->ui_data = NULL; + FINCH_SET_DATA(node, NULL); } static int @@ -192,7 +365,7 @@ get_blist_node_flag(PurpleBlistNode *node) { GntTextFormatFlags flag = 0; - FinchBlistNode *fnode = node->ui_data; + FinchBlistNode *fnode = FINCH_GET_DATA(node); if (ggblist->tagged && g_list_find(ggblist->tagged, node)) flag |= GNT_TEXT_FLAG_BOLD; @@ -201,7 +374,7 @@ flag |= GNT_TEXT_FLAG_BLINK; else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { node = (PurpleBlistNode*)purple_contact_get_priority_buddy((PurpleContact *)node); - fnode = node->ui_data; + fnode = FINCH_GET_DATA(node); if (fnode && fnode->signed_timer) flag |= GNT_TEXT_FLAG_BLINK; } @@ -216,12 +389,16 @@ gnt_tree_set_row_color(GNT_TREE(ggblist->tree), node, get_display_color(node)); } +#if 0 static gboolean is_contact_online(PurpleContact *contact) { PurpleBlistNode *node; - for (node = ((PurpleBlistNode*)contact)->child; node; node = node->next) { - if (PURPLE_BUDDY_IS_ONLINE((PurpleBuddy*)node)) + for (node = purple_blist_node_get_first_child(((PurpleBlistNode*)contact)); node; + node = purple_blist_node_get_sibling_next(node)) { + FinchBlistNode *fnode = FINCH_GET_DATA(node); + if (PURPLE_BUDDY_IS_ONLINE((PurpleBuddy*)node) || + (fnode && fnode->signed_timer)) return TRUE; } return FALSE; @@ -231,7 +408,8 @@ is_group_online(PurpleGroup *group) { PurpleBlistNode *node; - for (node = ((PurpleBlistNode*)group)->child; node; node = node->next) { + for (node = purple_blist_node_get_first_child(((PurpleBlistNode*)group)); node; + node = purple_blist_node_get_sibling_next(node)) { if (PURPLE_BLIST_NODE_IS_CHAT(node) && purple_account_is_connected(((PurpleChat *)node)->account)) return TRUE; @@ -240,14 +418,22 @@ } return FALSE; } +#endif static void new_node(PurpleBlistNode *node) { } -static void add_node(PurpleBlistNode *node, FinchBlist *ggblist) +static void +add_node(PurpleBlistNode *node, FinchBlist *ggblist) { + if (FINCH_GET_DATA(node)) + return; + + if (!ggblist->manager->can_add_node(node)) + return; + if (PURPLE_BLIST_NODE_IS_BUDDY(node)) add_buddy((PurpleBuddy*)node, ggblist); else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) @@ -256,9 +442,15 @@ add_group((PurpleGroup*)node, ggblist); else if (PURPLE_BLIST_NODE_IS_CHAT(node)) add_chat((PurpleChat *)node, ggblist); + draw_tooltip(ggblist); } +void finch_blist_manager_add_node(PurpleBlistNode *node) +{ + add_node(node, ggblist); +} + static void remove_tooltip(FinchBlist *ggblist) { @@ -270,9 +462,10 @@ static void node_remove(PurpleBuddyList *list, PurpleBlistNode *node) { - FinchBlist *ggblist = list->ui_data; - - if (ggblist == NULL || node->ui_data == NULL) + FinchBlist *ggblist = FINCH_GET_DATA(list); + PurpleBlistNode *parent; + + if (ggblist == NULL || FINCH_GET_DATA(node)== NULL) return; gnt_tree_remove(GNT_TREE(ggblist->tree), node); @@ -280,23 +473,16 @@ if (ggblist->tagged) ggblist->tagged = g_list_remove(ggblist->tagged, node); - if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { - PurpleContact *contact = (PurpleContact*)node->parent; - if ((!purple_prefs_get_bool(PREF_ROOT "/showoffline") && !is_contact_online(contact)) || - contact->currentsize < 1) - node_remove(list, (PurpleBlistNode*)contact); + parent = purple_blist_node_get_parent(node); + for (node = purple_blist_node_get_first_child(node); node; + node = purple_blist_node_get_sibling_next(node)) + node_remove(list, node); + + if (parent) { + if (!ggblist->manager->can_add_node(parent)) + node_remove(list, parent); else - node_update(list, (PurpleBlistNode*)contact); - } else if (!PURPLE_BLIST_NODE_IS_GROUP(node)) { - PurpleGroup *group = (PurpleGroup*)node->parent; - if ((group->currentsize < 1 && !purple_prefs_get_bool(PREF_ROOT "/emptygroups")) || - (!purple_prefs_get_bool(PREF_ROOT "/showoffline") && !is_group_online(group))) - node_remove(list, node->parent); - for (node = node->child; node; node = node->next) - reset_blist_node_ui_data(node); - } else { - for (node = node->child; node; node = node->next) - node_remove(list, node); + node_update(list, parent); } draw_tooltip(ggblist); @@ -310,48 +496,39 @@ happens, so maybe someone will figure it out. */ g_return_if_fail(node != NULL); - if (list->ui_data == NULL) + if (FINCH_GET_DATA(list)== NULL) return; /* XXX: this is probably the place to auto-join chats */ if (ggblist->window == NULL) return; - if (node->ui_data != NULL) { + if (FINCH_GET_DATA(node)!= NULL) { gnt_tree_change_text(GNT_TREE(ggblist->tree), node, 0, get_display_name(node)); gnt_tree_sort_row(GNT_TREE(ggblist->tree), node); blist_update_row_flags(node); + if (gnt_tree_get_parent_key(GNT_TREE(ggblist->tree), node) != + ggblist->manager->find_parent(node)) + node_remove(list, node); } if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { PurpleBuddy *buddy = (PurpleBuddy*)node; - if (purple_account_is_connected(buddy->account) && - (PURPLE_BUDDY_IS_ONLINE(buddy) || purple_prefs_get_bool(PREF_ROOT "/showoffline"))) - add_node((PurpleBlistNode*)buddy, list->ui_data); - - node_update(list, node->parent); + add_node((PurpleBlistNode*)buddy, FINCH_GET_DATA(list)); + node_update(list, purple_blist_node_get_parent(node)); } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { - add_chat((PurpleChat *)node, list->ui_data); + add_node(node, FINCH_GET_DATA(list)); } else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { - PurpleContact *contact = (PurpleContact*)node; - if ((!purple_prefs_get_bool(PREF_ROOT "/showoffline") && !is_contact_online(contact)) || - contact->currentsize < 1) - /* nothing */; - else { - if (node->ui_data == NULL) { - /* The core seems to expect the UI to add the buddies. */ - for (node = node->child; node; node = node->next) - add_node(node, list->ui_data); - } + if (FINCH_GET_DATA(node)== NULL) { + /* The core seems to expect the UI to add the buddies. */ + for (node = purple_blist_node_get_first_child(node); node; node = purple_blist_node_get_sibling_next(node)) + add_node(node, FINCH_GET_DATA(list)); } } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { - PurpleGroup *group = (PurpleGroup*)node; - if (!purple_prefs_get_bool(PREF_ROOT "/emptygroups") && - ((!purple_prefs_get_bool(PREF_ROOT "/showoffline") && !is_group_online(group)) || - group->currentsize < 1)) + if (!ggblist->manager->can_add_node(node)) node_remove(list, node); else - add_node(node, list->ui_data); + add_node(node, FINCH_GET_DATA(list)); } } @@ -362,7 +539,10 @@ return; ggblist = g_new0(FinchBlist, 1); - list->ui_data = ggblist; + FINCH_SET_DATA(list, ggblist); + ggblist->manager = finch_blist_manager_find(purple_prefs_get_string(PREF_ROOT "/grouping")); + if (!ggblist->manager) + ggblist->manager = &default_manager; } static void @@ -399,6 +579,8 @@ purple_blist_add_group(grp, NULL); } + /* XXX: Ask if there's already the same buddy in the same group (#4553) */ + buddy = purple_buddy_new(account, username, alias); purple_blist_add_buddy(buddy, NULL, grp, NULL); purple_account_add_buddy(account, buddy); @@ -447,6 +629,7 @@ GHashTable *hash = NULL; PurpleConnection *gc; gboolean autojoin; + PurplePluginProtocolInfo *info; account = purple_request_fields_get_account(allfields, "account"); name = purple_request_fields_get_string(allfields, "name"); @@ -456,15 +639,15 @@ if (!purple_account_is_connected(account) || !name || !*name) return; - + if (!group || !*group) group = _("Chats"); gc = purple_account_get_connection(account); - - if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL) - hash = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, name); - + info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + if (info->chat_info_defaults != NULL) + hash = info->chat_info_defaults(gc, name); + chat = purple_chat_new(account, name, hash); if (chat != NULL) { @@ -476,7 +659,7 @@ purple_blist_alias_chat(chat, alias); purple_blist_node_set_bool((PurpleBlistNode*)chat, "gnt-autojoin", autojoin); if (autojoin) - serv_join_chat(chat->account->gc, chat->components); + serv_join_chat(purple_account_get_connection(purple_chat_get_account(chat)), purple_chat_get_components(chat)); } } @@ -501,7 +684,7 @@ field = purple_request_field_string_new("alias", _("Alias"), alias, FALSE); purple_request_field_group_add_field(group, field); - field = purple_request_field_string_new("group", _("Group"), grp ? grp->name : NULL, FALSE); + field = purple_request_field_string_new("group", _("Group"), grp ? purple_group_get_name(grp) : NULL, FALSE); purple_request_field_group_add_field(group, field); field = purple_request_field_bool_new("autojoin", _("Auto-join"), FALSE); @@ -578,11 +761,14 @@ static void add_group(PurpleGroup *group, FinchBlist *ggblist) { + gpointer parent; PurpleBlistNode *node = (PurpleBlistNode *)group; - if (node->ui_data) + if (FINCH_GET_DATA(node)) return; + parent = ggblist->manager->find_parent((PurpleBlistNode*)group); create_finch_blist_node(node, gnt_tree_add_row_after(GNT_TREE(ggblist->tree), group, - gnt_tree_create_row(GNT_TREE(ggblist->tree), get_display_name(node)), NULL, NULL)); + gnt_tree_create_row(GNT_TREE(ggblist->tree), get_display_name(node)), + parent, NULL)); gnt_tree_set_expanded(GNT_TREE(ggblist->tree), node, !purple_blist_node_get_bool(node, "collapsed")); } @@ -638,7 +824,7 @@ strncpy(status, "~", sizeof(status) - 1); } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) - return ((PurpleGroup*)node)->name; + return purple_group_get_name((PurpleGroup*)node); snprintf(text, sizeof(text) - 1, "%s %s", status, name); @@ -648,41 +834,39 @@ static void add_chat(PurpleChat *chat, FinchBlist *ggblist) { - PurpleGroup *group; + gpointer parent; PurpleBlistNode *node = (PurpleBlistNode *)chat; - if (node->ui_data) + if (FINCH_GET_DATA(node)) return; - if (!purple_account_is_connected(chat->account)) + if (!purple_account_is_connected(purple_chat_get_account(chat))) return; - group = purple_chat_get_group(chat); - add_node((PurpleBlistNode*)group, ggblist); + parent = ggblist->manager->find_parent((PurpleBlistNode*)chat); create_finch_blist_node(node, gnt_tree_add_row_after(GNT_TREE(ggblist->tree), chat, gnt_tree_create_row(GNT_TREE(ggblist->tree), get_display_name(node)), - group, NULL)); + parent, NULL)); } static void add_contact(PurpleContact *contact, FinchBlist *ggblist) { - PurpleGroup *group; + gpointer parent; PurpleBlistNode *node = (PurpleBlistNode*)contact; const char *name; - if (node->ui_data) + if (FINCH_GET_DATA(node)) return; name = get_display_name(node); if (name == NULL) return; - group = (PurpleGroup*)node->parent; - add_node((PurpleBlistNode*)group, ggblist); + parent = ggblist->manager->find_parent((PurpleBlistNode*)contact); create_finch_blist_node(node, gnt_tree_add_row_after(GNT_TREE(ggblist->tree), contact, gnt_tree_create_row(GNT_TREE(ggblist->tree), name), - group, NULL)); + parent, NULL)); gnt_tree_set_expanded(GNT_TREE(ggblist->tree), contact, FALSE); } @@ -690,23 +874,19 @@ static void add_buddy(PurpleBuddy *buddy, FinchBlist *ggblist) { - PurpleContact *contact; + gpointer parent; PurpleBlistNode *node = (PurpleBlistNode *)buddy; - - if (node->ui_data) + PurpleContact *contact; + + if (FINCH_GET_DATA(node)) return; - if (!purple_account_is_connected(buddy->account)) - return; - - contact = (PurpleContact*)node->parent; - if (!contact) /* When a new buddy is added and show-offline is set */ - return; - add_node((PurpleBlistNode*)contact, ggblist); + contact = purple_buddy_get_contact(buddy); + parent = ggblist->manager->find_parent((PurpleBlistNode*)buddy); create_finch_blist_node(node, gnt_tree_add_row_after(GNT_TREE(ggblist->tree), buddy, gnt_tree_create_row(GNT_TREE(ggblist->tree), get_display_name(node)), - contact, NULL)); + parent, NULL)); blist_update_row_flags((PurpleBlistNode*)buddy); if (buddy == purple_contact_get_priority_buddy(contact)) @@ -756,7 +936,7 @@ purple_buddy_get_account(buddy), purple_buddy_get_name(buddy)); } else { - FinchConv *ggconv = conv->ui_data; + FinchConv *ggconv = FINCH_GET_DATA(conv); gnt_window_present(ggconv->window); } finch_conversation_set_active(conv); @@ -764,7 +944,7 @@ else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { PurpleChat *chat = (PurpleChat*)node; - serv_join_chat(chat->account->gc, chat->components); + serv_join_chat(purple_account_get_connection(purple_chat_get_account(chat)), purple_chat_get_components(chat)); } } @@ -809,7 +989,7 @@ append_proto_menu(GntMenu *menu, PurpleConnection *gc, PurpleBlistNode *node) { GList *list; - PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); if(!prpl_info || !prpl_info->blist_node_menu) return; @@ -851,7 +1031,7 @@ else val = g_strdup(purple_request_field_string_get_value(field)); - g_hash_table_replace(chat->components, g_strdup(id), val); /* val should not be free'd */ + g_hash_table_replace(purple_chat_get_components(chat), g_strdup(id), val); /* val should not be free'd */ } } } @@ -864,22 +1044,24 @@ PurpleRequestField *field; GList *parts, *iter; struct proto_chat_entry *pce; + PurpleConnection *gc; purple_request_fields_add_group(fields, group); - parts = PURPLE_PLUGIN_PROTOCOL_INFO(chat->account->gc->prpl)->chat_info(chat->account->gc); + gc = purple_account_get_connection(purple_chat_get_account(chat)); + parts = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))->chat_info(gc); for (iter = parts; iter; iter = iter->next) { pce = iter->data; if (pce->is_int) { int val; - const char *str = g_hash_table_lookup(chat->components, pce->identifier); + const char *str = g_hash_table_lookup(purple_chat_get_components(chat), pce->identifier); if (!str || sscanf(str, "%d", &val) != 1) val = pce->min; field = purple_request_field_int_new(pce->identifier, pce->label, val); } else { field = purple_request_field_string_new(pce->identifier, pce->label, - g_hash_table_lookup(chat->components, pce->identifier), FALSE); + g_hash_table_lookup(purple_chat_get_components(chat), pce->identifier), FALSE); } purple_request_field_group_add_field(group, field); @@ -920,7 +1102,7 @@ static void finch_add_buddy(PurpleBlistNode *selected, PurpleGroup *grp) { - purple_blist_request_add_buddy(NULL, NULL, grp ? grp->name : NULL, NULL); + purple_blist_request_add_buddy(NULL, NULL, grp ? purple_group_get_name(grp) : NULL, NULL); } static void @@ -961,13 +1143,13 @@ static void finch_blist_get_buddy_info_cb(PurpleBlistNode *selected, PurpleBuddy *buddy) { - finch_retrieve_user_info(buddy->account->gc, purple_buddy_get_name(buddy)); + finch_retrieve_user_info(purple_account_get_connection(purple_buddy_get_account(buddy)), purple_buddy_get_name(buddy)); } static void finch_blist_menu_send_file_cb(PurpleBlistNode *selected, PurpleBuddy *buddy) { - serv_send_file(buddy->account->gc, buddy->name, NULL); + serv_send_file(purple_account_get_connection(purple_buddy_get_account(buddy)), purple_buddy_get_name(buddy), NULL); } static void @@ -978,7 +1160,7 @@ b = purple_contact_get_priority_buddy((PurpleContact *)node); else b = (PurpleBuddy *)node; - finch_pounce_editor_show(b->account, b->name, NULL); + finch_pounce_editor_show(purple_buddy_get_account(b), purple_buddy_get_name(b), NULL); } @@ -986,8 +1168,9 @@ create_buddy_menu(GntMenu *menu, PurpleBuddy *buddy) { PurplePluginProtocolInfo *prpl_info; - - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(buddy->account->gc->prpl); + PurpleConnection *gc = purple_account_get_connection(purple_buddy_get_account(buddy)); + + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); if (prpl_info && prpl_info->get_info) { add_custom_action(menu, _("Get Info"), @@ -1000,7 +1183,7 @@ if (prpl_info && prpl_info->send_file) { if (!prpl_info->can_receive_file || - prpl_info->can_receive_file(buddy->account->gc, buddy->name)) + prpl_info->can_receive_file(gc, purple_buddy_get_name(buddy))) add_custom_action(menu, _("Send File"), PURPLE_CALLBACK(finch_blist_menu_send_file_cb), buddy); } @@ -1035,11 +1218,12 @@ PurpleGroup *group; cnode = (PurpleBlistNode *)contact; - group = (PurpleGroup*)cnode->parent; - for (bnode = cnode->child; bnode; bnode = bnode->next) { + group = (PurpleGroup*)purple_blist_node_get_parent(cnode); + for (bnode = purple_blist_node_get_first_child(cnode); bnode; bnode = purple_blist_node_get_sibling_next(bnode)) { PurpleBuddy *buddy = (PurpleBuddy*)bnode; - if (purple_account_is_connected(buddy->account)) - purple_account_remove_buddy(buddy->account, buddy, group); + PurpleAccount *account = purple_buddy_get_account(buddy); + if (purple_account_is_connected(account)) + purple_account_remove_buddy(account, buddy, group); } purple_blist_remove_contact(contact); } @@ -1082,7 +1266,7 @@ else if (PURPLE_BLIST_NODE_IS_CHAT(node)) name = purple_chat_get_name((PurpleChat*)node); else if (PURPLE_BLIST_NODE_IS_GROUP(node)) - name = ((PurpleGroup*)node)->name; + name = purple_group_get_name((PurpleGroup*)node); else g_return_if_reached(); @@ -1104,32 +1288,34 @@ { PurpleBlistNode *cnode, *bnode; - cnode = ((PurpleBlistNode*)group)->child; + cnode = purple_blist_node_get_first_child(((PurpleBlistNode*)group)); while (cnode) { if (PURPLE_BLIST_NODE_IS_CONTACT(cnode)) { - bnode = cnode->child; - cnode = cnode->next; + bnode = purple_blist_node_get_first_child(cnode); + cnode = purple_blist_node_get_sibling_next(cnode); while (bnode) { PurpleBuddy *buddy; if (PURPLE_BLIST_NODE_IS_BUDDY(bnode)) { + PurpleAccount *account; buddy = (PurpleBuddy*)bnode; - bnode = bnode->next; - if (purple_account_is_connected(buddy->account)) { - purple_account_remove_buddy(buddy->account, buddy, group); + bnode = purple_blist_node_get_sibling_next(bnode); + account = purple_buddy_get_account(buddy); + if (purple_account_is_connected(account)) { + purple_account_remove_buddy(account, buddy, group); purple_blist_remove_buddy(buddy); } } else { - bnode = bnode->next; + bnode = purple_blist_node_get_sibling_next(bnode); } } } else if (PURPLE_BLIST_NODE_IS_CHAT(cnode)) { PurpleChat *chat = (PurpleChat *)cnode; - cnode = cnode->next; - if (purple_account_is_connected(chat->account)) + cnode = purple_blist_node_get_sibling_next(cnode); + if (purple_account_is_connected(purple_chat_get_account(chat))) purple_blist_remove_chat(chat); } else { - cnode = cnode->next; + cnode = purple_blist_node_get_sibling_next(cnode); } } @@ -1172,7 +1358,7 @@ } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { name = purple_chat_get_name((PurpleChat*)node); } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { - name = ((PurpleGroup*)node)->name; + name = purple_group_get_name((PurpleGroup*)node); sec = _("Removing this group will also remove all the buddies in the group"); } else @@ -1216,18 +1402,19 @@ PurpleGroup *tg = NULL; PurpleContact *tc = NULL; - if (target == NULL) + if (target == NULL || + purple_blist_node_get_type(target) == PURPLE_BLIST_OTHER_NODE) return; if (PURPLE_BLIST_NODE_IS_GROUP(target)) tg = (PurpleGroup*)target; else if (PURPLE_BLIST_NODE_IS_BUDDY(target)) { - tc = (PurpleContact*)target->parent; - tg = (PurpleGroup*)target->parent->parent; + tc = (PurpleContact*)purple_blist_node_get_parent(target); + tg = (PurpleGroup*)purple_blist_node_get_parent((PurpleBlistNode*)tc); } else { if (PURPLE_BLIST_NODE_IS_CONTACT(target)) tc = (PurpleContact*)target; - tg = (PurpleGroup*)target->parent; + tg = (PurpleGroup*)purple_blist_node_get_parent(target); } if (ggblist->tagged) { @@ -1300,6 +1487,8 @@ tree = GNT_TREE(ggblist->tree); node = gnt_tree_get_selection_data(tree); + if (node && purple_blist_node_get_type(node) == PURPLE_BLIST_OTHER_NODE) + return; if (ggblist->tooltip) remove_tooltip(ggblist); @@ -1328,7 +1517,7 @@ } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { PurpleGroup *group = (PurpleGroup *)node; create_group_menu(GNT_MENU(context), group); - title = g_strdup(group->name); + title = g_strdup(purple_group_get_name(group)); } append_extended_menu(GNT_MENU(context), node); @@ -1393,7 +1582,7 @@ purple_account_get_protocol_name(account)); purple_notify_user_info_add_pair(user_info, _("Account"), tmp); g_free(tmp); - + prpl = purple_find_prpl(purple_account_get_protocol_id(account)); prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); if (prpl_info && prpl_info->tooltip_text) { @@ -1442,16 +1631,15 @@ { PurpleBlistNode *node; int x, y, top, width, w, h; - GString *str; + GString *str = NULL; GntTree *tree; GntWidget *widget, *box, *tv; char *title = NULL; - int lastseen = 0; widget = ggblist->tree; tree = GNT_TREE(widget); - if (!gnt_widget_has_focus(ggblist->tree) || + if (!gnt_widget_has_focus(ggblist->tree) || (ggblist->context && !GNT_WIDGET_IS_FLAG_SET(ggblist->context, GNT_WIDGET_INVISIBLE))) return FALSE; @@ -1466,65 +1654,8 @@ if (!node) return FALSE; - str = g_string_new(""); - - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { - PurpleBuddy *pr = purple_contact_get_priority_buddy((PurpleContact*)node); - gboolean offline = !PURPLE_BUDDY_IS_ONLINE(pr); - gboolean showoffline = purple_prefs_get_bool(PREF_ROOT "/showoffline"); - const char *name = purple_buddy_get_name(pr); - - title = g_strdup(name); - tooltip_for_buddy(pr, str, TRUE); - for (node = node->child; node; node = node->next) { - PurpleBuddy *buddy = (PurpleBuddy*)node; - if (offline) { - int value = purple_blist_node_get_int(node, "last_seen"); - if (value > lastseen) - lastseen = value; - } - if (node == (PurpleBlistNode*)pr) - continue; - if (!purple_account_is_connected(buddy->account)) - continue; - if (!showoffline && !PURPLE_BUDDY_IS_ONLINE(buddy)) - continue; - str = g_string_append(str, "\n----------\n"); - tooltip_for_buddy(buddy, str, FALSE); - } - } else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { - PurpleBuddy *buddy = (PurpleBuddy *)node; - tooltip_for_buddy(buddy, str, TRUE); - title = g_strdup(purple_buddy_get_name(buddy)); - if (!PURPLE_BUDDY_IS_ONLINE((PurpleBuddy*)node)) - lastseen = purple_blist_node_get_int(node, "last_seen"); - } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { - PurpleGroup *group = (PurpleGroup *)node; - - g_string_append_printf(str, _("Online: %d\nTotal: %d"), - purple_blist_get_group_online_count(group), - purple_blist_get_group_size(group, FALSE)); - - title = g_strdup(group->name); - } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { - PurpleChat *chat = (PurpleChat *)node; - PurpleAccount *account = chat->account; - - g_string_append_printf(str, _("Account: %s (%s)"), - purple_account_get_username(account), - purple_account_get_protocol_name(account)); - - title = g_strdup(purple_chat_get_name(chat)); - } else { - g_string_free(str, TRUE); + if (!ggblist->manager->create_tooltip(node, &str, &title)) return FALSE; - } - - if (lastseen > 0) { - char *tmp = purple_str_seconds_to_string(time(NULL) - lastseen); - g_string_append_printf(str, _("\nLast Seen: %s ago"), tmp); - g_free(tmp); - } gnt_widget_get_position(widget, &x, &y); gnt_widget_get_size(widget, &width, NULL); @@ -1684,7 +1815,7 @@ { PurpleBlistNode *node; purple_signals_disconnect_by_handle(finch_blist_get_handle()); - purple_get_blist()->ui_data = NULL; + FINCH_SET_DATA(purple_get_blist(), NULL); node = purple_blist_get_root(); while (node) { @@ -1707,6 +1838,9 @@ PurpleBlistNode *node; PurpleBuddyList *list; + if (ggblist->manager->init) + ggblist->manager->init(); + if (strcmp(purple_prefs_get_string(PREF_ROOT "/sort_type"), "text") == 0) { gnt_tree_set_compare_func(GNT_TREE(ggblist->tree), (GCompareFunc)blist_node_compare_text); @@ -1794,11 +1928,33 @@ redraw_blist(const char *name, PurplePrefType type, gconstpointer val, gpointer data) { PurpleBlistNode *node, *sel; - if (ggblist == NULL || ggblist->window == NULL) + FinchBlistManager *manager; + + if (ggblist == NULL) + return; + + manager = finch_blist_manager_find(purple_prefs_get_string(PREF_ROOT "/grouping")); + if (manager == NULL) + manager = &default_manager; + if (ggblist->manager != manager) { + if (ggblist->manager->uninit) + ggblist->manager->uninit(); + + ggblist->manager = manager; + if (manager->can_add_node == NULL) + manager->can_add_node = default_can_add_node; + if (manager->find_parent == NULL) + manager->find_parent = default_find_parent; + if (manager->create_tooltip == NULL) + manager->create_tooltip = default_create_tooltip; + } + + if (ggblist->window == NULL) return; sel = gnt_tree_get_selection_data(GNT_TREE(ggblist->tree)); gnt_tree_remove_all(GNT_TREE(ggblist->tree)); + node = purple_blist_get_root(); for (; node; node = purple_blist_node_next(node, TRUE)) reset_blist_node_ui_data(node); @@ -1833,6 +1989,7 @@ purple_prefs_add_bool(PREF_ROOT "/showoffline", FALSE); purple_prefs_add_bool(PREF_ROOT "/emptygroups", FALSE); purple_prefs_add_string(PREF_ROOT "/sort_type", "text"); + purple_prefs_add_string(PREF_ROOT "/grouping", "default"); purple_prefs_connect_callback(finch_blist_get_handle(), PREF_ROOT "/emptygroups", redraw_blist, NULL); @@ -1840,9 +1997,14 @@ PREF_ROOT "/showoffline", redraw_blist, NULL); purple_prefs_connect_callback(finch_blist_get_handle(), PREF_ROOT "/sort_type", redraw_blist, NULL); + purple_prefs_connect_callback(finch_blist_get_handle(), + PREF_ROOT "/grouping", redraw_blist, NULL); purple_signal_connect(purple_connections_get_handle(), "signed-on", purple_blist_get_handle(), G_CALLBACK(account_signed_on_cb), NULL); + + finch_blist_install_manager(&default_manager); + return; } @@ -2003,7 +2165,7 @@ static int blist_node_compare_position(PurpleBlistNode *n1, PurpleBlistNode *n2) { - while ((n1 = n1->prev) != NULL) + while ((n1 = purple_blist_node_get_sibling_prev(n1)) != NULL) if (n1 == n2) return 1; return -1; @@ -2016,10 +2178,10 @@ char *us1, *us2; int ret; - if (n1->type != n2->type) + if (purple_blist_node_get_type(n1) != purple_blist_node_get_type(n2)) return blist_node_compare_position(n1, n2); - switch (n1->type) + switch (purple_blist_node_get_type(n1)) { case PURPLE_BLIST_CHAT_NODE: s1 = purple_chat_get_name((PurpleChat*)n1); @@ -2051,10 +2213,10 @@ { int ret; - if (n1->type != n2->type) + if (purple_blist_node_get_type(n1) != purple_blist_node_get_type(n2)) return blist_node_compare_position(n1, n2); - switch (n1->type) { + switch (purple_blist_node_get_type(n1)) { case PURPLE_BLIST_CONTACT_NODE: n1 = (PurpleBlistNode*)purple_contact_get_priority_buddy((PurpleContact*)n1); n2 = (PurpleBlistNode*)purple_contact_get_priority_buddy((PurpleContact*)n2); @@ -2082,9 +2244,10 @@ int log = 0; PurpleBlistNode *node; - for (node = c->child; node; node = node->next) { + for (node = purple_blist_node_get_first_child(c); node; node = purple_blist_node_get_sibling_next(node)) { PurpleBuddy *b = (PurpleBuddy*)node; - log += purple_log_get_total_size(PURPLE_LOG_IM, b->name, b->account); + log += purple_log_get_total_size(PURPLE_LOG_IM, purple_buddy_get_name(b), + purple_buddy_get_account(b)); } return log; @@ -2096,15 +2259,15 @@ int ret; PurpleBuddy *b1, *b2; - if (n1->type != n2->type) + if (purple_blist_node_get_type(n1) != purple_blist_node_get_type(n2)) return blist_node_compare_position(n1, n2); - switch (n1->type) { + switch (purple_blist_node_get_type(n1)) { case PURPLE_BLIST_BUDDY_NODE: b1 = (PurpleBuddy*)n1; b2 = (PurpleBuddy*)n2; - ret = purple_log_get_total_size(PURPLE_LOG_IM, b2->name, b2->account) - - purple_log_get_total_size(PURPLE_LOG_IM, b1->name, b1->account); + ret = purple_log_get_total_size(PURPLE_LOG_IM, purple_buddy_get_name(b2), purple_buddy_get_account(b2)) - + purple_log_get_total_size(PURPLE_LOG_IM, purple_buddy_get_name(b1), purple_buddy_get_account(b1)); if (ret != 0) return ret; break; @@ -2165,19 +2328,17 @@ buddy_recent_signed_on_off(gpointer data) { PurpleBlistNode *node = data; - FinchBlistNode *fnode = node->ui_data; - PurpleBuddy *buddy = (PurpleBuddy*)node; + FinchBlistNode *fnode = FINCH_GET_DATA(node); purple_timeout_remove(fnode->signed_timer); fnode->signed_timer = 0; - if (!purple_account_is_connected(buddy->account) || - (!PURPLE_BUDDY_IS_ONLINE(buddy) && !purple_prefs_get_bool(PREF_ROOT "/showoffline"))) { + if (!ggblist->manager->can_add_node(node)) { node_remove(purple_get_blist(), node); } else { update_node_display(node, ggblist); - if (node->parent && PURPLE_BLIST_NODE_IS_CONTACT(node->parent)) - update_node_display(node->parent, ggblist); + if (purple_blist_node_get_parent(node) && PURPLE_BLIST_NODE_IS_CONTACT(purple_blist_node_get_parent(node))) + update_node_display(purple_blist_node_get_parent(node), ggblist); } return FALSE; @@ -2187,7 +2348,7 @@ buddy_signed_on_off_cb(gpointer data) { PurpleBlistNode *node = data; - FinchBlistNode *fnode = node->ui_data; + FinchBlistNode *fnode = FINCH_GET_DATA(node); if (!ggblist || !fnode) return FALSE; @@ -2195,8 +2356,8 @@ purple_timeout_remove(fnode->signed_timer); fnode->signed_timer = purple_timeout_add_seconds(6, (GSourceFunc)buddy_recent_signed_on_off, data); update_node_display(node, ggblist); - if (node->parent && PURPLE_BLIST_NODE_IS_CONTACT(node->parent)) - update_node_display(node->parent, ggblist); + if (purple_blist_node_get_parent(node) && PURPLE_BLIST_NODE_IS_CONTACT(purple_blist_node_get_parent(node))) + update_node_display(purple_blist_node_get_parent(node), ggblist); return FALSE; } @@ -2260,10 +2421,10 @@ PurpleAccount *account = iter->data; PurpleConnection *gc = purple_account_get_connection(account); PurplePlugin *prpl; - + if (!gc || !PURPLE_CONNECTION_IS_CONNECTED(gc)) continue; - prpl = gc->prpl; + prpl = purple_connection_get_prpl(gc); if (PURPLE_PLUGIN_HAS_ACTIONS(prpl)) { item = gnt_menuitem_new(purple_account_get_username(account)); @@ -2273,6 +2434,30 @@ } } +static void +reconstruct_grouping_menu(void) +{ + GList *iter; + GntWidget *subsub; + + if (!ggblist || !ggblist->grouping) + return; + + subsub = gnt_menu_new(GNT_MENU_POPUP); + gnt_menuitem_set_submenu(ggblist->grouping, GNT_MENU(subsub)); + + for (iter = managers; iter; iter = iter->next) { + char menuid[128]; + FinchBlistManager *manager = iter->data; + GntMenuItem *item = gnt_menuitem_new(_(manager->name)); + snprintf(menuid, sizeof(menuid), "grouping-%s", manager->id); + gnt_menuitem_set_id(GNT_MENU_ITEM(item), menuid); + gnt_menu_add_item(GNT_MENU(subsub), item); + g_object_set_data_full(G_OBJECT(item), "grouping-id", g_strdup(manager->id), g_free); + gnt_menuitem_set_callback(item, menu_group_set_cb, NULL); + } +} + static gboolean auto_join_chats(gpointer data) { @@ -2284,9 +2469,9 @@ node = purple_blist_node_next(node, FALSE)) { if (PURPLE_BLIST_NODE_IS_CHAT(node)) { PurpleChat *chat = (PurpleChat*)node; - if (chat->account == account && + if (purple_chat_get_account(chat) == account && purple_blist_node_get_bool(node, "gnt-autojoin")) - serv_join_chat(purple_account_get_connection(chat->account), chat->components); + serv_join_chat(purple_account_get_connection(account), purple_chat_get_components(chat)); } } return FALSE; @@ -2372,14 +2557,15 @@ if (!purple_account_is_connected(account)) return; - gc = purple_account_get_connection(account); + gc = purple_account_get_connection(account); purple_conversation_new(PURPLE_CONV_TYPE_CHAT, account, name); chat = purple_blist_find_chat(account, name); if (chat == NULL) { - if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL) - hash = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, name); + PurplePluginProtocolInfo *info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + if (info->chat_info_defaults != NULL) + hash = info->chat_info_defaults(gc, name); } else { - hash = chat->components; + hash = purple_chat_get_components(chat); } serv_join_chat(gc, hash); if (chat == NULL && hash != NULL) @@ -2439,6 +2625,13 @@ } static void +menu_group_set_cb(GntMenuItem *item, gpointer null) +{ + const char *id = g_object_get_data(G_OBJECT(item), "grouping-id"); + purple_prefs_set_string(PREF_ROOT "/grouping", id); +} + +static void create_menu(void) { GntWidget *menu, *sub, *subsub; @@ -2479,7 +2672,7 @@ purple_prefs_get_bool(PREF_ROOT "/emptygroups")); gnt_menu_add_item(GNT_MENU(subsub), item); gnt_menuitem_set_callback(GNT_MENU_ITEM(item), toggle_pref_cb, PREF_ROOT "/emptygroups"); - + item = gnt_menuitem_check_new(_("Offline buddies")); gnt_menuitem_set_id(GNT_MENU_ITEM(item), "show-offline-buddies"); gnt_menuitem_check_set_checked(GNT_MENU_ITEM_CHECK(item), @@ -2513,21 +2706,25 @@ subsub = gnt_menu_new(GNT_MENU_POPUP); gnt_menuitem_set_submenu(item, GNT_MENU(subsub)); - item = gnt_menuitem_new("Buddy"); + item = gnt_menuitem_new(_("Buddy")); gnt_menuitem_set_id(GNT_MENU_ITEM(item), "add-buddy"); gnt_menu_add_item(GNT_MENU(subsub), item); gnt_menuitem_set_callback(item, menu_add_buddy_cb, NULL); - item = gnt_menuitem_new("Chat"); + item = gnt_menuitem_new(_("Chat")); gnt_menuitem_set_id(GNT_MENU_ITEM(item), "add-chat"); gnt_menu_add_item(GNT_MENU(subsub), item); gnt_menuitem_set_callback(item, menu_add_chat_cb, NULL); - item = gnt_menuitem_new("Group"); + item = gnt_menuitem_new(_("Group")); gnt_menuitem_set_id(GNT_MENU_ITEM(item), "add-group"); gnt_menu_add_item(GNT_MENU(subsub), item); gnt_menuitem_set_callback(item, menu_add_group_cb, NULL); + ggblist->grouping = item = gnt_menuitem_new(_("Grouping")); + gnt_menu_add_item(GNT_MENU(sub), item); + reconstruct_grouping_menu(); + reconstruct_accounts_menu(); gnt_menu_add_item(GNT_MENU(menu), ggblist->accounts); @@ -2679,3 +2876,43 @@ { gnt_widget_set_size(ggblist->window, width, height); } + +void finch_blist_install_manager(const FinchBlistManager *manager) +{ + if (!g_list_find(managers, manager)) { + managers = g_list_append(managers, (gpointer)manager); + reconstruct_grouping_menu(); + if (strcmp(manager->id, purple_prefs_get_string(PREF_ROOT "/grouping")) == 0) + purple_prefs_trigger_callback(PREF_ROOT "/grouping"); + } +} + +void finch_blist_uninstall_manager(const FinchBlistManager *manager) +{ + if (g_list_find(managers, manager)) { + managers = g_list_remove(managers, manager); + reconstruct_grouping_menu(); + if (strcmp(manager->id, purple_prefs_get_string(PREF_ROOT "/grouping")) == 0) + purple_prefs_trigger_callback(PREF_ROOT "/grouping"); + } +} + +FinchBlistManager * finch_blist_manager_find(const char *id) +{ + GList *iter = managers; + if (!id) + return NULL; + + for (; iter; iter = iter->next) { + FinchBlistManager *m = iter->data; + if (strcmp(id, m->id) == 0) + return m; + } + return NULL; +} + +GntTree * finch_blist_get_tree(void) +{ + return ggblist ? GNT_TREE(ggblist->tree) : NULL; +} +
--- a/finch/gntblist.h Sun Jan 27 04:26:38 2008 +0000 +++ b/finch/gntblist.h Sun Jan 27 10:03:26 2008 +0000 @@ -27,12 +27,25 @@ #define _GNT_BLIST_H #include "blist.h" +#include "gnttree.h" /********************************************************************** * @name GNT BuddyList API **********************************************************************/ /*@{*/ +typedef struct +{ + const char *id; /**< An identifier for the manager. */ + const char *name; /**< Displayable name for the manager. */ + gboolean (*init)(void); /**< Called right before it's being used. */ + gboolean (*uninit)(void); /**< Called right after it's not being used any more. */ + gboolean (*can_add_node)(PurpleBlistNode *node); /**< Whether a node should be added to the view. */ + gpointer (*find_parent)(PurpleBlistNode *node); /**< Find the parent row for a node. */ + gboolean (*create_tooltip)(gpointer selected_row, GString **body, char **title); /**< Create tooltip for a selected row. */ + gpointer reserved[4]; +} FinchBlistManager; + /** * Get the ui-functions. * @@ -103,6 +116,47 @@ */ gpointer finch_retrieve_user_info(PurpleConnection *conn, const char *name); +/** + * Get the tree list of the buddy list. + * @return The GntTree widget. + * @since 2.4.0 + */ +GntTree * finch_blist_get_tree(void); + +/** + * Add an alternate buddy list manager. + * + * @param manager The alternate buddylist manager. + * @since 2.4.0 + */ +void finch_blist_install_manager(const FinchBlistManager *manager); + +/** + * Remove an alternate buddy list manager. + * + * @param manager The buddy list manager to remove. + * @since 2.4.0 + */ +void finch_blist_uninstall_manager(const FinchBlistManager *manager); + +/** + * Find a buddy list manager. + * + * @param id The identifier for the desired buddy list manager. + * + * @return The manager with the requested identifier, if available. @c NULL otherwise. + * @since 2.4.0 + */ +FinchBlistManager * finch_blist_manager_find(const char *id); + +/** + * Request the active buddy list manager to add a node. + * + * @param node The node to add + * @since 2.4.0 + */ +void finch_blist_manager_add_node(PurpleBlistNode *node); + /*@}*/ #endif
--- a/finch/gntcertmgr.c Sun Jan 27 04:26:38 2008 +0000 +++ b/finch/gntcertmgr.c Sun Jan 27 10:03:26 2008 +0000 @@ -25,14 +25,13 @@ * */ -#include "internal.h" +#include "finch.h" #include "certificate.h" #include "debug.h" #include "notify.h" #include "request.h" -#include "finch.h" #include "gntcertmgr.h" #include "gntbutton.h"
--- a/finch/gntconn.c Sun Jan 27 04:26:38 2008 +0000 +++ b/finch/gntconn.c Sun Jan 27 10:03:26 2008 +0000 @@ -101,13 +101,14 @@ } static void -finch_connection_report_disconnect(PurpleConnection *gc, const char *text) +finch_connection_report_disconnect(PurpleConnection *gc, PurpleConnectionError reason, + const char *text) { FinchAutoRecon *info; PurpleAccount *account = purple_connection_get_account(gc); GList *list; - if (!gc->wants_to_die) { + if (!purple_connection_error_is_fatal(reason)) { info = g_hash_table_lookup(hash, account); if (info == NULL) { @@ -148,7 +149,7 @@ while (list) { PurpleConversation *conv = list->data; list = list->next; - if (conv->account != account || + if (purple_conversation_get_account(conv) != account || purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv))) continue; purple_conversation_set_data(conv, "want-to-rejoin", GINT_TO_POINTER(TRUE)); @@ -179,10 +180,10 @@ NULL, /* connected */ NULL, /* disconnected */ NULL, /* notice */ - finch_connection_report_disconnect, + NULL, NULL, /* network_connected */ NULL, /* network_disconnected */ - NULL, + finch_connection_report_disconnect, NULL, NULL, NULL
--- a/finch/gntconv.c Sun Jan 27 04:26:38 2008 +0000 +++ b/finch/gntconv.c Sun Jan 27 10:03:26 2008 +0000 @@ -71,6 +71,20 @@ static int color_message_action; static int color_timestamp; +static PurpleBuddy * +find_buddy_for_conversation(PurpleConversation *conv) +{ + return purple_find_buddy(purple_conversation_get_account(conv), + purple_conversation_get_name(conv)); +} + +static PurpleChat * +find_chat_for_conversation(PurpleConversation *conv) +{ + return purple_blist_find_chat(purple_conversation_get_account(conv), + purple_conversation_get_name(conv)); +} + static PurpleBlistNode * get_conversation_blist_node(PurpleConversation *conv) { @@ -78,11 +92,11 @@ switch (purple_conversation_get_type(conv)) { case PURPLE_CONV_TYPE_IM: - node = (PurpleBlistNode*)purple_find_buddy(conv->account, conv->name); - node = node ? node->parent : NULL; + node = (PurpleBlistNode*)find_buddy_for_conversation(conv); + node = node ? purple_blist_node_get_parent(node) : NULL; break; case PURPLE_CONV_TYPE_CHAT: - node = (PurpleBlistNode*)purple_blist_find_chat(conv->account, conv->name); + node = (PurpleBlistNode*)find_chat_for_conversation(conv); break; default: break; @@ -168,7 +182,7 @@ } g_free(error); } - else if (!purple_account_is_connected(ggconv->active_conv->account)) + else if (!purple_account_is_connected(purple_conversation_get_account(ggconv->active_conv))) { purple_conversation_write(ggconv->active_conv, "", _("Message was not sent, because you are not signed on."), PURPLE_MESSAGE_ERROR | PURPLE_MESSAGE_NO_LOG, time(NULL)); @@ -236,11 +250,12 @@ if (!buddy) return NULL; - for (node = ((PurpleBlistNode*)buddy)->parent->child; node; node = node->next) { + for (node = purple_blist_node_get_first_child(purple_blist_node_get_parent((PurpleBlistNode*)buddy)); + node; node = purple_blist_node_get_sibling_next(node)) { if (node == (PurpleBlistNode*)buddy) continue; if ((ret = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - ((PurpleBuddy*)node)->name, ((PurpleBuddy*)node)->account)) != NULL) + purple_buddy_get_name((PurpleBuddy*)node), purple_buddy_get_account((PurpleBuddy*)node))) != NULL) break; } return ret; @@ -267,7 +282,7 @@ return; im = PURPLE_CONV_IM(conv); - ggc = conv->ui_data; + ggc = FINCH_GET_DATA(conv); if (purple_conv_im_get_typing_state(im) == PURPLE_TYPING) { int scroll; @@ -303,10 +318,10 @@ static void buddy_signed_on_off(PurpleBuddy *buddy, gpointer null) { - PurpleConversation *conv = find_conv_with_contact(buddy->account, buddy->name); + PurpleConversation *conv = find_conv_with_contact(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy)); if (conv == NULL) return; - generate_send_to_menu(conv->ui_data); + generate_send_to_menu(FINCH_GET_DATA(conv)); } static void @@ -315,9 +330,10 @@ GList *list = purple_get_ims(); while (list) { PurpleConversation *conv = list->data; - PurpleConversation *cc = find_conv_with_contact(conv->account, conv->name); + PurpleConversation *cc = find_conv_with_contact( + purple_conversation_get_account(conv), purple_conversation_get_name(conv)); if (cc) - generate_send_to_menu(cc->ui_data); + generate_send_to_menu(FINCH_GET_DATA(cc)); list = list->next; } @@ -331,16 +347,17 @@ GHashTable *comps = NULL; list = list->next; - if (conv->account != gc->account || + if (purple_conversation_get_account(conv) != purple_connection_get_account(gc) || !purple_conversation_get_data(conv, "want-to-rejoin")) continue; - chat = purple_blist_find_chat(conv->account, conv->name); + chat = find_chat_for_conversation(conv); if (chat == NULL) { - if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL) - comps = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, conv->name); + PurplePluginProtocolInfo *info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + if (info->chat_info_defaults != NULL) + comps = info->chat_info_defaults(gc, purple_conversation_get_name(conv)); } else { - comps = chat->components; + comps = purple_chat_get_components(chat); } serv_join_chat(gc, comps); if (chat == NULL && comps != NULL) @@ -413,15 +430,11 @@ purple_conversation_write(conv, NULL, _("Logging started. Future messages in this conversation will be logged."), - conv->logs ? (PURPLE_MESSAGE_SYSTEM) : - (PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG), - time(NULL)); + PURPLE_MESSAGE_SYSTEM, time(NULL)); } else { purple_conversation_write(conv, NULL, _("Logging stopped. Future messages in this conversation will not be logged."), - conv->logs ? (PURPLE_MESSAGE_SYSTEM) : - (PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG), - time(NULL)); + PURPLE_MESSAGE_SYSTEM, time(NULL)); /* Disable the logging second, so that the above message can be logged. */ purple_conversation_set_logging(conv, FALSE); @@ -462,7 +475,8 @@ GSList *buds; GList *list = NULL; - buds = purple_find_buddies(ggc->active_conv->account, ggc->active_conv->name); + buds = purple_find_buddies(purple_conversation_get_account(ggc->active_conv), + purple_conversation_get_name(ggc->active_conv)); if (!buds) return; @@ -476,7 +490,8 @@ for (; buds; buds = g_slist_delete_link(buds, buds)) { PurpleBlistNode *node = (PurpleBlistNode *)purple_buddy_get_contact((PurpleBuddy *)buds->data); - for (node = node->child; node != NULL; node = node->next) { + for (node = purple_blist_node_get_first_child(node); node != NULL; + node = purple_blist_node_get_sibling_next(node)) { PurpleBuddy *buddy = (PurpleBuddy *)node; PurpleAccount *account = purple_buddy_get_account(buddy); if (purple_account_is_connected(account)) { @@ -529,7 +544,9 @@ if (purple_conversation_get_type(ggc->active_conv) == PURPLE_CONV_TYPE_IM) { PurpleAccount *account = purple_conversation_get_account(ggc->active_conv); - PurplePluginProtocolInfo *pinfo = account->gc ? PURPLE_PLUGIN_PROTOCOL_INFO(account->gc->prpl) : NULL; + PurpleConnection *gc = purple_account_get_connection(account); + PurplePluginProtocolInfo *pinfo = + gc ? PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)) : NULL; if (pinfo && pinfo->get_info) { item = gnt_menuitem_new(_("Get Info")); @@ -543,7 +560,7 @@ if (pinfo && pinfo->send_file && (!pinfo->can_receive_file || - pinfo->can_receive_file(account->gc, purple_conversation_get_name(ggc->active_conv)))) { + pinfo->can_receive_file(gc, purple_conversation_get_name(ggc->active_conv)))) { item = gnt_menuitem_new(_("Send File")); gnt_menu_add_item(GNT_MENU(sub), item); gnt_menuitem_set_callback(item, send_file_cb, ggc); @@ -593,7 +610,7 @@ static void finch_create_conversation(PurpleConversation *conv) { - FinchConv *ggc = conv->ui_data; + FinchConv *ggc = FINCH_GET_DATA(conv); char *title; PurpleConversationType type; PurpleConversation *cc; @@ -603,9 +620,10 @@ if (ggc) return; - cc = find_conv_with_contact(conv->account, conv->name); - if (cc && cc->ui_data) - ggc = cc->ui_data; + account = purple_conversation_get_account(conv); + cc = find_conv_with_contact(account, purple_conversation_get_name(conv)); + if (cc && FINCH_GET_DATA(cc)) + ggc = FINCH_GET_DATA(cc); else ggc = g_new0(FinchConv, 1); @@ -617,14 +635,13 @@ ggc->list = g_list_prepend(ggc->list, conv); ggc->active_conv = conv; - conv->ui_data = ggc; + FINCH_SET_DATA(conv, ggc); - if (cc && cc->ui_data) { + if (cc && FINCH_GET_DATA(cc)) { finch_conversation_set_active(conv); return; } - account = purple_conversation_get_account(conv); type = purple_conversation_get_type(conv); title = get_conversation_title(conv, account); @@ -633,7 +650,7 @@ gnt_box_set_toplevel(GNT_BOX(ggc->window), TRUE); gnt_box_set_pad(GNT_BOX(ggc->window), 0); - switch(conv->type){ + switch (purple_conversation_get_type(conv)) { case PURPLE_CONV_TYPE_UNKNOWN: gnt_widget_set_name(ggc->window, "conversation-window-unknown" ); break; @@ -721,7 +738,7 @@ finch_destroy_conversation(PurpleConversation *conv) { /* do stuff here */ - FinchConv *ggc = conv->ui_data; + FinchConv *ggc = FINCH_GET_DATA(conv); ggc->list = g_list_remove(ggc->list, conv); if (ggc->list && conv == ggc->active_conv) ggc->active_conv = ggc->list->data; @@ -738,7 +755,7 @@ finch_write_common(PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime) { - FinchConv *ggconv = conv->ui_data; + FinchConv *ggconv = FINCH_GET_DATA(conv); char *strip, *newline; GntTextFormatFlags fl = 0; int pos; @@ -891,7 +908,7 @@ static void finch_chat_add_users(PurpleConversation *conv, GList *users, gboolean new_arrivals) { - FinchConv *ggc = conv->ui_data; + FinchConv *ggc = FINCH_GET_DATA(conv); GntEntry *entry = GNT_ENTRY(ggc->entry); if (!new_arrivals) @@ -930,7 +947,7 @@ finch_chat_rename_user(PurpleConversation *conv, const char *old, const char *new_n, const char *new_a) { /* Update the name for string completion */ - FinchConv *ggc = conv->ui_data; + FinchConv *ggc = FINCH_GET_DATA(conv); GntEntry *entry = GNT_ENTRY(ggc->entry); GntTree *tree = GNT_TREE(ggc->u.chat->userlist); PurpleConvChatBuddy *cb = purple_conv_chat_cb_find(PURPLE_CONV_CHAT(conv), new_n); @@ -948,7 +965,7 @@ finch_chat_remove_users(PurpleConversation *conv, GList *list) { /* Remove the name from string completion */ - FinchConv *ggc = conv->ui_data; + FinchConv *ggc = FINCH_GET_DATA(conv); GntEntry *entry = GNT_ENTRY(ggc->entry); for (; list; list = list->next) { GntTree *tree = GNT_TREE(ggc->u.chat->userlist); @@ -961,7 +978,7 @@ finch_chat_update_user(PurpleConversation *conv, const char *user) { PurpleConvChatBuddy *cb = purple_conv_chat_cb_find(PURPLE_CONV_CHAT(conv), user); - FinchConv *ggc = conv->ui_data; + FinchConv *ggc = FINCH_GET_DATA(conv); gnt_tree_change_text(GNT_TREE(ggc->u.chat->userlist), (gpointer)user, 0, chat_flag_text(cb->flags)); } @@ -1070,7 +1087,7 @@ clear_command_cb(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data) { - FinchConv *ggconv = conv->ui_data; + FinchConv *ggconv = FINCH_GET_DATA(conv); gnt_text_view_clear(GNT_TEXT_VIEW(ggconv->tv)); purple_conversation_clear_message_history(conv); return PURPLE_CMD_STATUS_OK; @@ -1127,7 +1144,7 @@ static PurpleCmdRet users_command_cb(PurpleConversation *conv, const char *cmd, char **args, char **error, gpointer data) { - FinchConv *fc = conv->ui_data; + FinchConv *fc = FINCH_GET_DATA(conv); FinchConvChat *ch; if (!fc) return PURPLE_CMD_STATUS_FAILED; @@ -1231,7 +1248,7 @@ void finch_conversation_set_active(PurpleConversation *conv) { - FinchConv *ggconv = conv->ui_data; + FinchConv *ggconv = FINCH_GET_DATA(conv); PurpleAccount *account; char *title; @@ -1247,7 +1264,7 @@ void finch_conversation_set_info_widget(PurpleConversation *conv, GntWidget *widget) { - FinchConv *fc = conv->ui_data; + FinchConv *fc = FINCH_GET_DATA(conv); int height, width; gnt_box_remove_all(GNT_BOX(fc->info));
--- a/finch/gntft.c Sun Jan 27 04:26:38 2008 +0000 +++ b/finch/gntft.c Sun Jan 27 10:03:26 2008 +0000 @@ -23,13 +23,14 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ +#include "finch.h" + #include <gnt.h> #include <gntbox.h> #include <gntbutton.h> #include <gntcheckbox.h> #include <gntlabel.h> #include <gnttree.h> -#include "internal.h" #include "debug.h" #include "notify.h" @@ -41,7 +42,7 @@ #include "prefs.h" #define FINCHXFER(xfer) \ - (PurpleGntXferUiData *)(xfer)->ui_data + (PurpleGntXferUiData *)FINCH_GET_DATA(xfer) typedef struct { @@ -168,9 +169,15 @@ stop_button_cb(GntButton *button) { PurpleXfer *selected_xfer = gnt_tree_get_selection_data(GNT_TREE(xfer_dialog->tree)); - if (selected_xfer && selected_xfer->status != PURPLE_XFER_STATUS_CANCEL_LOCAL && - selected_xfer->status != PURPLE_XFER_STATUS_CANCEL_REMOTE && - selected_xfer->status != PURPLE_XFER_STATUS_DONE) + PurpleXferStatusType status; + + if (!selected_xfer) + return; + + status = purple_xfer_get_status(selected_xfer); + if (status != PURPLE_XFER_STATUS_CANCEL_LOCAL && + status != PURPLE_XFER_STATUS_CANCEL_REMOTE && + status != PURPLE_XFER_STATUS_DONE) purple_xfer_cancel_local(selected_xfer); } @@ -397,14 +404,12 @@ time_t elapsed, now; char *kbsec; - if (xfer->end_time != 0) - now = xfer->end_time; - else + if ((now = purple_xfer_get_end_time(xfer)) == 0) now = time(NULL); kb_sent = purple_xfer_get_bytes_sent(xfer) / 1024.0; kb_rem = purple_xfer_get_bytes_remaining(xfer) / 1024.0; - elapsed = (xfer->start_time > 0 ? now - xfer->start_time : 0); + elapsed = (purple_xfer_get_start_time(xfer) > 0 ? now - purple_xfer_get_start_time(xfer) : 0); kbps = (elapsed > 0 ? (kb_sent / elapsed) : 0); g_return_if_fail(xfer_dialog != NULL); @@ -463,7 +468,7 @@ /* This is where we're setting xfer->ui_data for the first time. */ data = g_new0(PurpleGntXferUiData, 1); - xfer->ui_data = data; + FINCH_SET_DATA(xfer, data); } static void @@ -475,7 +480,7 @@ if (data) { g_free(data->name); g_free(data); - xfer->ui_data = NULL; + FINCH_SET_DATA(xfer, NULL); } }
--- a/finch/gntidle.c Sun Jan 27 04:26:38 2008 +0000 +++ b/finch/gntidle.c Sun Jan 27 10:03:26 2008 +0000 @@ -21,7 +21,7 @@ * */ -#include "internal.h" +#include "finch.h" #include "gntidle.h" #include "gntwm.h"
--- a/finch/gntpounce.c Sun Jan 27 04:26:38 2008 +0000 +++ b/finch/gntpounce.c Sun Jan 27 10:03:26 2008 +0000 @@ -35,7 +35,6 @@ #include <gnttree.h> #include <gntutils.h> -#include "internal.h" #include "finch.h" #include "account.h" @@ -808,39 +807,42 @@ if (purple_pounce_action_is_enabled(pounce, "popup-notify")) { - char *tmp; + char *tmp = NULL; const char *name_shown; const char *reason; + struct { + PurplePounceEvent event; + const char *format; + } messages[] = { + {PURPLE_POUNCE_TYPING, _("%s has started typing to you (%s)")}, + {PURPLE_POUNCE_TYPED, _("%s has paused while typing to you (%s)")}, + {PURPLE_POUNCE_SIGNON, _("%s has signed on (%s)")}, + {PURPLE_POUNCE_IDLE_RETURN, _("%s has returned from being idle (%s)")}, + {PURPLE_POUNCE_AWAY_RETURN, _("%s has returned from being away (%s)")}, + {PURPLE_POUNCE_TYPING_STOPPED, _("%s has stopped typing to you (%s)")}, + {PURPLE_POUNCE_SIGNOFF, _("%s has signed off (%s)")}, + {PURPLE_POUNCE_IDLE, _("%s has become idle (%s)")}, + {PURPLE_POUNCE_AWAY, _("%s has gone away. (%s)")}, + {PURPLE_POUNCE_MESSAGE_RECEIVED, _("%s has sent you a message. (%s)")}, + {0, NULL} + }; + int i; reason = purple_pounce_action_get_attribute(pounce, "popup-notify", - "reason"); + "reason"); /* * Here we place the protocol name in the pounce dialog to lessen * confusion about what protocol a pounce is for. */ - tmp = g_strdup_printf( - (events & PURPLE_POUNCE_TYPING) ? - _("%s has started typing to you (%s)") : - (events & PURPLE_POUNCE_TYPED) ? - _("%s has paused while typing to you (%s)") : - (events & PURPLE_POUNCE_SIGNON) ? - _("%s has signed on (%s)") : - (events & PURPLE_POUNCE_IDLE_RETURN) ? - _("%s has returned from being idle (%s)") : - (events & PURPLE_POUNCE_AWAY_RETURN) ? - _("%s has returned from being away (%s)") : - (events & PURPLE_POUNCE_TYPING_STOPPED) ? - _("%s has stopped typing to you (%s)") : - (events & PURPLE_POUNCE_SIGNOFF) ? - _("%s has signed off (%s)") : - (events & PURPLE_POUNCE_IDLE) ? - _("%s has become idle (%s)") : - (events & PURPLE_POUNCE_AWAY) ? - _("%s has gone away. (%s)") : - (events & PURPLE_POUNCE_MESSAGE_RECEIVED) ? - _("%s has sent you a message. (%s)") : - _("Unknown pounce event. Please report this!"), - alias, purple_account_get_protocol_name(account)); + for (i = 0; messages[i].format != NULL; i++) { + if (messages[i].event & events) { + tmp = g_strdup_printf(messages[i].format, alias, + purple_account_get_protocol_name(account)); + break; + } + } + if (tmp == NULL) + tmp = g_strdup(_("Unknown pounce event. Please report this!")); /* * Ok here is where I change the second argument, title, from @@ -880,7 +882,7 @@ purple_conversation_write(conv, NULL, message, PURPLE_MESSAGE_SEND, time(NULL)); - serv_send_im(account->gc, (char *)pouncee, (char *)message, 0); + serv_send_im(purple_account_get_connection(account), (char *)pouncee, (char *)message, 0); } }
--- a/finch/gntrequest.c Sun Jan 27 04:26:38 2008 +0000 +++ b/finch/gntrequest.c Sun Jan 27 10:03:26 2008 +0000 @@ -308,26 +308,26 @@ PurpleRequestFieldType type = purple_request_field_get_type(field); if (type == PURPLE_REQUEST_FIELD_BOOLEAN) { - GntWidget *check = field->ui_data; + GntWidget *check = FINCH_GET_DATA(field); gboolean value = gnt_check_box_get_checked(GNT_CHECK_BOX(check)); purple_request_field_bool_set_value(field, value); } else if (type == PURPLE_REQUEST_FIELD_STRING) { - GntWidget *entry = field->ui_data; + GntWidget *entry = FINCH_GET_DATA(field); const char *text = gnt_entry_get_text(GNT_ENTRY(entry)); purple_request_field_string_set_value(field, (text && *text) ? text : NULL); } else if (type == PURPLE_REQUEST_FIELD_INTEGER) { - GntWidget *entry = field->ui_data; + GntWidget *entry = FINCH_GET_DATA(field); const char *text = gnt_entry_get_text(GNT_ENTRY(entry)); int value = (text && *text) ? atoi(text) : 0; purple_request_field_int_set_value(field, value); } else if (type == PURPLE_REQUEST_FIELD_CHOICE) { - GntWidget *combo = field->ui_data; + GntWidget *combo = FINCH_GET_DATA(field); int id; id = GPOINTER_TO_INT(gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo))); purple_request_field_choice_set_value(field, id); @@ -338,7 +338,7 @@ if (purple_request_field_list_get_multi_select(field)) { GList *iter; - GntWidget *tree = field->ui_data; + GntWidget *tree = FINCH_GET_DATA(field); iter = purple_request_field_list_get_items(field); for (; iter; iter = iter->next) @@ -351,7 +351,7 @@ } else { - GntWidget *combo = field->ui_data; + GntWidget *combo = FINCH_GET_DATA(field); gpointer data = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo)); list = g_list_append(list, data); } @@ -361,7 +361,7 @@ } else if (type == PURPLE_REQUEST_FIELD_ACCOUNT) { - GntWidget *combo = field->ui_data; + GntWidget *combo = FINCH_GET_DATA(field); PurpleAccount *acc = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo)); purple_request_field_account_set_value(field, acc); } @@ -424,9 +424,10 @@ *screenname = entry; } else if (hint && !strcmp(hint, "group")) { PurpleBlistNode *node; - for (node = purple_blist_get_root(); node; node = node->next) { + for (node = purple_blist_get_root(); node; + node = purple_blist_node_get_sibling_next(node)) { if (PURPLE_BLIST_NODE_IS_GROUP(node)) - gnt_entry_add_suggest(GNT_ENTRY(entry), ((PurpleGroup *)node)->name); + gnt_entry_add_suggest(GNT_ENTRY(entry), purple_group_get_name((PurpleGroup *)node)); } } return entry; @@ -593,35 +594,35 @@ if (type == PURPLE_REQUEST_FIELD_BOOLEAN) { - field->ui_data = create_boolean_field(field); + FINCH_SET_DATA(field, create_boolean_field(field)); } else if (type == PURPLE_REQUEST_FIELD_STRING) { - field->ui_data = create_string_field(field, &screenname); + FINCH_SET_DATA(field, create_string_field(field, &screenname)); } else if (type == PURPLE_REQUEST_FIELD_INTEGER) { - field->ui_data = create_integer_field(field); + FINCH_SET_DATA(field, create_integer_field(field)); } else if (type == PURPLE_REQUEST_FIELD_CHOICE) { - field->ui_data = create_choice_field(field); + FINCH_SET_DATA(field, create_choice_field(field)); } else if (type == PURPLE_REQUEST_FIELD_LIST) { - field->ui_data = create_list_field(field); + FINCH_SET_DATA(field, create_list_field(field)); } else if (type == PURPLE_REQUEST_FIELD_ACCOUNT) { - accountlist = field->ui_data = create_account_field(field); + accountlist = FINCH_SET_DATA(field, create_account_field(field)); } else { - field->ui_data = gnt_label_new_with_format(_("Not implemented yet."), - GNT_TEXT_FLAG_BOLD); + FINCH_SET_DATA(field, gnt_label_new_with_format(_("Not implemented yet."), + GNT_TEXT_FLAG_BOLD)); } gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID); - gnt_box_add_widget(GNT_BOX(hbox), GNT_WIDGET(field->ui_data)); + gnt_box_add_widget(GNT_BOX(hbox), GNT_WIDGET(FINCH_GET_DATA(field))); } if (grlist->next) gnt_box_add_widget(GNT_BOX(box), gnt_hline_new());
--- a/finch/gntroomlist.c Sun Jan 27 04:26:38 2008 +0000 +++ b/finch/gntroomlist.c Sun Jan 27 10:03:26 2008 +0000 @@ -24,7 +24,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#include"internal.h" +#include "finch.h" #include "gntrequest.h" #include "gntroomlist.h" @@ -116,7 +116,7 @@ if (gc == NULL || room == NULL) return; - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); if(prpl_info != NULL && prpl_info->roomlist_room_serialize) name = prpl_info->roomlist_room_serialize(room); @@ -238,7 +238,7 @@ PurplePluginProtocolInfo *prpl_info = NULL; PurpleConnection *gc = list->data; - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); if (prpl_info->roomlist_get_list != NULL) { PurpleAccount *account = purple_connection_get_account(gc); char *text = g_strdup_printf("%s (%s)", @@ -341,7 +341,7 @@ static void fl_create(PurpleRoomlist *list) { - list->ui_data = &froomlist; + FINCH_SET_DATA(list, &froomlist); setup_roomlist(NULL); update_roomlist(list); }
--- a/finch/gntsound.c Sun Jan 27 04:26:38 2008 +0000 +++ b/finch/gntsound.c Sun Jan 27 10:03:26 2008 +0000 @@ -23,7 +23,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#include "internal.h" #include "finch.h" #ifdef _WIN32 @@ -142,13 +141,15 @@ char *nick = NULL; char *name = NULL; gboolean ret = FALSE; + PurpleAccount *account; + chat = purple_conversation_get_chat_data(conv); - if (chat == NULL) return ret; - nick = g_strdup(purple_normalize(conv->account, chat->nick)); - name = g_strdup(purple_normalize(conv->account, aname)); + account = purple_conversation_get_account(conv); + nick = g_strdup(purple_normalize(account, chat->nick)); + name = g_strdup(purple_normalize(account, aname)); if (g_utf8_collate(nick, name) == 0) ret = TRUE;
--- a/finch/gntui.c Sun Jan 27 04:26:38 2008 +0000 +++ b/finch/gntui.c Sun Jan 27 10:03:26 2008 +0000 @@ -19,7 +19,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#include "internal.h" +#include "finch.h" #include "gntui.h"
--- a/finch/libgnt/gnttree.c Sun Jan 27 04:26:38 2008 +0000 +++ b/finch/libgnt/gnttree.c Sun Jan 27 10:03:26 2008 +0000 @@ -39,6 +39,7 @@ { PROP_0, PROP_COLUMNS, + PROP_EXPANDER, }; enum @@ -59,6 +60,7 @@ GCompareFunc compare; int lastvisible; + int expander_level; }; #define TAB_SIZE 3 @@ -338,7 +340,7 @@ row->isselected ? 'X' : ' '); fl = 4; } - else if (row->parent == NULL && row->child) + else if (find_depth(row) < tree->priv->expander_level && row->child) { if (row->collapsed) { @@ -951,6 +953,11 @@ case PROP_COLUMNS: _gnt_tree_init_internals(tree, g_value_get_int(value)); break; + case PROP_EXPANDER: + if (tree->priv->expander_level == g_value_get_int(value)) + break; + tree->priv->expander_level = g_value_get_int(value); + g_object_notify(obj, "expander-level"); default: break; } @@ -965,6 +972,9 @@ case PROP_COLUMNS: g_value_set_int(value, tree->ncol); break; + case PROP_EXPANDER: + g_value_set_int(value, tree->priv->expander_level); + break; default: break; } @@ -995,6 +1005,14 @@ G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB ) ); + g_object_class_install_property(gclass, + PROP_EXPANDER, + g_param_spec_int("expander-level", "Expander level", + "Number of levels to show expander in the tree.", + 0, G_MAXINT, 1, + G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB + ) + ); signals[SIG_SELECTION_CHANGED] = g_signal_new("selection-changed", @@ -1618,6 +1636,7 @@ { GntWidget *widget = g_object_new(GNT_TYPE_TREE, "columns", col, + "expander-level", 1, NULL); return widget; @@ -1841,3 +1860,9 @@ tree->priv->search_func = func; } +gpointer gnt_tree_get_parent_key(GntTree *tree, gpointer key) +{ + GntTreeRow *row = g_hash_table_lookup(tree->hash, key); + return (row && row->parent) ? row->parent->key : NULL; +} +
--- a/finch/libgnt/gnttree.h Sun Jan 27 04:26:38 2008 +0000 +++ b/finch/libgnt/gnttree.h Sun Jan 27 10:03:26 2008 +0000 @@ -575,6 +575,17 @@ void gnt_tree_set_search_function(GntTree *tree, gboolean (*func)(GntTree *tree, gpointer key, const char *search, const char *current)); +/** + * Get the parent key for a row. + * + * @param tree The tree + * @param key The key for the row. + * + * @return The key of the parent row. + * @since 2.4.0 + */ +gpointer gnt_tree_get_parent_key(GntTree *tree, gpointer key); + G_END_DECLS #endif /* GNT_TREE_H */
--- a/finch/plugins/Makefile.am Sun Jan 27 04:26:38 2008 +0000 +++ b/finch/plugins/Makefile.am Sun Jan 27 10:03:26 2008 +0000 @@ -1,7 +1,8 @@ gntclipboard_la_LDFLAGS = -module -avoid-version gntgf_la_LDFLAGS = -module -avoid-version gnthistory_la_LDFLAGS = -module -avoid-version -gntlastlog_la_LDFLAGS = -module -avoid-version +gntlastlog_la_LDFLAGS = -module -avoid-version +grouping_la_LDFLAGS = -module -avoid-version if PLUGINS @@ -9,7 +10,8 @@ gntclipboard.la \ gntgf.la \ gnthistory.la \ - gntlastlog.la + gntlastlog.la \ + grouping.la plugindir = $(libdir)/finch @@ -17,6 +19,7 @@ gntgf_la_SOURCES = gntgf.c gnthistory_la_SOURCES = gnthistory.c gntlastlog_la_SOURCES = lastlog.c +grouping_la_SOURCES = grouping.c gntclipboard_la_CFLAGS = $(X11_CFLAGS) gntgf_la_CFLAGS = $(X11_CFLAGS) @@ -25,6 +28,7 @@ gntgf_la_LIBADD = $(GLIB_LIBS) $(X11_LIBS) $(top_builddir)/finch/libgnt/libgnt.la gnthistory_la_LIBADD = $(GLIB_LIBS) gntlastlog_la_LIBADD = $(GLIB_LIBS) +grouping_la_LIBADD = $(GLIB_LIBS) $(top_builddir)/finch/libgnt/libgnt.la endif # PLUGINS
--- a/finch/plugins/gnthistory.c Sun Jan 27 04:26:38 2008 +0000 +++ b/finch/plugins/gnthistory.c Sun Jan 27 10:03:26 2008 +0000 @@ -51,8 +51,7 @@ PurpleMessageFlags mflag; convtype = purple_conversation_get_type(c); - if (convtype == PURPLE_CONV_TYPE_IM) - { + if (convtype == PURPLE_CONV_TYPE_IM) { GSList *buddies; GSList *cur; @@ -62,17 +61,17 @@ return; /* Find buddies for this conversation. */ - buddies = purple_find_buddies(account, name); + buddies = purple_find_buddies(account, name); /* If we found at least one buddy, save the first buddy's alias. */ if (buddies != NULL) alias = purple_buddy_get_contact_alias((PurpleBuddy *)buddies->data); - for (cur = buddies; cur != NULL; cur = cur->next) - { - PurpleBlistNode *node = cur->data; - if ((node != NULL) && ((node->prev != NULL) || (node->next != NULL))) - { + for (cur = buddies; cur != NULL; cur = cur->next) { + PurpleBlistNode *node = cur->data; + if ((node != NULL) && + ((purple_blist_node_get_sibling_prev(node) != NULL) || + (purple_blist_node_get_sibling_next(node) != NULL))) { PurpleBlistNode *node2; alias = purple_buddy_get_contact_alias((PurpleBuddy *)node); @@ -80,26 +79,24 @@ /* We've found a buddy that matches this conversation. It's part of a * PurpleContact with more than one PurpleBuddy. Loop through the PurpleBuddies * in the contact and get all the logs. */ - for (node2 = node->parent->child ; node2 != NULL ; node2 = node2->next) - { + for (node2 = purple_blist_node_get_first_child(purple_blist_node_get_parent(node)); + node2 != NULL ; node2 = purple_blist_node_get_sibling_next(node2)) { logs = g_list_concat( - purple_log_get_logs(PURPLE_LOG_IM, - purple_buddy_get_name((PurpleBuddy *)node2), - purple_buddy_get_account((PurpleBuddy *)node2)), - logs); + purple_log_get_logs(PURPLE_LOG_IM, + purple_buddy_get_name((PurpleBuddy *)node2), + purple_buddy_get_account((PurpleBuddy *)node2)), + logs); } break; - } - } - g_slist_free(buddies); + } + } + g_slist_free(buddies); if (logs == NULL) logs = purple_log_get_logs(PURPLE_LOG_IM, name, account); else logs = g_list_sort(logs, purple_log_compare); - } - else if (convtype == PURPLE_CONV_TYPE_CHAT) - { + } else if (convtype == PURPLE_CONV_TYPE_CHAT) { /* If we're not logging, don't show anything. * Otherwise, we might show a very old log. */ if (!purple_prefs_get_bool("/purple/logging/log_chats")) @@ -115,7 +112,7 @@ history = purple_log_read((PurpleLog*)logs->data, &flags); header = g_strdup_printf(_("<b>Conversation with %s on %s:</b><br>"), alias, - purple_date_format_full(localtime(&((PurpleLog *)logs->data)->time))); + purple_date_format_full(localtime(&((PurpleLog *)logs->data)->time))); purple_conversation_write(c, "", header, mflag, time(NULL)); g_free(header);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/finch/plugins/grouping.c Sun Jan 27 10:03:26 2008 +0000 @@ -0,0 +1,278 @@ +/** + * @file grouping.c Provides different grouping options. + * + * Copyright (C) 2008 Sadrul Habib Chowdhury <sadrul@users.sourceforge.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define PURPLE_PLUGIN + +#include "internal.h" +#include "purple.h" + +#include "gntblist.h" +#include "gntplugin.h" + +#include "gnttree.h" + +/** + * Online/Offline + */ +static PurpleBlistNode online = {.type = PURPLE_BLIST_OTHER_NODE}, + offline = {.type = PURPLE_BLIST_OTHER_NODE}; + +static gboolean on_offline_init() +{ + GntTree *tree = finch_blist_get_tree(); + + gnt_tree_add_row_after(tree, &online, + gnt_tree_create_row(tree, _("Online")), NULL, NULL); + gnt_tree_add_row_after(tree, &offline, + gnt_tree_create_row(tree, _("Offline")), NULL, &online); + + return TRUE; +} + +static gboolean on_offline_can_add_node(PurpleBlistNode *node) +{ + switch (purple_blist_node_get_type(node)) { + case PURPLE_BLIST_CONTACT_NODE: + { + PurpleContact *contact = (PurpleContact*)node; + if (contact->currentsize > 0) + return TRUE; + return FALSE; + } + break; + case PURPLE_BLIST_BUDDY_NODE: + { + PurpleBuddy *buddy = (PurpleBuddy*)node; + if (PURPLE_BUDDY_IS_ONLINE(buddy)) + return TRUE; + if (purple_prefs_get_bool("/finch/blist/showoffline") && + purple_account_is_connected(purple_buddy_get_account(buddy))) + return TRUE; + return FALSE; + } + break; + case PURPLE_BLIST_CHAT_NODE: + { + PurpleChat *chat = (PurpleChat*)node; + return purple_account_is_connected(purple_chat_get_account(chat)); + } + break; + default: + return FALSE; + } +} + +static gpointer on_offline_find_parent(PurpleBlistNode *node) +{ + gpointer ret = NULL; + + switch (purple_blist_node_get_type(node)) { + case PURPLE_BLIST_CONTACT_NODE: + node = (PurpleBlistNode*)purple_contact_get_priority_buddy((PurpleContact*)node); + ret = PURPLE_BUDDY_IS_ONLINE((PurpleBuddy*)node) ? &online : &offline; + break; + case PURPLE_BLIST_BUDDY_NODE: + ret = purple_blist_node_get_parent(node); + finch_blist_manager_add_node(ret); + break; + case PURPLE_BLIST_CHAT_NODE: + ret = &online; + break; + default: + break; + } + return ret; +} + +static gboolean on_offline_create_tooltip(gpointer selected_row, GString **body, char **tool_title) +{ + static FinchBlistManager *def = NULL; + PurpleBlistNode *node = selected_row; + + if (def == NULL) + def = finch_blist_manager_find("default"); + + if (purple_blist_node_get_type(node) == PURPLE_BLIST_OTHER_NODE) { + /* There should be some easy way of getting the total online count, + * or total number of chats. Doing a loop here will probably be pretty + * expensive. */ + if (body) + *body = g_string_new(node == &online ? _("Online Buddies") : _("Offline Buddies")); + return TRUE; + } else { + return def ? def->create_tooltip(selected_row, body, tool_title) : FALSE; + } +} + +static FinchBlistManager on_offline = +{ + "on-offline", + N_("Online/Offline"), + on_offline_init, + NULL, + on_offline_can_add_node, + on_offline_find_parent, + on_offline_create_tooltip, + {NULL, NULL, NULL, NULL} +}; + +/** + * Meebo-like Grouping. + */ +static PurpleBlistNode meebo = {.type = PURPLE_BLIST_OTHER_NODE}; +static gboolean meebo_init() +{ + GntTree *tree = finch_blist_get_tree(); + if (!g_list_find(gnt_tree_get_rows(tree), &meebo)) { + gnt_tree_add_row_last(tree, &meebo, + gnt_tree_create_row(tree, _("Offline")), NULL); + } + return TRUE; +} + +static gpointer meebo_find_parent(PurpleBlistNode *node) +{ + static FinchBlistManager *def = NULL; + if (def == NULL) + def = finch_blist_manager_find("default"); + + if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + PurpleBuddy *buddy = purple_contact_get_priority_buddy((PurpleContact*)node); + if (buddy && !PURPLE_BUDDY_IS_ONLINE(buddy)) { + return &meebo; + } + } + return def->find_parent(node); +} + +static FinchBlistManager meebo_group = +{ + "meebo", + N_("Meebo"), + meebo_init, + NULL, + NULL, + meebo_find_parent, + NULL, + {NULL, NULL, NULL, NULL} +}; + +/** + * No Grouping. + */ +static gboolean no_group_init() +{ + GntTree *tree = finch_blist_get_tree(); + g_object_set(G_OBJECT(tree), "expander-level", 0, NULL); + return TRUE; +} + +static gboolean no_group_uninit() +{ + GntTree *tree = finch_blist_get_tree(); + g_object_set(G_OBJECT(tree), "expander-level", 1, NULL); + return TRUE; +} + +static gboolean no_group_can_add_node(PurpleBlistNode *node) +{ + return on_offline_can_add_node(node); /* These happen to be the same */ +} + +static gpointer no_group_find_parent(PurpleBlistNode *node) +{ + gpointer ret = NULL; + + switch (purple_blist_node_get_type(node)) { + case PURPLE_BLIST_BUDDY_NODE: + ret = purple_blist_node_get_parent(node); + finch_blist_manager_add_node(ret); + break; + default: + break; + } + return ret; +} + +static FinchBlistManager no_group = +{ + "no-group", + N_("No Grouping"), + no_group_init, + no_group_uninit, + no_group_can_add_node, + no_group_find_parent, + NULL, + {NULL, NULL, NULL, NULL} +}; + +static gboolean +plugin_load(PurplePlugin *plugin) +{ + finch_blist_install_manager(&on_offline); + finch_blist_install_manager(&meebo_group); + finch_blist_install_manager(&no_group); + return TRUE; +} + +static gboolean +plugin_unload(PurplePlugin *plugin) +{ + finch_blist_uninstall_manager(&on_offline); + finch_blist_uninstall_manager(&meebo_group); + finch_blist_uninstall_manager(&no_group); + return TRUE; +} + +static PurplePluginInfo info = +{ + PURPLE_PLUGIN_MAGIC, + PURPLE_MAJOR_VERSION, + PURPLE_MINOR_VERSION, + PURPLE_PLUGIN_STANDARD, + FINCH_PLUGIN_TYPE, + 0, + NULL, + PURPLE_PRIORITY_DEFAULT, + "grouping", + N_("Grouping"), + VERSION, + N_("Provides alternate buddylist grouping options."), + N_("Provides alternate buddylist grouping options."), + "Sadrul H Chowdhury <sadrul@users.sourceforge.net>", + PURPLE_WEBSITE, + plugin_load, + plugin_unload, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL,NULL,NULL,NULL +}; + +static void +init_plugin(PurplePlugin *plugin) +{ +} + +PURPLE_INIT_PLUGIN(ignore, init_plugin, info) + +
--- a/libpurple/accountopt.h Sun Jan 27 04:26:38 2008 +0000 +++ b/libpurple/accountopt.h Sun Jan 27 10:03:26 2008 +0000 @@ -83,7 +83,10 @@ /*@{*/ /** - * Creates a new account option. + * Creates a new account option. If you know what @a type will be in advance, + * consider using purple_account_option_bool_new(), + * purple_account_option_int_new(), purple_account_option_string_new() or + * purple_account_option_list_new() (as appropriate) instead. * * @param type The type of option. * @param text The text of the option. @@ -91,8 +94,8 @@ * * @return The account option. */ -PurpleAccountOption *purple_account_option_new(PurplePrefType type, const char *text, - const char *pref_name); +PurpleAccountOption *purple_account_option_new(PurplePrefType type, + const char *text, const char *pref_name); /** * Creates a new boolean account option. @@ -104,8 +107,7 @@ * @return The account option. */ PurpleAccountOption *purple_account_option_bool_new(const char *text, - const char *pref_name, - gboolean default_value); + const char *pref_name, gboolean default_value); /** * Creates a new integer account option. @@ -117,8 +119,7 @@ * @return The account option. */ PurpleAccountOption *purple_account_option_int_new(const char *text, - const char *pref_name, - int default_value); + const char *pref_name, int default_value); /** * Creates a new string account option. @@ -130,8 +131,7 @@ * @return The account option. */ PurpleAccountOption *purple_account_option_string_new(const char *text, - const char *pref_name, - const char *default_value); + const char *pref_name, const char *default_value); /** * Creates a new list account option. @@ -140,7 +140,7 @@ * strings inside will be freed automatically. * * The list is a list of PurpleKeyValuePair items. The key is the ID stored and - * used internally, and the value is the label displayed. + * used internally, and the <tt>(const char *)</tt> value is the label displayed. * * @param text The text of the option. * @param pref_name The account preference name for the option. @@ -149,8 +149,7 @@ * @return The account option. */ PurpleAccountOption *purple_account_option_list_new(const char *text, - const char *pref_name, - GList *list); + const char *pref_name, GList *list); /** * Destroys an account option. @@ -240,11 +239,13 @@ const char *purple_account_option_get_text(const PurpleAccountOption *option); /** - * Returns the account setting for an account option. + * Returns the name of an account option. This corresponds to the @c pref_name + * parameter supplied to purple_account_option_new() or one of the + * type-specific constructors. * * @param option The account option. * - * @return The account setting. + * @return The option's name. */ const char *purple_account_option_get_setting(const PurpleAccountOption *option);
--- a/libpurple/blist.c Sun Jan 27 04:26:38 2008 +0000 +++ b/libpurple/blist.c Sun Jan 27 10:03:26 2008 +0000 @@ -640,10 +640,10 @@ if (purple_account_is_connected(buddy->account)) { - int cmp; - - cmp = purple_presence_compare(purple_buddy_get_presence(new_priority), - purple_buddy_get_presence(buddy)); + int cmp = 1; + if (purple_account_is_connected(new_priority->account)) + cmp = purple_presence_compare(purple_buddy_get_presence(new_priority), + purple_buddy_get_presence(buddy)); if (cmp > 0 || (cmp == 0 && purple_prefs_get_bool("/purple/contact/last_match"))) @@ -753,6 +753,26 @@ return ret; } +PurpleBlistNode *purple_blist_node_get_parent(PurpleBlistNode *node) +{ + return node ? node->parent : NULL; +} + +PurpleBlistNode *purple_blist_node_get_first_child(PurpleBlistNode *node) +{ + return node ? node->child : NULL; +} + +PurpleBlistNode *purple_blist_node_get_sibling_next(PurpleBlistNode *node) +{ + return node? node->next : NULL; +} + +PurpleBlistNode *purple_blist_node_get_sibling_prev(PurpleBlistNode *node) +{ + return node? node->prev : NULL; +} + void purple_blist_update_buddy_status(PurpleBuddy *buddy, PurpleStatus *old_status) { @@ -2232,6 +2252,22 @@ return (PurpleGroup *)(((PurpleBlistNode *)chat)->parent); } +PurpleAccount * +purple_chat_get_account(PurpleChat *chat) +{ + g_return_val_if_fail(chat != NULL, NULL); + + return chat->account; +} + +GHashTable * +purple_chat_get_components(PurpleChat *chat) +{ + g_return_val_if_fail(chat != NULL, NULL); + + return chat->components; +} + PurpleContact *purple_buddy_get_contact(PurpleBuddy *buddy) { g_return_val_if_fail(buddy != NULL, NULL);
--- a/libpurple/blist.h Sun Jan 27 04:26:38 2008 +0000 +++ b/libpurple/blist.h Sun Jan 27 10:03:26 2008 +0000 @@ -53,13 +53,13 @@ } PurpleBlistNodeType; -#define PURPLE_BLIST_NODE_IS_CHAT(n) ((n)->type == PURPLE_BLIST_CHAT_NODE) -#define PURPLE_BLIST_NODE_IS_BUDDY(n) ((n)->type == PURPLE_BLIST_BUDDY_NODE) -#define PURPLE_BLIST_NODE_IS_CONTACT(n) ((n)->type == PURPLE_BLIST_CONTACT_NODE) -#define PURPLE_BLIST_NODE_IS_GROUP(n) ((n)->type == PURPLE_BLIST_GROUP_NODE) +#define PURPLE_BLIST_NODE_IS_CHAT(n) (purple_blist_node_get_type(n) == PURPLE_BLIST_CHAT_NODE) +#define PURPLE_BLIST_NODE_IS_BUDDY(n) (purple_blist_node_get_type(n) == PURPLE_BLIST_BUDDY_NODE) +#define PURPLE_BLIST_NODE_IS_CONTACT(n) (purple_blist_node_get_type(n) == PURPLE_BLIST_CONTACT_NODE) +#define PURPLE_BLIST_NODE_IS_GROUP(n) (purple_blist_node_get_type(n) == PURPLE_BLIST_GROUP_NODE) #define PURPLE_BUDDY_IS_ONLINE(b) \ - ((b) != NULL && purple_account_is_connected((b)->account) && \ + ((b) != NULL && purple_account_is_connected(purple_buddy_get_account(b)) && \ purple_presence_is_online(purple_buddy_get_presence(b))) typedef enum @@ -231,10 +231,66 @@ * @param node A node. * @param offline Whether to include nodes for offline accounts * @return The next node + * @see purple_blist_node_get_parent + * @see purple_blist_node_get_first_child + * @see purple_blist_node_get_sibling_next + * @see purple_blist_node_get_sibling_prev */ PurpleBlistNode *purple_blist_node_next(PurpleBlistNode *node, gboolean offline); /** + * Returns the parent node of a given node. + * + * @param node A node. + * @return The parent node. + * @since 2.4.0 + * @see purple_blist_node_get_first_child + * @see purple_blist_node_get_sibling_next + * @see purple_blist_node_get_sibling_prev + * @see purple_blist_node_next + */ +PurpleBlistNode *purple_blist_node_get_parent(PurpleBlistNode *node); + +/** + * Returns the the first child node of a given node. + * + * @param node A node. + * @return The child node. + * @since 2.4.0 + * @see purple_blist_node_get_parent + * @see purple_blist_node_get_sibling_next + * @see purple_blist_node_get_sibling_prev + * @see purple_blist_node_next + */ +PurpleBlistNode *purple_blist_node_get_first_child(PurpleBlistNode *node); + +/** + * Returns the sibling node of a given node. + * + * @param node A node. + * @return The sibling node. + * @since 2.4.0 + * @see purple_blist_node_get_parent + * @see purple_blist_node_get_first_child + * @see purple_blist_node_get_sibling_prev + * @see purple_blist_node_next + */ +PurpleBlistNode *purple_blist_node_get_sibling_next(PurpleBlistNode *node); + +/** + * Returns the previous sibling node of a given node. + * + * @param node A node. + * @return The sibling node. + * @since 2.4.0 + * @see purple_blist_node_get_parent + * @see purple_blist_node_get_first_child + * @see purple_blist_node_get_sibling_next + * @see purple_blist_node_next + */ +PurpleBlistNode *purple_blist_node_get_sibling_prev(PurpleBlistNode *node); + +/** * Shows the buddy list, creating a new one if necessary. */ void purple_blist_show(void); @@ -667,6 +723,26 @@ PurpleGroup *purple_chat_get_group(PurpleChat *chat); /** + * Returns the account the chat belongs to. + * + * @param chat The chat. + * + * @return The account the chat belongs to. + * @since 2.4.0 + */ +PurpleAccount *purple_chat_get_account(PurpleChat *chat); + +/** + * Get a hashtable containing information about a chat. + * + * @param chat The chat. + * + * @constreturn The hashtable. + * @since 2.4.0 + */ +GHashTable *purple_chat_get_components(PurpleChat *chat); + +/** * Returns the group of which the buddy is a member. * * @param buddy The buddy
--- a/libpurple/buddyicon.c Sun Jan 27 04:26:38 2008 +0000 +++ b/libpurple/buddyicon.c Sun Jan 27 10:03:26 2008 +0000 @@ -701,11 +701,6 @@ } unref_filename(old_icon); - if (img) - g_hash_table_insert(pointer_icon_cache, account, img); - else - g_hash_table_remove(pointer_icon_cache, account); - if (purple_account_is_connected(account)) { PurpleConnection *gc; @@ -729,6 +724,11 @@ } g_free(old_icon); + if (img) + g_hash_table_insert(pointer_icon_cache, account, img); + else + g_hash_table_remove(pointer_icon_cache, account); + return img; }
--- a/libpurple/connection.c Sun Jan 27 04:26:38 2008 +0000 +++ b/libpurple/connection.c Sun Jan 27 10:03:26 2008 +0000 @@ -52,8 +52,19 @@ PurpleConnection *gc = data; PurplePluginProtocolInfo *prpl_info = NULL; - if (gc != NULL && gc->prpl != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + if (gc == NULL) + return TRUE; + + /* Only send keep-alives if we haven't heard from the + * server in a while. + */ + if ((time(NULL) - gc->last_received) < KEEPALIVE_INTERVAL) + return TRUE; + + if (gc->prpl == NULL) + return TRUE; + + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); if (prpl_info && prpl_info->keepalive) prpl_info->keepalive(gc); @@ -413,6 +424,14 @@ return gc->account; } +PurplePlugin * +purple_connection_get_prpl(const PurpleConnection *gc) +{ + g_return_val_if_fail(gc != NULL, NULL); + + return gc->prpl; +} + const char * purple_connection_get_password(const PurpleConnection *gc) {
--- a/libpurple/connection.h Sun Jan 27 04:26:38 2008 +0000 +++ b/libpurple/connection.h Sun Jan 27 10:03:26 2008 +0000 @@ -251,6 +251,8 @@ gboolean wants_to_die; guint disconnect_timeout; /**< Timer used for nasty stack tricks */ + time_t last_received; /**< When we last received a packet. Set by the + prpl to avoid sending unneeded keepalives */ }; #ifdef __cplusplus @@ -362,7 +364,7 @@ * @return TRUE if the account is connected, otherwise returns FALSE. */ #define PURPLE_CONNECTION_IS_CONNECTED(gc) \ - (gc->state == PURPLE_CONNECTED) + (purple_connection_get_state(gc) == PURPLE_CONNECTED) /** * Returns the connection's account. @@ -374,6 +376,16 @@ PurpleAccount *purple_connection_get_account(const PurpleConnection *gc); /** + * Returns the protocol plugin managing a connection. + * + * @param gc The connection. + * + * @return The protocol plugin. + * @since 2.4.0 + */ +PurplePlugin * purple_connection_get_prpl(const PurpleConnection *gc); + +/** * Returns the connection's password. * * @param gc The connection.
--- a/libpurple/example/Makefile.am Sun Jan 27 04:26:38 2008 +0000 +++ b/libpurple/example/Makefile.am Sun Jan 27 10:03:26 2008 +0000 @@ -17,7 +17,8 @@ -DLIBDIR=\"$(libdir)/purple-$(PURPLE_MAJOR_VERSION)/\" \ -DLOCALEDIR=\"$(datadir)/locale\" \ -DSYSCONFDIR=\"$(sysconfdir)\" \ - -I$(top_srcdir)/libpurple/ \ + -I$(top_builddir)/libpurple \ + -I$(top_srcdir)/libpurple \ -I$(top_srcdir) \ $(DEBUG_CFLAGS) \ $(GLIB_CFLAGS) \
--- a/libpurple/ft.c Sun Jan 27 04:26:38 2008 +0000 +++ b/libpurple/ft.c Sun Jan 27 10:03:26 2008 +0000 @@ -669,6 +669,22 @@ return xfer->remote_port; } +time_t +purple_xfer_get_start_time(const PurpleXfer *xfer) +{ + g_return_val_if_fail(xfer != NULL, 0); + + return xfer->start_time; +} + +time_t +purple_xfer_get_end_time(const PurpleXfer *xfer) +{ + g_return_val_if_fail(xfer != NULL, 0); + + return xfer->end_time; +} + void purple_xfer_set_completed(PurpleXfer *xfer, gboolean completed) {
--- a/libpurple/ft.h Sun Jan 27 04:26:38 2008 +0000 +++ b/libpurple/ft.h Sun Jan 27 10:03:26 2008 +0000 @@ -358,6 +358,26 @@ unsigned int purple_xfer_get_remote_port(const PurpleXfer *xfer); /** + * Returns the time the transfer of a file started. + * + * @param xfer The file transfer. + * + * @return The time when the transfer started. + * @since 2.4.0 + */ +time_t purple_xfer_get_start_time(const PurpleXfer *xfer); + +/** + * Returns the time the transfer of a file ended. + * + * @param xfer The file transfer. + * + * @return The time when the transfer ended. + * @since 2.4.0 + */ +time_t purple_xfer_get_end_time(const PurpleXfer *xfer); + +/** * Sets the completed state for the file transfer. * * @param xfer The file transfer.
--- a/libpurple/protocols/gg/gg.c Sun Jan 27 04:26:38 2008 +0000 +++ b/libpurple/protocols/gg/gg.c Sun Jan 27 10:03:26 2008 +0000 @@ -1314,7 +1314,7 @@ _("Unable to read socket")); return; } - + gc->last_received = time(NULL); switch (ev->type) { case GG_EVENT_NONE: /* Nothing happened. */
--- a/libpurple/protocols/irc/irc.c Sun Jan 27 04:26:38 2008 +0000 +++ b/libpurple/protocols/irc/irc.c Sun Jan 27 10:03:26 2008 +0000 @@ -572,6 +572,7 @@ { char *cur, *end; + irc->account->gc->last_received = time(NULL); irc->inbufused += len; irc->inbuf[irc->inbufused] = '\0';
--- a/libpurple/protocols/jabber/auth.c Sun Jan 27 04:26:38 2008 +0000 +++ b/libpurple/protocols/jabber/auth.c Sun Jan 27 10:03:26 2008 +0000 @@ -344,6 +344,7 @@ * Doing otherwise means that simply compiling with SASL support renders the client unable to connect to servers * which would connect without issue otherwise. -evands */ + js->auth_type = JABBER_AUTH_IQ_AUTH; jabber_auth_start_old(js); return; }
--- a/libpurple/protocols/jabber/jabber.c Sun Jan 27 04:26:38 2008 +0000 +++ b/libpurple/protocols/jabber/jabber.c Sun Jan 27 10:03:26 2008 +0000 @@ -432,6 +432,7 @@ } while((len = purple_ssl_read(gsc, buf, sizeof(buf) - 1)) > 0) { + gc->last_received = time(NULL); buf[len] = '\0'; purple_debug(PURPLE_DEBUG_INFO, "jabber", "Recv (ssl)(%d): %s\n", len, buf); jabber_parser_process(js, buf, len); @@ -459,6 +460,7 @@ return; if((len = read(js->fd, buf, sizeof(buf) - 1)) > 0) { + gc->last_received = time(NULL); #ifdef HAVE_CYRUS_SASL if (js->sasl_maxbuf>0) { const char *out;
--- a/libpurple/protocols/jabber/si.c Sun Jan 27 04:26:38 2008 +0000 +++ b/libpurple/protocols/jabber/si.c Sun Jan 27 10:03:26 2008 +0000 @@ -1089,7 +1089,7 @@ } else { /* we've got multiple resources, we need to pick one to send to */ GList *l; - char *msg = g_strdup_printf(_("Please select which resource of %s you would like to send a file to"), xfer->who); + char *msg = g_strdup_printf(_("Please select the resource of %s to which you would like to send a file"), xfer->who); PurpleRequestFields *fields = purple_request_fields_new(); PurpleRequestField *field = purple_request_field_choice_new("resource", _("Resource"), 0); PurpleRequestFieldGroup *group = purple_request_field_group_new(NULL);
--- a/libpurple/protocols/msn/servconn.c Sun Jan 27 04:26:38 2008 +0000 +++ b/libpurple/protocols/msn/servconn.c Sun Jan 27 10:03:26 2008 +0000 @@ -391,6 +391,7 @@ session = servconn->session; len = read(servconn->fd, buf, sizeof(buf) - 1); + servconn->session->account->gc->last_received = time(NULL); if (len <= 0) { switch (errno) {
--- a/libpurple/protocols/msnp9/servconn.c Sun Jan 27 04:26:38 2008 +0000 +++ b/libpurple/protocols/msnp9/servconn.c Sun Jan 27 10:03:26 2008 +0000 @@ -387,6 +387,7 @@ session = servconn->session; len = read(servconn->fd, buf, sizeof(buf) - 1); + servconn->session->account->gc->last_received = time(NULL); if (len < 0 && errno == EAGAIN) return;
--- a/libpurple/protocols/myspace/myspace.c Sun Jan 27 04:26:38 2008 +0000 +++ b/libpurple/protocols/myspace/myspace.c Sun Jan 27 10:03:26 2008 +0000 @@ -649,7 +649,7 @@ msim_incoming_bm(MsimSession *session, MsimMessage *msg) { guint bm; - + bm = msim_msg_get_integer(msg, "bm"); msim_incoming_bm_record_cv(session, msg); @@ -780,7 +780,7 @@ } else if (g_str_equal(msg_text, "%stoptyping%")) { serv_got_typing_stopped(session->gc, username); rc = TRUE; - } else if (strstr(msg_text, "!!!ZAP_SEND!!!=RTE_BTN_ZAPS_")) { + } else if (strstr(msg_text, "!!!ZAP_SEND!!!=RTE_BTN_ZAPS_") == msg_text) { rc = msim_incoming_zap(session, msg); } else if (strstr(msg_text, "!!!GroupCount=")) { /* TODO: support group chats. I think the number in msg_text has @@ -792,14 +792,14 @@ /* TODO: support group chats. This one might mean a user * went offline or exited the chat. */ purple_debug_info("msim", "msim_incoming_action: TODO: implement #4691, group chats: %s\n", msg_text); - + rc = TRUE; } else if (msim_msg_get_integer(msg, "aid") != 0) { purple_debug_info("msim", "TODO: implement #4691, group chat from %d on %d: %s\n", msim_msg_get_integer(msg, "aid"), msim_msg_get_integer(msg, "f"), msg_text); - + rc = TRUE; } else { msim_unrecognized(session, msg, @@ -1209,7 +1209,7 @@ /* Special elements name beginning with '_', we'll use internally within the * program (did not come directly from the wire). */ msg = msim_msg_append(msg, "_username", MSIM_TYPE_STRING, username); /* This makes 'msg' the owner of 'username' */ - + /* TODO: attach more useful information, like ImageURL */ msim_process(session, msg);
--- a/libpurple/protocols/oscar/flap_connection.c Sun Jan 27 04:26:38 2008 +0000 +++ b/libpurple/protocols/oscar/flap_connection.c Sun Jan 27 10:03:26 2008 +0000 @@ -360,7 +360,7 @@ conn = data; od = conn->od; - account = (PURPLE_CONNECTION_IS_VALID(od->gc) ? purple_connection_get_account(od->gc) : NULL); + account = purple_connection_get_account(od->gc); purple_debug_info("oscar", "Destroying oscar connection of " "type 0x%04hx. Disconnect reason is %d\n", @@ -375,8 +375,8 @@ * TODO: If we don't have a SNAC_FAMILY_LOCATE connection then * we should try to request one instead of disconnecting. */ - if (account && !account->disconnecting && - ((od->oscar_connections == NULL) || (!flap_connection_getbytype(od, SNAC_FAMILY_LOCATE)))) + if (!account->disconnecting && ((od->oscar_connections == NULL) + || (!flap_connection_getbytype(od, SNAC_FAMILY_LOCATE)))) { /* No more FLAP connections! Sign off this PurpleConnection! */ gchar *tmp; @@ -817,6 +817,7 @@ OSCAR_DISCONNECT_LOST_CONNECTION, g_strerror(errno)); break; } + conn->od->gc->last_received = time(NULL); /* If we don't even have a complete FLAP header then do nothing */ conn->header_received += read;
--- a/libpurple/protocols/sametime/sametime.c Sun Jan 27 04:26:38 2008 +0000 +++ b/libpurple/protocols/sametime/sametime.c Sun Jan 27 10:03:26 2008 +0000 @@ -1695,7 +1695,9 @@ int len; len = read(sock, buf, BUF_LEN); - if(len > 0) mwSession_recv(session, buf, len); + if(len > 0) { + mwSession_recv(session, buf, len); + } return len; }
--- a/libpurple/protocols/simple/simple.c Sun Jan 27 04:26:38 2008 +0000 +++ b/libpurple/protocols/simple/simple.c Sun Jan 27 10:03:26 2008 +0000 @@ -1675,7 +1675,7 @@ if(sip->fd == source) sip->fd = -1; return; } - + gc->last_received = time(NULL); conn->inbufused += len; conn->inbuf[conn->inbufused] = '\0';
--- a/libpurple/protocols/yahoo/yahoo.c Sun Jan 27 04:26:38 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo.c Sun Jan 27 10:03:26 2008 +0000 @@ -2506,7 +2506,7 @@ _("Server closed the connection.")); return; } - + gc->last_received = time(NULL); yd->rxqueue = g_realloc(yd->rxqueue, len + yd->rxlen); memcpy(yd->rxqueue + yd->rxlen, buf, len); yd->rxlen += len;
--- a/libpurple/protocols/yahoo/yahoo_filexfer.c Sun Jan 27 04:26:38 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo_filexfer.c Sun Jan 27 10:03:26 2008 +0000 @@ -922,7 +922,7 @@ return xfer; } -static gchar* yahoo_xfer_new_xfer_id() +static gchar* yahoo_xfer_new_xfer_id(void) { gchar *ans; int i,j; @@ -937,7 +937,7 @@ else if(j < 52) ans[i] = j - 26 + 'A'; else - ans[i] = j - 52 + '0'; + ans[i] = j - 52 + '0'; } return ans; }
--- a/libpurple/tests/test_util.c Sun Jan 27 04:26:38 2008 +0000 +++ b/libpurple/tests/test_util.c Sun Jan 27 10:03:26 2008 +0000 @@ -71,6 +71,14 @@ START_TEST(test_util_email_is_valid) { fail_unless(purple_email_is_valid("purple-devel@lists.sf.net")); + fail_if(purple_email_is_valid("purple-devel@@lists.sf.net")); + fail_if(purple_email_is_valid("purple@devel@lists.sf.net")); + fail_if(purple_email_is_valid("purple-devel@list..sf.net")); + fail_if(purple_email_is_valid("purple-devel")); + fail_if(purple_email_is_valid("purple-devel@")); + fail_if(purple_email_is_valid("@lists.sf.net")); + fail_if(purple_email_is_valid("")); + fail_if(purple_email_is_valid("totally bogus")); } END_TEST
--- a/libpurple/util.c Sun Jan 27 04:26:38 2008 +0000 +++ b/libpurple/util.c Sun Jan 27 10:03:26 2008 +0000 @@ -1445,7 +1445,6 @@ ALLOW_TAG("pre"); ALLOW_TAG("q"); ALLOW_TAG("span"); - ALLOW_TAG("strong"); ALLOW_TAG("ul"); @@ -1465,9 +1464,14 @@ plain = g_string_append_c(plain, '\n'); continue; } - if(!g_ascii_strncasecmp(c, "<b>", 3) || !g_ascii_strncasecmp(c, "<bold>", strlen("<bold>"))) { + if(!g_ascii_strncasecmp(c, "<b>", 3) || !g_ascii_strncasecmp(c, "<bold>", strlen("<bold>")) || !g_ascii_strncasecmp(c, "<strong>", strlen("<strong>"))) { struct purple_parse_tag *pt = g_new0(struct purple_parse_tag, 1); - pt->src_tag = *(c+2) == '>' ? "b" : "bold"; + if (*(c+2) == '>') + pt->src_tag = "b"; + else if (*(c+2) == 'o') + pt->src_tag = "bold"; + else + pt->src_tag = "strong"; pt->dest_tag = "span"; tags = g_list_prepend(tags, pt); c = strchr(c, '>') + 1;
--- a/pidgin/gtkconv.c Sun Jan 27 04:26:38 2008 +0000 +++ b/pidgin/gtkconv.c Sun Jan 27 10:03:26 2008 +0000 @@ -169,6 +169,7 @@ static void pidgin_conv_set_position_size(PidginWindow *win, int x, int y, int width, int height); +static gboolean pidgin_conv_xy_to_right_infopane(PidginWindow *win, int x, int y); static GdkColor *get_nick_color(PidginConversation *gtkconv, const char *name) { static GdkColor col; @@ -6885,6 +6886,18 @@ gray_stuff_out(PIDGIN_CONVERSATION(conv)); } +static gboolean +pidgin_conv_xy_to_right_infopane(PidginWindow *win, int x, int y) +{ + gint pane_x, pane_y, x_rel; + PidginConversation *gtkconv; + + gdk_window_get_origin(win->notebook->window, &pane_x, &pane_y); + x_rel = x - pane_x; + gtkconv = pidgin_conv_window_get_active_gtkconv(win); + return (x_rel > gtkconv->infopane->allocation.x + gtkconv->infopane->allocation.width / 2); +} + int pidgin_conv_get_tab_at_xy(PidginWindow *win, int x, int y, gboolean *to_right) { @@ -6920,7 +6933,7 @@ tab = gtk_notebook_get_tab_label(GTK_NOTEBOOK(notebook), page); /* Make sure the tab is not hidden beyond an arrow */ - if (!GTK_WIDGET_DRAWABLE(tab)) + if (!GTK_WIDGET_DRAWABLE(tab) && gtk_notebook_get_show_tabs(notebook)) continue; if (horiz) { @@ -8179,7 +8192,6 @@ GtkWidget *tab; gint page_num; gboolean horiz_tabs = FALSE; - PidginConversation *gtkconv; gboolean to_right = FALSE; /* Get the window that the cursor is over. */ @@ -8193,20 +8205,27 @@ dest_notebook = GTK_NOTEBOOK(dest_win->notebook); - page_num = pidgin_conv_get_tab_at_xy(dest_win, - e->x_root, e->y_root, &to_right); - to_right = to_right && (win != dest_win); + if (gtk_notebook_get_show_tabs(dest_notebook)) { + page_num = pidgin_conv_get_tab_at_xy(dest_win, + e->x_root, e->y_root, &to_right); + to_right = to_right && (win != dest_win); + tab = pidgin_conv_window_get_gtkconv_at_index(dest_win, page_num)->tabby; + } else { + page_num = 0; + to_right = pidgin_conv_xy_to_right_infopane(dest_win, e->x_root, e->y_root); + tab = pidgin_conv_window_get_gtkconv_at_index(dest_win, page_num)->infopane; + } if (gtk_notebook_get_tab_pos(dest_notebook) == GTK_POS_TOP || gtk_notebook_get_tab_pos(dest_notebook) == GTK_POS_BOTTOM) { horiz_tabs = TRUE; } - gtkconv = pidgin_conv_window_get_gtkconv_at_index(dest_win, page_num); - tab = gtkconv->tabby; - if (gtk_notebook_get_show_tabs(dest_notebook) == FALSE) { - dnd_hints_show_relative(HINT_ARROW_DOWN, gtkconv->infopane, HINT_POSITION_CENTER, HINT_POSITION_TOP); - dnd_hints_show_relative(HINT_ARROW_UP, gtkconv->infopane, HINT_POSITION_CENTER, HINT_POSITION_BOTTOM); + if (gtk_notebook_get_show_tabs(dest_notebook) == FALSE && win == dest_win) + { + /* dragging a tab from a single-tabbed window over its own window */ + dnd_hints_hide_all(); + return TRUE; } else if (horiz_tabs) { if (((gpointer)win == (gpointer)dest_win && win->drag_tab < page_num) || to_right) { dnd_hints_show_relative(HINT_ARROW_DOWN, tab, HINT_POSITION_RIGHT, HINT_POSITION_TOP); @@ -8403,6 +8422,7 @@ notebook_release_cb(GtkWidget *widget, GdkEventButton *e, PidginWindow *win) { PidginWindow *dest_win; + GtkNotebook *dest_notebook; PurpleConversation *conv; PidginConversation *gtkconv; gint dest_page_num = 0; @@ -8478,9 +8498,16 @@ "conversation-dragging", win, dest_win); /* Get the destination page number. */ - if (!new_window) - dest_page_num = pidgin_conv_get_tab_at_xy(dest_win, - e->x_root, e->y_root, &to_right); + if (!new_window) { + dest_notebook = GTK_NOTEBOOK(dest_win->notebook); + if (gtk_notebook_get_show_tabs(dest_notebook)) { + dest_page_num = pidgin_conv_get_tab_at_xy(dest_win, + e->x_root, e->y_root, &to_right); + } else { + dest_page_num = 0; + to_right = pidgin_conv_xy_to_right_infopane(dest_win, e->x_root, e->y_root); + } + } gtkconv = pidgin_conv_window_get_gtkconv_at_index(win, win->drag_tab);
--- a/pidgin/gtkimhtml.c Sun Jan 27 04:26:38 2008 +0000 +++ b/pidgin/gtkimhtml.c Sun Jan 27 10:03:26 2008 +0000 @@ -1455,6 +1455,9 @@ gtk_text_buffer_create_tag(imhtml->text_buffer, "SUP", "rise", 5000, NULL); gtk_text_buffer_create_tag(imhtml->text_buffer, "PRE", "family", "Monospace", NULL); gtk_text_buffer_create_tag(imhtml->text_buffer, "search", "background", "#22ff00", "weight", "bold", NULL); +#if GTK_CHECK_VERSION(2,10,10) + gtk_text_buffer_create_tag(imhtml->text_buffer, "comment", "invisible", FALSE, NULL); +#endif /* When hovering over a link, we show the hand cursor--elsewhere we show the plain ol' pointer cursor */ imhtml->hand_cursor = gdk_cursor_new (GDK_HAND2); @@ -2981,10 +2984,15 @@ gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); +#if GTK_CHECK_VERSION(2,10,10) + wpos = g_snprintf (ws, len, "%s", tag); + gtk_text_buffer_insert_with_tags_by_name(imhtml->text_buffer, iter, ws, wpos, "comment", NULL); +#else if (imhtml->show_comments && !(options & GTK_IMHTML_NO_COMMENTS)) { wpos = g_snprintf (ws, len, "%s", tag); gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); } +#endif ws[0] = '\0'; wpos = 0; /* NEW_BIT (NEW_COMMENT_BIT); */ @@ -3130,6 +3138,12 @@ void gtk_imhtml_show_comments (GtkIMHtml *imhtml, gboolean show) { +#if GTK_CHECK_VERSION(2,10,10) + GtkTextTag *tag; + tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), "comment"); + if (tag) + g_object_set(G_OBJECT(tag), "invisible", !show, NULL); +#endif imhtml->show_comments = show; }
--- a/pidgin/gtknotify.c Sun Jan 27 04:26:38 2008 +0000 +++ b/pidgin/gtknotify.c Sun Jan 27 10:03:26 2008 +0000 @@ -1058,7 +1058,12 @@ /* if they are running gnome, use the gnome web browser */ if (purple_running_gnome() == TRUE) { - command = g_strdup_printf("gnome-open %s", escaped); + char *tmp = g_find_program_in_path("xdg-open"); + if (tmp == NULL) + command = g_strdup_printf("gnome-open %s", escaped); + else + command = g_strdup_printf("xdg-open %s", escaped); + g_free(tmp); } else if (purple_running_osx() == TRUE) { @@ -1074,6 +1079,10 @@ else command = g_strdup_printf("%s %s", web_browser, escaped); } + else if (!strcmp(web_browser, "xdg-open")) + { + command = g_strdup_printf("xdg-open %s", escaped); + } else if (!strcmp(web_browser, "gnome-open")) { command = g_strdup_printf("gnome-open %s", escaped);
--- a/pidgin/gtkprefs.c Sun Jan 27 04:26:38 2008 +0000 +++ b/pidgin/gtkprefs.c Sun Jan 27 10:03:26 2008 +0000 @@ -1369,6 +1369,7 @@ {N_("Netscape"), "netscape"}, {N_("Mozilla"), "mozilla"}, {N_("Konqueror"), "kfmclient"}, + {N_("Desktop Default"), "xdg-open"}, {N_("GNOME Default"), "gnome-open"}, {N_("Galeon"), "galeon"}, {N_("Firefox"), "firefox"}, @@ -1391,6 +1392,14 @@ browsers = g_list_prepend(browsers, (gpointer)_(possible_browsers[i].name)); if(browser_setting && !strcmp(possible_browsers[i].command, browser_setting)) browser_setting = NULL; + /* If xdg-open is valid, prefer it over gnome-open and skip forward */ + if(!strcmp(possible_browsers[i].command, "xdg-open")) { + if (browser_setting && !strcmp("gnome-open", browser_setting)) { + purple_prefs_set_string(PIDGIN_PREFS_ROOT "/browsers/browser", possible_browsers[i].command); + browser_setting = NULL; + } + i++; + } } }
--- a/pidgin/gtkstatusbox.c Sun Jan 27 04:26:38 2008 +0000 +++ b/pidgin/gtkstatusbox.c Sun Jan 27 10:03:26 2008 +0000 @@ -511,12 +511,26 @@ pidgin_status_box_finalize(GObject *obj) { PidginStatusBox *statusbox = PIDGIN_STATUS_BOX(obj); + int i; purple_signals_disconnect_by_handle(statusbox); purple_prefs_disconnect_by_handle(statusbox); destroy_icon_box(statusbox); + if (statusbox->active_row) + gtk_tree_row_reference_free(statusbox->active_row); + + for (i = 0; i < G_N_ELEMENTS(statusbox->connecting_pixbufs); i++) { + if (statusbox->connecting_pixbufs[i] != NULL) + gdk_pixbuf_unref(statusbox->connecting_pixbufs[i]); + } + + for (i = 0; i < G_N_ELEMENTS(statusbox->typing_pixbufs); i++) { + if (statusbox->typing_pixbufs[i] != NULL) + gdk_pixbuf_unref(statusbox->typing_pixbufs[i]); + } + g_object_unref(G_OBJECT(statusbox->store)); g_object_unref(G_OBJECT(statusbox->dropdown_store)); G_OBJECT_CLASS(parent_class)->finalize(obj); @@ -1166,18 +1180,15 @@ cache_pixbufs(PidginStatusBox *status_box) { GtkIconSize icon_size; + int i; g_object_set(G_OBJECT(status_box->icon_rend), "xpad", 3, NULL); icon_size = gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL); - if (status_box->connecting_pixbufs[0] != NULL) - gdk_pixbuf_unref(status_box->connecting_pixbufs[0]); - if (status_box->connecting_pixbufs[1] != NULL) - gdk_pixbuf_unref(status_box->connecting_pixbufs[1]); - if (status_box->connecting_pixbufs[2] != NULL) - gdk_pixbuf_unref(status_box->connecting_pixbufs[2]); - if (status_box->connecting_pixbufs[3] != NULL) - gdk_pixbuf_unref(status_box->connecting_pixbufs[3]); + for (i = 0; i < G_N_ELEMENTS(status_box->connecting_pixbufs); i++) { + if (status_box->connecting_pixbufs[i] != NULL) + gdk_pixbuf_unref(status_box->connecting_pixbufs[i]); + } status_box->connecting_index = 0; status_box->connecting_pixbufs[0] = gtk_widget_render_icon (GTK_WIDGET(status_box->vbox), PIDGIN_STOCK_ANIMATION_CONNECT0, @@ -1199,14 +1210,10 @@ status_box->connecting_pixbufs[8] = gtk_widget_render_icon (GTK_WIDGET(status_box->vbox), PIDGIN_STOCK_ANIMATION_CONNECT8, icon_size, "PidginStatusBox"); - if (status_box->typing_pixbufs[0] != NULL) - gdk_pixbuf_unref(status_box->typing_pixbufs[0]); - if (status_box->typing_pixbufs[1] != NULL) - gdk_pixbuf_unref(status_box->typing_pixbufs[1]); - if (status_box->typing_pixbufs[2] != NULL) - gdk_pixbuf_unref(status_box->typing_pixbufs[2]); - if (status_box->typing_pixbufs[3] != NULL) - gdk_pixbuf_unref(status_box->typing_pixbufs[3]); + for (i = 0; i < G_N_ELEMENTS(status_box->typing_pixbufs); i++) { + if (status_box->typing_pixbufs[i] != NULL) + gdk_pixbuf_unref(status_box->typing_pixbufs[i]); + } status_box->typing_index = 0; status_box->typing_pixbufs[0] = gtk_widget_render_icon (GTK_WIDGET(status_box->vbox), PIDGIN_STOCK_ANIMATION_TYPING0,
--- a/pidgin/gtkutils.h Sun Jan 27 04:26:38 2008 +0000 +++ b/pidgin/gtkutils.h Sun Jan 27 10:03:26 2008 +0000 @@ -798,11 +798,11 @@ * Add a labelled widget to a GtkVBox * * @param vbox The GtkVBox to add the widget to. - * @param widget_label The label to give the widget. - * @param sg The GtkSizeGroup to add the label to. - * @param widget The GtkWidget to add + * @param widget_label The label to give the widget, can be @c NULL. + * @param sg The GtkSizeGroup to add the label to, can be @c NULL. + * @param widget The GtkWidget to add. * @param expand Whether to expand the widget horizontally. - * @param p_label Place to store a pointer to the GtkLabel, or NULL if you don't care. + * @param p_label Place to store a pointer to the GtkLabel, or @c NULL if you don't care. * * @return A GtkHBox already added to the GtkVBox containing the GtkLabel and the GtkWidget. * @since 2.4.0
--- a/po/POTFILES.in Sun Jan 27 04:26:38 2008 +0000 +++ b/po/POTFILES.in Sun Jan 27 10:03:26 2008 +0000 @@ -33,6 +33,7 @@ finch/plugins/gntclipboard.c finch/plugins/gntgf.c finch/plugins/gnthistory.c +finch/plugins/grouping.c finch/plugins/lastlog.c libpurple/account.c libpurple/blist.c
--- a/po/de.po Sun Jan 27 04:26:38 2008 +0000 +++ b/po/de.po Sun Jan 27 10:03:26 2008 +0000 @@ -11,8 +11,8 @@ msgstr "" "Project-Id-Version: de\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-01-17 22:50+0100\n" -"PO-Revision-Date: 2008-01-17 22:50+0100\n" +"POT-Creation-Date: 2008-01-23 10:20+0100\n" +"PO-Revision-Date: 2008-01-23 10:19+0100\n" "Last-Translator: Jochen Kemnade <jochenkemnade@web.de>\n" "Language-Team: Deutsch <de@li.org>\n" "MIME-Version: 1.0\n" @@ -155,6 +155,29 @@ msgid "Deny" msgstr "Ablehnen" +#, c-format +msgid "" +"Online: %d\n" +"Total: %d" +msgstr "" +"Online: %d\n" +"Gesamt: %d" + +#, c-format +msgid "Account: %s (%s)" +msgstr "Konto: %s (%s)" + +#, c-format +msgid "" +"\n" +"Last Seen: %s ago" +msgstr "" +"\n" +"Zuletzt gesehen: vor %s" + +msgid "Default" +msgstr "Standard" + msgid "You must provide a screename for the buddy." msgstr "Sie müssen einen Benutzernamen für den Buddy angeben." @@ -303,26 +326,6 @@ msgid "On Mobile" msgstr "Am Handy" -#, c-format -msgid "" -"Online: %d\n" -"Total: %d" -msgstr "" -"Online: %d\n" -"Gesamt: %d" - -#, c-format -msgid "Account: %s (%s)" -msgstr "Konto: %s (%s)" - -#, c-format -msgid "" -"\n" -"Last Seen: %s ago" -msgstr "" -"\n" -"Zuletzt gesehen: vor %s" - msgid "New..." msgstr "Neu..." @@ -389,6 +392,15 @@ msgid "By Log Size" msgstr "Nach Größe der Logs" +msgid "Buddy" +msgstr "Buddy" + +msgid "Chat" +msgstr "Chat" + +msgid "Grouping" +msgstr "Gruppierung" + msgid "Certificate Import" msgstr "Zertifikat-Import" @@ -1321,6 +1333,27 @@ "Wenn eine neue Unterhaltung eröffnet wird, fügt dieses Plugin die letzte " "Unterhaltung in die aktuelle Unterhaltung ein." +msgid "Online" +msgstr "Online" + +msgid "Offline" +msgstr "Offline" + +msgid "Online Buddies" +msgstr "Online-Buddys" + +msgid "Offline Buddies" +msgstr "Offline-Buddys" + +msgid "Online/Offline" +msgstr "Online/Offline" + +msgid "No Grouping" +msgstr "Keine Gruppierung" + +msgid "Provides alternate buddylist grouping options." +msgstr "Bietet alternative Einstellungen für die Kontaktlisten-Gruppierung." + msgid "Lastlog" msgstr "Verlauf" @@ -2822,9 +2855,6 @@ msgid "Add to chat..." msgstr "Zum Chat hinzufügen..." -msgid "Offline" -msgstr "Offline" - msgid "Available" msgstr "Verfügbar" @@ -5976,9 +6006,6 @@ msgid "AIM Direct IM" msgstr "AIM direkte Nachricht" -msgid "Chat" -msgstr "Chat" - msgid "Get File" msgstr "Datei abrufen" @@ -6048,9 +6075,6 @@ msgid "Invisible" msgstr "Unsichtbar" -msgid "Online" -msgstr "Online" - msgid "IP Address" msgstr "IP-Adresse" @@ -10081,9 +10105,6 @@ msgid "Total Buddies" msgstr "Buddy-Anzahl" -msgid "Online Buddies" -msgstr "Online-Buddys" - #, c-format msgid "Idle %dd %dh %02dm" msgstr "Untätig %dd %dh %02dm" @@ -11691,9 +11712,6 @@ msgid "Pounce Target" msgstr "Alarm-Ziel" -msgid "Default" -msgstr "Standard" - msgid "Smiley theme failed to unpack." msgstr "Smiley-Thema konnte nicht entpackt werden."