/*
 * EveryBuddy 
 *
 * Copyright (C) 1999, Torrey Searle <tsearle@uci.edu>
 *
 * 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
 *
 */

/*
 * chat_window.c
 * implementation for the conversation window
 *
 */

#include <string.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <ctype.h>
#include "chat_window.h"
#include "util.h"
#include "gtkhtml.h"
#include "gtkspell.h"
#include "add_contact_window.h"
#include "sound.h"
#include "dialog.h"
#include "globals.h"
#include "status.h"
#include "away_window.h"
#include "message_parse.h"
//#include "gtksctext.h"
#include "gtk_eb_html.h"
#include "pixmaps/tb_book_red.xpm"
#include "pixmaps/tb_open.xpm"
#include "pixmaps/tb_volume.xpm"
#include "pixmaps/tb_edit.xpm"
#include "pixmaps/tb_search.xpm"
#include "pixmaps/tb_no.xpm"
#include "pixmaps/tb_mail_send.xpm"
#include "pixmaps/cancel.xpm"

#define BUF_SIZE 1024  /* Maximum message length */
#ifndef NAME_MAX
#define NAME_MAX 4096
#endif


#ifdef HAVE_ICONV_H
#include <iconv.h>
#endif


/*
    Recodes source text with iconv() and puts it in translated_text
    returns pointer to recoded text
*/
char *
recode_if_needed(char * source_text, char * recoded_text, int to_remote)
{

#ifdef HAVE_ICONV_H
	size_t inleft;
	size_t outleft;
	const char * ptr_src_text = source_text;
	char * ptr_recoded_text = recoded_text;
	iconv_t conv_desc;

    if( use_recoding == 1 )
    {
	if( to_remote == 1 )
	    conv_desc = iconv_open( remote_encoding, local_encoding );
	else
	    conv_desc = iconv_open( local_encoding, remote_encoding );

	if( conv_desc != (iconv_t)(-1) )
	{
	    ptr_src_text = source_text;
	    inleft = outleft = strlen(source_text) + 1;
		
	    iconv(conv_desc, &ptr_src_text, &inleft, 
			    &ptr_recoded_text, &outleft);
	    if( inleft || outleft )
	    {
	    /* translation is broken - leave the rest as it is :(
		may be better solution is to skip this char and 
		translate all other symbols */
		
		strcpy( ptr_recoded_text, ptr_src_text );
		fprintf( stderr, "Everybuddy: recoding broke in the middle "
				"of the line, leaving the rest as it is...\n");
	    }
	    iconv_close(conv_desc);
	    return recoded_text;
	}
	else
	{
	    fprintf( stderr, "Everybuddy: recoding from %s to %s is not valid, sorry!\n"
			"Turning recoding off.\n",
			     local_encoding, remote_encoding);
	    use_recoding = 0;
	    return source_text;
	}
    }
#endif

    return source_text;
}


static void destroy_event(GtkWidget *widget, gpointer data)
{
	GList * node;
	chat_window * cw = (chat_window *)data;
	gtk_widget_destroy(cw->window);
	cw->window=NULL;
	cw->contact->chatwindow = NULL;

	for(node = cw->contact->accounts; node; node = node->next)
	{
		eb_account * ea = (eb_account*)(node->data);
		
		if(eb_services[ea->service_id].sc->terminate_chat)
		{
			RUN_SERVICE(ea)->terminate_chat(ea);
		}
	}

	if(do_logging)
	{
		time_t my_time = time(NULL);

		fprintf(cw->fp, "%sConversation ended on %s %s\n",
			(do_strip_html ? "" : "<P ALIGN=\"CENTER\"><B>"),
			g_strchomp(asctime(localtime(&my_time))), 
			(do_strip_html ? "" : "</B></P>"));
	}

	if ((cw->fp != NULL )) fclose(cw->fp);
	
	g_free(cw);
}

static void add_unknown_callback(GtkWidget * add_button, gpointer userdata)
{
	chat_window * cw = userdata;

	/* if something wierd is going on and the unknown contact has multiple
	 * accounts, find use the perfered accout
	 */

	cw->perfered = find_suitable_remote_account(cw->perfered, cw->contact);

	/* if in the wierd case that the unknown user has gone offline
	 * just use the first account you see
	 */
	 
	if(!cw->perfered)
		cw->perfered = cw->contact->accounts->data;

	/* if that fails, something is seriously wrong
	 * bail out while you can
	 */

	if(!cw->perfered)
		return;

	/* now that we have a valid account, pop up the window already :) */

	add_unknown_account_window_new(cw->perfered);
}

