changeset 1525:ba8e6e211af5

[gaim-migrate @ 1535] icqlib updates. beginnings of system logging. committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Sat, 03 Mar 2001 00:26:04 +0000
parents a5c87ada5143
children 190cef255530
files plugins/icq/ChangeLog plugins/icq/icqlib.c plugins/icq/timeout.c plugins/icq/udp.c src/conversation.c src/gaim.h src/gaimrc.c src/prefs.c src/server.c src/util.c
diffstat 10 files changed, 343 insertions(+), 197 deletions(-) [+]
line wrap: on
line diff
--- a/plugins/icq/ChangeLog	Fri Mar 02 23:59:49 2001 +0000
+++ b/plugins/icq/ChangeLog	Sat Mar 03 00:26:04 2001 +0000
@@ -1,3 +1,19 @@
+2001-03-01  Bill Soudan  <soudan@kde.org>
+
+	This should fix all problems introduced by my 02-22 commit.
+
+	* icqlib/icqlib.c: only initialize TCP subsystem when use_tcp is 
+	enabled
+
+	* icqlib/timeout.c: don't crash when timeouts are deleted during 
+	icq_HandleTimeout, send a zero-length icq_SetTimeout when
+	appropriate to clear current timeout request
+
+	* icqlib/udp.c: rewrote icq_UDPEncode and icq_UDPCheckCode
+	functions to do their work in a seperate buffer so original
+	icq_Packet isn't corrupted, fixed bug where UDP_CMD_ACKs were
+	being queued on the UDP packet queue
+
 2001-02-22  Bill Soudan  <soudan@kde.org>
 
 	Note the icq_SetTimeout callback has been moved outside of
--- a/plugins/icq/icqlib.c	Fri Mar 02 23:59:49 2001 +0000
+++ b/plugins/icq/icqlib.c	Sat Mar 03 00:26:04 2001 +0000
@@ -1,9 +1,12 @@
 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /*
-$Id: icqlib.c 1508 2001-02-22 23:07:34Z warmenhoven $
+$Id: icqlib.c 1535 2001-03-03 00:26:04Z warmenhoven $
 $Log$
-Revision 1.5  2001/02/22 23:07:34  warmenhoven
-updating icqlib
+Revision 1.6  2001/03/03 00:26:04  warmenhoven
+icqlib updates. beginnings of system logging.
+
+Revision 1.52  2001/03/01 05:30:43  bills
+only initialize TCP subsystem when use_tcp is enabled
 
 Revision 1.51  2001/02/22 05:37:39  bills
 new timeout manager code, correct compilation warnings
@@ -188,8 +191,9 @@
   icq_UDPQueueNew(link);
 
   /* TCP stuff */
-  icq_TCPInit(link);
   link->icq_UseTCP = useTCP;
+  if (useTCP)
+    icq_TCPInit(link);
 
   /* Proxy stuff */
   link->icq_UseProxy = 0;
--- a/plugins/icq/timeout.c	Fri Mar 02 23:59:49 2001 +0000
+++ b/plugins/icq/timeout.c	Sat Mar 03 00:26:04 2001 +0000
@@ -2,6 +2,7 @@
 
 #include "timeout.h"
 
+icq_Timeout *icq_CurrentTimeout = NULL;
 list *icq_TimeoutList = NULL;
 
 void (*icq_SetTimeout)(long length);
@@ -38,25 +39,60 @@
 void icq_TimeoutDelete(icq_Timeout *timeout)
 {
   list_remove(icq_TimeoutList, timeout);
+
+  /* if this was the timeout we were currently waiting on, move on
+   * to the next */
+  if (icq_CurrentTimeout = timeout)
+  {
+    icq_CurrentTimeout = NULL;
+    icq_TimeoutDoNotify();
+  }
+
   free(timeout);
 }
 
-int _icq_HandleTimeout(void *p, va_list data)
+int _icq_HandleTimeout1(void *p, va_list data)
 {
   icq_Timeout *t = p;
+  int complete = 0;
   time_t current_time = va_arg(data, time_t);
-  int complete = 0;
+  list *expired_timeouts = va_arg(data, list *);
 
   if (t->expire_time <= current_time)
-    (*t->handler)(t->data);
+    list_enqueue(expired_timeouts, t);
   else
     /* traversal is complete when we reach an expire time in the future */
     complete = 1;
 
-  if (t->single_shot)
-    icq_TimeoutDelete(t);
+  return complete;
+}
+
+int _icq_HandleTimeout2(void *p, va_list data)
+{
+  icq_Timeout *t = p;
+
+  /* maybe a previously executed timeout caused us to be deleted, so
+   * make sure we're still around */
+  if (list_find(icq_TimeoutList, t))
+    (t->handler)(t->data);
+}
+
+int _icq_HandleTimeout3(void *p, va_list data)
+{
+  icq_Timeout *t = p;
+  int complete = 0;
+  time_t current_time = va_arg(data, time_t);
+
+  if (t->expire_time <= current_time)
+  {
+    if (t->single_shot)
+      icq_TimeoutDelete(t);
+    else
+      t->expire_time = current_time + t->length;
+  }
   else
-    t->expire_time = current_time + t->length;
+    /* traversal is complete when we reach an expire time in the future */
+    complete = 1;
 
   return complete;
 }
