changeset 2843:87d11d2a7d59

[gaim-migrate @ 2856] i think we've found our mole committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Tue, 04 Dec 2001 07:53:55 +0000
parents cf0f0153e2da
children e63cd7fdd9eb
files ChangeLog po/.cvsignore src/applet.c src/buddy_chat.c src/conversation.c src/convo.h src/gaim.h src/prefs.c src/prpl.c src/ui.h
diffstat 10 files changed, 419 insertions(+), 125 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Tue Dec 04 05:38:53 2001 +0000
+++ b/ChangeLog	Tue Dec 04 07:53:55 2001 +0000
@@ -6,6 +6,7 @@
 	* Galeon as browser option (Thanks Rob McQueen)
 	* IRC /list
 	* Added swedish translation (Thanks Christian Rose)
+	* Option to have IMs and Chats tabbed in same window
 
 version 0.49 (11/29/2001):
 	* Can compile against GTK+ 2.0 (version 1.3.10/1.3.11)
--- a/po/.cvsignore	Tue Dec 04 05:38:53 2001 +0000
+++ b/po/.cvsignore	Tue Dec 04 07:53:55 2001 +0000
@@ -14,3 +14,4 @@
 ru.gmo
 pl.gmo
 nl.gmo
+sv.gmo
--- a/src/applet.c	Tue Dec 04 05:38:53 2001 +0000
+++ b/src/applet.c	Tue Dec 04 07:53:55 2001 +0000
@@ -143,7 +143,7 @@
 	GdkPixmap *cache;
 	GdkGC *gc;
 	char *path;
-	GdkPixbuf *pb, *scale;
+	GdkPixbuf *pb, *scale = NULL;
 	guchar *dst;
 	double affine[6];
 
@@ -156,7 +156,8 @@
 	gdk_gc_copy(gc, applet->style->bg_gc[GTK_WIDGET_STATE(applet)]);
 
 	path = gnome_pixmap_file(name);
-	scale = gdk_pixbuf_new_from_file(path);
+	if (path)
+		scale = gdk_pixbuf_new_from_file(path);
 	g_free(path);
 	if (!scale)
 		return NULL;
--- a/src/buddy_chat.c	Tue Dec 04 05:38:53 2001 +0000
+++ b/src/buddy_chat.c	Tue Dec 04 07:53:55 2001 +0000
@@ -1074,35 +1074,6 @@
 			   GTK_SIGNAL_FUNC(right_click_chat), b);
 }
 