void send_message(GtkWidget *widget, gpointer d)
{
	chat_window * data = (chat_window*)d;
	gchar buff[BUF_SIZE];
	gchar buff2[BUF_SIZE];
	gchar * text;
	gchar * link_message;
	struct tm * cur_time;
	time_t t;

#ifdef HAVE_ICONV_H
    /* 'BUF_SIZE*2' e.g. for 'Latin-x' to 'UTF-8', 
	which is 1-byte to 2-byte recoding */
	char recode_buff[BUF_SIZE*2];	
#endif	
	/*determine what is the best account to send to*/

	data->perfered= find_suitable_remote_account(data->perfered, data->contact);
	
	if(!data->perfered)
	{
		/*Eventually this will need to become a dialog box that pops up*/

		if(data->contact->send_offline && can_offline_message(data->contact))
		{
			data->perfered = can_offline_message(data->contact);
		}
		else
		{
			gtk_eb_html_add(GTK_TEXT(data->chat), "<P><B>User is offline</B></P>\n");
			return;
		}
	}
	
	if(data->local_user && data->local_user->service_id != data->perfered->service_id)
	{
		data->local_user = NULL;
	}
	
	if(data->local_user && !data->local_user->connected)
	{
		data->local_user = NULL;
	}
	
	/*determine what is the best local account to use*/

	data->local_user =
			find_suitable_local_account(data->local_user, data->perfered->service_id);
	
	if(!data->local_user)
		return;
	
	g_snprintf(buff, BUF_SIZE, "%s (%s <=> %s via %s)",
			data->contact->nick, data->local_user->alias,
			data->perfered->handle, GET_SERVICE(data->perfered).name);

	gtk_window_set_title(GTK_WINDOW(data->window), buff);
   
	text = gtk_editable_get_chars(GTK_EDITABLE (data->entry), 0, -1);

	if(strlen(text) == 0)
		return;

	link_message = linkify(text);

	g_snprintf(buff, BUF_SIZE, "%s (%s <=> %s via %s)",
			data->contact->nick, data->local_user->alias,
			data->perfered->handle, GET_SERVICE(data->perfered).name);

	gtk_window_set_title(GTK_WINDOW(data->window), buff);
	
#ifdef HAVE_ICONV_H    
	RUN_SERVICE(data->local_user)->send_im(
							data->local_user,
							data->perfered,
					recode_if_needed(text, recode_buff, 1) );
	/* seems like variable 'text' is not used any more down
	    the function, so we don't have to assign it (BTW it's freed in the end)*/
#else
	RUN_SERVICE(data->local_user)->send_im(
								data->local_user,
								data->perfered,
								text);
#endif
	serv_touch_idle();
	
	if(data->sound_enabled)
		play_sound(SEND);
	
	if (do_convo_timestamp) 
	{
		time(&t);
		cur_time = localtime(&t);
		g_snprintf(buff2, BUF_SIZE, "%d:%.2d:%.2d %s", cur_time->tm_hour, 
				   cur_time->tm_min, cur_time->tm_sec, 
				   data->local_user->alias);
	} 
	else 
	{ 
		g_snprintf(buff2, BUF_SIZE, "%s", data->local_user->alias); 
	} 
 
	g_snprintf(buff, BUF_SIZE, "<FONT COLOR=\"#0000ff\"><B>%s: </B></FONT>", buff2); 

	gtk_eb_html_add(GTK_TEXT(data->chat), buff);
	gtk_eb_html_add(GTK_TEXT(data->chat), link_message);
	gtk_eb_html_add(GTK_TEXT(data->chat), "<br>");

	/* If an away message had been sent to this person, reset the away message tracker */
	/* It's probably faster to just do the assignment all the time--the test
	   is there for code clarity. */

	if (data->away_msg_sent) data->away_msg_sent = FALSE;
	
	/* Log the message */

	if(do_logging) eb_log_message(data->fp, buff, link_message); 
	
	gtk_editable_delete_text(GTK_EDITABLE (data->entry), 0, -1);
	g_free(link_message);
	g_free(text);
}

static GtkWidget * file_selector;

static void store_filename(GtkFileSelection *selector, eb_account * ea) 
{
	char *selected_filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION(file_selector));
	eb_account * x_fer_account;
    
    if ( ea == NULL )  // Accout is offline
    {
        return;
    }
        
    x_fer_account = find_suitable_file_transfer_account(ea, ea->account_contact);

	if(x_fer_account)
	{
		eb_local_account * ela = find_suitable_local_account(NULL, x_fer_account->service_id);

		RUN_SERVICE(ela)->send_file(ela, x_fer_account, selected_filename);
	}
	else
	{
		eb_local_account * ela = find_suitable_local_account(NULL, ea->service_id);
		strcpy(filename, selected_filename);
		RUN_SERVICE(ela)->send_im(ela, ea, "EB_COMMAND SEND_FILE");
	}
}

/*These are the action handlers for the buttons*/

/*** MIZHI
 * callback function for viewing the log
 */
static void view_log_callback(GtkWidget *widget, gpointer d)
{
  chat_window* cw = (chat_window*)d;

  if (cw->contact->logwindow == NULL) {
    cw->contact->logwindow = eb_log_window_new(cw->contact);
  }
}

/*This is the callback for ignoring a user*/
static void ignore_dialog_callback (GtkWidget *widget, gpointer userdata)
{
	struct contact *c = (struct contact *)userdata;
	int response = (int)gtk_object_get_user_data(GTK_OBJECT(widget));

	if (response) 
	{
		move_contact("Ignore", c);
      		//refresh_contact_list();
		MakeEditContactList();
		write_contact_list();
	}
	
}

static void ignore_callback (GtkWidget *ignore_button, gpointer userdata)
{
	chat_window * cw = (chat_window *)userdata;
	gchar *buff = (gchar *)g_new0(gchar *, BUF_SIZE);
	
	g_snprintf(buff, BUF_SIZE, "Do you really want to ignore %s?\n", cw->contact->nick);

	do_dialog(buff, "Ignore Contact", ignore_dialog_callback, cw->contact);	
}

/*This is the callback for file x-fer*/
static void send_file (GtkWidget * sendf_button, gpointer userdata)
{
	eb_account *ea;
    
	if ( ((chat_window*)userdata)->contact->online == 0 )
	{
		gtk_eb_html_add(GTK_TEXT(((chat_window*)userdata)->chat), "<P><B>User is offline</B></P>\n");
        	return;
	}
    
	ea = find_suitable_remote_account(((chat_window *)userdata)->perfered,
						((chat_window *)userdata)->contact);
                                                    
	file_selector = gtk_file_selection_new("Please select a file to send");
   
	file_selector = gtk_file_selection_new("Please select a file for editing.");
   
	gtk_signal_connect(GTK_OBJECT (GTK_FILE_SELECTION(file_selector)->ok_button),
                             "clicked", GTK_SIGNAL_FUNC (store_filename), ea);
   
	gtk_signal_connect_object(GTK_OBJECT (GTK_FILE_SELECTION(file_selector)->ok_button),
                                            "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy),
                                            (gpointer) file_selector);

	gtk_signal_connect_object(GTK_OBJECT (GTK_FILE_SELECTION(file_selector)->cancel_button),
                                            "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy),
                                            (gpointer) file_selector);
                                            
	gtk_widget_show (file_selector);	
}

/*These are the callback for setting the sound*/

static void set_sound_on_toggle(GtkWidget * sound_button, gpointer userdata)
{
	chat_window * cw = (chat_window *)userdata;
   
	/*Set the sound_enable variable depending on the toggle button*/
   
	if (GTK_TOGGLE_BUTTON (sound_button)->active)
		cw->sound_enabled = TRUE;
	else
   		cw->sound_enabled = FALSE;
}

static void set_sound_on_click(GtkWidget * button, gpointer userdata)
{
	chat_window * cw = (chat_window *)userdata;
   
	if (cw->sound_enabled)
	{
   		cw->sound_enabled = FALSE;
		gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(cw->sound_button), FALSE);
	}

	else
	{
   		cw->sound_enabled = TRUE;
		gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(cw->sound_button), TRUE);
	}
}

/*This is the callback for closing the window*/

