grim/purple-plugin-pack
--leaks
org.guifications.plugins
2009-04-15, darkrain42
* Nicksaid - Record when someone said your nick in a chat. * Copyright (C) 2006-2008 Sadrul Habib Chowdhury <sadrul@users.sourceforge.net> * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA /* If you can't figure out what this line is for, DON'T TOUCH IT. */ #include "../common/pp_internal.h" #define PLUGIN_ID "gtk-plugin_pack-nicksaid" #define PLUGIN_STATIC_NAME "nicksaid" #define PLUGIN_AUTHOR "Sadrul H Chowdhury <sadrul@users.sourceforge.net>" #define PREF_PREFIX "/plugins/gtk/" PLUGIN_ID #define PREF_HLWORDS PREF_PREFIX "/hlwords" #define PREF_CHARS PREF_PREFIX "/chars" #define PREF_TIMESTAMP PREF_PREFIX "/timestamp" #define PREF_DATESTAMP PREF_PREFIX "/datestamp" #define PREF_SHOWWHO PREF_PREFIX "/showwho" #define PREF_SHOWALL PREF_PREFIX "/showall" #define DELIMS " .,;|<>?/\\`~!@#$%^&*()_-+={}[]:'\"" static GList *hlwords = NULL; /* Words to highlight on */ go_next(GtkWidget *w, PidginConversation *gtkconv) go_previous(GtkWidget *w, PidginConversation *gtkconv) typedef struct _NickSaid NickSaid; /* <lift src="pidgin/src/util.c"> ??? */ strftime(buf, sizeof(buf), "%H:%M:%S", localtime(&tme)); strftime(buf, sizeof(buf), "%Y-%m-%d", localtime(&tme)); buf[strlen(buf) - 1] = '\0'; static gboolean draw_line(GtkWidget *widget, GdkEventExpose *event, struct _callbackdata *data); remove_line(struct _callbackdata *data) if (g_signal_handlers_disconnect_matched(G_OBJECT(data->view), G_SIGNAL_MATCH_DATA, g_object_set_data(G_OBJECT(data->view), "nicksaid:mark", GINT_TO_POINTER(0)); gtk_widget_queue_draw(GTK_WIDGET(data->view)); draw_line(GtkWidget *widget, GdkEventExpose *event, struct _callbackdata *data) GdkRectangle rect, visible_rect; GdkColor green = {0, 0, 0xffff, 0}; gtk_text_view_get_iter_location(view, &iter, &rect); pad = (gtk_text_view_get_pixels_below_lines(view) + gtk_text_view_get_pixels_above_lines(view)) / 2; bottom = rect.y + rect.height + pad; gtk_text_view_buffer_to_window_coords(view, GTK_TEXT_WINDOW_TEXT, gtk_text_view_buffer_to_window_coords(view, GTK_TEXT_WINDOW_TEXT, gtk_text_view_get_visible_rect(view, &visible_rect); gc = gdk_gc_new(GDK_DRAWABLE(event->window)); gdk_gc_set_rgb_fg_color(gc, &green); gdk_draw_line(event->window, gc, 0, top, visible_rect.width, top); gdk_draw_line(event->window, gc, 0, bottom, visible_rect.width, bottom); if (!g_object_get_data(G_OBJECT(view), "nicksaid:mark")) g_timeout_add(2500, (GSourceFunc)remove_line, data); g_object_set_data(G_OBJECT(view), "nicksaid:mark", GINT_TO_POINTER(1)); go_selected(GtkWidget *w, PidginConversation *gtkconv) struct _callbackdata *data; offset = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), "nicksaid:offset")) + 1; gtk_text_buffer_get_iter_at_offset(GTK_IMHTML(gtkconv->imhtml)->text_buffer, &iter, offset); gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(gtkconv->imhtml), &iter, 0, TRUE, 0, 0); data = g_new0(struct _callbackdata, 1); data->view = GTK_TEXT_VIEW(gtkconv->imhtml); g_signal_connect(G_OBJECT(gtkconv->imhtml), "expose_event", G_CALLBACK(draw_line), data); gtk_widget_queue_draw(gtkconv->imhtml); clear_list(GtkWidget *w, PidginConversation *gtkconv) ll = list = g_object_get_data(G_OBJECT(gtkconv->imhtml), "nicksaid:list"); NickSaid *said = list->data; g_object_set_data(G_OBJECT(gtkconv->imhtml), "nicksaid:list", NULL); show_all(GtkWidget *w, PidginConversation *gtkconv) GList *list = g_object_get_data(G_OBJECT(gtkconv->imhtml), "nicksaid:list"); GString *str = g_string_new(NULL); NickSaid *said = list->data; g_string_append_printf(str, "%s<br/>\n", said->what); purple_notify_formatted(gtkconv, _("Nicksaid"), _("List of highlighted messages:"), NULL, str->str, NULL, NULL); g_string_free(str, TRUE); generate_popup(GtkWidget *w, GdkEventButton *event, PidginWindow *win) PurpleConversation *conv; PidginConversation *gtkconv; conv = pidgin_conv_window_get_active_conversation(win); if (purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_CHAT) gtkconv = PIDGIN_CONVERSATION(conv); list = g_object_get_data(G_OBJECT(gtkconv->imhtml), "nicksaid:list"); item = gtk_menu_item_new_with_label(_("None")); gtk_widget_set_sensitive(item, FALSE); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); item = gtk_menu_item_new_with_label(_("Next")); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(go_next), gtkconv); item = gtk_menu_item_new_with_label(_("Previous")); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(go_previous), gtkconv); NickSaid *said = list->data; item = gtk_menu_item_new_with_label(said->who); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); g_object_set_data(G_OBJECT(item), "nicksaid:offset", GINT_TO_POINTER(said->offset)); g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(go_selected), gtkconv); * If the line to scrollback to is greater /pidgin/gtk/conversations/scrollback_lines, * desensitise the widget so it at least displays.. or something like that. you get the drift. */ item = gtk_menu_item_new_with_label(_("Clear History")); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(clear_list), gtkconv); item = gtk_menu_item_new_with_label(_("Show All")); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); if (purple_prefs_get_bool(PREF_SHOWALL)) g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(show_all), gtkconv); gtk_widget_set_sensitive(item, FALSE); gtk_widget_show_all(menu); gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, event->button, displaying_msg_cb(PurpleAccount *account, const char *name, char **buffer, PurpleConversation *conv, PurpleMessageFlags flags, gpointer null) PidginConversation *gtkconv; char *tmp, *who, *prefix = NULL; gboolean timestamp = purple_prefs_get_bool(PREF_TIMESTAMP); gboolean datestamp = purple_prefs_get_bool(PREF_DATESTAMP); gboolean showwho = purple_prefs_get_bool(PREF_SHOWWHO); if (!(flags & PURPLE_MESSAGE_NICK) || !PIDGIN_IS_PIDGIN_CONVERSATION(conv) || purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_CHAT) gtkconv = PIDGIN_CONVERSATION(conv); imhtml = gtkconv->imhtml; gtk_text_buffer_get_end_iter(GTK_IMHTML(imhtml)->text_buffer, &iter); pos = gtk_text_iter_get_offset(&iter); list = g_object_get_data(G_OBJECT(imhtml), "nicksaid:list"); tmp = purple_markup_strip_html(*buffer); who = g_strndup(tmp, purple_prefs_get_int(PREF_CHARS)); if (!g_utf8_validate(who, -1, (const char **)&tmp)) who = g_strdup_printf("%s: %s", name, tmp); if (datestamp && timestamp) { prefix = g_strdup_printf("(%s) ", ns_date_full()); } else if (datestamp && !timestamp) { prefix = g_strdup_printf("(%s) ", ns_date()); } else if (!datestamp && timestamp) { prefix = g_strdup_printf("(%s) ", ns_time()); said = g_new0(NickSaid, 1); said->who = g_strdup_printf("%s%s", prefix, who); if (purple_prefs_get_bool(PREF_SHOWALL)) said->what = g_strdup_printf("%s<b>%s: </b>%s", prefix ? prefix : "", name, *buffer); list = g_list_prepend(list, said); g_object_set_data(G_OBJECT(imhtml), "nicksaid:list", list); get_tray_icon_for_window(PidginWindow *win) GtkWidget *w = g_object_get_data(G_OBJECT(win->window), "nicksaid:trayicon"); #if GTK_CHECK_VERSION(2,4,0) gtk_event_box_set_visible_window(GTK_EVENT_BOX(w), TRUE); gtk_container_add(GTK_CONTAINER(w), gtk_image_new_from_stock(PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW, GTK_ICON_SIZE_MENU)); pidgin_menu_tray_append(PIDGIN_MENU_TRAY(win->menu.tray), w, "Nicksaid"); g_object_set_data(G_OBJECT(win->window), "nicksaid:trayicon", w); g_signal_connect(G_OBJECT(w), "button_press_event", G_CALLBACK(generate_popup), win); update_menu_tray(PurpleConversation *conv) PidginConversation *gtkconv; if (!PIDGIN_IS_PIDGIN_CONVERSATION(conv)) gtkconv = PIDGIN_CONVERSATION(conv); icon = get_tray_icon_for_window(win); if (purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_CHAT) gtk_widget_hide_all(icon); gtk_widget_show_all(icon); deleting_conversation_cb(PurpleConversation *conv, gpointer null) if (purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_CHAT || !PIDGIN_IS_PIDGIN_CONVERSATION(conv)) clear_list(NULL, PIDGIN_CONVERSATION(conv)); rcvd_msg_cb(PurpleAccount *account, const char **who, const char **message, PurpleConversation *conv, PurpleMessageFlags *flags) if (*flags & PURPLE_MESSAGE_NICK) delims = g_strdup(DELIMS); g_strdelimit(delims, purple_prefs_get_string(PREF_HLWORDS), ' '); msg = g_strdup(*message); g_strdelimit(msg, delims, ' '); for (iter = hlwords; iter; iter = iter->next) char *s = g_strstr_len(msg, -1, iter->data); if (s && (s == msg || *(s - 1) == ' ')) char *e = s + strlen(iter->data); if (*e == ' ' || *e == '\0') *flags |= PURPLE_MESSAGE_NICK; hlwords = g_list_delete_link(hlwords, hlwords); string = g_strdup(purple_prefs_get_string(PREF_HLWORDS)); while (*s == ' ' || *s == '\t') while (*e != ' ' && *e != '\t' && *e != '\0') hlwords = g_list_prepend(hlwords, g_strndup(s, e-s)); unload_cleanup_gtkconv(PidginConversation *gtkconv, gpointer null) clear_list(NULL, gtkconv); unload_cleanup_win(PidginWindow *win, gpointer null) GtkWidget *w = get_tray_icon_for_window(win); g_object_set_data(G_OBJECT(win->window), "nicksaid:trayicon", NULL); g_list_foreach(pidgin_conv_window_get_gtkconvs(win), (GFunc)unload_cleanup_gtkconv, NULL); plugin_load(PurplePlugin *plugin) purple_signal_connect(purple_conversations_get_handle(), "receiving-chat-msg", plugin, PURPLE_CALLBACK(rcvd_msg_cb), NULL); purple_signal_connect(pidgin_conversations_get_handle(), "displaying-chat-msg", plugin, PURPLE_CALLBACK(displaying_msg_cb), NULL); purple_signal_connect(pidgin_conversations_get_handle(), "conversation-switched", plugin, PURPLE_CALLBACK(update_menu_tray), NULL); purple_signal_connect(purple_conversations_get_handle(), "deleting-conversation", plugin, PURPLE_CALLBACK(deleting_conversation_cb), NULL); purple_prefs_connect_callback(plugin, PREF_HLWORDS, (PurplePrefCallback)construct_list, NULL); purple_conversation_foreach(update_menu_tray); plugin_unload(PurplePlugin *plugin) g_list_foreach(pidgin_conv_windows_get_list(), (GFunc)unload_cleanup_win, NULL); purple_prefs_disconnect_by_handle(plugin); static PurplePluginPrefFrame * get_plugin_pref_frame(PurplePlugin *plugin) PurplePluginPrefFrame *frame; frame = purple_plugin_pref_frame_new(); pref = purple_plugin_pref_new_with_label(_("Highlight")); purple_plugin_pref_frame_add(frame, pref); pref = purple_plugin_pref_new_with_name_and_label(PREF_HLWORDS, _("_Words to highlight on\n(separate the words with a blank space)")); purple_plugin_pref_frame_add(frame, pref); pref = purple_plugin_pref_new_with_label(_("Number of displayed characters")); purple_plugin_pref_frame_add(frame, pref); pref = purple_plugin_pref_new_with_name_and_label(PREF_CHARS, _("_Set the number of characters displayed\nin the nicksaid menu")); purple_plugin_pref_set_bounds(pref, 10, 40); purple_plugin_pref_frame_add(frame, pref); pref = purple_plugin_pref_new_with_name_and_label(PREF_SHOWWHO, _("Display who said your name in the nicksaid menu")); purple_plugin_pref_frame_add(frame, pref); pref = purple_plugin_pref_new_with_name_and_label(PREF_TIMESTAMP, _("Display _timestamps in the nicksaid menu")); purple_plugin_pref_frame_add(frame, pref); pref = purple_plugin_pref_new_with_name_and_label(PREF_DATESTAMP, _("_Display _datestamps in the nicksaid menu")); purple_plugin_pref_frame_add(frame, pref); pref = purple_plugin_pref_new_with_name_and_label(PREF_SHOWALL, _("Allow displaying in a separate dialog")); purple_plugin_pref_frame_add(frame, pref); static PurplePluginUiInfo prefs_info = { static PurplePluginInfo info = PURPLE_PLUGIN_MAGIC, /* Magic */ PURPLE_MAJOR_VERSION, /* Purple Major Version */ PURPLE_MINOR_VERSION, /* Purple Minor Version */ PURPLE_PLUGIN_STANDARD, /* plugin type */ PIDGIN_PLUGIN_TYPE, /* ui requirement */ PURPLE_PRIORITY_DEFAULT, /* priority */ PLUGIN_ID, /* plugin id */ PP_VERSION, /* version */ PLUGIN_AUTHOR, /* author */ PP_WEBSITE, /* website */ plugin_unload, /* unload */ &prefs_info, /* prefs_info */ init_plugin(PurplePlugin *plugin) bindtextdomain(GETTEXT_PACKAGE, PP_LOCALEDIR); bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); info.name = _("Nicksaid"); info.summary = _("Record when someone said your nick in a chat."); info.description = _("Record when someone said your nick in a chat."); purple_prefs_add_none(PREF_PREFIX); purple_prefs_add_string(PREF_HLWORDS, ""); purple_prefs_add_int(PREF_CHARS, 15); purple_prefs_add_bool(PREF_TIMESTAMP, TRUE); purple_prefs_add_bool(PREF_DATESTAMP, FALSE); purple_prefs_add_bool(PREF_SHOWWHO, TRUE); purple_prefs_add_bool(PREF_SHOWALL, FALSE); PURPLE_INIT_PLUGIN(PLUGIN_STATIC_NAME, init_plugin, info)