changeset 472:6a92cd7322cc

[gaim-migrate @ 482] merged chat and IM windows. /me is now in IM, font/color dialogs in chat, and smileys in chat too. also, fixed the GOOD bug. i don't know what kind of crack rob was smoking when he decided O could be eyes. committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Sun, 09 Jul 2000 23:19:21 +0000
parents 4d0b703a094c
children f9bb7761c52b
files ChangeLog TODO src/Makefile.am src/buddy.c src/buddy_chat.c src/conversation.c src/convo.h src/gaim.h src/oscar.c src/server.c src/toc.c
diffstat 11 files changed, 380 insertions(+), 581 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Sun Jul 09 18:06:11 2000 +0000
+++ b/ChangeLog	Sun Jul 09 23:19:21 2000 +0000
@@ -15,6 +15,7 @@
 	* Dialog windows are now prettier
 	* Fixed the LC_ALL compile problem on Solaris boxes 
 	* Fixed PPC and ARM compile problem with oscar.c
+	* /me in IM window; font/color dialogs and smileys in chat window
 
 version 0.9.19 (06/09/2000):
 	* Graphical Smiley Faces
--- a/TODO	Sun Jul 09 18:06:11 2000 +0000
+++ b/TODO	Sun Jul 09 23:19:21 2000 +0000
@@ -1,3 +1,2 @@
 --- STUFF FOR 0.9.20 RELEASE ---
-	Merge Buddy Chat window/IM Window (reduce code size)
 	Icons for buddy list (I forget what this was)
--- a/src/Makefile.am	Sun Jul 09 18:06:11 2000 +0000
+++ b/src/Makefile.am	Sun Jul 09 23:19:21 2000 +0000
@@ -14,4 +14,4 @@
 
 CFLAGS += -DLOCALEDIR=\"$(datadir)/locale\"
 
-EXTRA_DIST = gaim.h proxy.h gnome_applet_mgr.h gtkhtml.h gtkticker.h
+EXTRA_DIST = gaim.h proxy.h gnome_applet_mgr.h gtkhtml.h gtkticker.h convo.h
--- a/src/buddy.c	Sun Jul 09 18:06:11 2000 +0000
+++ b/src/buddy.c	Sun Jul 09 23:19:21 2000 +0000
@@ -1289,7 +1289,7 @@
                         	if (c == NULL)
                                 	c = new_conversation(name);
 
-                        	write_to_conv(c, b->message, WFLAG_SEND);
+                        	write_to_conv(c, b->message, WFLAG_SEND, NULL);
 
                         	escape_text(b->message);
 
@@ -1542,7 +1542,7 @@
                                                    ((display_options & OPT_DISP_SHOW_TIME) ? date() : ""));
 
 
-					write_to_conv(c, tmp, WFLAG_SYSTEM);
+					write_to_conv(c, tmp, WFLAG_SYSTEM, NULL);
 
 				}
 			}
@@ -1682,7 +1682,7 @@
                                                    ((display_options & OPT_DISP_SHOW_TIME) ? date() : ""));
 
 
-					write_to_conv(c, tmp, WFLAG_SYSTEM);
+					write_to_conv(c, tmp, WFLAG_SYSTEM, NULL);
 
 				}
 			}
--- a/src/buddy_chat.c	Sun Jul 09 18:06:11 2000 +0000
+++ b/src/buddy_chat.c	Sun Jul 09 23:19:21 2000 +0000
@@ -28,30 +28,10 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <gtk/gtk.h>
-#include "gaim.h"
 #include "gtkhtml.h"
 #include <gdk/gdkkeysyms.h>
 
-#include "pixmaps/underline.xpm"
-#include "pixmaps/bold.xpm"
-#include "pixmaps/italic.xpm"
-#include "pixmaps/small.xpm"
-#include "pixmaps/normal.xpm"
-#include "pixmaps/big.xpm"
-#include "pixmaps/fontface.xpm"
-#include "pixmaps/palette.xpm"
-#include "pixmaps/link.xpm"
-#include "pixmaps/strike.xpm"
-#include "pixmaps/speaker.xpm"
-#include "pixmaps/wood.xpm"
-#include "pixmaps/join.xpm"
-#include "pixmaps/cancel.xpm"
-
-/*
-#include "pixmaps/smile_happy.xpm"
-#include "pixmaps/smile_sad.xpm"
-#include "pixmaps/smile_wink.xpm"
-*/
+#include "convo.h"
 
 static GtkWidget *joinchat;
 static GtkWidget *entry;
@@ -204,11 +184,16 @@
 }
 
 