static void close_win (GtkWidget * close_button, gpointer userdata)
{
	chat_window * cw = (chat_window *)userdata;
	gtk_widget_destroy(cw->window);

#if 0
	cw->window=NULL;
	cw->contact->chatwindow = NULL;
	if(do_logging)
	{
		time_t my_time = time(NULL);

		fprintf(cw->fp, "%sConversation ended on %s %s\n",
			(do_strip_html ? "" : "<P ALIGN=\"CENTER\"><B>"),
			g_strchomp(asctime(localtime(&my_time))), 
			(do_strip_html ? "" : "</B></P>") );
	}
	fclose(cw->fp);
	g_free(cw);
#endif

}

static void allow_offline_on_toggle (GtkWidget *allow_button, gpointer userdata)
{ 
	chat_window * cw = (chat_window *)userdata;

	/*set send_offline based upon toggle button*/

	if (GTK_TOGGLE_BUTTON (allow_button)->active) 
		cw->contact->send_offline = TRUE;
	else
  		cw->contact->send_offline = FALSE;
}

static void allow_offline_on_click (GtkWidget * button, gpointer userdata)
{
	chat_window * cw = (chat_window *)userdata;

	if (cw->contact->send_offline)
   	{
   		cw->contact->send_offline = FALSE;
		gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(cw->allow_button), FALSE);
	}
   	else
	{
		cw->contact->send_offline = TRUE;
		gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(cw->allow_button), TRUE);      
	}    
}

/*This handles the right mouse button clicks*/

static void handle_click(GtkWidget *widget, GdkEventButton * event, gpointer userdata)
{
	if (event->type == GDK_BUTTON_PRESS && event->button == 3)
	{
		GtkWidget *menu;
		GtkWidget *button;

   		chat_window * cw = (chat_window*)userdata;
	
   		menu = gtk_menu_new();

		/*Add Contact Selection*/

		if(!strcmp(cw->contact->group->name, "Unknown"))
      		{
      			button = gtk_menu_item_new_with_label("Add Contact");
      			gtk_signal_connect(GTK_OBJECT(button), "activate",
						GTK_SIGNAL_FUNC(add_unknown_callback), cw);
			gtk_menu_append(GTK_MENU(menu), button);
			gtk_widget_show(button);
		}
      
		/*Allow Offline Messaging Selection*/

		if(can_offline_message(cw->contact))
		{	
			button = gtk_menu_item_new_with_label("Offline Messaging");
			gtk_signal_connect(GTK_OBJECT(button), "activate",
						GTK_SIGNAL_FUNC(allow_offline_on_click), cw);
			gtk_menu_append(GTK_MENU(menu), button);
			gtk_widget_show(button);
		}

		/*Sound Selection*/

   		if (cw->sound_enabled)
   			button = gtk_menu_item_new_with_label("Disabled Sounds");
   		else
   			button = gtk_menu_item_new_with_label("Enable Sounds");  

       
		gtk_signal_connect(GTK_OBJECT(button), "activate",
							GTK_SIGNAL_FUNC(set_sound_on_click), cw); 
   		gtk_menu_append(GTK_MENU(menu), button);
   		gtk_widget_show(button);

		/*View log selection*/
		
		button = gtk_menu_item_new_with_label("View Log");
		gtk_signal_connect(GTK_OBJECT(button), "activate",
							GTK_SIGNAL_FUNC(view_log_callback), cw);
		gtk_menu_append(GTK_MENU(menu), button);
		gtk_widget_show(button);
		
		/*Send File Selection*/

		button = gtk_menu_item_new_with_label("Send File");
		gtk_signal_connect(GTK_OBJECT(button), "activate",
							GTK_SIGNAL_FUNC(send_file), cw);
		gtk_menu_append(GTK_MENU(menu), button);
		gtk_widget_show(button);

		/*Ignore Section*/

		button = gtk_menu_item_new_with_label("Ignore Contact");
		gtk_signal_connect(GTK_OBJECT(button), "activate",
							GTK_SIGNAL_FUNC(ignore_callback), cw);
		gtk_menu_append(GTK_MENU(menu), button);
		gtk_widget_show(button);

		/*Send message Section*/

		button = gtk_menu_item_new_with_label("Send Message");
		gtk_signal_connect(GTK_OBJECT(button), "activate",
							GTK_SIGNAL_FUNC(send_message), cw);
		gtk_menu_append(GTK_MENU(menu), button);
		gtk_widget_show(button);	

		/*Close Selection*/
		
		button = gtk_menu_item_new_with_label("Close");

		gtk_signal_connect(GTK_OBJECT(button), "activate",
							GTK_SIGNAL_FUNC(close_win), cw);
		gtk_menu_append(GTK_MENU(menu), button);
		gtk_widget_show(button);
   
		gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
						event->button, event->time );
	}
}

#if 0
static void chat_insert_text( GtkEditable * editable, gchar * new_text,
							  gint length, gint * position,
							  gpointer data )
{
	gtk_signal_handler_block_by_func(GTK_OBJECT(editable),
									 GTK_SIGNAL_FUNC(chat_insert_text),
									 data);
	//gtk_editable_insert_text( editable, new_text, length, position );
	gtk_text_set_point(GTK_TEXT(editable), *position);
	gtk_text_insert(GTK_TEXT(editable), NULL, &(GTK_WIDGET(editable)->style->fg[0]),
					NULL, new_text, length );
#ifdef HAVE_ISPELL
	if(isspace(new_text[0]))
	{
		gtk_text_freeze(GTK_TEXT(editable));
		spell_check(GTK_WIDGET(editable));
		gtk_text_thaw(GTK_TEXT(editable));
	}
#endif

	gtk_signal_handler_unblock_by_func(GTK_OBJECT(editable),
							   GTK_SIGNAL_FUNC(chat_insert_text),
							   data);
	gtk_signal_emit_stop_by_name(GTK_OBJECT(editable), "insert-text");
}

static void chat_button_press_after(GtkWidget *widget, GdkEventButton * event, int * data)
{
  /* jump to cursor mark */
	gchar *word;
	gtk_text_set_point (GTK_TEXT (widget),
				gtk_editable_get_position (GTK_EDITABLE  (widget)));
	word=find_word(widget, gtk_editable_get_position(GTK_EDITABLE(widget)));
	spell_menu(word, (GdkEvent*)event, widget);
	gtk_signal_disconnect(GTK_OBJECT(widget), *data);
	free(data);
}