@@ -64,9 +100,24 @@
 void icq_HandleTimeout()
 {
   time_t current_time = time(NULL);
+  list *expired_timeouts = list_new();
 
-  /* call handler functions for all timeouts that have expired */
-  list_traverse(icq_TimeoutList, _icq_HandleTimeout, current_time);
+  icq_CurrentTimeout = NULL;
+
+  /* these three operations must be split up, in the case where a
+   * timeout function causes timers to be deleted - this ensures
+   * we don't try to free any timers that have already been removed
+   * or corrupt the list traversal process */
+
+  /* determine which timeouts that have expired */
+  list_traverse(icq_TimeoutList, _icq_HandleTimeout1, current_time,
+    expired_timeouts);
+
+  /* call handler function for expired timeouts */
+  list_traverse(expired_timeouts, _icq_HandleTimeout2);
+
+  /* delete any expired timeouts */
+  list_traverse(icq_TimeoutList, _icq_HandleTimeout3, current_time);
 
   if (icq_TimeoutList->count)
     icq_TimeoutDoNotify();
@@ -74,10 +125,18 @@
 
 void icq_TimeoutDoNotify()
 {
-  time_t current_time = time(NULL);
+  time_t length, current_time = time(NULL);
 
-  icq_Timeout *t = (icq_Timeout *)list_first(icq_TimeoutList);
-  long length = t->expire_time - current_time;
+  if (!icq_TimeoutList->count)
+  {
+    if (icq_SetTimeout)
+      (*icq_SetTimeout)(0);
+    return;
+  }
+
+  icq_CurrentTimeout = (icq_Timeout *)list_first(icq_TimeoutList);
+  length = icq_CurrentTimeout->expire_time - current_time;
+
   if (icq_SetTimeout)
     (*icq_SetTimeout)(length);
 }
--- a/plugins/icq/udp.c	Fri Mar 02 23:59:49 2001 +0000
+++ b/plugins/icq/udp.c	Sat Mar 03 00:26:04 2001 +0000
@@ -1,9 +1,14 @@
 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2  -*- */
 /*
-$Id: udp.c 1508 2001-02-22 23:07:34Z warmenhoven $
+$Id: udp.c 1535 2001-03-03 00:26:04Z warmenhoven $
 $Log$
-Revision 1.4  2001/02/22 23:07:34  warmenhoven
-updating icqlib
+Revision 1.5  2001/03/03 00:26:04  warmenhoven
+icqlib updates. beginnings of system logging.
+
+Revision 1.29  2001/03/01 05:37:15  bills
+rewrote icq_UDPEncode and icq_UDPCheckCode functions to do their work in
+a seperate buffer so original icq_Packet isn't corrupted, fixed bug where
+UDP_CMD_ACKs were being queued on the UDP packet queue
 
 Revision 1.28  2001/02/22 05:40:04  bills
 port tcp connect timeout code and UDP queue to new timeout manager
@@ -147,7 +152,7 @@
   0x47, 0x43, 0x69, 0x48, 0x33, 0x51, 0x54, 0x5D, 0x6E, 0x3C, 0x31, 0x64, 0x35, 0x5A, 0x00, 0x00,
 };
 
-void icq_UDPCheckCode(icq_Packet *p)
+DWORD icq_UDPCalculateCheckCode(icq_Packet *p)
 {
   DWORD num1, num2;
   DWORD r1,r2;
@@ -172,8 +177,7 @@
   num2 += icq_UDPTable[r2];
   num2 ^= 0xFF00FF;
 
-  icq_PacketGoto(p, 0x14);
-  icq_PacketAppend32(p, num1 ^ num2);
+  return num1 ^ num2;
 }
 
 DWORD icq_UDPScramble(DWORD cc)
@@ -195,29 +199,28 @@
   return a[0] + a[1] + a[2] + a[3] + a[4];
 }
 
-void icq_UDPEncode(icq_Packet *p)
+void icq_UDPEncode(icq_Packet *p, void *buffer)
 {
-  DWORD checkcode;
+  DWORD checkcode = icq_UDPCalculateCheckCode(p);
   DWORD code1, code2, code3;
   DWORD pos;
-  DWORD data;
 
-  icq_UDPCheckCode(p);
-  icq_PacketGoto(p, 20);
-  checkcode = icq_PacketRead32(p);
+  memcpy(buffer, p->data, p->length);
+
+  *(DWORD *)(buffer+0x14)=htoicql(checkcode);
   code1 = p->length * 0x68656c6cL;
   code2 = code1 + checkcode;
   pos = 0x0A;
 
   for(; pos < p->length; pos+=4)
   {
+    DWORD data = icqtohl(*(DWORD *)((p->data)+pos));
     code3 = code2 + icq_UDPTable[pos & 0xFF];
-    data = icqtohl(*(DWORD *)((p->data)+pos));
     data ^= code3;
-    *(DWORD*)((p->data)+pos)=htoicql(data);
+    *(DWORD*)(buffer+pos)=htoicql(data);
   }
   checkcode = icq_UDPScramble(checkcode);
-  *(DWORD *)((p->data)+0x14)=htoicql(checkcode);
+  *(DWORD *)(buffer+0x14)=htoicql(checkcode);
 }
 
 /*********************************************************
@@ -226,7 +229,7 @@
 *********************************************************/
 int icq_UDPSockWriteDirect(ICQLINK *link, icq_Packet *p)
 {
-  char tmpbuf[ICQ_PACKET_DATA_SIZE];
+  char tmpbuf[ICQ_PACKET_DATA_SIZE+10];
 
   if(link->icq_UDPSok <= 3)
   {
@@ -234,13 +237,14 @@
     return -1;
   }
 
-  icq_UDPEncode(p);
+  icq_UDPEncode(p, tmpbuf+10);
+
   if(!link->icq_UseProxy)
   {
 #ifdef _WIN32
-    return send(link->icq_UDPSok, p->data, p->length, 0);
+    return send(link->icq_UDPSok, tmpbuf+10, p->length, 0);
 #else
-    return write(link->icq_UDPSok, p->data, p->length);
+    return write(link->icq_UDPSok, tmpbuf+10, p->length);
 #endif
   }
   else
@@ -251,7 +255,6 @@
     tmpbuf[3] = 1; /* address type IP v4 */
     *(unsigned long*)&tmpbuf[4] = htonl(link->icq_ProxyDestIP);
     *(unsigned short*)&tmpbuf[8] = htons(link->icq_ProxyDestPort);
-    memcpy(&tmpbuf[10], p->data, p->length);
 #ifdef _WIN32
     return send(link->icq_UDPSok, tmpbuf, p->length+10, 0)-10;
 #else
@@ -498,7 +501,7 @@
   icq_PacketAppend32(p, rand());
 
   icq_FmtLog(link, ICQ_LOG_MESSAGE, "Acking\n");
-  icq_UDPSockWrite(link, p);
+  icq_UDPSockWriteDirect(link, p);
 }
 
 /***************************************************
--- a/src/conversation.c	Fri Mar 02 23:59:49 2001 +0000
+++ b/src/conversation.c	Sat Mar 03 00:26:04 2001 +0000
@@ -111,12 +111,12 @@
 	c = (struct conversation *)g_new0(struct conversation, 1);
 	g_snprintf(c->name, sizeof(c->name), "%s", name);
 
-	if ((general_options & OPT_GEN_LOG_ALL) || find_log_info(c->name)) {
+	if ((logging_options & OPT_LOG_ALL) || find_log_info(c->name)) {
 		FILE *fd;
 
 		fd = open_log_file(c->name);
 		if (fd > 0) {
-			if (!(general_options & OPT_GEN_STRIP_HTML))
+			if (!(logging_options & OPT_LOG_STRIP_HTML))
 				fprintf(fd,
 					"<HR><BR><H3 Align=Center> ---- New Conversation @ %s ----</H3><BR>\n",
 					full_date());
@@ -172,7 +172,7 @@
 	save_prefs();
 
 	if (cnv) {
-		if (!(general_options & OPT_GEN_LOG_ALL))
+		if (!(logging_options & OPT_LOG_ALL))
 			g_snprintf(buf, sizeof(buf), CONVERSATION_TITLE, cnv->name);
 		else
 			g_snprintf(buf, sizeof(buf), LOG_CONVERSATION_TITLE, cnv->name);
@@ -233,7 +233,7 @@
 
 		if (c->log_button)
 			gtk_widget_set_sensitive(c->log_button,
-						 ((general_options & OPT_GEN_LOG_ALL)) ? FALSE : TRUE);
+						 ((logging_options & OPT_LOG_ALL)) ? FALSE : TRUE);
 
 		cnv = cnv->next;
 	}
@@ -246,7 +246,7 @@
 
 			if (c->log_button)
 				gtk_widget_set_sensitive(c->log_button,
-							 ((general_options & OPT_GEN_LOG_ALL)) ? FALSE :
+							 ((logging_options & OPT_LOG_ALL)) ? FALSE :
 							 TRUE);
 
 			bcs = bcs->next;
@@ -1182,7 +1182,7 @@
 	if (display_options & OPT_DISP_IGNORE_SIZES)
 		gtk_font_options = gtk_font_options ^ GTK_IMHTML_NO_SIZES;
 
-	if (!(general_options & OPT_GEN_STRIP_HTML))
+	if (!(logging_options & OPT_LOG_STRIP_HTML))
 		gtk_font_options = gtk_font_options ^ GTK_IMHTML_RETURN_LOG;
 
 	if (!who) {
@@ -1211,7 +1211,7 @@
 
 		gtk_imhtml_append_text(GTK_IMHTML(c->text), "<BR>", 0);
 
-		if (general_options & OPT_GEN_STRIP_HTML) {
+		if (logging_options & OPT_LOG_STRIP_HTML) {
 			char *t1 = strip_html(what);
 			c->history = g_string_append(c->history, t1);
 			c->history = g_string_append(c->history, "\n");
@@ -1221,11 +1221,11 @@
 			c->history = g_string_append(c->history, "<BR>\n");
 		}
 
-		if ((general_options & OPT_GEN_LOG_ALL) || find_log_info(c->name)) {
+		if ((logging_options & OPT_LOG_ALL) || find_log_info(c->name)) {
 			char *t1;
 			char nm[256];
 
-			if (general_options & OPT_GEN_STRIP_HTML) {
+			if (logging_options & OPT_LOG_STRIP_HTML) {
 				t1 = strip_html(what);
 			} else {
 				t1 = what;
@@ -1236,14 +1236,14 @@
 				g_snprintf(nm, 256, "%s", c->name);
 			fd = open_log_file(nm);
 			if (fd > 0) {
-				if (general_options & OPT_GEN_STRIP_HTML) {
+				if (logging_options & OPT_LOG_STRIP_HTML) {
 					fprintf(fd, "%s\n", t1);
 				} else {
 					fprintf(fd, "%s<BR>\n", t1);
 				}
 				fclose(fd);
 			}
-			if (general_options & OPT_GEN_STRIP_HTML) {
+			if (logging_options & OPT_LOG_STRIP_HTML) {
 				g_free(t1);
 			}
 		}
@@ -1302,7 +1302,7 @@
 
 		gtk_imhtml_append_text(GTK_IMHTML(c->text), "<BR>", 0);
 
-		if (general_options & OPT_GEN_STRIP_HTML) {
+		if (logging_options & OPT_LOG_STRIP_HTML) {
 			char *t1, *t2;
 			t1 = strip_html(buf);
 			t2 = strip_html(what);
@@ -1324,7 +1324,7 @@
 			g_free(t2);
 		}
 
-		if ((general_options & OPT_GEN_LOG_ALL) || find_log_info(c->name)) {
+		if ((logging_options & OPT_LOG_ALL) || find_log_info(c->name)) {
 			char *t1, *t2;
 			char *nm = g_malloc(256);
 			if (c->is_chat)
@@ -1332,7 +1332,7 @@
 			else
 				g_snprintf(nm, 256, "%s", c->name);
 
-			if (general_options & OPT_GEN_STRIP_HTML) {
+			if (logging_options & OPT_LOG_STRIP_HTML) {
 				t1 = strip_html(buf);
 				t2 = strip_html(what);
 			} else {
@@ -1341,7 +1341,7 @@
 			}
 			fd = open_log_file(nm);
 			if (fd > 0) {
-				if (general_options & OPT_GEN_STRIP_HTML) {
+				if (logging_options & OPT_LOG_STRIP_HTML) {
 					fprintf(fd, "%s%s\n", t1, t2);
 				} else {
 					fprintf(fd, "%s%s%s<BR>\n", t1, t2, logstr->str);
@@ -1599,7 +1599,7 @@
 	c->font = font;
 	c->smiley = smiley;
 
-	gtk_widget_set_sensitive(c->log_button, ((general_options & OPT_GEN_LOG_ALL)) ? FALSE : TRUE);
+	gtk_widget_set_sensitive(c->log_button, ((logging_options & OPT_LOG_ALL)) ? FALSE : TRUE);
 
 	gtk_widget_set_sensitive(c->bold, ((font_options & OPT_FONT_BOLD)) ? FALSE : TRUE);
 	gtk_widget_set_sensitive(c->italic, ((font_options & OPT_FONT_ITALIC)) ? FALSE : TRUE);
@@ -1805,7 +1805,7 @@
 	gtk_container_border_width(GTK_CONTAINER(win), 10);
 	gtk_widget_realize(win);
 	aol_icon(win->window);
-	if ((find_log_info(c->name)) || ((general_options & OPT_GEN_LOG_ALL)))
+	if ((find_log_info(c->name)) || ((logging_options & OPT_LOG_ALL)))
 		 g_snprintf(buf, sizeof(buf), LOG_CONVERSATION_TITLE, c->name);
 	else
 		g_snprintf(buf, sizeof(buf), CONVERSATION_TITLE, c->name);
--- a/src/gaim.h	Fri Mar 02 23:59:49 2001 +0000
+++ b/src/gaim.h	Sat Mar 03 00:26:04 2001 +0000
@@ -422,8 +422,8 @@
 extern int general_options;
 #define OPT_GEN_ENTER_SENDS       0x00000001
 /* #define OPT_GEN_AUTO_LOGIN        0x00000002 now OPT_USR_AUTO */
-#define OPT_GEN_LOG_ALL           0x00000004
-#define OPT_GEN_STRIP_HTML        0x00000008
+#define OPT_GEN_LOG_ALL           0x00000004 /* now OPT_LOG_ALL */
+#define OPT_GEN_STRIP_HTML        0x00000008 /* now OPT_LOG_STRIP_HTML */
 #define OPT_GEN_APP_BUDDY_SHOW    0x00000010
 #define OPT_GEN_POPUP_WINDOWS     0x00000020
 #define OPT_GEN_SEND_LINKS        0x00000040
@@ -499,6 +499,15 @@
 #define OPT_FONT_BGCOL           0x00000080
 #define OPT_FONT_SIZE            0x00000100
 
+extern int logging_options;
+#define OPT_LOG_ALL              0x00000001
+#define OPT_LOG_STRIP_HTML       0x00000002
+#define OPT_LOG_BUDDY_SIGNON     0x00000004
+#define OPT_LOG_BUDDY_IDLE       0x00000008
+#define OPT_LOG_BUDDY_AWAY       0x00000010
+#define OPT_LOG_MY_SIGNON        0x00000020
+#define OPT_LOG_INDIVIDUAL       0x00000040
+
 #define OPT_USR_AUTO		0x00000001
 #define OPT_USR_KEEPALV		0x00000002
 #define OPT_USR_REM_PASS	0x00000004
--- a/src/gaimrc.c	Fri Mar 02 23:59:49 2001 +0000
+++ b/src/gaimrc.c	Sat Mar 03 00:26:04 2001 +0000
@@ -44,6 +44,7 @@
 int display_options;
 int sound_options;
 int font_options;
+int logging_options;
 
 int report_idle, web_browser;
 struct save_pos blist_pos;
@@ -610,6 +611,7 @@
 {
 	char buf[2048];
 	struct parse *p;
+	gboolean read_logging = FALSE;
 
 	buf[0] = 0;
 
@@ -630,6 +632,9 @@
 			sound_options = atoi(p->value[0]);
 		} else if (!strcmp(p->option, "font_options")) {
 			font_options = atoi(p->value[0]);
+		} else if (!strcmp(p->option, "logging_options")) {
+			logging_options = atoi(p->value[0]);
+			read_logging = TRUE;
 		} else if (!strcmp(p->option, "font_face")) {
 			if (p->value[0] != NULL)
 				g_snprintf(fontface, sizeof(fontface), "%s", p->value[0]);
@@ -660,6 +665,14 @@
 
 	}
 
+	if (!read_logging) {
+		logging_options = 0;
+		if (general_options & OPT_GEN_LOG_ALL)
+			logging_options |= OPT_LOG_ALL;
+		if (general_options & OPT_GEN_STRIP_HTML)
+			logging_options |= OPT_LOG_STRIP_HTML;
+	}
+
 }
 
 static void gaimrc_write_options(FILE *f)