-static void do_invite(GtkWidget *w, struct buddy_chat *b)
+static void do_invite(GtkWidget *w, struct conversation *b)
 {
 	char *buddy;
 	char *mess;
 
+	if (!b->is_chat) {
+		debug_print("do_invite: expecting chat, got IM\n");
+		return;
+	}
+
 	buddy = gtk_entry_get_text(GTK_ENTRY(inviteentry));
 	mess = gtk_entry_get_text(GTK_ENTRY(invitemess));
 
@@ -221,7 +206,7 @@
 
 
 
-static void invite_callback(GtkWidget *w, struct buddy_chat *b)
+void invite_callback(GtkWidget *w, struct conversation *b)
 {
 	GtkWidget *cancel;
 	GtkWidget *invite_btn;
@@ -284,7 +269,7 @@
 	gtk_widget_show(invite);
 }
 
-static gboolean meify(char *message) {
+gboolean meify(char *message) {
 	/* read /me-ify : if the message (post-HTML) starts with /me, remove
 	 * the "/me " part of it (including that space) and return TRUE */
 	char *c = message;
@@ -308,13 +293,15 @@
 		return FALSE;
 }
 
-void chat_write(struct buddy_chat *b, char *who, int flag, char *message)
+void chat_write(struct conversation *b, char *who, int flag, char *message)
 {
-        char *buf;
         GList *ignore = b->ignored;
-        char *str;
-        char colour[10];
+	char *str;
 
+	if (!b->is_chat) {
+		debug_print("chat_write: expecting chat, got IM\n");
+		return;
+	}
 
         while(ignore) {
                 if (!strcasecmp(who, ignore->data))
@@ -323,107 +310,28 @@
         }
 
         
-        buf = g_malloc(BUF_LONG);
-        
-        if (flag & WFLAG_WHISPER) {
-		if (meify(message)) {
-			str = g_malloc(64);
-			g_snprintf(str, 62, "***%s", who);
-			strcpy(colour, "#6C2585\0");
+        if (!(flag & WFLAG_WHISPER)) {
+		str = g_strdup(normalize(who));
+		if (!strcasecmp(str, normalize(current_user->username))) {
+			sprintf(debug_buff, "%s %s\n", normalize(who), normalize(current_user->username));
+			debug_print(debug_buff);
+			if (b->makesound && (sound_options & OPT_SOUND_CHAT_SAY))
+				play_sound(SEND);
+			flag |= WFLAG_SEND;
 		} else {
-	                str = g_malloc(64);
-	                g_snprintf(str, 62, "*%s*:", who);
-	                strcpy(colour, "#00ff00\0");
+			if (b->makesound && (sound_options & OPT_SOUND_CHAT_SAY))
+				play_sound(RECEIVE);
+			flag |= WFLAG_RECV;
 		}
-        } else {
-		if (meify(message)) {
-	                str = g_strdup(normalize(who));
-	                if (!strcasecmp(str, normalize(current_user->username))) {
-				if (b->makesound && (sound_options & OPT_SOUND_CHAT_SAY))
-					play_sound(SEND);
-			} else {
-				if (b->makesound && (sound_options & OPT_SOUND_CHAT_SAY))
-					play_sound(RECEIVE);
-			}
-	                g_free(str);
-			str = g_malloc(64);
-			g_snprintf(str, 62, "***%s", who);
-			strcpy(colour, "#6C2585\0");
-		} else {
-	                str = g_strdup(normalize(who));
-	                if (!strcasecmp(str, normalize(current_user->username))) {
-				if (b->makesound && (sound_options & OPT_SOUND_CHAT_SAY))
-					play_sound(SEND);
-	                        strcpy(colour, "#0000ff\0");
-			} else {
-				if (b->makesound && (sound_options & OPT_SOUND_CHAT_SAY))
-					play_sound(RECEIVE);
-	                        strcpy(colour, "#ff0000\0");
-			}
-	                g_free(str);
-	                str = g_malloc(64);
-			g_snprintf(str, 62, "%s:", who);
-		}
+		g_free(str);
         }
 
-
-
-	if (display_options & OPT_DISP_SHOW_TIME)
-                g_snprintf(buf, BUF_LONG, "<FONT COLOR=\"%s\"><B>%s %s </B></FONT>", colour, date(), str);
-	else
-                g_snprintf(buf, BUF_LONG, "<FONT COLOR=\"%s\"><B>%s </B></FONT>", colour, str);
-
-        gtk_html_freeze(GTK_HTML(b->text));
-                        
-        gtk_html_append_text(GTK_HTML(b->text), buf, 0);
-        gtk_html_append_text(GTK_HTML(b->text), message, (display_options & OPT_DISP_IGNORE_COLOUR) ? HTML_OPTION_NO_COLOURS : 0);
-        gtk_html_append_text(GTK_HTML(b->text), "<BR>", 0);
-        
-        gtk_html_thaw(GTK_HTML(b->text));
-        
-	if (general_options & OPT_GEN_POPUP_CHAT)
-		gdk_window_show(b->window->window);
-
-	if ((general_options & OPT_GEN_LOG_ALL) || find_log_info(b->name)) {
-		char *t1;
-		FILE *fd;
-
-		t1 = g_malloc(256);
-		snprintf(t1, 256, "%s.chat", b->name);
-		fd = open_log_file(t1);
-		g_free(t1);
-		if (general_options & OPT_GEN_STRIP_HTML) {
-			t1 = strip_html(message);
-			if (display_options & OPT_DISP_SHOW_TIME)
-				fprintf(fd, "%s %s %s\n", date(), str, t1);
-			else
-				fprintf(fd, "%s %s\n", str, t1);
-			g_free(t1);
-		} else {
-			if (display_options & OPT_DISP_SHOW_TIME)
-				fprintf(fd, "%s %s %s\n", date(), str, message);
-			else
-				fprintf(fd, "%s %s\n", str, message);
-		}
-		fclose(fd);
-	}
-
-	g_free(str);
-	g_free(buf);
-}
-
-static void close_callback(GtkWidget *widget, struct buddy_chat *b)
-{
-        if (b->window)
-                gtk_widget_destroy(b->window);
-        b->window = NULL;
-        
-        serv_chat_leave(b->id);
+	write_to_conv(b, message, flag, who);
 }
 
 
 
-static void whisper_callback(GtkWidget *widget, struct buddy_chat *b)
+void whisper_callback(GtkWidget *widget, struct conversation *b)
 {
 	char buf[BUF_LEN*4];
 	char buf2[BUF_LONG];
@@ -460,133 +368,18 @@
 }
 
 
-static void send_callback(GtkWidget *widget, struct buddy_chat *b)
-{
-	char buf[BUF_LEN*4];
 
-	strncpy(buf, gtk_editable_get_chars(GTK_EDITABLE(b->entry), 0, -1), sizeof(buf)/2);
-	if (!strlen(buf))
-		return;
-
-	gtk_editable_delete_text(GTK_EDITABLE(b->entry), 0, -1);
-
-	if (general_options & OPT_GEN_SEND_LINKS) {
-		linkify_text(buf);
-	}
-
-#ifdef GAIM_PLUGINS
-	{
-	GList *c = callbacks;
-	struct gaim_callback *g;
-	void (*function)(char *, char **, void *);
-	char *buffy = g_strdup(buf);
-	while (c) {
-		g = (struct gaim_callback *)c->data;
-		if (g->event == event_chat_send && g->function != NULL) {
-			function = g->function;
-			(*function)(b->name, &buffy, g->data);
-		}
-		c = c->next;
-	}
-	if (!buffy)
-		return;
-	g_snprintf(buf, sizeof buf, "%s", buffy);
-	g_free(buffy);
-	}
-#endif
-
-
-        escape_text(buf);
-        serv_chat_send(b->id, buf);
-        
-	gtk_widget_grab_focus(GTK_WIDGET(b->entry));
-
-	serv_set_idle(0);
-
-	if ((general_options & OPT_GEN_BACK_ON_IM) && awaymessage != NULL) {
-		do_im_back();
-	}
-}
-
-
-static gboolean chat_keypress_callback(GtkWidget *entry, GdkEventKey *event, struct buddy_chat *c)
-{
-	int pos;
-	if (event->keyval == GDK_Return) {
-		if (!(event->state & GDK_SHIFT_MASK)
-				&& (general_options & OPT_GEN_ENTER_SENDS)) {
-			gtk_signal_emit_by_name(GTK_OBJECT(entry), "activate", c);
-			gtk_signal_emit_stop_by_name(GTK_OBJECT(entry), "key_press_event");
-		} else {
-			gtk_signal_emit_stop_by_name(GTK_OBJECT(entry), "key_press_event");
-			pos = gtk_editable_get_position(GTK_EDITABLE(entry));
-			gtk_editable_insert_text(GTK_EDITABLE(entry), "\n", 1, &pos);
-		}
-	}
-
-	/* now we see if we need to unset any buttons */
-
-	if (invert_tags(c->entry, "<B>", "</B>", 0))
-		quiet_set(c->bold, TRUE);
-	else if (count_tag(c->entry, "<B>", "</B>")) 
-		quiet_set(c->bold, TRUE);
-	else
-		quiet_set(c->bold,FALSE);
-
-	if (invert_tags(c->entry, "<I>", "</I>", 0))
-		quiet_set(c->italic, TRUE);
-	else if (count_tag(c->entry, "<I>", "</I>"))  
-		quiet_set(c->italic, TRUE);
-	else
-		quiet_set(c->italic, FALSE);
-
-	if (invert_tags(entry, "<FONT COLOR", "</FONT>", 0))
-		quiet_set(c->palette, TRUE);
- 	else if (count_tag(entry, "<FONT COLOR", "</FONT>"))
-		quiet_set(c->palette, TRUE);
-	else
-		quiet_set(c->palette, FALSE);
-	
-	if (invert_tags(entry, "<FONT FACE", "</FONT>", 0))
-		quiet_set(c->font, TRUE);
-	else if (count_tag(entry, "<FONT FACE", "</FONT>"))
-		quiet_set(c->font, TRUE);
-	else
-		quiet_set(c->font, FALSE);
-
-	if (invert_tags(c->entry, "<A HREF", "</A>", 0))
-		quiet_set(c->link, TRUE);
-	else if (count_tag(c->entry, "<A HREF", "</A>"))
-		quiet_set(c->link, TRUE);
-	else
-		quiet_set(c->link, FALSE);
-
- 	if (invert_tags(entry, "<U>", "</U>", 0))
-		quiet_set(c->underline, TRUE);
-	else if (count_tag(entry, "<U>", "</U>"))
-		quiet_set(c->underline, TRUE);
-	else
-		quiet_set(c->underline, FALSE);  
-
-	if (invert_tags(entry, "<STRIKE>", "</STRIKE>", 0))
-		quiet_set(c->strike, TRUE);
-	else if (count_tag(entry, "<STRIKE>", "</STRIKE>"))
-		quiet_set(c->strike, TRUE);
-	else
-		quiet_set(c->strike, FALSE);
-
-	return TRUE;
-
-}
-
-
-void update_chat_list(struct buddy_chat *b)
+void update_chat_list(struct conversation *b)
 {
         GtkWidget *list_item;
         char name[80];
         char *tmp;
         GList *names = b->in_room;
 
+	if (!b->is_chat) {
+		debug_print("update_chat_list: expecting chat, got IM\n");
+		return;
+	}
 
         gtk_list_clear_items(GTK_LIST(b->list), 0, -1);
 
@@ -611,7 +404,7 @@
 
 
 
-void add_chat_buddy(struct buddy_chat *b, char *buddy)
+void add_chat_buddy(struct conversation *b, char *buddy)
 {
         char *name = g_strdup(buddy);
 
@@ -640,7 +433,7 @@
 
 
 
-void remove_chat_buddy(struct buddy_chat *b, char *buddy)
+void remove_chat_buddy(struct conversation *b, char *buddy)
 {	
         GList *names = b->in_room;
 
@@ -672,7 +465,7 @@
 }
 
 
-static void im_callback(GtkWidget *w, struct buddy_chat *b)
+void im_callback(GtkWidget *w, struct conversation *b)
 {
         char *name;
         GList *i;
@@ -695,7 +488,7 @@
         
 }
 
-static void ignore_callback(GtkWidget *w, struct buddy_chat *b)
+void ignore_callback(GtkWidget *w, struct conversation *b)
 {
         char *name;
         GList *i;
@@ -714,24 +507,9 @@
         update_chat_list(b);
 }
 
-static void info_callback(GtkWidget *w, struct buddy_chat *b)
-{
-        char *name;
-        GList *i;
-
-        i = GTK_LIST(b->list)->selection;
-        if (i)
-                name = (char *)gtk_object_get_user_data(GTK_OBJECT(i->data));
-        else
-                return;
-
-        serv_get_info(name);
-}
 
 
-
-
-void show_new_buddy_chat(struct buddy_chat *b)
+void show_new_buddy_chat(struct conversation *b)
 {
 	GtkWidget *win;
 	GtkWidget *text;
@@ -751,10 +529,6 @@
 	GtkWidget *vpaned;
 	GtkWidget *hpaned;
 	GtkWidget *toolbar;
-        GdkPixmap *strike_i, *small_i, *normal_i, *big_i, *bold_i, *italic_i, *underline_i, *speaker_i, *wood_i, *palette_i, *link_i, *font_i;
-        GtkWidget *strike_p, *small_p, *normal_p, *big_p, *bold_p, *italic_p, *underline_p, *speaker_p, *wood_p, *palette_p, *link_p, *font_p;
-        GtkWidget *strike, *small, *normal, *big, *bold, *italic, *underline, *speaker, *wood, *palette, *link, *font;
-	GdkBitmap *mask;
 	
 	win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 	b->window = win;
@@ -791,132 +565,7 @@
 
 	gtk_widget_realize(win);
 
-	toolbar = gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_ICONS);
-
-	link_i = gdk_pixmap_create_from_xpm_d(win->window, &mask,
-			&win->style->white, link_xpm );
-	link_p = gtk_pixmap_new(link_i, mask);
-	gtk_widget_show(link_p);
-
-	strike_i = gdk_pixmap_create_from_xpm_d ( win->window, &mask,
-			&win->style->white, strike_xpm );
-	strike_p = gtk_pixmap_new(strike_i, mask);
-	gtk_widget_show(strike_p);
-
-	palette_i = gdk_pixmap_create_from_xpm_d (win->window, &mask,
-             &win->style->white, palette_xpm );
-	palette_p = gtk_pixmap_new(palette_i, mask);
-	gtk_widget_show(palette_p);
-
-	bold_i = gdk_pixmap_create_from_xpm_d ( win->window, &mask,
-			&win->style->white, bold_xpm );
-	bold_p = gtk_pixmap_new(bold_i, mask);
-	gtk_widget_show(bold_p);
-
-	italic_i = gdk_pixmap_create_from_xpm_d ( win->window, &mask,
-			&win->style->white, italic_xpm );
-	italic_p = gtk_pixmap_new(italic_i, mask);
-	gtk_widget_show(italic_p);
-
-	underline_i = gdk_pixmap_create_from_xpm_d ( win->window, &mask,
-			&win->style->white, underline_xpm );
-	underline_p = gtk_pixmap_new(underline_i, mask);
-	gtk_widget_show(underline_p);
-
-	small_i = gdk_pixmap_create_from_xpm_d ( win->window, &mask,
-			&win->style->white, small_xpm );
-	small_p = gtk_pixmap_new(small_i, mask);
-	gtk_widget_show(small_p);
-
-	normal_i = gdk_pixmap_create_from_xpm_d ( win->window, &mask,
-			&win->style->white, normal_xpm );
-	normal_p = gtk_pixmap_new(normal_i, mask);
-	gtk_widget_show(normal_p);
-
-	big_i = gdk_pixmap_create_from_xpm_d ( win->window, &mask,
-			&win->style->white, big_xpm );
-	big_p = gtk_pixmap_new(big_i, mask);
-	gtk_widget_show(big_p);
-
-	wood_i = gdk_pixmap_create_from_xpm_d ( win->window, &mask, 
-	     &win->style->white, wood_xpm );
-	wood_p = gtk_pixmap_new(wood_i, mask);
-	gtk_widget_show(wood_p);
-
-	font_i = gdk_pixmap_create_from_xpm_d ( win->window, &mask,
-			&win->style->white, fontface_xpm );
-	font_p = gtk_pixmap_new(font_i, mask);
-	gtk_widget_show(font_p);
-
-	speaker_i = gdk_pixmap_create_from_xpm_d ( win->window, &mask,
-             &win->style->white, speaker_xpm );
-	speaker_p = gtk_pixmap_new(speaker_i, mask);
-	gtk_widget_show(speaker_p);
-	b->makesound=1;
-
-	bold = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
-	                                  GTK_TOOLBAR_CHILD_TOGGLEBUTTON, NULL,
-					  _("Bold"), _("Bold Text"), _("Bold"), bold_p,
-					  GTK_SIGNAL_FUNC(do_bold), chatentry);
-	italic = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), 
-		                            GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
-					    NULL, _("Italics"), _("Italics Text"),
-					    _("Italics"), italic_p, GTK_SIGNAL_FUNC(do_italic), chatentry);
-	underline = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
-					    GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
-					    NULL, _("Underline"), _("Underline Text"),
-					    _("Underline"), underline_p, GTK_SIGNAL_FUNC(do_underline), chatentry);
-	strike = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
-					    GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
-					    NULL, _("Strike"), _("Strike through Text"),
-					    _("Strike"), strike_p, GTK_SIGNAL_FUNC(do_strike), chatentry);
-	gtk_toolbar_append_space(GTK_TOOLBAR(toolbar));
-	small = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), _("Small"), _("Decrease font size"), _("Small"), small_p, GTK_SIGNAL_FUNC(do_small), chatentry);
-	normal = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), _("Normal"), _("Normal font size"), _("Normal"), normal_p, GTK_SIGNAL_FUNC(do_normal), chatentry);
-	big = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), _("Big"), _("Increase font size"), _("Big"), big_p, GTK_SIGNAL_FUNC(do_big), chatentry);
-	font = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
-						GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
-						NULL, _("Font"), _("Select Font"),
-						_("Font"), font_p, NULL, NULL);
-	gtk_widget_set_sensitive(GTK_WIDGET(font), FALSE);
-	
-	gtk_toolbar_append_space(GTK_TOOLBAR(toolbar));
-	link = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
-                                            GTK_TOOLBAR_CHILD_TOGGLEBUTTON,                                                 NULL, _("Link"), _("Insert Link"),
-                                            _("Link"), link_p, GTK_SIGNAL_FUNC(do_link), chatentry);                 
-	palette = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
-					    GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
-					    NULL, _("Color"), _("Text Color"),
-				 	    _("Color"), palette_p, NULL, NULL);
-	gtk_widget_set_sensitive(GTK_WIDGET(palette), FALSE);
-	wood = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
-					    GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
-					    NULL, _("Logging"), _("Enable logging"),
-                                          _("Logging"), wood_p, NULL, NULL);
-					  gtk_widget_set_sensitive(GTK_WIDGET(palette), FALSE);
-	gtk_widget_set_sensitive(GTK_WIDGET(wood), FALSE);
-        speaker = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
-		                            GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
-					    NULL, _("Sound"), _("Enable sounds"),
-					    _("Sound"), speaker_p, GTK_SIGNAL_FUNC(set_option), &b->makesound);
-	b->makesound = 0;
-	gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(speaker), TRUE);
-
-	gtk_widget_show(toolbar);
-
-	b->bold = bold;
-	b->strike = strike;
-	b->italic = italic;
-	b->underline = underline;
-	b->link = link;
-	b->palette = palette;
-	b->font = font;
-	b->wood = wood;
-
-	if (find_log_info(b->name))
-		gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(wood), TRUE);
-	else
-		gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(wood), FALSE);
+	toolbar = build_conv_toolbar(b);
 
 	gtk_object_set_user_data(GTK_OBJECT(chatentry), b);
 	b->entry = chatentry;