static void chat_button_press(GtkWidget *widget, GdkEventButton * event, gpointer d )
{
	GTK_EDITABLE_CLASS( GTK_OBJECT(widget)->klass)->move_cursor(GTK_EDITABLE(widget), 
				event->x,
				event->y);
	if(event->type == GDK_BUTTON_PRESS && event->button == 3)
	{
		int  *data = g_new0(int, 1 );
		*data = gtk_signal_connect_after(GTK_OBJECT(widget), 
						"button_press_event", 
						GTK_SIGNAL_FUNC(chat_button_press_after), data);
 	}

	return;
}
#endif

static void chat_key_press(GtkWidget *widget, GdkEventKey *event, gpointer data)
{
  	chat_window *cw = (chat_window *)data;
  
  	if (event->keyval == GDK_Return)
  	{
    		/* Just print a newline on Shift-Return */
    		if (event->state & GDK_SHIFT_MASK)
		{
      			event->state = 0;
		}
    		else if (do_enter_send) 
		{
      			/*Prevents a newline from being printed*/
      			event->keyval = GDK_BackSpace; 
      			send_message(NULL, cw);
    		}
  	}
}
   
chat_window * eb_chat_window_new(eb_local_account * local, struct contact * remote)
{
	GtkWidget *vbox;
	GtkWidget *hbox;
	GtkWidget *scrollwindow;
	GtkWidget *toolbar;
	GtkWidget *add_button;
	GtkWidget *sendf_button;
	GtkWidget *send_button;
	GtkWidget *view_log_button;
	GtkWidget *close_button;
	GtkWidget *ignore_button;
  	GtkWidget *iconwid;
  	GdkPixmap *icon;
	GdkBitmap *mask;
	GtkAccelGroup *accel_group; 
	GtkWidget *menu;
	GtkWidget *button;
	GtkWidget *separator;
	GtkWidget *resize_bar;
	gchar buff[NAME_MAX];
	chat_window * cw;
		
	if (do_ignore_unknown)
	{
		if (!strcmp("Unknown", remote->group->name))
			return NULL;
	}
			
	cw = g_new0(chat_window,1);
	cw->contact = remote;
	cw->away_msg_sent = 0;
	vbox = gtk_vbox_new(FALSE,0);	
	
	cw->perfered = NULL;
	cw->local_user = NULL;
	
	cw->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

	/* Next line allows making window smaller than orig. size */

	gtk_window_set_wmclass(GTK_WINDOW(cw->window), "everybuddy-chat", "Everybuddy");
	gtk_window_set_policy(GTK_WINDOW(cw->window), TRUE, TRUE, TRUE);
	gtk_widget_realize(cw->window);
	cw->chat = gtk_text_new(NULL,NULL);
	gtk_text_set_editable(GTK_TEXT(cw->chat), FALSE);
	gtk_text_set_word_wrap(GTK_TEXT(cw->chat), TRUE);
	scrollwindow = gtk_scrolled_window_new(NULL,
								GTK_TEXT(cw->chat)->vadj);
	gtk_widget_realize(cw->window);
	gtk_window_set_title(GTK_WINDOW(cw->window), remote->nick);
	eb_icon(cw->window->window);	
	gtk_widget_set_usize(scrollwindow, 375, 150);
	gtk_container_add(GTK_CONTAINER(scrollwindow),
							cw->chat);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwindow), 
			GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
	gtk_widget_show(scrollwindow);

	/* Create the bar for resizing chat/window box */
	
	/*Add stuff for multi-line*/
   
	if(do_multi_line)
	{
		resize_bar = gtk_vpaned_new();
		gtk_paned_set_gutter_size(GTK_PANED(resize_bar), 20);
		gtk_paned_pack1(GTK_PANED(resize_bar), scrollwindow, TRUE, TRUE);
		gtk_widget_show(scrollwindow);

   		scrollwindow = gtk_scrolled_window_new(NULL, NULL);
   		gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrollwindow), 
				GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
		
		cw->entry = gtk_text_new(NULL, NULL);
     
		gtk_widget_set_usize(scrollwindow, 375, 50);                                
		gtk_container_add(GTK_CONTAINER(scrollwindow), cw->entry);
      
		gtk_text_set_editable(GTK_TEXT(cw->entry), TRUE);
		gtk_text_set_word_wrap(GTK_TEXT(cw->entry), TRUE);
		gtk_text_set_line_wrap(GTK_TEXT(cw->entry), TRUE);
      
#ifdef HAVE_ISPELL
		if(!gtkspell_running())
		{
			gchar *ispell_cmd[] = { "ispell", "-a", NULL };
			gtkspell_start(NULL, ispell_cmd);
		}
		gtkspell_attach(GTK_TEXT(cw->entry));
#endif

#if 0 
		gtk_signal_connect(GTK_OBJECT(cw->entry), "insert-text",
				GTK_SIGNAL_FUNC(chat_insert_text),
				cw);
		
		gtk_signal_connect(GTK_OBJECT(cw->entry), "button_press_event", 
				GTK_SIGNAL_FUNC(chat_button_press), cw);