@@ -670,6 +683,7 @@
 	fprintf(f, "\tdisplay_options { %d }\n", display_options);
 	fprintf(f, "\tsound_options { %d }\n", sound_options);
 	fprintf(f, "\tfont_options { %d }\n", font_options);
+	fprintf(f, "\tlogging_options { %d }\n", logging_options);
 	if (fontface)
 		fprintf(f, "\tfont_face { %s }\n", fontface);
 	fprintf(f, "\tfont_size { %d }\n", fontsize);
--- a/src/prefs.c	Fri Mar 02 23:59:49 2001 +0000
+++ b/src/prefs.c	Sat Mar 03 00:26:04 2001 +0000
@@ -54,7 +54,6 @@
 static void prefs_build_convo();
 static void prefs_build_sound();
 static void prefs_build_away();
-static void prefs_build_browser();
 static void prefs_build_deny();
 static gint handle_delete(GtkWidget *, GdkEvent *, void *);
 static void delete_prefs(GtkWidget *, void *);
@@ -164,6 +163,161 @@
 	gtk_widget_show(prefdialog);
 }
 
+static GtkWidget *browser_entry = NULL;
+static GtkWidget *new_window = NULL;
+
+static void set_browser(GtkWidget *w, int *data)
+{
+	web_browser = (int)data;
+	if (web_browser != BROWSER_MANUAL) {
+		if (browser_entry)
+			gtk_widget_set_sensitive(browser_entry, FALSE);
+	} else {
+		if (browser_entry)
+			gtk_widget_set_sensitive(browser_entry, TRUE);
+	}
+
+	if (web_browser != BROWSER_NETSCAPE) {
+		if (new_window)
+			gtk_widget_set_sensitive(new_window, FALSE);
+	} else {
+		if (new_window)
+			gtk_widget_set_sensitive(new_window, TRUE);
+	}
+
+
+	save_prefs();
+}
+
+static int manualentry_key_pressed(GtkWidget *w, GdkEvent *event, void *dummy)
+{
+	g_snprintf(web_command, sizeof(web_command), "%s", gtk_entry_get_text(GTK_ENTRY(browser_entry)));
+	save_prefs();
+	return TRUE;
+}
+
+static GtkWidget *browser_radio(char *label, int which, GtkWidget *box, GtkWidget *set)
+{
+	GtkWidget *opt;
+
+	if (!set)
+		opt = gtk_radio_button_new_with_label(NULL, label);
+	else
+		opt =
+		    gtk_radio_button_new_with_label(gtk_radio_button_group(GTK_RADIO_BUTTON(set)),
+						    label);
+	gtk_box_pack_start(GTK_BOX(box), opt, FALSE, FALSE, 0);
+	gtk_signal_connect(GTK_OBJECT(opt), "clicked", GTK_SIGNAL_FUNC(set_browser), (void *)which);
+	gtk_widget_show(opt);
+	if (web_browser == which)
+		gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(opt), TRUE);
+
+	return opt;
+}
+
+static void brentdes(GtkWidget *m, gpointer n)
+{
+	browser_entry = NULL;
+	new_window = NULL;
+}
+
+static void browser_page()
+{
+	GtkWidget *parent;
+	GtkWidget *box;
+	GtkWidget *label;
+	GtkWidget *opt;
+
+	parent = prefdialog->parent;
+	gtk_widget_destroy(prefdialog);
+
+	prefdialog = gtk_frame_new(_("Browser Options"));
+	gtk_container_add(GTK_CONTAINER(parent), prefdialog);
+
+	box = gtk_vbox_new(FALSE, 5);
+	gtk_container_set_border_width(GTK_CONTAINER(box), 5);
+	gtk_container_add(GTK_CONTAINER(prefdialog), box);
+	gtk_widget_show(box);
+
+	label = gtk_label_new(_("All options take effect immediately unless otherwise noted."));
+	gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 5);
+	gtk_widget_show(label);
+
+	opt = browser_radio(_("Netscape"), BROWSER_NETSCAPE, box, NULL);
+	opt = browser_radio(_("KFM"), BROWSER_KFM, box, opt);
+#ifdef USE_GNOME
+	opt = browser_radio(_("GNOME URL Handler"), BROWSER_GNOME, box, opt);
+#endif /* USE_GNOME */
+	opt = browser_radio(_("Manual"), BROWSER_MANUAL, box, opt);
+
+	browser_entry = gtk_entry_new();
+	gtk_box_pack_start(GTK_BOX(box), browser_entry, FALSE, FALSE, 0);
+	gtk_entry_set_text(GTK_ENTRY(browser_entry), web_command);
+	gtk_signal_connect(GTK_OBJECT(browser_entry), "focus_out_event",
+			   GTK_SIGNAL_FUNC(manualentry_key_pressed), NULL);
+	gtk_signal_connect(GTK_OBJECT(browser_entry), "destroy", GTK_SIGNAL_FUNC(brentdes), NULL);
+	gtk_widget_show(browser_entry);
+
+	new_window =
+	    gaim_button(_("Pop up new window by default"), &general_options, OPT_GEN_BROWSER_POPUP, box);
+
+	if (web_browser != BROWSER_MANUAL) {
+		gtk_widget_set_sensitive(browser_entry, FALSE);
+	} else {
+		gtk_widget_set_sensitive(browser_entry, TRUE);
+	}
+
+	if (web_browser != BROWSER_NETSCAPE) {
+		gtk_widget_set_sensitive(new_window, FALSE);
+	} else {
+		gtk_widget_set_sensitive(new_window, TRUE);
+	}
+
+	gtk_widget_show(prefdialog);
+}
+
+static void logging_page()
+{
+	GtkWidget *parent;
+	GtkWidget *box;
+	GtkWidget *label;
+	GtkWidget *sep;
+
+	parent = prefdialog->parent;
+	gtk_widget_destroy(prefdialog);
+
+	prefdialog = gtk_frame_new(_("Logging Options"));
+	gtk_container_add(GTK_CONTAINER(parent), prefdialog);
+
+	box = gtk_vbox_new(FALSE, 5);
+	gtk_container_set_border_width(GTK_CONTAINER(box), 5);
+	gtk_container_add(GTK_CONTAINER(prefdialog), box);
+	gtk_widget_show(box);
+
+	label = gtk_label_new(_("All options take effect immediately unless otherwise noted."));
+	gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 5);
+	gtk_widget_show(label);
+
+	gaim_button(_("Log all conversations"), &logging_options, OPT_LOG_ALL, box);
+	gaim_button(_("Strip HTML from conversationlogs"), &logging_options, OPT_LOG_STRIP_HTML, box);
+
+	sep = gtk_hseparator_new();
+	gtk_box_pack_start(GTK_BOX(box), sep, FALSE, FALSE, 5);
+	gtk_widget_show(sep);
+
+	label = gtk_label_new(_("Nothing below is implemented yet"));
+	gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 5);
+	gtk_widget_show(label);
+
+	gaim_button(_("Log when buddies sign on/sign off"), &logging_options, OPT_LOG_BUDDY_SIGNON, box);
+	gaim_button(_("Log when buddies become idle/un-idle"), &logging_options, OPT_LOG_BUDDY_IDLE, box);
+	gaim_button(_("Log when buddies go away/come back"), &logging_options, OPT_LOG_BUDDY_AWAY, box);
+	gaim_button(_("Log your own signons/idleness/awayness (as set by options above)"), &logging_options, OPT_LOG_MY_SIGNON, box);
+	gaim_button(_("Individual log file for each buddy's signons"), &logging_options, OPT_LOG_INDIVIDUAL, box);
+
+	gtk_widget_show(prefdialog);
+}
+
 static void buddy_page()
 {
 	GtkWidget *parent;
@@ -261,13 +415,6 @@
 	gtk_box_pack_start(GTK_BOX(box), sep, FALSE, FALSE, 5);
 	gtk_widget_show(sep);
 
-	gaim_button(_("Log all conversations"), &general_options, OPT_GEN_LOG_ALL, box);
-	gaim_button(_("Strip HTML from logs"), &general_options, OPT_GEN_STRIP_HTML, box);
-
-	sep = gtk_hseparator_new();
-	gtk_box_pack_start(GTK_BOX(box), sep, FALSE, FALSE, 5);
-	gtk_widget_show(sep);
-
 	gaim_button(_("Highlight misspelled words"), &general_options, OPT_GEN_CHECK_SPELLING, box);
 	gaim_button(_("Show URLs as links"), &general_options, OPT_GEN_SEND_LINKS, box);
 	gaim_button(_("Sending messages removes away status"), &general_options, OPT_GEN_BACK_ON_IM,
@@ -1413,119 +1560,6 @@
 	gtk_widget_show(prefdialog);
 }
 
-static GtkWidget *browser_entry = NULL;
-static GtkWidget *new_window = NULL;
-
-static void set_browser(GtkWidget *w, int *data)
-{
-	web_browser = (int)data;
-	if (web_browser != BROWSER_MANUAL) {
-		if (browser_entry)
-			gtk_widget_set_sensitive(browser_entry, FALSE);
-	} else {
-		if (browser_entry)
-			gtk_widget_set_sensitive(browser_entry, TRUE);
-	}
-
-	if (web_browser != BROWSER_NETSCAPE) {
-		if (new_window)
-			gtk_widget_set_sensitive(new_window, FALSE);
-	} else {
-		if (new_window)
-			gtk_widget_set_sensitive(new_window, TRUE);
-	}
-
-
-	save_prefs();
-}
-
-static int manualentry_key_pressed(GtkWidget *w, GdkEvent *event, void *dummy)
-{
-	g_snprintf(web_command, sizeof(web_command), "%s", gtk_entry_get_text(GTK_ENTRY(browser_entry)));
-	save_prefs();
-	return TRUE;
-}
-
-static GtkWidget *browser_radio(char *label, int which, GtkWidget *box, GtkWidget *set)
-{
-	GtkWidget *opt;
-
-	if (!set)
-		opt = gtk_radio_button_new_with_label(NULL, label);
-	else
-		opt =
-		    gtk_radio_button_new_with_label(gtk_radio_button_group(GTK_RADIO_BUTTON(set)),
-						    label);
-	gtk_box_pack_start(GTK_BOX(box), opt, FALSE, FALSE, 0);
-	gtk_signal_connect(GTK_OBJECT(opt), "clicked", GTK_SIGNAL_FUNC(set_browser), (void *)which);
-	gtk_widget_show(opt);
-	if (web_browser == which)
-		gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(opt), TRUE);
-
-	return opt;
-}
-
-static void brentdes(GtkWidget *m, gpointer n)
-{
-	browser_entry = NULL;
-	new_window = NULL;
-}
-
-static void browser_page()
-{
-	GtkWidget *parent;
-	GtkWidget *box;
-	GtkWidget *label;
-	GtkWidget *opt;
-
-	parent = prefdialog->parent;
-	gtk_widget_destroy(prefdialog);
-
-	prefdialog = gtk_frame_new(_("Browser Options"));
-	gtk_container_add(GTK_CONTAINER(parent), prefdialog);
-
-	box = gtk_vbox_new(FALSE, 5);
-	gtk_container_set_border_width(GTK_CONTAINER(box), 5);
-	gtk_container_add(GTK_CONTAINER(prefdialog), box);
-	gtk_widget_show(box);
-
-	label = gtk_label_new(_("All options take effect immediately unless otherwise noted."));
-	gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 5);
-	gtk_widget_show(label);
-
-	opt = browser_radio(_("Netscape"), BROWSER_NETSCAPE, box, NULL);
-	opt = browser_radio(_("KFM"), BROWSER_KFM, box, opt);
-#ifdef USE_GNOME
-	opt = browser_radio(_("GNOME URL Handler"), BROWSER_GNOME, box, opt);
-#endif /* USE_GNOME */
-	opt = browser_radio(_("Manual"), BROWSER_MANUAL, box, opt);
-
-	browser_entry = gtk_entry_new();
-	gtk_box_pack_start(GTK_BOX(box), browser_entry, FALSE, FALSE, 0);
-	gtk_entry_set_text(GTK_ENTRY(browser_entry), web_command);
-	gtk_signal_connect(GTK_OBJECT(browser_entry), "focus_out_event",
-			   GTK_SIGNAL_FUNC(manualentry_key_pressed), NULL);
-	gtk_signal_connect(GTK_OBJECT(browser_entry), "destroy", GTK_SIGNAL_FUNC(brentdes), NULL);
-	gtk_widget_show(browser_entry);
-
-	new_window =
-	    gaim_button(_("Pop up new window by default"), &general_options, OPT_GEN_BROWSER_POPUP, box);
-
-	if (web_browser != BROWSER_MANUAL) {
-		gtk_widget_set_sensitive(browser_entry, FALSE);
-	} else {
-		gtk_widget_set_sensitive(browser_entry, TRUE);
-	}
-
-	if (web_browser != BROWSER_NETSCAPE) {
-		gtk_widget_set_sensitive(new_window, FALSE);
-	} else {
-		gtk_widget_set_sensitive(new_window, TRUE);
-	}
-
-	gtk_widget_show(prefdialog);
-}
-
 static GtkWidget *deny_conn_hbox = NULL;
 static GtkWidget *deny_opt_menu = NULL;
 static struct gaim_connection *current_deny_gc = NULL;