@@ -924,7 +573,7 @@
 	/* Hack something so we know have an entry click event */
 
 	gtk_signal_connect(GTK_OBJECT(chatentry), "activate", GTK_SIGNAL_FUNC(send_callback),b);
-	gtk_signal_connect(GTK_OBJECT(chatentry), "key_press_event", GTK_SIGNAL_FUNC(chat_keypress_callback), b);
+	gtk_signal_connect(GTK_OBJECT(chatentry), "key_press_event", GTK_SIGNAL_FUNC(keypress_callback), b);
         /* Text box */
 
         sw = gtk_scrolled_window_new (NULL, NULL);
--- a/src/conversation.c	Sun Jul 09 18:06:11 2000 +0000
+++ b/src/conversation.c	Sun Jul 09 23:19:21 2000 +0000
@@ -31,26 +31,9 @@
 #include <stdlib.h>
 #include <ctype.h>
 #include <gtk/gtk.h>
-#include "gaim.h"
 #include "gtkhtml.h"
 #include <gdk/gdkkeysyms.h>
-#include "pixmaps/underline.xpm"
-#include "pixmaps/bold.xpm"
-#include "pixmaps/italic.xpm"
-#include "pixmaps/small.xpm"
-#include "pixmaps/normal.xpm"
-#include "pixmaps/big.xpm"
-#include "pixmaps/fontface.xpm"
-#include "pixmaps/speaker.xpm"
-/* #include "pixmaps/aimicon2.xpm" */
-#include "pixmaps/wood.xpm"
-#include "pixmaps/palette.xpm"
-#include "pixmaps/link.xpm"
-#include "pixmaps/strike.xpm"
-
-#include "pixmaps/smile_happy.xpm"
-#include "pixmaps/smile_sad.xpm"
-#include "pixmaps/smile_wink.xpm"
+#include "convo.h"
 
 int state_lock=0;
 
