# HG changeset patch # User Richard Laager # Date 1183241564 0 # Node ID fafb3af5aa126bf1e691443fda6b69d435f4fe94 # Parent 2aad33bb021d2d69bea210fee7705fd5bcd71525# Parent b2caad7bc71bce6c9ac4da228aa313490491a5bb propagate from branch 'im.pidgin.pidgin' (head ede31f4a584caeaede8c7c46cbece5a420b41050) to branch 'org.maemo.garage.pidgin.smiley-install' (head 5270b8d15c2c493dd6582ce904fd6072a53d469b) diff -r 2aad33bb021d -r fafb3af5aa12 COPYRIGHT --- a/COPYRIGHT Thu Jun 28 17:07:48 2007 +0000 +++ b/COPYRIGHT Sat Jun 30 22:12:44 2007 +0000 @@ -324,6 +324,7 @@ Joe Shaw Scott Shedden Dossy Shiobara +Michael Shkutkov Ettore Simone John Silvestri Craig Slusher diff -r 2aad33bb021d -r fafb3af5aa12 ChangeLog --- a/ChangeLog Thu Jun 28 17:07:48 2007 +0000 +++ b/ChangeLog Sat Jun 30 22:12:44 2007 +0000 @@ -11,6 +11,7 @@ notifications in chats * With the HTML logger, images in conversations are now saved. NOTE: Saved images are not yet displayed when loading logs. + * Added support for QIP logs to the Log Reader plugin (Michael Shkutkov) Pidgin: * Ensure only one copy of Pidgin is running with a given configuration diff -r 2aad33bb021d -r fafb3af5aa12 doc/notify-signals.dox --- a/doc/notify-signals.dox Thu Jun 28 17:07:48 2007 +0000 +++ b/doc/notify-signals.dox Sat Jun 30 22:12:44 2007 +0000 @@ -1,4 +1,4 @@ -/** @page conversation-signals Notification Signals +/** @page notify-signals Notification Signals @signals @signal displaying-userinfo diff -r 2aad33bb021d -r fafb3af5aa12 finch/finch.c --- a/finch/finch.c Thu Jun 28 17:07:48 2007 +0000 +++ b/finch/finch.c Sat Jun 30 22:12:44 2007 +0000 @@ -381,6 +381,7 @@ { signal(SIGPIPE, SIG_IGN); + g_set_prgname("Finch"); g_set_application_name(_("Finch")); /* Initialize the libpurple stuff */ diff -r 2aad33bb021d -r fafb3af5aa12 finch/gntaccount.c --- a/finch/gntaccount.c Thu Jun 28 17:07:48 2007 +0000 +++ b/finch/gntaccount.c Sat Jun 30 22:12:44 2007 +0000 @@ -645,8 +645,10 @@ GList *iter; GntWidget *box, *button; - if (accounts.window) + if (accounts.window) { + gnt_window_present(accounts.window); return; + } accounts.window = gnt_vbox_new(FALSE); gnt_box_set_toplevel(GNT_BOX(accounts.window), TRUE); diff -r 2aad33bb021d -r fafb3af5aa12 finch/gntblist.c --- a/finch/gntblist.c Thu Jun 28 17:07:48 2007 +0000 +++ b/finch/gntblist.c Sat Jun 30 22:12:44 2007 +0000 @@ -2250,8 +2250,10 @@ { if (ggblist == NULL) new_list(list); - else if (ggblist->window) + else if (ggblist->window) { + gnt_window_present(ggblist->window); return; + } ggblist->window = gnt_vwindow_new(FALSE); gnt_widget_set_name(ggblist->window, "buddylist"); diff -r 2aad33bb021d -r fafb3af5aa12 finch/gntdebug.c --- a/finch/gntdebug.c Thu Jun 28 17:07:48 2007 +0000 +++ b/finch/gntdebug.c Sat Jun 30 22:12:44 2007 +0000 @@ -221,56 +221,59 @@ void finch_debug_window_show() { + GntWidget *wid, *box; + debug.paused = FALSE; - if (debug.window == NULL) - { - GntWidget *wid, *box; - debug.window = gnt_vbox_new(FALSE); - gnt_box_set_toplevel(GNT_BOX(debug.window), TRUE); - gnt_box_set_title(GNT_BOX(debug.window), _("Debug Window")); - gnt_box_set_pad(GNT_BOX(debug.window), 0); - gnt_box_set_alignment(GNT_BOX(debug.window), GNT_ALIGN_MID); + if (debug.window) { + gnt_window_present(debug.window); + return; + } - debug.tview = gnt_text_view_new(); - gnt_box_add_widget(GNT_BOX(debug.window), debug.tview); - gnt_widget_set_size(debug.tview, - purple_prefs_get_int(PREF_ROOT "/size/width"), - purple_prefs_get_int(PREF_ROOT "/size/height")); - g_signal_connect(G_OBJECT(debug.tview), "size_changed", G_CALLBACK(size_changed_cb), NULL); + debug.window = gnt_vbox_new(FALSE); + gnt_box_set_toplevel(GNT_BOX(debug.window), TRUE); + gnt_box_set_title(GNT_BOX(debug.window), _("Debug Window")); + gnt_box_set_pad(GNT_BOX(debug.window), 0); + gnt_box_set_alignment(GNT_BOX(debug.window), GNT_ALIGN_MID); - gnt_box_add_widget(GNT_BOX(debug.window), gnt_line_new(FALSE)); + debug.tview = gnt_text_view_new(); + gnt_box_add_widget(GNT_BOX(debug.window), debug.tview); + gnt_widget_set_size(debug.tview, + purple_prefs_get_int(PREF_ROOT "/size/width"), + purple_prefs_get_int(PREF_ROOT "/size/height")); + g_signal_connect(G_OBJECT(debug.tview), "size_changed", G_CALLBACK(size_changed_cb), NULL); - box = gnt_hbox_new(FALSE); - gnt_box_set_alignment(GNT_BOX(box), GNT_ALIGN_MID); - gnt_box_set_fill(GNT_BOX(box), FALSE); + gnt_box_add_widget(GNT_BOX(debug.window), gnt_line_new(FALSE)); + + box = gnt_hbox_new(FALSE); + gnt_box_set_alignment(GNT_BOX(box), GNT_ALIGN_MID); + gnt_box_set_fill(GNT_BOX(box), FALSE); - /* XXX: Setting the GROW_Y for the following widgets don't make sense. But right now - * it's necessary to make the width of the debug window resizable ... like I said, - * it doesn't make sense. The bug is likely in the packing in gntbox.c. - */ - wid = gnt_button_new(_("Clear")); - g_signal_connect(G_OBJECT(wid), "activate", G_CALLBACK(clear_debug_win), debug.tview); - GNT_WIDGET_SET_FLAGS(wid, GNT_WIDGET_GROW_Y); - gnt_box_add_widget(GNT_BOX(box), wid); - - debug.search = gnt_entry_new(purple_prefs_get_string(PREF_ROOT "/filter")); - gnt_box_add_widget(GNT_BOX(box), gnt_label_new(_("Filter: "))); - gnt_box_add_widget(GNT_BOX(box), debug.search); - g_signal_connect(G_OBJECT(debug.search), "text_changed", G_CALLBACK(update_filter_string), NULL); + /* XXX: Setting the GROW_Y for the following widgets don't make sense. But right now + * it's necessary to make the width of the debug window resizable ... like I said, + * it doesn't make sense. The bug is likely in the packing in gntbox.c. + */ + wid = gnt_button_new(_("Clear")); + g_signal_connect(G_OBJECT(wid), "activate", G_CALLBACK(clear_debug_win), debug.tview); + GNT_WIDGET_SET_FLAGS(wid, GNT_WIDGET_GROW_Y); + gnt_box_add_widget(GNT_BOX(box), wid); - wid = gnt_check_box_new(_("Pause")); - g_signal_connect(G_OBJECT(wid), "toggled", G_CALLBACK(toggle_pause), NULL); - GNT_WIDGET_SET_FLAGS(wid, GNT_WIDGET_GROW_Y); - gnt_box_add_widget(GNT_BOX(box), wid); + debug.search = gnt_entry_new(purple_prefs_get_string(PREF_ROOT "/filter")); + gnt_box_add_widget(GNT_BOX(box), gnt_label_new(_("Filter: "))); + gnt_box_add_widget(GNT_BOX(box), debug.search); + g_signal_connect(G_OBJECT(debug.search), "text_changed", G_CALLBACK(update_filter_string), NULL); - gnt_box_add_widget(GNT_BOX(debug.window), box); - GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_GROW_Y); + wid = gnt_check_box_new(_("Pause")); + g_signal_connect(G_OBJECT(wid), "toggled", G_CALLBACK(toggle_pause), NULL); + GNT_WIDGET_SET_FLAGS(wid, GNT_WIDGET_GROW_Y); + gnt_box_add_widget(GNT_BOX(box), wid); - gnt_widget_set_name(debug.window, "debug-window"); + gnt_box_add_widget(GNT_BOX(debug.window), box); + GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_GROW_Y); - g_signal_connect(G_OBJECT(debug.window), "destroy", G_CALLBACK(reset_debug_win), NULL); - gnt_text_view_attach_scroll_widget(GNT_TEXT_VIEW(debug.tview), debug.window); - } + gnt_widget_set_name(debug.window, "debug-window"); + + g_signal_connect(G_OBJECT(debug.window), "destroy", G_CALLBACK(reset_debug_win), NULL); + gnt_text_view_attach_scroll_widget(GNT_TEXT_VIEW(debug.tview), debug.window); gnt_widget_show(debug.window); } diff -r 2aad33bb021d -r fafb3af5aa12 finch/gntft.c --- a/finch/gntft.c Thu Jun 28 17:07:48 2007 +0000 +++ b/finch/gntft.c Sat Jun 30 22:12:44 2007 +0000 @@ -262,6 +262,8 @@ { if (xfer_dialog == NULL) finch_xfer_dialog_new(); + else + gnt_window_present(xfer_dialog->window); } void diff -r 2aad33bb021d -r fafb3af5aa12 finch/gntnotify.c --- a/finch/gntnotify.c Thu Jun 28 17:07:48 2007 +0000 +++ b/finch/gntnotify.c Sat Jun 30 22:12:44 2007 +0000 @@ -304,7 +304,7 @@ PurpleAccount *account = g_object_get_data(G_OBJECT(widget), "notify-account"); gpointer data = g_object_get_data(G_OBJECT(widget), "notify-data"); - list = gnt_tree_get_selection_text_list(GNT_TREE(widget)); + list = gnt_tree_get_selection_text_list(GNT_TREE(g_object_get_data(G_OBJECT(widget), "notify-tree"))); b->callback(purple_account_get_connection(account), list, data); g_list_foreach(list, (GFunc)g_free, NULL); @@ -335,23 +335,31 @@ { GntWidget *window, *tree, *box, *button; GList *iter; + int columns, i; window = gnt_vbox_new(FALSE); gnt_box_set_toplevel(GNT_BOX(window), TRUE); gnt_box_set_title(GNT_BOX(window), title); - gnt_box_set_fill(GNT_BOX(window), FALSE); + gnt_box_set_fill(GNT_BOX(window), TRUE); gnt_box_set_pad(GNT_BOX(window), 0); gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID); - gnt_box_add_widget(GNT_BOX(window), + if (primary) + gnt_box_add_widget(GNT_BOX(window), gnt_label_new_with_format(primary, GNT_TEXT_FLAG_BOLD)); - gnt_box_add_widget(GNT_BOX(window), + if (secondary) + gnt_box_add_widget(GNT_BOX(window), gnt_label_new_with_format(secondary, GNT_TEXT_FLAG_NORMAL)); - tree = gnt_tree_new_with_columns(g_list_length(results->columns)); + columns = purple_notify_searchresults_get_columns_count(results); + tree = gnt_tree_new_with_columns(columns); gnt_tree_set_show_title(GNT_TREE(tree), TRUE); gnt_box_add_widget(GNT_BOX(window), tree); + for (i = 0; i < columns; i++) + gnt_tree_set_column_title(GNT_TREE(tree), i, + purple_notify_searchresults_column_get_title(results, i)); + box = gnt_hbox_new(TRUE); for (iter = results->buttons; iter; iter = iter->next) @@ -389,7 +397,8 @@ button = gnt_button_new(text); g_object_set_data(G_OBJECT(button), "notify-account", purple_connection_get_account(gc)); g_object_set_data(G_OBJECT(button), "notify-data", data); - g_signal_connect_swapped(G_OBJECT(button), "activate", + g_object_set_data(G_OBJECT(button), "notify-tree", tree); + g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(notify_button_activated), b); gnt_box_add_widget(GNT_BOX(box), button); diff -r 2aad33bb021d -r fafb3af5aa12 finch/gntplugin.c --- a/finch/gntplugin.c Thu Jun 28 17:07:48 2007 +0000 +++ b/finch/gntplugin.c Sat Jun 30 22:12:44 2007 +0000 @@ -242,8 +242,10 @@ GList *iter; GList *seen; - if (plugins.window) + if (plugins.window) { + gnt_window_present(plugins.window); return; + } purple_plugins_probe(G_MODULE_SUFFIX); diff -r 2aad33bb021d -r fafb3af5aa12 finch/gntpounce.c --- a/finch/gntpounce.c Thu Jun 28 17:07:48 2007 +0000 +++ b/finch/gntpounce.c Sat Jun 30 22:12:44 2007 +0000 @@ -672,6 +672,7 @@ GntWidget *win; if (pounces_manager != NULL) { + gnt_window_present(pounces_manager->window); return; } diff -r 2aad33bb021d -r fafb3af5aa12 finch/gntprefs.c --- a/finch/gntprefs.c Thu Jun 28 17:07:48 2007 +0000 +++ b/finch/gntprefs.c Sat Jun 30 22:12:44 2007 +0000 @@ -30,9 +30,16 @@ #include "gntprefs.h" #include "gntrequest.h" +#include "gnt.h" +#include "gntwidget.h" + #include -static GList *freestrings; /* strings to be freed when the pref-window is closed */ +static struct { + GList *freestrings; /* strings to be freed when the pref-window is closed */ + gboolean showing; + GntWidget *window; +} pref_request; void finch_prefs_init() { @@ -98,7 +105,7 @@ str = g_strdup_printf("%ld", purple_savedstatus_get_creation_time(iter->data)); list = g_list_append(list, (char*)purple_savedstatus_get_title(iter->data)); list = g_list_append(list, str); - freestrings = g_list_prepend(freestrings, str); + pref_request.freestrings = g_list_prepend(pref_request.freestrings, str); } return list; } @@ -190,22 +197,22 @@ {PURPLE_PREF_NONE, NULL, NULL, NULL}, }; -/* XXX: Translate after the freeze */ static Prefs idle[] = { - {PURPLE_PREF_STRING, "/purple/away/idle_reporting", "Report Idle time", get_idle_options}, - {PURPLE_PREF_BOOLEAN, "/purple/away/away_when_idle", "Change status when idle", NULL}, - {PURPLE_PREF_INT, "/purple/away/mins_before_away", "Minutes before changing status", NULL}, - {PURPLE_PREF_INT, "/purple/savedstatus/idleaway", "Change status to", get_status_titles}, + {PURPLE_PREF_STRING, "/purple/away/idle_reporting", N_("Report Idle time"), get_idle_options}, + {PURPLE_PREF_BOOLEAN, "/purple/away/away_when_idle", N_("Change status when idle"), NULL}, + {PURPLE_PREF_INT, "/purple/away/mins_before_away", N_("Minutes before changing status"), NULL}, + {PURPLE_PREF_INT, "/purple/savedstatus/idleaway", N_("Change status to"), get_status_titles}, {PURPLE_PREF_NONE, NULL, NULL, NULL}, }; static void free_strings() { - g_list_foreach(freestrings, (GFunc)g_free, NULL); - g_list_free(freestrings); - freestrings = NULL; + g_list_foreach(pref_request.freestrings, (GFunc)g_free, NULL); + g_list_free(pref_request.freestrings); + pref_request.freestrings = NULL; + pref_request.showing = FALSE; } static void @@ -236,6 +243,11 @@ { PurpleRequestFields *fields; + if (pref_request.showing) { + gnt_window_present(pref_request.window); + return; + } + fields = purple_request_fields_new(); add_pref_group(fields, _("Buddy List"), blist); @@ -243,7 +255,8 @@ add_pref_group(fields, _("Logging"), logging); add_pref_group(fields, _("Idle"), idle); - purple_request_fields(NULL, _("Preferences"), NULL, NULL, fields, + pref_request.showing = TRUE; + pref_request.window = purple_request_fields(NULL, _("Preferences"), NULL, NULL, fields, _("Save"), G_CALLBACK(save_cb), _("Cancel"), free_strings, NULL, NULL, NULL, NULL); diff -r 2aad33bb021d -r fafb3af5aa12 finch/gntrequest.c --- a/finch/gntrequest.c Thu Jun 28 17:07:48 2007 +0000 +++ b/finch/gntrequest.c Sat Jun 30 22:12:44 2007 +0000 @@ -67,8 +67,35 @@ return window; } +/** + * If the window is closed by the wm (ie, without triggering any of + * the buttons, then do some default callback. + */ +static void +setup_default_callback(GntWidget *window, gpointer default_cb, gpointer data) +{ + g_object_set_data(G_OBJECT(window), "default-callback", default_cb); + g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(default_cb), data); +} + +static void +action_performed(GntWidget *button, gpointer data) +{ + g_signal_handlers_disconnect_matched(data, G_SIGNAL_MATCH_FUNC, + 0, 0, NULL, + g_object_get_data(data, "default-callback"), + NULL); +} + +/** + * window: this is the window + * userdata: the userdata to pass to the primary callbacks + * cb: the callback + * data: data for the callback + * (text, primary-callback) pairs, ended by a NULL + */ static GntWidget * -setup_button_box(gpointer userdata, gpointer cb, gpointer data, ...) +setup_button_box(GntWidget *win, gpointer userdata, gpointer cb, gpointer data, ...) { GntWidget *box, *button; va_list list; @@ -86,6 +113,7 @@ gnt_box_add_widget(GNT_BOX(box), button); g_object_set_data(G_OBJECT(button), "activate-callback", callback); g_object_set_data(G_OBJECT(button), "activate-userdata", userdata); + g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(action_performed), win); g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(cb), data); } @@ -127,10 +155,11 @@ gnt_entry_set_masked(GNT_ENTRY(entry), TRUE); gnt_box_add_widget(GNT_BOX(window), entry); - box = setup_button_box(user_data, notify_input_cb, entry, + box = setup_button_box(window, user_data, notify_input_cb, entry, ok_text, ok_cb, cancel_text, cancel_cb, NULL); gnt_box_add_widget(GNT_BOX(window), box); + setup_default_callback(window, cancel_cb, user_data); gnt_widget_show(window); return window; @@ -189,10 +218,11 @@ } gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), GINT_TO_POINTER(default_value + 1)); - box = setup_button_box(user_data, request_choice_cb, combo, + box = setup_button_box(window, user_data, request_choice_cb, combo, ok_text, ok_cb, cancel_text, cancel_cb, NULL); gnt_box_add_widget(GNT_BOX(window), box); + setup_default_callback(window, cancel_cb, user_data); gnt_widget_show(window); return window; @@ -538,10 +568,11 @@ } gnt_box_add_widget(GNT_BOX(window), box); - box = setup_button_box(userdata, request_fields_cb, allfields, + box = setup_button_box(window, userdata, request_fields_cb, allfields, ok, ok_cb, cancel, cancel_cb, NULL); gnt_box_add_widget(GNT_BOX(window), box); + setup_default_callback(window, cancel_cb, userdata); gnt_widget_show(window); g_object_set_data(G_OBJECT(window), "fields", allfields); diff -r 2aad33bb021d -r fafb3af5aa12 finch/gntstatus.c --- a/finch/gntstatus.c Thu Jun 28 17:07:48 2007 +0000 +++ b/finch/gntstatus.c Sat Jun 30 22:12:44 2007 +0000 @@ -163,8 +163,10 @@ void finch_savedstatus_show_all() { GntWidget *window, *tree, *box, *button; - if (statuses.window) + if (statuses.window) { + gnt_window_present(statuses.window); return; + } statuses.window = window = gnt_vbox_new(FALSE); gnt_box_set_toplevel(GNT_BOX(window), TRUE); diff -r 2aad33bb021d -r fafb3af5aa12 finch/libgnt/Makefile.am --- a/finch/libgnt/Makefile.am Thu Jun 28 17:07:48 2007 +0000 +++ b/finch/libgnt/Makefile.am Sat Jun 30 22:12:44 2007 +0000 @@ -26,6 +26,7 @@ gntmenu.c \ gntmenuitem.c \ gntmenuitemcheck.c \ + gntslider.c \ gntstyle.c \ gnttextview.c \ gnttree.c \ @@ -53,6 +54,7 @@ gntmenu.h \ gntmenuitem.h \ gntmenuitemcheck.h \ + gntslider.h \ gntstyle.h \ gnttextview.h \ gnttree.h \ diff -r 2aad33bb021d -r fafb3af5aa12 finch/libgnt/gntentry.c --- a/finch/libgnt/gntentry.c Thu Jun 28 17:07:48 2007 +0000 +++ b/finch/libgnt/gntentry.c Sat Jun 30 22:12:44 2007 +0000 @@ -179,7 +179,7 @@ stop = gnt_util_onscreen_width(entry->scroll, entry->end); if (stop < widget->priv.width) - whline(widget->window, ENTRY_CHAR, widget->priv.width - stop); + mvwhline(widget->window, 0, stop, ENTRY_CHAR, widget->priv.width - stop); if (focus) mvwchgat(widget->window, 0, gnt_util_onscreen_width(entry->scroll, entry->cursor), diff -r 2aad33bb021d -r fafb3af5aa12 finch/libgnt/gntlabel.c --- a/finch/libgnt/gntlabel.c Thu Jun 28 17:07:48 2007 +0000 +++ b/finch/libgnt/gntlabel.c Sat Jun 30 22:12:44 2007 +0000 @@ -138,8 +138,7 @@ if (GNT_WIDGET(label)->window) { - gnt_widget_hide(GNT_WIDGET(label)); - gnt_label_size_request(GNT_WIDGET(label)); + werase(GNT_WIDGET(label)->window); gnt_widget_draw(GNT_WIDGET(label)); } } diff -r 2aad33bb021d -r fafb3af5aa12 finch/libgnt/gntmain.c --- a/finch/libgnt/gntmain.c Thu Jun 28 17:07:48 2007 +0000 +++ b/finch/libgnt/gntmain.c Sat Jun 30 22:12:44 2007 +0000 @@ -488,8 +488,12 @@ * Stuff for 'window management' * *********************************/ -void gnt_window_present(GntWidget *window) { - gnt_wm_raise_window(wm, window); +void gnt_window_present(GntWidget *window) +{ + if (wm->event_stack) + gnt_wm_raise_window(wm, window); + else + gnt_widget_set_urgent(window); } void gnt_screen_occupy(GntWidget *widget) diff -r 2aad33bb021d -r fafb3af5aa12 finch/libgnt/gntslider.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/finch/libgnt/gntslider.c Sat Jun 30 22:12:44 2007 +0000 @@ -0,0 +1,277 @@ +/** + * GNT - The GLib Ncurses Toolkit + * + * GNT is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This library 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 + */ + +#include "gntcolors.h" +#include "gntkeys.h" +#include "gntslider.h" +#include "gntstyle.h" + +enum +{ + SIG_VALUE_CHANGED, + SIGS, +}; + +static guint signals[SIGS] = { 0 }; + +static GntWidgetClass *parent_class = NULL; + +/* returns TRUE if the value was changed */ +static gboolean +sanitize_value(GntSlider *slider) +{ + if (slider->current < slider->min) + slider->current = slider->min; + else if (slider->current > slider->max) + slider->current = slider->max; + else + return FALSE; + return TRUE; +} + +static void +redraw_slider(GntSlider *slider) +{ + GntWidget *widget = GNT_WIDGET(slider); + if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_MAPPED)) + gnt_widget_draw(widget); +} + +static void +slider_value_changed(GntSlider *slider) +{ + g_signal_emit(slider, signals[SIG_VALUE_CHANGED], 0, slider->current); +} + +static void +gnt_slider_draw(GntWidget *widget) +{ + GntSlider *slider = GNT_SLIDER(widget); + int attr = 0; + int position, size = 0; + + if (slider->vertical) + size = widget->priv.height; + else + size = widget->priv.width; + + if (gnt_widget_has_focus(widget)) + attr |= GNT_COLOR_HIGHLIGHT; + else + attr |= GNT_COLOR_HIGHLIGHT_D; + + if (slider->max != slider->min) + position = ((size - 1) * (slider->current - slider->min)) / (slider->max - slider->min); + else + position = 0; + if (slider->vertical) { + mvwvline(widget->window, size-position, 0, ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL) | A_BOLD, + position); + mvwvline(widget->window, 0, 0, ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL), + size-position); + } else { + mvwhline(widget->window, 0, 0, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL) | A_BOLD, + position); + mvwhline(widget->window, 0, position, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL), + size - position); + } + + mvwaddch(widget->window, + slider->vertical ? (size - position - 1) : 0, + slider->vertical ? 0 : position, + ACS_CKBOARD | COLOR_PAIR(attr)); +} + +static void +gnt_slider_size_request(GntWidget *widget) +{ + if (GNT_SLIDER(widget)->vertical) { + widget->priv.width = 1; + widget->priv.height = 5; + } else { + widget->priv.width = 5; + widget->priv.height = 1; + } +} + +static void +gnt_slider_map(GntWidget *widget) +{ + if (widget->priv.width == 0 || widget->priv.height == 0) + gnt_widget_size_request(widget); + GNTDEBUG; +} + +static gboolean +step_back(GntBindable *bindable, GList *null) +{ + GntSlider *slider = GNT_SLIDER(bindable); + if (slider->current <= slider->min) + return FALSE; + gnt_slider_advance_step(slider, -1); + return TRUE; +} + +static gboolean +step_forward(GntBindable *bindable, GList *list) +{ + GntSlider *slider = GNT_SLIDER(bindable); + if (slider->current >= slider->max) + return FALSE; + gnt_slider_advance_step(slider, 1); + return TRUE; +} + +static void +gnt_slider_class_init(GntSliderClass *klass) +{ + GntBindableClass *bindable = GNT_BINDABLE_CLASS(klass); + parent_class = GNT_WIDGET_CLASS(klass); + parent_class->draw = gnt_slider_draw; + parent_class->map = gnt_slider_map; + parent_class->size_request = gnt_slider_size_request; + + klass->changed = NULL; + + signals[SIG_VALUE_CHANGED] = + g_signal_new("changed", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GntSliderClass, changed), + NULL, NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + + gnt_bindable_class_register_action(bindable, "step-backward", step_back, GNT_KEY_LEFT, NULL); + gnt_bindable_register_binding(bindable, "step-backward", GNT_KEY_DOWN, NULL); + gnt_bindable_class_register_action(bindable, "step-forward", step_forward, GNT_KEY_RIGHT, NULL); + gnt_bindable_register_binding(bindable, "step-forward", GNT_KEY_UP, NULL); + + /* XXX: how would home/end work? */ + + gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass)); +} + +static void +gnt_slider_init(GTypeInstance *instance, gpointer class) +{ + GntWidget *widget = GNT_WIDGET(instance); + GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_SHADOW | GNT_WIDGET_NO_BORDER | GNT_WIDGET_CAN_TAKE_FOCUS); + widget->priv.minw = 1; + widget->priv.minh = 1; + GNTDEBUG; +} + +/****************************************************************************** + * GntSlider API + *****************************************************************************/ +GType +gnt_slider_get_gtype(void) +{ + static GType type = 0; + + if(type == 0) + { + static const GTypeInfo info = { + sizeof(GntSliderClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)gnt_slider_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(GntSlider), + 0, /* n_preallocs */ + gnt_slider_init, /* instance_init */ + NULL /* value_table */ + }; + + type = g_type_register_static(GNT_TYPE_WIDGET, + "GntSlider", + &info, 0); + } + + return type; +} + +GntWidget *gnt_slider_new(gboolean vertical, int max, int min) +{ + GntWidget *widget = g_object_new(GNT_TYPE_SLIDER, NULL); + GntSlider *slider = GNT_SLIDER(widget); + + slider->vertical = vertical; + + if (vertical) { + GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_Y); + } else { + GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_X); + } + + gnt_slider_set_range(slider, max, min); + slider->step = 1; + + return widget; +} + +void gnt_slider_set_value(GntSlider *slider, int value) +{ + if (slider->current == value) + return; + slider->current = value; + sanitize_value(slider); + redraw_slider(slider); + slider_value_changed(slider); +} + +int gnt_slider_advance_step(GntSlider *slider, int steps) +{ + slider->current += steps * slider->step; + sanitize_value(slider); + redraw_slider(slider); + slider_value_changed(slider); + return slider->current; +} + +void gnt_slider_set_step(GntSlider *slider, int step) +{ + slider->step = step; +} + +void gnt_slider_set_range(GntSlider *slider, int max, int min) +{ + slider->max = MAX(max, min); + slider->min = MIN(max, min); + sanitize_value(slider); +} + +static void +update_label(GntSlider *slider, int current_value, GntLabel *label) +{ + char value[256]; + g_snprintf(value, sizeof(value), "%d/%d", current_value, slider->max); + gnt_label_set_text(label, value); +} + +void gnt_slider_reflect_label(GntSlider *slider, GntLabel *label) +{ + g_signal_connect(G_OBJECT(slider), "changed", G_CALLBACK(update_label), label); +} + diff -r 2aad33bb021d -r fafb3af5aa12 finch/libgnt/gntslider.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/finch/libgnt/gntslider.h Sat Jun 30 22:12:44 2007 +0000 @@ -0,0 +1,139 @@ +/** + * @file gntslider.h Slider API + * @ingroup gnt + */ +/* + * GNT - The GLib Ncurses Toolkit + * + * GNT is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This library 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 + */ + +#ifndef GNT_SLIDER_H +#define GNT_SLIDER_H + +#include "gntwidget.h" +#include "gnt.h" +#include "gntlabel.h" + +#define GNT_TYPE_SLIDER (gnt_slider_get_gtype()) +#define GNT_SLIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_SLIDER, GntSlider)) +#define GNT_SLIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_SLIDER, GntSliderClass)) +#define GNT_IS_SLIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_SLIDER)) +#define GNT_IS_SLIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_SLIDER)) +#define GNT_SLIDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_SLIDER, GntSliderClass)) + +#define GNT_SLIDER_FLAGS(obj) (GNT_SLIDER(obj)->priv.flags) +#define GNT_SLIDER_SET_FLAGS(obj, flags) (GNT_SLIDER_FLAGS(obj) |= flags) +#define GNT_SLIDER_UNSET_FLAGS(obj, flags) (GNT_SLIDER_FLAGS(obj) &= ~(flags)) + +typedef struct _GntSlider GntSlider; +typedef struct _GntSliderPriv GntSliderPriv; +typedef struct _GntSliderClass GntSliderClass; + +struct _GntSlider +{ + GntWidget parent; + + gboolean vertical; + + int max; /* maximum value */ + int min; /* minimum value */ + int step; /* amount to change at each step */ + int current; /* current value */ +}; + +struct _GntSliderClass +{ + GntWidgetClass parent; + + void (*changed)(GntSlider *slider, int); + void (*gnt_reserved1)(void); + void (*gnt_reserved2)(void); + void (*gnt_reserved3)(void); + void (*gnt_reserved4)(void); +}; + +G_BEGIN_DECLS + +/** + * @return The GType for GntSlider + */ +GType gnt_slider_get_gtype(void); + +#define gnt_hslider_new(max, min) gnt_slider_new(FALSE, max, min) +#define gnt_vslider_new(max, min) gnt_slider_new(TRUE, max, min) + +/** + * Create a new slider. + * + * @param orient A vertical slider is created if @c TRUE, otherwise the slider is horizontal. + * @param max The maximum value for the slider + * @param min The minimum value for the slider + * + * @return The newly created slider + */ +GntWidget * gnt_slider_new(gboolean orient, int max, int min); + +/** + * Set the range of the slider. + * + * @param slider The slider + * @param max The maximum value + * @param min The minimum value + */ +void gnt_slider_set_range(GntSlider *slider, int max, int min); + +/** + * Sets the amount of change at each step. + * + * @param slider The slider + * @param step The amount for each ste + */ +void gnt_slider_set_step(GntSlider *slider, int step); + +/** + * Advance the slider forward or backward. + * + * @param slider The slider + * @param steps The number of amounts to change, positive to change + * forward, negative to change backward + * + * @return The value of the slider after the change + */ +int gnt_slider_advance_step(GntSlider *slider, int steps); + +/** + * Set the current value for the slider. + * + * @param slider The slider + * @param value The current value + */ +void gnt_slider_set_value(GntSlider *slider, int value); + +/** + * Update a label with the value of the slider whenever the value changes. + * + * @param slider The slider + * @param label The label to update + */ +void gnt_slider_reflect_label(GntSlider *slider, GntLabel *label); + +G_END_DECLS + +#endif /* GNT_SLIDER_H */ diff -r 2aad33bb021d -r fafb3af5aa12 finch/libgnt/gntstyle.c --- a/finch/libgnt/gntstyle.c Thu Jun 28 17:07:48 2007 +0000 +++ b/finch/libgnt/gntstyle.c Sat Jun 30 22:12:44 2007 +0000 @@ -269,7 +269,8 @@ { GError *error = NULL; gsize nkeys; - char **keys = g_key_file_get_keys(kfile, "general", &nkeys, &error); + const char *prgname = g_get_prgname(); + char **keys = NULL; int i; struct { @@ -282,6 +283,14 @@ {"remember_position", GNT_STYLE_REMPOS}, {NULL, 0}}; + if (prgname && *prgname) + keys = g_key_file_get_keys(kfile, prgname, &nkeys, NULL); + + if (keys == NULL) { + prgname = "general"; + keys = g_key_file_get_keys(kfile, prgname, &nkeys, &error); + } + if (error) { g_printerr("GntStyle: %s\n", error->message); @@ -292,7 +301,7 @@ for (i = 0; styles[i].style; i++) { str_styles[styles[i].en] = - g_key_file_get_string(kfile, "general", styles[i].style, NULL); + g_key_file_get_string(kfile, prgname, styles[i].style, NULL); } } g_strfreev(keys); diff -r 2aad33bb021d -r fafb3af5aa12 finch/libgnt/gnttree.c --- a/finch/libgnt/gnttree.c Thu Jun 28 17:07:48 2007 +0000 +++ b/finch/libgnt/gnttree.c Sat Jun 30 22:12:44 2007 +0000 @@ -1526,6 +1526,12 @@ tree->columns[col].width = width; } +void gnt_tree_set_column_title(GntTree *tree, int index, const char *title) +{ + g_free(tree->columns[index].title); + tree->columns[index].title = g_strdup(title); +} + void gnt_tree_set_column_titles(GntTree *tree, ...) { int i; diff -r 2aad33bb021d -r fafb3af5aa12 finch/libgnt/gnttree.h --- a/finch/libgnt/gnttree.h Thu Jun 28 17:07:48 2007 +0000 +++ b/finch/libgnt/gnttree.h Sat Jun 30 22:12:44 2007 +0000 @@ -302,6 +302,15 @@ void gnt_tree_set_col_width(GntTree *tree, int col, int width); /** + * Set the title for a column. + * + * @param tree The tree + * @param index The index of the column + * @param title The title for the column + */ +void gnt_tree_set_column_title(GntTree *tree, int index, const char *title); + +/** * * @param tree */ diff -r 2aad33bb021d -r fafb3af5aa12 finch/libgnt/gntwm.c --- a/finch/libgnt/gntwm.c Thu Jun 28 17:07:48 2007 +0000 +++ b/finch/libgnt/gntwm.c Sat Jun 30 22:12:44 2007 +0000 @@ -61,6 +61,7 @@ SIG_GIVE_FOCUS, SIG_KEY_PRESS, SIG_MOUSE_CLICK, + SIG_TERMINAL_REFRESH, SIGS }; @@ -1031,6 +1032,8 @@ endwin(); g_hash_table_foreach(wm->nodes, (GHFunc)refresh_node, NULL); + refresh(); + g_signal_emit(wm, signals[SIG_TERMINAL_REFRESH], 0); update_screen(wm); gnt_ws_draw_taskbar(wm->cws, TRUE); curs_set(0); /* endwin resets the cursor to normal */ @@ -1238,6 +1241,15 @@ gnt_closure_marshal_BOOLEAN__INT_INT_INT_POINTER, G_TYPE_BOOLEAN, 4, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_POINTER); + signals[SIG_TERMINAL_REFRESH] = + g_signal_new("terminal-refresh", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GntWMClass, terminal_refresh), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "window-next", window_next, "\033" "n", NULL); gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "window-prev", window_prev, diff -r 2aad33bb021d -r fafb3af5aa12 finch/libgnt/gntwm.h --- a/finch/libgnt/gntwm.h Thu Jun 28 17:07:48 2007 +0000 +++ b/finch/libgnt/gntwm.h Sat Jun 30 22:12:44 2007 +0000 @@ -169,10 +169,15 @@ */ /*GList *(*window_list)();*/ + /* This is invoked whenever the terminal window is resized, or the + * screen session is attached to a new terminal. (ie, from the + * SIGWINCH callback) + */ + void (*terminal_refresh)(GntWM *wm); + void (*res1)(void); void (*res2)(void); void (*res3)(void); - void (*res4)(void); }; G_BEGIN_DECLS diff -r 2aad33bb021d -r fafb3af5aa12 finch/libgnt/wms/irssi.c --- a/finch/libgnt/wms/irssi.c Thu Jun 28 17:07:48 2007 +0000 +++ b/finch/libgnt/wms/irssi.c Sat Jun 30 22:12:44 2007 +0000 @@ -248,6 +248,12 @@ } static void +irssi_terminal_refresh(GntWM *wm) +{ + draw_line_separators((Irssi*)wm); +} + +static void irssi_class_init(IrssiClass *klass) { GntWMClass *pclass = GNT_WM_CLASS(klass); @@ -258,6 +264,7 @@ pclass->window_resized = irssi_window_resized; pclass->close_window = irssi_close_window; pclass->window_update = irssi_update_window; + pclass->terminal_refresh = irssi_terminal_refresh; gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "move-up", move_direction, "\033" "K", GINT_TO_POINTER('k'), NULL); diff -r 2aad33bb021d -r fafb3af5aa12 libpurple/blist.h --- a/libpurple/blist.h Thu Jun 28 17:07:48 2007 +0000 +++ b/libpurple/blist.h Sat Jun 30 22:12:44 2007 +0000 @@ -21,6 +21,8 @@ * 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 + * + * @see @ref blist-signals */ #ifndef _PURPLE_BLIST_H_ #define _PURPLE_BLIST_H_ diff -r 2aad33bb021d -r fafb3af5aa12 libpurple/cipher.h --- a/libpurple/cipher.h Thu Jun 28 17:07:48 2007 +0000 +++ b/libpurple/cipher.h Sat Jun 30 22:12:44 2007 +0000 @@ -21,6 +21,8 @@ * 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 + * + * @see @ref cipher-signals */ #ifndef PURPLE_CIPHER_H #define PURPLE_CIPHER_H diff -r 2aad33bb021d -r fafb3af5aa12 libpurple/core.h --- a/libpurple/core.h Thu Jun 28 17:07:48 2007 +0000 +++ b/libpurple/core.h Sat Jun 30 22:12:44 2007 +0000 @@ -20,6 +20,8 @@ * 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 + * + * @see @ref core-signals */ #ifndef _PURPLE_CORE_H_ #define _PURPLE_CORE_H_ diff -r 2aad33bb021d -r fafb3af5aa12 libpurple/dbus-server.h --- a/libpurple/dbus-server.h Thu Jun 28 17:07:48 2007 +0000 +++ b/libpurple/dbus-server.h Sat Jun 30 22:12:44 2007 +0000 @@ -22,6 +22,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * @see @ref dbus-server-signals */ #ifndef _PURPLE_DBUS_SERVER_H_ diff -r 2aad33bb021d -r fafb3af5aa12 libpurple/imgstore.c --- a/libpurple/imgstore.c Thu Jun 28 17:07:48 2007 +0000 +++ b/libpurple/imgstore.c Sat Jun 30 22:12:44 2007 +0000 @@ -55,8 +55,8 @@ { PurpleStoredImage *img; - g_return_val_if_fail(data != NULL, 0); - g_return_val_if_fail(size > 0, 0); + g_return_val_if_fail(data != NULL, NULL); + g_return_val_if_fail(size > 0, NULL); img = g_new(PurpleStoredImage, 1); PURPLE_DBUS_REGISTER_POINTER(img, PurpleStoredImage); @@ -73,11 +73,13 @@ purple_imgstore_add_with_id(gpointer data, size_t size, const char *filename) { PurpleStoredImage *img = purple_imgstore_add(data, size, filename); - img->id = ++nextid; + if (img) { + img->id = ++nextid; - g_hash_table_insert(imgstore, &(img->id), img); + g_hash_table_insert(imgstore, &(img->id), img); + } - return img->id; + return (img ? img->id : 0); } PurpleStoredImage *purple_imgstore_find_by_id(int id) { diff -r 2aad33bb021d -r fafb3af5aa12 libpurple/imgstore.h --- a/libpurple/imgstore.h Thu Jun 28 17:07:48 2007 +0000 +++ b/libpurple/imgstore.h Sat Jun 30 22:12:44 2007 +0000 @@ -22,6 +22,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * @see @ref imgstore-signals */ #ifndef _PURPLE_IMGSTORE_H_ #define _PURPLE_IMGSTORE_H_ diff -r 2aad33bb021d -r fafb3af5aa12 libpurple/log.h --- a/libpurple/log.h Thu Jun 28 17:07:48 2007 +0000 +++ b/libpurple/log.h Sat Jun 30 22:12:44 2007 +0000 @@ -21,6 +21,8 @@ * 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 + * + * @see @ref log-signals */ #ifndef _PURPLE_LOG_H_ #define _PURPLE_LOG_H_ diff -r 2aad33bb021d -r fafb3af5aa12 libpurple/notify.h --- a/libpurple/notify.h Thu Jun 28 17:07:48 2007 +0000 +++ b/libpurple/notify.h Sat Jun 30 22:12:44 2007 +0000 @@ -21,6 +21,8 @@ * 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 + * + * @see @ref notify-signals */ #ifndef _PURPLE_NOTIFY_H_ #define _PURPLE_NOTIFY_H_ diff -r 2aad33bb021d -r fafb3af5aa12 libpurple/plugin.h --- a/libpurple/plugin.h Thu Jun 28 17:07:48 2007 +0000 +++ b/libpurple/plugin.h Sat Jun 30 22:12:44 2007 +0000 @@ -21,6 +21,10 @@ * 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 + * + * @see @ref plugin-signals + * @see @ref plugin-ids + * @see @ref plugin-i18n */ #ifndef _PURPLE_PLUGIN_H_ #define _PURPLE_PLUGIN_H_ diff -r 2aad33bb021d -r fafb3af5aa12 libpurple/plugins/log_reader.c --- a/libpurple/plugins/log_reader.c Thu Jun 28 17:07:48 2007 +0000 +++ b/libpurple/plugins/log_reader.c Sat Jun 30 22:12:44 2007 +0000 @@ -1,13 +1,5 @@ -#ifdef HAVE_CONFIG_H -# include -#endif - #include -#ifndef PURPLE_PLUGINS -# define PURPLE_PLUGINS -#endif - #include "internal.h" #include "debug.h" @@ -106,8 +98,8 @@ if (sscanf(date, "%u|%u|%u", &tm.tm_year, &tm.tm_mon, &tm.tm_mday) != 3) { - purple_debug(PURPLE_DEBUG_ERROR, "Adium log parse", - "Filename timestamp parsing error\n"); + purple_debug_error("Adium log parse", + "Filename timestamp parsing error\n"); } else { char *filename = g_build_filename(path, file, NULL); FILE *handle = g_fopen(filename, "rb"); @@ -141,8 +133,8 @@ if (sscanf(contents2, "%u.%u.%u", &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 3) { - purple_debug(PURPLE_DEBUG_ERROR, "Adium log parse", - "Contents timestamp parsing error\n"); + purple_debug_error("Adium log parse", + "Contents timestamp parsing error\n"); g_free(contents); g_free(filename); continue; @@ -161,7 +153,7 @@ log->logger = adium_logger; log->logger_data = data; - list = g_list_append(list, log); + list = g_list_prepend(list, log); } } else if (purple_str_has_suffix(file, ".adiumLog")) { struct tm tm; @@ -171,8 +163,8 @@ if (sscanf(date, "%u|%u|%u", &tm.tm_year, &tm.tm_mon, &tm.tm_mday) != 3) { - purple_debug(PURPLE_DEBUG_ERROR, "Adium log parse", - "Filename timestamp parsing error\n"); + purple_debug_error("Adium log parse", + "Filename timestamp parsing error\n"); } else { char *filename = g_build_filename(path, file, NULL); FILE *handle = g_fopen(filename, "rb"); @@ -201,8 +193,8 @@ if (sscanf(contents2, "%u.%u.%u", &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 3) { - purple_debug(PURPLE_DEBUG_ERROR, "Adium log parse", - "Contents timestamp parsing error\n"); + purple_debug_error("Adium log parse", + "Contents timestamp parsing error\n"); g_free(contents); g_free(filename); continue; @@ -222,7 +214,7 @@ log->logger = adium_logger; log->logger_data = data; - list = g_list_append(list, log); + list = g_list_prepend(list, log); } } } @@ -242,17 +234,19 @@ gchar *read = NULL; gsize length; + /* XXX: TODO: We probably want to set PURPLE_LOG_READ_NO_NEWLINE + * XXX: TODO: for HTML logs. */ + *flags = 0; + g_return_val_if_fail(log != NULL, g_strdup("")); data = log->logger_data; g_return_val_if_fail(data->path != NULL, g_strdup("")); - purple_debug(PURPLE_DEBUG_INFO, "Adium log read", - "Reading %s\n", data->path); + purple_debug_info("Adium log read", "Reading %s\n", data->path); if (!g_file_get_contents(data->path, &read, &length, &error)) { - purple_debug(PURPLE_DEBUG_ERROR, "Adium log read", - "Error reading log\n"); + purple_debug_error("Adium log read", "Error reading log\n"); if (error) g_error_free(error); return g_strdup(""); @@ -320,6 +314,7 @@ data = log->logger_data; g_free(data->path); + g_free(data); } @@ -481,7 +476,7 @@ if (!(datetime && *datetime)) { purple_debug_error("MSN log timestamp parse", - "Attribute missing: %s\n", "DateTime"); + "Attribute missing: %s\n", "DateTime"); return (time_t)0; } @@ -502,7 +497,7 @@ if (!(date && *date)) { purple_debug_error("MSN log timestamp parse", - "Attribute missing: %s\n", "Date"); + "Attribute missing: %s\n", "Date"); *tm_out = &tm2; return stamp; } @@ -511,7 +506,7 @@ if (!(time && *time)) { purple_debug_error("MSN log timestamp parse", - "Attribute missing: %s\n", "Time"); + "Attribute missing: %s\n", "Time"); *tm_out = &tm2; return stamp; } @@ -519,7 +514,7 @@ if (sscanf(date, "%u/%u/%u", &month, &day, &year) != 3) { purple_debug_error("MSN log timestamp parse", - "%s parsing error\n", "Date"); + "%s parsing error\n", "Date"); *tm_out = &tm2; return stamp; } @@ -536,7 +531,7 @@ if (sscanf(time, "%u:%u:%u %c", &hour, &min, &sec, &am_pm) != 4) { purple_debug_error("MSN log timestamp parse", - "%s parsing error\n", "Time"); + "%s parsing error\n", "Time"); *tm_out = &tm2; return stamp; } @@ -803,12 +798,10 @@ logfile = NULL; /* No sense saving the obvious buddy@domain.com. */ } - purple_debug(PURPLE_DEBUG_INFO, "MSN log read", - "Reading %s\n", path); + purple_debug_info("MSN log read", "Reading %s\n", path); if (!g_file_get_contents(path, &contents, &length, &error)) { g_free(path); - purple_debug(PURPLE_DEBUG_ERROR, "MSN log read", - "Error reading log\n"); + purple_debug_error("MSN log read", "Error reading log\n"); if (error) g_error_free(error); return list; @@ -837,8 +830,8 @@ session_id = xmlnode_get_attrib(message, "SessionID"); if (!session_id) { - purple_debug(PURPLE_DEBUG_ERROR, "MSN log parse", - "Error parsing message: %s\n", "SessionID missing"); + purple_debug_error("MSN log parse", + "Error parsing message: %s\n", "SessionID missing"); continue; } @@ -864,7 +857,7 @@ log->logger = msn_logger; log->logger_data = data; - list = g_list_append(list, log); + list = g_list_prepend(list, log); } old_session_id = session_id; } @@ -872,7 +865,7 @@ if (data) data->last_log = TRUE; - return list; + return g_list_reverse(list); } static char * msn_logger_read (PurpleLog *log, PurpleLogReadFlags *flags) @@ -881,6 +874,7 @@ GString *text = NULL; xmlnode *message; + *flags = PURPLE_LOG_READ_NO_NEWLINE; g_return_val_if_fail(log != NULL, g_strdup("")); data = log->logger_data; @@ -898,8 +892,8 @@ if (!data->root || !data->message || !data->session_id) { /* Something isn't allocated correctly. */ - purple_debug(PURPLE_DEBUG_ERROR, "MSN log parse", - "Error parsing message: %s\n", "Internal variables inconsistent"); + purple_debug_error("MSN log parse", + "Error parsing message: %s\n", "Internal variables inconsistent"); data->text = text; return text->str; @@ -926,8 +920,8 @@ /* If this triggers, something is wrong with the XML. */ if (!new_session_id) { - purple_debug(PURPLE_DEBUG_ERROR, "MSN log parse", - "Error parsing message: %s\n", "New SessionID missing"); + purple_debug_error("MSN log parse", + "Error parsing message: %s\n", "New SessionID missing"); break; } @@ -1133,10 +1127,10 @@ text = g_string_append(text, style); text = g_string_append(text, "\">"); text = g_string_append(text, tmp); - text = g_string_append(text, "\n"); + text = g_string_append(text, "
"); } else { text = g_string_append(text, tmp); - text = g_string_append(text, "\n"); + text = g_string_append(text, "
"); } g_free(tmp); } @@ -1176,6 +1170,8 @@ if (data->text) g_string_free(data->text, FALSE); + + g_free(data); } @@ -1238,8 +1234,7 @@ path = g_build_filename( logdir, prpl_name, filename, NULL); - purple_debug(PURPLE_DEBUG_INFO, "Trillian log list", - "Reading %s\n", path); + purple_debug_info("Trillian log list", "Reading %s\n", path); /* FIXME: There's really no need to read the entire file at once. * See src/log.c:old_logger_list for a better approach. */ @@ -1252,8 +1247,7 @@ path = g_build_filename( logdir, prpl_name, "Query", filename, NULL); - purple_debug(PURPLE_DEBUG_INFO, "Trillian log list", - "Reading %s\n", path); + purple_debug_info("Trillian log list", "Reading %s\n", path); if (!g_file_get_contents(path, &contents, &length, &error)) { if (error) g_error_free(error); @@ -1283,8 +1277,8 @@ /* This log had no data, so we remove it. */ GList *last = g_list_last(list); - purple_debug(PURPLE_DEBUG_INFO, "Trillian log list", - "Empty log. Offset %i\n", data->offset); + purple_debug_info("Trillian log list", + "Empty log. Offset %i\n", data->offset); trillian_logger_finalize((PurpleLog *)last->data); list = g_list_delete_link(list, last); @@ -1295,7 +1289,7 @@ /* The conditional is to make sure we're not reading off * the end of the string. We don't want strlen(), as that'd * have to count the whole string needlessly. - * + * * The odd check here is because a Session Start at the * beginning of the file can be overwritten with a UTF-8 * byte order mark. Yes, it's weird. @@ -1348,9 +1342,8 @@ &tm.tm_min, &tm.tm_sec, &tm.tm_year) != 5) { - purple_debug(PURPLE_DEBUG_ERROR, - "Trillian log timestamp parse", - "Session Start parsing error\n"); + purple_debug_error("Trillian log timestamp parse", + "Session Start parsing error\n"); } else { PurpleLog *log; @@ -1405,7 +1398,7 @@ log->logger = trillian_logger; log->logger_data = data; - list = g_list_append(list, log); + list = g_list_prepend(list, log); } } } @@ -1420,7 +1413,7 @@ g_free(prpl_name); - return list; + return g_list_reverse(list); } static char * trillian_logger_read (PurpleLog *log, PurpleLogReadFlags *flags) @@ -1434,6 +1427,7 @@ char *c; const char *line; + *flags = PURPLE_LOG_READ_NO_NEWLINE; g_return_val_if_fail(log != NULL, g_strdup("")); data = log->logger_data; @@ -1442,8 +1436,7 @@ g_return_val_if_fail(data->length > 0, g_strdup("")); g_return_val_if_fail(data->their_nickname != NULL, g_strdup("")); - purple_debug(PURPLE_DEBUG_INFO, "Trillian log read", - "Reading %s\n", data->path); + purple_debug_info("Trillian log read", "Reading %s\n", data->path); read = g_malloc(data->length + 2); @@ -1491,7 +1484,7 @@ * "> * Then, replace the next " " (or add this if the end-of-line is reached) with: * - * + * * As implemented, this isn't perfect, but it should cover common cases. */ while (line && (link = strstr(line, "(Link: "))) @@ -1689,10 +1682,14 @@ if (footer) g_string_append(formatted, footer); - g_string_append_c(formatted, '\n'); + g_string_append(formatted, "
"); } g_free(read); + + /* XXX: TODO: What can we do about removing \r characters? + * XXX: TODO: and will that allow us to avoid this + * XXX: TODO: g_strchomp(), or is that unrelated? */ /* XXX: TODO: Avoid this g_strchomp() */ return g_strchomp(g_string_free(formatted, FALSE)); } @@ -1728,9 +1725,369 @@ g_free(data->path); g_free(data->their_nickname); - + g_free(data); } +/***************************************************************************** + * QIP Logger * + *****************************************************************************/ + +/* The QIP logger doesn't write logs, only reads them. This is to include + * QIP logs in the log viewer transparently. + */ +#define QIP_LOG_DELIMITER "--------------------------------------" +#define QIP_LOG_IN_MESSAGE (QIP_LOG_DELIMITER "<-") +#define QIP_LOG_OUT_MESSAGE (QIP_LOG_DELIMITER ">-") +#define QIP_LOG_IN_MESSAGE_ESC (QIP_LOG_DELIMITER "<-") +#define QIP_LOG_OUT_MESSAGE_ESC (QIP_LOG_DELIMITER ">-") +#define QIP_LOG_TIMEOUT (60*60) + +static PurpleLogLogger *qip_logger; + +struct qip_logger_data { + + char *path; /* FIXME: Change this to use PurpleStringref like log.c:old_logger_list */ + int offset; + int length; +}; + +static GList *qip_logger_list(PurpleLogType type, const char *sn, PurpleAccount *account) +{ + GList *list = NULL; + const char *logdir; + PurplePlugin *plugin; + PurplePluginProtocolInfo *prpl_info; + char *username; + char *filename; + char *path; + char *contents; + struct qip_logger_data *data = NULL; + struct tm prev_tm; + struct tm tm; + gboolean prev_tm_init = FALSE; + gboolean main_cycle = TRUE; + char *c; + char *start_log; + char *new_line; + int offset = 0; + GError *error; + + g_return_val_if_fail(sn != NULL, list); + g_return_val_if_fail(account != NULL, list); + + /* QIP only supports ICQ. */ + if (strcmp(account->protocol_id, "prpl-icq")) + return list; + + logdir = purple_prefs_get_string("/plugins/core/log_reader/qip/log_directory"); + + /* By clearing the log directory path, this logger can be (effectively) disabled. */ + if (!*logdir) + return list; + + plugin = purple_find_prpl(purple_account_get_protocol_id(account)); + if (!plugin) + return NULL; + + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); + if (!prpl_info->list_icon) + return NULL; + + username = g_strdup(purple_normalize(account, account->username)); + filename = g_strdup_printf("%s.txt", purple_normalize(account, sn)); + path = g_build_filename(logdir, username, "History", filename, NULL); + g_free(username); + g_free(filename); + + purple_debug_info("QIP logger", "Reading %s\n", path); + + error = NULL; + if (!g_file_get_contents(path, &contents, NULL, &error)) { + purple_debug_error("QIP logger", + "Couldn't read file %s: %s \n", path, error->message); + g_error_free(error); + g_free(path); + return list; + } + + c = contents; + start_log = contents; + while (main_cycle) { + + gboolean add_new_log = FALSE; + + if (*c) { + if (purple_str_has_prefix(c, QIP_LOG_IN_MESSAGE) || + purple_str_has_prefix(c, QIP_LOG_OUT_MESSAGE)) { + + char *tmp; + + new_line = c; + + /* find EOL */ + c = strstr(c, "\n"); + c++; + + /* Find the last '(' character. */ + if ((tmp = strstr(c, "\n")) != NULL) { + while (*tmp && *tmp != '(') --tmp; + c = tmp; + } else { + while (*c) + c++; + c--; + c = g_strrstr(c, "("); + } + + if (c != NULL) { + const char *timestamp = ++c; + + /* Parse the time, day, month and year */ + if (sscanf(timestamp, "%u:%u:%u %u/%u/%u", + &tm.tm_hour, &tm.tm_min, &tm.tm_sec, + &tm.tm_mday, &tm.tm_mon, &tm.tm_year) != 6) { + + purple_debug_error("QIP logger list", + "Parsing timestamp error\n"); + } else { + tm.tm_mon -= 1; + tm.tm_year -= 1900; + + /* Let the C library deal with + * daylight savings time. */ + tm.tm_isdst = -1; + + if (!prev_tm_init) { + prev_tm = tm; + prev_tm_init = TRUE; + } else { + add_new_log = difftime(mktime(&tm), mktime(&prev_tm)) > QIP_LOG_TIMEOUT; + } + } + } + } + } else { + add_new_log = TRUE; + main_cycle = FALSE; + new_line = c; + } + + /* adding log */ + if (add_new_log && prev_tm_init) { + PurpleLog *log; + + /* filling data */ + data = g_new0(struct qip_logger_data, 1); + data->path = g_strdup(path); + data->length = new_line - start_log; + data->offset = offset; + offset += data->length; + purple_debug_info("QIP logger list", + "Creating log: path = (%s); length = (%d); offset = (%d)\n", + data->path, data->length, data->offset); + + /* XXX: Look into this later... Should we pass in a struct tm? */ + log = purple_log_new(PURPLE_LOG_IM, sn, account, + NULL, mktime(&prev_tm), NULL); + + log->logger = qip_logger; + log->logger_data = data; + + list = g_list_prepend(list, log); + + prev_tm = tm; + start_log = new_line; + } + + if (*c) { + /* find EOF */ + c = strstr(c, "\n"); + c++; + } + } + + g_free(contents); + g_free(path); + return g_list_reverse(list); +} + +static char *qip_logger_read(PurpleLog *log, PurpleLogReadFlags *flags) +{ + struct qip_logger_data *data; + PurpleBuddy *buddy; + GString *formatted; + char *c; + const char *line; + gchar *contents; + char *selected; + GError *error; + char *utf8_string; + FILE *file; + + + g_return_val_if_fail(log != NULL, g_strdup("")); + + data = log->logger_data; + + g_return_val_if_fail(data->path != NULL, g_strdup("")); + g_return_val_if_fail(data->length > 0, g_strdup("")); + + error = NULL; + + contents = g_malloc(data->length + 2); + + file = g_fopen(data->path, "rb"); + g_return_val_if_fail(file != NULL, g_strdup("")); + + fseek(file, data->offset, SEEK_SET); + fread(contents, data->length, 1, file); + fclose(file); + + contents[data->length] = '\n'; + contents[data->length + 1] = '\0'; + + /* Convert file contents from Cp1251 to UTF-8 codeset */ + error = NULL; + if (!(utf8_string = g_convert(contents, -1, "UTF-8", "Cp1251", NULL, NULL, &error))) { + purple_debug_error("QIP logger", + "Couldn't convert file %s to UTF-8: %s\n", data->path, error->message); + g_error_free(error); + g_free(contents); + return g_strdup(""); + } + + g_free(contents); + contents = g_markup_escape_text(utf8_string, -1); + g_free(utf8_string); + + buddy = purple_find_buddy(log->account, log->name); + + /* Apply formatting... */ + formatted = g_string_sized_new(data->length + 2); + c = contents; + line = contents; + + while (*c) { + gboolean is_in_message = FALSE; + + if (purple_str_has_prefix(line, QIP_LOG_IN_MESSAGE_ESC) || + purple_str_has_prefix(line, QIP_LOG_OUT_MESSAGE_ESC)) { + + char *tmp; + const char *buddy_name; + + is_in_message = purple_str_has_prefix(line, QIP_LOG_IN_MESSAGE_ESC); + + /* find EOL */ + c = strstr(c, "\n"); + + /* XXX: Do we need buddy_name when we have buddy->alias? */ + buddy_name = ++c; + + /* Find the last '(' character. */ + if ((tmp = strstr(c, "\n")) != NULL) { + while (*tmp && *tmp != '(') --tmp; + c = tmp; + } else { + while (*c) + c++; + c--; + c = g_strrstr(c, "("); + } + + if (c != NULL) { + const char *timestamp = c; + int hour; + int min; + int sec; + + timestamp++; + + /* Parse the time, day, month and year */ + if (sscanf(timestamp, "%u:%u:%u", + &hour, &min, &sec) != 3) { + purple_debug_error("QIP logger read", + "Parsing timestamp error\n"); + } else { + g_string_append(formatted, ""); + /* TODO: Figure out if we can do anything more locale-independent. */ + g_string_append_printf(formatted, + "(%u:%02u:%02u) %cM ", hour % 12, + min, sec, (hour >= 12) ? 'P': 'A'); + g_string_append(formatted, " "); + + if (is_in_message) { + if (buddy_name != NULL && buddy->alias) { + g_string_append_printf(formatted, + "" + "%s: ", buddy->alias); + } + } else { + const char *acct_name; + acct_name = purple_account_get_alias(log->account); + if (!acct_name) + acct_name = purple_account_get_username(log->account); + + g_string_append_printf(formatted, + "" + "%s: ", acct_name); + } + + /* find EOF */ + c = strstr(c, "\n"); + line = ++c; + } + } + } else { + if ((c = strstr(c, "\n"))) + *c = '\0'; + + if (line[0] != '\n' && line[0] != '\r') { + + g_string_append(formatted, line); + g_string_append(formatted, "
"); + } + line = ++c; + } + } + g_free(contents); + + /* XXX: TODO: Avoid this g_strchomp() */ + return g_strchomp(g_string_free(formatted, FALSE)); +} + +static int qip_logger_size (PurpleLog *log) +{ + struct qip_logger_data *data; + char *text; + size_t size; + + g_return_val_if_fail(log != NULL, 0); + + data = log->logger_data; + + if (purple_prefs_get_bool("/plugins/core/log_reader/fast_sizes")) { + return data ? data->length : 0; + } + + text = qip_logger_read(log, NULL); + size = strlen(text); + g_free(text); + + return size; +} + +static void qip_logger_finalize(PurpleLog *log) +{ + struct qip_logger_data *data; + + g_return_if_fail(log != NULL); + + data = log->logger_data; + + g_free(data->path); + g_free(data); +} /***************************************************************************** * Plugin Code * @@ -1761,15 +2118,11 @@ /* Calculate default Adium log directory. */ #ifdef _WIN32 - path = ""; + purple_prefs_add_string("/plugins/core/log_reader/adium/log_directory", ""); #else - path = g_build_filename(purple_home_dir(), "Library", "Application Support", - "Adium 2.0", "Users", "Default", "Logs", NULL); -#endif - + path = g_build_filename(purple_home_dir(), "Library", "Application Support", + "Adium 2.0", "Users", "Default", "Logs", NULL); purple_prefs_add_string("/plugins/core/log_reader/adium/log_directory", path); - -#ifndef _WIN32 g_free(path); #endif @@ -1779,15 +2132,11 @@ /* Calculate default Fire log directory. */ #ifdef _WIN32 - path = ""; + purple_prefs_add_string("/plugins/core/log_reader/fire/log_directory", ""); #else - path = g_build_filename(purple_home_dir(), "Library", "Application Support", - "Fire", "Sessions", NULL); -#endif - + path = g_build_filename(purple_home_dir(), "Library", "Application Support", + "Fire", "Sessions", NULL); purple_prefs_add_string("/plugins/core/log_reader/fire/log_directory", path); - -#ifndef _WIN32 g_free(path); #endif @@ -1799,21 +2148,15 @@ #ifdef _WIN32 folder = wpurple_get_special_folder(CSIDL_PERSONAL); if (folder) { -#endif - path = g_build_filename( -#ifdef _WIN32 - folder, + path = g_build_filename(folder, "My Chat Logs", NULL); + g_free(folder); + } else + path = g_strdup(""); #else - PURPLE_LOG_READER_WINDOWS_MOUNT_POINT, "Documents and Settings", - g_get_user_name(), "My Documents", + path = g_build_filename(PURPLE_LOG_READER_WINDOWS_MOUNT_POINT, + "Documents and Settings", g_get_user_name(), + "My Documents", "My Chat Logs", NULL); #endif - "My Chat Logs", NULL); -#ifdef _WIN32 - g_free(folder); - } else /* !folder */ - path = g_strdup(""); -#endif - purple_prefs_add_string("/plugins/core/log_reader/messenger_plus/log_directory", path); g_free(path); @@ -1825,21 +2168,15 @@ #ifdef _WIN32 folder = wpurple_get_special_folder(CSIDL_PERSONAL); if (folder) { -#endif - path = g_build_filename( -#ifdef _WIN32 - folder, + path = g_build_filename(folder, "My Received Files", NULL); + g_free(folder); + } else + path = g_strdup(""); #else - PURPLE_LOG_READER_WINDOWS_MOUNT_POINT, "Documents and Settings", - g_get_user_name(), "My Documents", + path = g_build_filename(PURPLE_LOG_READER_WINDOWS_MOUNT_POINT, + "Documents and Settings", g_get_user_name(), + "My Documents", "My Received Files", NULL); #endif - "My Received Files", NULL); -#ifdef _WIN32 - g_free(folder); - } else /* !folder */ - path = g_strdup(""); -#endif - purple_prefs_add_string("/plugins/core/log_reader/msn/log_directory", path); g_free(path); @@ -1882,7 +2219,7 @@ char *folder = wpurple_get_special_folder(CSIDL_PROGRAM_FILES); if (folder) { path = g_build_filename(folder, "Trillian", - "users", "default", "talk.ini", NULL); + "users", "default", "talk.ini", NULL); g_free(folder); } } @@ -1894,25 +2231,25 @@ #if 0 && GLIB_CHECK_VERSION(2,6,0) /* FIXME: Not tested yet. */ GKeyFile *key_file; - purple_debug(PURPLE_DEBUG_INFO, "Trillian talk.ini read", - "Reading %s\n", path); + purple_debug_info("Trillian talk.ini read", "Reading %s\n", path); + + error = NULL; if (!g_key_file_load_from_file(key_file, path, G_KEY_FILE_NONE, GError &error)) { - purple_debug(PURPLE_DEBUG_ERROR, "Trillian talk.ini read", - "Error reading talk.ini\n"); + purple_debug_error("Trillian talk.ini read", + "Error reading talk.ini\n"); if (error) g_error_free(error); } else { char *logdir = g_key_file_get_string(key_file, "Logging", "Directory", &error); if (error) { - purple_debug(PURPLE_DEBUG_ERROR, "Trillian talk.ini read", - "Error reading Directory value from Logging section\n"); + purple_debug_error("Trillian talk.ini read", + "Error reading Directory value from Logging section\n"); g_error_free(error); } if (logdir) { g_strchomp(logdir); - purple_prefs_add_string( - "/plugins/core/log_reader/trillian/log_directory", logdir); + purple_prefs_add_string("/plugins/core/log_reader/trillian/log_directory", logdir); found = TRUE; } @@ -1922,11 +2259,11 @@ gsize length; gchar *contents = NULL; - purple_debug(PURPLE_DEBUG_INFO, "Trillian talk.ini read", + purple_debug_info("Trillian talk.ini read", "Reading %s\n", path); if (!g_file_get_contents(path, &contents, &length, &error)) { - purple_debug(PURPLE_DEBUG_ERROR, "Trillian talk.ini read", - "Error reading talk.ini\n"); + purple_debug_error("Trillian talk.ini read", + "Error reading talk.ini\n"); if (error) g_error_free(error); } else { @@ -1957,32 +2294,43 @@ } /* path */ if (!found) { -#endif /* defined(_WIN32) */ + folder = wpurple_get_special_folder(CSIDL_PROGRAM_FILES); + if (folder) { + path = g_build_filename(folder, "Trillian", "users", + "default", "logs", NULL); + g_free(folder); + } else + path = g_strdup(""); + } +#else /* !defined(_WIN32) */ + /* TODO: At some point, this could attempt to parse talk.ini + * TODO: from the default Trillian install directory on the + * TODO: Windows mount point. */ /* Calculate default Trillian log directory. */ + path = g_build_filename(PURPLE_LOG_READER_WINDOWS_MOUNT_POINT, + "Program Files", "Trillian", "users", + "default", "logs", NULL); +#endif + + + /* Add QIP log directory preference. */ + purple_prefs_add_none("/plugins/core/log_reader/qip"); + + /* Calculate default QIP log directory. */ #ifdef _WIN32 folder = wpurple_get_special_folder(CSIDL_PROGRAM_FILES); if (folder) { -#endif - path = g_build_filename( -#ifdef _WIN32 - folder, + path = g_build_filename(folder, "QIP", "Users", NULL); + g_free(folder); + } else + path = g_strdup(""); #else - PURPLE_LOG_READER_WINDOWS_MOUNT_POINT, "Program Files", + path = g_build_filename(PURPLE_LOG_READER_WINDOWS_MOUNT_POINT, + "Program Files", "QIP", "Users", NULL); #endif - "Trillian", "users", "default", "logs", NULL); -#ifdef _WIN32 - g_free(folder); - } else /* !folder */ - path = g_strdup(""); -#endif - - purple_prefs_add_string("/plugins/core/log_reader/trillian/log_directory", path); + purple_prefs_add_string("/plugins/core/log_reader/qip/log_directory", path); g_free(path); - -#ifdef _WIN32 - } /* !found */ -#endif } static gboolean @@ -2026,11 +2374,24 @@ messenger_plus_logger_read, messenger_plus_logger_size); purple_log_logger_add(messenger_plus_logger); + #endif /* The names of IM clients are marked for translation at the request of translators who wanted to transliterate them. Many translators choose to leave them alone. Choose what's best for your language. */ + qip_logger = purple_log_logger_new("qip", _("QIP"), 6, + NULL, + NULL, + qip_logger_finalize, + qip_logger_list, + qip_logger_read, + qip_logger_size); + purple_log_logger_add(qip_logger); + + /* The names of IM clients are marked for translation at the request of + translators who wanted to transliterate them. Many translators + choose to leave them alone. Choose what's best for your language. */ msn_logger = purple_log_logger_new("msn", _("MSN Messenger"), 6, NULL, NULL, @@ -2067,6 +2428,7 @@ #endif purple_log_logger_remove(msn_logger); purple_log_logger_remove(trillian_logger); + purple_log_logger_remove(qip_logger); return TRUE; } @@ -2116,6 +2478,10 @@ #endif ppref = purple_plugin_pref_new_with_name_and_label( + "/plugins/core/log_reader/qip/log_directory", _("QIP")); + purple_plugin_pref_frame_add(frame, ppref); + + ppref = purple_plugin_pref_new_with_name_and_label( "/plugins/core/log_reader/msn/log_directory", _("MSN Messenger")); purple_plugin_pref_frame_add(frame, ppref); diff -r 2aad33bb021d -r fafb3af5aa12 libpurple/protocols/yahoo/yahoochat.c --- a/libpurple/protocols/yahoo/yahoochat.c Thu Jun 28 17:07:48 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoochat.c Sat Jun 30 22:12:44 2007 +0000 @@ -785,44 +785,6 @@ g_free(eroom); } -/* borrowed from gtkconv.c */ -static gboolean -meify(char *message, size_t len) -{ - /* - * Read /me-ify: If the message (post-HTML) starts with /me, - * remove the "/me " part of it (including that space) and return TRUE. - */ - char *c; - gboolean inside_html = 0; - - /* Umm.. this would be very bad if this happens. */ - g_return_val_if_fail(message != NULL, FALSE); - - if (len == -1) - len = strlen(message); - - for (c = message; *c != '\0'; c++, len--) { - if (inside_html) { - if (*c == '>') - inside_html = FALSE; - } - else { - if (*c == '<') - inside_html = TRUE; - else - break; - } - } - - if (*c != '\0' && !g_ascii_strncasecmp(c, "/me ", 4)) { - memmove(c, c + 4, len - 3); - return TRUE; - } - - return FALSE; -} - static int yahoo_chat_send(PurpleConnection *gc, const char *dn, const char *room, const char *what, PurpleMessageFlags flags) { struct yahoo_data *yd = gc->proto_data; @@ -839,7 +801,7 @@ msg1 = g_strdup(what); - if (meify(msg1, -1)) + if (purple_message_meify(msg1, -1)) me = 1; msg2 = yahoo_html_to_codes(msg1); diff -r 2aad33bb021d -r fafb3af5aa12 libpurple/savedstatuses.h --- a/libpurple/savedstatuses.h Thu Jun 28 17:07:48 2007 +0000 +++ b/libpurple/savedstatuses.h Sat Jun 30 22:12:44 2007 +0000 @@ -21,6 +21,8 @@ * 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 + * + * @see @ref savedstatus-signals */ #ifndef _PURPLE_SAVEDSTATUSES_H_ #define _PURPLE_SAVEDSTATUSES_H_ diff -r 2aad33bb021d -r fafb3af5aa12 libpurple/sound.h --- a/libpurple/sound.h Thu Jun 28 17:07:48 2007 +0000 +++ b/libpurple/sound.h Sat Jun 30 22:12:44 2007 +0000 @@ -21,6 +21,8 @@ * 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 + * + * @see @ref sound-signals */ #ifndef _PURPLE_SOUND_H_ #define _PURPLE_SOUND_H_ diff -r 2aad33bb021d -r fafb3af5aa12 libpurple/tests/check_libpurple.c --- a/libpurple/tests/check_libpurple.c Thu Jun 28 17:07:48 2007 +0000 +++ b/libpurple/tests/check_libpurple.c Sat Jun 30 22:12:44 2007 +0000 @@ -20,9 +20,17 @@ static PurpleEventLoopUiOps eventloop_ui_ops = { g_timeout_add, - (guint (*)(guint))g_source_remove, + g_source_remove, purple_check_input_add, - (guint (*)(guint))g_source_remove, + g_source_remove, + NULL, /* input_get_error */ +#if GLIB_CHECK_VERSION(2,14,0) + g_timeout_add_seconds, +#else + NULL, +#endif + NULL, + NULL, NULL }; diff -r 2aad33bb021d -r fafb3af5aa12 libpurple/util.h --- a/libpurple/util.h Thu Jun 28 17:07:48 2007 +0000 +++ b/libpurple/util.h Sat Jun 30 22:12:44 2007 +0000 @@ -1105,12 +1105,13 @@ void purple_print_utf8_to_console(FILE *filestream, char *message); /** - * Checks for messages starting with "/me " + * Checks for messages starting (post-HTML) with "/me ", including the space. * * @param message The message to check * @param len The message length, or -1 * - * @return TRUE if it starts with /me, and it has been removed, otherwise FALSE + * @return TRUE if it starts with "/me ", and it has been removed, otherwise + * FALSE */ gboolean purple_message_meify(char *message, size_t len); diff -r 2aad33bb021d -r fafb3af5aa12 pidgin/gtkconv.c --- a/pidgin/gtkconv.c Thu Jun 28 17:07:48 2007 +0000 +++ b/pidgin/gtkconv.c Sat Jun 30 22:12:44 2007 +0000 @@ -2406,9 +2406,6 @@ return FALSE; } - gtkconv->auto_resize = TRUE; - g_idle_add(reset_auto_resize_cb, gtkconv); - gdk_pixbuf_animation_iter_advance(gtkconv->u.im->iter, NULL); buf = gdk_pixbuf_animation_iter_get_pixbuf(gtkconv->u.im->iter); @@ -4256,7 +4253,7 @@ if (sr.height < height + PIDGIN_HIG_BOX_SPACE) { gtkconv->auto_resize = TRUE; gtkconv->entry_growing = TRUE; - gtk_widget_set_size_request(gtkconv->lower_hbox, -1, height + PIDGIN_HIG_BOX_SPACE); + gtk_widget_set_size_request(gtkconv->entry, -1, height); g_idle_add(reset_auto_resize_cb, gtkconv); } } diff -r 2aad33bb021d -r fafb3af5aa12 pidgin/gtkutils.c --- a/pidgin/gtkutils.c Thu Jun 28 17:07:48 2007 +0000 +++ b/pidgin/gtkutils.c Sat Jun 30 22:12:44 2007 +0000 @@ -176,7 +176,7 @@ sw = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), - GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0); gtk_widget_show(sw);