@@ -1938,7 +1972,6 @@
 	prefs_build_convo();
 	prefs_build_sound();
 	prefs_build_away();
-	prefs_build_browser();
 	prefs_build_deny();
 
 	//general_page();
@@ -2065,9 +2098,6 @@
 {
 	general_options = general_options ^ (int)option;
 
-	if ((int)option == OPT_GEN_LOG_ALL)
-		update_log_convs();
-
 	if ((int)option == OPT_GEN_CHECK_SPELLING)
 		toggle_spellchk();
 
@@ -2120,6 +2150,16 @@
 	save_prefs();
 }
 
+void set_logging_option(GtkWidget *w, int *option)
+{
+	logging_options = logging_options ^ (int)option;
+
+	if ((int)option == OPT_LOG_ALL)
+		update_log_convs();
+
+	save_prefs();
+}
+
 GtkWidget *gaim_button(const char *text, int *options, int option, GtkWidget *page)
 {
 	GtkWidget *button;
@@ -2130,17 +2170,18 @@
 	if (options == &font_options)
 		gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(set_font_option),
 				   (int *)option);
-
 	if (options == &sound_options)
 		gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(set_sound_option),
 				   (int *)option);
 	if (options == &display_options)
 		gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(set_display_option),
 				   (int *)option);