#endif 	/* HAVE_ISPELL*/

		gtk_signal_connect(GTK_OBJECT(cw->entry), "key_press_event",
				GTK_SIGNAL_FUNC(chat_key_press),
				cw);
                                      
		gtk_paned_pack2(GTK_PANED(resize_bar), scrollwindow, FALSE, FALSE);
		gtk_widget_show(scrollwindow);
		gtk_box_pack_start(GTK_BOX(vbox),resize_bar, TRUE, TRUE, 5);
		gtk_widget_show(resize_bar);
	}
   
	/*Or not multi-line*/
   
	else
	{
		cw->entry = gtk_entry_new();
		gtk_box_pack_start(GTK_BOX(vbox), scrollwindow, TRUE,TRUE, 5);
		gtk_box_pack_start(GTK_BOX(vbox), cw->entry, FALSE,FALSE, 5);
	}  
      
	gtk_container_set_border_width(GTK_CONTAINER(cw->window), 5);
	gtk_container_add(GTK_CONTAINER(cw->window), vbox);

	gtk_signal_connect(GTK_OBJECT(cw->entry), "activate",
			GTK_SIGNAL_FUNC(send_message), cw);
	gtk_signal_connect(GTK_OBJECT(cw->window), "destroy",
			GTK_SIGNAL_FUNC(destroy_event), cw);	
	gtk_signal_connect(GTK_OBJECT(cw->chat), "button_press_event",
			GTK_SIGNAL_FUNC(handle_click), cw);                     	
	
	hbox = gtk_hbox_new(FALSE, 0);
	gtk_widget_set_usize(hbox, 200, 25);
   
	toolbar = gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_ICONS);
	gtk_toolbar_set_button_relief(GTK_TOOLBAR(toolbar), GTK_RELIEF_NONE);
	gtk_container_set_border_width(GTK_CONTAINER(toolbar), 0);
	gtk_toolbar_set_space_size(GTK_TOOLBAR(toolbar), 5);        	
  
  	/* Adding accelerators to windows*/
	
  	accel_group = gtk_accel_group_new();
  	gtk_window_add_accel_group(GTK_WINDOW(cw->window), accel_group);
  	menu = gtk_menu_new();
  
	/* This is the same as handle_clicks, without showing the menu for
   	accelerators to hopefully work better now. 
	*/
   
  	/*Add Contact Selection*/
   
	if(!strcmp(cw->contact->group->name, "Unknown"))
	{
		button = gtk_menu_item_new_with_label("Add Contact");
		gtk_signal_connect(GTK_OBJECT(button), "activate",
				GTK_SIGNAL_FUNC(add_unknown_callback),
				cw);
		gtk_menu_append(GTK_MENU(menu), button);
	}
      
	/*Allow Offline Messaging Selection*/
   
	if(can_offline_message(cw->contact))
	{	
		button = gtk_menu_item_new_with_label("Offline Messaging");
		gtk_signal_connect(GTK_OBJECT(button), "activate",
				GTK_SIGNAL_FUNC(allow_offline_on_click),
				cw);
		gtk_widget_add_accelerator(button, "activate", accel_group, 
				GDK_o, GDK_CONTROL_MASK,
				GTK_ACCEL_VISIBLE);
		gtk_menu_append(GTK_MENU(menu), button);
	}

	/*Sound Selection*/
   
  	if (cw->sound_enabled)
	{
		button = gtk_menu_item_new_with_label("Disabled Sounds");
	}
	else
	{
   		button = gtk_menu_item_new_with_label("Enable Sounds");
	}  
       
	gtk_signal_connect(GTK_OBJECT(button), "activate",
			GTK_SIGNAL_FUNC(set_sound_on_click),
			cw); 
	gtk_widget_add_accelerator(button, "activate", accel_group, 
			GDK_s, GDK_CONTROL_MASK,
			GTK_ACCEL_VISIBLE);
	gtk_menu_append(GTK_MENU(menu), button);

	/* Ignore button section */

	button = gtk_menu_item_new_with_label("Ignore Contact");
	gtk_signal_connect(GTK_OBJECT(button), "activate",
	GTK_SIGNAL_FUNC(ignore_callback), cw);
	gtk_widget_add_accelerator(button, "activate", accel_group,
			GDK_g, GDK_CONTROL_MASK,
			GTK_ACCEL_VISIBLE);
	gtk_menu_append(GTK_MENU(menu), button);

	/*Send File Selection*/ 
          
	button = gtk_menu_item_new_with_label("Send File");
	gtk_signal_connect(GTK_OBJECT(button), "activate",
			GTK_SIGNAL_FUNC(send_file),
			cw);
	gtk_widget_add_accelerator(button, "activate", accel_group, 
			GDK_t, GDK_CONTROL_MASK,
			GTK_ACCEL_VISIBLE);
	gtk_menu_append(GTK_MENU(menu), button);
	
	/*Send Selection*/
      
	button = gtk_menu_item_new_with_label("Send Message");
  	gtk_signal_connect(GTK_OBJECT(button), "activate",
			GTK_SIGNAL_FUNC(send_message),
			cw);
	gtk_widget_add_accelerator(button, "activate", accel_group, 
			GDK_r, GDK_CONTROL_MASK,
			GTK_ACCEL_VISIBLE);
	gtk_menu_append(GTK_MENU(menu), button);  

	/*** MIZHI
	* view log file selection
	*/

	button = gtk_menu_item_new_with_label("View log");
	gtk_signal_connect(GTK_OBJECT(button), "activate",
			GTK_SIGNAL_FUNC(view_log_callback),
			cw);
	gtk_widget_add_accelerator(button, "activate", accel_group, 
			GDK_l, GDK_CONTROL_MASK,
			GTK_ACCEL_VISIBLE);
	gtk_menu_append(GTK_MENU(menu), button);
	
	/*Close Selection*/
      
	button = gtk_menu_item_new_with_label("Close");
  	gtk_signal_connect(GTK_OBJECT(button), "activate",
			GTK_SIGNAL_FUNC(close_win),
			cw);
	gtk_widget_add_accelerator(button, "activate", accel_group, 
			GDK_q, GDK_CONTROL_MASK,
			GTK_ACCEL_VISIBLE);
	gtk_menu_append(GTK_MENU(menu), button);  
  
	/*This is we decide whether or not the add button should be displayed*/
   
	if (!strcmp(cw->contact->group->name, "Unknown"))
	{
		/*This is the add button*/
		icon = gdk_pixmap_create_from_xpm_d(cw->window->window, &mask, NULL, tb_book_red_xpm);
		iconwid = gtk_pixmap_new(icon , mask);
		gtk_widget_show(iconwid);
		add_button = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),
				"Add",
				"Add Contact",
				"Add",
				iconwid,
				GTK_SIGNAL_FUNC(add_unknown_callback),
				cw);
		gtk_toolbar_append_space(GTK_TOOLBAR(toolbar));
	}
		
	/*Decide whether the offline messaging button should be displayed*/

	if(can_offline_message(remote))
	{
		icon = gdk_pixmap_create_from_xpm_d(cw->window->window, &mask, NULL, tb_edit_xpm);
		iconwid = gtk_pixmap_new(icon , mask);
		gtk_widget_show(iconwid);
		cw->allow_button = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
				GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
				NULL,
				"Allow",
				"Allow Offline Messaging CTRL+O",
				"Allow",
				iconwid,
				GTK_SIGNAL_FUNC(allow_offline_on_toggle),
				cw);
		gtk_toolbar_append_space(GTK_TOOLBAR(toolbar));
		gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(cw->allow_button), FALSE);
	}
   
	/*This is the sound toggle button*/

	icon = gdk_pixmap_create_from_xpm_d(cw->window->window, &mask, NULL, tb_volume_xpm);
	iconwid = gtk_pixmap_new(icon, mask);
	gtk_widget_show(iconwid);
	cw->sound_button = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
			GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
			NULL,
			"Sound",
			"Enable Sounds CTRL+S",
			"Sound",
			iconwid,
			GTK_SIGNAL_FUNC(set_sound_on_toggle),
			cw);
	gtk_toolbar_append_space(GTK_TOOLBAR(toolbar));
   
	/*Toggle the sound button based on preferences*/
   
	if (do_play_sounds)
		gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(cw->sound_button), TRUE);
	else
		gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(cw->sound_button), FALSE);

	/*Create the separator for the toolbar*/

	separator = gtk_vseparator_new();
	gtk_widget_set_usize(GTK_WIDGET(separator), 0, 20);
	gtk_toolbar_append_widget(GTK_TOOLBAR(toolbar), separator, NULL, NULL);
	gtk_widget_show(separator);
	gtk_toolbar_append_space(GTK_TOOLBAR(toolbar));
   
	/*** MIZHI
	* create the button for the log viewing functions
	*/

	icon = gdk_pixmap_create_from_xpm_d(cw->window->window, &mask, NULL, tb_search_xpm);
	iconwid = gtk_pixmap_new(icon, mask);
	gtk_widget_show(iconwid);
	view_log_button = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),
			"View",
			"View Log CTRL+L",
			"View",
			iconwid,
			GTK_SIGNAL_FUNC(view_log_callback),
			cw);
	gtk_toolbar_append_space(GTK_TOOLBAR(toolbar)); 

	/*This is the send file button*/

	icon = gdk_pixmap_create_from_xpm_d(cw->window->window, &mask, NULL, tb_open_xpm);
	iconwid = gtk_pixmap_new(icon, mask);
	gtk_widget_show(iconwid);
	sendf_button = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),
			"sendf",
			"Send File CTRL+T",
			"sendf",
			iconwid,
			GTK_SIGNAL_FUNC(send_file),
			cw);
	gtk_toolbar_append_space(GTK_TOOLBAR(toolbar)); 
  
	/*This is the ignore button*/

	icon = gdk_pixmap_create_from_xpm_d(cw->window->window, &mask, NULL, tb_no_xpm);
	iconwid = gtk_pixmap_new(icon, mask);
	gtk_widget_show(iconwid); 
	ignore_button = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),
			"ignore", 
			"Ignore CTRL+G", 
			"ignore",
			iconwid, 
			GTK_SIGNAL_FUNC(ignore_callback), 
			cw);
	gtk_toolbar_append_space(GTK_TOOLBAR(toolbar)); 

	/*This is the send button*/

	icon = gdk_pixmap_create_from_xpm_d(cw->window->window, &mask, NULL, tb_mail_send_xpm);
	iconwid = gtk_pixmap_new(icon, mask);
	gtk_widget_show(iconwid); 
	send_button = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),
			"send", 
			"Send Message CTRL+R", 
			"send",
			iconwid, 
			GTK_SIGNAL_FUNC(send_message), 
			cw);
	gtk_toolbar_append_space(GTK_TOOLBAR(toolbar)); 

	/* Vertical separator */
	
	separator = gtk_vseparator_new();
	gtk_widget_set_usize(GTK_WIDGET(separator), 0, 20);
	gtk_toolbar_append_widget(GTK_TOOLBAR(toolbar), separator, NULL, NULL);
	gtk_widget_show(separator);
	gtk_toolbar_append_space(GTK_TOOLBAR(toolbar));
	
	/*This is the close button*/

	icon = gdk_pixmap_create_from_xpm_d(cw->window->window, &mask, NULL, cancel_xpm);
	iconwid = gtk_pixmap_new(icon, mask);
	gtk_widget_show(iconwid);
	close_button = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),
			"close",
			"Close CTRL+Q",
			"close",
			iconwid,
			GTK_SIGNAL_FUNC(close_win),
			cw);                                       
	gtk_box_pack_end(GTK_BOX(hbox), toolbar, FALSE, FALSE, 0);
	gtk_widget_show(toolbar);
   
	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
	gtk_widget_show(hbox);

	make_safe_filename(buff, remote->nick);

	if ((cw->fp = fopen(buff, "a")) == NULL) 
	{
		perror(buff);
		do_logging=0;
	}

	if(do_logging)
	{
		time_t my_time = time(NULL);
		fprintf(cw->fp, "%sConversation started on %s %s\n",
				(do_strip_html ? "" : "<HR WIDTH=\"100\%\"><P ALIGN=\"CENTER\"><B>"),
				g_strchomp(asctime(localtime(&my_time))), (do_strip_html?"":"</B></P>"));
		fflush(cw->fp);
	}
	
	gtk_widget_show(cw->chat);
	gtk_widget_show(cw->entry);
	gtk_widget_show(vbox);

	return cw;		
}

