changeset 2205:cff4fbe01c7b

[gaim-migrate @ 2215] eric@blue:~/gaim/app/src/protocols $ cat gtk for i in icq irc jabber msn napster oscar toc yahoo zephyr do echo -n $i: grep -i g\[td\]k $i/*.c | wc -l done eric@blue:~/gaim/app/src/protocols $ ./gtk icq: 13 irc: 0 jabber: 59 msn: 0 napster: 106 oscar: 13 toc: 25 yahoo: 15 zephyr: 2 committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Fri, 31 Aug 2001 20:36:11 +0000
parents 5014b802eb41
children e2174cd3be6a
files TODO src/buddy_chat.c src/gaim.h src/multi.h src/protocols/irc/irc.c src/protocols/jabber/jabber.c src/protocols/napster/napster.c src/protocols/oscar/oscar.c src/protocols/toc/toc.c src/protocols/yahoo/yay.c src/protocols/zephyr/zephyr.c src/prpl.h src/server.c
diffstat 13 files changed, 296 insertions(+), 287 deletions(-) [+]
line wrap: on
line diff
--- a/TODO	Fri Aug 31 18:09:27 2001 +0000
+++ b/TODO	Fri Aug 31 20:36:11 2001 +0000
@@ -4,7 +4,6 @@
 	GPG Encryption of messages
 	Better way of showing away state - and possibly in main window
 	Moving GTK/GDK and related things out of the prpls
-		All: draw_join_chat (haven't thought about this yet)
 		ICQ and Yahoo: checkbox in convo window (haven't though about it)
 		Jabber: user registration (this is buggy anyway and should probably
 		        just be removed?)
--- a/src/buddy_chat.c	Fri Aug 31 18:09:27 2001 +0000
+++ b/src/buddy_chat.c	Fri Aug 31 20:36:11 2001 +0000
@@ -41,11 +41,11 @@
 
 GtkWidget *joinchat;
 static struct gaim_connection *joinchatgc;
-static GtkWidget *entry;
 static GtkWidget *invite;
 static GtkWidget *inviteentry;
 static GtkWidget *invitemess;
 static GtkWidget *jc_vbox = NULL;
+static GList *chatentries = NULL;
 extern int state_lock;
 
 GList *chats = NULL;
@@ -53,16 +53,6 @@
 GtkWidget *chat_notebook = NULL;
 
 
-static void destroy_prev_jc()
-{
-	if (!jc_vbox)
-		return;
-
-	while (GTK_BOX(jc_vbox)->children)
-		gtk_container_remove(GTK_CONTAINER(jc_vbox),
-				     ((GtkBoxChild *)GTK_BOX(jc_vbox)->children->data)->widget);
-}
-
 static void destroy_join_chat()
 {
 	if (joinchat)
@@ -81,47 +71,94 @@
 void do_join_chat()
 {
 	if (joinchat) {
-		if (joinchatgc->prpl->draw_join_chat)
-			serv_join_chat(joinchatgc, 0, NULL);
-		else
-			serv_join_chat(joinchatgc, 0, gtk_entry_get_text(GTK_ENTRY(entry)));
+		GList *data = NULL;
+		GList *tmp = chatentries;
+		int *ival;
+		char *sval;
+		while (tmp) {
+			if (gtk_object_get_user_data(tmp->data)) {
+				ival = g_new0(int, 1);
+				*ival = gtk_spin_button_get_value_as_int(tmp->data);
+				data = g_list_append(data, ival);
+			} else {
+				sval = g_strdup(gtk_entry_get_text(tmp->data));
+				data = g_list_append(data, sval);
+			}
+			tmp = tmp->next;
+		}
+		serv_join_chat(joinchatgc, data);
+
+		tmp = data;
+		while (tmp) {
+			g_free(tmp->data);
+			tmp = tmp->next;
+		}
+		g_list_free(data);
+
 		gtk_widget_destroy(joinchat);
+		if (chatentries)
+			g_list_free(chatentries);
+		chatentries = NULL;
 	}
 	joinchat = NULL;
 }
 
-static void default_draw_join_chat(struct gaim_connection *gc, GtkWidget *fbox) {
-	GtkWidget *label;
-	GtkWidget *rowbox;
-
-	if (!joinchat || !fbox)
-		return;
-	
-	rowbox = gtk_hbox_new(FALSE, 5);
-	gtk_box_pack_start(GTK_BOX(fbox), rowbox, TRUE, TRUE, 0);
-	gtk_widget_show(rowbox);
-
-	label = gtk_label_new(_("Join what group:"));
-	gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0);
-	gtk_widget_show(label);
-
-	entry = gtk_entry_new();
-	gtk_box_pack_start(GTK_BOX(rowbox), entry, TRUE, TRUE, 0);
-	gtk_widget_grab_focus(entry);
-	gtk_signal_connect(GTK_OBJECT(entry), "activate", GTK_SIGNAL_FUNC(do_join_chat), NULL);
-	gtk_widget_show(entry);
-}
-
 static void rebuild_jc()
 {
+	GList *list, *tmp;
+	struct proto_chat_entry *pce;
+
 	if (!joinchatgc)
 		return;
 
-	destroy_prev_jc();
-	if (joinchatgc->prpl->draw_join_chat)
-		(*joinchatgc->prpl->draw_join_chat)(joinchatgc, jc_vbox);
-	else
-		default_draw_join_chat(joinchatgc, jc_vbox);
+	while (GTK_BOX(jc_vbox)->children)
+		gtk_container_remove(GTK_CONTAINER(jc_vbox),
+				     ((GtkBoxChild *)GTK_BOX(jc_vbox)->children->data)->widget);
+	if (chatentries)
+		g_list_free(chatentries);
+	chatentries = NULL;
+
+	tmp = list = (*joinchatgc->prpl->chat_info)(joinchatgc);
+	while (list) {
+		GtkWidget *label;
+		GtkWidget *rowbox;
+		pce = list->data;
+
+		rowbox = gtk_hbox_new(FALSE, 5);
+		gtk_box_pack_start(GTK_BOX(jc_vbox), rowbox, TRUE, TRUE, 0);
+		gtk_widget_show(rowbox);
+
+		label = gtk_label_new(pce->label);
+		gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0);
+		gtk_widget_show(label);
+
+		if (pce->is_int) {
+			GtkObject *adjust;
+			GtkWidget *spin;
+			adjust = gtk_adjustment_new(pce->min, pce->min, pce->max, 1, 10, 10);
+			spin = gtk_spin_button_new(GTK_ADJUSTMENT(adjust), 1, 0);
+			gtk_object_set_user_data(GTK_OBJECT(spin), (void *)1);
+			chatentries = g_list_append(chatentries, spin);
+			gtk_widget_set_usize(spin, 50, -1);
+			gtk_box_pack_start(GTK_BOX(rowbox), spin, FALSE, FALSE, 0);
+			gtk_widget_show(spin);
+		} else {
+			GtkWidget *entry;
+			entry = gtk_entry_new();
+			chatentries = g_list_append(chatentries, entry);
+			gtk_box_pack_start(GTK_BOX(rowbox), entry, TRUE, TRUE, 0);
+			if (pce->def)
+				gtk_entry_set_text(GTK_ENTRY(entry), pce->def);
+			gtk_widget_grab_focus(entry);
+			gtk_signal_connect(GTK_OBJECT(entry), "activate",
+					   GTK_SIGNAL_FUNC(do_join_chat), NULL);
+			gtk_widget_show(entry);
+		}
+
+		g_free(pce);
+		list = list->next;
+	}
+	g_list_free(tmp);
 }
 
 static void joinchat_choose(GtkWidget *w, struct gaim_connection *g)
--- a/src/gaim.h	Fri Aug 31 18:09:27 2001 +0000
+++ b/src/gaim.h	Fri Aug 31 20:36:11 2001 +0000
@@ -678,8 +678,7 @@
 extern void serv_warn(struct gaim_connection *, char *, int);
 extern void serv_set_dir(struct gaim_connection *, char *, char *, char *, char *, char *, char *, char *, int);
 extern void serv_dir_search(struct gaim_connection *, char *, char *, char *, char *, char *, char *, char *, char *);
-extern void serv_accept_chat(struct gaim_connection *, int);
-extern void serv_join_chat(struct gaim_connection *, int, char *);
+extern void serv_join_chat(struct gaim_connection *, GList *);
 extern void serv_chat_invite(struct gaim_connection *, int, char *, char *);
 extern void serv_chat_leave(struct gaim_connection *, int);
 extern void serv_chat_whisper(struct gaim_connection *, int, char *, char *);
@@ -691,7 +690,7 @@
 extern void serv_got_update(struct gaim_connection *, char *, int, int, time_t, time_t, int, gushort);
 extern void serv_got_im(struct gaim_connection *, char *, char *, int, time_t);
 extern void serv_got_eviled(struct gaim_connection *, char *, int);
-extern void serv_got_chat_invite(struct gaim_connection *, char *, int, char *, char *);
+extern void serv_got_chat_invite(struct gaim_connection *, char *, char *, char *, GList *);
 extern struct conversation *serv_got_joined_chat(struct gaim_connection *, int, char *);
 extern void serv_got_chat_left(struct gaim_connection *, int);
 extern void serv_got_chat_in(struct gaim_connection *, int, char *, int, char *, time_t);
--- a/src/multi.h	Fri Aug 31 18:09:27 2001 +0000
+++ b/src/multi.h	Fri Aug 31 20:36:11 2001 +0000
@@ -96,6 +96,7 @@
 
 struct proto_chat_entry {
 	char *label;
+	char *def;
 	gboolean is_int;
 	int min;
 	int max;
--- a/src/protocols/irc/irc.c	Fri Aug 31 18:09:27 2001 +0000
+++ b/src/protocols/irc/irc.c	Fri Aug 31 20:36:11 2001 +0000
@@ -76,10 +76,28 @@
 
 static void irc_get_info(struct gaim_connection *gc, char *who);
 
-static void irc_join_chat(struct gaim_connection *gc, int id, char *name)
+static GList *irc_chat_info(struct gaim_connection *gc)
+{
+	GList *m = NULL;
+	struct proto_chat_entry *pce;
+
+	pce = g_new0(struct proto_chat_entry, 1);
+	pce->label = _("Room:");
+	m = g_list_append(m, pce);
+
+	return m;
+}
+
+static void irc_join_chat(struct gaim_connection *gc, GList *data)
 {
 	struct irc_data *idata = (struct irc_data *)gc->proto_data;
-	gchar *buf = (gchar *) g_malloc(IRC_BUF_LEN + 1);
+	gchar *buf, *name;
+
+	if (!data)
+		return;
+	name = data->data;
+	
+	buf = (gchar *) g_malloc(IRC_BUF_LEN + 1);
 
 	g_snprintf(buf, IRC_BUF_LEN, "JOIN %s\n", name);
 	write(idata->fd, buf, strlen(buf));
@@ -423,12 +441,14 @@
 		else if (!g_strncasecmp(message, "/join ", 6) && (strlen(message) > 6)) {
 
 			gchar *temp = (gchar *) g_malloc(IRC_BUF_LEN + 1);
+			GList *m = g_list_append(NULL, temp);
 
 			strcpy(temp, message + 6);
 
 
-			irc_join_chat(gc, 0, temp);
+			irc_join_chat(gc, m);
 			g_free(temp);
+			g_list_free(m);
 			is_command = TRUE;
 			return 0;
 		}
@@ -2074,6 +2094,7 @@
 	ret->login = irc_login;
 	ret->close = irc_close;
 	ret->send_im = irc_send_im;
+	ret->chat_info = irc_chat_info;
 	ret->join_chat = irc_join_chat;
 	ret->chat_leave = irc_chat_leave;
 	ret->chat_send = irc_chat_send;
--- a/src/protocols/jabber/jabber.c	Fri Aug 31 18:09:27 2001 +0000
+++ b/src/protocols/jabber/jabber.c	Fri Aug 31 20:36:11 2001 +0000
@@ -573,10 +573,17 @@
 
 		if (type && !strcasecmp(type, "jabber:x:conference")) {
 			char *room;
+			GList *m = NULL;
+			char **data;
 
 			room = xmlnode_get_attrib(xmlns, "jid");
+			data = g_strsplit(room, "@", 2);
+			m = g_list_append(m, g_strdup(data[0]));
+			m = g_list_append(m, g_strdup(data[1]));
+			m = g_list_append(m, g_strdup(j->user->user));
+			g_strfreev(data);
 
-			serv_got_chat_invite(GJ_GC(j), room, 0, from, msg);
+			serv_got_chat_invite(GJ_GC(j), room, from, msg, m);
 		} else if (msg) { /* whisper */
 			struct jabber_chat *jc;
 			g_snprintf(m, sizeof(m), "%s", msg);