-
 	if (options == &general_options)
 		gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(set_general_option),
 				   (int *)option);
+	if (options == &logging_options)
+		gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(set_logging_option),
+				   (int *)option);
 	gtk_widget_show(button);
 
 	return button;
@@ -2148,6 +2189,7 @@
 
 void prefs_build_general()
 {
+	GtkCTreeNode *node;
 	char *text[1];
 
 	text[0] = _("General");
@@ -2155,6 +2197,16 @@
 					     text, 5, NULL, NULL, NULL, NULL, 0, 1);
 	gtk_ctree_node_set_row_data(GTK_CTREE(preftree), general_node, general_page);
 
+	text[0] = _("Browser");
+	node = gtk_ctree_insert_node(GTK_CTREE(preftree), general_node, NULL,
+				     text, 5, NULL, NULL, NULL, NULL, 0, 1);
+	gtk_ctree_node_set_row_data(GTK_CTREE(preftree), node, browser_page);
+
+	text[0] = _("Logging");
+	node = gtk_ctree_insert_node(GTK_CTREE(preftree), general_node, NULL,
+				     text, 5, NULL, NULL, NULL, NULL, 0, 1);
+	gtk_ctree_node_set_row_data(GTK_CTREE(preftree), node, logging_page);
+
 	gtk_ctree_select(GTK_CTREE(preftree), general_node);
 }
 
