changeset 15169:8bc394797096

[gaim-migrate @ 17955] And the gtk plugins from the plugin pack. I've waited on listhandler until rekkanoryo (John Bailey) quits being indecisive... committer: Tailor Script <tailor@pidgin.im>
author Gary Kramlich <grim@reaperworld.com>
date Mon, 11 Dec 2006 05:29:50 +0000
parents 630b794db0c8
children b7f83eba6029
files gtk/plugins/Makefile.am gtk/plugins/Makefile.mingw gtk/plugins/convcolors.c gtk/plugins/markerline.c
diffstat 4 files changed, 684 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/gtk/plugins/Makefile.am	Mon Dec 11 05:03:52 2006 +0000
+++ b/gtk/plugins/Makefile.am	Mon Dec 11 05:29:50 2006 +0000
@@ -26,10 +26,12 @@
 
 plugindir = $(libdir)/gaim
 
+convcolors_la_LDFLAGS       = -module -avoid-version
 extplacement_la_LDFLAGS     = -module -avoid-version
 gaimrc_la_LDFLAGS           = -module -avoid-version
 history_la_LDFLAGS          = -module -avoid-version
 iconaway_la_LDFLAGS         = -module -avoid-version
+markerline_la_LDFLAGS       = -module -avoid-version
 notify_la_LDFLAGS           = -module -avoid-version
 relnot_la_LDFLAGS           = -module -avoid-version
 spellchk_la_LDFLAGS         = -module -avoid-version
@@ -39,31 +41,36 @@
 if PLUGINS
 
 plugin_LTLIBRARIES = \
+	convcolors.la       \
 	extplacement.la     \
 	gaimrc.la           \
 	history.la          \
 	iconaway.la         \
+	markerline.la       \
 	notify.la           \
 	relnot.la           \
 	spellchk.la         \
 	timestamp.la        \
 	timestamp_format.la
 
-
+convcolors_la_SOURCES       = convcolors.c
 extplacement_la_SOURCES     = extplacement.c
 gaimrc_la_SOURCES           = gaimrc.c
 history_la_SOURCES          = history.c
 iconaway_la_SOURCES         = iconaway.c
+markerline_la_SOURCES       = markerline.c
 notify_la_SOURCES           = notify.c
 relnot_la_SOURCES           = relnot.c
 spellchk_la_SOURCES         = spellchk.c
 timestamp_la_SOURCES        = timestamp.c
 timestamp_format_la_SOURCES = timestamp_format.c
 
+convcolors_la_LIBADD        = $(GTK_LIBS)
 extplacement_la_LIBADD      = $(GTK_LIBS)
 gaimrc_la_LIBADD            = $(GTK_LIBS)
 history_la_LIBADD           = $(GTK_LIBS)
 iconaway_la_LIBADD          = $(GTK_LIBS)
+markerline_la_LIBADD        = $(GTK_LIBS)
 notify_la_LIBADD            = $(GTK_LIBS)
 relnot_la_LIBADD            = $(GLIB_LIBS)
 spellchk_la_LIBADD          = $(GTK_LIBS)
--- a/gtk/plugins/Makefile.mingw	Mon Dec 11 05:03:52 2006 +0000
+++ b/gtk/plugins/Makefile.mingw	Mon Dec 11 05:29:50 2006 +0000
@@ -74,10 +74,12 @@
 	$(CC) -shared $@.o $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $@
 
 plugins: \
+		convcolors.dll \
 		extplacement.dll \
 		gaimrc.dll \
 		history.dll \
 		iconaway.dll \
+		markerline.dll \
 		notify.dll \
 		relnot.dll \
 		spellchk.dll \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gtk/plugins/convcolors.c	Mon Dec 11 05:29:50 2006 +0000