@@ -1326,7 +1333,31 @@
 	}
 }
 
-static void jabber_join_chat(struct gaim_connection *gc, int exch, char *name)
+static GList *jabber_chat_info(struct gaim_connection *gc)
+{
+	gjconn j = ((struct jabber_data *)gc->proto_data)->jc;
+
+	GList *m = NULL;
+	struct proto_chat_entry *pce;
+
+	pce = g_new0(struct proto_chat_entry, 1);
+	pce->label = _("Room:");
+	m = g_list_append(m, pce);
+
+	pce = g_new0(struct proto_chat_entry, 1);
+	pce->label = _("Server:");
+	pce->def = DEFAULT_GROUPCHAT;
+	m = g_list_append(m, pce);
+
+	pce = g_new0(struct proto_chat_entry, 1);
+	pce->label = _("Handle:");
+	pce->def = j->user->user;
+	m = g_list_append(m, pce);
+
+	return m;
+}
+
+static void jabber_join_chat(struct gaim_connection *gc, GList *data)
 {
 	xmlnode x;
 	char *realwho;
@@ -1334,11 +1365,12 @@
 	GSList *pc = ((struct jabber_data *)gc->proto_data)->pending_chats;
 	struct jabber_chat *jc;
 
-	if (!name)
+	if (!data || !data->next || !data->next->next)
 		return;
 
 	jc = g_new0(struct jabber_chat, 1);
-	realwho = create_valid_jid(name, DEFAULT_GROUPCHAT, j->user->user);
+	realwho = create_valid_jid(data->data, data->next->data,
+			data->next->next->data);
 	jc->Jid = jid_new(j->p, realwho);
 	jc->gc = gc;
 	debug_printf("%s\n", realwho);
@@ -1355,10 +1387,10 @@
 {
 	xmlnode x, y;
 	GSList *bcs = gc->buddy_chats;
-	struct conversation *b;
+	struct conversation *b = NULL;
 	struct jabber_data *jd = gc->proto_data;
 	gjconn j = jd->jc;
-	struct jabber_chat *jc;
+	struct jabber_chat *jc = NULL;
 	char *realwho, *subject;
 
 	if (!name)
@@ -1412,10 +1444,10 @@
 static void jabber_chat_leave(struct gaim_connection *gc, int id)
 {
 	GSList *bcs = gc->buddy_chats;
-	struct conversation *b;
+	struct conversation *b = NULL;
 	struct jabber_data *jd = gc->proto_data;
 	gjconn j = jd->jc;
-	struct jabber_chat *jc;
+	struct jabber_chat *jc = NULL;
 	char *realwho;
 	xmlnode x;
 
@@ -1450,10 +1482,10 @@
 static int jabber_chat_send(struct gaim_connection *gc, int id, char *message)
 {
 	GSList *bcs = gc->buddy_chats;
-	struct conversation *b;
+	struct conversation *b = NULL;
 	struct jabber_data *jd = gc->proto_data;
 	xmlnode x, y;
-	struct jabber_chat *jc;
+	struct jabber_chat *jc = NULL;
 	char *chatname;
 
 	while (bcs) {
@@ -1497,10 +1529,10 @@
 static void jabber_chat_set_topic(struct gaim_connection *gc, int id, char *topic)
 {
 	GSList *bcs = gc->buddy_chats;
-	struct conversation *b;
+	struct conversation *b = NULL;
 	struct jabber_data *jd = gc->proto_data;
 	xmlnode x, y;
-	struct jabber_chat *jc;
+	struct jabber_chat *jc = NULL;
 	char *chatname;
 	char buf[8192];
 
@@ -1547,10 +1579,10 @@
 static void jabber_chat_whisper(struct gaim_connection *gc, int id, char *who, char *message)
 {
 	GSList *bcs = gc->buddy_chats;
-	struct conversation *b;
+	struct conversation *b = NULL;
 	struct jabber_data *jd = gc->proto_data;
 	xmlnode x, y;
-	struct jabber_chat *jc;
+	struct jabber_chat *jc = NULL;
 	char *chatname;
 
 	while (bcs) {
@@ -2005,7 +2037,7 @@
 	ret->rem_deny = NULL;
 	ret->set_permit_deny = NULL;
 	ret->warn = NULL;
-	ret->accept_chat = NULL;
+	ret->chat_info = jabber_chat_info;
 	ret->join_chat = jabber_join_chat;
 	ret->chat_invite = jabber_chat_invite;
 	ret->chat_leave = jabber_chat_leave;
--- a/src/protocols/napster/napster.c	Fri Aug 31 18:09:27 2001 +0000
+++ b/src/protocols/napster/napster.c	Fri Aug 31 20:36:11 2001 +0000
@@ -921,9 +921,27 @@
 	}
 }
 
-static void nap_join_chat(struct gaim_connection *gc, int id, char *name)
+static GList *nap_chat_info(struct gaim_connection *gc)
+{
+	GList *m = NULL;
+	struct proto_chat_entry *pce;
+
+	pce = g_new0(struct proto_chat_entry, 1);
+	pce->label = _("Join what group:");
+	m = g_list_append(m, pce);
+
+	return m;
+}
+
+static void nap_join_chat(struct gaim_connection *gc, GList *data)
 {
 	gchar buf[NAP_BUF_LEN];
+	char *name;
+
+	if (!data)
+		return;
+
+	name = data->data;
 
 	/* Make sure the name has a # preceeding it */
 	if (name[0] != '#') 
@@ -1200,7 +1218,7 @@
 	ret->add_deny = NULL;
 	ret->rem_deny = NULL;
 	ret->warn = NULL;
-	ret->accept_chat = NULL;
+	ret->chat_info = nap_chat_info;
 	ret->join_chat = nap_join_chat;
 	ret->chat_invite = NULL;
 	ret->chat_leave = nap_chat_leave;
--- a/src/protocols/oscar/oscar.c	Fri Aug 31 18:09:27 2001 +0000
+++ b/src/protocols/oscar/oscar.c	Fri Aug 31 20:36:11 2001 +0000
@@ -59,9 +59,6 @@
 		       AIM_CAPS_BUDDYICON |
 		       AIM_CAPS_IMIMAGE;
 
-static GtkWidget *join_chat_spin = NULL;
-static GtkWidget *join_chat_entry = NULL;
-
 struct oscar_data {
 	struct aim_session_t *sess;
 	struct aim_conn_t *conn;
@@ -1331,11 +1328,16 @@
 		va_end(ap);
 		if (args->reqclass & AIM_CAPS_CHAT) {
 			char *name = extract_name(args->info.chat.roominfo.name);
+			int *exch = g_new0(int, 1);
+			GList *m = NULL;
+			m = g_list_append(m, g_strdup(name ? name : args->info.chat.roominfo.name));
+			*exch = args->info.chat.roominfo.exchange;
+			m = g_list_append(m, exch);
 			serv_got_chat_invite(gc,
 					     name ? name : args->info.chat.roominfo.name,
-					     args->info.chat.roominfo.exchange,
 					     userinfo->sn,
-					     args->info.chat.msg);
+					     args->info.chat.msg,
+					     m);
 			if (name)
 				g_free(name);
 		} else if (args->reqclass & AIM_CAPS_SENDFILE) {
@@ -2195,71 +2197,49 @@
 	aim_remove_buddy(odata->sess, odata->conn, name);
 }
 
-static void oscar_join_chat(struct gaim_connection *g, int exchange, char *name) {
+static GList *oscar_chat_info(struct gaim_connection *gc) {
+	GList *m = NULL;
+	struct proto_chat_entry *pce;
+
+	pce = g_new0(struct proto_chat_entry, 1);
+	pce->label = _("Join what group:");
+	m = g_list_append(m, pce);
+
+	pce = g_new0(struct proto_chat_entry, 1);
+	pce->label = _("Exchange:");
+	pce->is_int = TRUE;
+	pce->min = 4;
+	pce->max = 20;
+	m = g_list_append(m, pce);
+
+	return m;
+}
+
+static void oscar_join_chat(struct gaim_connection *g, GList *data) {
 	struct oscar_data *odata = (struct oscar_data *)g->proto_data;
 	struct aim_conn_t *cur = NULL;
-	if (!name) {
-		if (!join_chat_entry || !join_chat_spin)
-			return;
-		name = gtk_entry_get_text(GTK_ENTRY(join_chat_entry));
-		exchange = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(join_chat_spin));
-		if (!name || !strlen(name))
-			return;
-	}
+	char *name;
+	int *exchange;
+
+	if (!data || !data->next)
+		return;
+
+	name = data->data;
+	exchange = data->next->data;
+
 	debug_printf("Attempting to join chat room %s.\n", name);
 	if ((cur = aim_getconn_type(odata->sess, AIM_CONN_TYPE_CHATNAV))) {
 		debug_printf("chatnav exists, creating room\n");
-		aim_chatnav_createroom(odata->sess, cur, name, exchange);
+		aim_chatnav_createroom(odata->sess, cur, name, *exchange);
 	} else {
 		/* this gets tricky */
 		debug_printf("chatnav does not exist, opening chatnav\n");
-		odata->create_exchange = exchange;
+		odata->create_exchange = *exchange;
 		odata->create_name = g_strdup(name);
 		aim_bos_reqservice(odata->sess, odata->conn, AIM_CONN_TYPE_CHATNAV);
 	}
 }
 
-static void des_jc()
-{
-	join_chat_entry = NULL;
-	join_chat_spin = NULL;
-}
-
-static void oscar_draw_join_chat(struct gaim_connection *gc, GtkWidget *fbox) {
-	GtkWidget *label;
-	GtkWidget *rowbox;
-	GtkObject *adjust;
-
-	rowbox = gtk_hbox_new(FALSE, 5);
-	gtk_box_pack_start(GTK_BOX(fbox), rowbox, TRUE, TRUE, 0);
-	gtk_widget_show(rowbox);
-
-	label = gtk_label_new(_("Join what group:"));
-	gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0);
-	gtk_signal_connect(GTK_OBJECT(label), "destroy", GTK_SIGNAL_FUNC(des_jc), NULL);
-	gtk_widget_show(label);
-
-	join_chat_entry = gtk_entry_new();
-	gtk_box_pack_start(GTK_BOX(rowbox), join_chat_entry, TRUE, TRUE, 0);
-	gtk_widget_grab_focus(join_chat_entry);
-	gtk_signal_connect(GTK_OBJECT(join_chat_entry), "activate", GTK_SIGNAL_FUNC(do_join_chat), NULL);
-	gtk_widget_show(join_chat_entry);
-
-	rowbox = gtk_hbox_new(FALSE, 5);
-	gtk_box_pack_start(GTK_BOX(fbox), rowbox, TRUE, TRUE, 0);
-	gtk_widget_show(rowbox);
-
-	label = gtk_label_new(_("Exchange:"));
-	gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0);
-	gtk_widget_show(label);
-	
-	adjust = gtk_adjustment_new(4, 4, 20, 1, 10, 10);
-	join_chat_spin = gtk_spin_button_new(GTK_ADJUSTMENT(adjust), 1, 0);
-	gtk_widget_set_usize(join_chat_spin, 50, -1);
-	gtk_box_pack_start(GTK_BOX(rowbox), join_chat_spin, FALSE, FALSE, 0);
-	gtk_widget_show(join_chat_spin);
-}
-
 static void oscar_chat_invite(struct gaim_connection *g, int id, char *message, char *name) {
 	struct oscar_data *odata = (struct oscar_data *)g->proto_data;
 	struct chat_connection *ccon = find_oscar_chat(g, id);
@@ -2758,9 +2738,8 @@
 	ret->rem_deny = oscar_rem_deny;
 	ret->set_permit_deny = oscar_set_permit_deny;
 	ret->warn = oscar_warn;
-	ret->accept_chat = NULL; /* oscar doesn't have accept, it just joins */
+	ret->chat_info = oscar_chat_info;
 	ret->join_chat = oscar_join_chat;
-	ret->draw_join_chat = oscar_draw_join_chat;
 	ret->chat_invite = oscar_chat_invite;
 	ret->chat_leave = oscar_chat_leave;
 	ret->chat_whisper = NULL;
--- a/src/protocols/toc/toc.c	Fri Aug 31 18:09:27 2001 +0000
+++ b/src/protocols/toc/toc.c	Fri Aug 31 20:36:11 2001 +0000
@@ -123,9 +123,6 @@
 #define USEROPT_AUTH      0
 #define USEROPT_AUTHPORT  1
 
-static GtkWidget *join_chat_spin = NULL;
-static GtkWidget *join_chat_entry = NULL;
-
 static void toc_login_callback(gpointer, gint, GaimInputCondition);
 static void toc_callback(gpointer, gint, GaimInputCondition);
 static unsigned char *roast_password(char *);
@@ -546,14 +543,14 @@
 				remove_chat_buddy(b, buddy);
 	} else if (!strcasecmp(c, "CHAT_INVITE")) {
 		char *name, *who, *message;
-		int id;
+		int *id = g_new0(int, 1);
 
 		name = strtok(NULL, ":");
-		sscanf(strtok(NULL, ":"), "%d", &id);
+		sscanf(strtok(NULL, ":"), "%d", id);
 		who = strtok(NULL, ":");
 		message = strtok(NULL, ":");
 
-		serv_got_chat_invite(gc, name, id, who, message);
+		serv_got_chat_invite(gc, name, who, message, g_list_append(NULL, id));
 	} else if (!strcasecmp(c, "CHAT_LEFT")) {
 		GSList *bcs = gc->buddy_chats;
 		struct conversation *b = NULL;
@@ -882,27 +879,44 @@
 	sflap_send(g, send, -1, TYPE_DATA);
 }
 
-static void toc_accept_chat(struct gaim_connection *g, int i)
+static GList *toc_chat_info(struct gaim_connection *gc)
 {
-	char buf[BUF_LEN * 2];
-	g_snprintf(buf, 255, "toc_chat_accept %d", i);
-	sflap_send(g, buf, -1, TYPE_DATA);
+	GList *m = NULL;
+	struct proto_chat_entry *pce;
+
+	pce = g_new0(struct proto_chat_entry, 1);
+	pce->label = _("Join what group:");
+	m = g_list_append(m, pce);
+
+	pce = g_new0(struct proto_chat_entry, 1);
+	pce->label = _("Exchange:");
+	pce->is_int = TRUE;
+	pce->min = 4;
+	pce->max = 20;
+	m = g_list_append(m, pce);
+
+	return m;
 }
 
-static void toc_join_chat(struct gaim_connection *g, int exchange, char *name)
+static void toc_join_chat(struct gaim_connection *g, GList *data)
 {
 	char buf[BUF_LONG];
-	if (!name) {
-		const char *nm;
-		if (!join_chat_entry || !join_chat_spin)
-			return;
-		nm = gtk_entry_get_text(GTK_ENTRY(join_chat_entry));
-		exchange = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(join_chat_spin));
-		if (!nm || !strlen(nm))
-			return;
-		g_snprintf(buf, sizeof(buf) / 2, "toc_chat_join %d \"%s\"", exchange, nm);
-	} else
-		g_snprintf(buf, sizeof(buf) / 2, "toc_chat_join %d \"%s\"", exchange, name);
+	int *exchange;
+	char *name;
+	int *i;
+
+	if (!data)
+		return;
+
+	if (!data->next) {
+		i = data->data;
+		g_snprintf(buf, 255, "toc_chat_accept %d", *i);
+	} else {
+		name = data->data;
+		exchange = data->next->data;
+		g_snprintf(buf, sizeof(buf) / 2, "toc_chat_join %d \"%s\"", *exchange, name);
+	}
+
 	sflap_send(g, buf, -1, TYPE_DATA);
 }
 
@@ -976,47 +990,6 @@
 	return NULL;
 }
 
-static void des_jc()
-{
-	join_chat_entry = NULL;
-	join_chat_spin = NULL;
-}
-
-static void toc_draw_join_chat(struct gaim_connection *gc, GtkWidget *fbox) {
-	GtkWidget *label;
-	GtkWidget *rowbox;
-	GtkObject *adjust;
-
-	rowbox = gtk_hbox_new(FALSE, 5);
-	gtk_box_pack_start(GTK_BOX(fbox), rowbox, TRUE, TRUE, 0);
-	gtk_widget_show(rowbox);
-
-	label = gtk_label_new(_("Join what group:"));
-	gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0);
-	gtk_signal_connect(GTK_OBJECT(label), "destroy", GTK_SIGNAL_FUNC(des_jc), NULL);
-	gtk_widget_show(label);
-
-	join_chat_entry = gtk_entry_new();
-	gtk_box_pack_start(GTK_BOX(rowbox), join_chat_entry, TRUE, TRUE, 0);
-	gtk_widget_grab_focus(join_chat_entry);
-	gtk_signal_connect(GTK_OBJECT(join_chat_entry), "activate", GTK_SIGNAL_FUNC(do_join_chat), NULL);
-	gtk_widget_show(join_chat_entry);
-
-	rowbox = gtk_hbox_new(FALSE, 5);
-	gtk_box_pack_start(GTK_BOX(fbox), rowbox, TRUE, TRUE, 0);
-	gtk_widget_show(rowbox);
-
-	label = gtk_label_new(_("Community:"));
-	gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0);
-	gtk_widget_show(label);
-	
-	adjust = gtk_adjustment_new(4, 4, 20, 1, 10, 10);
-	join_chat_spin = gtk_spin_button_new(GTK_ADJUSTMENT(adjust), 1, 0);
-	gtk_widget_set_usize(join_chat_spin, 50, -1);
-	gtk_box_pack_start(GTK_BOX(rowbox), join_chat_spin, FALSE, FALSE, 0);
-	gtk_widget_show(join_chat_spin);
-}
-
 static GList *toc_buddy_menu(struct gaim_connection *gc, char *who)
 {
 	GList *m = NULL;
@@ -1236,8 +1209,7 @@
 	ret->rem_deny = toc_rem_deny;
 	ret->set_permit_deny = toc_set_permit_deny;
 	ret->warn = toc_warn;
-	ret->draw_join_chat = toc_draw_join_chat;
-	ret->accept_chat = toc_accept_chat;
+	ret->chat_info = toc_chat_info;
 	ret->join_chat = toc_join_chat;
 	ret->chat_invite = toc_chat_invite;
 	ret->chat_leave = toc_chat_leave;
--- a/src/protocols/yahoo/yay.c	Fri Aug 31 18:09:27 2001 +0000
+++ b/src/protocols/yahoo/yay.c	Fri Aug 31 20:36:11 2001 +0000
@@ -774,12 +774,6 @@
 	ret->rem_deny = NULL;
 	ret->set_permit_deny = NULL;
 	ret->warn = NULL;
-	ret->accept_chat = NULL;
-	ret->join_chat = NULL;
-	ret->chat_invite = NULL;
-	ret->chat_leave = NULL;
-	ret->chat_whisper = NULL;
-	ret->chat_send = NULL;
 	ret->keepalive = yahoo_keepalive;
 
 	my_protocol = ret;
--- a/src/protocols/zephyr/zephyr.c	Fri Aug 31 18:09:27 2001 +0000
+++ b/src/protocols/zephyr/zephyr.c	Fri Aug 31 20:36:11 2001 +0000
@@ -27,7 +27,6 @@
 #include "config.h"
 #endif
 
-#include <gtk/gtk.h>
 #include <string.h>
 #include <stdlib.h>
 #include <errno.h>
@@ -88,9 +87,6 @@
 static GList *pending_zloc_names = NULL;
 static GSList *subscrips = NULL;
 static int last_id = 0;
-static GtkWidget *class_entry;
-static GtkWidget *inst_entry;
-static GtkWidget *recip_entry;
 
 /* just for debugging
 static void handle_unknown(ZNotice_t notice)
@@ -819,80 +815,43 @@
 	return m;
 }
 
-static void zephyr_draw_jc(struct gaim_connection *gc, GtkWidget *vbox) {
-	GtkWidget *label;
-	GtkWidget *rowbox;
-	
-	rowbox = gtk_hbox_new(FALSE, 5);
-	gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0);
+static GList *zephyr_chat_info(struct gaim_connection *gc) {
+	GList *m = NULL;
+	struct proto_chat_entry *pce;
 
-	label = gtk_label_new(_("Class:"));
-	gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 5);
-	gtk_widget_show(label);
-	
-	class_entry = gtk_entry_new();
-	gtk_box_pack_end(GTK_BOX(rowbox), class_entry, FALSE, FALSE, 5);
-	gtk_widget_show(class_entry);
-	
-	gtk_widget_show(rowbox);
-
-	rowbox = gtk_hbox_new(FALSE, 5);
-	gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0);
+	pce = g_new0(struct proto_chat_entry, 1);
+	pce->label = _("Class:");
+	m = g_list_append(m, NULL);
 
-	label = gtk_label_new(_("Instance:"));
-	gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 5);
-	gtk_widget_show(label);
-	
-	inst_entry = gtk_entry_new();
-	gtk_box_pack_end(GTK_BOX(rowbox), inst_entry, FALSE, FALSE, 5);
-	gtk_widget_show(inst_entry);
-
-	gtk_widget_show(rowbox);
+	pce = g_new0(struct proto_chat_entry, 1);
+	pce->label = _("Instance:");
+	m = g_list_append(m, NULL);
 
-	rowbox = gtk_hbox_new(FALSE, 5);
-	gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0);
+	pce = g_new0(struct proto_chat_entry, 1);
+	pce->label = _("Recipient:");
+	m = g_list_append(m, NULL);
 
-	label = gtk_label_new(_("Recipient:"));
-	gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 5);
-	gtk_widget_show(label);
-	
-	recip_entry = gtk_entry_new();
-	gtk_box_pack_end(GTK_BOX(rowbox), recip_entry, FALSE, FALSE, 5);
-	gtk_widget_show(recip_entry);
-	
-	gtk_widget_show(rowbox);
+	return m;
 }
 
-static void zephyr_join_chat(struct gaim_connection *gc, int id, char *nm)
+static void zephyr_join_chat(struct gaim_connection *gc, GList *data)
 {
 	ZSubscription_t sub;
 	zephyr_triple *zt1, *zt2;
 	const char *classname;
 	const char *instname;
 	const char *recip;
-	char **splitted;
+
+	if (!data || !data->next || !data->next->next)
+		return;
 
-	if (!nm) {
-		splitted = NULL;
-		classname = gtk_entry_get_text(GTK_ENTRY(class_entry));
-		instname = gtk_entry_get_text(GTK_ENTRY(inst_entry));
-		recip = gtk_entry_get_text(GTK_ENTRY(recip_entry));
-		if (!g_strcasecmp(recip, "%me%"))
-			recip = g_getenv("USER");
-	} else {
-		splitted = g_strsplit(nm, ",", 3);
-		if (!splitted[0] || !splitted[1] || !splitted[2]) {
-			g_strfreev(splitted);
-			return;
-		}
-		classname = g_strstrip(splitted[0]);
-		instname = g_strstrip(splitted[1]);
-		recip = g_strstrip(splitted[2]);
-	}
+	classname = data->data;
+	instname = data->next->data;
+	recip = data->next->next->data;
+	if (!g_strcasecmp(recip, "%me%"))
+		recip = g_getenv("USER");
 
 	zt1 = new_triple(classname, instname, recip);
-	if (splitted)
-		g_strfreev(splitted);
 	zt2 = find_sub_by_triple(zt1);
 	if (zt2) {
 		free_triple(zt1);
@@ -942,7 +901,7 @@
 	ret->buddy_menu = zephyr_buddy_menu;
 	ret->away_states = zephyr_away_states;
 	ret->set_away = zephyr_set_away;
-	ret->draw_join_chat = zephyr_draw_jc;
+	ret->chat_info = zephyr_chat_info;
 	ret->join_chat = zephyr_join_chat;
 	ret->chat_send = zephyr_chat_send;
 	ret->chat_leave = zephyr_chat_leave;
--- a/src/prpl.h	Fri Aug 31 18:09:27 2001 +0000
+++ b/src/prpl.h	Fri Aug 31 20:36:11 2001 +0000
@@ -81,6 +81,7 @@
 	/* user_opts returns a GList* of g_malloc'd struct proto_user_opts */
 	GList *(* user_opts)();
 	GList *(* buddy_menu)(struct gaim_connection *, char *);
+	GList *(* chat_info)(struct gaim_connection *);
 
 	/* when UI plugins come, these will have to be reconciled by returning
 	 * structs indicating what kinds of information they want displayed. */
@@ -90,7 +91,6 @@
 	 * their UIs all that often anyway. */
 	void (* draw_new_user)(GtkWidget *);
 	void (* do_new_user)();
-	void (* draw_join_chat)(struct gaim_connection *, GtkWidget *);
 	void (* insert_convo)(struct gaim_connection *, struct conversation *);
 	void (* remove_convo)(struct gaim_connection *, struct conversation *);
 
@@ -130,8 +130,7 @@
 	void (* rem_deny)	(struct gaim_connection *, char *name);
 	void (* set_permit_deny)(struct gaim_connection *);
 	void (* warn)		(struct gaim_connection *, char *who, int anonymous);
-	void (* accept_chat)	(struct gaim_connection *, int id);
-	void (* join_chat)	(struct gaim_connection *, int id, char *name);
+	void (* join_chat)	(struct gaim_connection *, GList *data);
 	void (* chat_invite)	(struct gaim_connection *, int id, char *who, char *message);
 	void (* chat_leave)	(struct gaim_connection *, int id);
 	void (* chat_whisper)	(struct gaim_connection *, int id, char *who, char *message);
--- a/src/server.c	Fri Aug 31 18:09:27 2001 +0000
+++ b/src/server.c	Fri Aug 31 20:36:11 2001 +0000
@@ -286,16 +286,10 @@
 		(*g->prpl->warn)(g, name, anon);
 }
 
-void serv_accept_chat(struct gaim_connection *g, int i)
-{
-	if (g->prpl && g->prpl->accept_chat)
-		(*g->prpl->accept_chat)(g, i);
-}
-
-void serv_join_chat(struct gaim_connection *g, int exchange, char *name)
+void serv_join_chat(struct gaim_connection *g, GList *data)
 {
 	if (g->prpl && g->prpl->join_chat)
-		(*g->prpl->join_chat)(g, exchange, name);
+		(*g->prpl->join_chat)(g, data);
 }
 
 void serv_chat_invite(struct gaim_connection *g, int id, char *message, char *name)
@@ -741,10 +735,15 @@
 
 static void close_invite(GtkWidget *w, GtkWidget *w2)
 {
-	char *str = (char *)gtk_object_get_user_data(GTK_OBJECT(w2));
+	GList *str = gtk_object_get_user_data(GTK_OBJECT(w2));
+	GList *tmp = str;
 
+	while (tmp) {
+		g_free(tmp->data);
+		tmp = tmp->next;
+	}
 	if (str)
-		g_free(str);
+		g_list_free(str);
 
 	gtk_widget_destroy(w2);
 }
@@ -753,26 +752,28 @@
 {
 	struct gaim_connection *g = (struct gaim_connection *)
 					gtk_object_get_user_data(GTK_OBJECT(GTK_DIALOG(w2)->vbox));
-	int id;
-	char *str;
+	GList *str, *tmp;
+
+	str = gtk_object_get_user_data(GTK_OBJECT(w2));
 
-	id = (int)gtk_object_get_user_data(GTK_OBJECT(w));
-	str = (char *)gtk_object_get_user_data(GTK_OBJECT(w2));
+	serv_join_chat(g, str);
+
+	tmp = str;
 
-	if (g->prpl && g->prpl->accept_chat)
-		serv_accept_chat(g, id);
-	else
-		serv_join_chat(g, id, str);
-
+	while (tmp) {
+		/* this is either a g_malloc'd char* or g_malloc'd int* */
+		g_free(tmp->data);
+		tmp = tmp->next;
+	}
 	if (str)
-		g_free(str);
+		g_list_free(str);
 
 	gtk_widget_destroy(w2);
 }
 
 
 
-void serv_got_chat_invite(struct gaim_connection *g, char *name, int id, char *who, char *message)
+void serv_got_chat_invite(struct gaim_connection *g, char *name, char *who, char *message, GList *data)
 {
 	GtkWidget *d;
 	GtkWidget *label;
@@ -806,9 +807,7 @@
 	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(d)->action_area), nobtn, FALSE, FALSE, 5);
 
 	gtk_object_set_user_data(GTK_OBJECT(GTK_DIALOG(d)->vbox), g);
-	if (name)
-		gtk_object_set_user_data(GTK_OBJECT(d), (void *)g_strdup(name));
-	gtk_object_set_user_data(GTK_OBJECT(yesbtn), (void *)id);
+	gtk_object_set_user_data(GTK_OBJECT(d), data);
 
 
 	gtk_window_set_title(GTK_WINDOW(d), "Buddy chat invite");