@@ -61,7 +44,7 @@
 
 void check_everything(GtkWidget *entry);
 char *get_tag_by_prefix(GtkWidget *entry, const char *prefix);
-gboolean user_keypress_callback(GtkWidget *entry, GdkEventKey *event,  struct conversation *c);
+gboolean keypress_callback(GtkWidget *entry, GdkEventKey *event,  struct conversation *c);
 
 /*------------------------------------------------------------------------*/
 /*  Helpers                                                               */
@@ -235,6 +218,16 @@
 
 		cnv = cnv->next;
 	}
+
+	cnv = buddy_chats;
+	while(cnv) {
+		c = (struct conversation *)cnv->data;
+
+		if (c->log_button)
+			gtk_widget_set_sensitive(c->log_button, ((general_options & OPT_GEN_LOG_ALL)) ? FALSE : TRUE);
+
+		cnv = cnv->next;
+	}
 }
 
 void update_font_buttons()
@@ -300,10 +293,17 @@
 		show_log_dialog(p->name);
 }
 
-static int close_callback(GtkWidget *widget, struct conversation *c)
+int close_callback(GtkWidget *widget, struct conversation *c)
 {
-        gtk_widget_destroy(c->window);
-        delete_conversation(c);
+	if (c->window)
+	        gtk_widget_destroy(c->window);
+	c->window = NULL;
+
+	if (c->is_chat)
+		serv_chat_leave(c->id);
+	else
+	        delete_conversation(c);
+
         return TRUE;
 }
 
@@ -358,7 +358,7 @@
 	gtk_widget_grab_focus(c->entry);
 }
 
