# HG changeset patch # User Yoshiki Yazawa # Date 1183961667 0 # Node ID d4eebb5c3dbb1a75f45cf621045ed71dcc513790 # Parent d6362d94e747a6579f1e03ed7653ddeef2467cb5# Parent d2b6ae715eae136be7d337a6ec2406245f04a20c propagate from branch 'im.pidgin.pidgin' (head f77175b39d6209f3bca85b3d1baca3eee2f14900) to branch 'im.pidgin.pidgin.yaz' (head 58ac5ab84bec5e6519ec82a66adcb5d0f4b02bf3) diff -r d6362d94e747 -r d4eebb5c3dbb .mtn-ignore --- a/.mtn-ignore Fri Jul 06 06:12:02 2007 +0000 +++ b/.mtn-ignore Mon Jul 09 06:14:27 2007 +0000 @@ -9,7 +9,7 @@ .*\.dll$ .*\.exe$ intltool-.* -Doxyfile$ +Doxyfile(\.mingw)?$ aclocal.m4 compile config.cache diff -r d6362d94e747 -r d4eebb5c3dbb ChangeLog --- a/ChangeLog Fri Jul 06 06:12:02 2007 +0000 +++ b/ChangeLog Mon Jul 09 06:14:27 2007 +0000 @@ -30,6 +30,7 @@ * Some improvements for tab-completion, tooltip and the password entries * Some bugs regarding search results fixed * A new DBus-script to create a docklet for finch + * Support for showing empty groups in the buddy list (Eric Polino) version 2.0.2 (06/14/2007): Pidgin: diff -r d6362d94e747 -r d4eebb5c3dbb Makefile.mingw --- a/Makefile.mingw Fri Jul 06 06:12:02 2007 +0000 +++ b/Makefile.mingw Mon Jul 09 06:14:27 2007 +0000 @@ -56,7 +56,7 @@ #build an expression for `find` to use to ignore the above files EXTERNAL_DLLS_FIND_EXP = $(patsubst %,-o -name %,$(EXTERNAL_DLLS)) -.PHONY: all install installer installer_nogtk installer_debug installers clean uninstall create_release_install_dir +.PHONY: all docs install installer installer_nogtk installer_debug installers clean uninstall create_release_install_dir all: $(PIDGIN_CONFIG_H) $(MAKE) -C $(PURPLE_TOP) -f $(MINGW_MAKEFILE) @@ -88,11 +88,19 @@ installers: installer installer_nogtk installer_debug +Doxyfile.mingw: Doxyfile.in + sed -e "s/@PACKAGE@/pidgin/" -e "s/@VERSION@/$(PIDGIN_VERSION)/" -e "s/@top_srcdir@/$(PIDGIN_TREE_TOP)/g" -e "s/@enable_dot@/NO/" Doxyfile.in > Doxyfile.mingw + +docs: Doxyfile.mingw + @echo "Running doxygen..." + @doxygen Doxyfile.mingw + clean: $(MAKE) -C $(PURPLE_PO_TOP) -f $(MINGW_MAKEFILE) clean $(MAKE) -C $(PIDGIN_TOP) -f $(MINGW_MAKEFILE) clean $(MAKE) -C $(PURPLE_TOP) -f $(MINGW_MAKEFILE) clean rm -f $(PIDGIN_CONFIG_H) ./VERSION pidgin*.exe + rm -rf doc/html Doxyfile.mingw uninstall: rm -rf $(PURPLE_INSTALL_PERLMOD_DIR) $(PIDGIN_INSTALL_PLUGINS_DIR) $(PURPLE_INSTALL_PO_DIR) $(PIDGIN_INSTALL_DIR) $(PIDGIN_INSTALL_DIR).release diff -r d6362d94e747 -r d4eebb5c3dbb finch/finch.c --- a/finch/finch.c Fri Jul 06 06:12:02 2007 +0000 +++ b/finch/finch.c Mon Jul 09 06:14:27 2007 +0000 @@ -55,17 +55,36 @@ purple_debug_set_ui_ops(finch_debug_get_ui_ops()); } +/* XXX: this "leaks" a hashtable on shutdown. I'll let + * the finch guys decide if they want to go through the trouble + * of properly freeing it, since their quit function doesn't + * live in this file */ + +static GHashTable *ui_info = NULL; + +static GHashTable *finch_ui_get_info() +{ + if(NULL == ui_info) { + ui_info = g_hash_table_new(g_str_hash, g_str_equal); + + g_hash_table_insert(ui_info, "name", (char*)_("Finch")); + g_hash_table_insert(ui_info, "version", VERSION); + } + + return ui_info; +} + static PurpleCoreUiOps core_ops = { finch_prefs_init, debug_init, gnt_ui_init, gnt_ui_uninit, + finch_ui_get_info, /* padding */ NULL, NULL, - NULL, NULL }; diff -r d6362d94e747 -r d4eebb5c3dbb finch/gntblist.c --- a/finch/gntblist.c Fri Jul 06 06:12:02 2007 +0000 +++ b/finch/gntblist.c Mon Jul 09 06:14:27 2007 +0000 @@ -195,8 +195,8 @@ node_update(list, (PurpleBlistNode*)contact); } else if (!PURPLE_BLIST_NODE_IS_GROUP(node)) { PurpleGroup *group = (PurpleGroup*)node->parent; - if ((!purple_prefs_get_bool(PREF_ROOT "/showoffline") && !is_group_online(group)) || - group->currentsize < 1) + 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) node->ui_data = NULL; @@ -253,8 +253,9 @@ } } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { PurpleGroup *group = (PurpleGroup*)node; - if ((!purple_prefs_get_bool(PREF_ROOT "/showoffline") && !is_group_online(group)) || - group->currentsize < 1) + if (!purple_prefs_get_bool(PREF_ROOT "/emptygroups") && + ((!purple_prefs_get_bool(PREF_ROOT "/showoffline") && !is_group_online(group)) || + group->currentsize < 1)) node_remove(list, node); else add_node(node, list->ui_data); @@ -1726,9 +1727,12 @@ purple_prefs_add_int(PREF_ROOT "/position/y", 0); purple_prefs_add_bool(PREF_ROOT "/idletime", TRUE); 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_connect_callback(finch_blist_get_handle(), + PREF_ROOT "/emptygroups", redraw_blist, NULL); + purple_prefs_connect_callback(finch_blist_get_handle(), PREF_ROOT "/showoffline", redraw_blist, NULL); purple_prefs_connect_callback(finch_blist_get_handle(), PREF_ROOT "/sort_type", redraw_blist, NULL); @@ -2136,10 +2140,9 @@ } } -static void show_offline_cb(GntMenuItem *item, gpointer n) +static void toggle_pref_cb(GntMenuItem *item, gpointer n) { - purple_prefs_set_bool(PREF_ROOT "/showoffline", - !purple_prefs_get_bool(PREF_ROOT "/showoffline")); + purple_prefs_set_bool(n, !purple_prefs_get_bool(n)); } static void sort_blist_change_cb(GntMenuItem *item, gpointer n) @@ -2220,11 +2223,17 @@ gnt_menu_add_item(GNT_MENU(sub), item); gnt_menuitem_set_callback(GNT_MENU_ITEM(item), send_im_select, NULL); + item = gnt_menuitem_check_new(_("Show empty groups")); + gnt_menuitem_check_set_checked(GNT_MENU_ITEM_CHECK(item), + purple_prefs_get_bool(PREF_ROOT "/emptygroups")); + gnt_menu_add_item(GNT_MENU(sub), item); + gnt_menuitem_set_callback(GNT_MENU_ITEM(item), toggle_pref_cb, PREF_ROOT "/emptygroups"); + item = gnt_menuitem_check_new(_("Show offline buddies")); gnt_menuitem_check_set_checked(GNT_MENU_ITEM_CHECK(item), purple_prefs_get_bool(PREF_ROOT "/showoffline")); gnt_menu_add_item(GNT_MENU(sub), item); - gnt_menuitem_set_callback(GNT_MENU_ITEM(item), show_offline_cb, NULL); + gnt_menuitem_set_callback(GNT_MENU_ITEM(item), toggle_pref_cb, PREF_ROOT "/showoffline"); item = gnt_menuitem_new(_("Sort by status")); gnt_menu_add_item(GNT_MENU(sub), item); diff -r d6362d94e747 -r d4eebb5c3dbb finch/libgnt/gntcombobox.c --- a/finch/libgnt/gntcombobox.c Fri Jul 06 06:12:02 2007 +0000 +++ b/finch/libgnt/gntcombobox.c Mon Jul 09 06:14:27 2007 +0000 @@ -107,7 +107,7 @@ GntWidget *dd = GNT_COMBO_BOX(widget)->dropdown; gnt_widget_size_request(dd); widget->priv.height = 3; /* For now, a combobox will have border */ - widget->priv.width = MAX(10, dd->priv.width + 4); + widget->priv.width = MAX(10, dd->priv.width + 2); } } diff -r d6362d94e747 -r d4eebb5c3dbb finch/libgnt/gntfilesel.c --- a/finch/libgnt/gntfilesel.c Fri Jul 06 06:12:02 2007 +0000 +++ b/finch/libgnt/gntfilesel.c Mon Jul 09 06:14:27 2007 +0000 @@ -587,7 +587,7 @@ G_STRUCT_OFFSET(GntFileSelClass, file_selected), NULL, NULL, gnt_closure_marshal_VOID__STRING_STRING, - G_TYPE_NONE, 0); + G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); gnt_bindable_class_register_action(bindable, "toggle-tag", toggle_tag_selection, "t", NULL); gnt_bindable_class_register_action(bindable, "clear-tags", clear_tags, "c", NULL); @@ -634,6 +634,16 @@ return type; } +static void +select_activated_cb(GntWidget *button, GntFileSel *sel) +{ + char *path = gnt_file_sel_get_selected_file(sel); + char *file = g_path_get_basename(path); + g_signal_emit(sel, signals[SIG_FILE_SELECTED], 0, path, file); + g_free(file); + g_free(path); +} + GntWidget *gnt_file_sel_new(void) { GntWidget *widget = g_object_new(GNT_TYPE_FILE_SEL, NULL); @@ -653,6 +663,7 @@ gnt_tree_set_show_title(GNT_TREE(sel->files), TRUE); gnt_tree_set_col_width(GNT_TREE(sel->files), 0, 25); gnt_tree_set_col_width(GNT_TREE(sel->files), 1, 10); + gnt_tree_set_column_is_right_aligned(GNT_TREE(sel->files), 1, TRUE); g_signal_connect(G_OBJECT(sel->files), "selection_changed", G_CALLBACK(file_sel_changed), sel); /* The location entry */ @@ -662,6 +673,8 @@ sel->cancel = gnt_button_new("Cancel"); sel->select = gnt_button_new("Select"); + g_signal_connect(G_OBJECT(sel->select), "activate", G_CALLBACK(select_activated_cb), sel); + return widget; } diff -r d6362d94e747 -r d4eebb5c3dbb finch/libgnt/gntmain.c --- a/finch/libgnt/gntmain.c Fri Jul 06 06:12:02 2007 +0000 +++ b/finch/libgnt/gntmain.c Mon Jul 09 06:14:27 2007 +0000 @@ -352,6 +352,14 @@ static GntWidget *win = NULL; GntWidget *bbox, *button; + if (wm->menu) { + do { + gnt_widget_hide(GNT_WIDGET(wm->menu)); + if (wm->menu) + wm->menu = wm->menu->parentmenu; + } while (wm->menu); + } + if (win) goto raise; diff -r d6362d94e747 -r d4eebb5c3dbb finch/libgnt/gntmenu.c --- a/finch/libgnt/gntmenu.c Fri Jul 06 06:12:02 2007 +0000 +++ b/finch/libgnt/gntmenu.c Mon Jul 09 06:14:27 2007 +0000 @@ -23,6 +23,7 @@ #include "gntmenu.h" #include "gntmenuitemcheck.h" +#include #include enum @@ -30,11 +31,20 @@ SIGS = 1, }; +enum +{ + ITEM_TEXT = 0, + ITEM_TRIGGER, + ITEM_SUBMENU, + NUM_COLUMNS +}; + static GntTreeClass *parent_class = NULL; static void (*org_draw)(GntWidget *wid); static void (*org_destroy)(GntWidget *wid); static void (*org_map)(GntWidget *wid); +static void (*org_size_request)(GntWidget *wid); static gboolean (*org_key_pressed)(GntWidget *w, const char *t); static void @@ -75,21 +85,26 @@ widget->priv.height = 1; widget->priv.width = getmaxx(stdscr); } else { + org_size_request(widget); widget->priv.height = g_list_length(menu->list) + 2; - widget->priv.width = 25; /* XXX: */ } } static void menu_tree_add(GntMenu *menu, GntMenuItem *item, GntMenuItem *parent) { + char trigger[4] = "\0 )\0"; + + if ((trigger[1] = gnt_menuitem_get_trigger(item)) && trigger[1] != ' ') + trigger[0] = '('; + if (GNT_IS_MENU_ITEM_CHECK(item)) { gnt_tree_add_choice(GNT_TREE(menu), item, - gnt_tree_create_row(GNT_TREE(menu), item->text, " "), parent, NULL); + gnt_tree_create_row(GNT_TREE(menu), item->text, trigger, " "), parent, NULL); gnt_tree_set_choice(GNT_TREE(menu), item, gnt_menuitem_check_get_checked(GNT_MENU_ITEM_CHECK(item))); } else gnt_tree_add_row_last(GNT_TREE(menu), item, - gnt_tree_create_row(GNT_TREE(menu), item->text, item->submenu ? ">" : " "), parent); + gnt_tree_create_row(GNT_TREE(menu), item->text, trigger, item->submenu ? ">" : " "), parent); if (0 && item->submenu) { GntMenu *sub = GNT_MENU(item->submenu); @@ -101,6 +116,45 @@ } } +#define GET_VAL(ch) ((ch >= '0' && ch <= '9') ? (ch - '0') : (ch >= 'a' && ch <= 'z') ? (10 + ch - 'a') : 36) + +static void +assign_triggers(GntMenu *menu) +{ + GList *iter; + gboolean bools[37]; + + memset(bools, 0, sizeof(bools)); + bools[36] = 1; + + for (iter = menu->list; iter; iter = iter->next) { + GntMenuItem *item = iter->data; + char trigger = tolower(gnt_menuitem_get_trigger(item)); + if (trigger == '\0' || trigger == ' ') + continue; + bools[(int)GET_VAL(trigger)] = 1; + } + + for (iter = menu->list; iter; iter = iter->next) { + GntMenuItem *item = iter->data; + char trigger = gnt_menuitem_get_trigger(item); + const char *text = item->text; + if (trigger != '\0') + continue; + while (*text) { + char ch = tolower(*text++); + if (ch == ' ' || bools[(int)GET_VAL(ch)]) + continue; + trigger = ch; + break; + } + if (trigger == 0) + trigger = item->text[0]; + gnt_menuitem_set_trigger(item, trigger); + bools[(int)GET_VAL(trigger)] = 1; + } +} + static void gnt_menu_map(GntWidget *widget) { @@ -112,6 +166,8 @@ /* Populate the tree */ GList *iter; gnt_tree_remove_all(GNT_TREE(widget)); + /* Try to assign some trigger for the items */ + assign_triggers(menu); for (iter = menu->list; iter; iter = iter->next) { GntMenuItem *item = GNT_MENU_ITEM(iter->data); menu_tree_add(menu, item, NULL); @@ -149,6 +205,41 @@ } } +static GList* +find_item_with_trigger(GList *start, GList *end, char trigger) +{ + GList *iter; + for (iter = start; iter != (end ? end : NULL); iter = iter->next) { + if (gnt_menuitem_get_trigger(iter->data) == trigger) + return iter; + } + return NULL; +} + +static gboolean +check_for_trigger(GntMenu *menu, char trigger) +{ + /* check for a trigger key */ + GList *iter; + GList *nth = g_list_find(menu->list, gnt_tree_get_selection_data(GNT_TREE(menu))); + GList *find = find_item_with_trigger(nth->next, NULL, trigger); + if (!find) + find = find_item_with_trigger(menu->list, nth->next, trigger); + if (!find) + return FALSE; + if (find != nth) { + gnt_tree_set_selected(GNT_TREE(menu), find->data); + iter = find_item_with_trigger(find->next, NULL, trigger); + if (iter != NULL && iter != find) + return TRUE; + iter = find_item_with_trigger(menu->list, nth, trigger); + if (iter != NULL && iter != find) + return TRUE; + } + gnt_widget_activate(GNT_WIDGET(menu)); + return TRUE; +} + static gboolean gnt_menu_key_pressed(GntWidget *widget, const char *text) { @@ -189,6 +280,10 @@ return TRUE; } } else { + if (text[1] == '\0') { + if (check_for_trigger(menu, text[0])) + return TRUE; + } return org_key_pressed(widget, text); } @@ -260,6 +355,7 @@ org_map = wid_class->map; org_draw = wid_class->draw; org_key_pressed = wid_class->key_pressed; + org_size_request = wid_class->size_request; wid_class->destroy = gnt_menu_destroy; wid_class->draw = gnt_menu_draw; @@ -327,9 +423,11 @@ widget->priv.y = 0; } else { GNT_TREE(widget)->show_separator = FALSE; - _gnt_tree_init_internals(GNT_TREE(widget), 2); - gnt_tree_set_col_width(GNT_TREE(widget), 1, 1); /* The second column is to indicate that it has a submenu */ - gnt_tree_set_column_resizable(GNT_TREE(widget), 1, FALSE); + _gnt_tree_init_internals(GNT_TREE(widget), NUM_COLUMNS); + gnt_tree_set_col_width(GNT_TREE(widget), ITEM_TRIGGER, 3); + gnt_tree_set_column_resizable(GNT_TREE(widget), ITEM_TRIGGER, FALSE); + gnt_tree_set_col_width(GNT_TREE(widget), ITEM_SUBMENU, 1); + gnt_tree_set_column_resizable(GNT_TREE(widget), ITEM_SUBMENU, FALSE); GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_NO_BORDER); } diff -r d6362d94e747 -r d4eebb5c3dbb finch/libgnt/gntmenuitem.c --- a/finch/libgnt/gntmenuitem.c Fri Jul 06 06:12:02 2007 +0000 +++ b/finch/libgnt/gntmenuitem.c Mon Jul 09 06:14:27 2007 +0000 @@ -104,3 +104,13 @@ item->submenu = menu; } +void gnt_menuitem_set_trigger(GntMenuItem *item, char trigger) +{ + item->priv.trigger = trigger; +} + +char gnt_menuitem_get_trigger(GntMenuItem *item) +{ + return item->priv.trigger; +} + diff -r d6362d94e747 -r d4eebb5c3dbb finch/libgnt/gntmenuitem.h --- a/finch/libgnt/gntmenuitem.h Fri Jul 06 06:12:02 2007 +0000 +++ b/finch/libgnt/gntmenuitem.h Mon Jul 09 06:14:27 2007 +0000 @@ -52,6 +52,7 @@ /* These will be used to determine the position of the submenu */ int x; int y; + char trigger; }; typedef void (*GntMenuItemCallback)(GntMenuItem *item, gpointer data); @@ -114,6 +115,25 @@ */ void gnt_menuitem_set_submenu(GntMenuItem *item, GntMenu *menu); +/** + * Set a trigger key for the item. + * + * @param item The menuitem + * @param trigger The key that will trigger the item when the parent manu is visible + */ +void gnt_menuitem_set_trigger(GntMenuItem *item, char trigger); + +/** + * Get the trigger key for a menuitem. + * + * @param item The menuitem + * + * @return The trigger key for the menuitem. + * + * @see gnt_menuitem_set_trigger + */ +char gnt_menuitem_get_trigger(GntMenuItem *item); + G_END_DECLS #endif /* GNT_MENUITEM_H */ diff -r d6362d94e747 -r d4eebb5c3dbb finch/libgnt/gnttree.c --- a/finch/libgnt/gnttree.c Fri Jul 06 06:12:02 2007 +0000 +++ b/finch/libgnt/gnttree.c Mon Jul 09 06:14:27 2007 +0000 @@ -33,6 +33,7 @@ #define COLUMN_INVISIBLE(tree, index) (tree->columns[index].flags & GNT_TREE_COLUMN_INVISIBLE) #define BINARY_DATA(tree, index) (tree->columns[index].flags & GNT_TREE_COLUMN_BINARY_DATA) +#define RIGHT_ALIGNED(tree, index) (tree->columns[index].flags & GNT_TREE_COLUMN_RIGHT_ALIGNED) enum { @@ -86,13 +87,15 @@ int width; #define WIDTH(i) (tree->columns[i].width_ratio ? tree->columns[i].width_ratio : tree->columns[i].width) gnt_widget_get_size(GNT_WIDGET(tree), &width, NULL); + if (!GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_NO_BORDER)) + width -= 2; for (i = 0, total = 0; i < tree->ncol ; i++) { if (tree->columns[i].flags & GNT_TREE_COLUMN_INVISIBLE) continue; if (tree->columns[i].flags & GNT_TREE_COLUMN_FIXED_SIZE) - width -= WIDTH(i); + width -= WIDTH(i) + 1; else - total += WIDTH(i); + total += WIDTH(i) + 1; } if (total == 0) @@ -283,10 +286,6 @@ GList *iter; int i; gboolean notfirst = FALSE; - int lastvisible = tree->ncol; - - while (lastvisible && COLUMN_INVISIBLE(tree, lastvisible)) - lastvisible--; for (i = 0, iter = row->columns; i < tree->ncol && iter; i++, iter = iter->next) { @@ -308,10 +307,7 @@ len = gnt_util_onscreen_width(display, NULL); - if (i == lastvisible) - width = GNT_WIDGET(tree)->priv.width - gnt_util_onscreen_width(string->str, NULL); - else - width = tree->columns[i].width; + width = tree->columns[i].width; if (i == 0) { @@ -339,8 +335,7 @@ g_string_append_printf(string, "%*s", fl, ""); } len += fl; - } - else if (notfirst) + } else if (notfirst && tree->show_separator) g_string_append_c(string, '|'); else g_string_append_c(string, ' '); @@ -351,6 +346,11 @@ len = width - 1; cut = TRUE; } + + if (RIGHT_ALIGNED(tree, i) && len < tree->columns[i].width) { + g_string_append_printf(string, "%*s", width - len, ""); + } + text = gnt_util_onscreen_width_to_pointer(display, len - fl, NULL); string = g_string_append_len(string, display, text - display); if (cut) { /* ellipsis */ @@ -361,7 +361,7 @@ len++; } - if (len < tree->columns[i].width && iter->next) + if (!RIGHT_ALIGNED(tree, i) && len < tree->columns[i].width && iter->next) g_string_append_printf(string, "%*s", width - len, ""); } return g_string_free(string, FALSE); @@ -598,9 +598,13 @@ { GntTree *tree = GNT_TREE(widget); int i, width = 0; + width = 1 + 2 * (!GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_NO_BORDER)); for (i = 0; i < tree->ncol; i++) - if (!COLUMN_INVISIBLE(tree, i)) - width += tree->columns[i].width + 1; + if (!COLUMN_INVISIBLE(tree, i)) { + width = width + tree->columns[i].width; + if (tree->lastvisible != i) + width++; + } widget->priv.width = width; } } @@ -1502,6 +1506,7 @@ tree->ncol = col; tree->hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_tree_row); tree->columns = g_new0(struct _GntTreeColInfo, col); + tree->lastvisible = col - 1; while (col--) { tree->columns[col].width = 15; @@ -1647,9 +1652,14 @@ twidth = 1 + 2 * (!GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_NO_BORDER)); for (i = 0; i < tree->ncol; i++) { + if (tree->columns[i].flags & GNT_TREE_COLUMN_FIXED_SIZE) + widths[i] = tree->columns[i].width; gnt_tree_set_col_width(tree, i, widths[i]); - if (!COLUMN_INVISIBLE(tree, i)) - twidth += widths[i] + (tree->show_separator ? 1 : 0) + 1; + if (!COLUMN_INVISIBLE(tree, i)) { + twidth = twidth + widths[i]; + if (tree->lastvisible != i) + twidth += 1; + } } g_free(widths); @@ -1676,6 +1686,18 @@ { g_return_if_fail(col < tree->ncol); set_column_flag(tree, col, GNT_TREE_COLUMN_INVISIBLE, !vis); + if (vis) { + /* the column is visible */ + if (tree->lastvisible < col) + tree->lastvisible = col; + } else { + if (tree->lastvisible == col) + while (tree->lastvisible) { + tree->lastvisible--; + if (!COLUMN_INVISIBLE(tree, tree->lastvisible)) + break; + } + } } void gnt_tree_set_column_resizable(GntTree *tree, int col, gboolean res) @@ -1690,6 +1712,12 @@ set_column_flag(tree, col, GNT_TREE_COLUMN_FIXED_SIZE, bin); } +void gnt_tree_set_column_is_right_aligned(GntTree *tree, int col, gboolean right) +{ + g_return_if_fail(col < tree->ncol); + set_column_flag(tree, col, GNT_TREE_COLUMN_RIGHT_ALIGNED, right); +} + void gnt_tree_set_column_width_ratio(GntTree *tree, int cols[]) { int i; diff -r d6362d94e747 -r d4eebb5c3dbb finch/libgnt/gnttree.h --- a/finch/libgnt/gnttree.h Fri Jul 06 06:12:02 2007 +0000 +++ b/finch/libgnt/gnttree.h Mon Jul 09 06:14:27 2007 +0000 @@ -51,6 +51,7 @@ GNT_TREE_COLUMN_INVISIBLE = 1 << 0, GNT_TREE_COLUMN_FIXED_SIZE = 1 << 1, GNT_TREE_COLUMN_BINARY_DATA = 1 << 2, + GNT_TREE_COLUMN_RIGHT_ALIGNED = 1 << 3, } GntTreeColumnFlag; struct _GntTree @@ -86,6 +87,7 @@ int search_timeout; GCompareFunc compare; + int lastvisible; }; struct _GntTreeClass @@ -480,6 +482,15 @@ void gnt_tree_set_column_is_binary(GntTree *tree, int col, gboolean bin); /** + * Set whether text in a column should be right-aligned. + * + * @param tree The tree + * @param col The index of the column + * @param right @c TRUE if the text in the column should be right aligned + */ +void gnt_tree_set_column_is_right_aligned(GntTree *tree, int col, gboolean right); + +/** * Set column widths to use when calculating column widths after a tree * is resized. * diff -r d6362d94e747 -r d4eebb5c3dbb libpurple/account.c --- a/libpurple/account.c Fri Jul 06 06:12:02 2007 +0000 +++ b/libpurple/account.c Mon Jul 09 06:14:27 2007 +0000 @@ -2183,6 +2183,7 @@ purple_accounts_delete(PurpleAccount *account) { PurpleBlistNode *gnode, *cnode, *bnode; + GList *iter; g_return_if_fail(account != NULL); @@ -2231,6 +2232,14 @@ } } + /* Remove any open conversation for this account */ + for (iter = purple_get_conversations(); iter; ) { + PurpleConversation *conv = iter->data; + iter = iter->next; + if (purple_conversation_get_account(conv) == account) + purple_conversation_destroy(conv); + } + /* Remove this account's pounces */ purple_pounce_destroy_all_by_account(account); diff -r d6362d94e747 -r d4eebb5c3dbb libpurple/core.c --- a/libpurple/core.c Fri Jul 06 06:12:02 2007 +0000 +++ b/libpurple/core.c Mon Jul 09 06:14:27 2007 +0000 @@ -764,3 +764,12 @@ g_free(status_file); return TRUE; } + +GHashTable* purple_core_get_ui_info() { + PurpleCoreUiOps *ops = purple_core_get_ui_ops(); + + if(NULL == ops || NULL == ops->get_ui_info) + return NULL; + + return ops->get_ui_info(); +} diff -r d6362d94e747 -r d4eebb5c3dbb libpurple/core.h --- a/libpurple/core.h Fri Jul 06 06:12:02 2007 +0000 +++ b/libpurple/core.h Mon Jul 09 06:14:27 2007 +0000 @@ -34,11 +34,11 @@ void (*debug_ui_init)(void); /* Unfortunate necessity. */ void (*ui_init)(void); void (*quit)(void); + GHashTable* (*get_ui_info)(void); void (*_purple_reserved1)(void); void (*_purple_reserved2)(void); void (*_purple_reserved3)(void); - void (*_purple_reserved4)(void); } PurpleCoreUiOps; #ifdef __cplusplus @@ -133,6 +133,17 @@ */ gboolean purple_core_ensure_single_instance(void); +/** + * Returns a hashtable containing various information about the UI + * + * @return A GHashTable with strings for keys and values. This + * hash table must not be freed. + * + * @since 2.1.0 + * + */ +GHashTable* purple_core_get_ui_info(void); + #ifdef __cplusplus } #endif diff -r d6362d94e747 -r d4eebb5c3dbb libpurple/plugins/perl/common/Makefile.mingw --- a/libpurple/plugins/perl/common/Makefile.mingw Fri Jul 06 06:12:02 2007 +0000 +++ b/libpurple/plugins/perl/common/Makefile.mingw Mon Jul 09 06:14:27 2007 +0000 @@ -20,6 +20,7 @@ INCLUDE_PATHS += -I. \ -I$(PIDGIN_TREE_TOP) \ -I$(PURPLE_TOP) \ + -I$(PURPLE_TOP)/win32 \ -I$(GTK_TOP)/include \ -I$(GTK_TOP)/include/glib-2.0 \ -I$(GTK_TOP)/lib/glib-2.0/include \ diff -r d6362d94e747 -r d4eebb5c3dbb libpurple/plugins/perl/perl-common.h --- a/libpurple/plugins/perl/perl-common.h Fri Jul 06 06:12:02 2007 +0000 +++ b/libpurple/plugins/perl/perl-common.h Mon Jul 09 06:14:27 2007 +0000 @@ -11,7 +11,14 @@ /* XXX: perl defines it's own _ but I think it's safe to undef it */ #undef _ +/* Dirty hack to prevent the win32 libc compat stuff from interfering with the Perl internal stuff */ +#ifdef _WIN32 +#define _WIN32DEP_H_ +#endif #include "internal.h" +#ifdef _WIN32 +#undef _WIN32DEP_H_ +#endif #include "plugin.h" #include "value.h" diff -r d6362d94e747 -r d4eebb5c3dbb libpurple/protocols/jabber/iq.c --- a/libpurple/protocols/jabber/iq.c Fri Jul 06 06:12:02 2007 +0000 +++ b/libpurple/protocols/jabber/iq.c Mon Jul 09 06:14:27 2007 +0000 @@ -19,6 +19,7 @@ * */ #include "internal.h" +#include "core.h" #include "debug.h" #include "prefs.h" #include "util.h" @@ -250,6 +251,8 @@ type = xmlnode_get_attrib(packet, "type"); if(type && !strcmp(type, "get")) { + GHashTable *ui_info; + const char *ui_name = NULL, *ui_version = NULL; if(!purple_prefs_get_bool("/plugins/prpl/jabber/hide_os")) { struct utsname osinfo; @@ -268,9 +271,23 @@ query = xmlnode_get_child(iq->node, "query"); - /* TODO: ask the core for the version of libpurple and the name and version of the UI */ - xmlnode_insert_data(xmlnode_new_child(query, "name"), "libpurple", -1); - xmlnode_insert_data(xmlnode_new_child(query, "version"), VERSION, -1); + ui_info = purple_core_get_ui_info(); + + if(NULL != ui_info) { + ui_name = g_hash_table_lookup(ui_info, "name"); + ui_version = g_hash_table_lookup(ui_info, "version"); + } + + if(NULL != ui_name && NULL != ui_version) { + char *version_complete = g_strdup_printf("%s (libpurple " VERSION ")", ui_version); + xmlnode_insert_data(xmlnode_new_child(query, "name"), ui_name, -1); + xmlnode_insert_data(xmlnode_new_child(query, "version"), version_complete, -1); + g_free(version_complete); + } else { + xmlnode_insert_data(xmlnode_new_child(query, "name"), "libpurple", -1); + xmlnode_insert_data(xmlnode_new_child(query, "version"), VERSION, -1); + } + if(os) { xmlnode_insert_data(xmlnode_new_child(query, "os"), os, -1); g_free(os); diff -r d6362d94e747 -r d4eebb5c3dbb libpurple/win32/win32dep.c --- a/libpurple/win32/win32dep.c Fri Jul 06 06:12:02 2007 +0000 +++ b/libpurple/win32/win32dep.c Mon Jul 09 06:14:27 2007 +0000 @@ -43,8 +43,6 @@ /* * DEFINES & MACROS */ -#define _(x) gettext(x) - #define WIN32_PROXY_REGKEY "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings" /* For shfolder.dll */ diff -r d6362d94e747 -r d4eebb5c3dbb pidgin/gtkconv.c --- a/pidgin/gtkconv.c Fri Jul 06 06:12:02 2007 +0000 +++ b/pidgin/gtkconv.c Mon Jul 09 06:14:27 2007 +0000 @@ -4886,8 +4886,14 @@ gtkconv->convs = g_list_remove(gtkconv->convs, conv); /* Don't destroy ourselves until all our convos are gone */ - if (gtkconv->convs) + if (gtkconv->convs) { + /* Make sure the destroyed conversation is not the active one */ + if (gtkconv->active_conv == conv) { + gtkconv->active_conv = gtkconv->convs->data; + purple_conversation_update(gtkconv->active_conv, PURPLE_CONV_UPDATE_FEATURES); + } return; + } pidgin_conv_window_remove_gtkconv(gtkconv->win, gtkconv); @@ -8391,6 +8397,9 @@ #ifdef _WIN32 g_signal_connect(G_OBJECT(win->window), "show", G_CALLBACK(winpidgin_ensure_onscreen), win->window); + + if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/win32/minimize_new_convs")) + gtk_window_iconify(GTK_WINDOW(win->window)); #endif return win; diff -r d6362d94e747 -r d4eebb5c3dbb pidgin/gtkimhtml.c --- a/pidgin/gtkimhtml.c Fri Jul 06 06:12:02 2007 +0000 +++ b/pidgin/gtkimhtml.c Mon Jul 09 06:14:27 2007 +0000 @@ -28,8 +28,8 @@ #include #endif +#include "internal.h" #include "pidgin.h" -#include "internal.h" #include "debug.h" #include "util.h" @@ -220,7 +220,6 @@ clipboard_html_to_win32(char *html) { int length; GString *clipboard; - gchar *tmp; if (html == NULL) return NULL; @@ -228,13 +227,9 @@ length = strlen(html); clipboard = g_string_new ("Version:1.0\r\n"); g_string_append(clipboard, "StartHTML:0000000105\r\n"); - tmp = g_strdup_printf("EndHTML:%010d\r\n", 147 + length); - g_string_append(clipboard, tmp); - g_free(tmp); + g_string_append_printf(clipboard, "EndHTML:%010d\r\n", 147 + length); g_string_append(clipboard, "StartFragment:0000000127\r\n"); - tmp = g_strdup_printf("EndFragment:%010d\r\n", 127 + length); - g_string_append(clipboard, tmp); - g_free(tmp); + g_string_append_printf(clipboard, "EndFragment:%010d\r\n", 127 + length); g_string_append(clipboard, "\r\n"); g_string_append(clipboard, html); g_string_append(clipboard, "\r\n"); @@ -917,7 +912,7 @@ gtk_selection_data_set(selection_data, gdk_atom_intern("text/html", FALSE), 16, (const guchar *)selection, len); g_string_free(str, TRUE); #else - selection = clipboard_html_to_win32(imhtml->clipboard_html_string); + selection = clipboard_html_to_win32(html_clipboard); gtk_selection_data_set(selection_data, gdk_atom_intern("HTML Format", FALSE), 8, (const guchar *)selection, strlen(selection)); #endif g_free(selection); @@ -965,8 +960,8 @@ (GtkClipboardGetFunc)gtk_imhtml_clipboard_get, (GtkClipboardClearFunc)gtk_imhtml_clipboard_clear, G_OBJECT(imhtml)); - g_free(imhtml->clipboard_html_string); - g_free(imhtml->clipboard_text_string); + g_free(html_clipboard); + g_free(text_clipboard); imhtml->clipboard_html_string = gtk_imhtml_get_markup_range(imhtml, &start, &end); imhtml->clipboard_text_string = gtk_imhtml_get_text(imhtml, &start, &end); @@ -990,8 +985,8 @@ (GtkClipboardGetFunc)gtk_imhtml_clipboard_get, (GtkClipboardClearFunc)gtk_imhtml_clipboard_clear, G_OBJECT(imhtml)); - g_free(imhtml->clipboard_html_string); - g_free(imhtml->clipboard_text_string); + g_free(html_clipboard); + g_free(text_clipboard); imhtml->clipboard_html_string = gtk_imhtml_get_markup_range(imhtml, &start, &end); imhtml->clipboard_text_string = gtk_imhtml_get_text(imhtml, &start, &end); diff -r d6362d94e747 -r d4eebb5c3dbb pidgin/gtkmain.c --- a/pidgin/gtkmain.c Fri Jul 06 06:12:02 2007 +0000 +++ b/pidgin/gtkmain.c Mon Jul 09 06:14:27 2007 +0000 @@ -318,6 +318,8 @@ pidgin_docklet_init(); } +static GHashTable *ui_info = NULL; + static void pidgin_quit(void) { @@ -339,17 +341,32 @@ pidgin_xfers_uninit(); pidgin_debug_uninit(); + if(NULL != ui_info) + g_hash_table_destroy(ui_info); + /* and end it all... */ gtk_main_quit(); } +static GHashTable *pidgin_ui_get_info() +{ + if(NULL == ui_info) { + ui_info = g_hash_table_new(g_str_hash, g_str_equal); + + g_hash_table_insert(ui_info, "name", (char*)PIDGIN_NAME); + g_hash_table_insert(ui_info, "version", VERSION); + } + + return ui_info; +} + static PurpleCoreUiOps core_ops = { pidgin_prefs_init, debug_init, pidgin_ui_init, pidgin_quit, - NULL, + pidgin_ui_get_info, NULL, NULL, NULL diff -r d6362d94e747 -r d4eebb5c3dbb pidgin/gtkprefs.c --- a/pidgin/gtkprefs.c Fri Jul 06 06:12:02 2007 +0000 +++ b/pidgin/gtkprefs.c Mon Jul 09 06:14:27 2007 +0000 @@ -1017,6 +1017,8 @@ pidgin_prefs_checkbox(_("Use msn messenger style"), "/purple/conversations/msnstyle", vbox);//yaz #ifdef _WIN32 pidgin_prefs_checkbox(_("F_lash window when IMs are received"), PIDGIN_PREFS_ROOT "/win32/blink_im", vbox); + + pidgin_prefs_checkbox(_("Minimi_ze new conversation windows"), PIDGIN_PREFS_ROOT "/win32/minimize_new_convs", vbox); #endif #if GTK_CHECK_VERSION(2,4,0) diff -r d6362d94e747 -r d4eebb5c3dbb pidgin/plugins/perl/common/Makefile.mingw --- a/pidgin/plugins/perl/common/Makefile.mingw Fri Jul 06 06:12:02 2007 +0000 +++ b/pidgin/plugins/perl/common/Makefile.mingw Mon Jul 09 06:14:27 2007 +0000 @@ -18,6 +18,7 @@ INCLUDE_PATHS = -I. \ -I$(PIDGIN_TREE_TOP) \ -I$(PURPLE_TOP) \ + -I$(PURPLE_TOP)/win32 \ -I$(PIDGIN_TOP) \ -I$(PIDGIN_TOP)/win32 \ -I$(GTK_TOP)/include \ diff -r d6362d94e747 -r d4eebb5c3dbb pidgin/plugins/win32/transparency/win2ktrans.c --- a/pidgin/plugins/win32/transparency/win2ktrans.c Fri Jul 06 06:12:02 2007 +0000 +++ b/pidgin/plugins/win32/transparency/win2ktrans.c Mon Jul 09 06:14:27 2007 +0000 @@ -76,15 +76,6 @@ /* * CODE */ -static GtkWidget *wpurple_button(const char *text, const char *pref, GtkWidget *page) { - GtkWidget *button; - button = gtk_check_button_new_with_mnemonic(text); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), - purple_prefs_get_bool(pref)); - gtk_box_pack_start(GTK_BOX(page), button, FALSE, FALSE, 0); - gtk_widget_show(button); - return button; -} /* Set window transparency level */ static void set_wintrans(GtkWidget *window, int alpha, gboolean enabled, @@ -233,7 +224,8 @@ G_CALLBACK(focus_conv_win_cb), window); } -static void purple_conversation_delete(PurpleConversation *conv) { +static void +conversation_delete_cb(PurpleConversation *conv) { PidginWindow *win = pidgin_conv_get_window(PIDGIN_CONVERSATION(conv)); /* If it is the last conversation in the window, cleanup */ if (pidgin_conv_window_get_gtkconv_count(win) == 1) @@ -391,12 +383,35 @@ remove_convs_wintrans(FALSE); } -static void purple_new_conversation(PurpleConversation *conv) { +static void +conv_updated_cb(PurpleConversation *conv, PurpleConvUpdateType type) { + PidginConversation *pconv = PIDGIN_CONVERSATION(conv); + PidginWindow *win = pidgin_conv_get_window(pconv); + + if (type == PURPLE_CONV_UPDATE_UNSEEN && !pidgin_conv_is_hidden(pconv) + && pconv->unseen_state == PIDGIN_UNSEEN_NONE + && pidgin_conv_window_get_gtkconv_count(win) == 1) { + GtkWidget *window = win->window; + + set_conv_window_trans(NULL, win); + + if (g_signal_handler_find(G_OBJECT(window), G_SIGNAL_MATCH_FUNC, + 0, 0, NULL, G_CALLBACK(focus_conv_win_cb), NULL) == 0) { + g_signal_connect(G_OBJECT(window), "focus_in_event", + G_CALLBACK(focus_conv_win_cb), window); + g_signal_connect(G_OBJECT(window), "focus_out_event", + G_CALLBACK(focus_conv_win_cb), window); + } + } +} + +static void +new_conversation_cb(PurpleConversation *conv) { PidginWindow *win = pidgin_conv_get_window(PIDGIN_CONVERSATION(conv)); /* If it is the first conversation in the window, * add the sliders, and set transparency */ - if (pidgin_conv_window_get_gtkconv_count(win) == 1) { + if (!pidgin_conv_is_hidden(PIDGIN_CONVERSATION(conv)) && pidgin_conv_window_get_gtkconv_count(win) == 1) { GtkWidget *window = win->window; set_conv_window_trans(NULL, win); @@ -408,7 +423,8 @@ } } -static void blist_created_cb(PurpleBuddyList *purple_blist, gpointer data) { +static void +blist_created_cb(PurpleBuddyList *purple_blist, gpointer data) { if (blist) { if (purple_prefs_get_bool(OPT_WINTRANS_BL_ENABLED)) { set_wintrans(blist, @@ -477,17 +493,21 @@ purple_signal_connect(purple_conversations_get_handle(), "conversation-created", plugin, - PURPLE_CALLBACK(purple_new_conversation), NULL); + PURPLE_CALLBACK(new_conversation_cb), NULL); /* Set callback to remove window from the list, if the window is destroyed */ purple_signal_connect(purple_conversations_get_handle(), "deleting-conversation", plugin, - PURPLE_CALLBACK(purple_conversation_delete), NULL); + PURPLE_CALLBACK(conversation_delete_cb), NULL); purple_signal_connect(pidgin_conversations_get_handle(), "conversation-dragging", plugin, PURPLE_CALLBACK(set_conv_window_trans), NULL); + purple_signal_connect(purple_conversations_get_handle(), + "conversation-updated", plugin, + PURPLE_CALLBACK(conv_updated_cb), NULL); + update_existing_convs(); if (blist) @@ -531,7 +551,7 @@ /* IM Convo trans options */ imtransbox = pidgin_make_frame(ret, _("IM Conversation Windows")); - button = wpurple_button(_("_IM window transparency"), + button = pidgin_prefs_checkbox(_("_IM window transparency"), OPT_WINTRANS_IM_ENABLED, imtransbox); g_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(update_convs_wintrans), @@ -545,7 +565,7 @@ g_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(pidgin_toggle_sensitive), trans_box); - button = wpurple_button(_("_Show slider bar in IM window"), + button = pidgin_prefs_checkbox(_("_Show slider bar in IM window"), OPT_WINTRANS_IM_SLIDER, trans_box); g_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(update_convs_wintrans), @@ -555,7 +575,7 @@ _("Remove IM window transparency on focus"), OPT_WINTRANS_IM_ONFOCUS, trans_box); - button = wpurple_button(_("Always on top"), OPT_WINTRANS_IM_ONTOP, + button = pidgin_prefs_checkbox(_("Always on top"), OPT_WINTRANS_IM_ONTOP, trans_box); g_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(update_convs_wintrans), @@ -588,7 +608,7 @@ /* Buddy List trans options */ bltransbox = pidgin_make_frame (ret, _("Buddy List Window")); - button = wpurple_button(_("_Buddy List window transparency"), + button = pidgin_prefs_checkbox(_("_Buddy List window transparency"), OPT_WINTRANS_BL_ENABLED, bltransbox); g_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(set_blist_trans), @@ -603,7 +623,7 @@ button = pidgin_prefs_checkbox( _("Remove Buddy List window transparency on focus"), OPT_WINTRANS_BL_ONFOCUS, trans_box); - button = wpurple_button(_("Always on top"), OPT_WINTRANS_BL_ONTOP, + button = pidgin_prefs_checkbox(_("Always on top"), OPT_WINTRANS_BL_ONTOP, trans_box); g_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(set_blist_trans), diff -r d6362d94e747 -r d4eebb5c3dbb pidgin/win32/gtkwin32dep.c --- a/pidgin/win32/gtkwin32dep.c Fri Jul 06 06:12:02 2007 +0000 +++ b/pidgin/win32/gtkwin32dep.c Mon Jul 09 06:14:27 2007 +0000 @@ -36,6 +36,8 @@ #include #include +#include "internal.h" + #include "debug.h" #include "notify.h" diff -r d6362d94e747 -r d4eebb5c3dbb pidgin/win32/gtkwin32dep.h --- a/pidgin/win32/gtkwin32dep.h Fri Jul 06 06:12:02 2007 +0000 +++ b/pidgin/win32/gtkwin32dep.h Mon Jul 09 06:14:27 2007 +0000 @@ -45,5 +45,5 @@ void winpidgin_post_init(void); void winpidgin_cleanup(void); -#endif /* _WIN32DEP_H_ */ +#endif /* _GTKWIN32DEP_H_ */