void eb_chat_window_display_error(eb_account * remote, gchar * message)
{
	struct contact * remote_contact = remote->account_contact;
	
	if(remote_contact->chatwindow)
	{
    	gtk_eb_html_add(GTK_TEXT(remote_contact->chatwindow->chat), 
						"<b>Error: </b>");
		gtk_eb_html_add(GTK_TEXT(remote_contact->chatwindow->chat), message);
		gtk_eb_html_add(GTK_TEXT(remote_contact->chatwindow->chat), "<br>");
	}
}

void eb_chat_window_do_timestamp(struct contact * c, gboolean online)
{
	gchar buff[BUF_SIZE];
	time_t my_time = time(NULL);
	if(!c || !c->chatwindow)
		return;
	
	if(!do_timestamp)
	{
		return;
	}

	gtk_eb_html_add(GTK_TEXT(c->chatwindow->chat), "<hr>");
	g_snprintf(buff, BUF_SIZE,"<b>%s is logged %s @ %s.</b>", 
			   c->nick, (online?"in":"out"), g_strchomp(asctime(localtime(&my_time))));
	gtk_eb_html_add(GTK_TEXT(c->chatwindow->chat), buff);
	gtk_eb_html_add(GTK_TEXT(c->chatwindow->chat), "<hr>");
}
	