@@ -2227,17 +2279,6 @@
 	gtk_ctree_node_set_row_data(GTK_CTREE(preftree), parent, away_page);
 }
 
-void prefs_build_browser()
-{
-	GtkCTreeNode *parent;
-	char *text[1];
-
-	text[0] = _("Browser");
-	parent = gtk_ctree_insert_node(GTK_CTREE(preftree), NULL, NULL,
-				       text, 5, NULL, NULL, NULL, NULL, 0, 1);
-	gtk_ctree_node_set_row_data(GTK_CTREE(preftree), parent, browser_page);
-}
-
 void prefs_build_deny()
 {
 	char *text[1];
--- a/src/server.c	Fri Mar 02 23:59:49 2001 +0000
+++ b/src/server.c	Sat Mar 03 00:26:04 2001 +0000
@@ -448,7 +448,7 @@
 			cv = (struct conversation *)cnv->data;
 			if (!strcasecmp(who, normalize(cv->name))) {
 				g_snprintf(cv->name, sizeof(cv->name), "%s", name);
-				if (find_log_info(name) || (general_options & OPT_GEN_LOG_ALL))
+				if (find_log_info(name) || (logging_options & OPT_LOG_ALL))
 					 g_snprintf(who, 63, LOG_CONVERSATION_TITLE, name);
 				else
 					g_snprintf(who, 63, CONVERSATION_TITLE, name);
@@ -637,7 +637,7 @@
 	b->history = g_string_new("");
 	g_snprintf(b->name, 80, "%s", name);
 
-	if ((general_options & OPT_GEN_LOG_ALL) || find_log_info(b->name)) {
+	if ((logging_options & OPT_LOG_ALL) || find_log_info(b->name)) {
 		FILE *fd;
 		char *filename;
 
@@ -645,7 +645,7 @@
 		g_snprintf(filename, 100, "%s.chat", b->name);
 
 		fd = open_log_file(filename);
-		if (!(general_options & OPT_GEN_STRIP_HTML))
+		if (!(logging_options & OPT_LOG_STRIP_HTML))
 			fprintf(fd,
 				"<HR><BR><H3 Align=Center> ---- New Conversation @ %s ----</H3><BR>\n",
 				full_date());
--- a/src/util.c	Fri Mar 02 23:59:49 2001 +0000
+++ b/src/util.c	Sat Mar 03 00:26:04 2001 +0000
@@ -347,7 +347,7 @@
 	int res;
 	gchar *gaim_dir;
 
-	if (!(general_options & OPT_GEN_LOG_ALL)) {
+	if (!(logging_options & OPT_LOG_ALL)) {
 
 		l = find_log_info(name);
 		if (!l)