-static void add_callback(GtkWidget *widget, struct conversation *c)
+void add_callback(GtkWidget *widget, struct conversation *c)
 {
 	if (find_buddy(c->name) != NULL) {
 		sprintf(debug_buff,_("Removing '%s' from buddylist.\n"), c->name);
@@ -376,25 +376,38 @@
 }
 
 
-static void block_callback(GtkWidget *widget, struct conversation *c)
+void block_callback(GtkWidget *widget, struct conversation *c)
 {
         show_add_perm(c->name);
 	gtk_widget_grab_focus(c->entry);
 }
 
-static void warn_callback(GtkWidget *widget, struct conversation *c)
+void warn_callback(GtkWidget *widget, struct conversation *c)
 {
         show_warn_dialog(c->name);
 	gtk_widget_grab_focus(c->entry);
 }
 
-static void info_callback(GtkWidget *widget, struct conversation *c)
+void info_callback(GtkWidget *w, struct conversation *c)
 {
-        serv_get_info(c->name);
-	gtk_widget_grab_focus(c->entry);
+	if (c->is_chat) {
+	        char *name;
+	        GList *i;
+
+	        i = GTK_LIST(c->list)->selection;
+	        if (i)
+	                name = (char *)gtk_object_get_user_data(GTK_OBJECT(i->data));
+	        else
+	                return;
+
+	        serv_get_info(name);
+	} else {
+	        serv_get_info(c->name);
+		gtk_widget_grab_focus(c->entry);
+	}
 }
 
-gboolean user_keypress_callback(GtkWidget *entry, GdkEventKey *event,  struct conversation *c)
+gboolean keypress_callback(GtkWidget *entry, GdkEventKey *event,  struct conversation *c)
 {
   int pos;
   if(event->keyval==GDK_Return) {
@@ -415,10 +428,11 @@
 }
 
 
-static void send_callback(GtkWidget *widget, struct conversation *c)
+void send_callback(GtkWidget *widget, struct conversation *c)
 {
         char *buf = g_malloc(BUF_LEN * 4);
 	char *buf2;
+	char *buf3;
 	gchar *buf4;
         int hdrlen;
 
@@ -433,6 +447,8 @@
                 return;
         }
 
+	gtk_editable_delete_text(GTK_EDITABLE(c->entry), 0, -1);
+
         if (general_options & OPT_GEN_SEND_LINKS) {
                 linkify_text(buf);
         }
@@ -474,9 +490,10 @@
 		struct gaim_callback *g;
 		void (*function)(char *, char **, void *);
 		char *buffy = g_strdup(buf);
+		enum gaim_event evnt = c->is_chat ? event_chat_send : event_im_send;
 		while (ca) {
 			g = (struct gaim_callback *)(ca->data);
-			if (g->event == event_im_send && g->function != NULL) {
+			if (g->event == evnt && g->function != NULL) {
 				function = g->function;
 				(*function)(c->name, &buffy, g->data);
 			}
@@ -491,16 +508,27 @@
 	}
 #endif
         
-	write_to_conv(c, buf, WFLAG_SEND);
-
-	gtk_editable_delete_text(GTK_EDITABLE(c->entry), 0, -1);
+	if (!c->is_chat) {
+		buf3 = g_strdup(buf);
+		write_to_conv(c, buf3, WFLAG_SEND, NULL);
+		g_free(buf3);
+	}
 
 	escape_text(buf);
 	if (escape_message(buf) > MSG_LEN - hdrlen) {
 		do_error_dialog(_("Message too long, some data truncated."), _("Error"));
 	}
 
-        serv_send_im(c->name, buf, 0);
+	if (c->is_chat) {
+		serv_chat_send(c->id, buf);
+
+		/* no sound because we do that when we receive our message */
+	} else {
+	        serv_send_im(c->name, buf, 0);
+
+		if (c->makesound && (sound_options & OPT_SOUND_SEND))
+			play_sound(SEND);
+	}
         
 	quiet_set(c->bold, FALSE);
 	quiet_set(c->strike, FALSE);
@@ -510,14 +538,11 @@
 	quiet_set(c->palette, FALSE);
 	quiet_set(c->link, FALSE);
         
-	if (c->makesound && (sound_options & OPT_SOUND_SEND))
-		play_sound(SEND);
-
 	if ((general_options & OPT_GEN_BACK_ON_IM) && awaymessage != NULL) {
 		do_im_back();
 	}
 
-    set_font_face(NULL, c);
+	set_font_face(NULL, c);
 	
 	gtk_widget_grab_focus(c->entry);
 
@@ -684,7 +709,7 @@
 	gtk_widget_grab_focus(entry);
 }
 
-static void toggle_color(GtkWidget *color, struct conversation *c)
+void toggle_color(GtkWidget *color, struct conversation *c)
 {
 	if (state_lock)
                 return;
@@ -694,7 +719,7 @@
 		advance_past(c->entry, "<FONT COLOR>", "</FONT>" );
 }
 
-static void toggle_font(GtkWidget *font, struct conversation *c)
+void toggle_font(GtkWidget *font, struct conversation *c)
 {
 	if (state_lock)
 		return;
@@ -841,11 +866,14 @@
 /*------------------------------------------------------------------------*/
 
 
-void write_to_conv(struct conversation *c, char *what, int flags)
+/* this is going to be interesting since the conversation could either be a
+ * normal IM conversation or a chat window. but hopefully it won't matter */
+void write_to_conv(struct conversation *c, char *what, int flags, char *who)
 {
 	char *buf = g_malloc(BUF_LONG);
         char *buf2 = g_malloc(BUF_LONG);
-        char *who = NULL;
+	char *buf3;
+	char *str;
         FILE *fd;
         char colour[10];
 	GdkBitmap *mask;
@@ -854,6 +882,8 @@
 	int y;
 	int i;
 	char *smiley = g_malloc(7);
+
+	if (!who) who = c->name;
 	
         if (flags & WFLAG_SYSTEM) {
 
@@ -883,23 +913,44 @@
                 
         } else {
 
-                if (flags & WFLAG_RECV) {
-                        strcpy(colour, "#ff0000");
-			who = c->name;
-                } else if (flags & WFLAG_SEND) {
-                        strcpy(colour, "#0000ff");
-                        who = current_user->username;
-                }
+		buf3 = g_malloc(BUF_LONG);
+		
+		if (flags & WFLAG_WHISPER) {
+			/* if we're whispering, it's not an autoresponse */
+			if (meify(what)) {
+				str = g_malloc(64);
+				g_snprintf(str, 62, "***%s", who);
+				strcpy(colour, "#6C2585\0");
+			} else {
+				str = g_malloc(64);
+				g_snprintf(str, 62, "*%s*:", who);
+				strcpy(colour, "#00ff00\0");
+			}
+		} else {
+			if (meify(what)) {
+				str = g_malloc(64);
+				if (flags & WFLAG_AUTO)
+					g_snprintf(str, 62, "%s ***%s", AUTO_RESPONSE, who);
+				else
+					g_snprintf(str, 62, "***%s", who);
+				strcpy(colour, "#062585\0");
+			} else {
+				str = g_malloc(64);
+				if (flags & WFLAG_AUTO)
+					g_snprintf(str, 62, "%s %s", who, AUTO_RESPONSE);
+				else
+					g_snprintf(str, 62, "%s:", who);
+		                if (flags & WFLAG_RECV)
+		                        strcpy(colour, "#ff0000");
+				else if (flags & WFLAG_SEND)
+		                        strcpy(colour, "#0000ff");
+			}
+		}
 
-                if (flags & WFLAG_AUTO)
-                        sprintf(buf2, " %s", AUTO_RESPONSE);
-                else
-                        buf2[0]=0; /* sprintf(buf2, ""); */
-
-                if (display_options & OPT_DISP_SHOW_TIME)
-                        g_snprintf(buf, BUF_LONG, "<FONT COLOR=\"%s\"><B>%s %s:%s</B></FONT> ", colour, date(), who, buf2);
-                else
-                        g_snprintf(buf, BUF_LONG, "<FONT COLOR=\"%s\"><B>%s:%s</B></FONT> ", colour, who, buf2);
+		if (display_options & OPT_DISP_SHOW_TIME)
+			g_snprintf(buf, BUF_LONG, "<FONT COLOR=\"%s\"><B>%s %s</B></FONT> ", colour, date(), str);
+		else
+			g_snprintf(buf, BUF_LONG, "<FONT COLOR=\"%s\"><B>%s</B></FONT>", colour, str);
 
                 gtk_html_freeze(GTK_HTML(c->text));
 
@@ -917,7 +968,7 @@
                			buf2[y] = what[i];
                			y++;
 
-		                if ( (what[i] == ':') || (what[i] == ';') || (what[i] == 'O') )
+		                if ( (what[i] == ':') || (what[i] == ';') || (what[i] == '8') )
                			{
                        			if (state < 2)
                         	  	{
@@ -1007,6 +1058,11 @@
 
                 if ((general_options & OPT_GEN_LOG_ALL) || find_log_info(c->name)) {
                         char *t1, *t2;
+			char *nm = g_malloc(256);
+			if (c->is_chat)
+				g_snprintf(nm, 256, "%s.chat", c->name);
+			else
+				g_snprintf(nm, 256, "%s", c->name);
 
                         if (general_options & OPT_GEN_STRIP_HTML) {
                                 t1 = strip_html(buf);
@@ -1015,13 +1071,14 @@
                                 t1 = buf;
                                 t2 = what;
                         }
-                        fd = open_log_file(c->name);
+                        fd = open_log_file(nm);
                         fprintf(fd, "%s%s\n", t1, t2);
                         fclose(fd);
                         if (general_options & OPT_GEN_STRIP_HTML) {
                                 g_free(t1);
                                 g_free(t2);
                         }
+			g_free(nm);
                 }
         }
 
@@ -1034,7 +1091,8 @@
 	}
 */
 
-        if (general_options & OPT_GEN_POPUP_WINDOWS)
+        if ((c->is_chat && (general_options & OPT_GEN_POPUP_CHAT)) ||
+	   (!c->is_chat && (general_options & OPT_GEN_POPUP_WINDOWS)))
                 gdk_window_show(c->window->window);
 
 	g_free(smiley);        
@@ -1067,69 +1125,18 @@
 }
 
 
-void show_conv(struct conversation *c)
-{
-	GtkWidget *win;
-        char buf[256];
-        GtkWidget *text;
-        GtkWidget *sw;
-	GtkWidget *send;
-	GtkWidget *info;
-        GtkWidget *warn;
-        GtkWidget *block;
-	/* GtkWidget *color; */
-	GtkWidget *close;
-	GtkWidget *entry;
-	GtkWidget *toolbar;
-	GtkWidget *bbox;
-        GtkWidget *vbox;
-	GtkWidget *vbox2;
-	GtkWidget *paned;
-        GtkWidget *add;
+GtkWidget *build_conv_toolbar(struct conversation *c) {
         GdkPixmap *strike_i, *small_i, *normal_i, *big_i, *bold_i, *italic_i, *underline_i, *speaker_i, *wood_i, *palette_i, *link_i, *font_i;
         GtkWidget *strike_p, *small_p, *normal_p, *big_p, *bold_p, *italic_p, *underline_p, *speaker_p, *wood_p, *palette_p, *link_p, *font_p;
         GtkWidget *strike, *small, *normal, *big, *bold, *italic, *underline, *speaker, *wood, *palette, *link, *font;
         GdkBitmap *mask;
-	
-	win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-        gtk_window_set_policy(GTK_WINDOW(win), TRUE, TRUE, TRUE);
+	GtkWidget *toolbar;
+	GtkWidget *win;
+	GtkWidget *entry;
 
-        gtk_widget_realize(win);
-        aol_icon(win->window);
- 
-        
-        c->window = win;
-        
-	send = gtk_button_new_with_label(_("Send"));
-	info = gtk_button_new_with_label(_("Info"));
-	warn = gtk_button_new_with_label(_("Warn"));
-	/* color = gtk_button_new_with_label("Color"); */
-	close = gtk_button_new_with_label(_("Close"));
-	if (find_buddy(c->name) != NULL) {
-       		add = gtk_button_new_with_label(_("Remove"));
-	}
-	else {
-		add = gtk_button_new_with_label(_("Add"));
-	}
-        block = gtk_button_new_with_label(_("Block"));
-
-
-        bbox = gtk_hbox_new(TRUE, 0);
-	vbox = gtk_vbox_new(FALSE, 0);
-	vbox2 = gtk_vbox_new(FALSE, 0);
-	paned = gtk_vpaned_new();
-
-	gtk_paned_pack1(GTK_PANED(paned), vbox, FALSE, TRUE);
-	gtk_paned_pack2(GTK_PANED(paned), vbox2, FALSE, FALSE);
-	gtk_widget_show(vbox2);
-	gtk_widget_show(paned);
-	
-	entry = gtk_text_new(NULL, NULL);
-	gtk_text_set_editable(GTK_TEXT(entry), TRUE);
-	gtk_text_set_word_wrap(GTK_TEXT(entry), TRUE);
-
-	/* Toolbar */
 	toolbar = gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_ICONS);
+	win = c->window;
+	entry = c->entry;
 
 	link_i = gdk_pixmap_create_from_xpm_d(win->window, &mask,
 	     &win->style->white, link_xpm );
@@ -1239,7 +1246,6 @@
         
 	gtk_widget_show(toolbar);
 	
-	c->entry = entry;
 	c->bold = bold;
 	c->strike = strike;
         c->italic = italic;
@@ -1247,7 +1253,6 @@
         c->log_button = wood;
 	c->palette = palette;
 	c->link = link;  
-        c->add_button = add;
 	c->font = font;
 
         gtk_widget_set_sensitive(c->log_button, ((general_options & OPT_GEN_LOG_ALL)) ? FALSE : TRUE);
@@ -1256,9 +1261,75 @@
 	gtk_widget_set_sensitive(c->italic, ((font_options & OPT_FONT_ITALIC)) ? FALSE : TRUE);
 	gtk_widget_set_sensitive(c->underline, ((font_options & OPT_FONT_UNDERLINE)) ? FALSE : TRUE);
 	gtk_widget_set_sensitive(c->strike, ((font_options & OPT_FONT_STRIKE)) ? FALSE : TRUE);
+
+	return toolbar;
+}
+
+
+void show_conv(struct conversation *c)
+{
+	GtkWidget *win;
+        char buf[256];
+        GtkWidget *text;
+        GtkWidget *sw;
+	GtkWidget *send;
+	GtkWidget *info;
+        GtkWidget *warn;
+        GtkWidget *block;
+	/* GtkWidget *color; */
+	GtkWidget *close;
+	GtkWidget *entry;
+	GtkWidget *toolbar;
+	GtkWidget *bbox;
+        GtkWidget *vbox;
+	GtkWidget *vbox2;
+	GtkWidget *paned;
+        GtkWidget *add;
+	
+	win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+        gtk_window_set_policy(GTK_WINDOW(win), TRUE, TRUE, TRUE);
+
+        gtk_widget_realize(win);
+        aol_icon(win->window);
+ 
         
+        c->window = win;
+        
+	send = gtk_button_new_with_label(_("Send"));
+	info = gtk_button_new_with_label(_("Info"));
+	warn = gtk_button_new_with_label(_("Warn"));
+	/* color = gtk_button_new_with_label("Color"); */
+	close = gtk_button_new_with_label(_("Close"));
+	if (find_buddy(c->name) != NULL) {
+       		add = gtk_button_new_with_label(_("Remove"));
+	}
+	else {
+		add = gtk_button_new_with_label(_("Add"));
+	}
+        block = gtk_button_new_with_label(_("Block"));
+
+
+        bbox = gtk_hbox_new(TRUE, 0);
+	vbox = gtk_vbox_new(FALSE, 0);
+	vbox2 = gtk_vbox_new(FALSE, 0);
+	paned = gtk_vpaned_new();
+
+	gtk_paned_pack1(GTK_PANED(paned), vbox, FALSE, TRUE);
+	gtk_paned_pack2(GTK_PANED(paned), vbox2, FALSE, FALSE);
+	gtk_widget_show(vbox2);
+	gtk_widget_show(paned);
+	
+	entry = gtk_text_new(NULL, NULL);
+	gtk_text_set_editable(GTK_TEXT(entry), TRUE);
+	gtk_text_set_word_wrap(GTK_TEXT(entry), TRUE);
 	gtk_object_set_user_data(GTK_OBJECT(entry), c);
+	c->entry = entry;
 
+	/* Toolbar */
+	toolbar = build_conv_toolbar(c);
+        
+
+        c->add_button = add;
 	
 
 	gtk_signal_connect(GTK_OBJECT(entry), "activate", GTK_SIGNAL_FUNC(send_callback),c);
@@ -1300,7 +1371,7 @@
         gtk_signal_connect(GTK_OBJECT(block), "clicked", GTK_SIGNAL_FUNC(block_callback), c);
 	/* gtk_signal_connect(GTK_OBJECT(color), "clicked", GTK_SIGNAL_FUNC(color_callback), c); */
        
-	gtk_signal_connect(GTK_OBJECT(entry), "key_press_event", GTK_SIGNAL_FUNC(user_keypress_callback), c);
+	gtk_signal_connect(GTK_OBJECT(entry), "key_press_event", GTK_SIGNAL_FUNC(keypress_callback), c);
 	gtk_widget_set_usize(entry, 300, 25);
 
 	gtk_box_pack_start(GTK_BOX(bbox), send, TRUE, TRUE, 5);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/convo.h	Sun Jul 09 23:19:21 2000 +0000
@@ -0,0 +1,87 @@
+/*
+ * gaim
+ *
+ * Copyright (C) 1998-1999, Mark Spencer <markster@marko.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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _GAIMCONVO_H_
+#define _GAIMCONVO_H_
+
+#include <gtk/gtk.h>
+#include "gaim.h"
+
+#include "pixmaps/underline.xpm"
+#include "pixmaps/bold.xpm"
+#include "pixmaps/italic.xpm"
+#include "pixmaps/small.xpm"
+#include "pixmaps/normal.xpm"
+#include "pixmaps/big.xpm"
+#include "pixmaps/fontface.xpm"
+#include "pixmaps/speaker.xpm"
+/* #include "pixmaps/aimicon2.xpm" */
+#include "pixmaps/wood.xpm"
+#include "pixmaps/palette.xpm"
+#include "pixmaps/link.xpm"
+#include "pixmaps/strike.xpm"
+
+#include "pixmaps/smile_happy.xpm"
+#include "pixmaps/smile_sad.xpm"
+#include "pixmaps/smile_wink.xpm"
+
+#include "pixmaps/join.xpm"
+#include "pixmaps/cancel.xpm"
+
+
+/* we declare all of the global functions for chat and IM windows here, so
+ * that it's easy to keep them merged. */
+
+/* chat first */
+extern void im_callback(GtkWidget *, struct conversation *);
+extern void ignore_callback(GtkWidget *, struct conversation *);
+extern void whisper_callback(GtkWidget *, struct conversation *);
+extern void invite_callback(GtkWidget *, struct conversation *);
+
+/* now IM */
+extern void warn_callback(GtkWidget *, struct conversation *);
+extern void block_callback(GtkWidget *, struct conversation *);
+extern void add_callback(GtkWidget *, struct conversation *);
+
+/* now both */
+extern void info_callback(GtkWidget *, struct conversation *);
+extern void do_bold(GtkWidget *, GtkWidget *);
+extern void do_italic(GtkWidget *, GtkWidget *);
+extern void do_underline(GtkWidget *, GtkWidget *);
+extern void do_strike(GtkWidget *, GtkWidget *);
+extern void do_small(GtkWidget *, GtkWidget *);
+extern void do_normal(GtkWidget *, GtkWidget *);
+extern void do_big(GtkWidget *, GtkWidget *);
+extern void toggle_font(GtkWidget *, struct conversation *);
+extern void do_link(GtkWidget *, GtkWidget *);
+extern void toggle_color(GtkWidget *, struct conversation *);
+extern void toggle_loggle(GtkWidget *, struct conversation *);
+/* sound is handled by set_option */
+extern gboolean keypress_callback(GtkWidget *, GdkEventKey *, struct conversation *);
+
+extern GtkWidget *build_conv_toolbar(struct conversation *);
+
+extern void send_callback(GtkWidget *, struct conversation *);
+extern int close_callback(GtkWidget *, struct conversation *);
+
+extern gboolean meify(char *);
+
+#endif
--- a/src/gaim.h	Sun Jul 09 18:06:11 2000 +0000
+++ b/src/gaim.h	Sun Jul 09 23:19:21 2000 +0000
@@ -223,28 +223,6 @@
 	GList *members;
 };
 
-struct buddy_chat {
-	GtkWidget *window;
-	GtkWidget *text;
-	GtkWidget *list;
-        GtkWidget *entry;
-	GtkWidget *italic;
-	GtkWidget *bold;
-	GtkWidget *underline;
-	GtkWidget *palette;
-	GtkWidget *link;
-	GtkWidget *strike;
-	GtkWidget *font;
-	GtkWidget *wood;
-	GtkWidget *color_dialog;
-	GtkWidget *font_dialog;
-        GList *in_room;
-        GList *ignored;
-	int makesound;
-        int id;
-	char name[80];
-};
-
 struct chat_room {
         char name[128];
         int exchange;
@@ -262,7 +240,9 @@
 	GtkWidget *entry;
 };
 
+/* struct buddy_chat went away and got merged with this. */
 struct conversation {
+	/* stuff used for both IM and chat */
 	GtkWidget *window;
 	char name[80];
 	GtkWidget *text;
@@ -272,17 +252,27 @@
 	GtkWidget *underline;
 	GtkWidget *palette;
 	GtkWidget *link;
-	GtkWidget *add_button;
 	GtkWidget *log_button;
 	GtkWidget *strike;
 	GtkWidget *font;
 	GtkWidget *color_dialog;
 	GtkWidget *font_dialog;
-
+	int makesound;
 	char current_fontface[64];
 	char current_fontname[64];
-	int makesound;
+
+	/* stuff used just for IM */
+	GtkWidget *add_button;
  	time_t sent_away;
+
+	/* stuff used just for chat */
+        GList *in_room;
+        GList *ignored;
+        int id;
+	GtkWidget *list;
+
+	/* something to distinguish */
+	gboolean is_chat;
 };
 
 struct file_header {
@@ -385,7 +375,7 @@
 #define TYPE_SIGNOFF   4
 #define TYPE_KEEPALIVE 5
 
-#define REVISION "gaim:$Revision: 446 $"
+#define REVISION "gaim:$Revision: 482 $"
 #define FLAPON "FLAPON\r\n\r\n"
 
 #define ROAST "Tic/Toc"
@@ -519,10 +509,10 @@
 
 /* Functions in buddy_chat.c */
 extern void join_chat();
-extern void chat_write(struct buddy_chat *, char *, int, char *);
-extern void add_chat_buddy(struct buddy_chat *, char *);
-extern void remove_chat_buddy(struct buddy_chat *, char *);
-extern void show_new_buddy_chat(struct buddy_chat *);
+extern void chat_write(struct conversation *, char *, int, char *);
+extern void add_chat_buddy(struct conversation *, char *);
+extern void remove_chat_buddy(struct conversation *, char *);
+extern void show_new_buddy_chat(struct conversation *);
 extern void setup_buddy_chats();
 extern void do_quit();
 
@@ -597,7 +587,7 @@
 extern void serv_rvous_cancel(char *, char *, char *);
 
 /* Functions in conversation.c */
-extern void write_to_conv(struct conversation *, char *, int);
+extern void write_to_conv(struct conversation *, char *, int, char *);
 extern void show_conv(struct conversation *);
 extern struct conversation *new_conversation(char *);
 extern struct conversation *find_conversation(char *);
--- a/src/oscar.c	Sun Jul 09 18:06:11 2000 +0000
+++ b/src/oscar.c	Sun Jul 09 23:19:21 2000 +0000
@@ -720,7 +720,7 @@
 	struct aim_userinfo_s *info;
 
 	GList *bcs = buddy_chats;
-	struct buddy_chat *b = NULL;
+	struct conversation *b = NULL;
 
 	va_start(ap, command);
 	count = va_arg(ap, int);
@@ -728,7 +728,7 @@
 	va_end(ap);
 
 	while(bcs) {
-		b = (struct buddy_chat *)bcs->data;
+		b = (struct conversation *)bcs->data;
 		if (!strcasecmp(b->name, (char *)command->conn->priv))
 			break;	
 		bcs = bcs->next;
@@ -750,7 +750,7 @@
 	struct aim_userinfo_s *info;
 
 	GList *bcs = buddy_chats;
-	struct buddy_chat *b = NULL;
+	struct conversation *b = NULL;
 
 	va_start(ap, command);
 	count = va_arg(ap, int);
@@ -758,7 +758,7 @@
 	va_end(ap);
 
 	while(bcs) {
-		b = (struct buddy_chat *)bcs->data;
+		b = (struct conversation *)bcs->data;
 		if (!strcasecmp(b->name, (char *)command->conn->priv))
 			break;	
 		bcs = bcs->next;
@@ -787,14 +787,14 @@
 	char *msg;
 
 	GList *bcs = buddy_chats;
-	struct buddy_chat *b = NULL;
+	struct conversation *b = NULL;
 
 	va_start(ap, command);
 	info = va_arg(ap, struct aim_userinfo_s *);
 	msg  = va_arg(ap, char *);
 
 	while(bcs) {
-		b = (struct buddy_chat *)bcs->data;
+		b = (struct conversation *)bcs->data;
 		if (!strcasecmp(b->name, (char *)command->conn->priv))
 			break;
 		bcs = bcs->next;
--- a/src/server.c	Sun Jul 09 18:06:11 2000 +0000
+++ b/src/server.c	Sun Jul 09 23:19:21 2000 +0000
@@ -158,16 +158,16 @@
 void serv_send_im(char *name, char *message, int away)
 {
 	if (!USE_OSCAR) {
-	char buf[MSG_LEN - 7];
+		char buf[MSG_LEN - 7];
 
-        g_snprintf(buf, MSG_LEN - 8, "toc_send_im %s \"%s\"%s", normalize(name),
-                   message, ((away) ? " auto" : ""));
-	sflap_send(buf, strlen(buf), TYPE_DATA);
+	        g_snprintf(buf, MSG_LEN - 8, "toc_send_im %s \"%s\"%s", normalize(name),
+	                   message, ((away) ? " auto" : ""));
+		sflap_send(buf, strlen(buf), TYPE_DATA);
 	} else {
-	if (away)
-		aim_send_im(gaim_sess, gaim_conn, name, AIM_IMFLAGS_AWAY, message);
-	else
-		aim_send_im(gaim_sess, gaim_conn, name, 0, message);
+		if (away)
+			aim_send_im(gaim_sess, gaim_conn, name, AIM_IMFLAGS_AWAY, message);
+		else
+			aim_send_im(gaim_sess, gaim_conn, name, 0, message);
 	}
         if (!away)
                 serv_touch_idle();
@@ -520,10 +520,10 @@
 	        sflap_send(buf, -1, TYPE_DATA);
 	} else {
 		GList *bcs = buddy_chats;
-		struct buddy_chat *b = NULL;
+		struct conversation *b = NULL;
 
 		while (bcs) {
-			b = (struct buddy_chat *)bcs->data;
+			b = (struct conversation *)bcs->data;
 			if (id == b->id)
 				break;
 			bcs = bcs->next;
@@ -546,13 +546,13 @@
 	        g_free(buf);
 	} else {
 	GList *bcs = buddy_chats;
-	struct buddy_chat *b = NULL;
+	struct conversation *b = NULL;
 	struct chat_connection *c = NULL;
 	int count = 0;
 
 	while (bcs) {
 		count++;
-		b = (struct buddy_chat *)bcs->data;
+		b = (struct conversation *)bcs->data;
 		if (id == b->id)
 			break;
 		bcs = bcs->next;
@@ -600,10 +600,10 @@
 	} else {
 		struct aim_conn_t *cn;
 		GList *bcs = buddy_chats;
-		struct buddy_chat *b = NULL;
+		struct conversation *b = NULL;
 
 		while (bcs) {
-			b = (struct buddy_chat *)bcs->data;
+			b = (struct conversation *)bcs->data;
 			if (id == b->id)
 				break;
 			bcs = bcs->next;
@@ -615,6 +615,7 @@
 		cn = aim_chat_getconn(gaim_sess, b->name);
 		aim_chat_send_im(gaim_sess, cn, message);
 	}
+	serv_touch_idle();
 }
 
 
@@ -682,7 +683,7 @@
 		if (cnv != NULL) {
 			if (sound_options & OPT_SOUND_WHEN_AWAY)
 				play_sound(AWAY);
-			write_to_conv(cnv, message, away | WFLAG_RECV);
+			write_to_conv(cnv, message, away | WFLAG_RECV, NULL);
 		}
 
 	} else {
@@ -696,7 +697,7 @@
 			if (cnv->makesound && (sound_options & OPT_SOUND_RECV))
 				play_sound(RECEIVE);
 		}
-		write_to_conv(cnv, message, away | WFLAG_RECV);
+		write_to_conv(cnv, message, away | WFLAG_RECV, NULL);
 	}
 
 
@@ -726,7 +727,7 @@
 			is_idle = 1;
 		
                 if (cnv != NULL)
-			write_to_conv(cnv, awaymessage->message, WFLAG_SEND | WFLAG_AUTO);
+			write_to_conv(cnv, awaymessage->message, WFLAG_SEND | WFLAG_AUTO, NULL);
         }
 }
 
@@ -963,7 +964,7 @@
 
 void serv_got_joined_chat(int id, char *name)
 {
-        struct buddy_chat *b;
+        struct conversation *b;
 
 #ifdef GAIM_PLUGINS
 	GList *c = callbacks;
@@ -979,9 +980,10 @@
 	}
 #endif
 
-        b = (struct buddy_chat *)g_new0(struct buddy_chat, 1);
+        b = (struct conversation *)g_new0(struct conversation, 1);
         buddy_chats = g_list_append(buddy_chats, b);
 
+	b->is_chat = TRUE;
         b->ignored = NULL;
         b->in_room = NULL;
         b->id = id;
@@ -992,11 +994,11 @@
 void serv_got_chat_left(int id)
 {
         GList *bcs = buddy_chats;
-        struct buddy_chat *b = NULL;
+        struct conversation *b = NULL;
 
 
         while(bcs) {
-                b = (struct buddy_chat *)bcs->data;
+                b = (struct conversation *)bcs->data;
                 if (id == b->id) {
                         break;
                         }
@@ -1035,10 +1037,10 @@
 {
         int w;
         GList *bcs = buddy_chats;
-        struct buddy_chat *b = NULL;
+        struct conversation *b = NULL;
 
         while(bcs) {
-                b = (struct buddy_chat *)bcs->data;
+                b = (struct conversation *)bcs->data;
                 if (id == b->id)
                         break;
                 bcs = bcs->next;
--- a/src/toc.c	Sun Jul 09 18:06:11 2000 +0000
+++ b/src/toc.c	Sun Jul 09 23:19:21 2000 +0000
@@ -517,14 +517,14 @@
 		char *in;
 		char *buddy;
                 GList *bcs = buddy_chats;
-		struct buddy_chat *b = NULL;
+		struct conversation *b = NULL;
 		
 		sscanf(strtok(NULL, ":"), "%d", &id);
 
 		in = strtok(NULL, ":");
 
 		while(bcs) {
-			b = (struct buddy_chat *)bcs->data;
+			b = (struct conversation *)bcs->data;
 			if (id == b->id)
 				break;	
 			bcs = bcs->next;