void eb_chat_window_display_remote_message(eb_local_account * account,
											eb_account * remote,
		                                    gchar * message)
{
	struct contact * remote_contact = remote->account_contact;
	gchar buff[BUF_SIZE];
	gchar buff2[BUF_SIZE];
	struct tm * cur_time;
	time_t t;
	gboolean firstmsg = FALSE; /* init to false so only play if
				    * first msg is one received rather
				    * than sent */
#ifdef HAVE_ICONV_H
    /* 'BUF_SIZE*2' e.g. for 'Latin-x' to 'UTF-8', 
	which is 1-byte to 2-byte recoding */
	char recode_buff[BUF_SIZE*2];	
#endif

	/* do we need to ignore this user? */

	if(!strcasecmp(remote_contact->group->name, "Ignore" ))
		return;
	
	if(!remote_contact->chatwindow || !remote_contact->chatwindow->window)
	{
		if(remote_contact->chatwindow)
			g_free(remote_contact->chatwindow);

		remote_contact->chatwindow = eb_chat_window_new(account, remote_contact);

		if (!remote_contact->chatwindow)
			/* this message is ignored */
			return;

		gtk_widget_show(remote_contact->chatwindow->window);
		firstmsg = TRUE;        /* chat window created by
					 * receive msg, so set to true */
		if (do_restore_last_conv){
		   gchar buff[1024];
  	   make_safe_filename(buff, remote_contact->nick);
       eb_restore_last_conv(buff,remote_contact->chatwindow);
    }
	}
	
	/*for now we will assume the identity that the person in question talked
	  to us last as */
	
	remote_contact->chatwindow->local_user = account;
	
	/*also specify that if possible, try to use the same account they used
	  to last talk to us with */
	
	remote_contact->chatwindow->perfered = remote;
	
	g_snprintf(buff, BUF_SIZE, "%s (%s <=> %s via %s)",
			remote_contact->nick, account->alias,
			remote->handle, GET_SERVICE(account).name);

	gtk_window_set_title(GTK_WINDOW(remote_contact->chatwindow->window), buff);
	gtk_window_set_focus(GTK_WINDOW(remote_contact->chatwindow->window),
							remote_contact->chatwindow->entry);
	
	if(remote_contact->chatwindow->sound_enabled)
	{   
	    if (firstmsg)
	    {
		play_sound(FIRSTMSG);
		firstmsg = FALSE;
	    }
	    else
		play_sound(RECEIVE);
	}
	
	/*for grab the focus*/
	
	if(do_raise_window)
	{
		gdk_window_raise(remote_contact->chatwindow->window->window);
		gtk_widget_grab_focus(remote_contact->chatwindow->entry);
	}
	
    if (do_convo_timestamp) 
	{
       	time(&t);
       	cur_time = localtime(&t);
       	g_snprintf(buff2, BUF_SIZE, "%d:%.2d:%.2d %s", 
					cur_time->tm_hour, cur_time->tm_min, 
					cur_time->tm_sec, remote_contact->nick); 
    } 
	else 
	{ 
	   g_snprintf(buff2, BUF_SIZE, "%s", remote_contact->nick); 
	}

#ifdef HAVE_ICONV_H
    message = recode_if_needed(message, recode_buff, 0);
    /*	'message' is used below yet, so we have to assign
	and it's not freed, so should not be no harm
    */
#endif

	g_snprintf(buff, BUF_SIZE, "<FONT COLOR=\"#ff0000\"><B>%s: </B></FONT>",buff2); 

	gtk_eb_html_add(GTK_TEXT(remote_contact->chatwindow->chat), buff);
	gtk_eb_html_add(GTK_TEXT(remote_contact->chatwindow->chat), "</FONT>");
	gtk_eb_html_add(GTK_TEXT(remote_contact->chatwindow->chat), message);
	gtk_eb_html_add(GTK_TEXT(remote_contact->chatwindow->chat), "<BR>");
	
	/* Log the message */

	if(do_logging) eb_log_message(remote_contact->chatwindow->fp, buff, message); 

	/* If user's away and hasn't yet sent the away message in the last 5 minutes,
	   send, display, & log his away message.
	   We might want to give the option of whether or not to always send the message.*/

	if(is_away && (time(NULL) - remote_contact->chatwindow->away_msg_sent) > 300)
	{
		send_message(NULL, remote_contact->chatwindow);
	    RUN_SERVICE(account)->send_im(
                                account,
                                remote,
                                gtk_entry_get_text(GTK_ENTRY(away_message)));
		time(&t);
		cur_time = localtime(&t);
		g_snprintf(buff, BUF_SIZE, "<FONT COLOR=\"#0000ff\"><B>%d:%.2d:%.2d %s: </B></FONT>",
						cur_time->tm_hour, cur_time->tm_min, cur_time->tm_sec,
					    account->alias); 
		gtk_eb_html_add(GTK_TEXT(remote_contact->chatwindow->chat), buff);
		gtk_eb_html_add(GTK_TEXT(remote_contact->chatwindow->chat), 
								gtk_entry_get_text(GTK_ENTRY(away_message)));
		gtk_eb_html_add(GTK_TEXT(remote_contact->chatwindow->chat), "<br>");
		
		/* Note that the time the last away message has been sent */

		remote_contact->chatwindow->away_msg_sent = time(NULL);
		
		/* Log it */

		if(do_logging) eb_log_message(remote_contact->chatwindow->fp, buff, 
					      gtk_entry_get_text(GTK_ENTRY(away_message))); 
	}
}

void eb_chat_window_display_contact(struct contact * remote_contact) 
{
	eb_account * remote_account = find_suitable_remote_account(NULL, remote_contact);
    eb_local_account *account = NULL;

   	if(remote_account)
		account=find_suitable_local_account(NULL, remote_account->service_id); 

	if(!remote_contact->chatwindow || !remote_contact->chatwindow->window)
	{
		if(remote_contact->chatwindow)
			g_free(remote_contact->chatwindow);

		remote_contact->chatwindow = eb_chat_window_new(account, remote_contact);

		if(remote_contact->chatwindow)
		{
			gtk_widget_show(remote_contact->chatwindow->window);		
    	if (do_restore_last_conv) {
         gchar buff[1024];
  	     make_safe_filename(buff, remote_contact->nick);
         eb_restore_last_conv(buff,remote_contact->chatwindow);
      }
			gtk_window_set_focus(GTK_WINDOW(remote_contact->chatwindow->window),
									remote_contact->chatwindow->entry);
		}
      
	}
}
	