@@ -0,0 +1,372 @@
+/*
+ * Conversation Colors
+ * Copyright (C) 2006
+ *
+ * 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.
+ */
+#include "internal.h"
+
+#define PLUGIN_ID			"gtk-plugin_pack-convcolors"
+#define PLUGIN_NAME			"Conversation Colors"
+#define PLUGIN_STATIC_NAME	"Conversation Colors"
+#define PLUGIN_SUMMARY		"Customize colors in the conversation window"
+#define PLUGIN_DESCRIPTION	"Customize colors in the conversation window"
+#define PLUGIN_AUTHOR		"Sadrul H Chowdhury <sadrul@users.sourceforge.net>"
+
+/* System headers */
+#include <gdk/gdk.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+
+/* Gaim headers */
+#include <gtkplugin.h>
+#include <version.h>
+
+#include <conversation.h>
+#include <gtkconv.h>
+#include <gtkprefs.h>
+#include <gtkutils.h>
+
+#define	PREF_PREFIX	"/plugins/gtk/" PLUGIN_ID
+#define PREF_IGNORE	PREF_PREFIX "/ignore_incoming"
+#define PREF_CHATS	PREF_PREFIX "/chats"
+#define PREF_IMS	PREF_PREFIX "/ims"
+
+#define	PREF_SEND	PREF_PREFIX "/send"
+#define	PREF_SEND_C	PREF_SEND "/color"
+#define	PREF_SEND_F	PREF_SEND "/format"
+
+#define PREF_RECV	PREF_PREFIX "/recv"
+#define	PREF_RECV_C	PREF_RECV "/color"
+#define	PREF_RECV_F	PREF_RECV "/format"
+
+#define PREF_SYSTEM	PREF_PREFIX "/system"
+#define	PREF_SYSTEM_C	PREF_SYSTEM "/color"
+#define	PREF_SYSTEM_F	PREF_SYSTEM "/format"
+
+#define PREF_ERROR	PREF_PREFIX "/error"
+#define	PREF_ERROR_C	PREF_ERROR "/color"
+#define	PREF_ERROR_F	PREF_ERROR "/format"
+
+#define PREF_NICK	PREF_PREFIX "/nick"
+#define	PREF_NICK_C	PREF_NICK "/color"
+#define	PREF_NICK_F	PREF_NICK "/format"
+
+enum
+{
+	FONT_BOLD		= 1 << 0,
+	FONT_ITALIC		= 1 << 1,
+	FONT_UNDERLINE	= 1 << 2
+};
+
+struct
+{
+	GaimMessageFlags flag;
+	char *prefix;
+	const char *text;
+} formats[] = 
+{
+	{GAIM_MESSAGE_ERROR, PREF_ERROR, N_("Error Messages")},
+	{GAIM_MESSAGE_NICK, PREF_NICK, N_("Highlighted Messages")},
+	{GAIM_MESSAGE_SYSTEM, PREF_SYSTEM, N_("System Messages")},
+	{GAIM_MESSAGE_SEND, PREF_SEND, N_("Sent Messages")},
+	{GAIM_MESSAGE_RECV, PREF_RECV, N_("Received Messages")},
+	{0, NULL, NULL}
+};
+
+static gboolean
+displaying_msg(GaimAccount *account, const char *who, char **displaying,
+				GaimConversation *conv, GaimMessageFlags flags)
+{
+	int i;
+	char tmp[128], *t;
+	gboolean bold, italic, underline;
+	int f;
+	const char *color;
+
+	for (i = 0; formats[i].prefix; i++)
+		if (flags & formats[i].flag)
+			break;
+
+	if (!formats[i].prefix)
+		return FALSE;
+
+	if ((gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_IM &&
+			!gaim_prefs_get_bool(PREF_IMS)) ||
+			(gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT &&
+			!gaim_prefs_get_bool(PREF_CHATS)))
+		return FALSE;
+
+	g_snprintf(tmp, sizeof(tmp), "%s/color", formats[i].prefix);
+	color = gaim_prefs_get_string(tmp);
+
+	g_snprintf(tmp, sizeof(tmp), "%s/format", formats[i].prefix);
+	f = gaim_prefs_get_int(tmp);
+	bold = (f & FONT_BOLD);
+	italic = (f & FONT_ITALIC);
+	underline = (f & FONT_UNDERLINE);
+
+	if (gaim_prefs_get_bool(PREF_IGNORE))
+	{
+		t = *displaying;
+		*displaying = gaim_markup_strip_html(t);
+		g_free(t);
+	}
+
+	if (color && *color)
+	{
+		t = *displaying;
+		*displaying = g_strdup_printf("<FONT COLOR=\"%s\">%s</FONT>", color, t);
+		g_free(t);
+	}
+
+	t = *displaying;
+	*displaying = g_strdup_printf("%s%s%s%s%s%s%s",
+						bold ? "<B>" : "</B>",
+						italic ? "<I>" : "</I>",
+						underline ? "<U>" : "</U>",
+						t, 
+						bold ? "</B>" : "<B>",
+						italic ? "</I>" : "<I>",
+						underline ? "</U>" : "<U>"
+			);
+	g_free(t);
+
+	return FALSE;
+}
+
+static gboolean
+plugin_load(GaimPlugin *plugin)
+{
+	gaim_signal_connect(gaim_gtk_conversations_get_handle(),
+					"displaying-im-msg", plugin,
+					GAIM_CALLBACK(displaying_msg), NULL);
+	gaim_signal_connect(gaim_gtk_conversations_get_handle(),
+					"displaying-chat-msg", plugin,
+					GAIM_CALLBACK(displaying_msg), NULL);
+	return TRUE;
+}
+
+static gboolean
+plugin_unload(GaimPlugin *plugin)
+{
+	return TRUE;
+}
+
+/* Ripped from GaimRC */
+static void
+color_response(GtkDialog *color_dialog, gint response, const char *data)
+{
+	if (response == GTK_RESPONSE_OK)
+	{
+		GtkWidget *colorsel = GTK_COLOR_SELECTION_DIALOG(color_dialog)->colorsel;
+		GdkColor color;
+		char colorstr[8];
+		char tmp[128];
+
+		gtk_color_selection_get_current_color(GTK_COLOR_SELECTION(colorsel), &color);
+
+		g_snprintf(colorstr, sizeof(colorstr), "#%02X%02X%02X",
+		           color.red/256, color.green/256, color.blue/256);
+
+		g_snprintf(tmp, sizeof(tmp), "%s/color", data);
+
+		gaim_prefs_set_string(tmp, colorstr);
+	}
+
+	gtk_widget_destroy(GTK_WIDGET(color_dialog));
+}
+
+static void
+set_color(GtkWidget *widget, const char *data)
+{
+	GtkWidget *color_dialog = NULL;
+	GdkColor color;
+	char title[128];
+	char tmp[128];
+
+	g_snprintf(title, sizeof(title), _("Select Color for %s"), _(data));
+	color_dialog = gtk_color_selection_dialog_new(title);
+	g_signal_connect(G_OBJECT(color_dialog), "response",
+	                 G_CALLBACK(color_response), (gpointer)data);
+
+	g_snprintf(tmp, sizeof(tmp), "%s/color", data);
+	if (gdk_color_parse(gaim_prefs_get_string(tmp), &color))
+	{
+		gtk_color_selection_set_current_color(
+				GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(color_dialog)->colorsel), &color);
+	}
+
+	gtk_window_present(GTK_WINDOW(color_dialog));
+}
+
+static void
+toggle_something(const char *prefix, int format)
+{
+	int f;
+	char tmp[128];
+	
+	g_snprintf(tmp, sizeof(tmp), "%s/format", prefix);
+	f = gaim_prefs_get_int(tmp);
+	f ^= format;
+	gaim_prefs_set_int(tmp, f);
+}
+		
+static void
+toggle_bold(GtkWidget *widget, gpointer data)
+{
+	toggle_something(data, FONT_BOLD);
+}
+
+static void
+toggle_italic(GtkWidget *widget, gpointer data)
+{
+	toggle_something(data, FONT_ITALIC);
+}
+
+static void
+toggle_underline(GtkWidget *widget, gpointer data)
+{
+	toggle_something(data, FONT_UNDERLINE);
+}
+
+static GtkWidget *
+get_config_frame(GaimPlugin *plugin)
+{
+	GtkWidget *ret;
+	GtkWidget *frame;
+	int i;
+
+	ret = gtk_vbox_new(FALSE, GAIM_HIG_CAT_SPACE);
+	gtk_container_set_border_width(GTK_CONTAINER(ret), GAIM_HIG_BORDER);
+
+	for (i = 0; formats[i].prefix; i++)
+	{
+		char tmp[128];
+		int f;
+		GtkWidget *vbox, *hbox, *button;
+
+		g_snprintf(tmp, sizeof(tmp), "%s/format", formats[i].prefix);
+		f = gaim_prefs_get_int(tmp);
+
+		frame = gaim_gtk_make_frame(ret, _(formats[i].text));
+		vbox = gtk_vbox_new(FALSE, GAIM_HIG_BOX_SPACE);
+		gtk_box_pack_start(GTK_BOX(frame), vbox, FALSE, FALSE, 0);
+
+		hbox = gtk_hbox_new(FALSE, GAIM_HIG_BOX_SPACE);
+		gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+
+		button = gaim_pixbuf_button_from_stock(" Color", GTK_STOCK_SELECT_COLOR,
+				GAIM_BUTTON_HORIZONTAL);
+		gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+		g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(set_color),
+				formats[i].prefix);
+
+		button = gtk_check_button_new_with_label(_("Bold"));
+		gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+		if (f & FONT_BOLD)
+			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
+		g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(toggle_bold),
+				formats[i].prefix);
+		
+		button = gtk_check_button_new_with_label(_("Italic"));
+		gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+		if (f & FONT_ITALIC)
+			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
+		g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(toggle_italic),
+				formats[i].prefix);
+		
+		button = gtk_check_button_new_with_label(_("Underline"));
+		gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+		if (f & FONT_UNDERLINE)
+			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
+		g_signal_connect(G_OBJECT(button), "clicked",
+				G_CALLBACK(toggle_underline), formats[i].prefix);
+	}
+
+	frame = gaim_gtk_make_frame(ret, _("General"));
+	gaim_gtk_prefs_checkbox(_("Ignore incoming format"), PREF_IGNORE, frame);
+	gaim_gtk_prefs_checkbox(_("Apply in Chats"), PREF_CHATS, frame);
+	gaim_gtk_prefs_checkbox(_("Apply in IMs"), PREF_IMS, frame);
+
+	gtk_widget_show_all(ret);
+	return ret;
+}
+
+static GaimGtkPluginUiInfo ui_info = 
+{
+	get_config_frame,
+	0,
+};
+
+static GaimPluginInfo info =
+{
+	GAIM_PLUGIN_MAGIC,            /* Magic              */
+	GAIM_MAJOR_VERSION,           /* Gaim Major Version */
+	GAIM_MINOR_VERSION,           /* Gaim Minor Version */
+	GAIM_PLUGIN_STANDARD,         /* plugin type        */
+	GAIM_GTK_PLUGIN_TYPE,         /* ui requirement     */
+	0,                            /* flags              */
+	NULL,                         /* dependencies       */
+	GAIM_PRIORITY_DEFAULT,        /* priority           */
+
+	PLUGIN_ID,                    /* plugin id          */
+	N_(PLUGIN_NAME),              /* name               */
+	VERSION,                      /* version            */
+	N_(PLUGIN_SUMMARY),           /* summary            */
+	N_(PLUGIN_DESCRIPTION),       /* description        */
+	PLUGIN_AUTHOR,                /* author             */
+	GAIM_WEBSITE,                 /* website            */
+
+	plugin_load,                  /* load               */
+	plugin_unload,                /* unload             */
+	NULL,                         /* destroy            */
+
+	&ui_info,                     /* ui_info            */
+	NULL,                         /* extra_info         */
+	NULL,                         /* prefs_info         */
+	NULL                          /* actions            */
+};
+
+static void
+init_plugin(GaimPlugin *plugin)
+{
+	gaim_prefs_add_none(PREF_PREFIX);
+
+	gaim_prefs_add_bool(PREF_IGNORE, TRUE);
+	gaim_prefs_add_bool(PREF_CHATS, TRUE);
+	gaim_prefs_add_bool(PREF_IMS, TRUE);
+
+	gaim_prefs_add_none(PREF_SEND);
+	gaim_prefs_add_none(PREF_RECV);
+	gaim_prefs_add_none(PREF_SYSTEM);
+	gaim_prefs_add_none(PREF_ERROR);
+	gaim_prefs_add_none(PREF_NICK);
+
+	gaim_prefs_add_string(PREF_SEND_C, "#909090");
+	gaim_prefs_add_string(PREF_RECV_C, "#000000");
+	gaim_prefs_add_string(PREF_SYSTEM_C, "#50a050");
+	gaim_prefs_add_string(PREF_ERROR_C, "#ff0000");
+	gaim_prefs_add_string(PREF_NICK_C, "#0000dd");
+
+	gaim_prefs_add_int(PREF_SEND_F, 0);
+	gaim_prefs_add_int(PREF_RECV_F, 0);
+	gaim_prefs_add_int(PREF_SYSTEM_F, FONT_ITALIC);
+	gaim_prefs_add_int(PREF_ERROR_F, FONT_BOLD | FONT_UNDERLINE);
+	gaim_prefs_add_int(PREF_NICK_F, FONT_BOLD);
+}
+
+GAIM_INIT_PLUGIN(PLUGIN_STATIC_NAME, init_plugin, info)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gtk/plugins/markerline.c	Mon Dec 11 05:29:50 2006 +0000
@@ -0,0 +1,302 @@
+/*
+ * Markerline - Draw a line to indicate new messages in a conversation.
+ * Copyright (C) 2006
+ *
+ * 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.
+ */
+#include "internal.h"
+
+#define PLUGIN_ID			"gtk-plugin_pack-markerline"
+#define PLUGIN_NAME			"Markerline"
+#define PLUGIN_STATIC_NAME	"Markerline"
+#define PLUGIN_SUMMARY		"Draw a line to indicate new messages in a conversation."
+#define PLUGIN_DESCRIPTION	"Draw a line to indicate new messages in a conversation."
+#define PLUGIN_AUTHOR		"Sadrul H Chowdhury <sadrul@users.sourceforge.net>"
+
+/* System headers */
+#include <gdk/gdk.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+
+/* Gaim headers */
+#include <gtkconv.h>
+#include <gtkimhtml.h>
+#include <gtkplugin.h>
+#include <version.h>
+
+#define PREF_PREFIX     "/plugins/gtk/" PLUGIN_ID
+#define PREF_IMS        PREF_PREFIX "/ims"
+#define PREF_CHATS      PREF_PREFIX "/chats"
+
+static int
+imhtml_expose_cb(GtkWidget *widget, GdkEventExpose *event, GaimGtkConversation *gtkconv)
+{
+	int y, last_y, offset;
+	GdkRectangle visible_rect;
+	GtkTextIter iter;
+	GdkRectangle buf;
+	int pad;
+	GaimConversation *conv = gtkconv->active_conv;
+	GaimConversationType type = gaim_conversation_get_type(conv);
+
+	if ((type == GAIM_CONV_TYPE_CHAT && !gaim_prefs_get_bool(PREF_CHATS)) ||
+			(type == GAIM_CONV_TYPE_IM && !gaim_prefs_get_bool(PREF_IMS)))
+		return FALSE;
+
+	gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(widget), &visible_rect);
+
+	offset = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "markerline"));
+	if (offset)
+	{
+		gtk_text_buffer_get_iter_at_offset(gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget)),
+							&iter, offset);
+
+		gtk_text_view_get_iter_location(GTK_TEXT_VIEW(widget), &iter, &buf);
+		last_y = buf.y + buf.height;
+		pad = (gtk_text_view_get_pixels_below_lines(GTK_TEXT_VIEW(widget)) + 
+				gtk_text_view_get_pixels_above_lines(GTK_TEXT_VIEW(widget))) / 2;
+		last_y += pad;
+	}
+	else
+		last_y = 0;
+
+	gtk_text_view_buffer_to_window_coords(GTK_TEXT_VIEW(widget), GTK_TEXT_WINDOW_TEXT,
+										0, last_y, 0, &y);
+
+	if (y >= event->area.y)
+	{
+		GdkColor red = {0, 0xffff, 0, 0};
+		GdkGC *gc = gdk_gc_new(GDK_DRAWABLE(event->window));
+
+		gdk_gc_set_rgb_fg_color(gc, &red);
+		gdk_draw_line(event->window, gc,
+					0, y, visible_rect.width, y);
+		gdk_gc_unref(gc);
+	}
+	return FALSE;
+}
+
+static void
+update_marker_for_gtkconv(GaimGtkConversation *gtkconv)
+{
+	GtkTextIter iter;
+	GtkTextBuffer *buffer;
+	g_return_if_fail(gtkconv != NULL);
+
+	buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml));
+
+	if (!gtk_text_buffer_get_char_count(buffer))
+		return;
+
+	gtk_text_buffer_get_end_iter(buffer, &iter);
+
+	g_object_set_data(G_OBJECT(gtkconv->imhtml), "markerline",
+						GINT_TO_POINTER(gtk_text_iter_get_offset(&iter)));
+	gtk_widget_queue_draw(gtkconv->imhtml);
+}
+
+static gboolean
+focus_removed(GtkWidget *widget, GdkEventVisibility *event, GaimGtkWindow *win)
+{
+	GaimConversation *conv;
+	GaimGtkConversation *gtkconv;
+
+	conv = gaim_gtk_conv_window_get_active_conversation(win);
+	g_return_val_if_fail(conv != NULL, FALSE);
+
+	gtkconv = GAIM_GTK_CONVERSATION(conv);
+	update_marker_for_gtkconv(gtkconv);
+
+	return FALSE;
+}
+
+#if 0
+static gboolean
+window_resized(GtkWidget *w, GdkEventConfigure *event, GaimGtkWindow *win)
+{
+	GList *list;
+
+	list = gaim_gtk_conv_window_get_gtkconvs(win);
+	
+	for (; list; list = list->next)
+		update_marker_for_gtkconv(list->data);
+
+	return FALSE;
+}
+
+static gboolean
+imhtml_resize_cb(GtkWidget *w, GtkAllocation *allocation, GaimGtkConversation *gtkconv)
+{
+	gtk_widget_queue_draw(w);
+	return FALSE;
+}
+#endif
+
+static void
+page_switched(GtkWidget *widget, GtkWidget *page, gint num, GaimGtkWindow *win)
+{
+	focus_removed(NULL, NULL, win);
+}
+
+static void
+detach_from_gtkconv(GaimGtkConversation *gtkconv, gpointer null)
+{
+	g_signal_handlers_disconnect_by_func(G_OBJECT(gtkconv->imhtml), imhtml_expose_cb, gtkconv);
+}
+
+static void
+detach_from_gaim_gtk_window(GaimGtkWindow *win, gpointer null)
+{
+	g_list_foreach(gaim_gtk_conv_window_get_gtkconvs(win), (GFunc)detach_from_gtkconv, NULL);
+	g_signal_handlers_disconnect_by_func(G_OBJECT(win->notebook), page_switched, win);
+	g_signal_handlers_disconnect_by_func(G_OBJECT(win->window), focus_removed, win);
+
+	gtk_widget_queue_draw(win->window);
+}
+
+static void
+attach_to_gtkconv(GaimGtkConversation *gtkconv, gpointer null)
+{
+	detach_from_gtkconv(gtkconv, NULL);
+	g_signal_connect(G_OBJECT(gtkconv->imhtml), "expose_event",
+					 G_CALLBACK(imhtml_expose_cb), gtkconv);
+}
+
+static void
+attach_to_gaim_gtk_window(GaimGtkWindow *win, gpointer null)
+{
+	g_list_foreach(gaim_gtk_conv_window_get_gtkconvs(win), (GFunc)attach_to_gtkconv, NULL);
+
+	g_signal_connect(G_OBJECT(win->window), "focus_out_event",
+					 G_CALLBACK(focus_removed), win);
+
+	g_signal_connect(G_OBJECT(win->notebook), "switch_page",
+					G_CALLBACK(page_switched), win);
+
+	gtk_widget_queue_draw(win->window);
+}
+
+static void
+detach_from_all_windows()
+{
+	g_list_foreach(gaim_gtk_conv_windows_get_list(), (GFunc)detach_from_gaim_gtk_window, NULL);
+}
+
+static void
+attach_to_all_windows()
+{
+	g_list_foreach(gaim_gtk_conv_windows_get_list(), (GFunc)attach_to_gaim_gtk_window, NULL);
+}
+
+static void
+conv_created(GaimConversation *conv, gpointer null)
+{
+	GaimGtkConversation *gtkconv = GAIM_GTK_CONVERSATION(conv);
+	GaimGtkWindow *win;
+
+	if (!gtkconv)
+		return;
+
+	win = gaim_gtkconv_get_window(gtkconv);
+
+	detach_from_gaim_gtk_window(win, NULL);
+	attach_to_gaim_gtk_window(win, NULL);
+}
+
+static gboolean
+plugin_load(GaimPlugin *plugin)
+{
+	attach_to_all_windows();
+
+	gaim_signal_connect(gaim_conversations_get_handle(), "conversation-created",
+						plugin, GAIM_CALLBACK(conv_created), NULL);
+
+	return TRUE;
+}
+
+static gboolean
+plugin_unload(GaimPlugin *plugin)
+{
+	detach_from_all_windows();
+
+	return TRUE;
+}
+
+static GaimPluginPrefFrame *
+get_plugin_pref_frame(GaimPlugin *plugin)
+{
+	GaimPluginPrefFrame *frame;
+	GaimPluginPref *pref;
+
+	frame = gaim_plugin_pref_frame_new();
+
+	pref = gaim_plugin_pref_new_with_label(_("Draw Markerline in "));
+	gaim_plugin_pref_frame_add(frame, pref);
+
+	pref = gaim_plugin_pref_new_with_name_and_label(PREF_IMS,
+					_("_IM windows"));
+	gaim_plugin_pref_frame_add(frame, pref);
+
+	pref = gaim_plugin_pref_new_with_name_and_label(PREF_CHATS,
+					_("C_hat windows"));
+	gaim_plugin_pref_frame_add(frame, pref);
+
+	return frame;
+}
+
+static GaimPluginUiInfo prefs_info = {
+	get_plugin_pref_frame,
+	0,
+	NULL,
+};
+
+static GaimPluginInfo info = {
+	GAIM_PLUGIN_MAGIC,			/* Magic				*/
+	GAIM_MAJOR_VERSION,			/* Gaim Major Version	*/
+	GAIM_MINOR_VERSION,			/* Gaim Minor Version	*/
+	GAIM_PLUGIN_STANDARD,		/* plugin type			*/
+	GAIM_GTK_PLUGIN_TYPE,		/* ui requirement		*/
+	0,							/* flags				*/
+	NULL,						/* dependencies			*/
+	GAIM_PRIORITY_DEFAULT,		/* priority				*/
+
+	PLUGIN_ID,					/* plugin id			*/
+	N_(PLUGIN_NAME),			/* name					*/
+	VERSION,					/* version				*/
+	N_(PLUGIN_SUMMARY),			/* summary				*/
+	N_(PLUGIN_DESCRIPTION),		/* description			*/
+	PLUGIN_AUTHOR,				/* author				*/
+	GAIM_WEBSITE,				/* website				*/
+
+	plugin_load,				/* load					*/
+	plugin_unload,				/* unload				*/
+	NULL,						/* destroy				*/
+
+	NULL,						/* ui_info				*/
+	NULL,						/* extra_info			*/
+	&prefs_info,				/* prefs_info			*/
+	NULL						/* actions				*/
+};
+
+static void
+init_plugin(GaimPlugin *plugin)
+{
+	gaim_prefs_add_none(PREF_PREFIX);
+	gaim_prefs_add_bool(PREF_IMS, FALSE);
+	gaim_prefs_add_bool(PREF_CHATS, TRUE);
+}
+
+GAIM_INIT_PLUGIN(PLUGIN_STATIC_NAME, init_plugin, info)