Mercurial > pidgin
changeset 18113:97b735ca9d7a
merge of '55af2e26c71950d7f8fc3a7b6a9b2249abb5ae0f'
and 'ab66c9deff83832be4f49fffce0742d853b6c8b1'
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Sat, 16 Jun 2007 20:16:36 +0000 |
parents | f52def9dc7c9 (diff) d40fd7106ebf (current diff) |
children | 9b9e202eb449 |
files | ChangeLog.API libpurple/blist.c libpurple/conversation.c pidgin/gtkaccount.c pidgin/gtkblist.c pidgin/gtkconv.c pidgin/gtkdialogs.c pidgin/gtkimhtml.c pidgin/gtkimhtmltoolbar.c pidgin/gtkpounce.c pidgin/gtkutils.c |
diffstat | 172 files changed, 6032 insertions(+), 789 deletions(-) [+] |
line wrap: on
line diff
--- a/COPYRIGHT Fri Jun 15 08:16:29 2007 +0000 +++ b/COPYRIGHT Sat Jun 16 20:16:36 2007 +0000 @@ -52,6 +52,7 @@ Jeremy Brooks Jonathan Brossard Philip Brown +Norbert Buchmuller Sean Burke Thomas Butter Trevor Caira @@ -146,6 +147,7 @@ Charlie Gordon Ryan C. Gordon Miah Gregory +David Grohmann Christian Hammond Erick Hamness Fred Hampton
--- a/ChangeLog Fri Jun 15 08:16:29 2007 +0000 +++ b/ChangeLog Sat Jun 16 20:16:36 2007 +0000 @@ -1,5 +1,23 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul +version 2.1.0 (??/??/????): + libpurple: + * Core changes to allow UIs to use second-granularity for scheduling. + Pidgin and Finch, which use the glib event loop, were changed to use + g_timeout_add_seconds() on glib >= 2.14 when possible. This allows + glib to better group our longer timers to increase power efficiency. + (Arjan van de Ven with Intel Corporation) + * No longer linkifies screennames containing @ signs in join/part + notifications in chats + * With the HTML logger, images in conversations are now saved. + NOTE: Saved images are not yet displayed when loading logs. + + Pidgin: + * Ensure only one copy of Pidgin is running with a given configuration + directory. The net effect of this is that trying to start Pidgin a + second time will raise the buddy list. (Gabriel Schulhof) + * Undo capability in the conversation window + version 2.0.2 (06/14/2007): Pidgin: * Added a custom conversation font option to preferences
--- a/ChangeLog.API Fri Jun 15 08:16:29 2007 +0000 +++ b/ChangeLog.API Sat Jun 16 20:16:36 2007 +0000 @@ -1,5 +1,74 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul +version 2.1.0 (??/??/????): + libpurple: + Added: + * purple-remote: added getstatus command + * conversation-extended-menu signal (See Doxygen docs) + * OPT_PROTO_SLASH_COMMANDS_NATIVE protocol option to indicate that + slash commands are "native" to the protocol + * PURPLE_MESSAGE_NO_LINKIFY message flag to indicate that the message + should not be auto-linkified + * PurpleEventLoopUiOps.timeout_add_seconds + UIs can now use better scheduling for whole-second timers. For + example, clients based on the glib event loop can now use + g_timeout_add_seconds. + * gtk_imhtml_setup_entry + * pidgin_create_window + * purple_blist_node_get_type + * purple_conversation_do_command + * purple_conversation_get_extended_menu + * purple_core_ensure_single_instance + This is for UIs to use to ensure only one copy is running. + * purple_dbus_is_owner + * purple_dbusify_const_GList + * purple_dbusify_const_GSList + * purple_const_GList_to_array + * purple_const_GSList_to_array + * purple_image_data_calculate_filename + * pidgin_retrieve_user_info, shows immediate feedback when getting + information about a user. + * purple_timeout_add_seconds + Callers should prefer this to purple_timeout_add for timers + longer than 1 second away. Be aware of the rounding, though. + * purple_timeout_add_seconds + Callers should prefer this to purple_timeout_add for timers + longer than 1 second away. Be aware of the rounding, though. + * purple_xfer_get_remote_user + * gtk_imhtml_animation_new + Can be used for inserting an animated image into an IMHTML. + + Changed: + * Mark some return types const: + * purple_accounts_get_all + * purple_connections_get_all + * purple_connections_get_connecting + * purple_conv_chat_get_ignored + * purple_conv_chat_get_users + * purple_get_chats + * purple_get_conversations + * purple_get_ims + * purple_notify_user_info_get_entries + + Deprecated: + * purple_dbusify_GList: Use purple_dbusify_const_GList (and + g_list_free if needed) if depending on 2.1.0 is okay. + * purple_dbusify_GSList: Use purple_dbusify_const_GSList (and + g_slist_free if needed) if depending on 2.1.0 is okay.. + * purple_GList_to_array: Use purple_const_GList_to_array (and + g_list_free if needed) if depending on 2.1.0 is okay.. + * purple_GSList_to_array: Use purple_const_GSList_to_array (and + g_slist_free if needed) if depending on 2.1.0 is okay.. + + Pidgin: + Changed: + * pidgin_append_menu_action returns the menuitem added to the menu. + * pidgin_separator returns the separator added to the menu. + + Finch: + Added: + * finch_retrieve_user_info + version 2.0.2 (6/14/2007): Pidgin: Deprecated:
--- a/configure.ac Fri Jun 15 08:16:29 2007 +0000 +++ b/configure.ac Sat Jun 16 20:16:36 2007 +0000 @@ -43,19 +43,19 @@ # # Make sure to update finch/libgnt/configure.ac with libgnt version changes. # -m4_define([purple_lt_current], [0]) +m4_define([purple_lt_current], [1]) m4_define([purple_major_version], [2]) -m4_define([purple_minor_version], [0]) -m4_define([purple_micro_version], [2]) +m4_define([purple_minor_version], [1]) +m4_define([purple_micro_version], [0]) m4_define([purple_version_suffix], []) m4_define([purple_version], [purple_major_version.purple_minor_version.purple_micro_version]) m4_define([purple_display_version], purple_version[]m4_ifdef([purple_version_suffix],[purple_version_suffix])) -m4_define([gnt_lt_current], [0]) -m4_define([gnt_major_version], [1]) +m4_define([gnt_lt_current], [1]) +m4_define([gnt_major_version], [2]) m4_define([gnt_minor_version], [0]) -m4_define([gnt_micro_version], [2]) +m4_define([gnt_micro_version], [0]) m4_define([gnt_version_suffix], []) m4_define([gnt_version], [gnt_major_version.gnt_minor_version.gnt_micro_version])
--- a/doc/finch.1.in Fri Jun 15 08:16:29 2007 +0000 +++ b/doc/finch.1.in Sat Jun 16 20:16:36 2007 +0000 @@ -109,6 +109,15 @@ .B Ctrl \+ o Bring up the menu (if there is one) for a window. Note that currently only the buddylist has a menu. +.TP +.B Alt \+ Shift \+ . +Switch to the next workspace +.TP +.B Alt \+ Shift \+ , +Switch to the previous workspace +.TP +.B Alt \+ s +Show the workspace list .SH FILES \fI~/.gntrc\fR: configuration file for gnt applications. @@ -134,6 +143,33 @@ .br .br +# Workspaces are created simply by adding Workspace-X groups as follows: +.br +[Workspace-1] +.br +name = blist +.br +# window-names specifies that windows with these semi-colon separated names are placed +into this workspace +.br +window-names = buddylist;debug-window +.br + +.br +[Workspace-2] +.br +name = IM +.br +window-names = conversation-window +.br +# window-titles specifies that windows with these semi-colon separated titles are placed +into this workspace. These are matched as substrings. Window titles take precedence over +names. +.br +window-titles = Preferences;Pounce +.br + +.br [colors] .br # The RGB values range in [0, 1000]
--- a/finch/finch.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/finch.c Sat Jun 16 20:16:36 2007 +0000 @@ -156,11 +156,15 @@ gnt_input_add, g_source_remove, NULL, /* input_get_error */ +#if GLIB_CHECK_VERSION(2,14,0) + g_timeout_add_seconds, +#else + NULL, +#endif /* padding */ NULL, NULL, - NULL, NULL };
--- a/finch/gntaccount.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/gntaccount.c Sat Jun 16 20:16:36 2007 +0000 @@ -282,7 +282,11 @@ if (dialog->account) { - s = strrchr(username, purple_account_user_split_get_separator(split)); + if(purple_account_user_split_get_reverse(split)) + s = strrchr(username, purple_account_user_split_get_separator(split)); + else + s = strchr(username, purple_account_user_split_get_separator(split)); + if (s != NULL) { *s = '\0'; @@ -637,7 +641,7 @@ void finch_accounts_show_all() { - GList *iter; + const GList *iter; GntWidget *box, *button; if (accounts.window) @@ -730,7 +734,7 @@ void finch_accounts_init() { - GList *iter; + const GList *iter; purple_signal_connect(purple_accounts_get_handle(), "account-added", finch_accounts_get_handle(), PURPLE_CALLBACK(account_added_callback), @@ -827,7 +831,7 @@ { PurpleConnection *gc = purple_account_get_connection(data->account); - if (g_list_find(purple_connections_get_all(), gc)) + if (g_list_find((GList *)purple_connections_get_all(), gc)) { purple_blist_request_add_buddy(data->account, data->username, NULL, data->alias);
--- a/finch/gntblist.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/gntblist.c Sat Jun 16 20:16:36 2007 +0000 @@ -640,9 +640,18 @@ if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { PurpleBuddy *buddy = (PurpleBuddy *)node; - PurpleConversation *conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, - purple_buddy_get_account(buddy), - purple_buddy_get_name(buddy)); + PurpleConversation *conv; + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, + purple_buddy_get_name(buddy), + purple_buddy_get_account(buddy)); + if (!conv) { + conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, + purple_buddy_get_account(buddy), + purple_buddy_get_name(buddy)); + } else { + FinchConv *ggconv = conv->ui_data; + gnt_window_present(ggconv->window); + } finch_conversation_set_active(conv); } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) @@ -2308,6 +2317,8 @@ ggblist, 0, G_CONNECT_AFTER | G_CONNECT_SWAPPED); g_signal_connect_data(G_OBJECT(ggblist->tree), "lost-focus", G_CALLBACK(remove_peripherals), ggblist, 0, G_CONNECT_AFTER | G_CONNECT_SWAPPED); + g_signal_connect_data(G_OBJECT(ggblist->window), "workspace-hidden", G_CALLBACK(remove_peripherals), + ggblist, 0, G_CONNECT_AFTER | G_CONNECT_SWAPPED); g_signal_connect(G_OBJECT(ggblist->tree), "size_changed", G_CALLBACK(size_changed_cb), NULL); g_signal_connect(G_OBJECT(ggblist->window), "position_set", G_CALLBACK(save_position_cb), NULL); g_signal_connect(G_OBJECT(ggblist->window), "destroy", G_CALLBACK(reset_blist_window), NULL);
--- a/finch/gntconv.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/gntconv.c Sat Jun 16 20:16:36 2007 +0000 @@ -440,6 +440,16 @@ } static void +gained_focus_cb(GntWindow *window, FinchConv *fc) +{ + GList *iter; + for (iter = fc->list; iter; iter = iter->next) { + purple_conversation_set_data(iter->data, "unseen-count", 0); + purple_conversation_update(iter->data, PURPLE_CONV_UPDATE_UNSEEN); + } +} + +static void finch_create_conversation(PurpleConversation *conv) { FinchConv *ggc = conv->ui_data; @@ -529,6 +539,7 @@ g_free(title); gnt_box_give_focus_to_child(GNT_BOX(ggc->window), ggc->entry); + g_signal_connect(G_OBJECT(ggc->window), "gained-focus", G_CALLBACK(gained_focus_cb), ggc); } static void @@ -622,6 +633,11 @@ if (flags & (PURPLE_MESSAGE_RECV | PURPLE_MESSAGE_NICK | PURPLE_MESSAGE_ERROR)) gnt_widget_set_urgent(ggconv->tv); + if (flags & PURPLE_MESSAGE_RECV && !gnt_widget_has_focus(ggconv->window)) { + int count = GPOINTER_TO_INT(purple_conversation_get_data(conv, "unseen-count")); + purple_conversation_set_data(conv, "unseen-count", GINT_TO_POINTER(count + 1)); + purple_conversation_update(conv, PURPLE_CONV_UPDATE_UNSEEN); + } } static void
--- a/finch/gntplugin.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/gntplugin.c Sat Jun 16 20:16:36 2007 +0000 @@ -106,6 +106,9 @@ char *text; GList *list = NULL, *iter = NULL; + if (!plugin) + return; + /* If the selected plugin was unseen before, mark it as seen. But save the list * only when the plugin list is closed. So if the user enables a plugin, and it * crashes, it won't get marked as seen so the user can fix the bug and still
--- a/finch/gntpounce.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/gntpounce.c Sat Jun 16 20:16:36 2007 +0000 @@ -288,7 +288,7 @@ GntWidget *hbox, *vbox; GntWidget *button; GntWidget *combo; - GList *list; + const GList *list; g_return_if_fail((cur_pounce != NULL) || (account != NULL) || @@ -303,7 +303,7 @@ dialog->pounce = NULL; dialog->account = account; } else { - GList *connections = purple_connections_get_all(); + const GList *connections = purple_connections_get_all(); PurpleConnection *gc; if (connections != NULL) {
--- a/finch/gntrequest.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/gntrequest.c Sat Jun 16 20:16:36 2007 +0000 @@ -490,7 +490,7 @@ { gboolean all; PurpleAccount *def; - GList *list; + const GList *list; GntWidget *combo = gnt_combo_box_new(); gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID); gnt_box_add_widget(GNT_BOX(hbox), combo);
--- a/finch/gntstatus.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/gntstatus.c Sat Jun 16 20:16:36 2007 +0000 @@ -497,7 +497,7 @@ GntWidget *window, *box, *button, *entry, *combo, *label, *tree; PurpleStatusPrimitive prims[] = {PURPLE_STATUS_AVAILABLE, PURPLE_STATUS_AWAY, PURPLE_STATUS_INVISIBLE, PURPLE_STATUS_OFFLINE, PURPLE_STATUS_UNSET}, current; - GList *iter; + const GList *iter; int i; if (saved)
--- a/finch/libgnt/Makefile.am Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/Makefile.am Sat Jun 16 20:16:36 2007 +0000 @@ -32,6 +32,7 @@ gntutils.c \ gntwindow.c \ gntwm.c \ + gntws.c \ gntmain.c libgnt_la_headers = \ @@ -58,6 +59,7 @@ gntutils.h \ gntwindow.h \ gntwm.h \ + gntws.h \ gnt.h CLEANFILES = \
--- a/finch/libgnt/configure.ac Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/configure.ac Sat Jun 16 20:16:36 2007 +0000 @@ -24,11 +24,11 @@ # Make sure to update ../../configure.ac with libgnt version changes. # -m4_define([gnt_lt_current], [0]) -m4_define([gnt_major_version], [1]) +m4_define([gnt_lt_current], [1]) +m4_define([gnt_major_version], [2]) m4_define([gnt_minor_version], [0]) m4_define([gnt_micro_version], [0]) -m4_define([gnt_version_suffix], [beta7]) +m4_define([gnt_version_suffix], [devel]) m4_define([gnt_version], [gnt_major_version.gnt_minor_version.gnt_micro_version]) m4_define([gnt_display_version], gnt_version[]m4_ifdef([gnt_version_suffix],[gnt_version_suffix]))
--- a/finch/libgnt/gnt-skel.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gnt-skel.c Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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 "gnt-skel.h" enum
--- a/finch/libgnt/gnt-skel.h Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gnt-skel.h Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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_SKEL_H #define GNT_SKEL_H @@ -38,9 +60,19 @@ G_BEGIN_DECLS +/** + * + * + * @return + */ GType gnt_skel_get_gtype(void); -GntWidget *gnt_skel_new(); +/** + * + * + * @return + */ +GntWidget * gnt_skel_new(); G_END_DECLS
--- a/finch/libgnt/gnt.h Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gnt.h Sat Jun 16 20:16:36 2007 +0000 @@ -1,39 +1,141 @@ +/** + * 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 <glib.h> #include "gntwidget.h" #include "gntclipboard.h" #include "gntcolors.h" #include "gntkeys.h" +/** + * + */ void gnt_init(void); +/** + * + */ void gnt_main(void); +/** + * + * + * @return + */ gboolean gnt_ascii_only(void); +void gnt_window_present(GntWidget *window); +/** + * + * @param widget + */ void gnt_screen_occupy(GntWidget *widget); +/** + * + * @param widget + */ void gnt_screen_release(GntWidget *widget); +/** + * + * @param widget + */ void gnt_screen_update(GntWidget *widget); +/** + * + * @param widget + * @param width + * @param height + */ void gnt_screen_resize_widget(GntWidget *widget, int width, int height); +/** + * + * @param widget + * @param x + * @param y + */ void gnt_screen_move_widget(GntWidget *widget, int x, int y); +/** + * + * @param widget + * @param text + */ void gnt_screen_rename_widget(GntWidget *widget, const char *text); +/** + * + * @param widget + * + * @return + */ gboolean gnt_widget_has_focus(GntWidget *widget); +/** + * + * @param widget + */ void gnt_widget_set_urgent(GntWidget *widget); +/** + * + * @param label + * @param callback)() + */ void gnt_register_action(const char *label, void (*callback)()); +/** + * + * @param menu + * + * @return + */ gboolean gnt_screen_menu_show(gpointer menu); +/** + * + */ void gnt_quit(void); -GntClipboard *gnt_get_clipboard(void); +/** + * + * + * @return + */ +GntClipboard * gnt_get_clipboard(void); -gchar *gnt_get_clipboard_string(void); +/** + * + * + * @return + */ +gchar * gnt_get_clipboard_string(void); +/** + * + * @param string + */ void gnt_set_clipboard_string(gchar *string); +
--- a/finch/libgnt/gntbindable.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntbindable.c Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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 "gntbindable.h" #include "gntstyle.h" #include "gnt.h"
--- a/finch/libgnt/gntbindable.h Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntbindable.h Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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_BINDABLE_H #define GNT_BINDABLE_H @@ -39,6 +61,11 @@ G_BEGIN_DECLS +/** + * + * + * @return + */ GType gnt_bindable_get_gtype(void); /******************/ @@ -70,18 +97,53 @@ GList *list; }; - /*GntBindableAction *gnt_bindable_action_parse(const char *name);*/ +/** + * + * @param action + */ void gnt_bindable_action_free(GntBindableAction *action); + +/** + * + * @param param + */ void gnt_bindable_action_param_free(GntBindableActionParam *param); -void gnt_bindable_class_register_action(GntBindableClass *klass, const char *name, - GntBindableActionCallback callback, const char *trigger, ...); -void gnt_bindable_register_binding(GntBindableClass *klass, const char *name, - const char *trigger, ...); +/** + * + * @param klass + * @param name + * @param callback + * @param trigger + */ +void gnt_bindable_class_register_action(GntBindableClass *klass, const char *name, GntBindableActionCallback callback, const char *trigger, ...); + +/** + * + * @param klass + * @param name + * @param trigger + */ +void gnt_bindable_register_binding(GntBindableClass *klass, const char *name, const char *trigger, ...); +/** + * + * @param bindable + * @param keys + * + * @return + */ gboolean gnt_bindable_perform_action_key(GntBindable *bindable, const char *keys); + +/** + * + * @param bindable + * @param name + * + * @return + */ gboolean gnt_bindable_perform_action_named(GntBindable *bindable, const char *name, ...); G_END_DECLS
--- a/finch/libgnt/gntbox.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntbox.c Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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 "gntbox.h" #include "gntutils.h"
--- a/finch/libgnt/gntbox.h Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntbox.h Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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_BOX_H #define GNT_BOX_H @@ -61,35 +83,110 @@ G_BEGIN_DECLS +/** + * + * + * @return + */ GType gnt_box_get_gtype(void); #define gnt_vbox_new(homo) gnt_box_new(homo, TRUE) #define gnt_hbox_new(homo) gnt_box_new(homo, FALSE) -GntWidget *gnt_box_new(gboolean homo, gboolean vert); +/** + * + * @param homo + * @param vert + * + * @return + */ +GntWidget * gnt_box_new(gboolean homo, gboolean vert); +/** + * + * @param box + * @param widget + */ void gnt_box_add_widget(GntBox *box, GntWidget *widget); +/** + * + * @param box + * @param title + */ void gnt_box_set_title(GntBox *box, const char *title); +/** + * + * @param box + * @param pad + */ void gnt_box_set_pad(GntBox *box, int pad); +/** + * + * @param box + * @param set + */ void gnt_box_set_toplevel(GntBox *box, gboolean set); +/** + * + * @param box + */ void gnt_box_sync_children(GntBox *box); +/** + * + * @param box + * @param alignment + */ void gnt_box_set_alignment(GntBox *box, GntAlignment alignment); -void gnt_box_remove(GntBox *box, GntWidget *widget); /* XXX: does NOT destroy widget */ +/** + * + * @param box + * @param widget + */ +void gnt_box_remove(GntBox *box, GntWidget *widget); + + /* XXX: does NOT destroy widget */ -void gnt_box_remove_all(GntBox *box); /* Removes AND destroys all the widgets in it */ +/** + * + * @param box + */ +void gnt_box_remove_all(GntBox *box); + /* Removes AND destroys all the widgets in it */ + +/** + * + * @param box + */ void gnt_box_readjust(GntBox *box); +/** + * + * @param box + * @param fill + */ void gnt_box_set_fill(GntBox *box, gboolean fill); -void gnt_box_move_focus(GntBox *box, int dir); /* +1 to move forward, -1 for backward */ +/** + * + * @param box + * @param dir + */ +void gnt_box_move_focus(GntBox *box, int dir); + /* +1 to move forward, -1 for backward */ + +/** + * + * @param box + * @param widget + */ void gnt_box_give_focus_to_child(GntBox *box, GntWidget *widget); G_END_DECLS
--- a/finch/libgnt/gntbutton.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntbutton.c Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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 <string.h> #include "gntbutton.h"
--- a/finch/libgnt/gntbutton.h Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntbutton.h Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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_BUTTON_H #define GNT_BUTTON_H @@ -46,9 +68,20 @@ G_BEGIN_DECLS +/** + * + * + * @return + */ GType gnt_button_get_gtype(void); -GntWidget *gnt_button_new(const char *text); +/** + * + * @param text + * + * @return + */ +GntWidget * gnt_button_new(const char *text); G_END_DECLS
--- a/finch/libgnt/gntcheckbox.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntcheckbox.c Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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 "gntcheckbox.h" enum
--- a/finch/libgnt/gntcheckbox.h Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntcheckbox.h Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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_CHECK_BOX_H #define GNT_CHECK_BOX_H @@ -41,12 +63,34 @@ G_BEGIN_DECLS +/** + * + * + * @return + */ GType gnt_check_box_get_gtype(void); -GntWidget *gnt_check_box_new(const char *text); +/** + * + * @param text + * + * @return + */ +GntWidget * gnt_check_box_new(const char *text); +/** + * + * @param box + * @param set + */ void gnt_check_box_set_checked(GntCheckBox *box, gboolean set); +/** + * + * @param box + * + * @return + */ gboolean gnt_check_box_get_checked(GntCheckBox *box); G_END_DECLS
--- a/finch/libgnt/gntclipboard.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntclipboard.c Sat Jun 16 20:16:36 2007 +0000 @@ -1,6 +1,26 @@ -#include "gntclipboard.h" +/** + * 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 + */ -gchar *string; +#include "gntclipboard.h" enum { SIG_CLIPBOARD = 0,
--- a/finch/libgnt/gntclipboard.h Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntclipboard.h Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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_CLIPBOARD_H #define GNT_CLIPBOARD_H @@ -33,10 +55,26 @@ G_BEGIN_DECLS +/** + * + * + * @return + */ GType gnt_clipboard_get_gtype(void); -gchar *gnt_clipboard_get_string(GntClipboard *clip); +/** + * + * @param clip + * + * @return + */ +gchar * gnt_clipboard_get_string(GntClipboard *clip); +/** + * + * @param clip + * @param string + */ void gnt_clipboard_set_string(GntClipboard *clip, gchar *string); G_END_DECLS
--- a/finch/libgnt/gntcolors.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntcolors.c Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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 "config.h" #include <ncurses.h>
--- a/finch/libgnt/gntcolors.h Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntcolors.h Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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_COLORS_H #define GNT_COLORS_H @@ -33,14 +55,29 @@ }; /* populate some default colors */ +/** + * + */ void gnt_init_colors(void); +/** + * + */ void gnt_uninit_colors(void); #if GLIB_CHECK_VERSION(2,6,0) +/** + * + * @param kfile + */ void gnt_colors_parse(GKeyFile *kfile); +/** + * + * @param kfile + */ void gnt_color_pairs_parse(GKeyFile *kfile); + #endif #endif
--- a/finch/libgnt/gntcombobox.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntcombobox.c Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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 "gntbox.h" #include "gntcombobox.h" #include "gnttree.h"
--- a/finch/libgnt/gntcombobox.h Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntcombobox.h Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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_COMBO_BOX_H #define GNT_COMBO_BOX_H @@ -42,18 +64,54 @@ G_BEGIN_DECLS +/** + * + * + * @return + */ GType gnt_combo_box_get_gtype(void); -GntWidget *gnt_combo_box_new(void); +/** + * + * + * @return + */ +GntWidget * gnt_combo_box_new(void); +/** + * + * @param box + * @param key + * @param text + */ void gnt_combo_box_add_data(GntComboBox *box, gpointer key, const char *text); +/** + * + * @param box + * @param key + */ void gnt_combo_box_remove(GntComboBox *box, gpointer key); +/** + * + * @param box + */ void gnt_combo_box_remove_all(GntComboBox *box); +/** + * + * @param box + * + * @return + */ gpointer gnt_combo_box_get_selected_data(GntComboBox *box); +/** + * + * @param box + * @param key + */ void gnt_combo_box_set_selected(GntComboBox *box, gpointer key); G_END_DECLS
--- a/finch/libgnt/gntentry.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntentry.c Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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 <ctype.h> #include <string.h>
--- a/finch/libgnt/gntentry.h Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntentry.h Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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_ENTRY_H #define GNT_ENTRY_H @@ -73,32 +95,97 @@ G_BEGIN_DECLS +/** + * + * + * @return + */ GType gnt_entry_get_gtype(void); -GntWidget *gnt_entry_new(const char *text); +/** + * + * @param text + * + * @return + */ +GntWidget * gnt_entry_new(const char *text); +/** + * + * @param entry + * @param max + */ void gnt_entry_set_max(GntEntry *entry, int max); +/** + * + * @param entry + * @param text + */ void gnt_entry_set_text(GntEntry *entry, const char *text); +/** + * + * @param entry + * @param flag + */ void gnt_entry_set_flag(GntEntry *entry, GntEntryFlag flag); const char *gnt_entry_get_text(GntEntry *entry); +/** + * + * @param entry + */ void gnt_entry_clear(GntEntry *entry); +/** + * + * @param entry + * @param set + */ void gnt_entry_set_masked(GntEntry *entry, gboolean set); +/** + * + * @param entry + * @param text + */ void gnt_entry_add_to_history(GntEntry *entry, const char *text); +/** + * + * @param entry + * @param num + */ void gnt_entry_set_history_length(GntEntry *entry, int num); +/** + * + * @param entry + * @param word + */ void gnt_entry_set_word_suggest(GntEntry *entry, gboolean word); +/** + * + * @param entry + * @param always + */ void gnt_entry_set_always_suggest(GntEntry *entry, gboolean always); +/** + * + * @param entry + * @param text + */ void gnt_entry_add_suggest(GntEntry *entry, const char *text); +/** + * + * @param entry + * @param text + */ void gnt_entry_remove_suggest(GntEntry *entry, const char *text); G_END_DECLS
--- a/finch/libgnt/gntfilesel.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntfilesel.c Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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 "gntbutton.h" #include "gntentry.h" #include "gntfilesel.h"
--- a/finch/libgnt/gntfilesel.h Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntfilesel.h Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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_FILE_SEL_H #define GNT_FILE_SEL_H @@ -71,32 +93,115 @@ G_BEGIN_DECLS +/** + * + * + * @return + */ GType gnt_file_sel_get_gtype(void); -GntWidget *gnt_file_sel_new(void); +/** + * + * + * @return + */ +GntWidget * gnt_file_sel_new(void); +/** + * + * @param sel + * @param path + * + * @return + */ gboolean gnt_file_sel_set_current_location(GntFileSel *sel, const char *path); +/** + * + * @param sel + * @param dirs + */ void gnt_file_sel_set_dirs_only(GntFileSel *sel, gboolean dirs); +/** + * + * @param sel + * + * @return + */ gboolean gnt_file_sel_get_dirs_only(GntFileSel *sel); +/** + * + * @param sel + * @param must + */ void gnt_file_sel_set_must_exist(GntFileSel *sel, gboolean must); +/** + * + * @param sel + * + * @return + */ gboolean gnt_file_sel_get_must_exist(GntFileSel *sel); -char *gnt_file_sel_get_selected_file(GntFileSel *sel); /* The returned value should be free'd */ +/** + * + * @param sel + * + * @return + */ +char * gnt_file_sel_get_selected_file(GntFileSel *sel); + + /* The returned value should be free'd */ -GList *gnt_file_sel_get_selected_multi_files(GntFileSel *sel); +/** + * + * @param sel + * + * @return + */ +GList * gnt_file_sel_get_selected_multi_files(GntFileSel *sel); +/** + * + * @param sel + * @param set + */ void gnt_file_sel_set_multi_select(GntFileSel *sel, gboolean set); +/** + * + * @param sel + * @param suggest + */ void gnt_file_sel_set_suggested_filename(GntFileSel *sel, const char *suggest); +/** + * + * @param sel + * @param path + * @param files + * @param error) + */ void gnt_file_sel_set_read_fn(GntFileSel *sel, gboolean (*read_fn)(const char *path, GList **files, GError **error)); +/** + * + * @param name + * @param size + * + * @return + */ GntFile* gnt_file_new(const char *name, unsigned long size); +/** + * + * @param name + * + * @return + */ GntFile* gnt_file_new_dir(const char *name); G_END_DECLS
--- a/finch/libgnt/gntkeys.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntkeys.c Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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 "gntkeys.h" #include <glib.h> @@ -184,8 +206,8 @@ node->flags |= IS_END; return; } - while (*path && node->next[*path]) { - node = node->next[*path]; + while (*path && node->next[(unsigned char)*path]) { + node = node->next[(unsigned char)*path]; node->ref++; path++; } @@ -193,7 +215,7 @@ return; n = g_new0(struct _node, 1); n->ref = 1; - node->next[*path++] = n; + node->next[(unsigned char)*path++] = n; add_path(n, path); } @@ -208,13 +230,13 @@ if (!*path) return; - next = node->next[*path]; + next = node->next[(unsigned char)*path]; if (!next) return; del_path(next, path + 1); next->ref--; if (next->ref == 0) { - node->next[*path] = NULL; + node->next[(unsigned char)*path] = NULL; g_free(next); } } @@ -230,12 +252,12 @@ struct _node *n = &root; root.flags &= ~IS_END; - while (*path && n->next[*path] && !(n->flags & IS_END)) { + while (*path && n->next[(unsigned char)*path] && !(n->flags & IS_END)) { if (!g_ascii_isspace(*path) && !g_ascii_iscntrl(*path) && !g_ascii_isgraph(*path)) return 0; - n = n->next[*path++]; + n = n->next[(unsigned char)*path++]; depth++; }
--- a/finch/libgnt/gntkeys.h Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntkeys.h Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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_KEYS_H #define GNT_KEYS_H @@ -80,16 +102,40 @@ /** * This will do stuff with the terminal settings and stuff. */ +/** + * + */ void gnt_init_keys(void); + +/** + * + * @param text + */ void gnt_keys_refine(char *text); + const char *gnt_key_translate(const char *name); const char *gnt_key_lookup(const char *key); +/** + * + * @param path + */ void gnt_keys_add_combination(const char *path); + +/** + * + * @param path + */ void gnt_keys_del_combination(const char *path); + +/** + * + * @param path + * + * @return + */ int gnt_keys_find_combination(const char *path); - /* A lot of commonly used variable names are defined in <term.h>. * #undef them to make life easier for everyone. */
--- a/finch/libgnt/gntlabel.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntlabel.c Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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 "gntlabel.h" #include "gntutils.h"
--- a/finch/libgnt/gntlabel.h Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntlabel.h Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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_LABEL_H #define GNT_LABEL_H @@ -40,12 +62,35 @@ G_BEGIN_DECLS +/** + * + * + * @return + */ GType gnt_label_get_gtype(void); -GntWidget *gnt_label_new(const char *text); +/** + * + * @param text + * + * @return + */ +GntWidget * gnt_label_new(const char *text); -GntWidget *gnt_label_new_with_format(const char *text, GntTextFormatFlags flags); +/** + * + * @param text + * @param flags + * + * @return + */ +GntWidget * gnt_label_new_with_format(const char *text, GntTextFormatFlags flags); +/** + * + * @param label + * @param text + */ void gnt_label_set_text(GntLabel *label, const char *text); G_END_DECLS
--- a/finch/libgnt/gntline.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntline.c Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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 "gntline.h" enum
--- a/finch/libgnt/gntline.h Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntline.h Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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_LINE_H #define GNT_LINE_H @@ -40,12 +62,23 @@ G_BEGIN_DECLS +/** + * + * + * @return + */ GType gnt_line_get_gtype(void); #define gnt_hline_new() gnt_line_new(FALSE) #define gnt_vline_new() gnt_line_new(TRUE) -GntWidget *gnt_line_new(gboolean vertical); +/** + * + * @param vertical + * + * @return + */ +GntWidget * gnt_line_new(gboolean vertical); G_END_DECLS
--- a/finch/libgnt/gntmain.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntmain.c Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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 + */ + #define _GNU_SOURCE #if defined(__APPLE__) || defined(__unix__) #define _XOPEN_SOURCE_EXTENDED @@ -51,7 +73,7 @@ static gboolean refresh_screen(); -GntWM *wm; +static GntWM *wm; static GntClipboard *clipboard; #define HOLDING_ESCAPE (escape_stuff.timer != 0) @@ -94,7 +116,7 @@ GntWidget *widget = NULL; PANEL *p = NULL; - if (!wm->ordered || buffer[0] != 27) + if (!wm->cws->ordered || buffer[0] != 27) return FALSE; buffer++; @@ -150,7 +172,7 @@ if (event == GNT_LEFT_MOUSE_DOWN && widget && widget != wm->_list.window && !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_TRANSIENT)) { - if (widget != wm->ordered->data) { + if (widget != wm->cws->ordered->data) { gnt_wm_raise_window(wm, widget); } if (y == widget->priv.y) { @@ -161,7 +183,7 @@ } else if (event == GNT_MOUSE_UP) { if (button == MOUSE_NONE && y == getmaxy(stdscr) - 1) { /* Clicked on the taskbar */ - int n = g_list_length(wm->list); + int n = g_list_length(wm->cws->list); if (n) { int width = getmaxx(stdscr) / n; gnt_bindable_perform_action_named(GNT_BINDABLE(wm), "switch-window-n", x/width, NULL); @@ -462,6 +484,10 @@ * Stuff for 'window management' * *********************************/ +void gnt_window_present(GntWidget *window) { + gnt_wm_raise_window(wm, window); +} + void gnt_screen_occupy(GntWidget *widget) { gnt_wm_new_window(wm, widget); @@ -493,7 +519,7 @@ if (widget == wm->_list.window) return TRUE; - if (wm->ordered && wm->ordered->data == widget) { + if (wm->cws->ordered && wm->cws->ordered->data == widget) { if (GNT_IS_BOX(widget) && (GNT_BOX(widget)->active == w || widget == w)) return TRUE; @@ -506,7 +532,7 @@ while (widget->parent) widget = widget->parent; - if (wm->ordered && wm->ordered->data == widget) + if (wm->cws->ordered && wm->cws->ordered->data == widget) return; GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_URGENT);
--- a/finch/libgnt/gntmenu.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntmenu.c Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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 "gntmenu.h" #include "gntmenuitemcheck.h" @@ -220,7 +242,10 @@ static void gnt_menu_hide(GntWidget *widget) { - GntMenu *menu = GNT_MENU(widget); + GntMenu *sub, *menu = GNT_MENU(widget); + + while ((sub = menu->submenu)) + gnt_widget_hide(GNT_WIDGET(sub)); if (menu->parentmenu) menu->parentmenu->submenu = NULL; }
--- a/finch/libgnt/gntmenu.h Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntmenu.h Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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_MENU_H #define GNT_MENU_H @@ -59,10 +81,26 @@ G_BEGIN_DECLS +/** + * + * + * @return + */ GType gnt_menu_get_gtype(void); -GntWidget *gnt_menu_new(GntMenuType type); +/** + * + * @param type + * + * @return + */ +GntWidget * gnt_menu_new(GntMenuType type); +/** + * + * @param menu + * @param item + */ void gnt_menu_add_item(GntMenu *menu, GntMenuItem *item); G_END_DECLS
--- a/finch/libgnt/gntmenuitem.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntmenuitem.c Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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 "gntmenu.h" #include "gntmenuitem.h"
--- a/finch/libgnt/gntmenuitem.h Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntmenuitem.h Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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_MENUITEM_H #define GNT_MENUITEM_H @@ -58,12 +80,34 @@ G_BEGIN_DECLS +/** + * + * + * @return + */ GType gnt_menuitem_get_gtype(void); -GntMenuItem *gnt_menuitem_new(const char *text); +/** + * + * @param text + * + * @return + */ +GntMenuItem * gnt_menuitem_new(const char *text); +/** + * + * @param item + * @param callback + * @param data + */ void gnt_menuitem_set_callback(GntMenuItem *item, GntMenuItemCallback callback, gpointer data); +/** + * + * @param item + * @param menu + */ void gnt_menuitem_set_submenu(GntMenuItem *item, GntMenu *menu); G_END_DECLS
--- a/finch/libgnt/gntmenuitemcheck.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntmenuitemcheck.c Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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 "gntmenuitemcheck.h" static GntMenuItemClass *parent_class = NULL;
--- a/finch/libgnt/gntmenuitemcheck.h Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntmenuitemcheck.h Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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_MENU_ITEM_CHECK_H #define GNT_MENU_ITEM_CHECK_H @@ -39,12 +61,34 @@ G_BEGIN_DECLS +/** + * + * + * @return + */ GType gnt_menuitem_check_get_gtype(void); -GntMenuItem *gnt_menuitem_check_new(const char *text); +/** + * + * @param text + * + * @return + */ +GntMenuItem * gnt_menuitem_check_new(const char *text); +/** + * + * @param item + * + * @return + */ gboolean gnt_menuitem_check_get_checked(GntMenuItemCheck *item); +/** + * + * @param item + * @param set + */ void gnt_menuitem_check_set_checked(GntMenuItemCheck *item, gboolean set); G_END_DECLS
--- a/finch/libgnt/gntstyle.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntstyle.c Sat Jun 16 20:16:36 2007 +0000 @@ -1,13 +1,42 @@ +/** + * 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 "gntstyle.h" #include "gntcolors.h" +#include "gntws.h" +#include <glib.h> #include <ctype.h> +#include <glib/gprintf.h> +#include <stdlib.h> #include <string.h> +#define MAX_WORKSPACES 99 + #if GLIB_CHECK_VERSION(2,6,0) static GKeyFile *gkfile; #endif +static GHashTable *unknowns; static char * str_styles[GNT_STYLES]; static int int_styles[GNT_STYLES]; static int bool_styles[GNT_STYLES]; @@ -17,6 +46,11 @@ return str_styles[style]; } +const char *gnt_style_get_from_name(const char *name) +{ + return g_hash_table_lookup(unknowns, name); +} + gboolean gnt_style_get_bool(GntStyle style, gboolean def) { int i; @@ -87,6 +121,44 @@ return (char *)gnt_key_translate(key); } +void gnt_style_read_workspaces(GntWM *wm) +{ +#if GLIB_CHECK_VERSION(2,6,0) + int i; + gchar *name; + gsize c; + + for (i = 1; i < MAX_WORKSPACES; ++i) { + int j; + GntWS *ws; + gchar **titles; + char *group = calloc(12, 1); + g_sprintf(group, "Workspace-%d", i); + name = g_key_file_get_value(gkfile, group, "name", NULL); + if (!name) + return; + + ws = gnt_ws_new(name); + gnt_wm_add_workspace(wm, ws); + g_free(name); + + titles = g_key_file_get_string_list(gkfile, group, "window-names", &c, NULL); + if (titles) { + for (j = 0; j < c; ++j) + g_hash_table_replace(wm->name_places, g_strdup(titles[j]), ws); + g_strfreev(titles); + } + + titles = g_key_file_get_string_list(gkfile, group, "window-titles", &c, NULL); + if (titles) { + for (j = 0; j < c; ++j) + g_hash_table_replace(wm->title_places, g_strdup(titles[j]), ws); + g_strfreev(titles); + } + g_free(group); + } +#endif +} void gnt_style_read_actions(GType type, GntBindableClass *klass) { #if GLIB_CHECK_VERSION(2,6,0) @@ -221,6 +293,10 @@ str_styles[styles[i].en] = g_key_file_get_string(kfile, "general", styles[i].style, NULL); } + + for (i = 0; i < nkeys; i++) + g_hash_table_replace(unknowns, g_strdup(keys[i]), + g_strdup(g_key_file_get_string(kfile, "general", keys[i], NULL))); } g_strfreev(keys); } @@ -231,6 +307,7 @@ #if GLIB_CHECK_VERSION(2,6,0) GError *error = NULL; gkfile = g_key_file_new(); + unknowns = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); if (!g_key_file_load_from_file(gkfile, filename, G_KEY_FILE_NONE, &error)) { @@ -260,6 +337,7 @@ for (i = 0; i < GNT_STYLES; i++) g_free(str_styles[i]); + g_hash_table_destroy(unknowns); #if GLIB_CHECK_VERSION(2,6,0) g_key_file_free(gkfile); #endif
--- a/finch/libgnt/gntstyle.h Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntstyle.h Sat Jun 16 20:16:36 2007 +0000 @@ -1,4 +1,27 @@ +/** + * 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 "gnt.h" +#include "gntwm.h" typedef enum { @@ -10,18 +33,49 @@ GNT_STYLES } GntStyle; +/** + * + * @param filename + */ void gnt_style_read_configure_file(const char *filename); const char *gnt_style_get(GntStyle style); +const char *gnt_style_get_from_name(const char *key); + +/** + * + * @param style + * @param def + * + * @return + */ gboolean gnt_style_get_bool(GntStyle style, gboolean def); /* This should be called only once for the each type */ +/** + * + * @param type + * @param hash + */ void gnt_styles_get_keyremaps(GType type, GHashTable *hash); +/** + * + * @param type + * @param klass + */ void gnt_style_read_actions(GType type, GntBindableClass *klass); +void gnt_style_read_workspaces(GntWM *wm); + +/** + * + */ void gnt_init_styles(void); +/** + * + */ void gnt_uninit_styles(void);
--- a/finch/libgnt/gnttextview.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gnttextview.c Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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 "gnttextview.h" #include "gntutils.h"
--- a/finch/libgnt/gnttextview.h Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gnttextview.h Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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_TEXT_VIEW_H #define GNT_TEXT_VIEW_H @@ -53,34 +75,102 @@ G_BEGIN_DECLS +/** + * + * + * @return + */ GType gnt_text_view_get_gtype(void); /* XXX: For now, don't set a textview to have any border. * If you want borders real bad, put it in a box. */ -GntWidget *gnt_text_view_new(void); +/** + * + * + * @return + */ +GntWidget * gnt_text_view_new(void); /* scroll > 0 means scroll up, < 0 means scroll down, == 0 means scroll to the end */ +/** + * + * @param view + * @param scroll + */ void gnt_text_view_scroll(GntTextView *view, int scroll); +/** + * + * @param view + * @param text + * @param flags + */ void gnt_text_view_append_text_with_flags(GntTextView *view, const char *text, GntTextFormatFlags flags); +/** + * + * @param view + * @param text + * @param flags + * @param tag + */ void gnt_text_view_append_text_with_tag(GntTextView *view, const char *text, GntTextFormatFlags flags, const char *tag); /* Move the cursor to the beginning of the next line and resets text-attributes. * It first completes the current line with the current text-attributes. */ +/** + * + * @param view + */ void gnt_text_view_next_line(GntTextView *view); +/** + * + * @param flags + * + * @return + */ chtype gnt_text_format_flag_to_chtype(GntTextFormatFlags flags); +/** + * + * @param view + */ void gnt_text_view_clear(GntTextView *view); +/** + * + * @param view + * + * @return + */ int gnt_text_view_get_lines_below(GntTextView *view); +/** + * + * @param view + * + * @return + */ int gnt_text_view_get_lines_above(GntTextView *view); /* If text is NULL, then the tag is removed. */ +/** + * + * @param view + * @param name + * @param text + * @param all + * + * @return + */ int gnt_text_view_tag_change(GntTextView *view, const char *name, const char *text, gboolean all); +/** + * + * @param view + * @param widget + */ void gnt_text_view_attach_scroll_widget(GntTextView *view, GntWidget *widget); G_END_DECLS
--- a/finch/libgnt/gnttree.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gnttree.c Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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 "gntmarshal.h" #include "gntstyle.h" #include "gnttree.h" @@ -281,7 +303,7 @@ notfirst = TRUE; - if (len > width) { + if (len > width - 2) { len = width - 1; cut = TRUE; } @@ -731,15 +753,16 @@ g_signal_emit(tree, signals[SIG_TOGGLED], 0, row->key); redraw_tree(tree); } + } else { + return FALSE; } if (old != tree->current) { tree_selection_changed(tree, old, tree->current); - return TRUE; } - return FALSE; + return TRUE; } static void
--- a/finch/libgnt/gnttree.h Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gnttree.h Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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_TREE_H #define GNT_TREE_H @@ -74,75 +96,267 @@ G_BEGIN_DECLS +/** + * + * + * @return + */ GType gnt_tree_get_gtype(void); -GntWidget *gnt_tree_new(void); /* A tree with just one column */ +/** + * + * + * @return + */ +GntWidget * gnt_tree_new(void); + + /* A tree with just one column */ -GntWidget *gnt_tree_new_with_columns(int columns); +/** + * + * @param columns + * + * @return + */ +GntWidget * gnt_tree_new_with_columns(int columns); +/** + * + * @param tree + * @param rows + */ void gnt_tree_set_visible_rows(GntTree *tree, int rows); +/** + * + * @param tree + * + * @return + */ int gnt_tree_get_visible_rows(GntTree *tree); +/** + * + * @param tree + * @param count + */ void gnt_tree_scroll(GntTree *tree, int count); -GntTreeRow *gnt_tree_add_row_after(GntTree *tree, void *key, GntTreeRow *row, void *parent, void *bigbro); +/** + * + * @param tree + * @param key + * @param row + * @param parent + * @param bigbro + * + * @return + */ +GntTreeRow * gnt_tree_add_row_after(GntTree *tree, void *key, GntTreeRow *row, void *parent, void *bigbro); -GntTreeRow *gnt_tree_add_row_last(GntTree *tree, void *key, GntTreeRow *row, void *parent); +/** + * + * @param tree + * @param key + * @param row + * @param parent + * + * @return + */ +GntTreeRow * gnt_tree_add_row_last(GntTree *tree, void *key, GntTreeRow *row, void *parent); +/** + * + * @param tree + * + * @return + */ gpointer gnt_tree_get_selection_data(GntTree *tree); /* Returned string needs to be freed */ -char *gnt_tree_get_selection_text(GntTree *tree); +/** + * + * @param tree + * + * @return + */ +char * gnt_tree_get_selection_text(GntTree *tree); -GList *gnt_tree_get_selection_text_list(GntTree *tree); +/** + * + * @param tree + * + * @return + */ +GList * gnt_tree_get_selection_text_list(GntTree *tree); const GList *gnt_tree_get_rows(GntTree *tree); +/** + * + * @param tree + * @param key + */ void gnt_tree_remove(GntTree *tree, gpointer key); +/** + * + * @param tree + */ void gnt_tree_remove_all(GntTree *tree); /* Returns the visible line number of the selected row */ +/** + * + * @param tree + * + * @return + */ int gnt_tree_get_selection_visible_line(GntTree *tree); +/** + * + * @param tree + * @param key + * @param colno + * @param text + */ void gnt_tree_change_text(GntTree *tree, gpointer key, int colno, const char *text); -GntTreeRow *gnt_tree_add_choice(GntTree *tree, void *key, GntTreeRow *row, void *parent, void *bigbro); +/** + * + * @param tree + * @param key + * @param row + * @param parent + * @param bigbro + * + * @return + */ +GntTreeRow * gnt_tree_add_choice(GntTree *tree, void *key, GntTreeRow *row, void *parent, void *bigbro); +/** + * + * @param tree + * @param key + * @param set + */ void gnt_tree_set_choice(GntTree *tree, void *key, gboolean set); +/** + * + * @param tree + * @param key + * + * @return + */ gboolean gnt_tree_get_choice(GntTree *tree, void *key); +/** + * + * @param tree + * @param key + * @param flags + */ void gnt_tree_set_row_flags(GntTree *tree, void *key, GntTextFormatFlags flags); +/** + * + * @param key + */ void gnt_tree_set_selected(GntTree *tree , void *key); -GntTreeRow *gnt_tree_create_row(GntTree *tree, ...); +/** + * + * @param tree + * + * @return + */ +GntTreeRow * gnt_tree_create_row(GntTree *tree, ...); -GntTreeRow *gnt_tree_create_row_from_list(GntTree *tree, GList *list); +/** + * + * @param tree + * @param list + * + * @return + */ +GntTreeRow * gnt_tree_create_row_from_list(GntTree *tree, GList *list); +/** + * + * @param tree + * @param col + * @param width + */ void gnt_tree_set_col_width(GntTree *tree, int col, int width); +/** + * + * @param tree + */ void gnt_tree_set_column_titles(GntTree *tree, ...); +/** + * + * @param tree + * @param set + */ void gnt_tree_set_show_title(GntTree *tree, gboolean set); +/** + * + * @param tree + * @param func + */ void gnt_tree_set_compare_func(GntTree *tree, GCompareFunc func); +/** + * + * @param tree + * @param key + * @param expanded + */ void gnt_tree_set_expanded(GntTree *tree, void *key, gboolean expanded); +/** + * + * @param tree + * @param set + */ void gnt_tree_set_show_separator(GntTree *tree, gboolean set); +/** + * + * @param tree + * @param row + */ void gnt_tree_sort_row(GntTree *tree, void *row); /* This will try to automatically adjust the width of the columns in the tree */ +/** + * + * @param tree + */ void gnt_tree_adjust_columns(GntTree *tree); +/** + * + * @param tree + * @param hash + * @param eq + * @param kd + */ void gnt_tree_set_hash_fns(GntTree *tree, gpointer hash, gpointer eq, gpointer kd); /* This can be useful when, for example, we want to store some data * which we don't want/need to display. */ +/** + * + * @param tree + * @param col + * @param vis + */ void gnt_tree_set_column_visible(GntTree *tree, int col, gboolean vis); G_END_DECLS @@ -150,6 +364,11 @@ /* The following functions should NOT be used by applications. */ /* This should be called by the subclasses of GntTree's in their _new function */ +/** + * + * @param tree + * @param col + */ void _gnt_tree_init_internals(GntTree *tree, int col); #endif /* GNT_TREE_H */
--- a/finch/libgnt/gntutils.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntutils.c Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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 "gntbutton.h" #include "gntcheckbox.h" #include "gntcombobox.h"
--- a/finch/libgnt/gntutils.h Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntutils.h Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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 <glib.h> #include "gnt.h" @@ -5,9 +27,22 @@ typedef gpointer (*GDupFunc)(gconstpointer data); +/** + * + * @param text + * @param width + * @param height + */ void gnt_util_get_text_bound(const char *text, int *width, int *height); /* excluding *end */ +/** + * + * @param start + * @param end + * + * @return + */ int gnt_util_onscreen_width(const char *start, const char *end); const char *gnt_util_onscreen_width_to_pointer(const char *str, int len, int *w); @@ -18,29 +53,62 @@ * * Returns a newly allocated string. */ -char *gnt_util_onscreen_fit_string(const char *string, int maxw); +/** + * + * @param string + * @param maxw + * + * @return + */ +char * gnt_util_onscreen_fit_string(const char *string, int maxw); -GHashTable *g_hash_table_duplicate(GHashTable *src, GHashFunc hash, - GEqualFunc equal, GDestroyNotify key_d, GDestroyNotify value_d, - GDupFunc key_dup, GDupFunc value_dup); - +/** + * + * @param src + * @param hash + * @param equal + * @param key_d + * @param value_d + * @param key_dup + * @param value_dup + * + * @return + */ +GHashTable * g_hash_table_duplicate(GHashTable *src, GHashFunc hash, GEqualFunc equal, GDestroyNotify key_d, GDestroyNotify value_d, GDupFunc key_dup, GDupFunc value_dup); /** * To be used with g_signal_new. Look in the key_pressed signal-definition in * gntwidget.c for usage. */ -gboolean gnt_boolean_handled_accumulator(GSignalInvocationHint *ihint, - GValue *return_accu, - const GValue *handler_return, - gpointer dummy); +/** + * + * @param ihint + * @param return_accu + * @param handler_return + * @param dummy + * + * @return + */ +gboolean gnt_boolean_handled_accumulator(GSignalInvocationHint *ihint, GValue *return_accu, const GValue *handler_return, gpointer dummy); /** * Returns a GntTree populated with "key" -> "binding" for the widget. */ -GntWidget *gnt_widget_bindings_view(GntWidget *widget); +/** + * + * @param widget + * + * @return + */ +GntWidget * gnt_widget_bindings_view(GntWidget *widget); /** * Parse widgets from 'string'. */ +/** + * + * @param string + * @param num + */ void gnt_util_parse_widgets(const char *string, int num, ...);
--- a/finch/libgnt/gntwidget.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntwidget.c Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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 + */ + /* Stuff brutally ripped from Gflib */ #include "gntwidget.h"
--- a/finch/libgnt/gntwidget.h Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntwidget.h Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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_WIDGET_H #define GNT_WIDGET_H @@ -112,39 +134,169 @@ G_BEGIN_DECLS +/** + * + * + * @return + */ GType gnt_widget_get_gtype(void); + +/** + * + * @param widget + */ void gnt_widget_destroy(GntWidget *widget); + +/** + * + * @param widget + */ void gnt_widget_show(GntWidget *widget); + +/** + * + * @param widget + */ void gnt_widget_draw(GntWidget *widget); + +/** + * + * @param widget + * @param x + * @param y + * @param width + * @param height + */ void gnt_widget_expose(GntWidget *widget, int x, int y, int width, int height); + +/** + * + * @param widget + */ void gnt_widget_hide(GntWidget *widget); +/** + * + * @param widget + * @param x + * @param y + */ void gnt_widget_get_position(GntWidget *widget, int *x, int *y); + +/** + * + * @param widget + * @param x + * @param y + */ void gnt_widget_set_position(GntWidget *widget, int x, int y); + +/** + * + * @param widget + */ void gnt_widget_size_request(GntWidget *widget); + +/** + * + * @param widget + * @param width + * @param height + */ void gnt_widget_get_size(GntWidget *widget, int *width, int *height); + +/** + * + * @param widget + * @param width + * @param height + * + * @return + */ gboolean gnt_widget_set_size(GntWidget *widget, int width, int height); + +/** + * + * @param widget + * @param width + * @param height + * + * @return + */ gboolean gnt_widget_confirm_size(GntWidget *widget, int width, int height); +/** + * + * @param widget + * @param keys + * + * @return + */ gboolean gnt_widget_key_pressed(GntWidget *widget, const char *keys); +/** + * + * @param widget + * @param event + * @param x + * @param y + * + * @return + */ gboolean gnt_widget_clicked(GntWidget *widget, GntMouseEvent event, int x, int y); +/** + * + * @param widget + * @param set + * + * @return + */ gboolean gnt_widget_set_focus(GntWidget *widget, gboolean set); + +/** + * + * @param widget + */ void gnt_widget_activate(GntWidget *widget); +/** + * + * @param widget + * @param name + */ void gnt_widget_set_name(GntWidget *widget, const char *name); const char *gnt_widget_get_name(GntWidget *widget); /* Widget-subclasses should call this from the draw-callback. * Applications should just call gnt_widget_draw instead of this. */ +/** + * + * @param widget + */ void gnt_widget_queue_update(GntWidget *widget); +/** + * + * @param widget + * @param set + */ void gnt_widget_set_take_focus(GntWidget *widget, gboolean set); +/** + * + * @param widget + * @param set + */ void gnt_widget_set_visible(GntWidget *widget, gboolean set); +/** + * + * @param widget + * + * @return + */ gboolean gnt_widget_has_shadow(GntWidget *widget); G_END_DECLS
--- a/finch/libgnt/gntwindow.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntwindow.c Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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 "gntstyle.h" #include "gntwindow.h" @@ -5,9 +27,13 @@ enum { - SIGS = 1, + SIG_WORKSPACE_HIDE, + SIG_WORKSPACE_SHOW, + SIGS, }; +static guint signals[SIGS] = { 0 }; + static GntBoxClass *parent_class = NULL; static void (*org_destroy)(GntWidget *widget); @@ -42,6 +68,24 @@ org_destroy = wid_class->destroy; wid_class->destroy = gnt_window_destroy; + signals[SIG_WORKSPACE_HIDE] = + g_signal_new("workspace-hidden", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[SIG_WORKSPACE_SHOW] = + g_signal_new("workspace-shown", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + gnt_bindable_class_register_action(bindable, "show-menu", show_menu, GNT_KEY_CTRL_O, NULL); gnt_bindable_register_binding(bindable, "show-menu", GNT_KEY_F10, NULL); @@ -109,6 +153,20 @@ return wid; } +void +gnt_window_workspace_hiding(GntWindow *window) +{ + if (window->menu) + gnt_widget_hide(GNT_WIDGET(window->menu)); + g_signal_emit(window, signals[SIG_WORKSPACE_HIDE], 0); +} + +void +gnt_window_workspace_showing(GntWindow *window) +{ + g_signal_emit(window, signals[SIG_WORKSPACE_SHOW], 0); +} + void gnt_window_set_menu(GntWindow *window, GntMenu *menu) { /* If a menu already existed, then destroy that first. */
--- a/finch/libgnt/gntwindow.h Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntwindow.h Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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_WINDOW_H #define GNT_WINDOW_H @@ -40,17 +62,42 @@ G_BEGIN_DECLS +/** + * + * + * @return + */ GType gnt_window_get_gtype(void); #define gnt_vwindow_new(homo) gnt_window_box_new(homo, TRUE) #define gnt_hwindow_new(homo) gnt_window_box_new(homo, FALSE) -GntWidget *gnt_window_new(void); +/** + * + * + * @return + */ +GntWidget * gnt_window_new(void); -GntWidget *gnt_window_box_new(gboolean homo, gboolean vert); +/** + * + * @param homo + * @param vert + * + * @return + */ +GntWidget * gnt_window_box_new(gboolean homo, gboolean vert); +/** + * + * @param window + * @param menu + */ void gnt_window_set_menu(GntWindow *window, GntMenu *menu); +void gnt_window_workspace_hiding(GntWindow *); +void gnt_window_workspace_showing(GntWindow *); + G_END_DECLS #endif /* GNT_WINDOW_H */
--- a/finch/libgnt/gntwm.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntwm.c Sat Jun 16 20:16:36 2007 +0000 @@ -1,3 +1,25 @@ +/** + * 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 + */ + #define _GNU_SOURCE #if defined(__APPLE__) || defined(__unix__) #define _XOPEN_SOURCE_EXTENDED @@ -6,6 +28,8 @@ #include "config.h" #include <ctype.h> +#include <glib/gprintf.h> +#include <gmodule.h> #include <stdlib.h> #include <string.h> #include <time.h> @@ -47,6 +71,8 @@ static void gnt_wm_give_focus(GntWM *wm, GntWidget *widget); static void update_window_in_list(GntWM *wm, GntWidget *wid); static void shift_window(GntWM *wm, GntWidget *widget, int dir); +static gboolean workspace_next(GntBindable *wm, GList *n); +static gboolean workspace_prev(GntBindable *wm, GList *n); #ifndef NO_WIDECHAR static int widestringwidth(wchar_t *wide); @@ -56,6 +82,7 @@ static int write_timeout; static time_t last_active_time; static gboolean idle_update; +static GList *act = NULL; /* list of WS with unseen activitiy */ static GList * g_list_bring_to_front(GList *list, gpointer data) @@ -74,61 +101,8 @@ g_free(node); } -static void -draw_taskbar(GntWM *wm, gboolean reposition) -{ - static WINDOW *taskbar = NULL; - GList *iter; - int n, width = 0; - int i; - - if (taskbar == NULL) { - taskbar = newwin(1, getmaxx(stdscr), getmaxy(stdscr) - 1, 0); - } else if (reposition) { - int Y_MAX = getmaxy(stdscr) - 1; - mvwin(taskbar, Y_MAX, 0); - } - - wbkgdset(taskbar, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL)); - werase(taskbar); - - n = g_list_length(wm->list); - if (n) - width = getmaxx(stdscr) / n; - - for (i = 0, iter = wm->list; iter; iter = iter->next, i++) - { - GntWidget *w = iter->data; - int color; - const char *title; - - if (w == wm->ordered->data) { - /* This is the current window in focus */ - color = GNT_COLOR_TITLE; - } else if (GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_URGENT)) { - /* This is a window with the URGENT hint set */ - color = GNT_COLOR_URGENT; - } else { - color = GNT_COLOR_NORMAL; - } - wbkgdset(taskbar, '\0' | COLOR_PAIR(color)); - if (iter->next) - mvwhline(taskbar, 0, width * i, ' ' | COLOR_PAIR(color), width); - else - mvwhline(taskbar, 0, width * i, ' ' | COLOR_PAIR(color), getmaxx(stdscr) - width * i); - title = GNT_BOX(w)->title; - mvwprintw(taskbar, 0, width * i, "%s", title ? title : "<gnt>"); - if (i) - mvwaddch(taskbar, 0, width *i - 1, ACS_VLINE | A_STANDOUT | COLOR_PAIR(GNT_COLOR_NORMAL)); - - update_window_in_list(wm, w); - } - - wrefresh(taskbar); -} - -static void -copy_win(GntWidget *widget, GntNode *node) +void +gnt_wm_copy_win(GntWidget *widget, GntNode *node) { WINDOW *src, *dst; int shadow; @@ -199,6 +173,33 @@ #endif } +static void +update_act_msg() +{ + GntWidget *label; + GList *iter; + static GntWidget *message = NULL; + GString *text = g_string_new("act: "); + if (message) + gnt_widget_destroy(message); + if (g_list_length(act) == 0) + return; + for (iter = act; iter; iter = iter->next) { + GntWS *ws = iter->data; + g_string_append_printf(text, "%s, ", gnt_ws_get_name(ws)); + } + g_string_erase(text, text->len - 2, 2); + message = gnt_vbox_new(FALSE); + label = gnt_label_new_with_format(text->str, GNT_TEXT_FLAG_BOLD | GNT_TEXT_FLAG_HIGHLIGHT); + GNT_WIDGET_UNSET_FLAGS(GNT_BOX(message), GNT_WIDGET_CAN_TAKE_FOCUS); + GNT_WIDGET_SET_FLAGS(GNT_BOX(message), GNT_WIDGET_TRANSIENT); + gnt_box_add_widget(GNT_BOX(message), label); + gnt_widget_set_name(message, "wm-message"); + gnt_widget_set_position(message, 0, 0); + gnt_widget_draw(message); + g_string_free(text, TRUE); +} + static gboolean update_screen(GntWM *wm) { @@ -329,9 +330,18 @@ gnt_wm_init(GTypeInstance *instance, gpointer class) { GntWM *wm = GNT_WM(instance); - wm->list = NULL; - wm->ordered = NULL; + wm->workspaces = NULL; + wm->name_places = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + wm->title_places = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + gnt_style_read_workspaces(wm); + if (wm->workspaces == NULL) { + wm->cws = gnt_ws_new("default"); + gnt_wm_add_workspace(wm, wm->cws); + } else { + wm->cws = wm->workspaces->data; + } wm->event_stack = FALSE; + wm->tagged = NULL; wm->windows = NULL; wm->actions = NULL; wm->nodes = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_node); @@ -340,6 +350,7 @@ read_window_positions(wm); g_timeout_add(IDLE_CHECK_INTERVAL * 1000, check_idle, NULL); time(&last_active_time); + gnt_wm_switch_workspace(wm, 0); } static void @@ -351,23 +362,23 @@ if (wm->_list.window || wm->menu) return; - if (!wm->ordered || !wm->ordered->next) + if (!wm->cws->ordered || !wm->cws->ordered->next) return; - w = wm->ordered->data; - pos = g_list_index(wm->list, w); + w = wm->cws->ordered->data; + pos = g_list_index(wm->cws->list, w); pos += direction; if (pos < 0) - wid = g_list_last(wm->list)->data; - else if (pos >= g_list_length(wm->list)) - wid = wm->list->data; + wid = g_list_last(wm->cws->list)->data; + else if (pos >= g_list_length(wm->cws->list)) + wid = wm->cws->list->data; else if (pos >= 0) - wid = g_list_nth_data(wm->list, pos); + wid = g_list_nth_data(wm->cws->list, pos); - wm->ordered = g_list_bring_to_front(wm->ordered, wid); + wm->cws->ordered = g_list_bring_to_front(wm->cws->ordered, wid); - gnt_wm_raise_window(wm, wm->ordered->data); + gnt_wm_raise_window(wm, wm->cws->ordered->data); if (w != wid) { gnt_widget_set_focus(w, FALSE); @@ -398,7 +409,7 @@ GList *l; int n; - if (!wm->ordered) + if (!wm->cws->ordered) return TRUE; if (list) @@ -406,9 +417,9 @@ else n = 0; - w = wm->ordered->data; + w = wm->cws->ordered->data; - if ((l = g_list_nth(wm->list, n)) != NULL) + if ((l = g_list_nth(wm->cws->list, n)) != NULL) { gnt_wm_raise_window(wm, l->data); } @@ -427,17 +438,17 @@ GntWidget *window; GntNode *node; - if (!wm->ordered) + if (!wm->cws->ordered) return TRUE; - window = wm->ordered->data; + window = wm->cws->ordered->data; node = g_hash_table_lookup(wm->nodes, window); if (!node) return TRUE; if (node->scroll) { node->scroll--; - copy_win(window, node); + gnt_wm_copy_win(window, node); update_screen(wm); } return TRUE; @@ -451,10 +462,10 @@ GntNode *node; int w, h; - if (!wm->ordered) + if (!wm->cws->ordered) return TRUE; - window = wm->ordered->data; + window = wm->cws->ordered->data; node = g_hash_table_lookup(wm->nodes, window); if (!node) return TRUE; @@ -462,7 +473,7 @@ gnt_widget_get_size(window, &w, &h); if (h - node->scroll > getmaxy(node->window)) { node->scroll++; - copy_win(window, node); + gnt_wm_copy_win(window, node); update_screen(wm); } return TRUE; @@ -476,8 +487,8 @@ if (wm->_list.window) return TRUE; - if (wm->ordered) { - gnt_widget_destroy(wm->ordered->data); + if (wm->cws->ordered) { + gnt_widget_destroy(wm->cws->ordered->data); } return TRUE; @@ -490,10 +501,10 @@ GntWidget *widget, *tree, *win, *active; char *title; - if (!wm->ordered) + if (!wm->cws->ordered) return TRUE; - widget = wm->ordered->data; + widget = wm->cws->ordered->data; if (!GNT_IS_BOX(widget)) return TRUE; active = GNT_BOX(widget)->active; @@ -540,85 +551,123 @@ static void window_list_activate(GntTree *tree, GntWM *wm) { - GntWidget *widget = gnt_tree_get_selection_data(GNT_TREE(tree)); + GntBindable *sel = gnt_tree_get_selection_data(GNT_TREE(tree)); - if (!wm->ordered || !widget) + gnt_widget_destroy(wm->_list.window); + + if (!sel) return; - gnt_widget_destroy(wm->_list.window); - gnt_wm_raise_window(wm, widget); + if (GNT_IS_WS(sel)) { + gnt_wm_switch_workspace(wm, g_list_index(wm->workspaces, sel)); + } else { + gnt_wm_raise_window(wm, GNT_WIDGET(sel)); + } } static void -populate_window_list(GntWM *wm) +populate_window_list(GntWM *wm, gboolean workspace) { GList *iter; GntTree *tree = GNT_TREE(wm->windows->tree); - for (iter = wm->list; iter; iter = iter->next) { - GntBox *box = GNT_BOX(iter->data); + if (!workspace) { + for (iter = wm->cws->list; iter; iter = iter->next) { + GntBox *box = GNT_BOX(iter->data); - gnt_tree_add_row_last(tree, box, - gnt_tree_create_row(tree, box->title), NULL); - update_window_in_list(wm, GNT_WIDGET(box)); + gnt_tree_add_row_last(tree, box, + gnt_tree_create_row(tree, box->title), NULL); + update_window_in_list(wm, GNT_WIDGET(box)); + } + } else { + GList *ws = wm->workspaces; + for (; ws; ws = ws->next) { + gnt_tree_add_row_last(tree, ws->data, + gnt_tree_create_row(tree, gnt_ws_get_name(GNT_WS(ws->data))), NULL); + for (iter = GNT_WS(ws->data)->list; iter; iter = iter->next) { + GntBox *box = GNT_BOX(iter->data); + + gnt_tree_add_row_last(tree, box, + gnt_tree_create_row(tree, box->title), ws->data); + update_window_in_list(wm, GNT_WIDGET(box)); + } + } } } static gboolean window_list_key_pressed(GntWidget *widget, const char *text, GntWM *wm) { - if (text[1] == 0 && wm->ordered) { - GntWidget *sel = gnt_tree_get_selection_data(GNT_TREE(widget)); + if (text[1] == 0 && wm->cws->ordered) { + GntBindable *sel = gnt_tree_get_selection_data(GNT_TREE(widget)); switch (text[0]) { case '-': case ',': - shift_window(wm, sel, -1); + if (GNT_IS_WS(sel)) { + /* reorder the workspace. */ + } else + shift_window(wm, GNT_WIDGET(sel), -1); break; case '=': case '.': - shift_window(wm, sel, 1); + if (GNT_IS_WS(sel)) { + /* reorder the workspace. */ + } else + shift_window(wm, GNT_WIDGET(sel), 1); break; default: return FALSE; } gnt_tree_remove_all(GNT_TREE(widget)); - populate_window_list(wm); + populate_window_list(wm, GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "workspace"))); gnt_tree_set_selected(GNT_TREE(widget), sel); return TRUE; } return FALSE; } +static void +list_of_windows(GntWM *wm, gboolean workspace) +{ + GntWidget *tree, *win; + setup__list(wm); + wm->windows = &wm->_list; + + win = wm->windows->window; + tree = wm->windows->tree; + + gnt_box_set_title(GNT_BOX(win), workspace ? "Workspace List" : "Window List"); + + populate_window_list(wm, workspace); + + if (wm->cws->ordered) + gnt_tree_set_selected(GNT_TREE(tree), wm->cws->ordered->data); + else if (workspace) + gnt_tree_set_selected(GNT_TREE(tree), wm->cws); + + g_signal_connect(G_OBJECT(tree), "activate", G_CALLBACK(window_list_activate), wm); + g_signal_connect(G_OBJECT(tree), "key_pressed", G_CALLBACK(window_list_key_pressed), wm); + g_object_set_data(G_OBJECT(tree), "workspace", GINT_TO_POINTER(workspace)); + + gnt_tree_set_col_width(GNT_TREE(tree), 0, getmaxx(stdscr) / 3); + gnt_widget_set_size(tree, 0, getmaxy(stdscr) / 2); + gnt_widget_set_position(win, getmaxx(stdscr) / 3, getmaxy(stdscr) / 4); + + gnt_widget_show(win); +} + static gboolean window_list(GntBindable *bindable, GList *null) { GntWM *wm = GNT_WM(bindable); - GntWidget *tree, *win; if (wm->_list.window || wm->menu) return TRUE; - if (!wm->ordered) + if (!wm->cws->ordered) return TRUE; - setup__list(wm); - wm->windows = &wm->_list; - - win = wm->windows->window; - tree = wm->windows->tree; - - gnt_box_set_title(GNT_BOX(win), "Window List"); - - populate_window_list(wm); + list_of_windows(wm, FALSE); - gnt_tree_set_selected(GNT_TREE(tree), wm->ordered->data); - g_signal_connect(G_OBJECT(tree), "activate", G_CALLBACK(window_list_activate), wm); - g_signal_connect(G_OBJECT(tree), "key_pressed", G_CALLBACK(window_list_key_pressed), wm); - - gnt_tree_set_col_width(GNT_TREE(tree), 0, getmaxx(stdscr) / 3); - gnt_widget_set_size(tree, 0, getmaxy(stdscr) / 2); - gnt_widget_set_position(win, getmaxx(stdscr) / 3, getmaxy(stdscr) / 4); - - gnt_widget_show(win); return TRUE; } @@ -758,7 +807,7 @@ static void shift_window(GntWM *wm, GntWidget *widget, int dir) { - GList *all = wm->list; + GList *all = wm->cws->list; GList *list = g_list_find(all, widget); int length, pos; if (!list) @@ -778,8 +827,8 @@ all = g_list_insert(all, widget, pos); all = g_list_delete_link(all, list); - wm->list = all; - draw_taskbar(wm, FALSE); + wm->cws->list = all; + gnt_ws_draw_taskbar(wm->cws, FALSE); } static gboolean @@ -789,7 +838,7 @@ if (wm->_list.window) return TRUE; - shift_window(wm, wm->ordered->data, -1); + shift_window(wm, wm->cws->ordered->data, -1); return TRUE; } @@ -800,7 +849,7 @@ if (wm->_list.window) return TRUE; - shift_window(wm, wm->ordered->data, 1); + shift_window(wm, wm->cws->ordered->data, 1); return TRUE; } @@ -924,7 +973,7 @@ for (i = 0; i < h; i += reverse_char(d, i, 0, set)); for (i = 0; i < h; i += reverse_char(d, i, w-1, set)); - copy_win(win, g_hash_table_lookup(wm->nodes, win)); + gnt_wm_copy_win(win, g_hash_table_lookup(wm->nodes, win)); update_screen(wm); } @@ -934,11 +983,11 @@ GntWM *wm = GNT_WM(bindable); if (wm->_list.window || wm->menu) return TRUE; - if (!wm->ordered) + if (!wm->cws->ordered) return TRUE; wm->mode = GNT_KP_MODE_MOVE; - window_reverse(GNT_WIDGET(wm->ordered->data), TRUE, wm); + window_reverse(GNT_WIDGET(wm->cws->ordered->data), TRUE, wm); return TRUE; } @@ -949,11 +998,11 @@ GntWM *wm = GNT_WM(bindable); if (wm->_list.window || wm->menu) return TRUE; - if (!wm->ordered) + if (!wm->cws->ordered) return TRUE; wm->mode = GNT_KP_MODE_RESIZE; - window_reverse(GNT_WIDGET(wm->ordered->data), TRUE, wm); + window_reverse(GNT_WIDGET(wm->cws->ordered->data), TRUE, wm); return TRUE; } @@ -983,7 +1032,7 @@ g_hash_table_foreach(wm->nodes, (GHFunc)refresh_node, NULL); update_screen(wm); - draw_taskbar(wm, TRUE); + gnt_ws_draw_taskbar(wm->cws, TRUE); curs_set(0); /* endwin resets the cursor to normal */ return FALSE; @@ -1015,6 +1064,78 @@ return TRUE; } +static void remove_tag(gpointer wid, gpointer wim) +{ + GntWM *wm = GNT_WM(wim); + GntWidget *w = GNT_WIDGET(wid); + wm->tagged = g_list_remove(wm->tagged, w); + mvwhline(w->window, 0, 1, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL), 3); + gnt_widget_draw(w); +} + +static gboolean +tag_widget(GntBindable *b, GList *params) +{ + GntWM *wm = GNT_WM(b); + GntWidget *widget; + + if (!wm->cws->ordered) + return FALSE; + widget = wm->cws->ordered->data; + + if (g_list_find(wm->tagged, widget)) { + remove_tag(widget, wm); + return TRUE; + } + + wm->tagged = g_list_prepend(wm->tagged, widget); + wbkgdset(widget->window, ' ' | COLOR_PAIR(GNT_COLOR_HIGHLIGHT)); + mvwprintw(widget->window, 0, 1, "[T]"); + gnt_widget_draw(widget); + return TRUE; +} + +static void +widget_move_ws(gpointer wid, gpointer w) +{ + GntWM *wm = GNT_WM(w); + gnt_wm_widget_move_workspace(wm, wm->cws, GNT_WIDGET(wid)); +} + +static gboolean +place_tagged(GntBindable *b, GList *params) +{ + GntWM *wm = GNT_WM(b); + g_list_foreach(wm->tagged, widget_move_ws, wm); + g_list_foreach(wm->tagged, remove_tag, wm); + g_list_free(wm->tagged); + wm->tagged = NULL; + return TRUE; +} + +static gboolean +workspace_list(GntBindable *b, GList *params) +{ + GntWM *wm = GNT_WM(b); + + if (wm->_list.window || wm->menu) + return TRUE; + + list_of_windows(wm, TRUE); + + return TRUE; +} + +static gboolean +workspace_new(GntBindable *bindable, GList *null) +{ + GntWM *wm = GNT_WM(bindable); + GntWS *ws = gnt_ws_new(NULL); + gnt_wm_add_workspace(wm, ws); + gnt_wm_switch_workspace(wm, g_list_index(wm->workspaces, ws)); + return TRUE; +} + static void gnt_wm_class_init(GntWMClass *klass) { @@ -1149,6 +1270,18 @@ "\033" GNT_KEY_CTRL_K, NULL); gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "help-for-widget", help_for_widget, "\033" "/", NULL); + gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "workspace-new", workspace_new, + GNT_KEY_F9, NULL); + gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "workspace-next", workspace_next, + "\033" ">", NULL); + gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "workspace-prev", workspace_prev, + "\033" "<", NULL); + gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "window-tag", tag_widget, + "\033" "t", NULL); + gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "place-tagged", place_tagged, + "\033" "T", NULL); + gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "workspace-list", workspace_list, + "\033" "s", NULL); gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "toggle-clipboard", toggle_clipboard, "\033" "C", NULL); @@ -1193,6 +1326,119 @@ return type; } + +void +gnt_wm_add_workspace(GntWM *wm, GntWS *ws) +{ + wm->workspaces = g_list_append(wm->workspaces, ws); +} + +gboolean +gnt_wm_switch_workspace(GntWM *wm, gint n) +{ + GntWS *s = g_list_nth_data(wm->workspaces, n); + if (!s) + return FALSE; + + if (wm->_list.window) { + gnt_widget_destroy(wm->_list.window); + } + gnt_ws_hide(wm->cws, wm->nodes); + wm->cws = s; + gnt_ws_show(wm->cws, wm->nodes); + + gnt_ws_draw_taskbar(wm->cws, TRUE); + update_screen(wm); + if (wm->cws->ordered) { + gnt_widget_set_focus(wm->cws->ordered->data, TRUE); + gnt_wm_raise_window(wm, wm->cws->ordered->data); + } + + if (act && g_list_find(act, wm->cws)) { + act = g_list_remove(act, wm->cws); + update_act_msg(); + } + return TRUE; +} + +gboolean +gnt_wm_switch_workspace_prev(GntWM *wm) +{ + int n = g_list_index(wm->workspaces, wm->cws); + return gnt_wm_switch_workspace(wm, --n); +} + +gboolean +gnt_wm_switch_workspace_next(GntWM *wm) +{ + int n = g_list_index(wm->workspaces, wm->cws); + return gnt_wm_switch_workspace(wm, ++n); +} + +static gboolean +workspace_next(GntBindable *wm, GList *n) +{ + return gnt_wm_switch_workspace_next(GNT_WM(wm)); +} + +static gboolean +workspace_prev(GntBindable *wm, GList *n) +{ + return gnt_wm_switch_workspace_prev(GNT_WM(wm)); +} + +void +gnt_wm_widget_move_workspace(GntWM *wm, GntWS *neww, GntWidget *widget) +{ + GntWS *oldw = gnt_wm_widget_find_workspace(wm, widget); + GntNode *node; + if (!oldw || oldw == neww) + return; + node = g_hash_table_lookup(wm->nodes, widget); + if (node && node->ws == neww) + return; + + if (node) + node->ws = neww; + + gnt_ws_remove_widget(oldw, widget); + gnt_ws_add_widget(neww, widget); + if (neww == wm->cws) { + gnt_ws_widget_show(widget, wm->nodes); + } else { + gnt_ws_widget_hide(widget, wm->nodes); + } +} + +static gint widget_in_workspace(gconstpointer workspace, gconstpointer wid) +{ + GntWS *s = (GntWS *)workspace; + if (s->list && g_list_find(s->list, wid)) + return 0; + return 1; +} + +GntWS *gnt_wm_widget_find_workspace(GntWM *wm, GntWidget *widget) +{ + GList *l = g_list_find_custom(wm->workspaces, widget, widget_in_workspace); + if (l) + return l->data; + return NULL; +} + +static void free_workspaces(gpointer data, gpointer n) +{ + GntWS *s = data; + g_free(s->name); +} + +void gnt_wm_set_workspaces(GntWM *wm, GList *workspaces) +{ + g_list_foreach(wm->workspaces, free_workspaces, NULL); + wm->workspaces = workspaces; + gnt_wm_switch_workspace(wm, 0); +} + static void update_window_in_list(GntWM *wm, GntWidget *wid) { @@ -1201,7 +1447,7 @@ if (wm->windows == NULL) return; - if (wid == wm->ordered->data) + if (wm->cws->ordered && wid == wm->cws->ordered->data) flag |= GNT_TEXT_FLAG_DIM; else if (GNT_WIDGET_IS_FLAG_SET(wid, GNT_WIDGET_URGENT)) flag |= GNT_TEXT_FLAG_BOLD; @@ -1209,6 +1455,29 @@ gnt_tree_set_row_flags(GNT_TREE(wm->windows->tree), wid, flag); } +static gboolean +match_title(gpointer title, gpointer n, gpointer wid_title) +{ + /* maybe check for regex.h? */ + if (g_strrstr((gchar *)wid_title, (gchar *)title)) + return TRUE; + return FALSE; +} + +static GntWS * +new_widget_find_workspace(GntWM *wm, GntWidget *widget, gchar *wid_title) +{ + GntWS *ret; + const gchar *name; + ret = g_hash_table_find(wm->title_places, match_title, wid_title); + if (ret) + return ret; + name = gnt_widget_get_name(widget); + if (name) + ret = g_hash_table_lookup(wm->name_places, name); + return ret ? ret : wm->cws; +} + static void gnt_wm_new_window_real(GntWM *wm, GntWidget *widget) { @@ -1255,7 +1524,7 @@ w = MIN(w, maxx); h = MIN(h, maxy); node->window = newwin(h + shadow, w + shadow, y, x); - copy_win(widget, node); + gnt_wm_copy_win(widget, node); } #endif @@ -1263,18 +1532,25 @@ set_panel_userptr(node->panel, node); if (!transient) { + GntWS *ws = wm->cws; if (node->me != wm->_list.window) { GntWidget *w = NULL; - if (wm->ordered) - w = wm->ordered->data; + if (GNT_IS_BOX(widget)) { + char *title = GNT_BOX(widget)->title; + ws = new_widget_find_workspace(wm, widget, title); + } - wm->list = g_list_append(wm->list, widget); + if (ws->ordered) + w = ws->ordered->data; + + node->ws = ws; + ws->list = g_list_append(ws->list, widget); if (wm->event_stack) - wm->ordered = g_list_prepend(wm->ordered, widget); + ws->ordered = g_list_prepend(ws->ordered, widget); else - wm->ordered = g_list_append(wm->ordered, widget); + ws->ordered = g_list_append(ws->ordered, widget); gnt_widget_set_focus(widget, TRUE); if (w) @@ -1285,7 +1561,10 @@ gnt_wm_raise_window(wm, node->me); } else { bottom_panel(node->panel); /* New windows should not grab focus */ + gnt_widget_set_focus(node->me, FALSE); gnt_widget_set_urgent(node->me); + if (wm->cws != ws) + gnt_ws_widget_hide(widget, wm->nodes); } } } @@ -1319,13 +1598,13 @@ && GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_CAN_TAKE_FOCUS)) { gnt_tree_add_row_last(GNT_TREE(wm->windows->tree), widget, gnt_tree_create_row(GNT_TREE(wm->windows->tree), GNT_BOX(widget)->title), - NULL); + g_object_get_data(G_OBJECT(wm->windows->tree), "workspace") ? wm->cws : NULL); update_window_in_list(wm, widget); } } update_screen(wm); - draw_taskbar(wm, FALSE); + gnt_ws_draw_taskbar(wm->cws, FALSE); } void gnt_wm_window_decorate(GntWM *wm, GntWidget *widget) @@ -1335,9 +1614,12 @@ void gnt_wm_window_close(GntWM *wm, GntWidget *widget) { + GntWS *s; GntNode *node; int pos; + s = gnt_wm_widget_find_workspace(wm, widget); + if ((node = g_hash_table_lookup(wm->nodes, widget)) == NULL) return; @@ -1348,18 +1630,20 @@ gnt_tree_remove(GNT_TREE(wm->windows->tree), widget); } - pos = g_list_index(wm->list, widget); + if (s) { + pos = g_list_index(s->list, widget); - if (pos != -1) { - wm->list = g_list_remove(wm->list, widget); - wm->ordered = g_list_remove(wm->ordered, widget); + if (pos != -1) { + s->list = g_list_remove(s->list, widget); + s->ordered = g_list_remove(s->ordered, widget); - if (wm->ordered) - gnt_wm_raise_window(wm, wm->ordered->data); + if (s->ordered && wm->cws == s) + gnt_wm_raise_window(wm, s->ordered->data); + } } update_screen(wm); - draw_taskbar(wm, FALSE); + gnt_ws_draw_taskbar(wm->cws, FALSE); } time_t gnt_wm_get_idle_time() @@ -1380,10 +1664,10 @@ } /* Do some manual checking */ - if (wm->ordered && wm->mode != GNT_KP_MODE_NORMAL) { + if (wm->cws->ordered && wm->mode != GNT_KP_MODE_NORMAL) { int xmin = 0, ymin = 0, xmax = getmaxx(stdscr), ymax = getmaxy(stdscr) - 1; int x, y, w, h; - GntWidget *widget = GNT_WIDGET(wm->ordered->data); + GntWidget *widget = GNT_WIDGET(wm->cws->ordered->data); int ox, oy, ow, oh; gnt_widget_get_position(widget, &x, &y); @@ -1459,8 +1743,8 @@ ret = gnt_widget_key_pressed(GNT_WIDGET(wm->menu), keys); else if (wm->_list.window) ret = gnt_widget_key_pressed(wm->_list.window, keys); - else if (wm->ordered) - ret = gnt_widget_key_pressed(GNT_WIDGET(wm->ordered->data), keys); + else if (wm->cws->ordered) + ret = gnt_widget_key_pressed(GNT_WIDGET(wm->cws->ordered->data), keys); return ret; } @@ -1594,9 +1878,9 @@ return; if (widget != wm->_list.window && !GNT_IS_MENU(widget) && - wm->ordered->data != widget) { - GntWidget *w = wm->ordered->data; - wm->ordered = g_list_bring_to_front(wm->ordered, widget); + wm->cws->ordered->data != widget) { + GntWidget *w = wm->cws->ordered->data; + wm->cws->ordered = g_list_bring_to_front(wm->cws->ordered, widget); gnt_widget_set_focus(w, FALSE); } @@ -1610,27 +1894,35 @@ top_panel(nd->panel); } update_screen(wm); - draw_taskbar(wm, FALSE); + gnt_ws_draw_taskbar(wm->cws, FALSE); } void gnt_wm_update_window(GntWM *wm, GntWidget *widget) { - GntNode *node; + GntNode *node = NULL; + GntWS *ws; while (widget->parent) widget = widget->parent; if (!GNT_IS_MENU(widget)) gnt_box_sync_children(GNT_BOX(widget)); + ws = gnt_wm_widget_find_workspace(wm, widget); node = g_hash_table_lookup(wm->nodes, widget); if (node == NULL) { gnt_wm_new_window(wm, widget); } else g_signal_emit(wm, signals[SIG_UPDATE_WIN], 0, node); - copy_win(widget, node); - update_screen(wm); - draw_taskbar(wm, FALSE); + if (ws == wm->cws || GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_TRANSIENT)) { + gnt_wm_copy_win(widget, node); + update_screen(wm); + gnt_ws_draw_taskbar(wm->cws, FALSE); + } else if (ws != wm->cws && GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_URGENT)) { + if (!act || (act && !g_list_find(act, ws))) + act = g_list_prepend(act, ws); + update_act_msg(); + } } gboolean gnt_wm_process_click(GntWM *wm, GntMouseEvent event, int x, int y, GntWidget *widget) @@ -1643,6 +1935,9 @@ void gnt_wm_raise_window(GntWM *wm, GntWidget *widget) { + GntWS *ws = gnt_wm_widget_find_workspace(wm, widget); + if (wm->cws != ws) + gnt_wm_switch_workspace(wm, g_list_index(wm->workspaces, ws)); g_signal_emit(wm, signals[SIG_GIVE_FOCUS], 0, widget); }
--- a/finch/libgnt/gntwm.h Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/gntwm.h Sat Jun 16 20:16:36 2007 +0000 @@ -1,6 +1,31 @@ +/** + * 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 GNTWM_H +#define GNTWM_H #include "gntwidget.h" #include "gntmenu.h" +#include "gntws.h" #include <panel.h> #include <time.h> @@ -26,9 +51,10 @@ WINDOW *window; int scroll; PANEL *panel; + GntWS *ws; } GntNode; -typedef struct _GnttWM GntWM; +typedef struct _GntWM GntWM; typedef struct _GntPosition { @@ -45,14 +71,15 @@ void (*callback)(); } GntAction; -struct _GnttWM +struct _GntWM { GntBindable inherit; GMainLoop *loop; - GList *list; /* List of windows ordered on their creation time */ - GList *ordered; /* List of windows ordered on their focus */ + GList *workspaces; + GList *tagged; /* tagged windows */ + GntWS *cws; struct { GntWidget *window; @@ -62,6 +89,8 @@ *actions; /* Action-list window */ GHashTable *nodes; /* GntWidget -> GntNode */ + GHashTable *name_places; /* window name -> ws*/ + GHashTable *title_places; /* window title -> ws */ GList *acts; /* List of actions */ @@ -144,28 +173,111 @@ G_BEGIN_DECLS +/** + * + * + * @return + */ GType gnt_wm_get_gtype(void); +void gnt_wm_add_workspace(GntWM *wm, GntWS *ws); + +gboolean gnt_wm_switch_workspace(GntWM *wm, gint n); +gboolean gnt_wm_switch_workspace_prev(GntWM *wm); +gboolean gnt_wm_switch_workspace_next(GntWM *wm); +void gnt_wm_widget_move_workspace(GntWM *wm, GntWS *neww, GntWidget *widget); +void gnt_wm_set_workspaces(GntWM *wm, GList *workspaces); +GntWS *gnt_wm_widget_find_workspace(GntWM *wm, GntWidget *widget); + +/** + * + * @param wm + * @param widget + */ void gnt_wm_new_window(GntWM *wm, GntWidget *widget); +/** + * + * @param wm + * @param widget + */ void gnt_wm_window_decorate(GntWM *wm, GntWidget *widget); +/** + * + * @param wm + * @param widget + */ void gnt_wm_window_close(GntWM *wm, GntWidget *widget); +/** + * + * @param wm + * @param string + * + * @return + */ gboolean gnt_wm_process_input(GntWM *wm, const char *string); +/** + * + * @param wm + * @param event + * @param x + * @param y + * @param widget + * + * @return + */ gboolean gnt_wm_process_click(GntWM *wm, GntMouseEvent event, int x, int y, GntWidget *widget); +/** + * + * @param wm + * @param widget + * @param width + * @param height + */ void gnt_wm_resize_window(GntWM *wm, GntWidget *widget, int width, int height); +/** + * + * @param wm + * @param widget + * @param x + * @param y + */ void gnt_wm_move_window(GntWM *wm, GntWidget *widget, int x, int y); +/** + * + * @param wm + * @param widget + */ void gnt_wm_update_window(GntWM *wm, GntWidget *widget); +/** + * + * @param wm + * @param widget + */ void gnt_wm_raise_window(GntWM *wm, GntWidget *widget); +/** + * + * @param wm + * @param set + */ void gnt_wm_set_event_stack(GntWM *wm, gboolean set); +void gnt_wm_copy_win(GntWidget *widget, GntNode *node); + +/** + * + * + * @return + */ time_t gnt_wm_get_idle_time(void); G_END_DECLS +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/finch/libgnt/gntws.c Sat Jun 16 20:16:36 2007 +0000 @@ -0,0 +1,168 @@ +#include <gmodule.h> + +#include "gntbox.h" +#include "gntwidget.h" +#include "gntwindow.h" +#include "gntwm.h" +#include "gntws.h" + +static void +widget_hide(gpointer data, gpointer nodes) +{ + GntWidget *widget = GNT_WIDGET(data); + GntNode *node = g_hash_table_lookup(nodes, widget); + if (GNT_IS_WINDOW(widget)) + gnt_window_workspace_hiding(GNT_WINDOW(widget)); + hide_panel(node->panel); +} + +static void +widget_show(gpointer data, gpointer nodes) +{ + GntNode *node = g_hash_table_lookup(nodes, data); + GNT_WIDGET_UNSET_FLAGS(GNT_WIDGET(data), GNT_WIDGET_INVISIBLE); + if (node) { + show_panel(node->panel); + gnt_wm_copy_win(GNT_WIDGET(data), node); + } +} + +void +gnt_ws_draw_taskbar(GntWS *ws, gboolean reposition) +{ + static WINDOW *taskbar = NULL; + GList *iter; + int n, width = 0; + int i; + + if (taskbar == NULL) { + taskbar = newwin(1, getmaxx(stdscr), getmaxy(stdscr) - 1, 0); + } else if (reposition) { + int Y_MAX = getmaxy(stdscr) - 1; + mvwin(taskbar, Y_MAX, 0); + } + + wbkgdset(taskbar, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL)); + werase(taskbar); + + n = g_list_length(ws->list); + if (n) + width = getmaxx(stdscr) / n; + + for (i = 0, iter = ws->list; iter; iter = iter->next, i++) { + GntWidget *w = iter->data; + int color; + const char *title; + + if (w == ws->ordered->data) { + /* This is the current window in focus */ + color = GNT_COLOR_TITLE; + } else if (GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_URGENT)) { + /* This is a window with the URGENT hint set */ + color = GNT_COLOR_URGENT; + } else { + color = GNT_COLOR_NORMAL; + } + wbkgdset(taskbar, '\0' | COLOR_PAIR(color)); + if (iter->next) + mvwhline(taskbar, 0, width * i, ' ' | COLOR_PAIR(color), width); + else + mvwhline(taskbar, 0, width * i, ' ' | COLOR_PAIR(color), getmaxx(stdscr) - width * i); + title = GNT_BOX(w)->title; + mvwprintw(taskbar, 0, width * i, "%s", title ? title : "<gnt>"); + if (i) + mvwaddch(taskbar, 0, width *i - 1, ACS_VLINE | A_STANDOUT | COLOR_PAIR(GNT_COLOR_NORMAL)); + } + wrefresh(taskbar); +} + +static void +gnt_ws_init(GTypeInstance *instance, gpointer class) +{ + GntWS *ws = GNT_WS(instance); + ws->list = NULL; + ws->ordered = NULL; + ws->name = NULL; +} + +void gnt_ws_add_widget(GntWS *ws, GntWidget* wid) +{ + ws->list = g_list_append(ws->list, wid); + ws->ordered = g_list_prepend(ws->ordered, wid); +} + +void gnt_ws_remove_widget(GntWS *ws, GntWidget* wid) +{ + ws->list = g_list_remove(ws->list, wid); + ws->ordered = g_list_remove(ws->ordered, wid); +} + +void +gnt_ws_set_name(GntWS *ws, const gchar *name) +{ + g_free(ws->name); + ws->name = g_strdup(name); +} + +void +gnt_ws_hide(GntWS *ws, GHashTable *nodes) +{ + g_list_foreach(ws->ordered, widget_hide, nodes); +} + +void gnt_ws_widget_hide(GntWidget *widget, GHashTable *nodes) { + widget_hide(widget, nodes); +} + +void gnt_ws_widget_show(GntWidget *widget, GHashTable *nodes) { + widget_show(widget, nodes); +} + +void +gnt_ws_show(GntWS *ws, GHashTable *nodes) +{ + GList *l; + for (l = g_list_last(ws->ordered); l; l = g_list_previous(l)) + widget_show(l->data, nodes); +} + +GType +gnt_ws_get_gtype(void) +{ + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(GntWSClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + NULL, + /*(GClassInitFunc)gnt_ws_class_init,*/ + NULL, + NULL, /* class_data */ + sizeof(GntWS), + 0, /* n_preallocs */ + gnt_ws_init, /* instance_init */ + NULL /* value_table */ + }; + + type = g_type_register_static(GNT_TYPE_BINDABLE, + "GntWS", + &info, 0); + } + + return type; +} + +GntWS *gnt_ws_new(const char *name) +{ + GntWS *ws = GNT_WS(g_object_new(GNT_TYPE_WS, NULL)); + ws->name = g_strdup(name ? name : "(noname)"); + return ws; +} + +const char * gnt_ws_get_name(GntWS *ws) +{ + return ws->name; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/finch/libgnt/gntws.h Sat Jun 16 20:16:36 2007 +0000 @@ -0,0 +1,60 @@ +#ifndef GNTWS_H +#define GNTWS_H + +#include "gntwidget.h" + +#include <panel.h> + +#define GNT_TYPE_WS (gnt_ws_get_gtype()) +#define GNT_WS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_WS, GntWS)) +#define GNT_IS_WS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_WS)) +#define GNT_IS_WS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_WS)) +#define GNT_WS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_WS, GntWSClass)) + +typedef struct _GntWS GntWS; + +struct _GntWS +{ + GntBindable inherit; + gchar *name; + GList *list; + GList *ordered; + gpointer ui_data; + + void *res1; + void *res2; + void *res3; + void *res4; +}; + +typedef struct _GntWSClass GntWSClass; + +struct _GntWSClass +{ + GntBindableClass parent; + + void (*draw_taskbar)(GntWS *ws, gboolean ); + + void (*res1)(void); + void (*res2)(void); + void (*res3)(void); + void (*res4)(void); +}; + +G_BEGIN_DECLS + +GType gnt_ws_get_gtype(void); + +GntWS *gnt_ws_new(const char *name); +void gnt_ws_set_name(GntWS *, const gchar *); +void gnt_ws_add_widget(GntWS *, GntWidget *); +void gnt_ws_remove_widget(GntWS *, GntWidget *); +void gnt_ws_widget_hide(GntWidget *, GHashTable *nodes); +void gnt_ws_widget_show(GntWidget *, GHashTable *nodes); +void gnt_ws_draw_taskbar(GntWS *, gboolean reposition); +void gnt_ws_hide(GntWS *, GHashTable *); +void gnt_ws_show(GntWS *, GHashTable *); + +const char * gnt_ws_get_name(GntWS *ws); + +#endif
--- a/finch/libgnt/wms/irssi.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/wms/irssi.c Sat Jun 16 20:16:36 2007 +0000 @@ -1,12 +1,13 @@ /** - * 1. Buddylist and conversation windows are borderless and full height of the screen. - * 2. Conversation windows will have (full-screen-width - buddylist-width) width - * - It's possible to auto-resize the conversation windows when the buddylist - * is closed/opened/resized to keep this always true. But resizing the textview - * in conversation window is rather costly, especially when there's a lot of text - * in the scrollback. So it's not done yet. + * 1. Buddylist is aligned on the left. + * 2. The rest of the screen is split into MxN grid for conversation windows. + * - M = irssi-split-h in ~/.gntrc:[general] + * - N = irssi-split-v in ~/.gntrc:[general] + * - Press alt-shift-k/j/l/h to move the selected window to the frame + * above/below/left/right of the current frame. * 3. All the other windows are always centered. */ +#include <stdlib.h> #include <string.h> #include <sys/types.h> @@ -23,6 +24,11 @@ typedef struct _Irssi { GntWM inherit; + int vert; + int horiz; + + /* This is changed whenever the buddylist is opened/closed or resized. */ + int buddylistwidth; } Irssi; typedef struct _IrssiClass @@ -35,8 +41,63 @@ static void (*org_new_window)(GntWM *wm, GntWidget *win); -/* This is changed whenever the buddylist is opened/closed or resized. */ -static int buddylistwidth; +static void +get_xywh_for_frame(Irssi *irssi, int hor, int vert, int *x, int *y, int *w, int *h) +{ + int width, height, rx, ry; + + width = (getmaxx(stdscr) - irssi->buddylistwidth) / irssi->horiz; + height = (getmaxy(stdscr) - 1) / irssi->vert; + + rx = irssi->buddylistwidth; + if (hor) + rx += hor * width; + rx++; + + ry = 0; + if (vert) + ry += vert * height + 1; + + if (x) *x = rx; + if (y) *y = ry; + if (w) { + *w = (hor == irssi->horiz - 1) ? (getmaxx(stdscr) - rx) : (width - 1); + } + if (h) { + *h = (vert == irssi->vert - 1) ? (getmaxy(stdscr) - 1 - ry) : (height - !!vert); + } +} + +static void +draw_line_separators(Irssi *irssi) +{ + int x, y; + int width, height; + + wclear(stdscr); + /* Draw the separator for the buddylist */ + if (irssi->buddylistwidth) + mvwvline(stdscr, 0, irssi->buddylistwidth, + ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL), getmaxy(stdscr) - 1); + + /* Now the separators for the conversation windows */ + width = (getmaxx(stdscr) - irssi->buddylistwidth) / irssi->horiz; + height = (getmaxy(stdscr) - 1) / irssi->vert; + for (x = 1; x < irssi->horiz; x++) { + mvwvline(stdscr, 0, irssi->buddylistwidth + x * width, + ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL), getmaxy(stdscr) - 1); + } + + for (y = 1; y < irssi->vert; y++) { + mvwhline(stdscr, y * height, irssi->buddylistwidth + 1, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL), + getmaxx(stdscr) - irssi->buddylistwidth); + for (x = 1; x < irssi->horiz; x++) { + mvwaddch(stdscr, y * height, x * width + irssi->buddylistwidth, ACS_PLUS | COLOR_PAIR(GNT_COLOR_NORMAL)); + } + if (irssi->buddylistwidth) + mvwaddch(stdscr, y * height, irssi->buddylistwidth, ACS_LTEE | COLOR_PAIR(GNT_COLOR_NORMAL)); + } +} static gboolean is_budddylist(GntWidget *win) @@ -62,12 +123,12 @@ irssi_new_window(GntWM *wm, GntWidget *win) { const char *name; + int x, y, w, h; name = gnt_widget_get_name(win); if (!name || strcmp(name, "conversation-window")) { if (!GNT_IS_MENU(win) && !GNT_WIDGET_IS_FLAG_SET(win, GNT_WIDGET_TRANSIENT)) { if ((!name || strcmp(name, "buddylist"))) { - int w, h, x, y; gnt_widget_get_size(win, &w, &h); x = (getmaxx(stdscr) - w) / 2; y = (getmaxy(stdscr) - h) / 2; @@ -75,9 +136,8 @@ mvwin(win->window, y, x); } else { remove_border_set_position_size(wm, win, 0, 0, -1, getmaxy(stdscr) - 1); - gnt_widget_get_size(win, &buddylistwidth, NULL); - mvwvline(stdscr, 0, buddylistwidth, ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL), getmaxy(stdscr) - 1); - buddylistwidth++; + gnt_widget_get_size(win, &((Irssi*)wm)->buddylistwidth, NULL); + draw_line_separators((Irssi*)wm); } } org_new_window(wm, win); @@ -85,8 +145,12 @@ } /* The window we have here is a conversation window. */ - remove_border_set_position_size(wm, win, buddylistwidth, 0, - getmaxx(stdscr) - buddylistwidth, getmaxy(stdscr) - 1); + + /* XXX: There should be some way to remember which frame a conversation window + * was in the last time. Perhaps save them in some ~/.gntpositionirssi or some + * such. */ + get_xywh_for_frame((Irssi*)wm, 0, 0, &x, &y, &w, &h); + remove_border_set_position_size(wm, win, x, y, w, h); org_new_window(wm, win); } @@ -96,23 +160,94 @@ if (!is_budddylist(node->me)) return; - if (buddylistwidth) - mvwvline(stdscr, 0, buddylistwidth - 1, - ' ' | COLOR_PAIR(GNT_COLOR_NORMAL), getmaxy(stdscr) - 1); - gnt_widget_get_size(node->me, &buddylistwidth, NULL); - mvwvline(stdscr, 0, buddylistwidth, ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL), getmaxy(stdscr) - 1); - buddylistwidth++; + gnt_widget_get_size(node->me, &((Irssi*)wm)->buddylistwidth, NULL); + draw_line_separators((Irssi*)wm); } static gboolean irssi_close_window(GntWM *wm, GntWidget *win) { if (is_budddylist(win)) - buddylistwidth = 0; + ((Irssi*)wm)->buddylistwidth = 0; + return FALSE; +} + +static gboolean +update_conv_window_title(GntNode *node) +{ + char title[256]; + snprintf(title, sizeof(title), "%d: %s", + GPOINTER_TO_INT(g_object_get_data(G_OBJECT(node->me), "irssi-index")) + 1, + GNT_BOX(node->me)->title); + wbkgdset(node->window, '\0' | COLOR_PAIR(gnt_widget_has_focus(node->me) ? GNT_COLOR_TITLE : GNT_COLOR_TITLE_D)); + mvwaddstr(node->window, 0, 0, title); + update_panels(); + doupdate(); return FALSE; } static void +irssi_update_window(GntWM *wm, GntNode *node) +{ + GntWidget *win = node->me; + const char *name = gnt_widget_get_name(win); + if (!name || !GNT_IS_BOX(win) || strcmp(name, "conversation-window")) + return; + g_object_set_data(G_OBJECT(win), "irssi-index", GINT_TO_POINTER(g_list_index(wm->cws->list, win))); + g_timeout_add(0, (GSourceFunc)update_conv_window_title, node); +} + +static void +find_window_position(Irssi *irssi, GntWidget *win, int *h, int *v) +{ + int x, y; + int width, height; + + gnt_widget_get_position(win, &x, &y); + width = (getmaxx(stdscr) - irssi->buddylistwidth) / irssi->horiz; + height = (getmaxy(stdscr) - 1) / irssi->vert; + + if (h) + *h = (x - irssi->buddylistwidth) / width; + if (v) + *v = y / height; +} + +static gboolean +move_direction(GntBindable *bindable, GList *list) +{ + GntWM *wm = GNT_WM(bindable); + Irssi *irssi = (Irssi*)wm; + int vert, hor; + int x, y, w, h; + GntWidget *win; + + if (wm->cws->ordered == NULL || is_budddylist(win = GNT_WIDGET(wm->cws->ordered->data))) + return FALSE; + + find_window_position(irssi, win, &hor, &vert); + + switch (GPOINTER_TO_INT(list->data)) { + case 'k': + vert = MAX(0, vert - 1); + break; + case 'j': + vert = MIN(vert + 1, irssi->vert - 1); + break; + case 'l': + hor = MIN(hor + 1, irssi->horiz - 1); + break; + case 'h': + hor = MAX(0, hor - 1); + break; + } + get_xywh_for_frame(irssi, hor, vert, &x, &y, &w, &h); + gnt_wm_move_window(wm, win, x, y); + gnt_wm_resize_window(wm, win, w, h); + return TRUE; +} + +static void irssi_class_init(IrssiClass *klass) { GntWMClass *pclass = GNT_WM_CLASS(klass); @@ -122,6 +257,16 @@ pclass->new_window = irssi_new_window; pclass->window_resized = irssi_window_resized; pclass->close_window = irssi_close_window; + pclass->window_update = irssi_update_window; + + gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "move-up", move_direction, + "\033" "K", GINT_TO_POINTER('k'), NULL); + gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "move-down", move_direction, + "\033" "J", GINT_TO_POINTER('j'), NULL); + gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "move-right", move_direction, + "\033" "L", GINT_TO_POINTER('l'), NULL); + gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "move-left", move_direction, + "\033" "H", GINT_TO_POINTER('h'), NULL); gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass)); GNTDEBUG; @@ -129,8 +274,22 @@ void gntwm_init(GntWM **wm) { - buddylistwidth = 0; - *wm = g_object_new(TYPE_IRSSI, NULL); + const char *style = NULL; + Irssi *irssi; + + irssi = g_object_new(TYPE_IRSSI, NULL); + *wm = GNT_WM(irssi); + + style = gnt_style_get_from_name("irssi-split-v"); + irssi->vert = style ? atoi(style) : 1; + + style = gnt_style_get_from_name("irssi-split-h"); + irssi->horiz = style ? atoi(style) : 1; + + irssi->vert = MAX(irssi->vert, 1); + irssi->horiz = MAX(irssi->horiz, 1); + + irssi->buddylistwidth = 0; } GType irssi_get_gtype(void)
--- a/finch/libgnt/wms/s.c Fri Jun 15 08:16:29 2007 +0000 +++ b/finch/libgnt/wms/s.c Sat Jun 16 20:16:36 2007 +0000 @@ -121,7 +121,7 @@ static GntWidget * find_widget(GntWM *wm, const char *wname) { - const GList *iter = wm->list; + const GList *iter = wm->cws->list; for (; iter; iter = iter->next) { GntWidget *widget = iter->data; const char *name = gnt_widget_get_name(widget);
--- a/libpurple/account.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/account.c Sat Jun 16 20:16:36 2007 +0000 @@ -371,7 +371,7 @@ accounts_to_xmlnode(void) { xmlnode *node, *child; - GList *cur; + const GList *cur; node = xmlnode_new("account"); xmlnode_set_attrib(node, "version", "1.0"); @@ -417,7 +417,7 @@ schedule_accounts_save() { if (save_timer == 0) - save_timer = purple_timeout_add(5000, save_cb, NULL); + save_timer = purple_timeout_add_seconds(5, save_cb, NULL); } @@ -877,7 +877,7 @@ void purple_account_destroy(PurpleAccount *account) { - GList *l; + const GList *l; g_return_if_fail(account != NULL); @@ -2272,7 +2272,7 @@ schedule_accounts_save(); } -GList * +const GList * purple_accounts_get_all(void) { return accounts; @@ -2282,7 +2282,7 @@ purple_accounts_get_all_active(void) { GList *list = NULL; - GList *all = purple_accounts_get_all(); + const GList *all = purple_accounts_get_all(); while (all != NULL) { PurpleAccount *account = all->data; @@ -2300,7 +2300,7 @@ purple_accounts_find(const char *name, const char *protocol_id) { PurpleAccount *account = NULL; - GList *l; + const GList *l; char *who; g_return_val_if_fail(name != NULL, NULL); @@ -2327,7 +2327,7 @@ void purple_accounts_restore_current_statuses() { - GList *l; + const GList *l; PurpleAccount *account; /* If we're not connected to the Internet right now, we bail on this */
--- a/libpurple/account.h Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/account.h Sat Jun 16 20:16:36 2007 +0000 @@ -886,7 +886,7 @@ * * @return A list of all accounts. */ -GList *purple_accounts_get_all(void); +const GList *purple_accounts_get_all(void); /** * Returns a list of all enabled accounts
--- a/libpurple/accountopt.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/accountopt.c Sat Jun 16 20:16:36 2007 +0000 @@ -308,6 +308,7 @@ split->text = g_strdup(text); split->field_sep = sep; split->default_value = g_strdup(default_value); + split->reverse = TRUE; return split; } @@ -345,3 +346,19 @@ return split->field_sep; } + +gboolean +purple_account_user_split_get_reverse(const PurpleAccountUserSplit *split) +{ + g_return_val_if_fail(split != NULL, FALSE); + + return split->reverse; +} + +void +purple_account_user_split_set_reverse(PurpleAccountUserSplit *split, gboolean reverse) +{ + g_return_if_fail(split != NULL); + + split->reverse = reverse; +}
--- a/libpurple/accountopt.h Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/accountopt.h Sat Jun 16 20:16:36 2007 +0000 @@ -64,6 +64,9 @@ char *text; /**< The text that will appear to the user. */ char *default_value; /**< The default value. */ char field_sep; /**< The field separator. */ + gboolean reverse; /**< TRUE if the separator should be found + starting a the end of the string, FALSE + otherwise */ } PurpleAccountUserSplit; @@ -353,6 +356,23 @@ */ char purple_account_user_split_get_separator(const PurpleAccountUserSplit *split); +/** + * Returns the 'reverse' value for an account split. + * + * @param split The account username split. + * + * @return The 'reverse' value. + */ +gboolean purple_account_user_split_get_reverse(const PurpleAccountUserSplit *split); + +/** + * Sets the 'reverse' value for an account split. + * + * @param split The account username split. + * @param reverse The 'reverse' value + */ +void purple_account_user_split_set_reverse(PurpleAccountUserSplit *split, gboolean reverse); + /*@}*/ #ifdef __cplusplus
--- a/libpurple/blist.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/blist.c Sat Jun 16 20:16:36 2007 +0000 @@ -304,7 +304,7 @@ { xmlnode *node, *child, *grandchild; PurpleBlistNode *gnode; - GList *cur; + const GList *cur; node = xmlnode_new("purple"); xmlnode_set_attrib(node, "version", "1.0"); @@ -365,7 +365,7 @@ purple_blist_schedule_save() { if (save_timer == 0) - save_timer = purple_timeout_add(5000, save_cb, NULL); + save_timer = purple_timeout_add_seconds(5, save_cb, NULL); } @@ -1895,7 +1895,7 @@ { PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); PurpleBlistNode *node; - GList *l; + const GList *l; g_return_if_fail(group != NULL);
--- a/libpurple/buddyicon.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/buddyicon.c Sat Jun 16 20:16:36 2007 +0000 @@ -24,7 +24,6 @@ */ #include "internal.h" #include "buddyicon.h" -#include "cipher.h" #include "conversation.h" #include "dbus-maybe.h" #include "debug.h" @@ -93,33 +92,6 @@ } } -static char * -purple_buddy_icon_data_calculate_filename(guchar *icon_data, size_t icon_len) -{ - PurpleCipherContext *context; - gchar digest[41]; - - context = purple_cipher_context_new_by_name("sha1", NULL); - if (context == NULL) - { - purple_debug_error("buddyicon", "Could not find sha1 cipher\n"); - g_return_val_if_reached(NULL); - } - - /* Hash the icon data */ - purple_cipher_context_append(context, icon_data, icon_len); - if (!purple_cipher_context_digest_to_str(context, sizeof(digest), digest, NULL)) - { - purple_debug_error("buddyicon", "Failed to get SHA-1 digest.\n"); - g_return_val_if_reached(NULL); - } - purple_cipher_context_destroy(context); - - /* Return the filename */ - return g_strdup_printf("%s.%s", digest, - purple_util_get_image_extension(icon_data, icon_len)); -} - static void purple_buddy_icon_data_cache(PurpleStoredImage *img) { @@ -238,7 +210,7 @@ if (filename == NULL) { - file = purple_buddy_icon_data_calculate_filename(icon_data, icon_len); + file = purple_util_get_image_filename(icon_data, icon_len); if (file == NULL) { g_free(icon_data); @@ -966,7 +938,7 @@ g_free(path); - new_filename = purple_buddy_icon_data_calculate_filename(icon_data, icon_len); + new_filename = purple_util_get_image_filename(icon_data, icon_len); if (new_filename == NULL) { purple_debug_error("buddyicon", @@ -1049,7 +1021,7 @@ _purple_buddy_icons_account_loaded_cb() { const char *dirname = purple_buddy_icons_get_cache_dir(); - GList *cur; + const GList *cur; for (cur = purple_accounts_get_all(); cur != NULL; cur = cur->next) {
--- a/libpurple/buddyicon.h Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/buddyicon.h Sat Jun 16 20:16:36 2007 +0000 @@ -31,6 +31,7 @@ #include "blist.h" #include "imgstore.h" #include "prpl.h" +#include "util.h" #ifdef __cplusplus extern "C" {
--- a/libpurple/connection.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/connection.c Sat Jun 16 20:16:36 2007 +0000 @@ -72,7 +72,7 @@ if (on && !gc->keepalive) { purple_debug_info("connection", "Activating keepalive.\n"); - gc->keepalive = purple_timeout_add(30000, send_keepalive, gc); + gc->keepalive = purple_timeout_add_seconds(30, send_keepalive, gc); } else if (!on && gc->keepalive > 0) { @@ -456,7 +456,7 @@ void purple_connections_disconnect_all(void) { - GList *l; + const GList *l; PurpleConnection *gc; while ((l = purple_connections_get_all()) != NULL) { @@ -466,13 +466,13 @@ } } -GList * +const GList * purple_connections_get_all(void) { return connections; } -GList * +const GList * purple_connections_get_connecting(void) { return connections_connecting;
--- a/libpurple/connection.h Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/connection.h Sat Jun 16 20:16:36 2007 +0000 @@ -261,14 +261,14 @@ * * @return A list of all active connections. */ -GList *purple_connections_get_all(void); +const GList *purple_connections_get_all(void); /** * Returns a list of all connections in the process of connecting. * * @return A list of connecting connections. */ -GList *purple_connections_get_connecting(void); +const GList *purple_connections_get_connecting(void); /** * Checks if gc is still a valid pointer to a gc. @@ -279,7 +279,7 @@ * TODO: Eventually this bad boy will be removed, because it is * a gross fix for a crashy problem. */ -#define PURPLE_CONNECTION_IS_VALID(gc) (g_list_find(purple_connections_get_all(), (gc)) != NULL) +#define PURPLE_CONNECTION_IS_VALID(gc) (g_list_find((GList *)purple_connections_get_all(), (gc)) != NULL) /*@}*/
--- a/libpurple/conversation.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/conversation.c Sat Jun 16 20:16:36 2007 +0000 @@ -109,8 +109,12 @@ type = purple_conversation_get_type(conv); - /* Always linkfy the text for display */ - displayed = purple_markup_linkify(message); + /* Always linkfy the text for display, unless we're + * explicitly asked to do otheriwse*/ + if(msgflags & PURPLE_MESSAGE_NO_LINKIFY) + displayed = g_strdup(message); + else + displayed = purple_markup_linkify(message); if ((conv->features & PURPLE_CONNECTION_HTML) && !(msgflags & PURPLE_MESSAGE_RAW)) @@ -627,7 +631,7 @@ purple_conversation_foreach(void (*func)(PurpleConversation *conv)) { PurpleConversation *conv; - GList *l; + const GList *l; g_return_if_fail(func != NULL); @@ -728,19 +732,19 @@ return g_hash_table_lookup(conv->data, key); } -GList * +const GList * purple_get_conversations(void) { return conversations; } -GList * +const GList * purple_get_ims(void) { return ims; } -GList * +const GList * purple_get_chats(void) { return chats; @@ -755,7 +759,7 @@ PurpleConversation *c = NULL; gchar *name1; const gchar *name2; - GList *cnv; + const GList *cnv; g_return_val_if_fail(name != NULL, NULL); @@ -815,7 +819,7 @@ return; if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM && - !g_list_find(purple_get_conversations(), conv)) + !g_list_find((GList *)purple_get_conversations(), conv)) return; displayed = g_strdup(message); @@ -1011,7 +1015,7 @@ conv = purple_conv_im_get_conversation(im); name = purple_conversation_get_name(conv); - im->typing_timeout = purple_timeout_add(timeout * 1000, reset_typing_cb, conv); + im->typing_timeout = purple_timeout_add_seconds(timeout, reset_typing_cb, conv); } void @@ -1246,7 +1250,7 @@ return users; } -GList * +const GList * purple_conv_chat_get_users(const PurpleConvChat *chat) { g_return_val_if_fail(chat != NULL, NULL); @@ -1265,7 +1269,7 @@ return; purple_conv_chat_set_ignored(chat, - g_list_append(purple_conv_chat_get_ignored(chat), g_strdup(name))); + g_list_append(chat->ignored, g_strdup(name))); } void @@ -1280,11 +1284,11 @@ if (!purple_conv_chat_is_user_ignored(chat, name)) return; - item = g_list_find(purple_conv_chat_get_ignored(chat), + item = g_list_find((GList *)purple_conv_chat_get_ignored(chat), purple_conv_chat_get_ignored_user(chat, name)); purple_conv_chat_set_ignored(chat, - g_list_remove_link(purple_conv_chat_get_ignored(chat), item)); + g_list_remove_link(chat->ignored, item)); g_free(item->data); g_list_free_1(item); @@ -1300,7 +1304,7 @@ return ignored; } -GList * +const GList * purple_conv_chat_get_ignored(const PurpleConvChat *chat) { g_return_val_if_fail(chat != NULL, NULL); @@ -1311,7 +1315,7 @@ const char * purple_conv_chat_get_ignored_user(const PurpleConvChat *chat, const char *user) { - GList *ignored; + const GList *ignored; g_return_val_if_fail(chat != NULL, NULL); g_return_val_if_fail(user != NULL, NULL); @@ -1561,7 +1565,7 @@ cbuddy = purple_conv_chat_cb_new(user, alias, flag); /* This seems dumb. Why should we set users thousands of times? */ purple_conv_chat_set_users(chat, - g_list_prepend(purple_conv_chat_get_users(chat), cbuddy)); + g_list_prepend(chat->in_room, cbuddy)); cbuddies = g_list_prepend(cbuddies, cbuddy); @@ -1579,7 +1583,9 @@ } g_free(escaped); - purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL)); + purple_conversation_write(conv, NULL, tmp, + PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LINKIFY, + time(NULL)); g_free(tmp); } @@ -1628,7 +1634,7 @@ flags = purple_conv_chat_user_get_flags(chat, old_user); cb = purple_conv_chat_cb_new(new_user, NULL, flags); purple_conv_chat_set_users(chat, - g_list_prepend(purple_conv_chat_get_users(chat), cb)); + g_list_prepend(chat->in_room, cb)); if (!strcmp(chat->nick, purple_normalize(conv->account, old_user))) { const char *alias; @@ -1660,7 +1666,7 @@ if (cb) { purple_conv_chat_set_users(chat, - g_list_remove(purple_conv_chat_get_users(chat), cb)); + g_list_remove(chat->in_room, cb)); purple_conv_chat_cb_destroy(cb); } @@ -1705,7 +1711,9 @@ g_free(escaped2); } - purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL)); + purple_conversation_write(conv, NULL, tmp, + PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LINKIFY, + time(NULL)); } } @@ -1752,7 +1760,7 @@ if (cb) { purple_conv_chat_set_users(chat, - g_list_remove(purple_conv_chat_get_users(chat), cb)); + g_list_remove(chat->in_room, cb)); purple_conv_chat_cb_destroy(cb); } @@ -1782,7 +1790,9 @@ } g_free(escaped); - purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL)); + purple_conversation_write(conv, NULL, tmp, + PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LINKIFY, + time(NULL)); g_free(tmp); } @@ -1799,14 +1809,15 @@ { PurpleConversation *conv; PurpleConversationUiOps *ops; - GList *users, *names = NULL; - GList *l; + GList *users; + const GList *l; + GList *names = NULL; g_return_if_fail(chat != NULL); conv = purple_conv_chat_get_conversation(chat); ops = purple_conversation_get_ui_ops(conv); - users = purple_conv_chat_get_users(chat); + users = chat->in_room; if (ops != NULL && ops->chat_remove_users != NULL) { for (l = users; l; l = l->next) { @@ -1908,7 +1919,7 @@ PurpleConversation * purple_find_chat(const PurpleConnection *gc, int id) { - GList *l; + const GList *l; PurpleConversation *conv; for (l = purple_get_chats(); l != NULL; l = l->next) { @@ -1957,7 +1968,7 @@ PurpleConvChatBuddy * purple_conv_chat_cb_find(PurpleConvChat *chat, const char *name) { - GList *l; + const GList *l; PurpleConvChatBuddy *cb = NULL; g_return_val_if_fail(chat != NULL, NULL);
--- a/libpurple/conversation.h Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/conversation.h Sat Jun 16 20:16:36 2007 +0000 @@ -116,7 +116,9 @@ PURPLE_MESSAGE_RAW = 0x0800, /**< "Raw" message - don't apply formatting */ PURPLE_MESSAGE_IMAGES = 0x1000, /**< Message contains images */ - PURPLE_MESSAGE_NOTIFY = 0x2000 /**< Message is a notification */ + PURPLE_MESSAGE_NOTIFY = 0x2000, /**< Message is a notification */ + PURPLE_MESSAGE_NO_LINKIFY = 0x4000 /**< Message should not be auto- + linkified */ } PurpleMessageFlags; @@ -502,21 +504,21 @@ * * @return A GList of all conversations. */ -GList *purple_get_conversations(void); +const GList *purple_get_conversations(void); /** * Returns a list of all IMs. * * @return A GList of all IMs. */ -GList *purple_get_ims(void); +const GList *purple_get_ims(void); /** * Returns a list of all chats. * * @return A GList of all chats. */ -GList *purple_get_chats(void); +const GList *purple_get_chats(void); /** * Finds a conversation with the specified type, name, and Purple account. @@ -875,7 +877,7 @@ * * @return The list of users. */ -GList *purple_conv_chat_get_users(const PurpleConvChat *chat); +const GList *purple_conv_chat_get_users(const PurpleConvChat *chat); /** * Ignores a user in a chat room. @@ -910,7 +912,7 @@ * * @return The list of ignored users. */ -GList *purple_conv_chat_get_ignored(const PurpleConvChat *chat); +const GList *purple_conv_chat_get_ignored(const PurpleConvChat *chat); /** * Returns the actual name of the specified ignored user, if it exists in
--- a/libpurple/core.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/core.c Sat Jun 16 20:16:36 2007 +0000 @@ -48,7 +48,11 @@ #include "util.h" #ifdef HAVE_DBUS +# define DBUS_API_SUBJECT_TO_CHANGE +# include <dbus/dbus.h> +# include "dbus-purple.h" # include "dbus-server.h" +# include "dbus-bindings.h" #endif struct PurpleCore @@ -276,6 +280,91 @@ return _ops; } +#ifdef HAVE_DBUS +static char *purple_dbus_owner_user_dir(void) +{ + DBusMessage *msg = NULL, *reply = NULL; + DBusConnection *dbus_connection = NULL; + DBusError dbus_error; + char *remote_user_dir = NULL; + + if ((dbus_connection = purple_dbus_get_connection()) == NULL) + return NULL; + + if ((msg = dbus_message_new_method_call(DBUS_SERVICE_PURPLE, DBUS_PATH_PURPLE, DBUS_INTERFACE_PURPLE, "PurpleUserDir")) == NULL) + return NULL; + + dbus_error_init(&dbus_error); + reply = dbus_connection_send_with_reply_and_block(dbus_connection, msg, 5000, &dbus_error); + dbus_message_unref(msg); + dbus_error_free(&dbus_error); + + if (reply) + { + dbus_error_init(&dbus_error); + dbus_message_get_args(reply, &dbus_error, DBUS_TYPE_STRING, &remote_user_dir, DBUS_TYPE_INVALID); + remote_user_dir = g_strdup(remote_user_dir); + dbus_error_free(&dbus_error); + dbus_message_unref(reply); + } + + return remote_user_dir; +} + +static void purple_dbus_owner_show_buddy_list(void) +{ + DBusError dbus_error; + DBusMessage *msg = NULL, *reply = NULL; + DBusConnection *dbus_connection = NULL; + + if ((dbus_connection = purple_dbus_get_connection()) == NULL) + return; + + if ((msg = dbus_message_new_method_call(DBUS_SERVICE_PURPLE, DBUS_PATH_PURPLE, DBUS_INTERFACE_PURPLE, "PurpleBlistShow")) == NULL) + return; + + dbus_error_init(&dbus_error); + if ((reply = dbus_connection_send_with_reply_and_block(dbus_connection, msg, 5000, &dbus_error)) != NULL) + { + dbus_message_unref(msg); + } + dbus_error_free(&dbus_error); +} +#endif /* HAVE_DBUS */ + +gboolean +purple_core_ensure_single_instance() +{ + gboolean is_single_instance = TRUE; +#ifdef HAVE_DBUS + /* in the future, other mechanisms might have already set this to FALSE */ + if (is_single_instance) + { + if (!purple_dbus_is_owner()) + { + const char *user_dir = purple_user_dir(); + char *dbus_owner_user_dir = purple_dbus_owner_user_dir(); + + if (NULL == user_dir && NULL != dbus_owner_user_dir) + is_single_instance = TRUE; + else if (NULL != user_dir && NULL == dbus_owner_user_dir) + is_single_instance = TRUE; + else if (NULL == user_dir && NULL == dbus_owner_user_dir) + is_single_instance = FALSE; + else + is_single_instance = strcmp(dbus_owner_user_dir, user_dir); + + if (!is_single_instance) + purple_dbus_owner_show_buddy_list(); + + g_free(dbus_owner_user_dir); + } + } +#endif /* HAVE_DBUS */ + + return is_single_instance; +} + static gboolean move_and_symlink_dir(const char *path, const char *basename, const char *old_base, const char *new_base, const char *relative) {
--- a/libpurple/core.h Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/core.h Sat Jun 16 20:16:36 2007 +0000 @@ -121,6 +121,16 @@ */ gboolean purple_core_migrate(void); +/** + * Ensures that only one instance is running. + * + * @return A boolean such that @c TRUE indicates that this is the first instance, + * whereas @c FALSE indicates that there is another instance running. + * + * @since 2.1.0 + */ +gboolean purple_core_ensure_single_instance(void); + #ifdef __cplusplus } #endif
--- a/libpurple/dbus-analyze-functions.py Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/dbus-analyze-functions.py Sat Jun 16 20:16:36 2007 +0000 @@ -33,9 +33,13 @@ ] # This is a list of functions that return a GList* whose elements are -# string, not pointers to objects. Don't put any functions here, it -# won't work. -stringlists = [] +# string, not pointers to objects. +stringlists = [ + "purple_prefs_get_path_list", + "purple_prefs_get_string_list", + "purple_uri_list_extract_filenames", + "purple_uri_list_extract_uris", +] pointer = "#pointer#" myexception = "My Exception" @@ -148,7 +152,7 @@ return self.outputpurplestructure(type, name) if type[0] in ["GList", "GSList"]: - return self.outputlist(type, name) + return self.outputlist(type, name, const) raise myexception @@ -250,7 +254,7 @@ self.returncode.append("return (%s*) GINT_TO_POINTER(%s);" % (type[0], name)); self.definepurplestructure(type) - def outputlist(self, type, name): + def outputlist(self, type, name, const): self.functiontype = "%s*" % type[0] self.decls.append("GArray *%s;" % name) self.outputparams.append(('dbus_g_type_get_collection("GArray", G_TYPE_INT)', name)) @@ -385,28 +389,40 @@ self.addouttype("i", name) # GList*, GSList*, assume that list is a list of objects - - # fixme: at the moment, we do NOT free the memory occupied by - # the list, we should free it if the list has NOT been declared const - - # fixme: we assume that this is a list of objects, not a list - # of strings - - def outputlist(self, type, name): + # unless the function is in stringlists + def outputlist(self, type, name, const): self.cdecls.append("\tdbus_int32_t %s_LEN;" % name) self.ccodeout.append("\tg_free(%s);" % name) + if const: + const_prefix = "const_" + else: + const_prefix = "" + + if (const): + self.cdecls.append("\tconst %s *list;" % type[0]); + else: + self.cdecls.append("\t%s *list;" % type[0]); + if self.function.name in stringlists: self.cdecls.append("\tchar **%s;" % name) - self.ccode.append("\t%s = purple_%s_to_array(%s, FALSE, &%s_LEN);" % \ - (name, type[0], self.call, name)) + self.ccode.append("\tlist = %s;" % self.call) + self.ccode.append("\t%s = (char **)purple_const_%s_to_array(list, &%s_LEN);" % \ + (name, type[0], name)) self.cparamsout.append("\tDBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &%s, %s_LEN" \ % (name, name)) + if (not const): + type_name = type[0].lower()[1:] + self.ccodeout.append("\tg_%s_foreach(list, (GFunc)g_free, NULL);" % type_name) + self.ccodeout.append("\tg_%s_free(list);" % type_name) self.addouttype("as", name) else: self.cdecls.append("\tdbus_int32_t *%s;" % name) - self.ccode.append("\t%s = purple_dbusify_%s(%s, FALSE, &%s_LEN);" % \ - (name, type[0], self.call, name)) + self.ccode.append("\tlist = %s;" % self.call) + self.ccode.append("\t%s = purple_dbusify_const_%s(list, &%s_LEN);" % \ + (name, type[0], name)) + if (not const): + self.ccode.append("\tg_%s_free(list);" % type[0].lower()[1:]) self.cparamsout.append("\tDBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &%s, %s_LEN" \ % (name, name)) self.addouttype("ai", name)
--- a/libpurple/dbus-bindings.h Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/dbus-bindings.h Sat Jun 16 20:16:36 2007 +0000 @@ -83,14 +83,52 @@ int first_arg_type, va_list var_args); +/** + * @deprecated In 3.0.0, this method will have a signature and behavior + * like that of purple_dbusify_const_GList(). + */ dbus_int32_t* purple_dbusify_GList(GList *list, gboolean free_memory, dbus_int32_t *len); +/** + * @deprecated In 3.0.0, this method will have a signature and behavior + * like that of purple_dbusify_const_GSList(). + */ dbus_int32_t* purple_dbusify_GSList(GSList *list, gboolean free_memory, dbus_int32_t *len); + +/** + * @since 2.1.0 + */ +dbus_int32_t* purple_dbusify_const_GList(const GList *list, dbus_int32_t *len); + +/** + * @since 2.1.0 + */ +dbus_int32_t* purple_dbusify_const_GSList(const GSList *list, dbus_int32_t *len); + +/** + * @deprecated In 3.0.0, this method will have a signature and behavior + * like that of purple_const_GList_to_array(). + */ gpointer* purple_GList_to_array(GList *list, gboolean free_memory, dbus_int32_t *len); +/** + * @deprecated In 3.0.0, this method will have a signature and behavior + * like that of purple_const_GSList_to_array(). + */ gpointer* purple_GSList_to_array(GSList *list, gboolean free_memory, dbus_int32_t *len); + +/** + * @since 2.1.0 + */ +gpointer* purple_const_GList_to_array(const GList *list, dbus_int32_t *len); + +/** + * @since 2.1.0 + */ +gpointer* purple_const_GSList_to_array(const GSList *list, dbus_int32_t *len); + GHashTable *purple_dbus_iter_hash_table(DBusMessageIter *iter, DBusError *error); const char* empty_to_null(const char *str);
--- a/libpurple/dbus-server.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/dbus-server.c Sat Jun 16 20:16:36 2007 +0000 @@ -65,6 +65,12 @@ static GHashTable *map_id_type; static gchar *init_error; +static int dbus_request_name_reply = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER; + +gboolean purple_dbus_is_owner(void) +{ + return(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER == dbus_request_name_reply); +} /** * This function initializes the pointer-id traslation system. It @@ -284,19 +290,45 @@ } dbus_int32_t * -purple_dbusify_GList(GList *list, gboolean free_memory, dbus_int32_t *len) +purple_dbusify_const_GList(const GList *list, dbus_int32_t *len) { dbus_int32_t *array; int i; - GList *elem; + const GList *elem; - *len = g_list_length(list); - array = g_new0(dbus_int32_t, g_list_length(list)); + /* g_list_length() should really take a const GList */ + *len = g_list_length((GList *)list); + array = g_new0(dbus_int32_t, *len); for (i = 0, elem = list; elem != NULL; elem = elem->next, i++) array[i] = purple_dbus_pointer_to_id(elem->data); - if (free_memory) - g_list_free(list); + return array; +} + +dbus_int32_t * +purple_dbusify_GList(GList *list, gboolean free_memory, dbus_int32_t *len) +{ + dbus_int32_t *array = purple_dbusify_const_GList(list, len); + + if (!free_memory) + return array; + + g_list_free(list); + return array; +} + +dbus_int32_t * +purple_dbusify_const_GSList(const GSList *list, dbus_int32_t *len) +{ + dbus_int32_t *array; + int i; + const GSList *elem; + + /* g_slist_length should really take a const GSList */ + *len = g_slist_length((GSList *)list); + array = g_new0(dbus_int32_t, *len); + for (i = 0, elem = list; elem != NULL; elem = elem->next, i++) + array[i] = purple_dbus_pointer_to_id(elem->data); return array; } @@ -304,17 +336,26 @@ dbus_int32_t * purple_dbusify_GSList(GSList *list, gboolean free_memory, dbus_int32_t *len) { - dbus_int32_t *array; - int i; - GSList *elem; + dbus_int32_t *array = purple_dbusify_const_GSList(list, len); + + if (!free_memory) + return array; + + g_slist_free(list); + return array; +} - *len = g_slist_length(list); - array = g_new0(dbus_int32_t, g_slist_length(list)); +gpointer * +purple_const_GList_to_array(const GList *list, dbus_int32_t *len) +{ + gpointer *array; + int i; + const GList *elem; + + *len = g_list_length((GList *)list); + array = g_new0(gpointer, *len); for (i = 0, elem = list; elem != NULL; elem = elem->next, i++) - array[i] = purple_dbus_pointer_to_id(elem->data); - - if (free_memory) - g_slist_free(list); + array[i] = elem->data; return array; } @@ -322,36 +363,39 @@ gpointer * purple_GList_to_array(GList *list, gboolean free_memory, dbus_int32_t *len) { + gpointer *array = purple_const_GList_to_array(list, len); + + if (!free_memory) + return array; + + g_list_free(list); + return array; +} + +gpointer * +purple_const_GSList_to_array(const GSList *list, dbus_int32_t *len) +{ gpointer *array; int i; - GList *elem; + const GSList *elem; - *len = g_list_length(list); - array = g_new0(gpointer, g_list_length(list)); + *len = g_slist_length((GSList *)list); + array = g_new0(gpointer, *len); for (i = 0, elem = list; elem != NULL; elem = elem->next, i++) array[i] = elem->data; - if (free_memory) - g_list_free(list); - return array; } gpointer * purple_GSList_to_array(GSList *list, gboolean free_memory, dbus_int32_t *len) { - gpointer *array; - int i; - GSList *elem; + gpointer *array = purple_const_GSList_to_array(list, len); - *len = g_slist_length(list); - array = g_new0(gpointer, g_slist_length(list)); - for (i = 0, elem = list; elem != NULL; elem = elem->next, i++) - array[i] = elem->data; + if (!free_memory) + return array; - if (free_memory) - g_slist_free(list); - + g_slist_free(list); return array; } @@ -592,6 +636,7 @@ return; } + dbus_request_name_reply = result = dbus_bus_request_name(purple_dbus_connection, DBUS_SERVICE_PURPLE, 0, &error);
--- a/libpurple/dbus-server.h Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/dbus-server.h Sat Jun 16 20:16:36 2007 +0000 @@ -169,6 +169,13 @@ void *purple_dbus_get_handle(void); /** + * Determines whether this instance owns the DBus service name + * + * @since 2.1.0 + */ +gboolean purple_dbus_is_owner(void); + +/** * Starts Purple's D-BUS server. It is responsible for handling DBUS * requests from other applications. */
--- a/libpurple/dbus-useful.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/dbus-useful.c Sat Jun 16 20:16:36 2007 +0000 @@ -11,7 +11,7 @@ gboolean (*account_test)(const PurpleAccount *account)) { PurpleAccount *result = NULL; - GList *l; + const GList *l; char *who; if (name)
--- a/libpurple/eventloop.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/eventloop.c Sat Jun 16 20:16:36 2007 +0000 @@ -35,6 +35,17 @@ return ops->timeout_add(interval, function, data); } +guint +purple_timeout_add_seconds(guint interval, GSourceFunc function, gpointer data) +{ + PurpleEventLoopUiOps *ops = purple_eventloop_get_ui_ops(); + + if (ops->timeout_add_seconds) + return ops->timeout_add_seconds(interval, function, data); + else + return ops->timeout_add(1000 * interval, function, data); +} + gboolean purple_timeout_remove(guint tag) {
--- a/libpurple/eventloop.h Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/eventloop.h Sat Jun 16 20:16:36 2007 +0000 @@ -48,7 +48,7 @@ struct _PurpleEventLoopUiOps { /** - * Creates a callback timer. + * Creates a callback timer with an interval measured in milliseconds. * @see g_timeout_add, purple_timeout_add **/ guint (*timeout_add)(guint interval, GSourceFunc function, gpointer data); @@ -81,7 +81,20 @@ */ int (*input_get_error)(int fd, int *error); - void (*_purple_reserved1)(void); + /** + * Creates a callback timer with an interval measured in seconds. + * + * This allows UIs to group timers for better power efficiency. For + * this reason, @a interval may be rounded by up to a second. + * + * Implementation of this UI op is optional. If it's not implemented, + * calls to purple_timeout_add_seconds() will be serviced by the + * timeout_add UI op. + * + * @see g_timeout_add_seconds, purple_timeout_add_seconds() + **/ + guint (*timeout_add_seconds)(guint interval, GSourceFunc function, gpointer data); + void (*_purple_reserved2)(void); void (*_purple_reserved3)(void); void (*_purple_reserved4)(void); @@ -93,10 +106,15 @@ /*@{*/ /** * Creates a callback timer. + * * The timer will repeat until the function returns @c FALSE. The * first call will be at the end of the first interval. + * + * If the timer is in a multiple of seconds, use purple_timeout_add_seconds() + * instead as it allows UIs to group timers for power efficiency. + * * @param interval The time between calls of the function, in - * milliseconds. + * milliseconds. * @param function The function to call. * @param data data to pass to @a function. * @return A handle to the timer which can be passed to @@ -105,6 +123,24 @@ guint purple_timeout_add(guint interval, GSourceFunc function, gpointer data); /** + * Creates a callback timer. + * + * The timer will repeat until the function returns @c FALSE. The + * first call will be at the end of the first interval. + * + * This function allows UIs to group timers for better power efficiency. For + * this reason, @a interval may be rounded by up to a second. + * + * @param interval The time between calls of the function, in + * seconds. + * @param function The function to call. + * @param data data to pass to @a function. + * @return A handle to the timer which can be passed to + * purple_timeout_remove to remove the timer. + */ +guint purple_timeout_add_seconds(guint interval, GSourceFunc function, gpointer data); + +/** * Removes a timeout handler. * * @param handle The handle, as returned by purple_timeout_add.
--- a/libpurple/example/nullclient.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/example/nullclient.c Sat Jun 16 20:16:36 2007 +0000 @@ -108,11 +108,15 @@ glib_input_add, g_source_remove, NULL, +#if GLIB_CHECK_VERSION(2,14,0) + g_timeout_add_seconds, +#else + NULL, +#endif /* padding */ NULL, NULL, - NULL, NULL }; /*** End of the eventloop functions. ***/
--- a/libpurple/idle.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/idle.c Sat Jun 16 20:16:36 2007 +0000 @@ -199,7 +199,7 @@ /* Idle reporting stuff */ if (report_idle && (time_idle >= IDLEMARK)) { - GList *l; + const GList *l; for (l = purple_connections_get_all(); l != NULL; l = l->next) { PurpleConnection *gc = l->data; @@ -224,7 +224,11 @@ if (time_until_next_idle_event == 0) idle_timer = 0; else - idle_timer = purple_timeout_add(1000 * (time_until_next_idle_event + 1), check_idleness_timer, NULL); + { + /* +1 for the boundary, + * +1 more for g_timeout_add_seconds rounding. */ + idle_timer = purple_timeout_add_seconds(time_until_next_idle_event + 2, check_idleness_timer, NULL); + } return FALSE; } @@ -311,8 +315,10 @@ void purple_idle_init() { - /* Add the timer to check if we're idle */ - idle_timer = purple_timeout_add(1000 * (IDLEMARK + 1), check_idleness_timer, NULL); + /* Add the timer to check if we're idle. + * IDLEMARK + 1 as the boundary, + * +1 more for g_timeout_add_seconds rounding. */ + idle_timer = purple_timeout_add_seconds((IDLEMARK + 2), check_idleness_timer, NULL); purple_signal_connect(purple_conversations_get_handle(), "sent-im-msg", purple_idle_get_handle(),
--- a/libpurple/log.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/log.c Sat Jun 16 20:16:36 2007 +0000 @@ -32,6 +32,7 @@ #include "prefs.h" #include "util.h" #include "stringref.h" +#include "imgstore.h" static GSList *loggers = NULL; @@ -405,6 +406,9 @@ if (g_slist_find(loggers, logger)) return; loggers = g_slist_append(loggers, logger); + if (strcmp(purple_prefs_get_string("/purple/logging/format"), logger->id) == 0) { + purple_prefs_trigger_callback("/purple/logging/format"); + } } void purple_log_logger_remove (PurpleLogLogger *logger) @@ -690,6 +694,107 @@ return g_strdup(purple_time_format(&tm)); } +/* NOTE: This can return msg (which you may or may not want to g_free()) + * NOTE: or a newly allocated string which you MUST g_free(). */ +static char * +convert_image_tags(const PurpleLog *log, const char *msg) +{ + const char *tmp; + const char *start; + const char *end; + GData *attributes; + GString *newmsg = NULL; + + tmp = msg; + + while (purple_markup_find_tag("img", tmp, &start, &end, &attributes)) { + int imgid = 0; + char *idstr = NULL; + + if (newmsg == NULL) + newmsg = g_string_new(""); + + /* copy any text before the img tag */ + if (tmp < start) + g_string_append_len(newmsg, tmp, start - tmp); + + idstr = g_datalist_get_data(&attributes, "id"); + + imgid = atoi(idstr); + if (imgid != 0) + { + FILE *image_file; + char *dir; + PurpleStoredImage *image; + gconstpointer image_data; + char *new_filename = NULL; + char *path = NULL; + size_t image_byte_count; + + image = purple_imgstore_find_by_id(imgid); + if (image == NULL) + { + /* This should never happen. */ + g_string_free(newmsg, TRUE); + g_return_val_if_reached((char *)msg); + } + + image_data = purple_imgstore_get_data(image); + image_byte_count = purple_imgstore_get_size(image); + dir = purple_log_get_log_dir(log->type, log->name, log->account); + new_filename = purple_util_get_image_filename(image_data, image_byte_count); + + path = g_build_filename(dir, new_filename, NULL); + + /* Only save unique files. */ + if (!g_file_test(path, G_FILE_TEST_EXISTS)) + { + if ((image_file = g_fopen(path, "wb")) != NULL) + { + if (!fwrite(image_data, image_byte_count, 1, image_file)) + { + purple_debug_error("log", "Error writing %s: %s\n", + path, strerror(errno)); + fclose(image_file); + + /* Attempt to not leave half-written files around. */ + unlink(path); + } + else + { + purple_debug_info("log", "Wrote image file: %s\n", path); + fclose(image_file); + } + } + else + { + purple_debug_error("log", "Unable to create file %s: %s\n", + path, strerror(errno)); + } + } + + /* Write the new image tag */ + g_string_append_printf(newmsg, "<IMG SRC=\"%s\">", new_filename); + g_free(new_filename); + g_free(path); + } + + /* Continue from the end of the tag */ + tmp = end + 1; + } + + if (newmsg == NULL) + { + /* No images were found to change. */ + return (char *)msg; + } + + /* Append any remaining message data */ + g_string_append(newmsg, tmp); + + return g_string_free(newmsg, FALSE); +} + void purple_log_common_writer(PurpleLog *log, const char *ext) { PurpleLogCommonLoggerData *data = log->logger_data; @@ -880,7 +985,7 @@ GDir *protocol_dir; const gchar *username; gchar *protocol_unescaped; - GList *account_iter; + const GList *account_iter; GList *accounts = NULL; if ((protocol_dir = g_dir_open(protocol_path, 0, NULL)) == NULL) { @@ -1191,6 +1296,7 @@ const char *from, time_t time, const char *message) { char *msg_fixed; + char *image_corrected_msg; char *date; char *header; PurplePlugin *plugin = purple_find_prpl(purple_account_get_protocol_id(log->account)); @@ -1231,7 +1337,14 @@ if(!data->file) return 0; - purple_markup_html_to_xhtml(message, &msg_fixed, NULL); + image_corrected_msg = convert_image_tags(log, message); + purple_markup_html_to_xhtml(image_corrected_msg, &msg_fixed, NULL); + + /* Yes, this breaks encapsulation. But it's a static function and + * this saves a needless strdup(). */ + if (image_corrected_msg != message) + g_free(image_corrected_msg); + date = log_get_timestamp(log, time); if(log->type == PURPLE_LOG_SYSTEM){
--- a/libpurple/notify.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/notify.c Sat Jun 16 20:16:36 2007 +0000 @@ -530,7 +530,7 @@ g_free(user_info); } -GList * +const GList * purple_notify_user_info_get_entries(PurpleNotifyUserInfo *user_info) { g_return_val_if_fail(user_info != NULL, NULL);
--- a/libpurple/notify.h Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/notify.h Sat Jun 16 20:16:36 2007 +0000 @@ -458,7 +458,7 @@ * * @result A GList of PurpleNotifyUserInfoEntry objects */ -GList *purple_notify_user_info_get_entries(PurpleNotifyUserInfo *user_info); +const GList *purple_notify_user_info_get_entries(PurpleNotifyUserInfo *user_info); /** * Create a textual representation of a PurpleNotifyUserInfo, separating entries with newline
--- a/libpurple/plugins/joinpart.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/plugins/joinpart.c Sat Jun 16 20:16:36 2007 +0000 @@ -86,7 +86,7 @@ /* If the room is small, don't bother. */ chat = PURPLE_CONV_CHAT(conv); threshold = purple_prefs_get_int(THRESHOLD_PREF); - if (g_list_length(purple_conv_chat_get_users(chat)) < threshold) + if (g_list_length((GList *)purple_conv_chat_get_users(chat)) < threshold) return FALSE; /* We always care about our buddies! */
--- a/libpurple/plugins/log_reader.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/plugins/log_reader.c Sat Jun 16 20:16:36 2007 +0000 @@ -1290,9 +1290,16 @@ list = g_list_delete_link(list, last); } } - } else if (line[0] && line[1] && line [3] && + } else if (line[0] && line[1] && line[2] && purple_str_has_prefix(&line[3], "sion Start ")) { - + /* 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. + */ char *their_nickname = line; char *timestamp;
--- a/libpurple/plugins/perl/common/Account.xs Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/plugins/perl/common/Account.xs Sat Jun 16 20:16:36 2007 +0000 @@ -290,7 +290,7 @@ void purple_accounts_get_all() PREINIT: - GList *l; + const GList *l; PPCODE: for (l = purple_accounts_get_all(); l != NULL; l = l->next) { XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Account")));
--- a/libpurple/plugins/perl/common/Connection.xs Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/plugins/perl/common/Connection.xs Sat Jun 16 20:16:36 2007 +0000 @@ -72,7 +72,7 @@ void purple_connections_get_all() PREINIT: - GList *l; + const GList *l; PPCODE: for (l = purple_connections_get_all(); l != NULL; l = l->next) { XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Connection"))); @@ -81,7 +81,7 @@ void purple_connections_get_connecting() PREINIT: - GList *l; + const GList *l; PPCODE: for (l = purple_connections_get_connecting(); l != NULL; l = l->next) { XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Connection")));
--- a/libpurple/plugins/perl/common/Conversation.xs Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/plugins/perl/common/Conversation.xs Sat Jun 16 20:16:36 2007 +0000 @@ -93,7 +93,7 @@ void purple_get_ims() PREINIT: - GList *l; + const GList *l; PPCODE: for (l = purple_get_ims(); l != NULL; l = l->next) { XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Conversation"))); @@ -102,7 +102,7 @@ void purple_get_conversations() PREINIT: - GList *l; + const GList *l; PPCODE: for (l = purple_get_conversations(); l != NULL; l = l->next) { XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Conversation"))); @@ -111,7 +111,7 @@ void purple_get_chats() PREINIT: - GList *l; + const GList *l; PPCODE: for (l = purple_get_chats(); l != NULL; l = l->next) { XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Conversation"))); @@ -354,7 +354,7 @@ purple_conv_chat_get_users(chat) Purple::Conversation::Chat chat PREINIT: - GList *l; + const GList *l; PPCODE: for (l = purple_conv_chat_get_users(chat); l != NULL; l = l->next) { XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::ListEntry"))); @@ -394,7 +394,7 @@ purple_conv_chat_get_ignored(chat) Purple::Conversation::Chat chat PREINIT: - GList *l; + const GList *l; PPCODE: for (l = purple_conv_chat_get_ignored(chat); l != NULL; l = l->next) { XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::ListEntry")));
--- a/libpurple/plugins/perl/perl-handlers.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/plugins/perl/perl-handlers.c Sat Jun 16 20:16:36 2007 +0000 @@ -214,6 +214,7 @@ perl_timeout_cb(gpointer data) { PurplePerlTimeoutHandler *handler = (PurplePerlTimeoutHandler *)data; + gboolean ret = FALSE; dSP; ENTER; @@ -224,16 +225,16 @@ call_sv(handler->callback, G_EVAL | G_SCALAR); SPAGAIN; + ret = POPi; + PUTBACK; FREETMPS; LEAVE; - /* We're returning FALSE, so no need to manually remove the source */ - handler->iotag = 0; + if (ret == FALSE) + destroy_timeout_handler(handler); - destroy_timeout_handler(handler); - - return FALSE; + return ret; } typedef void *DATATYPE;
--- a/libpurple/plugins/tcl/tcl_cmds.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/plugins/tcl/tcl_cmds.c Sat Jun 16 20:16:36 2007 +0000 @@ -43,7 +43,7 @@ static PurpleAccount *tcl_validate_account(Tcl_Obj *obj, Tcl_Interp *interp) { PurpleAccount *account; - GList *cur; + const GList *cur; account = purple_tcl_ref_get(interp, obj, PurpleTclRefAccount); @@ -62,7 +62,7 @@ static PurpleConversation *tcl_validate_conversation(Tcl_Obj *obj, Tcl_Interp *interp) { PurpleConversation *convo; - GList *cur; + const GList *cur; convo = purple_tcl_ref_get(interp, obj, PurpleTclRefConversation); @@ -81,7 +81,7 @@ static PurpleConnection *tcl_validate_gc(Tcl_Obj *obj, Tcl_Interp *interp) { PurpleConnection *gc; - GList *cur; + const GList *cur; gc = purple_tcl_ref_get(interp, obj, PurpleTclRefConnection); @@ -612,7 +612,7 @@ const char *cmds[] = { "account", "displayname", "handle", "list", NULL }; enum { CMD_CONN_ACCOUNT, CMD_CONN_DISPLAYNAME, CMD_CONN_HANDLE, CMD_CONN_LIST } cmd; int error; - GList *cur; + const GList *cur; PurpleConnection *gc; if (objc < 2) { @@ -680,7 +680,7 @@ PurpleConversation *convo; PurpleAccount *account; PurpleConversationType type; - GList *cur; + const GList *cur; char *opt, *from, *what; int error, argsused, flags = 0;
--- a/libpurple/pounce.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/pounce.c Sat Jun 16 20:16:36 2007 +0000 @@ -273,7 +273,7 @@ schedule_pounces_save(void) { if (save_timer == 0) - save_timer = purple_timeout_add(5000, save_cb, NULL); + save_timer = purple_timeout_add_seconds(5, save_cb, NULL); }
--- a/libpurple/prefs.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/prefs.c Sat Jun 16 20:16:36 2007 +0000 @@ -226,7 +226,7 @@ schedule_prefs_save(void) { if (save_timer == 0) - save_timer = purple_timeout_add(5000, save_cb, NULL); + save_timer = purple_timeout_add_seconds(5, save_cb, NULL); }
--- a/libpurple/protocols/irc/irc.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/protocols/irc/irc.c Sat Jun 16 20:16:36 2007 +0000 @@ -592,7 +592,7 @@ struct irc_conn *irc = gc->proto_data; int len; - if(!g_list_find(purple_connections_get_all(), gc)) { + if(!g_list_find((GList *)purple_connections_get_all(), gc)) { purple_ssl_close(gsc); return; } @@ -814,7 +814,8 @@ static PurplePluginProtocolInfo prpl_info = { - OPT_PROTO_CHAT_TOPIC | OPT_PROTO_PASSWORD_OPTIONAL, + OPT_PROTO_CHAT_TOPIC | OPT_PROTO_PASSWORD_OPTIONAL | + OPT_PROTO_SLASH_COMMANDS_NATIVE, NULL, /* user_splits */ NULL, /* protocol_options */ NO_BUDDY_ICONS, /* icon_spec */
--- a/libpurple/protocols/jabber/disco.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/protocols/jabber/disco.c Sat Jun 16 20:16:36 2007 +0000 @@ -96,6 +96,7 @@ SUPPORT_FEATURE("http://jabber.org/protocol/si") SUPPORT_FEATURE("http://jabber.org/protocol/si/profile/file-transfer") SUPPORT_FEATURE("http://jabber.org/protocol/xhtml-im") + SUPPORT_FEATURE("urn:xmpp:ping") } else { xmlnode *error, *inf;
--- a/libpurple/protocols/jabber/iq.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/protocols/jabber/iq.c Sat Jun 16 20:16:36 2007 +0000 @@ -201,6 +201,24 @@ xmlnode_insert_data(xmlnode_new_child(query, "display"), date, -1); jabber_iq_send(iq); + } else { + /* XXX: error */ + } +} + +static void urn_xmpp_ping_parse(JabberStream *js, xmlnode *packet) +{ + const char *type, *id; + JabberIq *iq; + + if(type && !strcmp(type, "get")) { + iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "urn:xmpp:ping"); + + jabber_iq_set_id(iq, id); + + jabber_iq_send(iq); + } else { + /* XXX: error */ } } @@ -232,7 +250,8 @@ query = xmlnode_get_child(iq->node, "query"); - xmlnode_insert_data(xmlnode_new_child(query, "name"), PACKAGE, -1); + /* 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); if(os) { xmlnode_insert_data(xmlnode_new_child(query, "os"), os, -1); @@ -327,6 +346,7 @@ jabber_iq_register_handler("http://jabber.org/protocol/disco#info", jabber_disco_info_parse); jabber_iq_register_handler("http://jabber.org/protocol/disco#items", jabber_disco_items_parse); jabber_iq_register_handler("jabber:iq:register", jabber_register_parse); + jabber_iq_register_handler("urn:xmpp:ping", urn_xmpp_ping_parse); } void jabber_iq_uninit(void)
--- a/libpurple/protocols/jabber/jutil.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/protocols/jabber/jutil.c Sat Jun 16 20:16:36 2007 +0000 @@ -221,7 +221,7 @@ jabber_find_unnormalized_conv(const char *name, PurpleAccount *account) { PurpleConversation *c = NULL; - GList *cnv; + const GList *cnv; g_return_val_if_fail(name != NULL, NULL);
--- a/libpurple/protocols/jabber/libxmpp.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/protocols/jabber/libxmpp.c Sat Jun 16 20:16:36 2007 +0000 @@ -43,9 +43,11 @@ { #ifdef HAVE_CYRUS_SASL OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | - OPT_PROTO_MAIL_CHECK | OPT_PROTO_PASSWORD_OPTIONAL, + OPT_PROTO_MAIL_CHECK | OPT_PROTO_PASSWORD_OPTIONAL | + OPT_PROTO_SLASH_COMMANDS_NATIVE, #else - OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_MAIL_CHECK, + OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_MAIL_CHECK | + OPT_PROTO_SLASH_COMMANDS_NATIVE, #endif NULL, /* user_splits */ NULL, /* protocol_options */ @@ -193,9 +195,11 @@ /* Translators: 'domain' is used here in the context of Internet domains, e.g. pidgin.im */ split = purple_account_user_split_new(_("Domain"), NULL, '@'); + purple_account_user_split_set_reverse(split, FALSE); prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); split = purple_account_user_split_new(_("Resource"), "Home", '/'); + purple_account_user_split_set_reverse(split, FALSE); prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); option = purple_account_option_bool_new(_("Force old (port 5223) SSL"), "old_ssl", FALSE);
--- a/libpurple/protocols/msn/msn.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/protocols/msn/msn.c Sat Jun 16 20:16:36 2007 +0000 @@ -1463,7 +1463,7 @@ purple_debug_info("msn", "In msn_got_info\n"); /* Make sure the connection is still valid */ - if (g_list_find(purple_connections_get_all(), info_data->gc) == NULL) + if (g_list_find((GList *)purple_connections_get_all(), info_data->gc) == NULL) { purple_debug_warning("msn", "invalid connection. ignoring buddy info.\n"); g_free(info_data->name); @@ -1883,7 +1883,7 @@ /* Make sure the connection is still valid if we got here by fetching a photo url */ if (url_text && (error_message != NULL || - g_list_find(purple_connections_get_all(), info_data->gc) == NULL)) + g_list_find((GList *)purple_connections_get_all(), info_data->gc) == NULL)) { purple_debug_warning("msn", "invalid connection. ignoring buddy photo info.\n"); g_free(stripped); @@ -1982,7 +1982,7 @@ if (acct && !purple_account_is_connected(acct)) acct = NULL; } else { /* Otherwise find an active account for the protocol */ - GList *l = purple_accounts_get_all(); + const GList *l = purple_accounts_get_all(); while (l) { if (!strcmp(prpl, purple_account_get_protocol_id(l->data)) && purple_account_is_connected(l->data)) {
--- a/libpurple/protocols/msn/switchboard.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/protocols/msn/switchboard.c Sat Jun 16 20:16:36 2007 +0000 @@ -422,7 +422,7 @@ break; case MSN_SB_ERROR_AUTHFAILED: str_reason = _("Message could not be sent " - "because we wer unable to establish a " + "because we were unable to establish a " "session with the server. This is " "likely a server problem, try again in " "a few minutes:");
--- a/libpurple/protocols/oscar/oscar.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/protocols/oscar/oscar.c Sat Jun 16 20:16:36 2007 +0000 @@ -6558,7 +6558,7 @@ if (acct && !purple_account_is_connected(acct)) acct = NULL; } else { /* Otherwise find an active account for the protocol */ - GList *l = purple_accounts_get_all(); + const GList *l = purple_accounts_get_all(); while (l) { if (!strcmp(prpl, purple_account_get_protocol_id(l->data)) && purple_account_is_connected(l->data)) {
--- a/libpurple/protocols/silc/ft.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/protocols/silc/ft.c Sat Jun 16 20:16:36 2007 +0000 @@ -111,7 +111,7 @@ } else if (error == SILC_CLIENT_FILE_TIMEOUT) { purple_notify_error(gc, _("Secure File Transfer"), _("Error during file transfer"), - _("Connection timedout")); + _("Connection timed out")); } else if (error == SILC_CLIENT_FILE_CONNECT_FAILED) { purple_notify_error(gc, _("Secure File Transfer"), _("Error during file transfer"),
--- a/libpurple/protocols/silc/silc.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/protocols/silc/silc.c Sat Jun 16 20:16:36 2007 +0000 @@ -1787,7 +1787,8 @@ static PurplePluginProtocolInfo prpl_info = { OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | - OPT_PROTO_PASSWORD_OPTIONAL | OPT_PROTO_IM_IMAGE, + OPT_PROTO_PASSWORD_OPTIONAL | OPT_PROTO_IM_IMAGE | + OPT_PROTO_SLASH_COMMANDS_NATIVE, NULL, /* user_splits */ NULL, /* protocol_options */ {"jpeg,gif,png,bmp", 0, 0, 96, 96, 0, PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */
--- a/libpurple/protocols/silc10/silc.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/protocols/silc10/silc.c Sat Jun 16 20:16:36 2007 +0000 @@ -1717,10 +1717,12 @@ { #ifdef HAVE_SILCMIME_H OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | - OPT_PROTO_PASSWORD_OPTIONAL | OPT_PROTO_IM_IMAGE, + OPT_PROTO_PASSWORD_OPTIONAL | OPT_PROTO_IM_IMAGE | + OPT_PROTO_SLASH_COMMANDS_NATIVE, #else OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | - OPT_PROTO_PASSWORD_OPTIONAL, + OPT_PROTO_PASSWORD_OPTIONAL | + OPT_PROTO_SLASH_COMMANDS_NATIVE, #endif NULL, /* user_splits */ NULL, /* protocol_options */
--- a/libpurple/protocols/yahoo/yahoo.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo.c Sat Jun 16 20:16:36 2007 +0000 @@ -3861,7 +3861,7 @@ if (acct && !purple_account_is_connected(acct)) acct = NULL; } else { /* Otherwise find an active account for the protocol */ - GList *l = purple_accounts_get_all(); + const GList *l = purple_accounts_get_all(); while (l) { if (!strcmp(prpl, purple_account_get_protocol_id(l->data)) && purple_account_is_connected(l->data)) {
--- a/libpurple/protocols/yahoo/yahoochat.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoochat.c Sat Jun 16 20:16:36 2007 +0000 @@ -633,10 +633,10 @@ * I think conference names are always ascii. */ -void yahoo_conf_leave(struct yahoo_data *yd, const char *room, const char *dn, GList *who) +void yahoo_conf_leave(struct yahoo_data *yd, const char *room, const char *dn, const GList *who) { struct yahoo_packet *pkt; - GList *w; + const GList *w; purple_debug_misc("yahoo", "leaving conference %s\n", room); @@ -653,11 +653,11 @@ } static int yahoo_conf_send(PurpleConnection *gc, const char *dn, const char *room, - GList *members, const char *what) + const GList *members, const char *what) { struct yahoo_data *yd = gc->proto_data; struct yahoo_packet *pkt; - GList *who; + const GList *who; char *msg, *msg2; int utf8 = 1; @@ -714,7 +714,7 @@ { struct yahoo_data *yd = gc->proto_data; struct yahoo_packet *pkt; - GList *members; + const GList *members; char *msg2 = NULL; if (msg)
--- a/libpurple/protocols/yahoo/yahoochat.h Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoochat.h Sat Jun 16 20:16:36 2007 +0000 @@ -50,7 +50,7 @@ char *yahoo_get_chat_name(GHashTable *data); void yahoo_c_invite(PurpleConnection *gc, int id, const char *msg, const char *name); -void yahoo_conf_leave(struct yahoo_data *yd, const char *room, const char *dn, GList *who); +void yahoo_conf_leave(struct yahoo_data *yd, const char *room, const char *dn, const GList *who); void yahoo_chat_goto(PurpleConnection *gc, const char *name);
--- a/libpurple/prpl.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/prpl.c Sat Jun 16 20:16:36 2007 +0000 @@ -83,44 +83,50 @@ purple_prpl_got_user_idle(PurpleAccount *account, const char *name, gboolean idle, time_t idle_time) { - PurpleBuddy *buddy; PurplePresence *presence; + GSList *list; g_return_if_fail(account != NULL); g_return_if_fail(name != NULL); g_return_if_fail(purple_account_is_connected(account)); - if ((buddy = purple_find_buddy(account, name)) == NULL) + if ((list = purple_find_buddies(account, name)) == NULL) return; - presence = purple_buddy_get_presence(buddy); - - purple_presence_set_idle(presence, idle, idle_time); + while (list) { + presence = purple_buddy_get_presence(list->data); + list = g_slist_delete_link(list, list); + purple_presence_set_idle(presence, idle, idle_time); + } } void purple_prpl_got_user_login_time(PurpleAccount *account, const char *name, time_t login_time) { - PurpleBuddy *buddy; + GSList *list; PurplePresence *presence; g_return_if_fail(account != NULL); g_return_if_fail(name != NULL); - if ((buddy = purple_find_buddy(account, name)) == NULL) + if ((list = purple_find_buddies(account, name)) == NULL) return; if (login_time == 0) login_time = time(NULL); - presence = purple_buddy_get_presence(buddy); + while (list) { + PurpleBuddy *buddy = list->data; + presence = purple_buddy_get_presence(buddy); + list = g_slist_delete_link(list, list); - if (purple_presence_get_login_time(presence) != login_time) - { - purple_presence_set_login_time(presence, login_time); + if (purple_presence_get_login_time(presence) != login_time) + { + purple_presence_set_login_time(presence, login_time); - purple_signal_emit(purple_blist_get_handle(), "buddy-got-login-time", buddy); + purple_signal_emit(purple_blist_get_handle(), "buddy-got-login-time", buddy); + } } }
--- a/libpurple/prpl.h Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/prpl.h Sat Jun 16 20:16:36 2007 +0000 @@ -158,6 +158,12 @@ */ OPT_PROTO_REGISTER_NOSCREENNAME = 0x00000200, + /** + * Indicates that slash commands are native to this protocol. + * Used as a hint that unknown commands should not be sent as messages. + */ + OPT_PROTO_SLASH_COMMANDS_NATIVE = 0x00000400, + } PurpleProtocolOptions; /**
--- a/libpurple/purple-remote Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/purple-remote Sat Jun 16 20:16:36 2007 +0000 @@ -157,6 +157,12 @@ return None + elif command == "getstatus": + current = purple.PurpleSavedstatusGetCurrent() + status_type = purple.PurpleSavedstatusGetType(current) + status_id = purple.PurplePrimitiveGetIdFromType(status_type) + return status_id + elif command == "getinfo": account = findaccount(accountname, protocol) connection = cpurple.PurpleAccountGetConnection(account)
--- a/libpurple/savedstatuses.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/savedstatuses.c Sat Jun 16 20:16:36 2007 +0000 @@ -357,7 +357,7 @@ schedule_save(void) { if (save_timer == 0) - save_timer = purple_timeout_add(5000, save_cb, NULL); + save_timer = purple_timeout_add_seconds(5, save_cb, NULL); }
--- a/libpurple/server.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/server.c Sat Jun 16 20:16:36 2007 +0000 @@ -92,7 +92,7 @@ /* because we're modifying or creating a lar, schedule the * function to expire them as the pref dictates */ - purple_timeout_add((SECS_BEFORE_RESENDING_AUTORESPONSE + 1) * 1000, expire_last_auto_responses, NULL); + purple_timeout_add_seconds((SECS_BEFORE_RESENDING_AUTORESPONSE + 1), expire_last_auto_responses, NULL); tmp = last_auto_responses; @@ -233,8 +233,9 @@ char *tmp = g_strdup_printf(_("%s is now known as %s.\n"), who, alias); - purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, - time(NULL)); + purple_conversation_write(conv, NULL, tmp, + PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LINKIFY, + time(NULL)); g_free(tmp); }
--- a/libpurple/util.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/util.c Sat Jun 16 20:16:36 2007 +0000 @@ -22,6 +22,7 @@ */ #include "internal.h" +#include "cipher.h" #include "conversation.h" #include "core.h" #include "debug.h" @@ -156,6 +157,31 @@ return data; } +gchar * +purple_base16_encode_chunked(const guchar *data, gsize len) +{ + int i; + gchar *ascii = NULL; + + g_return_val_if_fail(data != NULL, NULL); + g_return_val_if_fail(len > 0, NULL); + + /* For each byte of input, we need 2 bytes for the hex representation + * and 1 for the colon. + * The final colon will be replaced by a terminating NULL + */ + ascii = g_malloc(len * 3 + 1); + + for (i = 0; i < len; i++) + g_snprintf(&ascii[i * 3], 4, "%02hhx:", data[i]); + + /* Replace the final colon with NULL */ + ascii[len * 3 - 1] = 0; + + return ascii; +} + + /************************************************************************** * Base64 Functions **************************************************************************/ @@ -987,7 +1013,6 @@ g_return_val_if_fail( needle != NULL, FALSE); g_return_val_if_fail( *needle != '\0', FALSE); g_return_val_if_fail( haystack != NULL, FALSE); - g_return_val_if_fail( *haystack != '\0', FALSE); g_return_val_if_fail( start != NULL, FALSE); g_return_val_if_fail( end != NULL, FALSE); g_return_val_if_fail(attributes != NULL, FALSE); @@ -1397,6 +1422,40 @@ plain = g_string_append_c(plain, '\n'); continue; } + if(!g_ascii_strncasecmp(c, "<img", 4) && (*(c+4) == '>' || *(c+4) == ' ')) { + const char *p = c; + GString *src = NULL; + struct purple_parse_tag *pt; + while(*p && *p != '>') { + if(!g_ascii_strncasecmp(p, "src=", strlen("src="))) { + const char *q = p + strlen("src="); + src = g_string_new(""); + if(*q == '\'' || *q == '\"') + q++; + while(*q && *q != '\"' && *q != '\'' && *q != ' ') { + src = g_string_append_c(src, *q); + q++; + } + p = q; + } + p++; + } + if ((c = strchr(c, '>')) != NULL) + c++; + else + c = p; + pt = g_new0(struct purple_parse_tag, 1); + pt->src_tag = "img"; + pt->dest_tag = "img"; + tags = g_list_prepend(tags, pt); + if(xhtml && src && src->len) + g_string_append_printf(xhtml, "<img src='%s' alt=''>", g_strstrip(src->str)); + else + pt->ignore = TRUE; + if (src) + g_string_free(src, TRUE); + continue; + } if(!g_ascii_strncasecmp(c, "<b>", 3) || !g_ascii_strncasecmp(c, "<bold>", strlen("<bold>"))) { struct purple_parse_tag *pt = g_new0(struct purple_parse_tag, 1); pt->src_tag = *(c+2) == '>' ? "b" : "bold"; @@ -1538,10 +1597,7 @@ pt->dest_tag = "span"; tags = g_list_prepend(tags, pt); if(style->len) - { - if(xhtml) - g_string_append_printf(xhtml, "<span style='%s'>", g_strstrip(style->str)); - } + g_string_append_printf(xhtml, "<span style='%s'>", g_strstrip(style->str)); else pt->ignore = TRUE; g_string_free(style, TRUE); @@ -2670,6 +2726,33 @@ return "icon"; } +char * +purple_util_get_image_filename(gconstpointer image_data, size_t image_len) +{ + PurpleCipherContext *context; + gchar digest[41]; + + context = purple_cipher_context_new_by_name("sha1", NULL); + if (context == NULL) + { + purple_debug_error("util", "Could not find sha1 cipher\n"); + g_return_val_if_reached(NULL); + } + + /* Hash the image data */ + purple_cipher_context_append(context, image_data, image_len); + if (!purple_cipher_context_digest_to_str(context, sizeof(digest), digest, NULL)) + { + purple_debug_error("util", "Failed to get SHA-1 digest.\n"); + g_return_val_if_reached(NULL); + } + purple_cipher_context_destroy(context); + + /* Return the filename */ + return g_strdup_printf("%s.%s", digest, + purple_util_get_image_extension(image_data, image_len)); +} + gboolean purple_program_is_valid(const char *program) {
--- a/libpurple/util.h Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/util.h Sat Jun 16 20:16:36 2007 +0000 @@ -32,6 +32,7 @@ #include "account.h" #include "xmlnode.h" +#include "notify.h" #ifdef __cplusplus extern "C" { @@ -118,6 +119,21 @@ */ guchar *purple_base16_decode(const char *str, gsize *ret_len); +/** + * Converts a chunk of binary data to a chunked base-16 representation + * (handy for key fingerprints) + * + * Example output: 01:23:45:67:89:AB:CD:EF + * + * @param data The data to convert. + * @param len The length of the data. + * + * @return The base-16 string in the ASCII chunked encoding. Must be + * g_free'd when no longer needed. + */ +gchar *purple_base16_encode_chunked(const guchar *data, gsize len); + + /*@}*/ /**************************************************************************/ @@ -608,6 +624,12 @@ const char * purple_util_get_image_extension(gconstpointer data, size_t len); +/** + * Returns a SHA-1 hash string of the data passed in with the correct file + * extention appended. + */ +char *purple_util_get_image_filename(gconstpointer image_data, size_t image_len); + /*@}*/
--- a/libpurple/xmlnode.c Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/xmlnode.c Sat Jun 16 20:16:36 2007 +0000 @@ -333,8 +333,9 @@ for(c = node->child; c; c = c->next) { if(c->type == XMLNODE_TYPE_DATA) { if(!str) - str = g_string_new(""); - str = g_string_append_len(str, c->data, c->data_sz); + str = g_string_new_len(c->data, c->data_sz); + else + str = g_string_append_len(str, c->data, c->data_sz); } } @@ -344,6 +345,18 @@ return g_string_free(str, FALSE); } +char * +xmlnode_get_data_unescaped(xmlnode *node) +{ + char *escaped = xmlnode_get_data(node); + + char *unescaped = escaped ? purple_unescape_html(escaped) : NULL; + + g_free(escaped); + + return unescaped; +} + static char * xmlnode_to_str_helper(xmlnode *node, int *len, gboolean formatting, int depth) {
--- a/libpurple/xmlnode.h Fri Jun 15 08:16:29 2007 +0000 +++ b/libpurple/xmlnode.h Sat Jun 16 20:16:36 2007 +0000 @@ -124,14 +124,24 @@ void xmlnode_insert_data(xmlnode *node, const char *data, gssize size); /** - * Gets data from a node. + * Gets (escaped) data from a node. * * @param node The node to get data from. * - * @return The data from the node. You must g_free + * @return The data from the node. This data is in raw escaped format. + * You must g_free this string when finished using it. + */ +char *xmlnode_get_data(xmlnode *node); + +/** + * Gets unescaped data from a node. + * + * @param node The node to get data from. + * + * @return The data from the node, in unescaped form. You must g_free * this string when finished using it. */ -char *xmlnode_get_data(xmlnode *node); +char *xmlnode_get_data_unescaped(xmlnode *node); /** * Sets an attribute for a node.
--- a/pidgin/Makefile.am Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/Makefile.am Sat Jun 16 20:16:36 2007 +0000 @@ -109,6 +109,8 @@ gtksession.c \ gtksound.c \ gtksourceiter.c \ + gtksourceundomanager.c \ + gtksourceview-marshal.c \ gtkstatusbox.c \ gtkthemes.c \ gtkutils.c \ @@ -156,6 +158,8 @@ gtksession.h \ gtksound.h \ gtksourceiter.h \ + gtksourceundomanager.h \ + gtksourceview-marshal.h \ gtkstatusbox.h \ pidginstock.h \ gtkthemes.h \
--- a/pidgin/Makefile.mingw Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/Makefile.mingw Sat Jun 16 20:16:36 2007 +0000 @@ -85,6 +85,7 @@ gtkscrollbook.c \ gtksound.c \ gtksourceiter.c \ + gtksourceundomanager.c \ gtkstatusbox.c \ gtkthemes.c \ gtkutils.c \
--- a/pidgin/gtkaccount.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/gtkaccount.c Sat Jun 16 20:16:36 2007 +0000 @@ -484,7 +484,11 @@ char *c; if (dialog->account != NULL) { - c = strrchr(username, + if(purple_account_user_split_get_reverse(split)) + c = strrchr(username, + purple_account_user_split_get_separator(split)); + else + c = strchr(username, purple_account_user_split_get_separator(split)); if (c != NULL) { @@ -702,7 +706,7 @@ GList *l; char buf[1024]; char *title, *tmp; - const char *str_value, *protocol; + const char *str_value; gboolean bool_value; if (dialog->protocol_frame != NULL) { @@ -829,8 +833,7 @@ /* Google Talk default domain hackery! */ menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(dialog->protocol_menu)); item = gtk_menu_get_active(GTK_MENU(menu)); - protocol = g_object_get_data(G_OBJECT(item), "protocol"); - if (str_value == NULL && protocol != NULL && !strcmp(protocol, "prpl-fake") && + if (str_value == NULL && g_object_get_data(G_OBJECT(item), "fake") && !strcmp(_("Connect server"), purple_account_option_get_text(option))) str_value = "talk.google.com"; @@ -1467,18 +1470,8 @@ if ((dialog->plugin = purple_find_prpl(dialog->protocol_id)) != NULL) dialog->prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(dialog->plugin); - - dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_role(GTK_WINDOW(win), "account"); - - if (type == PIDGIN_ADD_ACCOUNT_DIALOG) - gtk_window_set_title(GTK_WINDOW(win), _("Add Account")); - else - gtk_window_set_title(GTK_WINDOW(win), _("Modify Account")); - - gtk_window_set_resizable(GTK_WINDOW(win), FALSE); - - gtk_container_set_border_width(GTK_CONTAINER(win), PIDGIN_HIG_BORDER); + dialog->window = win = pidgin_create_window((type == PIDGIN_ADD_ACCOUNT_DIALOG) ? _("Add Account") : _("Modify Account"), + PIDGIN_HIG_BORDER, "account", FALSE); g_signal_connect(G_OBJECT(win), "delete_event", G_CALLBACK(account_win_destroy_cb), dialog); @@ -1593,7 +1586,7 @@ account = purple_connection_get_account(gc); model = GTK_TREE_MODEL(accounts_window->model); - index = g_list_index(purple_accounts_get_all(), account); + index = g_list_index((GList *)purple_accounts_get_all(), account); if (gtk_tree_model_iter_nth_child(model, &iter, NULL, index)) { @@ -1796,13 +1789,13 @@ case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: move_account_after(dialog->model, &dialog->drag_iter, &iter); - dest_index = g_list_index(purple_accounts_get_all(), + dest_index = g_list_index((GList *)purple_accounts_get_all(), account) + 1; break; case GTK_TREE_VIEW_DROP_BEFORE: case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: - dest_index = g_list_index(purple_accounts_get_all(), + dest_index = g_list_index((GList *)purple_accounts_get_all(), account); move_account_before(dialog->model, &dialog->drag_iter, @@ -2101,7 +2094,7 @@ static gboolean populate_accounts_list(AccountsWindow *dialog) { - GList *l; + const GList *l; gboolean ret = FALSE; GdkPixbuf *global_buddyicon = NULL; const char *path; @@ -2305,7 +2298,7 @@ global_buddyicon_changed(const char *name, PurplePrefType type, gconstpointer value, gpointer window) { - GList *list; + const GList *list; for (list = purple_accounts_get_all(); list; list = list->next) { account_modified_cb(list->data, window); } @@ -2322,7 +2315,6 @@ GtkWidget *button; int width, height; - if (accounts_window != NULL) { gtk_window_present(GTK_WINDOW(accounts_window->window)); return; @@ -2333,11 +2325,8 @@ width = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/accounts/dialog/width"); height = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/accounts/dialog/height"); - dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); + dialog->window = win = pidgin_create_window(_("Accounts"), PIDGIN_HIG_BORDER, "accounts", TRUE); gtk_window_set_default_size(GTK_WINDOW(win), width, height); - gtk_window_set_role(GTK_WINDOW(win), "accounts"); - gtk_window_set_title(GTK_WINDOW(win), _("Accounts")); - gtk_container_set_border_width(GTK_CONTAINER(win), PIDGIN_HIG_BORDER); g_signal_connect(G_OBJECT(win), "delete_event", G_CALLBACK(accedit_win_destroy_cb), accounts_window); @@ -2440,7 +2429,7 @@ { PurpleConnection *gc = purple_account_get_connection(data->account); - if (g_list_find(purple_connections_get_all(), gc)) + if (g_list_find((GList *)purple_connections_get_all(), gc)) { purple_blist_request_add_buddy(data->account, data->username, NULL, data->alias);
--- a/pidgin/gtkblist.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/gtkblist.c Sat Jun 16 20:16:36 2007 +0000 @@ -273,12 +273,7 @@ static void gtk_blist_menu_info_cb(GtkWidget *w, PurpleBuddy *b) { - PurpleNotifyUserInfo *info = purple_notify_user_info_new(); - purple_notify_user_info_add_pair(info, _("Information"), _("Retrieving...")); - purple_notify_userinfo(b->account->gc, purple_buddy_get_name(b), info, NULL, NULL); - purple_notify_user_info_destroy(info); - - serv_get_info(b->account->gc, b->name); + pidgin_retrieve_user_info(b->account->gc, purple_buddy_get_name(b)); } static void gtk_blist_menu_im_cb(GtkWidget *w, PurpleBuddy *b) @@ -701,7 +696,7 @@ gboolean pidgin_blist_joinchat_is_showable() { - GList *c; + const GList *c; PurpleConnection *gc; for (c = purple_connections_get_all(); c != NULL; c = c->next) { @@ -1155,7 +1150,8 @@ } static gboolean -gtk_blist_key_press_cb(GtkWidget *tv, GdkEventKey *event, gpointer data) { +gtk_blist_key_press_cb(GtkWidget *tv, GdkEventKey *event, gpointer data) +{ PurpleBlistNode *node; GValue val; GtkTreeIter iter; @@ -1182,7 +1178,7 @@ return FALSE; } if(buddy) - gtk_blist_menu_info_cb(NULL, buddy); + pidgin_retrieve_user_info(buddy->account->gc, buddy->name); } else if (event->keyval == GDK_F2) { gtk_blist_menu_alias_cb(tv, node); } @@ -1436,7 +1432,7 @@ prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); if (prpl && prpl_info->get_info) - gtk_blist_menu_info_cb(NULL, b); + pidgin_retrieve_user_info(b->account->gc, b->name); handled = TRUE; } @@ -1555,7 +1551,7 @@ add_buddies_from_vcard(const char *prpl_id, PurpleGroup *group, GList *list, const char *alias) { - GList *l; + const GList *l; PurpleAccount *account = NULL; PurpleConnection *gc; @@ -2864,6 +2860,7 @@ { N_("/Buddies/Add C_hat..."), NULL, pidgin_blist_add_chat_cb, 0, "<StockItem>", GTK_STOCK_ADD }, { N_("/Buddies/Add _Group..."), NULL, purple_blist_request_add_group, 0, "<StockItem>", GTK_STOCK_ADD }, { "/Buddies/sep3", NULL, NULL, 0, "<Separator>", NULL }, + { N_("/Buddies/_About Pidgin"), NULL, pidgin_dialogs_about, 0, "<Item>", NULL }, { N_("/Buddies/_Quit"), "<CTL>Q", purple_core_quit, 0, "<StockItem>", GTK_STOCK_QUIT }, /* Accounts menu */ @@ -2880,9 +2877,9 @@ { N_("/Tools/_File Transfers"), "<CTL>T", pidgin_xfer_dialog_show, 0, "<Item>", NULL }, { N_("/Tools/R_oom List"), NULL, pidgin_roomlist_dialog_show, 0, "<Item>", NULL }, { N_("/Tools/System _Log"), NULL, gtk_blist_show_systemlog_cb, 0, "<Item>", NULL }, + { N_("/Tools/_Debug Window"), NULL, toggle_debug, 0, "<Item>", NULL }, { "/Tools/sep3", NULL, NULL, 0, "<Separator>", NULL }, { N_("/Tools/Mute _Sounds"), "<CTL>S", pidgin_blist_mute_sounds_cb, 0, "<CheckItem>", NULL }, - /* Help */ { N_("/_Help"), NULL, NULL, 0, "<Branch>", NULL }, { N_("/Help/Online _Help"), "F1", gtk_blist_show_onlinehelp_cb, 0, "<StockItem>", GTK_STOCK_HELP }, @@ -2912,7 +2909,7 @@ prpl = purple_find_prpl(purple_account_get_protocol_id(chat->account)); prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - if (g_list_length(purple_connections_get_all()) > 1) + if (g_list_length((GList *)purple_connections_get_all()) > 1) { tmp = g_markup_escape_text(chat->account->username, -1); g_string_append_printf(str, _("\n<b>Account:</b> %s"), tmp); @@ -2977,7 +2974,7 @@ user_info = purple_notify_user_info_new(); /* Account */ - if (full && g_list_length(purple_connections_get_all()) > 1) + if (full && g_list_length((GList *)purple_connections_get_all()) > 1) { tmp = g_markup_escape_text(purple_account_get_username( purple_buddy_get_account(b)), -1); @@ -3864,15 +3861,17 @@ static gboolean gtk_blist_window_key_press_cb(GtkWidget *w, GdkEventKey *event, PidginBuddyList *gtkblist) { - GtkWidget *imhtml; + GtkWidget *widget; if (!gtkblist) return FALSE; - imhtml = gtk_window_get_focus(GTK_WINDOW(gtkblist->window)); - - if (GTK_IS_IMHTML(imhtml) && gtk_bindings_activate(GTK_OBJECT(imhtml), event->keyval, event->state)) - return TRUE; + widget = gtk_window_get_focus(GTK_WINDOW(gtkblist->window)); + + if (GTK_IS_IMHTML(widget) || GTK_IS_ENTRY(widget)) { + if (gtk_bindings_activate(GTK_OBJECT(widget), event->keyval, event->state)) + return TRUE; + } return FALSE; } @@ -4244,9 +4243,7 @@ gtkblist->empty_avatar = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 32, 32); gdk_pixbuf_fill(gtkblist->empty_avatar, 0x00000000); - gtkblist->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_role(GTK_WINDOW(gtkblist->window), "buddy_list"); - gtk_window_set_title(GTK_WINDOW(gtkblist->window), _("Buddy List")); + gtkblist->window = pidgin_create_window(_("Buddy List"), 0, "buddy_list", TRUE); g_signal_connect(G_OBJECT(gtkblist->window), "focus-in-event", G_CALLBACK(blist_focus_cb), gtkblist); GTK_WINDOW(gtkblist->window)->allow_shrink = TRUE; @@ -4902,7 +4899,7 @@ GROUP_EXPANDER_VISIBLE_COLUMN, TRUE, CONTACT_EXPANDER_VISIBLE_COLUMN, FALSE, BUDDY_ICON_VISIBLE_COLUMN, FALSE, - IDLE_VISIBLE_COLUMN, FALSE, + IDLE_VISIBLE_COLUMN, FALSE, EMBLEM_VISIBLE_COLUMN, FALSE, -1); g_free(title); @@ -5000,6 +4997,7 @@ idle = i2; } } + gtk_tree_store_set(gtkblist->treemodel, iter, STATUS_ICON_COLUMN, status, STATUS_ICON_VISIBLE_COLUMN, TRUE, @@ -5014,7 +5012,7 @@ CONTACT_EXPANDER_COLUMN, NULL, CONTACT_EXPANDER_VISIBLE_COLUMN, expanded, GROUP_EXPANDER_VISIBLE_COLUMN, FALSE, - -1); + -1); g_free(mark); g_free(idle); @@ -5735,7 +5733,7 @@ { PidginAddChatData *data; PidginBuddyList *gtkblist; - GList *l; + const GList *l; PurpleConnection *gc; GtkWidget *label; GtkWidget *rowbox; @@ -6502,7 +6500,8 @@ { GtkWidget *menuitem = NULL, *submenu = NULL; GtkAccelGroup *accel_group = NULL; - GList *l = NULL, *accounts = NULL; + GList *l = NULL; + const GList *accounts; gboolean disabled_accounts = FALSE; if (accountmenu == NULL)
--- a/pidgin/gtkconv.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/gtkconv.c Sat Jun 16 20:16:36 2007 +0000 @@ -420,6 +420,7 @@ char *cmd; const char *prefix; GtkTextIter start; + gboolean retval = FALSE; gtkconv = PIDGIN_CONVERSATION(conv); prefix = pidgin_get_cmd_prefix(); @@ -443,24 +444,50 @@ gtk_text_buffer_get_end_iter(GTK_IMHTML(gtkconv->entry)->text_buffer, &end); markup = gtk_imhtml_get_markup_range(GTK_IMHTML(gtkconv->entry), &start, &end); status = purple_cmd_do_command(conv, cmdline, markup, &error); - g_free(cmd); g_free(markup); switch (status) { case PURPLE_CMD_STATUS_OK: - return TRUE; + retval = TRUE; + break; case PURPLE_CMD_STATUS_NOT_FOUND: - return FALSE; + { + PurplePluginProtocolInfo *prpl_info = NULL; + PurpleConnection *gc; + + if ((gc = purple_conversation_get_gc(conv))) + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + + if ((prpl_info != NULL) && (prpl_info->options & OPT_PROTO_SLASH_COMMANDS_NATIVE)) { + char *firstspace; + char *slash; + + firstspace = strchr(cmdline, ' '); + if (firstspace != NULL) { + slash = strrchr(firstspace, '/'); + } else { + slash = strchr(cmdline, '/'); + } + + if (slash == NULL) { + purple_conversation_write(conv, "", _("Unknown command."), PURPLE_MESSAGE_NO_LOG, time(NULL)); + retval = TRUE; + } + } + break; + } case PURPLE_CMD_STATUS_WRONG_ARGS: purple_conversation_write(conv, "", _("Syntax Error: You typed the wrong number of arguments " "to that command."), PURPLE_MESSAGE_NO_LOG, time(NULL)); - return TRUE; + retval = TRUE; + break; case PURPLE_CMD_STATUS_FAILED: purple_conversation_write(conv, "", error ? error : _("Your command failed for an unknown reason."), PURPLE_MESSAGE_NO_LOG, time(NULL)); g_free(error); - return TRUE; + retval = TRUE; + break; case PURPLE_CMD_STATUS_WRONG_TYPE: if(purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) purple_conversation_write(conv, "", _("That command only works in chats, not IMs."), @@ -468,16 +495,18 @@ else purple_conversation_write(conv, "", _("That command only works in IMs, not chats."), PURPLE_MESSAGE_NO_LOG, time(NULL)); - return TRUE; + retval = TRUE; + break; case PURPLE_CMD_STATUS_WRONG_PRPL: purple_conversation_write(conv, "", _("That command doesn't work on this protocol."), PURPLE_MESSAGE_NO_LOG, time(NULL)); - return TRUE; + retval = TRUE; + break; } } g_free(cmd); - return FALSE; + return retval; } static void @@ -2661,7 +2690,7 @@ gboolean hidden_only, guint max_count) { - GList *l; + const GList *l; GList *r = NULL; guint c = 0; @@ -3821,7 +3850,7 @@ g_list_free(list); } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { PurpleConvChat *chat = PURPLE_CONV_CHAT(conv); - GList *l = purple_conv_chat_get_users(chat); + const GList *l = purple_conv_chat_get_users(chat); GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(PIDGIN_CONVERSATION(conv)->u.chat->list)); GtkTreeIter iter; int f; @@ -5060,7 +5089,11 @@ g_return_if_fail(gc != NULL); /* Make sure URLs are clickable */ - displaying = purple_markup_linkify(message); + if(flags & PURPLE_MESSAGE_NO_LINKIFY) + displaying = g_strdup(message); + else + displaying = purple_markup_linkify(message); + plugin_return = GPOINTER_TO_INT(purple_signal_emit_return_1( pidgin_conversations_get_handle(), (type == PURPLE_CONV_TYPE_IM ? "displaying-im-msg" : "displaying-chat-msg"), @@ -5413,7 +5446,7 @@ gtkconv = PIDGIN_CONVERSATION(conv); gtkchat = gtkconv->u.chat; - num_users = g_list_length(purple_conv_chat_get_users(chat)); + num_users = g_list_length((GList *)purple_conv_chat_get_users(chat)); g_snprintf(tmp, sizeof(tmp), ngettext("%d person in room", "%d people in room", @@ -5507,7 +5540,7 @@ gtkconv = PIDGIN_CONVERSATION(conv); gtkchat = gtkconv->u.chat; - num_users = g_list_length(purple_conv_chat_get_users(chat)); + num_users = g_list_length((GList *)purple_conv_chat_get_users(chat)); for (l = users; l != NULL; l = l->next) { model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); @@ -6504,7 +6537,7 @@ close_on_tabs_pref_cb(const char *name, PurplePrefType type, gconstpointer value, gpointer data) { - GList *l; + const GList *l; PurpleConversation *conv; PidginConversation *gtkconv; @@ -6528,7 +6561,7 @@ gconstpointer value, gpointer data) { #ifdef USE_GTKSPELL - GList *cl; + const GList *cl; PurpleConversation *conv; PidginConversation *gtkconv; GtkSpell *spell; @@ -6575,7 +6608,7 @@ show_timestamps_pref_cb(const char *name, PurplePrefType type, gconstpointer value, gpointer data) { - GList *l; + const GList *l; PurpleConversation *conv; PidginConversation *gtkconv; PidginWindow *win; @@ -6603,7 +6636,7 @@ show_formatting_toolbar_pref_cb(const char *name, PurplePrefType type, gconstpointer value, gpointer data) { - GList *l; + const GList *l; PurpleConversation *conv; PidginConversation *gtkconv; PidginWindow *win; @@ -6633,7 +6666,7 @@ animate_buddy_icons_pref_cb(const char *name, PurplePrefType type, gconstpointer value, gpointer data) { - GList *l; + const GList *l; PurpleConversation *conv; PidginConversation *gtkconv; PidginWindow *win; @@ -6660,7 +6693,7 @@ show_buddy_icons_pref_cb(const char *name, PurplePrefType type, gconstpointer value, gpointer data) { - GList *l; + const GList *l; for (l = purple_get_conversations(); l != NULL; l = l->next) { PurpleConversation *conv = l->data; @@ -6786,7 +6819,7 @@ static void account_signed_off_cb(PurpleConnection *gc, gpointer event) { - GList *iter; + const GList *iter; for (iter = purple_get_conversations(); iter; iter = iter->next) { @@ -8065,10 +8098,7 @@ window_list = g_list_append(window_list, win); /* Create the window. */ - win->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_role(GTK_WINDOW(win->window), "conversation"); - gtk_window_set_resizable(GTK_WINDOW(win->window), TRUE); - gtk_container_set_border_width(GTK_CONTAINER(win->window), 0); + win->window = pidgin_create_window(NULL, 0, "conversation", TRUE); GTK_WINDOW(win->window)->allow_shrink = TRUE; if (available_list == NULL) {
--- a/pidgin/gtkdialogs.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/gtkdialogs.c Sat Jun 16 20:16:36 2007 +0000 @@ -822,17 +822,8 @@ if (username != NULL && purple_str_has_suffix(username, "rocksmyworld")) found = pidgin_dialogs_ee(username); - if (!found && username != NULL && *username != '\0' && account != NULL) { - - PurpleConnection *gc = purple_account_get_connection(account); - - PurpleNotifyUserInfo *info = purple_notify_user_info_new(); - purple_notify_user_info_add_pair(info, _("Information"), _("Retrieving...")); - purple_notify_userinfo(gc, username, info, NULL, NULL); - purple_notify_user_info_destroy(info); - - serv_get_info(gc, username); - } + if (!found && username != NULL && *username != '\0' && account != NULL) + pidgin_retrieve_user_info(purple_account_get_connection(account), username); g_free(username); }
--- a/pidgin/gtkdocklet-x11.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/gtkdocklet-x11.c Sat Jun 16 20:16:36 2007 +0000 @@ -139,9 +139,9 @@ static void docklet_x11_resize_icon(GtkWidget *widget) { - if (docklet_height == widget->allocation.height) + if (docklet_height == MIN(widget->allocation.height, widget->allocation.width)) return; - docklet_height = widget->allocation.height; + docklet_height = MIN(widget->allocation.height, widget->allocation.width); pidgin_docklet_update_icon(); }
--- a/pidgin/gtkdocklet.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/gtkdocklet.c Sat Jun 16 20:16:36 2007 +0000 @@ -109,7 +109,8 @@ static gboolean docklet_update_status() { - GList *convs, *l; + GList *convs; + const GList *l; int count; PurpleSavedStatus *saved_status; PurpleStatusPrimitive newstatus = PURPLE_STATUS_OFFLINE; @@ -213,8 +214,7 @@ static gboolean online_account_supports_chat() { - GList *c = NULL; - c = purple_connections_get_all(); + const GList *c = purple_connections_get_all(); while(c != NULL) { PurpleConnection *gc = c->data;
--- a/pidgin/gtkeventloop.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/gtkeventloop.c Sat Jun 16 20:16:36 2007 +0000 @@ -120,7 +120,11 @@ pidgin_input_add, g_source_remove, NULL, /* input_get_error */ +#if GLIB_CHECK_VERSION(2,14,0) + g_timeout_add_seconds, +#else NULL, +#endif NULL, NULL, NULL
--- a/pidgin/gtkft.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/gtkft.c Sat Jun 16 20:16:36 2007 +0000 @@ -758,10 +758,7 @@ purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/filetransfer/clear_finished"); /* Create the window. */ - dialog->window = window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_role(GTK_WINDOW(window), "file transfer"); - gtk_window_set_title(GTK_WINDOW(window), _("File Transfers")); - gtk_container_set_border_width(GTK_CONTAINER(window), PIDGIN_HIG_BORDER); + dialog->window = window = pidgin_create_window(_("File Transfers"), PIDGIN_HIG_BORDER, "file transfer", TRUE); g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(delete_win_cb), dialog);
--- a/pidgin/gtkimhtml.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/gtkimhtml.c Sat Jun 16 20:16:36 2007 +0000 @@ -27,11 +27,15 @@ #ifdef HAVE_CONFIG_H #include <config.h> #endif + +#include "pidgin.h" + #include "debug.h" #include "util.h" #include "gtkimhtml.h" #include "gtksourceiter.h" -#include "pidgin.h" +#include "gtksourceundomanager.h" +#include "gtksourceview-marshal.h" #include <gtk/gtk.h> #include <glib/gerror.h> #include <gdk/gdkkeysyms.h> @@ -137,6 +141,8 @@ CLEAR_FORMAT, UPDATE_FORMAT, MESSAGE_SEND, + UNDO, + REDO, LAST_SIGNAL }; static guint signals [LAST_SIGNAL] = { 0 }; @@ -1151,6 +1157,23 @@ return FALSE; } +static void +gtk_imhtml_undo(GtkIMHtml *imhtml) { + g_return_if_fail(GTK_IS_IMHTML(imhtml)); + g_return_if_fail(imhtml->editable); + + gtk_source_undo_manager_undo(imhtml->undo_manager); +} + +static void +gtk_imhtml_redo(GtkIMHtml *imhtml) { + g_return_if_fail(GTK_IS_IMHTML(imhtml)); + g_return_if_fail(imhtml->editable); + + gtk_source_undo_manager_redo(imhtml->undo_manager); + +} + static gboolean imhtml_message_send(GtkIMHtml *imhtml) { return FALSE; @@ -1229,6 +1252,7 @@ g_queue_free(imhtml->animations); g_free(imhtml->protocol_name); g_free(imhtml->search_string); + g_object_unref(imhtml->undo_manager); G_OBJECT_CLASS(parent_class)->finalize (object); if (clipboard_selection) gtk_clipboard_set_with_owner(clipboard_selection, @@ -1298,10 +1322,32 @@ NULL, 0, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + signals [UNDO] = g_signal_new ("undo", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GtkIMHtmlClass, undo), + NULL, + NULL, + gtksourceview_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + signals [REDO] = g_signal_new ("redo", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GtkIMHtmlClass, redo), + NULL, + NULL, + gtksourceview_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + klass->toggle_format = imhtml_toggle_format; klass->message_send = imhtml_message_send; klass->clear_format = imhtml_clear_formatting; + klass->undo = gtk_imhtml_undo; + klass->redo = gtk_imhtml_redo; gobject_class->finalize = gtk_imhtml_finalize; widget_class->drag_motion = gtk_text_view_drag_motion; @@ -1326,12 +1372,17 @@ gtk_binding_entry_add_signal (binding_set, GDK_r, GDK_CONTROL_MASK, "format_function_clear", 0); gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0, "message_send", 0); gtk_binding_entry_add_signal (binding_set, GDK_Return, 0, "message_send", 0); + gtk_binding_entry_add_signal (binding_set, GDK_z, GDK_CONTROL_MASK, "undo", 0); + gtk_binding_entry_add_signal (binding_set, GDK_z, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "redo", 0); + gtk_binding_entry_add_signal (binding_set, GDK_F14, 0, "undo", 0); + } static void gtk_imhtml_init (GtkIMHtml *imhtml) { GtkTextIter iter; imhtml->text_buffer = gtk_text_buffer_new(NULL); + imhtml->undo_manager = gtk_source_undo_manager_new(imhtml->text_buffer); gtk_text_buffer_get_end_iter (imhtml->text_buffer, &iter); gtk_text_view_set_buffer(GTK_TEXT_VIEW(imhtml), imhtml->text_buffer); gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(imhtml), GTK_WRAP_WORD_CHAR); @@ -3114,14 +3165,13 @@ GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename, int id) { GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage)); - GtkImage *image = GTK_IMAGE(gtk_image_new_from_pixbuf(img)); GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale; GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to; GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_image_free; im_image->pixbuf = img; - im_image->image = image; + im_image->image = GTK_IMAGE(gtk_image_new_from_pixbuf(im_image->pixbuf)); im_image->width = gdk_pixbuf_get_width(img); im_image->height = gdk_pixbuf_get_height(img); im_image->mark = NULL; @@ -3133,6 +3183,76 @@ return GTK_IMHTML_SCALABLE(im_image); } +static gboolean +animate_image_cb(gpointer data) +{ + GtkIMHtmlImage *im_image; + int width, height; + int delay; + + im_image = data; + + /* Update the pointer to this GdkPixbuf frame of the animation */ + g_object_unref(G_OBJECT(im_image->pixbuf)); + gdk_pixbuf_animation_iter_advance(GTK_IMHTML_ANIMATION(im_image)->iter, NULL); + im_image->pixbuf = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter); + g_object_ref(G_OBJECT(im_image->pixbuf)); + + /* Update the displayed GtkImage */ + width = gdk_pixbuf_get_width(gtk_image_get_pixbuf(im_image->image)); + height = gdk_pixbuf_get_height(gtk_image_get_pixbuf(im_image->image)); + if (width > 0 && height > 0) + { + /* Need to scale the new frame to the same size as the old frame */ + GdkPixbuf *tmp; + tmp = gdk_pixbuf_scale_simple(im_image->pixbuf, width, height, GDK_INTERP_BILINEAR); + gtk_image_set_from_pixbuf(im_image->image, tmp); + g_object_unref(G_OBJECT(tmp)); + } else { + /* Display at full-size */ + gtk_image_set_from_pixbuf(im_image->image, im_image->pixbuf); + } + + delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100); + GTK_IMHTML_ANIMATION(im_image)->timer = g_timeout_add(delay, animate_image_cb, im_image); + + return FALSE; +} + +GtkIMHtmlScalable *gtk_imhtml_animation_new(GdkPixbufAnimation *anim, const gchar *filename, int id) +{ + GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlAnimation)); + + GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale; + GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to; + GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_animation_free; + + GTK_IMHTML_ANIMATION(im_image)->anim = anim; + if (gdk_pixbuf_animation_is_static_image(anim)) { + GTK_IMHTML_ANIMATION(im_image)->iter = NULL; + im_image->pixbuf = gdk_pixbuf_animation_get_static_image(anim); + GTK_IMHTML_ANIMATION(im_image)->timer = 0; + } else { + int delay; + GTK_IMHTML_ANIMATION(im_image)->iter = gdk_pixbuf_animation_get_iter(anim, NULL); + im_image->pixbuf = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter); + delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100); + GTK_IMHTML_ANIMATION(im_image)->timer = g_timeout_add(delay, animate_image_cb, im_image); + } + im_image->image = GTK_IMAGE(gtk_image_new_from_pixbuf(im_image->pixbuf)); + im_image->width = gdk_pixbuf_animation_get_width(anim); + im_image->height = gdk_pixbuf_animation_get_height(anim); + im_image->mark = NULL; + im_image->filename = g_strdup(filename); + im_image->id = id; + im_image->filesel = NULL; + + g_object_ref(anim); + g_object_ref(im_image->pixbuf); + + return GTK_IMHTML_SCALABLE(im_image); +} + void gtk_imhtml_image_scale(GtkIMHtmlScalable *scale, int width, int height) { GtkIMHtmlImage *im_image = (GtkIMHtmlImage *)scale; @@ -3407,7 +3527,6 @@ static gboolean gtk_imhtml_smiley_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlSmiley *smiley) { GdkPixbufAnimation *anim = NULL; - GdkPixbuf *pix = NULL; GtkIMHtmlScalable *image = NULL; gboolean ret; @@ -3418,11 +3537,9 @@ if (!anim) return FALSE; - pix = gdk_pixbuf_animation_get_static_image(anim); - image = gtk_imhtml_image_new(pix, smiley->smile, 0); + image = gtk_imhtml_animation_new(anim, smiley->smile, 0); ret = gtk_imhtml_image_clicked(w, event, (GtkIMHtmlImage*)image); g_object_set_data_full(G_OBJECT(w), "image-data", image, (GDestroyNotify)gtk_imhtml_image_free); - g_object_unref(G_OBJECT(pix)); return ret; } @@ -3437,6 +3554,19 @@ g_free(scale); } +void gtk_imhtml_animation_free(GtkIMHtmlScalable *scale) +{ + GtkIMHtmlAnimation *animation = (GtkIMHtmlAnimation *)scale; + + if (animation->timer > 0) + g_source_remove(animation->timer); + if (animation->iter != NULL) + g_object_unref(animation->iter); + g_object_unref(animation->anim); + + gtk_imhtml_image_free(scale); +} + void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) { GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; @@ -4517,7 +4647,7 @@ void gtk_imhtml_insert_image_at_iter(GtkIMHtml *imhtml, int id, GtkTextIter *iter) { - GdkPixbuf *pixbuf = NULL; + GdkPixbufAnimation *anim = NULL; const char *filename = NULL; gpointer image; GdkRectangle rect; @@ -4544,28 +4674,33 @@ GdkPixbufLoader *loader = gdk_pixbuf_loader_new(); gdk_pixbuf_loader_write(loader, data, len, NULL); gdk_pixbuf_loader_close(loader, NULL); - pixbuf = gdk_pixbuf_loader_get_pixbuf(loader); - if (pixbuf) - g_object_ref(G_OBJECT(pixbuf)); + anim = gdk_pixbuf_loader_get_animation(loader); + if (anim) + g_object_ref(G_OBJECT(anim)); g_object_unref(G_OBJECT(loader)); } } - if (pixbuf) { + if (anim) { struct im_image_data *t = g_new(struct im_image_data, 1); filename = imhtml->funcs->image_get_filename(image); imhtml->funcs->image_ref(id); t->id = id; t->mark = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, iter, TRUE); imhtml->im_images = g_slist_prepend(imhtml->im_images, t); + scalable = gtk_imhtml_animation_new(anim, filename, id); + g_object_unref(G_OBJECT(anim)); } else { + GdkPixbuf *pixbuf; pixbuf = gtk_widget_render_icon(GTK_WIDGET(imhtml), GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_BUTTON, "gtkimhtml-missing-image"); + scalable = gtk_imhtml_image_new(pixbuf, filename, id); + g_object_unref(G_OBJECT(pixbuf)); } sd = g_new(struct scalable_data, 1); - sd->scalable = scalable = gtk_imhtml_image_new(pixbuf, filename, id); + sd->scalable = scalable; sd->mark = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, iter, TRUE); gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); scalable->add_to(scalable, imhtml, iter); @@ -4573,8 +4708,6 @@ gtk_text_view_get_right_margin(GTK_TEXT_VIEW(imhtml)); scalable->scale(scalable, rect.width - minus, rect.height); imhtml->scalables = g_list_append(imhtml->scalables, sd); - - g_object_unref(G_OBJECT(pixbuf)); } static const gchar *tag_to_html_start(GtkTextTag *tag) @@ -4966,3 +5099,4 @@ } } +
--- a/pidgin/gtkimhtml.h Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/gtkimhtml.h Sat Jun 16 20:16:36 2007 +0000 @@ -27,6 +27,7 @@ #include <gtk/gtktextview.h> #include <gtk/gtktooltips.h> #include <gtk/gtkimage.h> +#include "gtksourceundomanager.h" #include "connection.h" @@ -45,6 +46,7 @@ #define GTK_IS_IMHTML(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_IMHTML)) #define GTK_IS_IMHTML_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_IMHTML)) #define GTK_IMHTML_SCALABLE(obj) ((GtkIMHtmlScalable *)obj) +#define GTK_IMHTML_ANIMATION(obj) ((GtkIMHtmlAnimation *)obj) typedef struct _GtkIMHtml GtkIMHtml; typedef struct _GtkIMHtmlClass GtkIMHtmlClass; @@ -53,6 +55,7 @@ typedef struct _GtkIMHtmlSmiley GtkIMHtmlSmiley; typedef struct _GtkIMHtmlScalable GtkIMHtmlScalable; typedef struct _GtkIMHtmlImage GtkIMHtmlImage; +typedef struct _GtkIMHtmlAnimation GtkIMHtmlAnimation; typedef struct _GtkIMHtmlHr GtkIMHtmlHr; typedef struct _GtkIMHtmlFuncs GtkIMHtmlFuncs; @@ -128,6 +131,7 @@ GSList *im_images; GtkIMHtmlFuncs *funcs; + GtkSourceUndoManager *undo_manager; }; struct _GtkIMHtmlClass { @@ -139,6 +143,8 @@ void (*clear_format)(GtkIMHtml *); void (*update_format)(GtkIMHtml *); gboolean (*message_send)(GtkIMHtml *); + void (*undo)(GtkIMHtml *); + void (*redo)(GtkIMHtml *); }; struct _GtkIMHtmlFontDetail { @@ -177,8 +183,8 @@ struct _GtkIMHtmlImage { GtkIMHtmlScalable scalable; - GtkImage *image; - GdkPixbuf *pixbuf; + GtkImage *image; /**< Contains the scaled version of this pixbuf. */ + GdkPixbuf *pixbuf; /**< The original pixbuf, before any scaling. */ GtkTextMark *mark; gchar *filename; int width; @@ -187,6 +193,13 @@ GtkWidget *filesel; }; +struct _GtkIMHtmlAnimation { + GtkIMHtmlImage imhtmlimage; + GdkPixbufAnimation *anim; /**< The original animation, before any scaling. */ + GdkPixbufAnimationIter *iter; + guint timer; +}; + struct _GtkIMHtmlHr { GtkIMHtmlScalable scalable; GtkWidget *sep; @@ -407,7 +420,7 @@ GtkIMHtmlScalable *gtk_imhtml_scalable_new(void); /** - * Creates and returns an new GTK+ IM/HTML scalable object with an image. + * Creates and returns a new GTK+ IM/HTML scalable object with an image. * * @param img A GdkPixbuf of the image to add. * @param filename The filename to associate with the image. @@ -418,19 +431,47 @@ GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename, int id); /** + * Creates and returns a new GTK+ IM/HTML scalable object with an + * animated image. + * + * @param img A GdkPixbufAnimation of the image to add. + * @param filename The filename to associate with the image. + * @param id The id to associate with the image. + * + * @return A new IM/HTML Scalable object with an image. + */ +/* + * TODO: All this animation code could be combined much better with + * the image code. It couldn't be done when it was written + * because it requires breaking backward compatibility. It + * would be good to do it for 3.0.0. + */ +GtkIMHtmlScalable *gtk_imhtml_animation_new(GdkPixbufAnimation *img, const gchar *filename, int id); + +/** * Destroys and frees a GTK+ IM/HTML scalable image. * * @param scale The GTK+ IM/HTML scalable. */ +/* TODO: Is there any reason this isn't private? */ void gtk_imhtml_image_free(GtkIMHtmlScalable *scale); /** + * Destroys and frees a GTK+ IM/HTML scalable animation. + * + * @param scale The GTK+ IM/HTML scalable. + */ +/* TODO: Is there any reason this isn't private? */ +void gtk_imhtml_animation_free(GtkIMHtmlScalable *scale); + +/** * Rescales a GTK+ IM/HTML scalable image to a given size. * * @param scale The GTK+ IM/HTML scalable. * @param width The new width. * @param height The new height. */ +/* TODO: Is there any reason this isn't private? */ void gtk_imhtml_image_scale(GtkIMHtmlScalable *scale, int width, int height); /** @@ -440,6 +481,7 @@ * @param imhtml The GTK+ IM/HTML. * @param iter The GtkTextIter at which to add the scalable. */ +/* TODO: Is there any reason this isn't private? */ void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter); /**
--- a/pidgin/gtkimhtmltoolbar.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/gtkimhtmltoolbar.c Sat Jun 16 20:16:36 2007 +0000 @@ -792,7 +792,8 @@ g_object_unref(object); } -static void update_buttons(GtkIMHtmlToolbar *toolbar) { +static void update_buttons(GtkIMHtmlToolbar *toolbar) +{ gboolean bold, italic, underline; char *tmp; char *tmp2; @@ -862,51 +863,53 @@ int *x, int *y, gboolean *push_in, - gpointer data) + gpointer data) { - GtkRequisition menu_req; - GtkTextDirection direction; - GdkRectangle monitor; - gint monitor_num; - GdkScreen *screen; - GtkWidget *widget = data; + GtkRequisition menu_req; + GtkTextDirection direction; + GdkRectangle monitor; + gint monitor_num; + GdkScreen *screen; + GtkWidget *widget = GTK_WIDGET(data); - gtk_widget_size_request (GTK_WIDGET (widget), &menu_req); + gtk_widget_size_request (GTK_WIDGET (menu), &menu_req); - direction = gtk_widget_get_direction (widget); + direction = gtk_widget_get_direction (widget); - screen = gtk_widget_get_screen (GTK_WIDGET (menu)); - monitor_num = gdk_screen_get_monitor_at_window (screen, widget->window); - if (monitor_num < 0) - monitor_num = 0; - gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor); + screen = gtk_widget_get_screen (GTK_WIDGET (menu)); + monitor_num = gdk_screen_get_monitor_at_window (screen, widget->window); + if (monitor_num < 0) + monitor_num = 0; + gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor); - gdk_window_get_origin (widget->window, x, y); - *x += widget->allocation.x; - *y += widget->allocation.y; + gdk_window_get_origin (widget->window, x, y); + *x += widget->allocation.x; + *y += widget->allocation.y; - if (direction == GTK_TEXT_DIR_LTR) - *x += MAX (widget->allocation.width - menu_req.width, 0); - else if (menu_req.width > widget->allocation.width) - *x -= menu_req.width - widget->allocation.width; + if (direction == GTK_TEXT_DIR_LTR) + *x += MAX (widget->allocation.width - menu_req.width, 0); + else if (menu_req.width > widget->allocation.width) + *x -= menu_req.width - widget->allocation.width; - if ((*y + widget->allocation.height + menu_req.height) <= monitor.y + monitor.height) - *y += widget->allocation.height; - else if ((*y - menu_req.height) >= monitor.y) - *y -= menu_req.height; - else if (monitor.y + monitor.height - (*y + widget->allocation.height) > *y) - *y += widget->allocation.height; - else - *y -= menu_req.height; - *push_in = FALSE; + if ((*y + widget->allocation.height + menu_req.height) <= monitor.y + monitor.height) + *y += widget->allocation.height; + else if ((*y - menu_req.height) >= monitor.y) + *y -= menu_req.height; + else if (monitor.y + monitor.height - (*y + widget->allocation.height) > *y) + *y += widget->allocation.height; + else + *y -= menu_req.height; + *push_in = FALSE; } -static void pidgin_menu_clicked(GtkWidget *button, GtkMenu *menu) { +static void pidgin_menu_clicked(GtkWidget *button, GtkMenu *menu) +{ gtk_widget_show_all(GTK_WIDGET(menu)); gtk_menu_popup(menu, NULL, NULL, menu_position_func, button, 0, gtk_get_current_event_time()); } -static void pidgin_menu_deactivate(GtkWidget *menu, GtkToggleButton *button) { +static void pidgin_menu_deactivate(GtkWidget *menu, GtkToggleButton *button) +{ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE); } @@ -1026,8 +1029,20 @@ g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(insert_smiley_cb), toolbar); toolbar->smiley = button; +} +static void +button_sensitiveness_changed(GtkWidget *button, gpointer dontcare, GtkWidget *item) +{ + gtk_widget_set_sensitive(item, GTK_WIDGET_IS_SENSITIVE(button)); +} +static void +update_menuitem(GtkToggleButton *button, GtkCheckMenuItem *item) +{ + g_signal_handlers_block_by_func(G_OBJECT(item), G_CALLBACK(gtk_button_clicked), button); + gtk_check_menu_item_set_active(item, gtk_toggle_button_get_active(button)); + g_signal_handlers_unblock_by_func(G_OBJECT(item), G_CALLBACK(gtk_button_clicked), button); } static void gtk_imhtmltoolbar_init (GtkIMHtmlToolbar *toolbar) @@ -1042,6 +1057,25 @@ GtkWidget *insert_menu; GtkWidget *button; GtkWidget *sep; + int i; + struct { + const char *label; + GtkWidget **button; + } buttons[] = { + {_("_Bold"), &toolbar->bold}, + {_("_Italic"), &toolbar->italic}, + {_("_Underline"), &toolbar->underline}, + {_("_Larger"), &toolbar->larger_size}, +#if 0 + {_("_Normal"), &toolbar->normal_size}, +#endif + {_("_Smaller"), &toolbar->smaller_size}, + {_("_Font face"), &toolbar->font}, + {_("_Foreground color"), &toolbar->fgcolor}, + {_("_Background color"), &toolbar->bgcolor}, + {NULL, NULL} + }; + toolbar->imhtml = NULL; toolbar->font_dialog = NULL; @@ -1057,7 +1091,7 @@ gtk_imhtmltoolbar_create_old_buttons(toolbar); - /* Bold */ + /* Fonts */ font_button = gtk_toggle_button_new(); gtk_button_set_relief(GTK_BUTTON(font_button), GTK_RELIEF_NONE); bbox = gtk_hbox_new(FALSE, 3); @@ -1071,44 +1105,21 @@ font_menu = gtk_menu_new(); - button = gtk_check_menu_item_new_with_mnemonic(_("_Bold")); - g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gtk_button_clicked), toolbar->bold); - gtk_menu_shell_append(GTK_MENU_SHELL(font_menu), button); - - button = gtk_check_menu_item_new_with_mnemonic(_("_Italic")); - g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gtk_button_clicked), toolbar->italic); - gtk_menu_shell_append(GTK_MENU_SHELL(font_menu), button); - - button = gtk_check_menu_item_new_with_mnemonic(_("_Underline")); - g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gtk_button_clicked), toolbar->underline); - gtk_menu_shell_append(GTK_MENU_SHELL(font_menu), button); - - button = gtk_menu_item_new_with_mnemonic(_("_Larger")); - g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gtk_button_clicked), toolbar->larger_size); - gtk_menu_shell_append(GTK_MENU_SHELL(font_menu), button); - - button = gtk_menu_item_new_with_mnemonic(_("_Normal")); - g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gtk_button_clicked), toolbar->normal_size); - gtk_menu_shell_append(GTK_MENU_SHELL(font_menu), button); - - button = gtk_menu_item_new_with_mnemonic(_("_Smaller")); - g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gtk_button_clicked), toolbar->smaller_size); - gtk_menu_shell_append(GTK_MENU_SHELL(font_menu), button); - - button = gtk_menu_item_new_with_mnemonic(_("_Font face")); - g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gtk_button_clicked), toolbar->font); - gtk_menu_shell_append(GTK_MENU_SHELL(font_menu), button); - - button = gtk_menu_item_new_with_mnemonic(_("_Foreground color")); - g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gtk_button_clicked), toolbar->fgcolor); - gtk_menu_shell_append(GTK_MENU_SHELL(font_menu), button); - - button = gtk_menu_item_new_with_mnemonic(_("_Background color")); - g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gtk_button_clicked), toolbar->bgcolor); - gtk_menu_shell_append(GTK_MENU_SHELL(font_menu), button); - + + for (i = 0; buttons[i].label; i++) { + GtkWidget *old = *buttons[i].button; + GtkWidget *menuitem = gtk_check_menu_item_new_with_mnemonic(buttons[i].label); + g_signal_connect_swapped(G_OBJECT(menuitem), "activate", + G_CALLBACK(gtk_button_clicked), old); + g_signal_connect_after(G_OBJECT(old), "toggled", + G_CALLBACK(update_menuitem), menuitem); + gtk_menu_shell_append(GTK_MENU_SHELL(font_menu), menuitem); + g_signal_connect(G_OBJECT(old), "notify::sensitive", + G_CALLBACK(button_sensitiveness_changed), menuitem); + } + g_signal_connect(G_OBJECT(font_button), "clicked", G_CALLBACK(pidgin_menu_clicked), font_menu); - g_signal_connect(G_OBJECT(font_menu), "deactivate", G_CALLBACK(pidgin_menu_deactivate), font_button); + g_signal_connect(G_OBJECT(font_menu), "deactivate", G_CALLBACK(pidgin_menu_deactivate), font_button); /* Sep */ sep = gtk_vseparator_new(); @@ -1135,7 +1146,7 @@ gtk_box_pack_start(GTK_BOX(hbox), sep, FALSE, FALSE, 0); gtk_widget_show_all(sep); - /* Insert Link */ + /* Insert */ insert_button = gtk_toggle_button_new(); gtk_button_set_relief(GTK_BUTTON(insert_button), GTK_RELIEF_NONE); bbox = gtk_hbox_new(FALSE, 3);
--- a/pidgin/gtklog.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/gtklog.c Sat Jun 16 20:16:36 2007 +0000 @@ -757,7 +757,7 @@ void pidgin_syslog_show() { - GList *accounts = NULL; + const GList *accounts; GList *logs = NULL; if (syslog_viewer != NULL) {
--- a/pidgin/gtkmain.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/gtkmain.c Sat Jun 16 20:16:36 2007 +0000 @@ -125,7 +125,7 @@ } g_strfreev(names); } else { /* no name given, use the first account */ - GList *accounts; + const GList *accounts; accounts = purple_accounts_get_all(); if (accounts != NULL) @@ -435,7 +435,7 @@ char *opt_login_arg = NULL; char *opt_session_arg = NULL; char *search_path; - GList *accounts; + const GList *accounts; #ifdef HAVE_SIGNAL_H int sig_indx; /* for setting up signal catching */ sigset_t sigset; @@ -450,6 +450,7 @@ gboolean gui_check; gboolean debug_enabled; gboolean migration_failed = FALSE; + GList *active_accounts; struct option long_options[] = { {"config", required_argument, NULL, 'c'}, @@ -727,6 +728,15 @@ abort(); } + if (!purple_core_ensure_single_instance()) { + purple_core_quit(); +#ifdef HAVE_SIGNAL_H + g_free(segfault_message); +#endif + return 0; + } + + /* TODO: Move blist loading into purple_blist_init() */ purple_set_blist(purple_blist_new()); purple_blist_load(); @@ -822,13 +832,13 @@ purple_accounts_restore_current_statuses(); } - if ((accounts = purple_accounts_get_all_active()) == NULL) + if ((active_accounts = purple_accounts_get_all_active()) == NULL) { pidgin_accounts_window_show(); } else { - g_list_free(accounts); + g_list_free(active_accounts); } #ifdef HAVE_STARTUP_NOTIFICATION
--- a/pidgin/gtknotify.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/gtknotify.c Sat Jun 16 20:16:36 2007 +0000 @@ -583,10 +583,8 @@ char label_text[2048]; char *linked_text, *primary_esc, *secondary_esc; - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(window), title); + window = pidgin_create_window(title, PIDGIN_HIG_BORDER, NULL, TRUE); gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG); - gtk_container_set_border_width(GTK_CONTAINER(window), PIDGIN_HIG_BORDER); g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(formatted_close_cb), NULL); @@ -718,10 +716,8 @@ data->results = results; /* Create the window */ - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(window), (title ? title :_("Search Results"))); + window = pidgin_create_window(title ? title :_("Search Results"), PIDGIN_HIG_BORDER, NULL, TRUE); gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG); - gtk_container_set_border_width(GTK_CONTAINER(window), PIDGIN_HIG_BORDER); g_signal_connect_swapped(G_OBJECT(window), "delete_event", G_CALLBACK(searchresults_close_cb), data);
--- a/pidgin/gtkpounce.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/gtkpounce.c Sat Jun 16 20:16:36 2007 +0000 @@ -496,7 +496,7 @@ } else { - GList *connections = purple_connections_get_all(); + const GList *connections = purple_connections_get_all(); PurpleConnection *gc; if (connections != NULL) @@ -513,15 +513,9 @@ sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); /* Create the window. */ - dialog->window = window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + dialog->window = window = pidgin_create_window((cur_pounce == NULL ? _("New Buddy Pounce") : _("Edit Buddy Pounce")), + PIDGIN_HIG_BORDER, "buddy_pounce", FALSE) ; gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG); - gtk_window_set_role(GTK_WINDOW(window), "buddy_pounce"); - gtk_window_set_resizable(GTK_WINDOW(window), FALSE); - gtk_window_set_title(GTK_WINDOW(window), - (cur_pounce == NULL - ? _("New Buddy Pounce") : _("Edit Buddy Pounce"))); - - gtk_container_set_border_width(GTK_CONTAINER(window), PIDGIN_HIG_BORDER); g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(delete_win_cb), dialog); @@ -1342,11 +1336,8 @@ width = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/pounces/dialog/width"); height = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/pounces/dialog/height"); - dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); + dialog->window = win = pidgin_create_window(_("Buddy Pounces"), PIDGIN_HIG_BORDER, "pounces", TRUE); gtk_window_set_default_size(GTK_WINDOW(win), width, height); - gtk_window_set_role(GTK_WINDOW(win), "pounces"); - gtk_window_set_title(GTK_WINDOW(win), _("Buddy Pounces")); - gtk_container_set_border_width(GTK_CONTAINER(win), PIDGIN_HIG_BORDER); g_signal_connect(G_OBJECT(win), "delete_event", G_CALLBACK(pounces_manager_destroy_cb), dialog);
--- a/pidgin/gtkprefs.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/gtkprefs.c Sat Jun 16 20:16:36 2007 +0000 @@ -949,7 +949,7 @@ label = gtk_label_new_with_mnemonic(_("Conversation _font:")); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); font_name = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/custom_font"); - font_button = gtk_font_button_new_with_font(purple_prefs_get_string(font_name ? font_name : NULL)); + font_button = gtk_font_button_new_with_font(font_name ? font_name : NULL); gtk_font_button_set_show_style(GTK_FONT_BUTTON(font_button), TRUE); gtk_box_pack_start(GTK_BOX(hbox), font_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); @@ -977,7 +977,7 @@ gtk_imhtml_append_text(GTK_IMHTML(imhtml), _("This is how your outgoing message text will appear when you use protocols that support formatting. :)"), 0); - gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); gtk_imhtml_setup_entry(GTK_IMHTML(imhtml), PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_FORMATTING_WBFO); @@ -1977,11 +1977,7 @@ /* Back to instant-apply! I win! BU-HAHAHA! */ /* Create the window */ - prefs = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_role(GTK_WINDOW(prefs), "preferences"); - gtk_window_set_title(GTK_WINDOW(prefs), _("Preferences")); - gtk_window_set_resizable (GTK_WINDOW(prefs), FALSE); - gtk_container_set_border_width(GTK_CONTAINER(prefs), PIDGIN_HIG_BORDER); + prefs = pidgin_create_window(_("Preferences"), PIDGIN_HIG_BORDER, "preferences", FALSE); g_signal_connect(G_OBJECT(prefs), "destroy", G_CALLBACK(delete_prefs), NULL);
--- a/pidgin/gtkprivacy.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/gtkprivacy.c Sat Jun 16 20:16:36 2007 +0000 @@ -366,11 +366,7 @@ dialog = g_new0(PidginPrivacyDialog, 1); - dialog->win = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_resizable(GTK_WINDOW(dialog->win), FALSE); - gtk_window_set_role(GTK_WINDOW(dialog->win), "privacy"); - gtk_window_set_title(GTK_WINDOW(dialog->win), _("Privacy")); - gtk_container_set_border_width(GTK_CONTAINER(dialog->win), PIDGIN_HIG_BORDER); + dialog->win = pidgin_create_window(_("Privacy"), PIDGIN_HIG_BORDER, "privacy", FALSE); g_signal_connect(G_OBJECT(dialog->win), "delete_event", G_CALLBACK(destroy_cb), dialog);
--- a/pidgin/gtkrequest.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/gtkrequest.c Sat Jun 16 20:16:36 2007 +0000 @@ -1070,16 +1070,12 @@ data->cbs[0] = ok_cb; data->cbs[1] = cancel_cb; - data->dialog = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); - - if (title != NULL) - gtk_window_set_title(GTK_WINDOW(win), title); + #ifdef _WIN32 - gtk_window_set_title(GTK_WINDOW(win), PIDGIN_ALERT_TITLE); -#endif - - gtk_window_set_role(GTK_WINDOW(win), "multifield"); - gtk_container_set_border_width(GTK_CONTAINER(win), PIDGIN_HIG_BORDER); + data->dialog = win = pidgin_create_window(PIDGIN_ALERT_TITLE, PIDGIN_HIG_BORDER, "multifield", TRUE) ; +#else /* !_WIN32 */ + data->dialog = win = pidgin_create_window(title, PIDGIN_HIG_BORDER, "multifield", TRUE) ; +#endif /* _WIN32 */ g_signal_connect(G_OBJECT(win), "delete_event", G_CALLBACK(destroy_multifield_cb), data);
--- a/pidgin/gtkroomlist.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/gtkroomlist.c Sat Jun 16 20:16:36 2007 +0000 @@ -343,7 +343,7 @@ gboolean pidgin_roomlist_is_showable() { - GList *c; + const GList *c; PurpleConnection *gc; for (c = purple_connections_get_all(); c != NULL; c = c->next) { @@ -371,11 +371,7 @@ dialog->account = account; /* Create the window. */ - dialog->window = window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_role(GTK_WINDOW(window), "room list"); - gtk_window_set_title(GTK_WINDOW(window), _("Room List")); - - gtk_container_set_border_width(GTK_CONTAINER(window), PIDGIN_HIG_BORDER); + dialog->window = window = pidgin_create_window(_("Room List"), PIDGIN_HIG_BORDER, "room list", TRUE); g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(delete_win_cb), dialog);
--- a/pidgin/gtksavedstatuses.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/gtksavedstatuses.c Sat Jun 16 20:16:36 2007 +0000 @@ -551,11 +551,8 @@ width = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/status/dialog/width"); height = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/status/dialog/height"); - dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); + dialog->window = win = pidgin_create_window(_("Saved Statuses"), PIDGIN_HIG_BORDER, "statuses", TRUE); gtk_window_set_default_size(GTK_WINDOW(win), width, height); - gtk_window_set_role(GTK_WINDOW(win), "statuses"); - gtk_window_set_title(GTK_WINDOW(win), _("Saved Statuses")); - gtk_container_set_border_width(GTK_CONTAINER(win), PIDGIN_HIG_BORDER); g_signal_connect(G_OBJECT(win), "delete_event", G_CALLBACK(status_window_destroy_cb), dialog); @@ -1015,7 +1012,7 @@ static void status_editor_populate_list(StatusEditor *dialog, PurpleSavedStatus *saved_status) { - GList *iter; + const GList *iter; PurpleSavedStatusSub *substatus; gtk_list_store_clear(dialog->model); @@ -1085,10 +1082,7 @@ if (edit) dialog->original_title = g_strdup(purple_savedstatus_get_title(saved_status)); - dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_role(GTK_WINDOW(win), "status"); - gtk_window_set_title(GTK_WINDOW(win), _("Status")); - gtk_container_set_border_width(GTK_CONTAINER(win), PIDGIN_HIG_BORDER); + dialog->window = win = pidgin_create_window (_("Status"), PIDGIN_HIG_BORDER, "status", FALSE) ; g_signal_connect(G_OBJECT(win), "delete_event", G_CALLBACK(status_editor_destroy_cb), dialog); @@ -1422,13 +1416,9 @@ dialog->status_editor = status_editor; dialog->account = account; - dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_role(GTK_WINDOW(win), "substatus"); tmp = g_strdup_printf(_("Status for %s"), purple_account_get_username(account)); - gtk_window_set_title(GTK_WINDOW(win), tmp); + dialog->window = win = pidgin_create_window(tmp, PIDGIN_HIG_BORDER, "substatus", FALSE) ; g_free(tmp); - gtk_window_set_resizable(GTK_WINDOW(win), FALSE); - gtk_container_set_border_width(GTK_CONTAINER(win), PIDGIN_HIG_BORDER); g_signal_connect(G_OBJECT(win), "delete_event", G_CALLBACK(substatus_editor_destroy_cb), dialog);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/gtksourceundomanager.c Sat Jun 16 20:16:36 2007 +0000 @@ -0,0 +1,1123 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * gtksourceundomanager.c + * This file is part of GtkSourceView + * + * Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence + * Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi + * Copyright (C) 2002-2005 Paolo Maggi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <glib.h> +#include <stdlib.h> +#include <string.h> + +#include "gtksourceundomanager.h" +#include "gtksourceview-marshal.h" + + +#define DEFAULT_MAX_UNDO_LEVELS 25 + + +typedef struct _GtkSourceUndoAction GtkSourceUndoAction; +typedef struct _GtkSourceUndoInsertAction GtkSourceUndoInsertAction; +typedef struct _GtkSourceUndoDeleteAction GtkSourceUndoDeleteAction; + +typedef enum { + GTK_SOURCE_UNDO_ACTION_INSERT, + GTK_SOURCE_UNDO_ACTION_DELETE +} GtkSourceUndoActionType; + +/* + * We use offsets instead of GtkTextIters because the last ones + * require to much memory in this context without giving us any advantage. + */ + +struct _GtkSourceUndoInsertAction +{ + gint pos; + gchar *text; + gint length; + gint chars; +}; + +struct _GtkSourceUndoDeleteAction +{ + gint start; + gint end; + gchar *text; + gboolean forward; +}; + +struct _GtkSourceUndoAction +{ + GtkSourceUndoActionType action_type; + + union { + GtkSourceUndoInsertAction insert; + GtkSourceUndoDeleteAction delete; + } action; + + gint order_in_group; + + /* It is TRUE whether the action can be merged with the following action. */ + guint mergeable : 1; + + /* It is TRUE whether the action is marked as "modified". + * An action is marked as "modified" if it changed the + * state of the buffer from "not modified" to "modified". Only the first + * action of a group can be marked as modified. + * There can be a single action marked as "modified" in the actions list. + */ + guint modified : 1; +}; + +/* INVALID is a pointer to an invalid action */ +#define INVALID ((void *) "IA") + +struct _GtkSourceUndoManagerPrivate +{ + GtkTextBuffer *document; + + GList* actions; + gint next_redo; + + gint actions_in_current_group; + + gint running_not_undoable_actions; + + gint num_of_groups; + + gint max_undo_levels; + + guint can_undo : 1; + guint can_redo : 1; + + /* It is TRUE whether, while undoing an action of the current group (with order_in_group > 1), + * the state of the buffer changed from "not modified" to "modified". + */ + guint modified_undoing_group : 1; + + /* Pointer to the action (in the action list) marked as "modified". + * It is NULL when no action is marked as "modified". + * It is INVALID when the action marked as "modified" has been removed + * from the action list (freeing the list or resizing it) */ + GtkSourceUndoAction *modified_action; +}; + +enum { + CAN_UNDO, + CAN_REDO, + LAST_SIGNAL +}; + +static void gtk_source_undo_manager_class_init (GtkSourceUndoManagerClass *klass); +static void gtk_source_undo_manager_init (GtkSourceUndoManager *um); +static void gtk_source_undo_manager_finalize (GObject *object); + +static void gtk_source_undo_manager_insert_text_handler (GtkTextBuffer *buffer, + GtkTextIter *pos, + const gchar *text, + gint length, + GtkSourceUndoManager *um); +static void gtk_source_undo_manager_delete_range_handler (GtkTextBuffer *buffer, + GtkTextIter *start, + GtkTextIter *end, + GtkSourceUndoManager *um); +static void gtk_source_undo_manager_begin_user_action_handler (GtkTextBuffer *buffer, + GtkSourceUndoManager *um); +static void gtk_source_undo_manager_modified_changed_handler (GtkTextBuffer *buffer, + GtkSourceUndoManager *um); + +static void gtk_source_undo_manager_free_action_list (GtkSourceUndoManager *um); + +static void gtk_source_undo_manager_add_action (GtkSourceUndoManager *um, + const GtkSourceUndoAction *undo_action); +static void gtk_source_undo_manager_free_first_n_actions (GtkSourceUndoManager *um, + gint n); +static void gtk_source_undo_manager_check_list_size (GtkSourceUndoManager *um); + +static gboolean gtk_source_undo_manager_merge_action (GtkSourceUndoManager *um, + const GtkSourceUndoAction *undo_action); + +static GObjectClass *parent_class = NULL; +static guint undo_manager_signals [LAST_SIGNAL] = { 0 }; + +GType +gtk_source_undo_manager_get_type (void) +{ + static GType undo_manager_type = 0; + + if (undo_manager_type == 0) + { + static const GTypeInfo our_info = + { + sizeof (GtkSourceUndoManagerClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gtk_source_undo_manager_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GtkSourceUndoManager), + 0, /* n_preallocs */ + (GInstanceInitFunc) gtk_source_undo_manager_init, + NULL /* value_table */ + }; + + undo_manager_type = g_type_register_static (G_TYPE_OBJECT, + "GtkSourceUndoManager", + &our_info, + 0); + } + + return undo_manager_type; +} + +static void +gtk_source_undo_manager_class_init (GtkSourceUndoManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = gtk_source_undo_manager_finalize; + + klass->can_undo = NULL; + klass->can_redo = NULL; + + undo_manager_signals[CAN_UNDO] = + g_signal_new ("can_undo", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkSourceUndoManagerClass, can_undo), + NULL, NULL, + gtksourceview_marshal_VOID__BOOLEAN, + G_TYPE_NONE, + 1, + G_TYPE_BOOLEAN); + + undo_manager_signals[CAN_REDO] = + g_signal_new ("can_redo", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkSourceUndoManagerClass, can_redo), + NULL, NULL, + gtksourceview_marshal_VOID__BOOLEAN, + G_TYPE_NONE, + 1, + G_TYPE_BOOLEAN); +} + +static void +gtk_source_undo_manager_init (GtkSourceUndoManager *um) +{ + um->priv = g_new0 (GtkSourceUndoManagerPrivate, 1); + + um->priv->actions = NULL; + um->priv->next_redo = 0; + + um->priv->can_undo = FALSE; + um->priv->can_redo = FALSE; + + um->priv->running_not_undoable_actions = 0; + + um->priv->num_of_groups = 0; + + um->priv->max_undo_levels = DEFAULT_MAX_UNDO_LEVELS; + + um->priv->modified_action = NULL; + + um->priv->modified_undoing_group = FALSE; +} + +static void +gtk_source_undo_manager_finalize (GObject *object) +{ + GtkSourceUndoManager *um; + + g_return_if_fail (object != NULL); + g_return_if_fail (GTK_SOURCE_IS_UNDO_MANAGER (object)); + + um = GTK_SOURCE_UNDO_MANAGER (object); + + g_return_if_fail (um->priv != NULL); + + if (um->priv->actions != NULL) + { + gtk_source_undo_manager_free_action_list (um); + } + + g_signal_handlers_disconnect_by_func (G_OBJECT (um->priv->document), + G_CALLBACK (gtk_source_undo_manager_delete_range_handler), + um); + + g_signal_handlers_disconnect_by_func (G_OBJECT (um->priv->document), + G_CALLBACK (gtk_source_undo_manager_insert_text_handler), + um); + + g_signal_handlers_disconnect_by_func (G_OBJECT (um->priv->document), + G_CALLBACK (gtk_source_undo_manager_begin_user_action_handler), + um); + + g_free (um->priv); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +GtkSourceUndoManager* +gtk_source_undo_manager_new (GtkTextBuffer* buffer) +{ + GtkSourceUndoManager *um; + + um = GTK_SOURCE_UNDO_MANAGER (g_object_new (GTK_SOURCE_TYPE_UNDO_MANAGER, NULL)); + + g_return_val_if_fail (um->priv != NULL, NULL); + um->priv->document = buffer; + + g_signal_connect (G_OBJECT (buffer), "insert_text", + G_CALLBACK (gtk_source_undo_manager_insert_text_handler), + um); + + g_signal_connect (G_OBJECT (buffer), "delete_range", + G_CALLBACK (gtk_source_undo_manager_delete_range_handler), + um); + + g_signal_connect (G_OBJECT (buffer), "begin_user_action", + G_CALLBACK (gtk_source_undo_manager_begin_user_action_handler), + um); + + g_signal_connect (G_OBJECT (buffer), "modified_changed", + G_CALLBACK (gtk_source_undo_manager_modified_changed_handler), + um); + return um; +} + +void +gtk_source_undo_manager_begin_not_undoable_action (GtkSourceUndoManager *um) +{ + g_return_if_fail (GTK_SOURCE_IS_UNDO_MANAGER (um)); + g_return_if_fail (um->priv != NULL); + + ++um->priv->running_not_undoable_actions; +} + +static void +gtk_source_undo_manager_end_not_undoable_action_internal (GtkSourceUndoManager *um) +{ + g_return_if_fail (GTK_SOURCE_IS_UNDO_MANAGER (um)); + g_return_if_fail (um->priv != NULL); + + g_return_if_fail (um->priv->running_not_undoable_actions > 0); + + --um->priv->running_not_undoable_actions; +} + +void +gtk_source_undo_manager_end_not_undoable_action (GtkSourceUndoManager *um) +{ + g_return_if_fail (GTK_SOURCE_IS_UNDO_MANAGER (um)); + g_return_if_fail (um->priv != NULL); + + gtk_source_undo_manager_end_not_undoable_action_internal (um); + + if (um->priv->running_not_undoable_actions == 0) + { + gtk_source_undo_manager_free_action_list (um); + + um->priv->next_redo = -1; + + if (um->priv->can_undo) + { + um->priv->can_undo = FALSE; + g_signal_emit (G_OBJECT (um), + undo_manager_signals [CAN_UNDO], + 0, + FALSE); + } + + if (um->priv->can_redo) + { + um->priv->can_redo = FALSE; + g_signal_emit (G_OBJECT (um), + undo_manager_signals [CAN_REDO], + 0, + FALSE); + } + } +} + +gboolean +gtk_source_undo_manager_can_undo (const GtkSourceUndoManager *um) +{ + g_return_val_if_fail (GTK_SOURCE_IS_UNDO_MANAGER (um), FALSE); + g_return_val_if_fail (um->priv != NULL, FALSE); + + return um->priv->can_undo; +} + +gboolean +gtk_source_undo_manager_can_redo (const GtkSourceUndoManager *um) +{ + g_return_val_if_fail (GTK_SOURCE_IS_UNDO_MANAGER (um), FALSE); + g_return_val_if_fail (um->priv != NULL, FALSE); + + return um->priv->can_redo; +} + +static void +set_cursor (GtkTextBuffer *buffer, gint cursor) +{ + GtkTextIter iter; + + /* Place the cursor at the requested position */ + gtk_text_buffer_get_iter_at_offset (buffer, &iter, cursor); + gtk_text_buffer_place_cursor (buffer, &iter); +} + +static void +insert_text (GtkTextBuffer *buffer, gint pos, const gchar *text, gint len) +{ + GtkTextIter iter; + + gtk_text_buffer_get_iter_at_offset (buffer, &iter, pos); + gtk_text_buffer_insert (buffer, &iter, text, len); +} + +static void +delete_text (GtkTextBuffer *buffer, gint start, gint end) +{ + GtkTextIter start_iter; + GtkTextIter end_iter; + + gtk_text_buffer_get_iter_at_offset (buffer, &start_iter, start); + + if (end < 0) + gtk_text_buffer_get_end_iter (buffer, &end_iter); + else + gtk_text_buffer_get_iter_at_offset (buffer, &end_iter, end); + + gtk_text_buffer_delete (buffer, &start_iter, &end_iter); +} + +static gchar* +get_chars (GtkTextBuffer *buffer, gint start, gint end) +{ + GtkTextIter start_iter; + GtkTextIter end_iter; + + gtk_text_buffer_get_iter_at_offset (buffer, &start_iter, start); + + if (end < 0) + gtk_text_buffer_get_end_iter (buffer, &end_iter); + else + gtk_text_buffer_get_iter_at_offset (buffer, &end_iter, end); + + return gtk_text_buffer_get_slice (buffer, &start_iter, &end_iter, TRUE); +} + +void +gtk_source_undo_manager_undo (GtkSourceUndoManager *um) +{ + GtkSourceUndoAction *undo_action; + gboolean modified = FALSE; + + g_return_if_fail (GTK_SOURCE_IS_UNDO_MANAGER (um)); + g_return_if_fail (um->priv != NULL); + g_return_if_fail (um->priv->can_undo); + + um->priv->modified_undoing_group = FALSE; + + gtk_source_undo_manager_begin_not_undoable_action (um); + + do + { + undo_action = g_list_nth_data (um->priv->actions, um->priv->next_redo + 1); + g_return_if_fail (undo_action != NULL); + + /* undo_action->modified can be TRUE only if undo_action->order_in_group <= 1 */ + g_return_if_fail ((undo_action->order_in_group <= 1) || + ((undo_action->order_in_group > 1) && !undo_action->modified)); + + if (undo_action->order_in_group <= 1) + { + /* Set modified to TRUE only if the buffer did not change its state from + * "not modified" to "modified" undoing an action (with order_in_group > 1) + * in current group. */ + modified = (undo_action->modified && !um->priv->modified_undoing_group); + } + + switch (undo_action->action_type) + { + case GTK_SOURCE_UNDO_ACTION_DELETE: + insert_text ( + um->priv->document, + undo_action->action.delete.start, + undo_action->action.delete.text, + strlen (undo_action->action.delete.text)); + + if (undo_action->action.delete.forward) + set_cursor ( + um->priv->document, + undo_action->action.delete.start); + else + set_cursor ( + um->priv->document, + undo_action->action.delete.end); + + break; + + case GTK_SOURCE_UNDO_ACTION_INSERT: + delete_text ( + um->priv->document, + undo_action->action.insert.pos, + undo_action->action.insert.pos + + undo_action->action.insert.chars); + + set_cursor ( + um->priv->document, + undo_action->action.insert.pos); + break; + + default: + /* Unknown action type. */ + g_return_if_reached (); + } + + ++um->priv->next_redo; + + } while (undo_action->order_in_group > 1); + + if (modified) + { + --um->priv->next_redo; + gtk_text_buffer_set_modified (um->priv->document, FALSE); + ++um->priv->next_redo; + } + + gtk_source_undo_manager_end_not_undoable_action_internal (um); + + um->priv->modified_undoing_group = FALSE; + + if (!um->priv->can_redo) + { + um->priv->can_redo = TRUE; + g_signal_emit (G_OBJECT (um), + undo_manager_signals [CAN_REDO], + 0, + TRUE); + } + + if (um->priv->next_redo >= (gint)(g_list_length (um->priv->actions) - 1)) + { + um->priv->can_undo = FALSE; + g_signal_emit (G_OBJECT (um), + undo_manager_signals [CAN_UNDO], + 0, + FALSE); + } +} + +void +gtk_source_undo_manager_redo (GtkSourceUndoManager *um) +{ + GtkSourceUndoAction *undo_action; + gboolean modified = FALSE; + + g_return_if_fail (GTK_SOURCE_IS_UNDO_MANAGER (um)); + g_return_if_fail (um->priv != NULL); + g_return_if_fail (um->priv->can_redo); + + undo_action = g_list_nth_data (um->priv->actions, um->priv->next_redo); + g_return_if_fail (undo_action != NULL); + + gtk_source_undo_manager_begin_not_undoable_action (um); + + do + { + if (undo_action->modified) + { + g_return_if_fail (undo_action->order_in_group <= 1); + modified = TRUE; + } + + --um->priv->next_redo; + + switch (undo_action->action_type) + { + case GTK_SOURCE_UNDO_ACTION_DELETE: + delete_text ( + um->priv->document, + undo_action->action.delete.start, + undo_action->action.delete.end); + + set_cursor ( + um->priv->document, + undo_action->action.delete.start); + + break; + + case GTK_SOURCE_UNDO_ACTION_INSERT: + set_cursor ( + um->priv->document, + undo_action->action.insert.pos); + + insert_text ( + um->priv->document, + undo_action->action.insert.pos, + undo_action->action.insert.text, + undo_action->action.insert.length); + + break; + + default: + /* Unknown action type */ + ++um->priv->next_redo; + g_return_if_reached (); + } + + if (um->priv->next_redo < 0) + undo_action = NULL; + else + undo_action = g_list_nth_data (um->priv->actions, um->priv->next_redo); + + } while ((undo_action != NULL) && (undo_action->order_in_group > 1)); + + if (modified) + { + ++um->priv->next_redo; + gtk_text_buffer_set_modified (um->priv->document, FALSE); + --um->priv->next_redo; + } + + gtk_source_undo_manager_end_not_undoable_action_internal (um); + + if (um->priv->next_redo < 0) + { + um->priv->can_redo = FALSE; + g_signal_emit (G_OBJECT (um), undo_manager_signals [CAN_REDO], 0, FALSE); + } + + if (!um->priv->can_undo) + { + um->priv->can_undo = TRUE; + g_signal_emit (G_OBJECT (um), undo_manager_signals [CAN_UNDO], 0, TRUE); + } +} + +static void +gtk_source_undo_action_free (GtkSourceUndoAction *action) +{ + if (action == NULL) + return; + + if (action->action_type == GTK_SOURCE_UNDO_ACTION_INSERT) + g_free (action->action.insert.text); + else if (action->action_type == GTK_SOURCE_UNDO_ACTION_DELETE) + g_free (action->action.delete.text); + else + g_return_if_reached (); + + g_free (action); +} + +static void +gtk_source_undo_manager_free_action_list (GtkSourceUndoManager *um) +{ + GList *l; + + l = um->priv->actions; + + while (l != NULL) + { + GtkSourceUndoAction *action = l->data; + + if (action->order_in_group == 1) + --um->priv->num_of_groups; + + if (action->modified) + um->priv->modified_action = INVALID; + + gtk_source_undo_action_free (action); + + l = g_list_next (l); + } + + g_list_free (um->priv->actions); + um->priv->actions = NULL; +} + +static void +gtk_source_undo_manager_insert_text_handler (GtkTextBuffer *buffer, + GtkTextIter *pos, + const gchar *text, + gint length, + GtkSourceUndoManager *um) +{ + GtkSourceUndoAction undo_action; + + if (um->priv->running_not_undoable_actions > 0) + return; + + g_return_if_fail (strlen (text) >= (guint)length); + + undo_action.action_type = GTK_SOURCE_UNDO_ACTION_INSERT; + + undo_action.action.insert.pos = gtk_text_iter_get_offset (pos); + undo_action.action.insert.text = (gchar*) text; + undo_action.action.insert.length = length; + undo_action.action.insert.chars = g_utf8_strlen (text, length); + + if ((undo_action.action.insert.chars > 1) || (g_utf8_get_char (text) == '\n')) + + undo_action.mergeable = FALSE; + else + undo_action.mergeable = TRUE; + + undo_action.modified = FALSE; + + gtk_source_undo_manager_add_action (um, &undo_action); +} + +static void +gtk_source_undo_manager_delete_range_handler (GtkTextBuffer *buffer, + GtkTextIter *start, + GtkTextIter *end, + GtkSourceUndoManager *um) +{ + GtkSourceUndoAction undo_action; + GtkTextIter insert_iter; + + if (um->priv->running_not_undoable_actions > 0) + return; + + undo_action.action_type = GTK_SOURCE_UNDO_ACTION_DELETE; + + gtk_text_iter_order (start, end); + + undo_action.action.delete.start = gtk_text_iter_get_offset (start); + undo_action.action.delete.end = gtk_text_iter_get_offset (end); + + undo_action.action.delete.text = get_chars ( + buffer, + undo_action.action.delete.start, + undo_action.action.delete.end); + + /* figure out if the user used the Delete or the Backspace key */ + gtk_text_buffer_get_iter_at_mark (buffer, &insert_iter, + gtk_text_buffer_get_insert (buffer)); + if (gtk_text_iter_get_offset (&insert_iter) <= undo_action.action.delete.start) + undo_action.action.delete.forward = TRUE; + else + undo_action.action.delete.forward = FALSE; + + if (((undo_action.action.delete.end - undo_action.action.delete.start) > 1) || + (g_utf8_get_char (undo_action.action.delete.text ) == '\n')) + undo_action.mergeable = FALSE; + else + undo_action.mergeable = TRUE; + + undo_action.modified = FALSE; + + gtk_source_undo_manager_add_action (um, &undo_action); + + g_free (undo_action.action.delete.text); + +} + +static void +gtk_source_undo_manager_begin_user_action_handler (GtkTextBuffer *buffer, GtkSourceUndoManager *um) +{ + g_return_if_fail (GTK_SOURCE_IS_UNDO_MANAGER (um)); + g_return_if_fail (um->priv != NULL); + + if (um->priv->running_not_undoable_actions > 0) + return; + + um->priv->actions_in_current_group = 0; +} + +static void +gtk_source_undo_manager_add_action (GtkSourceUndoManager *um, + const GtkSourceUndoAction *undo_action) +{ + GtkSourceUndoAction* action; + + if (um->priv->next_redo >= 0) + { + gtk_source_undo_manager_free_first_n_actions (um, um->priv->next_redo + 1); + } + + um->priv->next_redo = -1; + + if (!gtk_source_undo_manager_merge_action (um, undo_action)) + { + action = g_new (GtkSourceUndoAction, 1); + *action = *undo_action; + + if (action->action_type == GTK_SOURCE_UNDO_ACTION_INSERT) + action->action.insert.text = g_strdup (undo_action->action.insert.text); + else if (action->action_type == GTK_SOURCE_UNDO_ACTION_DELETE) + action->action.delete.text = g_strdup (undo_action->action.delete.text); + else + { + g_free (action); + g_return_if_reached (); + } + + ++um->priv->actions_in_current_group; + action->order_in_group = um->priv->actions_in_current_group; + + if (action->order_in_group == 1) + ++um->priv->num_of_groups; + + um->priv->actions = g_list_prepend (um->priv->actions, action); + } + + gtk_source_undo_manager_check_list_size (um); + + if (!um->priv->can_undo) + { + um->priv->can_undo = TRUE; + g_signal_emit (G_OBJECT (um), undo_manager_signals [CAN_UNDO], 0, TRUE); + } + + if (um->priv->can_redo) + { + um->priv->can_redo = FALSE; + g_signal_emit (G_OBJECT (um), undo_manager_signals [CAN_REDO], 0, FALSE); + } +} + +static void +gtk_source_undo_manager_free_first_n_actions (GtkSourceUndoManager *um, + gint n) +{ + gint i; + + if (um->priv->actions == NULL) + return; + + for (i = 0; i < n; i++) + { + GtkSourceUndoAction *action = g_list_first (um->priv->actions)->data; + + if (action->order_in_group == 1) + --um->priv->num_of_groups; + + if (action->modified) + um->priv->modified_action = INVALID; + + gtk_source_undo_action_free (action); + + um->priv->actions = g_list_delete_link (um->priv->actions, + um->priv->actions); + + if (um->priv->actions == NULL) + return; + } +} + +static void +gtk_source_undo_manager_check_list_size (GtkSourceUndoManager *um) +{ + gint undo_levels; + + g_return_if_fail (GTK_SOURCE_IS_UNDO_MANAGER (um)); + g_return_if_fail (um->priv != NULL); + + undo_levels = gtk_source_undo_manager_get_max_undo_levels (um); + + if (undo_levels < 1) + return; + + if (um->priv->num_of_groups > undo_levels) + { + GtkSourceUndoAction *undo_action; + GList *last; + + last = g_list_last (um->priv->actions); + undo_action = (GtkSourceUndoAction*) last->data; + + do + { + GList *tmp; + + if (undo_action->order_in_group == 1) + --um->priv->num_of_groups; + + if (undo_action->modified) + um->priv->modified_action = INVALID; + + gtk_source_undo_action_free (undo_action); + + tmp = g_list_previous (last); + um->priv->actions = g_list_delete_link (um->priv->actions, last); + last = tmp; + g_return_if_fail (last != NULL); + + undo_action = (GtkSourceUndoAction*) last->data; + + } while ((undo_action->order_in_group > 1) || + (um->priv->num_of_groups > undo_levels)); + } +} + +/** + * gtk_source_undo_manager_merge_action: + * @um: a #GtkSourceUndoManager. + * @undo_action: a #GtkSourceUndoAction. + * + * This function tries to merge the undo action at the top of + * the stack with a new undo action. So when we undo for example + * typing, we can undo the whole word and not each letter by itself. + * + * Return Value: %TRUE is merge was sucessful, %FALSE otherwise.² + **/ +static gboolean +gtk_source_undo_manager_merge_action (GtkSourceUndoManager *um, + const GtkSourceUndoAction *undo_action) +{ + GtkSourceUndoAction *last_action; + + g_return_val_if_fail (GTK_SOURCE_IS_UNDO_MANAGER (um), FALSE); + g_return_val_if_fail (um->priv != NULL, FALSE); + + if (um->priv->actions == NULL) + return FALSE; + + last_action = (GtkSourceUndoAction*) g_list_nth_data (um->priv->actions, 0); + + if (!last_action->mergeable) + return FALSE; + + if ((!undo_action->mergeable) || + (undo_action->action_type != last_action->action_type)) + { + last_action->mergeable = FALSE; + return FALSE; + } + + if (undo_action->action_type == GTK_SOURCE_UNDO_ACTION_DELETE) + { + if ((last_action->action.delete.forward != undo_action->action.delete.forward) || + ((last_action->action.delete.start != undo_action->action.delete.start) && + (last_action->action.delete.start != undo_action->action.delete.end))) + { + last_action->mergeable = FALSE; + return FALSE; + } + + if (last_action->action.delete.start == undo_action->action.delete.start) + { + gchar *str; + +#define L (last_action->action.delete.end - last_action->action.delete.start - 1) +#define g_utf8_get_char_at(p,i) g_utf8_get_char(g_utf8_offset_to_pointer((p),(i))) + + /* Deleted with the delete key */ + if ((g_utf8_get_char (undo_action->action.delete.text) != ' ') && + (g_utf8_get_char (undo_action->action.delete.text) != '\t') && + ((g_utf8_get_char_at (last_action->action.delete.text, L) == ' ') || + (g_utf8_get_char_at (last_action->action.delete.text, L) == '\t'))) + { + last_action->mergeable = FALSE; + return FALSE; + } + + str = g_strdup_printf ("%s%s", last_action->action.delete.text, + undo_action->action.delete.text); + + g_free (last_action->action.delete.text); + last_action->action.delete.end += (undo_action->action.delete.end - + undo_action->action.delete.start); + last_action->action.delete.text = str; + } + else + { + gchar *str; + + /* Deleted with the backspace key */ + if ((g_utf8_get_char (undo_action->action.delete.text) != ' ') && + (g_utf8_get_char (undo_action->action.delete.text) != '\t') && + ((g_utf8_get_char (last_action->action.delete.text) == ' ') || + (g_utf8_get_char (last_action->action.delete.text) == '\t'))) + { + last_action->mergeable = FALSE; + return FALSE; + } + + str = g_strdup_printf ("%s%s", undo_action->action.delete.text, + last_action->action.delete.text); + + g_free (last_action->action.delete.text); + last_action->action.delete.start = undo_action->action.delete.start; + last_action->action.delete.text = str; + } + } + else if (undo_action->action_type == GTK_SOURCE_UNDO_ACTION_INSERT) + { + gchar* str; + +#define I (last_action->action.insert.chars - 1) + + if ((undo_action->action.insert.pos != + (last_action->action.insert.pos + last_action->action.insert.chars)) || + ((g_utf8_get_char (undo_action->action.insert.text) != ' ') && + (g_utf8_get_char (undo_action->action.insert.text) != '\t') && + ((g_utf8_get_char_at (last_action->action.insert.text, I) == ' ') || + (g_utf8_get_char_at (last_action->action.insert.text, I) == '\t'))) + ) + { + last_action->mergeable = FALSE; + return FALSE; + } + + str = g_strdup_printf ("%s%s", last_action->action.insert.text, + undo_action->action.insert.text); + + g_free (last_action->action.insert.text); + last_action->action.insert.length += undo_action->action.insert.length; + last_action->action.insert.text = str; + last_action->action.insert.chars += undo_action->action.insert.chars; + + } + else + /* Unknown action inside undo merge encountered */ + g_return_val_if_reached (TRUE); + + return TRUE; +} + +gint +gtk_source_undo_manager_get_max_undo_levels (GtkSourceUndoManager *um) +{ + g_return_val_if_fail (um != NULL, 0); + g_return_val_if_fail (GTK_SOURCE_IS_UNDO_MANAGER (um), 0); + + return um->priv->max_undo_levels; +} + +void +gtk_source_undo_manager_set_max_undo_levels (GtkSourceUndoManager *um, + gint max_undo_levels) +{ + gint old_levels; + + g_return_if_fail (um != NULL); + g_return_if_fail (GTK_SOURCE_IS_UNDO_MANAGER (um)); + + old_levels = um->priv->max_undo_levels; + um->priv->max_undo_levels = max_undo_levels; + + if (max_undo_levels < 1) + return; + + if (old_levels > max_undo_levels) + { + /* strip redo actions first */ + while (um->priv->next_redo >= 0 && (um->priv->num_of_groups > max_undo_levels)) + { + gtk_source_undo_manager_free_first_n_actions (um, 1); + um->priv->next_redo--; + } + + /* now remove undo actions if necessary */ + gtk_source_undo_manager_check_list_size (um); + + /* emit "can_undo" and/or "can_redo" if appropiate */ + if (um->priv->next_redo < 0 && um->priv->can_redo) + { + um->priv->can_redo = FALSE; + g_signal_emit (G_OBJECT (um), undo_manager_signals [CAN_REDO], 0, FALSE); + } + + if (um->priv->can_undo && + um->priv->next_redo >= (gint)(g_list_length (um->priv->actions) - 1)) + { + um->priv->can_undo = FALSE; + g_signal_emit (G_OBJECT (um), undo_manager_signals [CAN_UNDO], 0, FALSE); + } + } +} + +static void +gtk_source_undo_manager_modified_changed_handler (GtkTextBuffer *buffer, + GtkSourceUndoManager *um) +{ + GtkSourceUndoAction *action; + GList *list; + + g_return_if_fail (GTK_SOURCE_IS_UNDO_MANAGER (um)); + g_return_if_fail (um->priv != NULL); + + if (um->priv->actions == NULL) + return; + + list = g_list_nth (um->priv->actions, um->priv->next_redo + 1); + + if (list != NULL) + action = (GtkSourceUndoAction*) list->data; + else + action = NULL; + + if (gtk_text_buffer_get_modified (buffer) == FALSE) + { + if (action != NULL) + action->mergeable = FALSE; + + if (um->priv->modified_action != NULL) + { + if (um->priv->modified_action != INVALID) + um->priv->modified_action->modified = FALSE; + + um->priv->modified_action = NULL; + } + + return; + } + + if (action == NULL) + { + g_return_if_fail (um->priv->running_not_undoable_actions > 0); + + return; + } + + /* gtk_text_buffer_get_modified (buffer) == TRUE */ + + g_return_if_fail (um->priv->modified_action == NULL); + + if (action->order_in_group > 1) + um->priv->modified_undoing_group = TRUE; + + while (action->order_in_group > 1) + { + list = g_list_next (list); + g_return_if_fail (list != NULL); + + action = (GtkSourceUndoAction*) list->data; + g_return_if_fail (action != NULL); + } + + action->modified = TRUE; + um->priv->modified_action = action; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/gtksourceundomanager.h Sat Jun 16 20:16:36 2007 +0000 @@ -0,0 +1,83 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * gtksourceundomanager.h + * This file is part of GtkSourceView + * + * Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence + * Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi + * Copyright (C) 2002, 2003 Paolo Maggi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. * * + */ + +#ifndef __GTK_SOURCE_UNDO_MANAGER_H__ +#define __GTK_SOURCE_UNDO_MANAGER_H__ + +#include <gtk/gtktextbuffer.h> + +#define GTK_SOURCE_TYPE_UNDO_MANAGER (gtk_source_undo_manager_get_type ()) +#define GTK_SOURCE_UNDO_MANAGER(obj) (GTK_CHECK_CAST ((obj), GTK_SOURCE_TYPE_UNDO_MANAGER, GtkSourceUndoManager)) +#define GTK_SOURCE_UNDO_MANAGER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_SOURCE_TYPE_UNDO_MANAGER, GtkSourceUndoManagerClass)) +#define GTK_SOURCE_IS_UNDO_MANAGER(obj) (GTK_CHECK_TYPE ((obj), GTK_SOURCE_TYPE_UNDO_MANAGER)) +#define GTK_SOURCE_IS_UNDO_MANAGER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_SOURCE_TYPE_UNDO_MANAGER)) +#define GTK_SOURCE_UNDO_MANAGER_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), GTK_SOURCE_TYPE_UNDO_MANAGER, GtkSourceUndoManagerClass)) + + +typedef struct _GtkSourceUndoManager GtkSourceUndoManager; +typedef struct _GtkSourceUndoManagerClass GtkSourceUndoManagerClass; + +typedef struct _GtkSourceUndoManagerPrivate GtkSourceUndoManagerPrivate; + +struct _GtkSourceUndoManager +{ + GObject base; + + GtkSourceUndoManagerPrivate *priv; +}; + +struct _GtkSourceUndoManagerClass +{ + GObjectClass parent_class; + + /* Signals */ + void (*can_undo) (GtkSourceUndoManager *um, gboolean can_undo); + void (*can_redo) (GtkSourceUndoManager *um, gboolean can_redo); +}; + +GType gtk_source_undo_manager_get_type (void) G_GNUC_CONST; + +GtkSourceUndoManager* gtk_source_undo_manager_new (GtkTextBuffer *buffer); + +gboolean gtk_source_undo_manager_can_undo (const GtkSourceUndoManager *um); +gboolean gtk_source_undo_manager_can_redo (const GtkSourceUndoManager *um); + +void gtk_source_undo_manager_undo (GtkSourceUndoManager *um); +void gtk_source_undo_manager_redo (GtkSourceUndoManager *um); + +void gtk_source_undo_manager_begin_not_undoable_action + (GtkSourceUndoManager *um); +void gtk_source_undo_manager_end_not_undoable_action + (GtkSourceUndoManager *um); + +gint gtk_source_undo_manager_get_max_undo_levels + (GtkSourceUndoManager *um); +void gtk_source_undo_manager_set_max_undo_levels + (GtkSourceUndoManager *um, + gint undo_levels); + +#endif /* __GTK_SOURCE_UNDO_MANAGER_H__ */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/gtksourceview-marshal.c Sat Jun 16 20:16:36 2007 +0000 @@ -0,0 +1,95 @@ +#include "gtksourceview-marshal.h" + +#include <glib-object.h> + + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_char (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +/* VOID:VOID (gtksourceview-marshal.list:1) */ + +/* VOID:BOOLEAN (gtksourceview-marshal.list:2) */ + +/* VOID:BOXED (gtksourceview-marshal.list:3) */ + +/* VOID:BOXED,BOXED (gtksourceview-marshal.list:4) */ +void +gtksourceview_marshal_VOID__BOXED_BOXED (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__BOXED_BOXED) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer data2); + register GMarshalFunc_VOID__BOXED_BOXED callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__BOXED_BOXED) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_boxed (param_values + 1), + g_marshal_value_peek_boxed (param_values + 2), + data2); +} + +/* VOID:STRING (gtksourceview-marshal.list:5) */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/gtksourceview-marshal.h Sat Jun 16 20:16:36 2007 +0000 @@ -0,0 +1,32 @@ + +#ifndef __gtksourceview_marshal_MARSHAL_H__ +#define __gtksourceview_marshal_MARSHAL_H__ + +#include <glib-object.h> + +G_BEGIN_DECLS + +/* VOID:VOID (gtksourceview-marshal.list:1) */ +#define gtksourceview_marshal_VOID__VOID g_cclosure_marshal_VOID__VOID + +/* VOID:BOOLEAN (gtksourceview-marshal.list:2) */ +#define gtksourceview_marshal_VOID__BOOLEAN g_cclosure_marshal_VOID__BOOLEAN + +/* VOID:BOXED (gtksourceview-marshal.list:3) */ +#define gtksourceview_marshal_VOID__BOXED g_cclosure_marshal_VOID__BOXED + +/* VOID:BOXED,BOXED (gtksourceview-marshal.list:4) */ +extern void gtksourceview_marshal_VOID__BOXED_BOXED (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +/* VOID:STRING (gtksourceview-marshal.list:5) */ +#define gtksourceview_marshal_VOID__STRING g_cclosure_marshal_VOID__STRING + +G_END_DECLS + +#endif /* __gtksourceview_marshal_MARSHAL_H__ */ +
--- a/pidgin/gtkstatusbox.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/gtkstatusbox.c Sat Jun 16 20:16:36 2007 +0000 @@ -1434,7 +1434,7 @@ } } } else { - GList *accounts; + const GList *accounts; for (accounts = purple_accounts_get_all(); accounts != NULL; accounts = accounts->next) { PurpleAccount *account = accounts->data; PurplePlugin *plug = purple_find_prpl(purple_account_get_protocol_id(account));
--- a/pidgin/gtkthemes.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/gtkthemes.c Sat Jun 16 20:16:36 2007 +0000 @@ -237,7 +237,7 @@ } if (load) { - GList *cnv; + const GList *cnv; if (current_smiley_theme) pidgin_themes_destroy_smiley_theme(current_smiley_theme);
--- a/pidgin/gtkutils.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/gtkutils.c Sat Jun 16 20:16:36 2007 +0000 @@ -130,6 +130,22 @@ } GtkWidget * +pidgin_create_window(const char *title, guint border_width, const char *role, gboolean resizable) +{ + GtkWindow *wnd = NULL; + + wnd = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); + if (title) + gtk_window_set_title(wnd, title); + gtk_container_set_border_width(GTK_CONTAINER(wnd), border_width); + if (role) + gtk_window_set_role(wnd, role); + gtk_window_set_resizable(wnd, resizable); + + return GTK_WIDGET(wnd); +} + +GtkWidget * pidgin_create_imhtml(gboolean editable, GtkWidget **imhtml_ret, GtkWidget **toolbar_ret, GtkWidget **sw_ret) { GtkWidget *frame; @@ -671,8 +687,8 @@ AopMenu *aop_menu = NULL; PurpleAccount *account; GdkPixbuf *pixbuf = NULL; - GList *list; - GList *p; + const GList *list; + const GList *p; GtkSizeGroup *sg; int i; char buf[256]; @@ -979,9 +995,9 @@ /* Check for a compatible account. */ if (ret_account != NULL) { - GList *list; + const GList *list; PurpleAccount *account = NULL; - GList *l; + const GList *l; const char *protoname; if (all_accounts) @@ -3074,3 +3090,4 @@ return path; } #endif +
--- a/pidgin/gtkutils.h Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/gtkutils.h Sat Jun 16 20:16:36 2007 +0000 @@ -93,6 +93,18 @@ GtkWidget *pidgin_create_imhtml(gboolean editable, GtkWidget **imhtml_ret, GtkWidget **toolbar_ret, GtkWidget **sw_ret); /** + * Creates a new window + * + * @param title The window title, or @c NULL + * @param border_width The window's desired border width + * @param role A string indicating what the window is responsible for doing, or @c NULL + * @param resizable Whether the window should be resizable (@c TRUE) or not (@c FALSE) + * + * @since 2.1.0 + */ +GtkWidget *pidgin_create_window(const char *title, guint border_width, const char *role, gboolean resizable); + +/** * Toggles the sensitivity of a widget. * * @param widget @c NULL. Used for signal handlers.
--- a/pidgin/gtkwhiteboard.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/gtkwhiteboard.c Sat Jun 16 20:16:36 2007 +0000 @@ -28,6 +28,7 @@ #include "debug.h" #include "gtkwhiteboard.h" +#include "gtkutils.h" /****************************************************************************** * Prototypes @@ -143,21 +144,14 @@ gtkwb->brush_color = 0xff0000; } - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtkwb->window = window; - gtk_widget_set_name(window, wb->who); - /* Try and set window title as the name of the buddy, else just use their * username */ buddy = purple_find_buddy(wb->account, wb->who); - if (buddy != NULL) - gtk_window_set_title((GtkWindow*)(window), purple_buddy_get_contact_alias(buddy)); - else - gtk_window_set_title((GtkWindow*)(window), wb->who); - - gtk_window_set_resizable((GtkWindow*)(window), FALSE); + window = pidgin_create_window(buddy != NULL ? purple_buddy_get_contact_alias(buddy) : wb->who, 0, NULL, FALSE); + gtkwb->window = window; + gtk_widget_set_name(window, wb->who); g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(whiteboard_close_cb), gtkwb);
--- a/pidgin/pidginstock.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/pidginstock.c Sat Jun 16 20:16:36 2007 +0000 @@ -151,6 +151,7 @@ { PIDGIN_STOCK_TOOLBAR_FONT_FACE, "toolbar", "font-face.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, { PIDGIN_STOCK_TOOLBAR_TEXT_SMALLER, "toolbar", "font-size-down.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, { PIDGIN_STOCK_TOOLBAR_TEXT_LARGER, "toolbar", "font-size-up.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TOOLBAR_INSERT, "toolbar", "insert.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, { PIDGIN_STOCK_TOOLBAR_INSERT_IMAGE, "toolbar", "insert-image.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, { PIDGIN_STOCK_TOOLBAR_INSERT_LINK, "toolbar", "insert-link.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, { PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW, "toolbar", "message-new.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
--- a/pidgin/pidginstock.h Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/pidginstock.h Sat Jun 16 20:16:36 2007 +0000 @@ -116,6 +116,7 @@ #define PIDGIN_STOCK_TOOLBAR_FONT_FACE "pidgin-font-face" #define PIDGIN_STOCK_TOOLBAR_TEXT_SMALLER "pidgin-text-smaller" #define PIDGIN_STOCK_TOOLBAR_TEXT_LARGER "pidgin-text-larger" +#define PIDGIN_STOCK_TOOLBAR_INSERT "pidgin-insert" #define PIDGIN_STOCK_TOOLBAR_INSERT_IMAGE "pidgin-insert-image" #define PIDGIN_STOCK_TOOLBAR_INSERT_LINK "pidgin-insert-link" #define PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW "pidgin-message-new"
--- a/pidgin/pixmaps/toolbar/16/Makefile.am Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/pixmaps/toolbar/16/Makefile.am Sat Jun 16 20:16:36 2007 +0000 @@ -6,6 +6,7 @@ font-face.png \ font-size-down.png \ font-size-up.png \ + insert.png \ insert-image.png \ insert-link.png \ message-new.png \
--- a/pidgin/plugins/gestures/gestures.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/plugins/gestures/gestures.c Sat Jun 16 20:16:36 2007 +0000 @@ -176,7 +176,7 @@ plugin_load(PurplePlugin *plugin) { PurpleConversation *conv; - GList *l; + const GList *l; for (l = purple_get_conversations(); l != NULL; l = l->next) { conv = (PurpleConversation *)l->data; @@ -199,7 +199,7 @@ { PurpleConversation *conv; PidginConversation *gtkconv; - GList *l; + const GList *l; for (l = purple_get_conversations(); l != NULL; l = l->next) { conv = (PurpleConversation *)l->data;
--- a/pidgin/plugins/gevolution/add_buddy_dialog.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/plugins/gevolution/add_buddy_dialog.c Sat Jun 16 20:16:36 2007 +0000 @@ -162,7 +162,7 @@ GList *list, const char *id) { PurpleAccount *account = NULL; - GList *l; + const GList *l; GtkTreeIter iter; GdkPixbuf *pixbuf; @@ -442,10 +442,7 @@ if (username != NULL) dialog->username = g_strdup(username); - dialog->win = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_role(GTK_WINDOW(dialog->win), "add_buddy"); - gtk_window_set_title(GTK_WINDOW(dialog->win), _("Add Buddy")); - gtk_container_set_border_width(GTK_CONTAINER(dialog->win), 12); + dialog->win = pidgin_create_window(_("Add Buddy"), PIDGIN_HIG_BORDER, "add_buddy", TRUE); gtk_widget_set_size_request(dialog->win, -1, 400); g_signal_connect(G_OBJECT(dialog->win), "delete_event",
--- a/pidgin/plugins/gevolution/assoc-buddy.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/plugins/gevolution/assoc-buddy.c Sat Jun 16 20:16:36 2007 +0000 @@ -329,9 +329,7 @@ dialog->buddy = buddy; - dialog->win = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_role(GTK_WINDOW(dialog->win), "assoc_buddy"); - gtk_container_set_border_width(GTK_CONTAINER(dialog->win), 12); + dialog->win = pidgin_create_window(NULL, PIDGIN_HIG_BORDER, "assoc_buddy", TRUE); g_signal_connect(G_OBJECT(dialog->win), "delete_event", G_CALLBACK(delete_win_cb), dialog);
--- a/pidgin/plugins/gevolution/gevolution.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/plugins/gevolution/gevolution.c Sat Jun 16 20:16:36 2007 +0000 @@ -69,7 +69,8 @@ const char *prpl_id, EContactField field) { GList *ims = e_contact_get(contact, field); - GList *l, *l2; + const GList *l; + const GList *l2; if (ims == NULL) return; @@ -400,7 +401,7 @@ GtkCellRenderer *renderer; GdkPixbuf *pixbuf; GtkListStore *model; - GList *l; + const GList *l; /* Outside container */ ret = gtk_vbox_new(FALSE, 18);
--- a/pidgin/plugins/gevolution/new_person_dialog.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/plugins/gevolution/new_person_dialog.c Sat Jun 16 20:16:36 2007 +0000 @@ -246,11 +246,7 @@ dialog->book = book; g_object_ref(book); - dialog->win = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_role(GTK_WINDOW(dialog->win), "new_person"); - gtk_window_set_title(GTK_WINDOW(dialog->win), _("New Person")); - gtk_window_set_resizable(GTK_WINDOW(dialog->win), FALSE); - gtk_container_set_border_width(GTK_CONTAINER(dialog->win), 12); + dialog->win = pidgin_create_window(_("New Person"), PIDGIN_HIG_BORDER, "new_person", FALSE); g_signal_connect(G_OBJECT(dialog->win), "delete_event", G_CALLBACK(delete_win_cb), dialog);
--- a/pidgin/plugins/notify.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/plugins/notify.c Sat Jun 16 20:16:36 2007 +0000 @@ -624,7 +624,7 @@ static void apply_method() { - GList *convs; + const GList *convs; PidginWindow *purplewin = NULL; for (convs = purple_get_conversations(); convs != NULL; @@ -644,7 +644,7 @@ static void apply_notify() { - GList *convs = purple_get_conversations(); + const GList *convs = purple_get_conversations(); while (convs) { PurpleConversation *conv = (PurpleConversation *)convs->data; @@ -818,7 +818,7 @@ static gboolean plugin_load(PurplePlugin *plugin) { - GList *convs = purple_get_conversations(); + const GList *convs = purple_get_conversations(); void *conv_handle = purple_conversations_get_handle(); void *gtk_conv_handle = pidgin_conversations_get_handle(); @@ -860,7 +860,7 @@ static gboolean plugin_unload(PurplePlugin *plugin) { - GList *convs = purple_get_conversations(); + const GList *convs = purple_get_conversations(); while (convs) { PurpleConversation *conv = (PurpleConversation *)convs->data;
--- a/pidgin/plugins/relnot.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/plugins/relnot.c Sat Jun 16 20:16:36 2007 +0000 @@ -70,8 +70,9 @@ message = g_string_new(""); g_string_append_printf(message, _("You are using %s version %s. The " "current version is %s. You can get it from " - "<a href=\"" PURPLE_WEBSITE "\">" PURPLE_WEBSITE "</a><hr>"), - PIDGIN_NAME, purple_core_get_version(), cur_ver); + "<a href=\"%s\">%s</a><hr>"), + PIDGIN_NAME, purple_core_get_version(), cur_ver, + PURPLE_WEBSITE, PURPLE_WEBSITE); if(*changelog) { formatted = purple_strdup_withhtml(changelog);
--- a/pidgin/plugins/spellchk.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/plugins/spellchk.c Sat Jun 16 20:16:36 2007 +0000 @@ -2118,7 +2118,7 @@ plugin_load(PurplePlugin *plugin) { void *conv_handle = purple_conversations_get_handle(); - GList *convs; + const GList *convs; load_conf(); @@ -2137,7 +2137,7 @@ static gboolean plugin_unload(PurplePlugin *plugin) { - GList *convs; + const GList *convs; /* Detach from existing conversations */ for (convs = purple_get_conversations(); convs != NULL; convs = convs->next)
--- a/pidgin/plugins/ticker/ticker.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/plugins/ticker/ticker.c Sat Jun 16 20:16:36 2007 +0000 @@ -36,6 +36,7 @@ #include "gtkblist.h" #include "gtkplugin.h" +#include "gtkutils.h" #include "gtkticker.h" @@ -70,12 +71,10 @@ return; } - tickerwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); + tickerwindow = pidgin_create_window(_("Buddy Ticker"), 0, "ticker", TRUE); gtk_window_set_default_size(GTK_WINDOW(tickerwindow), 500, -1); g_signal_connect(G_OBJECT(tickerwindow), "delete_event", G_CALLBACK (buddy_ticker_destroy_window), NULL); - gtk_window_set_title (GTK_WINDOW(tickerwindow), _("Buddy Ticker")); - gtk_window_set_role (GTK_WINDOW(tickerwindow), "ticker"); ticker = gtk_ticker_new(); gtk_ticker_set_spacing(GTK_TICKER(ticker), 20);
--- a/pidgin/plugins/timestamp.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/plugins/timestamp.c Sat Jun 16 20:16:36 2007 +0000 @@ -77,7 +77,7 @@ time_t now = time(NULL) / interval * interval; time_t then; - if (!g_list_find(purple_get_conversations(), conv)) + if (!g_list_find((GList *)purple_get_conversations(), conv)) return FALSE; then = GPOINTER_TO_INT(purple_conversation_get_data( @@ -98,7 +98,7 @@ PidginConversation *gtk_conv = PIDGIN_CONVERSATION(conv); GtkTextBuffer *buffer; - if (!g_list_find(purple_get_conversations(), conv)) + if (!g_list_find((GList *)purple_get_conversations(), conv)) return; buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtk_conv->imhtml));
--- a/pidgin/plugins/xmppconsole.c Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/plugins/xmppconsole.c Sat Jun 16 20:16:36 2007 +0000 @@ -29,6 +29,7 @@ #if !GTK_CHECK_VERSION(2,4,0) #include "pidgincombobox.h" #endif +#include "gtkutils.h" typedef struct { PurpleConnection *gc; @@ -730,7 +731,7 @@ GtkWidget *label; GtkTextBuffer *buffer; GtkWidget *toolbar; - GList *connections; + const GList *connections; #if GTK_CHECK_VERSION(2,4,0) GtkToolItem *button; #endif @@ -742,10 +743,8 @@ console = g_new0(XmppConsole, 1); - console->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(console->window), _("XMPP Console")); + console->window = pidgin_create_window(_("XMPP Console"), PIDGIN_HIG_BORDER, NULL, TRUE); g_signal_connect(G_OBJECT(console->window), "destroy", G_CALLBACK(console_destroy), NULL); - gtk_container_set_border_width(GTK_CONTAINER(console->window), 12); gtk_window_set_default_size(GTK_WINDOW(console->window), 580, 400); gtk_container_add(GTK_CONTAINER(console->window), vbox);
--- a/pidgin/win32/nsis/pidgin-installer.nsi Fri Jun 15 08:16:29 2007 +0000 +++ b/pidgin/win32/nsis/pidgin-installer.nsi Sat Jun 16 20:16:36 2007 +0000 @@ -127,7 +127,7 @@ !define MUI_FINISHPAGE_RUN "$INSTDIR\pidgin.exe" !define MUI_FINISHPAGE_RUN_NOTCHECKED !define MUI_FINISHPAGE_LINK $(PIDGIN_FINISH_VISIT_WEB_SITE) - !define MUI_FINISHPAGE_LINK_LOCATION "http://pidgin.im/win32" + !define MUI_FINISHPAGE_LINK_LOCATION "http://pidgin.im" ;-------------------------------- ;Pages @@ -358,7 +358,7 @@ StrCmp $R0 "2" upgrade_gtk ;StrCmp $R0 "3" no_gtk no_gtk - no_gtk: + ;no_gtk: StrCmp $R1 "NONE" gtk_no_install_rights ClearErrors ExecWait '"$TEMP\gtk-runtime.exe" /L=$LANGUAGE $ISSILENT /D=$GTK_FOLDER'