void eb_chat_window_display_account(eb_account * remote_account) 
{
	struct contact * remote_contact  = remote_account->account_contact;
	eb_local_account * account =find_suitable_local_account(NULL, remote_account->service_id); 
	gchar buff[BUF_SIZE];

	if(!remote_contact->chatwindow || !remote_contact->chatwindow->window)
	{
		if(remote_contact->chatwindow)
			g_free(remote_contact->chatwindow);

		remote_contact->chatwindow = eb_chat_window_new(account, remote_contact);

		if(remote_contact->chatwindow) {
			gtk_widget_show(remote_contact->chatwindow->window);
    	if (do_restore_last_conv) {
    	 gchar buff[1024];
  	   make_safe_filename(buff, remote_contact->nick);
       eb_restore_last_conv(buff,remote_contact->chatwindow);	
      }
		}
	}

	g_snprintf(buff, BUF_SIZE, "%s (%s <=> %s via %s)",
				remote_contact->nick, account->alias,
				remote_account->handle, GET_SERVICE(account).name);

	gtk_window_set_title(GTK_WINDOW(remote_contact->chatwindow->window), buff);
	gtk_window_set_focus(GTK_WINDOW(remote_contact->chatwindow->window),
   							remote_contact->chatwindow->entry);
	
	remote_contact->chatwindow->perfered = remote_account;
}
	
void eb_log_message(FILE *log_file, gchar buff[], gchar *message)
{
	gchar * my_name = malloc(strlen(buff)+1);
	gchar * my_message = malloc(strlen(message)+1);

	strcpy(my_name, buff);
	strcpy( my_message, message);

	/* Get rid of the HTML if the user doesn't want it */

	if(do_strip_html) 
	{
		strip_html(my_message);
		strip_html(my_name);
	}

	/* Log the message, using the appropriate formatting */

	fprintf(log_file, "%s %s %s %s\n", 
			(do_strip_html ? "" : "<P>"), my_name, my_message, (do_strip_html ? "" : "</P>"));
	fflush(log_file);

	free(my_message);
	free(my_name);
}

void eb_restore_last_conv(gchar *file_name, chat_window* cw){
  FILE * fp;
  gchar buff[1024];
  gchar buff2[1024];
  gchar *buff3;
  gchar color[8];
  gchar name[512];
  gchar *token;
  long location = -1;
  long lastlocation = -1;
  long beforeget;

  if ( (fp = fopen(file_name, "r")) == NULL) 
    {
      //there must not be a list logfile...
      return;
    }


  /*find last conversation */
  while(!feof(fp))
    {
      beforeget = ftell(fp);
      fgets(buff, 1024, fp);
      if(feof(fp)) break;
      g_strchomp(buff);
      if(!strncmp(buff,"Conversation started",strlen("Conversation started"))
       || !strncmp(buff,"<HR WIDTH=\"100%\"><P ALIGN=\"CENTER\"><B>Conversation started",strlen("<HR WIDTH=\"100%\"><P ALIGN=\"CENTER\"><B>Conversation started"))) {
        lastlocation = location;
      	location = beforeget;
      }
    }

  if(lastlocation == -1)
    {
     if(location == -1 || location == 0) {
       fclose(fp);
       return;
      }
      lastlocation = location;
    }
  fseek(fp,lastlocation, SEEK_SET);

  /* now we display the log */
  while(!feof(fp))
    {
      fgets(buff,1024,fp);
      if(feof(fp)) break;
      g_strchomp(buff);

      if(buff[0] == '<') /*this is html*/
	{
	
	  if(!strncmp(buff,"<HR WIDTH=\"100%\">",strlen("<HR WIDTH=\"100%\">")))
            gtk_eb_html_add(GTK_TEXT(cw->chat), buff+strlen("<HR WIDTH=\"100%\">"));
          else
            gtk_eb_html_add(GTK_TEXT(cw->chat), buff);
	gtk_eb_html_add(GTK_TEXT(cw->chat), "<br>");
	if(strlen(buff) > 34 && !strncmp(buff+34,"ended on",8)) break;
	}
      else if(!strncmp(buff,"Conversation started",20))
	{
	  gtk_eb_html_add(GTK_TEXT(cw->chat), "<hr>");
	  gtk_eb_html_add(GTK_TEXT(cw->chat), buff);
	  gtk_eb_html_add(GTK_TEXT(cw->chat), "<br>");

        } else if(!strncmp(buff,"Conversation ended",18)) {

	  gtk_eb_html_add(GTK_TEXT(cw->chat), buff);
	  gtk_eb_html_add(GTK_TEXT(cw->chat), "<br>");
          gtk_eb_html_add(GTK_TEXT(cw->chat), "<hr>");
          break;
	} else {
          strip_html(buff); /*better safe than sorry */
          strcpy(buff2, buff);

          token = strtok(buff2,":");
       
          if(token && (strcmp(buff,token) != 0)) {
           /* not happy with this if statement at all! */
            if(((strlen(token)==3)&&isdigit((int)token[1])&&isdigit(token[2]))
		       || ((strlen(token)==2) && isdigit((int)token[1])))
	    {  /* we must have time stamps */
	      /* allready have hours */
              token = strtok(NULL,":"); /*minutes*/
              if(token == NULL) /* we were wrong, this isn't a time stamp */
	         break; /* need to test this */
              token = strtok(NULL,":"); /*seconds + name*/
              if(token == NULL) /* we were wrong, this isn't a time stamp */
	        break; /* need to test this */
              buff3 = token + strlen(token)+1; /* should be the end of the screen name */
              token+=3;
	    } else {
	      /* no time stamps */
   	      buff3 = buff2+strlen(token)+1;
              token++;
            }
	    if( !strncmp(token,cw->contact->nick,strlen(cw->contact->nick)))
 	      { /* this is the other person */
                strcpy(color,"#ff0000");
       	    } else {
	        /* must be me */
	        strcpy(color,"#0000ff");
            }
	    strncpy(name,buff,buff3-buff2);
           name[buff3-buff2] = '\0';
           g_snprintf(buff, BUF_SIZE, "<FONT COLOR=\"%s\"><B>%s </B></FONT>",color, name);
           gtk_eb_html_add(GTK_TEXT(cw->chat), buff);
           gtk_eb_html_add(GTK_TEXT(cw->chat), buff3);
           gtk_eb_html_add(GTK_TEXT(cw->chat), "<br>");
	  } else {
            /* hmm, no ':' must be a non start/blank line */
            gtk_eb_html_add(GTK_TEXT(cw->chat),buff2);
            gtk_eb_html_add(GTK_TEXT(cw->chat), "<br>");
	  }
    }
  }
  fclose(fp);

}