-static gint delete_all_chats(GtkWidget *w, GdkEventAny *e, gpointer d)
-{
-	while (chats) {
-		struct conversation *c = chats->data;
-		close_callback(c->close, c);
-	}
-	return FALSE;
-}
-
-static void chat_switch(GtkNotebook *notebook, GtkWidget *page, gint page_num, gpointer data)
-{
-	GtkWidget *label = gtk_notebook_get_tab_label(GTK_NOTEBOOK(chat_notebook),
-						      gtk_notebook_get_nth_page(GTK_NOTEBOOK
-										(chat_notebook),
-										page_num));
-	GtkStyle *style;
-	struct conversation *b = g_list_nth_data(chats, page_num);
-	if (b && b->window && b->entry)
-		gtk_window_set_focus(GTK_WINDOW(b->window), b->entry);
-	if (!GTK_WIDGET_REALIZED(label))
-		return;
-	style = gtk_style_new();
-	gdk_font_unref(gtk_style_get_font(style));
-	gtk_style_set_font(style, gdk_font_ref(gtk_style_get_font(label->style)));
-	gtk_widget_set_style(label, style);
-	gtk_style_unref(style);
-	b->unseen = 0;
-}
-
 void show_new_buddy_chat(struct conversation *b)
 {
 	GtkWidget *win;
@@ -1131,6 +1102,8 @@
 	if (chat_options & OPT_CHAT_ONE_WINDOW) {
 		if (!all_chats) {
 			win = all_chats = b->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+			if ((convo_options & OPT_CONVO_COMBINE) && (im_options & OPT_IM_ONE_WINDOW))
+				all_convos = all_chats;
 			gtk_window_set_wmclass(GTK_WINDOW(win), "buddy_chat", "Gaim");
 			gtk_window_set_policy(GTK_WINDOW(win), TRUE, TRUE, TRUE);
 			gtk_container_border_width(GTK_CONTAINER(win), 0);
@@ -1138,9 +1111,11 @@
 			aol_icon(win->window);
 			gtk_window_set_title(GTK_WINDOW(win), _("Gaim - Group Chats"));
 			gtk_signal_connect(GTK_OBJECT(win), "delete_event",
-					   GTK_SIGNAL_FUNC(delete_all_chats), NULL);
+					   GTK_SIGNAL_FUNC(delete_all_convo), NULL);
 
 			chat_notebook = gtk_notebook_new();
+			if ((convo_options & OPT_CONVO_COMBINE) && (im_options & OPT_IM_ONE_WINDOW))
+				convo_notebook = chat_notebook;
 			if (chat_options & OPT_CHAT_SIDE_TAB) {
 				if (chat_options & OPT_CHAT_BR_TAB) {
 					gtk_notebook_set_tab_pos(GTK_NOTEBOOK(chat_notebook),
@@ -1162,7 +1137,7 @@
 			gtk_notebook_popup_enable(GTK_NOTEBOOK(chat_notebook));
 			gtk_container_add(GTK_CONTAINER(win), chat_notebook);
 			gtk_signal_connect(GTK_OBJECT(chat_notebook), "switch-page",
-					   GTK_SIGNAL_FUNC(chat_switch), NULL);
+					   GTK_SIGNAL_FUNC(convo_switch), NULL);
 			gtk_widget_show(chat_notebook);
 		} else
 			win = b->window = all_chats;
@@ -1461,9 +1436,14 @@
 void chat_tabize()
 {
 	int pos = 0;
+	char tmp[BUF_LONG];
 	/* evil, evil i tell you! evil! */
 	if (chat_options & OPT_CHAT_ONE_WINDOW) {
 		GList *x = chats;
+		if ((convo_options & OPT_CONVO_COMBINE) && (im_options & OPT_IM_ONE_WINDOW)) {
+			all_chats = all_convos;
+			chat_notebook = convo_notebook;
+		}
 		while (x) {
 			struct conversation *c = x->data;
 			GtkWidget *imhtml, *win;
@@ -1482,6 +1462,10 @@
 			if (c->topic)
 				gtk_entry_set_text(GTK_ENTRY(c->topic_text), c->topic);
 
+			g_snprintf(tmp, sizeof(tmp), _("%d %s in room"), g_list_length(c->in_room),
+				   g_list_length(c->in_room) == 1 ? "person" : "people");
+			gtk_label_set_text(GTK_LABEL(c->count), tmp);
+
 			while (r) {
 				char *name = r->data;
 				GtkWidget *list_item;
@@ -1524,6 +1508,10 @@
 			if (c->topic)
 				gtk_entry_set_text(GTK_ENTRY(c->topic_text), c->topic);
 
+			g_snprintf(tmp, sizeof(tmp), _("%d %s in room"), g_list_length(c->in_room),
+				   g_list_length(c->in_room) == 1 ? "person" : "people");
+			gtk_label_set_text(GTK_LABEL(c->count), tmp);
+
 			while (r) {
 				char *name = r->data;
 				GtkWidget *list_item;
@@ -1548,10 +1536,17 @@
 
 			x = x->next;
 		}
-		if (all_chats)
+		chats = m;
+		if ((convo_options & OPT_CONVO_COMBINE) &&
+		    (im_options & OPT_IM_ONE_WINDOW) && conversations) {
+			while (m) {
+				gtk_notebook_remove_page(GTK_NOTEBOOK(chat_notebook),
+							 g_list_length(conversations));
+				m = m->next;
+			}
+		} else if (all_chats)
 			gtk_widget_destroy(all_chats);
 		all_chats = NULL;
 		chat_notebook = NULL;
-		chats = m;
 	}
 }
--- a/src/conversation.c	Tue Dec 04 05:38:53 2001 +0000
+++ b/src/conversation.c	Tue Dec 04 07:53:55 2001 +0000
@@ -68,7 +68,7 @@
 GdkBitmap *dark_icon_bm = NULL;
 
 GtkWidget *all_convos = NULL;
-static GtkWidget *convo_notebook = NULL;
+GtkWidget *convo_notebook = NULL;
 
 char fontface[128] = { 0 };
 char fontxfld[256] = { 0 };
@@ -428,7 +428,9 @@
 		remove_icon(c);
 		remove_checkbox(c);
 		if (im_options & OPT_IM_ONE_WINDOW) {
-			if (g_list_length(conversations) > 1) {
+			if ((g_list_length(conversations) > 1) ||
+					((convo_options & OPT_CONVO_COMBINE) &&
+					 (chat_options & OPT_CHAT_ONE_WINDOW) && chats)) {
 				gtk_notebook_remove_page(GTK_NOTEBOOK(convo_notebook),
 							 g_list_index(conversations, c));
 			} else {
@@ -437,6 +439,10 @@
 				c->window = NULL;
 				all_convos = NULL;
 				convo_notebook = NULL;
+				if (convo_options & OPT_CONVO_COMBINE) {
+					all_chats = NULL;
+					chat_notebook = NULL;
+				}
 			}
 		} else {
 			if (c->window)
@@ -445,15 +451,22 @@
 		}
 	} else {
 		if (chat_options & OPT_CHAT_ONE_WINDOW) {
-			if (g_list_length(chats) > 1) {
+			if ((g_list_length(chats) > 1) ||
+					((convo_options & OPT_CONVO_COMBINE) &&
+					 (im_options & OPT_IM_ONE_WINDOW) && conversations)) {
 				gtk_notebook_remove_page(GTK_NOTEBOOK(chat_notebook),
-							 g_list_index(chats, c));
+							 g_list_index(chats, c) +
+								g_list_length(conversations));
 			} else {
 				if (c->window)
 					gtk_widget_destroy(c->window);
 				c->window = NULL;
 				all_chats = NULL;
 				chat_notebook = NULL;
+				if (convo_options & OPT_CONVO_COMBINE) {
+					all_convos = NULL;
+					convo_notebook = NULL;
+				}
 			}
 		} else {
 			if (c->window)
@@ -517,11 +530,19 @@
 	g_free(pre_fontface);
 }
 
-static gint delete_all_convo(GtkWidget *w, GdkEventAny *e, gpointer d)
+gint delete_all_convo(GtkWidget *w, GdkEventAny *e, gpointer d)
 {
-	while (conversations) {
-		struct conversation *c = conversations->data;
-		close_callback(c->close, c);
+	if (w == all_convos) {
+		while (conversations) {
+			struct conversation *c = conversations->data;
+			close_callback(c->close, c);
+		}
+	}
+	if (w == all_chats) {
+		while (chats) {
+			struct conversation *c = chats->data;
+			close_callback(c->close, c);
+		}
 	}
 	return FALSE;
 }
@@ -577,6 +598,119 @@
 	}
 }
 
+static void move_next_tab(GtkNotebook *notebook, gboolean chat)
+{
+	int currpage = gtk_notebook_get_current_page(notebook);
+	int convlen;
+	GList *cnv;
+	struct conversation *d = NULL;
+
+	if ((convo_options & OPT_CONVO_COMBINE) &&
+	    (im_options & OPT_IM_ONE_WINDOW) &&
+	    (chat_options & OPT_CHAT_ONE_WINDOW))
+		convlen = g_list_length(conversations);
+	else
+		convlen = 0;
+
+	if (chat) {
+		/* if chat, find next unread chat */
+		cnv = g_list_nth(chats, currpage - convlen);
+		while (cnv) {
+			d = cnv->data;
+			if (d->unseen)
+				break;
+			cnv = cnv->next;
+			d = NULL;
+		}
+		if (d) {
+			gtk_notebook_set_page(notebook, convlen + g_list_index(chats, d));
+			return;
+		}
+	} else {
+		/* else find next unread convo */
+		cnv = g_list_nth(conversations, currpage);
+		while (cnv) {
+			d = cnv->data;
+			if (d->unseen)
+				break;
+			cnv = cnv->next;
+			d = NULL;
+		}
+		if (d) {
+			gtk_notebook_set_page(notebook, g_list_index(conversations, d));
+			return;
+		}
+	}
+
+	if (convo_options & OPT_CONVO_COMBINE) {
+		if (chat && (im_options & OPT_IM_ONE_WINDOW)) {
+			/* if chat find next unread convo */
+			cnv = conversations;
+			while (cnv) {
+				d = cnv->data;
+				if (d->unseen)
+					break;
+				cnv = cnv->next;
+				d = NULL;
+			}
+			if (d) {
+				gtk_notebook_set_page(notebook, g_list_index(conversations, d));
+				return;
+			}
+		} else if (!chat && (chat_options & OPT_CHAT_ONE_WINDOW)) {
+			/* else find next unread chat */
+			cnv = chats;
+			while (cnv) {
+				d = cnv->data;
+				if (d->unseen)
+					break;
+				cnv = cnv->next;
+				d = NULL;
+			}
+			if (d) {
+				gtk_notebook_set_page(notebook, convlen + g_list_index(chats, d));
+				return;
+			}
+		}
+	}
+
+	if (chat) {
+		/* if chat find first unread chat */
+		cnv = chats;
+		while (cnv) {
+			d = cnv->data;
+			if (d->unseen)
+				break;
+			cnv = cnv->next;
+			d = NULL;
+		}
+		if (d) {
+			gtk_notebook_set_page(notebook, convlen + g_list_index(chats, d));
+			return;
+		}
+	} else {
+		/* else find first unread convo */
+		cnv = conversations;
+		while (cnv) {
+			d = cnv->data;
+			if (d->unseen)
+				break;
+			cnv = cnv->next;
+			d = NULL;
+		}
+		if (d) {
+			gtk_notebook_set_page(notebook, g_list_index(conversations, d));
+			return;
+		}
+	}
+
+	/* go to next page */
+	if (currpage + 1 == g_list_length(notebook->children))
+		gtk_notebook_set_page(notebook, 0);
+	else
+		gtk_notebook_next_page(notebook);
+}
+
 gboolean keypress_callback(GtkWidget *entry, GdkEventKey * event, struct conversation *c)
 {
 	int pos;
@@ -733,41 +867,7 @@
 				gtk_notebook_next_page(GTK_NOTEBOOK(notebook));
 				gtk_signal_emit_stop_by_name(GTK_OBJECT(entry), "key_press_event");
 			} else if (event->keyval == GDK_Tab) {
-				GList *ws = (c->is_chat ? chats : conversations);
-				GList *cnv = g_list_nth(ws,
-							gtk_notebook_get_current_page(GTK_NOTEBOOK
-										      (notebook)));
-				struct conversation *d = NULL;
-				while (cnv) {
-					d = cnv->data;
-					if (d->unseen)
-						break;
-					cnv = cnv->next;
-					d = NULL;
-				}
-				if (d) {
-					gtk_notebook_set_page(GTK_NOTEBOOK(notebook),
-							      g_list_index(ws, d));
-				} else {
-					cnv = ws;
-					while (cnv) {
-						d = cnv->data;
-						if (d->unseen)
-							break;
-						cnv = cnv->next;
-						d = NULL;
-					}
-					if (d) {
-						gtk_notebook_set_page(GTK_NOTEBOOK(notebook),
-								      g_list_index(ws, d));
-					} else {
-						cnv = g_list_last(ws);
-						if (c == cnv->data)
-							gtk_notebook_set_page(GTK_NOTEBOOK(notebook), 0);
-						else
-							gtk_notebook_next_page(GTK_NOTEBOOK(notebook));
-					}
-				}
+				move_next_tab(GTK_NOTEBOOK(notebook), c->is_chat);
 				gtk_signal_emit_stop_by_name(GTK_OBJECT(entry), "key_press_event");
 				return TRUE;
 			}
@@ -1588,23 +1688,41 @@
 	    (!c->is_chat && (im_options & OPT_IM_POPUP)))
 		gdk_window_show(c->window->window);
 
-	if (((flags & WFLAG_RECV) || (flags & WFLAG_SYSTEM)) &&
-	    ((!c->is_chat && (im_options & OPT_IM_ONE_WINDOW) &&
-	      (gtk_notebook_get_current_page(GTK_NOTEBOOK(convo_notebook))
-	       != g_list_index(conversations, c))) ||
-	     (c->is_chat && (chat_options & OPT_CHAT_ONE_WINDOW) &&
-	      (gtk_notebook_get_current_page(GTK_NOTEBOOK(chat_notebook))
-	       != g_list_index(chats, c))))) {
-		GtkWidget *notebook = (c->is_chat ? chat_notebook : convo_notebook);
+	/* tab highlighting */
+	if (c->is_chat && !(chat_options & OPT_CHAT_ONE_WINDOW)) /* if chat but not tabbed chat */
+		return;
+	if (!c->is_chat && !(im_options & OPT_IM_ONE_WINDOW)) /* if convo but not tabbed convo */
+		return;
+	if (!(flags & WFLAG_RECV) && !(flags & WFLAG_SYSTEM))
+		return;
+	if ((c->unseen == 2) || ((c->unseen == 1) && !(flags & WFLAG_NICK)))
+		return;
+
+	if (c->is_chat) {
+		int offs;
+		if ((convo_options & OPT_CONVO_COMBINE) && (im_options & OPT_IM_ONE_WINDOW))
+			offs = g_list_length(conversations);
+		else
+			offs = 0;
+		if (gtk_notebook_get_current_page(GTK_NOTEBOOK(chat_notebook)) ==
+				g_list_index(chats, c) + offs)
+			return;
+	} else {
+		if (gtk_notebook_get_current_page(GTK_NOTEBOOK(convo_notebook)) ==
+				g_list_index(conversations, c))
+			return;
+	}
+
+	{
+		GtkNotebook *notebook = GTK_NOTEBOOK(c->is_chat ? chat_notebook : convo_notebook);
+		int offs = ((convo_options & OPT_CONVO_COMBINE) &&
+			    (im_options & OPT_IM_ONE_WINDOW) && c->is_chat) ?
+			g_list_length(conversations) : 0;
 		GList *ws = (c->is_chat ? chats : conversations);
-		GtkWidget *label = gtk_notebook_get_tab_label(GTK_NOTEBOOK(notebook),
-							      gtk_notebook_get_nth_page(GTK_NOTEBOOK
-											(notebook),
-											g_list_index(ws,
-												     c)));
+		GtkWidget *label = gtk_notebook_get_tab_label(notebook,
+							      gtk_notebook_get_nth_page(notebook,
+								      offs + g_list_index(ws, c)));
 		GtkStyle *style;
-		if ((c->unseen == 2) || ((c->unseen == 1) && !(flags & WFLAG_NICK)))
-			return;
 		style = gtk_style_new();
 		if (!GTK_WIDGET_REALIZED(label))
 			gtk_widget_realize(label);
@@ -2104,14 +2222,24 @@
 	}
 }
 
-static void convo_switch(GtkNotebook *notebook, GtkWidget *page, gint page_num, gpointer data)
+void convo_switch(GtkNotebook *notebook, GtkWidget *page, gint page_num, gpointer data)
 {
-	GtkWidget *label = gtk_notebook_get_tab_label(GTK_NOTEBOOK(convo_notebook),
-						      gtk_notebook_get_nth_page(GTK_NOTEBOOK
-										(convo_notebook),
-										page_num));
+	GtkWidget *label = gtk_notebook_get_tab_label(notebook,
+			gtk_notebook_get_nth_page(notebook, page_num));
 	GtkStyle *style;
-	struct conversation *c = g_list_nth_data(conversations, page_num);
+	struct conversation *c;
+	if ((convo_options & OPT_CONVO_COMBINE) &&
+	    (im_options & OPT_IM_ONE_WINDOW) &&
+	    (chat_options & OPT_CHAT_ONE_WINDOW)) {
+		int len = g_list_length(conversations);
+		if (page_num < len)
+			c = g_list_nth_data(conversations, page_num);
+		else
+			c = g_list_nth_data(chats, page_num - len);
+	} else if (GTK_WIDGET(notebook) == convo_notebook)
+		c = g_list_nth_data(conversations, page_num);
+	else
+		c = g_list_nth_data(chats, page_num);
 	if (c && c->window && c->entry)
 		gtk_window_set_focus(GTK_WINDOW(c->window), c->entry);
 	if (!GTK_WIDGET_REALIZED(label))
@@ -2121,7 +2249,8 @@
 	gtk_style_set_font(style, gdk_font_ref(gtk_style_get_font(label->style)));
 	gtk_widget_set_style(label, style);
 	gtk_style_unref(style);
-	c->unseen = 0;
+	if (c)
+		c->unseen = 0;
 }
 
 
@@ -2164,6 +2293,8 @@
 	if (im_options & OPT_IM_ONE_WINDOW) {
 		if (!all_convos) {
 			win = all_convos = c->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+			if ((convo_options & OPT_CONVO_COMBINE) && (chat_options & OPT_CHAT_ONE_WINDOW))
+				all_chats = all_convos;
 			gtk_window_set_wmclass(GTK_WINDOW(win), "conversation", "Gaim");
 			gtk_window_set_policy(GTK_WINDOW(win), TRUE, TRUE, FALSE);
 			gtk_container_border_width(GTK_CONTAINER(win), 0);
@@ -2174,6 +2305,8 @@
 					   GTK_SIGNAL_FUNC(delete_all_convo), NULL);
 
 			convo_notebook = gtk_notebook_new();
+			if ((convo_options & OPT_CONVO_COMBINE) && (chat_options & OPT_CHAT_ONE_WINDOW))
+				chat_notebook = convo_notebook;
 			if (im_options & OPT_IM_SIDE_TAB) {
 				if (im_options & OPT_IM_BR_TAB) {
 					gtk_notebook_set_tab_pos(GTK_NOTEBOOK(convo_notebook),
@@ -2202,8 +2335,9 @@
 
 		cont = gtk_vbox_new(FALSE, 5);
 		gtk_container_set_border_width(GTK_CONTAINER(cont), 5);
-		/* this doesn't actually matter since we're resetting it once we're out of the if/else */
-		gtk_notebook_append_page(GTK_NOTEBOOK(convo_notebook), cont, gtk_label_new(c->name));
+		/* this doesn't matter since we're resetting the name once we're out of the if */
+		gtk_notebook_insert_page(GTK_NOTEBOOK(convo_notebook), cont, gtk_label_new(c->name),
+				g_list_index(conversations, c));
 		gtk_widget_show(cont);
 	} else {
 		cont = win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
@@ -2451,11 +2585,15 @@
 	}
 }
 
-void tabize()
+void im_tabize()
 {
 	/* evil, evil i tell you! evil! */
 	if (im_options & OPT_IM_ONE_WINDOW) {
 		GList *x = conversations;
+		if ((convo_options & OPT_CONVO_COMBINE) && (chat_options & OPT_CHAT_ONE_WINDOW)) {
+			all_convos = all_chats;
+			convo_notebook = chat_notebook;
+		}
 		while (x) {
 			struct conversation *c = x->data;
 			GtkWidget *imhtml, *win;
@@ -2471,6 +2609,7 @@
 			gtk_widget_destroy(win);
 			update_icon(c);
 			update_checkbox(c);
+			set_convo_title(c);
 
 			x = x->next;
 		}
@@ -2486,19 +2625,108 @@
 			remove_icon(c);
 			remove_checkbox(c);
 			show_conv(c);
-			gtk_widget_destroy(c->text);
+			gtk_container_remove(GTK_CONTAINER(c->sw), c->text);
 			gtk_widget_reparent(imhtml, c->sw);
 			c->text = imhtml;
 			update_icon(c);
 			update_checkbox(c);
+			set_convo_title(c);
 
 			x = x->next;
 		}
-		if (all_convos)
+		conversations = m;
+		if ((convo_options & OPT_CONVO_COMBINE) && (chat_options & OPT_CHAT_ONE_WINDOW)) {
+			if (chats) {
+				struct conversation *c;
+				while (m) {
+					gtk_notebook_remove_page(GTK_NOTEBOOK(chat_notebook), 0);
+					m = m->next;
+				}
+				c = chats->data;
+				gtk_window_set_focus(GTK_WINDOW(c->window), c->entry);
+			} else {
+				if (all_convos)
+					gtk_widget_destroy(all_convos);
+				all_chats = NULL;
+				chat_notebook = NULL;
+			}
+		} else if (all_convos)
 			gtk_widget_destroy(all_convos);
 		all_convos = NULL;
 		convo_notebook = NULL;
-		conversations = m;
+	}
+}
+
+void convo_tabize()
+{
+	GList *x, *m;
+	GtkWidget *tmp;
+
+	if (!chats && !conversations)
+		return;
+
+	if (convo_options & OPT_CONVO_COMBINE) {
+		if (!chats) {
+			all_chats = all_convos;
+			chat_notebook = convo_notebook;
+			return;
+		} else if (!conversations) {
+			all_convos = all_chats;
+			convo_notebook = chat_notebook;
+			return;
+		}
+	} else {
+		if (!chats) {
+			all_chats = NULL;
+			chat_notebook = NULL;
+			return;
+		} else if (!conversations) {
+			all_convos = NULL;
+			convo_notebook = NULL;
+			return;
+		}
+	}
+
+	tmp = all_convos;
+	if (convo_options & OPT_CONVO_COMBINE) {
+		all_convos = all_chats;
+		convo_notebook = chat_notebook;
+	} else {
+		all_convos = NULL;
+		convo_notebook = NULL;
+	}
+	x = m = conversations;
+	while (x) {
+		struct conversation *c = x->data;
+		GtkWidget *imhtml;
+
+		imhtml = c->text;
+		remove_icon(c);
+		remove_checkbox(c);
+		show_conv(c);
+		gtk_container_remove(GTK_CONTAINER(c->sw), c->text);
+		gtk_widget_reparent(imhtml, c->sw);
+		c->text = imhtml;
+		update_icon(c);
+		update_checkbox(c);
+
+		x = x->next;
+	}
+
+	conversations = m;
+	if (convo_options & OPT_CONVO_COMBINE) {
+		if (tmp)
+			gtk_widget_destroy(tmp);
+	} else {
+		while (m) {
+			gtk_notebook_remove_page(GTK_NOTEBOOK(chat_notebook), 0);
+			m = m->next;
+		}
+	}
+	m = conversations;
+	while (m) {
+		set_convo_title(m->data);
+		m = m->next;
 	}
 }
 
@@ -2514,17 +2742,17 @@
 	else
 		text = c->name;
 
-	if (!convo_notebook) {
+	if (im_options & OPT_IM_ONE_WINDOW) {
+		nb = GTK_NOTEBOOK(convo_notebook);
+		index = g_list_index(conversations, c);
+		gtk_notebook_set_tab_label_text(nb, gtk_notebook_get_nth_page(nb, index), text);
+	} else {
 		char buf[256];
 		if ((find_log_info(c->name)) || (logging_options & OPT_LOG_ALL))
 			g_snprintf(buf, sizeof(buf), LOG_CONVERSATION_TITLE, text);
 		else
 			g_snprintf(buf, sizeof(buf), CONVERSATION_TITLE, text);
 		gtk_window_set_title(GTK_WINDOW(c->window), buf);
-	} else {
-		nb = GTK_NOTEBOOK(convo_notebook);
-		index = g_list_index(conversations, c);
-		gtk_notebook_set_tab_label_text(nb, gtk_notebook_get_nth_page(nb, index), text);
 	}
 }
 
--- a/src/convo.h	Tue Dec 04 05:38:53 2001 +0000
+++ b/src/convo.h	Tue Dec 04 07:53:55 2001 +0000
@@ -33,6 +33,9 @@
 #include "pixmaps/tb_search.xpm"
 #include "pixmaps/block.xpm"
 
+extern GtkWidget *convo_notebook;
+extern GtkWidget *chat_notebook;
+
 /* we declare all of the global functions for chat and IM windows here, so
  * that it's easy to keep them merged. */
 
@@ -67,6 +70,9 @@
 extern void check_spelling( GtkEditable *, gchar *, gint, gint *, gpointer);
 extern int entry_key_pressed(GtkWidget *, GtkWidget *);
 
+extern void convo_switch(GtkNotebook *, GtkWidget *, gint, gpointer);
+extern gint delete_all_convo(GtkWidget *, GdkEventAny *, gpointer);
+
 extern GtkWidget *build_conv_toolbar(struct conversation *);
 
 extern void send_callback(GtkWidget *, struct conversation *);
--- a/src/gaim.h	Tue Dec 04 05:38:53 2001 +0000
+++ b/src/gaim.h	Tue Dec 04 07:53:55 2001 +0000
@@ -233,6 +233,7 @@
 #define OPT_CONVO_SHOW_SMILEY		0x00000400
 #define OPT_CONVO_IGNORE_FONTS		0x00000800
 #define OPT_CONVO_IGNORE_SIZES		0x00001000
+#define OPT_CONVO_COMBINE		0x00002000
 
 extern guint im_options;
 #define OPT_IM_POPUP			0x00000001
--- a/src/prefs.c	Tue Dec 04 05:38:53 2001 +0000
+++ b/src/prefs.c	Tue Dec 04 07:53:55 2001 +0000
@@ -766,16 +766,30 @@
 static void set_tab_opt(GtkWidget *w, int data)
 {
 	int mask;
-	if (data & 0x1) {	/* set the first bit if we're affecting chat buttons */
+	if (convo_options & OPT_CONVO_COMBINE) {
+		/* through an amazing coincidence (this wasn't planned), we're able to do this,
+		 * since the two sets of options end up having the same value. isn't that great. */
 		mask = (OPT_CHAT_SIDE_TAB | OPT_CHAT_BR_TAB);
 		chat_options &= ~(mask);
 		chat_options |= (data & mask);
-		update_chat_tabs();
-	} else {
+
 		mask = (OPT_IM_SIDE_TAB | OPT_IM_BR_TAB);
 		im_options &= ~(mask);
 		im_options |= (data & mask);
+
 		update_im_tabs();
+	} else {
+		if (data & 0x1) {	/* set the first bit if we're affecting chat buttons */
+			mask = (OPT_CHAT_SIDE_TAB | OPT_CHAT_BR_TAB);
+			chat_options &= ~(mask);
+			chat_options |= (data & mask);
+			update_chat_tabs();
+		} else {
+			mask = (OPT_IM_SIDE_TAB | OPT_IM_BR_TAB);
+			im_options &= ~(mask);
+			im_options |= (data & mask);
+			update_im_tabs();
+		}
 	}
 
 	save_prefs();
@@ -840,6 +854,13 @@
 	gtk_widget_show(spin);
 }
 
+static gboolean current_is_im = FALSE;
+
+static void not_im()
+{
+	current_is_im = FALSE;
+}
+
 static void im_page()
 {
 	GtkWidget *parent;
@@ -858,8 +879,11 @@
 	parent = prefdialog->parent;
 	gtk_widget_destroy(prefdialog);
 
+	current_is_im = TRUE;
+
 	prefdialog = gtk_frame_new(_("IM Options"));
 	gtk_container_add(GTK_CONTAINER(parent), prefdialog);
+	gtk_signal_connect(GTK_OBJECT(prefdialog), "destroy", GTK_SIGNAL_FUNC(not_im), NULL);
 
 	box = gtk_vbox_new(FALSE, 5);
 	gtk_container_set_border_width(GTK_CONTAINER(box), 5);
@@ -905,6 +929,13 @@
 	button =
 	    gaim_button(_("Show all conversations in one tabbed window"), &im_options, OPT_IM_ONE_WINDOW,
 			vbox2);
+	opt = gaim_button(_("Show chats in the same tabbed window"), &convo_options, OPT_CONVO_COMBINE, vbox2);
+	if (chat_options & OPT_CHAT_ONE_WINDOW) {
+		if (!(im_options & OPT_IM_ONE_WINDOW))
+			gtk_widget_set_sensitive(opt, FALSE);
+		gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(toggle_sensitive), opt);
+	} else
+		gtk_widget_set_sensitive(opt, FALSE);
 	gaim_button(_("Raise windows on events"), &im_options, OPT_IM_POPUP, vbox2);
 	gaim_button(_("Show logins in window"), &im_options, OPT_IM_LOGON, vbox2);
 	gaim_button(_("Show aliases in tabs/titles"), &im_options, OPT_IM_ALIAS_TAB, vbox2);
@@ -1044,6 +1075,13 @@
 	button =
 	    gaim_button(_("Show all chats in one tabbed window"), &chat_options, OPT_CHAT_ONE_WINDOW,
 			vbox2);
+	opt = gaim_button(_("Show conversations in the same tabbed window"), &convo_options, OPT_CONVO_COMBINE, vbox2);
+	if (im_options & OPT_IM_ONE_WINDOW) {
+		if (!(chat_options & OPT_CHAT_ONE_WINDOW))
+			gtk_widget_set_sensitive(opt, FALSE);
+		gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(toggle_sensitive), opt);
+	} else
+		gtk_widget_set_sensitive(opt, FALSE);
 	gaim_button(_("Raise windows on events"), &chat_options, OPT_CHAT_POPUP, vbox2);
 	gaim_button(_("Show people joining/leaving in window"), &chat_options, OPT_CHAT_LOGON, vbox2);
 
@@ -1776,8 +1814,6 @@
 	gtk_option_menu_set_history(GTK_OPTION_MENU(omenu), g_slist_index(away_messages, default_away));
 }
 
-
-
 static void away_page()
 {
 	GtkWidget *parent;
@@ -2622,6 +2658,20 @@
 	if (option == OPT_CONVO_CHECK_SPELLING)
 		toggle_spellchk();
 
+	if (option == OPT_CONVO_COMBINE) {
+		/* (OPT_IM_SIDE_TAB | OPT_IM_BR_TAB) == (OPT_CHAT_SIDE_TAB | OPT_CHAT_BR_TAB) */
+		if (current_is_im) {
+			int set = im_options & (OPT_IM_SIDE_TAB | OPT_IM_BR_TAB);
+			chat_options &= ~(OPT_CHAT_SIDE_TAB | OPT_CHAT_BR_TAB);
+			chat_options |= set;
+		} else {
+			int set = chat_options & (OPT_IM_SIDE_TAB | OPT_IM_BR_TAB);
+			im_options &= ~(OPT_CHAT_SIDE_TAB | OPT_CHAT_BR_TAB);
+			im_options |= set;
+		}
+		convo_tabize();
+	}
+
 	save_prefs();
 }
 
@@ -2630,7 +2680,7 @@
 	im_options ^= option;
 
 	if (option == OPT_IM_ONE_WINDOW)
-		tabize();
+		im_tabize();
 
 	if (option == OPT_IM_HIDE_ICONS)
 		set_hide_icons();
--- a/src/prpl.c	Tue Dec 04 05:38:53 2001 +0000
+++ b/src/prpl.c	Tue Dec 04 07:53:55 2001 +0000
@@ -612,7 +612,7 @@
 	}
 
 	if (!P) {
-		GtkWidget *no = gtk_label_new(_("You do not currently have any plugins loaded"
+		GtkWidget *no = gtk_label_new(_("You do not currently have any protocols available"
 						" that are able to register new accounts."));
 		gtk_box_pack_start(GTK_BOX(reg_area), no, FALSE, FALSE, 5);
 		gtk_widget_show(no);
@@ -621,6 +621,18 @@
 
 		return;
 	}
+
+	gtk_widget_set_sensitive(reg_reg, TRUE);
+
+	while (P) {	/* we can safely ignore all the previous ones */
+		struct prpl *p = P->data;
+		P = P->next;
+
+		if (!p->register_user)
+			continue;
+
+		/* do stuff */
+	}
 }
 
 void register_dialog()
--- a/src/ui.h	Tue Dec 04 05:38:53 2001 +0000
+++ b/src/ui.h	Tue Dec 04 07:53:55 2001 +0000
@@ -255,15 +255,13 @@
 extern GtkWidget *blist;
 
 /* Globals in buddy_chat.c */
-/* it is very important that you don't use this for anything.
- * its sole purpose is to allow all group chats to be in one
- * window. use struct gaim_connection's buddy_chats instead. */
-extern GList *chats;
-/* these are ok to use */
+extern GList *chats;	/* list of all chats (only use for tabbing!) */
 extern GtkWidget *all_chats;
-extern GtkWidget *chat_notebook;
 extern GtkWidget *joinchat;
 
+/* Globals in conversation.c */
+extern GtkWidget *all_convos;
+
 /* Globals in dialog.c */
 extern char fontface[128];
 extern char fontxfld[256];
@@ -370,8 +368,9 @@
 extern void toggle_smileys();
 extern void toggle_timestamps();
 extern void update_pixmaps();
-extern void tabize();
+extern void im_tabize();
 extern void chat_tabize();
+extern void convo_tabize();
 extern void update_convo_color();
 extern void update_convo_font();
 extern void set_hide_icons();