diff -urP irssi-0.8.10-rc5/src/fe-text/gui-readline.c irssi-0.8.10-rc5-mouse_xterm/src/fe-text/gui-readline.c
--- irssi-0.8.10-rc5/src/fe-text/gui-readline.c	2004-03-24 17:24:57.000000000 +0000
+++ irssi-0.8.10-rc5-mouse_xterm/src/fe-text/gui-readline.c	2005-04-10 02:11:53.000000000 +0100
@@ -38,6 +38,10 @@
 #include "gui-windows.h"
 #include "utf8.h"
 
+#include "statusbar.h"
+char *get_activity_list(MAIN_WINDOW_REC *window, int normal, int hilight);
+static void key_change_window(const char *data);
+
 #include <signal.h>
 
 typedef void (*ENTRY_REDIRECT_KEY_FUNC) (int key, void *data, SERVER_REC *server, WI_ITEM_REC *item);
@@ -69,6 +73,12 @@
 
 static void sig_input(void);
 
+#include <math.h>
+static int mouse_xterm_status = -1; /* -1:off 0,1,2:filling mouse_xterm_combo */
+static unichar mouse_xterm_combo[3]; /* 0:button 1:x 2:y */
+static unichar mouse_xterm_previous[3]; /* previous contents of mouse_xterm_combo */
+static int old_window_refnum = -1;
+
 void input_listen_init(int handle)
 {
         GIOChannel *stdin_channel;
@@ -442,6 +452,176 @@
 	return paste_state == 2;
 }
 
+/* Check if the "act" item exists in the statusbar and if the mouse is over
+   it. If it is, then set the current window to the window with the number
+   which has been clicked, if any. */
+static void mouse_check_act(STATUSBAR_REC *bar, int mouse_xpos)
+{
+	GSList *l_item;
+	char *actlist;
+	SBAR_ITEM_REC *item;
+	int i, status, pos;
+
+	for (l_item = bar->items; l_item != NULL; l_item = l_item->next) {
+		item = l_item->data;
+		if (strcmp (item->config->name, "act") != 0 || item->size == 0 || mouse_xpos <= item->xpos || mouse_xpos >= item->xpos+item->size)
+			continue;
+		actlist = get_activity_list(item->bar->parent_window, TRUE, TRUE);
+		if (actlist == NULL)
+			continue;
+		/* Match mouse coordinates with window numbers in actlist.
+		   FIXME: it assumes the default act template "{sb Act: $0-}"
+		   is used. To minimize things, I assume $0- is at the end
+		   anyway, and parse actlist in reverse order. */
+		status = -1;
+		pos = 0;
+		/* Parse from the end to the beginning */
+		for (i = strlen(actlist)-1; i >= 0; i--) {
+			/* Tricky because it may be part of a window number >10 */
+			if (isdigit(actlist[i])) {
+				if (status == -1) {
+					status = actlist[i]-'0';
+				} else
+					status = status + (actlist[i]-'0')*10;
+				if (item->xpos+item->size-2-pos == mouse_xpos) {
+					/* look-ahead */
+					while (i > 0 && isdigit(actlist[i-1])) {
+						status = status + (actlist[i-1]-'0')*10;
+						i--;
+					}
+					ltoa(actlist, status);
+					key_change_window(actlist);
+					i = -1;
+					break;
+				}
+				pos++;
+			} else if (actlist[i] == ',') {
+				if (item->xpos-2-pos == mouse_xpos)
+					break;
+				status = -1;
+				pos++;
+			}
+		}
+		g_free_not_null(actlist);
+		break;
+	}
+}
+
+/* Handle mouse event (button press or release) */
+static void sig_mouse_event(int b, int x, int y, int oldb, int oldx, int oldy)
+{
+	int xd, yd;
+	double distance, angle;
+
+	/* proceed only if a button is being released */
+	if (b != 3)
+		return;
+
+	/* if it was a mouse click (press and release in the same position) */
+	if (x == oldx && y == oldy) {
+		signal_emit("mouse click", 3, oldb, x, y);
+		return;
+	}
+
+	/* otherwise, find mouse gestures on left button*/
+	if (oldb != 0)
+		return;
+	xd = x - oldx;
+	yd = -1 * (y - oldy);
+	distance = sqrt(xd*xd + yd*yd);
+	/* ignore small gestures */
+	if (distance < 3)
+		return;
+	angle = asin(yd/distance) * 180 / 3.14159265358979;
+	if (angle < 20 && angle > -20 && xd > 0) {
+		if (distance <= 40)
+			signal_emit("mouse gesture right", 0);
+		else
+			signal_emit("mouse gesture bigright", 0);
+	} else if (angle < 20 && angle > -20 && xd < 0) {
+		if (distance <= 40)
+			signal_emit("mouse gesture left", 0);
+		else
+			signal_emit("mouse gesture bigleft", 0);
+	} else if (angle > 40) {
+		signal_emit("mouse gesture up", 0);
+	} else if (angle < -40) {
+		signal_emit("mouse gesture down", 0);
+	}
+}
+
+/* Mouse click (press and release in the same position) */
+static void sig_mouse_click(int b, int x, int y)
+{
+	GSList *l_bar;
+	
+	switch (b) {
+	/* left button */
+	case 0:
+		for (l_bar = active_mainwin->statusbars; l_bar != NULL; l_bar = l_bar->next) {
+			STATUSBAR_REC *bar = l_bar->data;
+			/* mouse is somewhere over the statusbar */
+			if (bar->real_ypos == y)
+				/* but is it over the "act" item? */
+				mouse_check_act (bar, x);
+		}
+		break;
+	/* middle button (in 3-button mice) */
+	case 1:
+		break;
+	/* mouse wheel up */
+	case 64:
+		window_prev_page();
+		break;
+	/* mouse wheel down */
+	case 65:
+		window_next_page();
+		break;
+	}
+}
+
+static void sig_mouse_gesture_up(void)
+{
+	const char *cmd = settings_get_str("mouse_gesture_up");
+	if (cmd[0])
+		signal_emit("send command", 3, cmd, active_win->active_server, active_win->active);
+}
+
+static void sig_mouse_gesture_down(void)
+{
+	const char *cmd = settings_get_str("mouse_gesture_down");
+	if (cmd[0])
+		signal_emit("send command", 3, cmd, active_win->active_server, active_win->active);
+}
+
+static void sig_mouse_gesture_left(void)
+{
+	const char *cmd = settings_get_str("mouse_gesture_left");
+	if (cmd[0])
+		signal_emit("send command", 3, cmd, active_win->active_server, active_win->active);
+}
+
+static void sig_mouse_gesture_bigleft(void)
+{
+	const char *cmd = settings_get_str("mouse_gesture_bigleft");
+	if (cmd[0])
+		signal_emit("send command", 3, cmd, active_win->active_server, active_win->active);
+}
+
+static void sig_mouse_gesture_right(void)
+{
+	const char *cmd = settings_get_str("mouse_gesture_right");
+	if (cmd[0])
+		signal_emit("send command", 3, cmd, active_win->active_server, active_win->active);
+}
+
+static void sig_mouse_gesture_bigright(void)
+{
+	const char *cmd = settings_get_str("mouse_gesture_bigright");
+	if (cmd[0])
+		signal_emit("send command", 3, cmd, active_win->active_server, active_win->active);
+}
+
 static void sig_gui_key_pressed(gpointer keyp)
 {
 	GTimeVal now;
@@ -456,6 +636,21 @@
 		return;
 	}
 
+	if (mouse_xterm_status != -1) {
+		if (mouse_xterm_status == 0)
+			memcpy(mouse_xterm_previous, mouse_xterm_combo, 3*sizeof(unichar));
+		mouse_xterm_combo[mouse_xterm_status] = key-32;
+		mouse_xterm_status++;
+		if (mouse_xterm_status == 3) {
+			mouse_xterm_status = -1;
+			/* match screen coordinates */
+			mouse_xterm_combo[1]--;
+			mouse_xterm_combo[2]--;
+			signal_emit("mouse event", 6, mouse_xterm_combo[0], mouse_xterm_combo[1], mouse_xterm_combo[2], mouse_xterm_previous[0], mouse_xterm_previous[1], mouse_xterm_previous[2]);
+		}
+		return;
+	}
+
         g_get_current_time(&now);
 	diff = (now.tv_sec - last_keypress.tv_sec) * 1000 +
 		(now.tv_usec - last_keypress.tv_usec)/1000;
@@ -565,6 +760,11 @@
 {
 }
 
+static void key_start_mouse_xterm(void)
+{
+	mouse_xterm_status = 0;
+}
+
 static void key_backward_history(void)
 {
 	const char *text;
@@ -963,6 +1163,12 @@
         g_free(text);
 }
 
+static void sig_window_changed(WINDOW_REC *window, WINDOW_REC *old)
+{
+	if (old != NULL)
+		old_window_refnum = old->refnum;
+}
+
 static void sig_gui_entry_redirect(SIGNAL_FUNC func, const char *entry,
 				   void *flags, void *data)
 {
@@ -1010,6 +1216,12 @@
 	g_get_current_time(&last_keypress);
         input_listen_init(STDIN_FILENO);
 
+	settings_add_str("lookandfeel", "mouse_gesture_up", "/window last");
+	settings_add_str("lookandfeel", "mouse_gesture_down", "/window goto active");
+	settings_add_str("lookandfeel", "mouse_gesture_left", "/window prev");
+	settings_add_str("lookandfeel", "mouse_gesture_bigleft", "/eval window prev;window prev");
+	settings_add_str("lookandfeel", "mouse_gesture_right", "/window next");
+	settings_add_str("lookandfeel", "mouse_gesture_bigright", "/eval window next;window next");
 	settings_add_str("history", "scroll_page_count", "/2");
 	settings_add_time("misc", "paste_detect_time", "5msecs");
 	settings_add_int("misc", "paste_detect_keycount", 5);
@@ -1034,6 +1246,7 @@
 	key_bind("key", NULL, "meta-[", "meta2", (SIGNAL_FUNC) key_combo);
 	key_bind("key", NULL, "meta-O", "meta2", (SIGNAL_FUNC) key_combo);
 	key_bind("key", NULL, "meta-[O", "meta2", (SIGNAL_FUNC) key_combo);
+	key_bind("key", NULL, "meta-[M", "mouse_xterm", (SIGNAL_FUNC) key_combo);
 
         /* arrow keys */
 	key_bind("key", NULL, "meta2-A", "up", (SIGNAL_FUNC) key_combo);
@@ -1137,13 +1350,23 @@
 
         /* misc */
 	key_bind("stop_irc", "Send SIGSTOP to client", "^Z", NULL, (SIGNAL_FUNC) key_sig_stop);
+	key_bind("start_mouse_xterm", "Start of xterm mouse tracking sequence", "mouse_xterm", NULL, (SIGNAL_FUNC) key_start_mouse_xterm);
 
         key_configure_thaw();
 
 	signal_add("window changed automatic", (SIGNAL_FUNC) sig_window_auto_changed);
+	signal_add("window changed", (SIGNAL_FUNC) sig_window_changed);
 	signal_add("gui entry redirect", (SIGNAL_FUNC) sig_gui_entry_redirect);
 	signal_add("gui key pressed", (SIGNAL_FUNC) sig_gui_key_pressed);
 	signal_add("setup changed", (SIGNAL_FUNC) setup_changed);
+	signal_add("mouse event", (SIGNAL_FUNC) sig_mouse_event);
+	signal_add("mouse click", (SIGNAL_FUNC) sig_mouse_click);
+	signal_add("mouse gesture up", (SIGNAL_FUNC) sig_mouse_gesture_up);
+	signal_add("mouse gesture down", (SIGNAL_FUNC) sig_mouse_gesture_down);
+	signal_add("mouse gesture left", (SIGNAL_FUNC) sig_mouse_gesture_left);
+	signal_add("mouse gesture bigleft", (SIGNAL_FUNC) sig_mouse_gesture_bigleft);
+	signal_add("mouse gesture right", (SIGNAL_FUNC) sig_mouse_gesture_right);
+	signal_add("mouse gesture bigright", (SIGNAL_FUNC) sig_mouse_gesture_bigright);
 }
 
 void gui_readline_deinit(void)
@@ -1201,13 +1424,23 @@
 	key_unbind("insert_text", (SIGNAL_FUNC) key_insert_text);
 	key_unbind("change_window", (SIGNAL_FUNC) key_change_window);
 	key_unbind("stop_irc", (SIGNAL_FUNC) key_sig_stop);
+	key_unbind("start_mouse_xterm", (SIGNAL_FUNC) key_start_mouse_xterm);
 	keyboard_destroy(keyboard);
         g_array_free(paste_buffer, TRUE);
 
         key_configure_thaw();
 
 	signal_remove("window changed automatic", (SIGNAL_FUNC) sig_window_auto_changed);
+	signal_remove("window changed", (SIGNAL_FUNC) sig_window_changed);
 	signal_remove("gui entry redirect", (SIGNAL_FUNC) sig_gui_entry_redirect);
 	signal_remove("gui key pressed", (SIGNAL_FUNC) sig_gui_key_pressed);
 	signal_remove("setup changed", (SIGNAL_FUNC) setup_changed);
+	signal_remove("mouse event", (SIGNAL_FUNC) sig_mouse_event);
+	signal_remove("mouse click", (SIGNAL_FUNC) sig_mouse_click);
+	signal_remove("mouse gesture up", (SIGNAL_FUNC) sig_mouse_gesture_up);
+	signal_remove("mouse gesture down", (SIGNAL_FUNC) sig_mouse_gesture_down);
+	signal_remove("mouse gesture left", (SIGNAL_FUNC) sig_mouse_gesture_left);
+	signal_remove("mouse gesture bigleft", (SIGNAL_FUNC) sig_mouse_gesture_bigleft);
+	signal_remove("mouse gesture right", (SIGNAL_FUNC) sig_mouse_gesture_right);
+	signal_remove("mouse gesture bigright", (SIGNAL_FUNC) sig_mouse_gesture_bigright);
 }
diff -urP irssi-0.8.10-rc5/src/fe-text/statusbar-items.c irssi-0.8.10-rc5-mouse_xterm/src/fe-text/statusbar-items.c
--- irssi-0.8.10-rc5/src/fe-text/statusbar-items.c	2002-12-31 12:36:36.000000000 +0000
+++ irssi-0.8.10-rc5-mouse_xterm/src/fe-text/statusbar-items.c	2005-04-10 02:08:22.000000000 +0100
@@ -68,7 +68,7 @@
 	}
 }
 
-static char *get_activity_list(MAIN_WINDOW_REC *window, int normal, int hilight)
+char *get_activity_list(MAIN_WINDOW_REC *window, int normal, int hilight)
 {
         THEME_REC *theme;
 	GString *str;
diff -urP irssi-0.8.10-rc5/src/fe-text/term.c irssi-0.8.10-rc5-mouse_xterm/src/fe-text/term.c
--- irssi-0.8.10-rc5/src/fe-text/term.c	2004-08-20 01:02:29.000000000 +0100
+++ irssi-0.8.10-rc5-mouse_xterm/src/fe-text/term.c	2005-04-10 02:08:22.000000000 +0100
@@ -42,6 +42,7 @@
 
 int term_use_colors;
 int term_type;
+int term_mouse_xterm = 0;
 
 static int force_colors;
 static int resize_dirty;
@@ -110,11 +111,21 @@
 	irssi_redraw();
 }
 
+static void mouse_xterm_tracking(int start)
+{
+	term_mouse_xterm = start;
+	if (start)
+		printf("\e[?1000h");
+	else
+		printf("\e[?1000l");
+}
+
 static void read_settings(void)
 {
         const char *str;
 	int old_colors = term_use_colors;
         int old_type = term_type;
+        int old_mouse_xterm = term_mouse_xterm;
 
         term_auto_detach(settings_get_bool("term_auto_detach"));
 
@@ -141,6 +152,32 @@
 
 	if (term_use_colors != old_colors)
 		irssi_redraw();
+
+	term_mouse_xterm = settings_get_bool("term_mouse_xterm");
+	if (term_mouse_xterm != old_mouse_xterm)
+		mouse_xterm_tracking(term_mouse_xterm);
+}
+
+/* Return 1 if $TERM is set to a xterm-compatible terminal, 0 otherwise */
+static int term_is_xterm_compatible(void)
+{
+	char *term;
+	int i;
+	static char *terms[] = {
+		"rxvt",
+		"screen",
+		"xterm",
+		"xterm-color",
+		NULL
+	};
+
+	term = getenv("TERM");
+	if (term == NULL)
+		return 0;
+	for (i = 0; terms[i] != NULL; i++)
+		if (strcmp(term, terms[i]) == 0)
+			return 1;
+	return 0;
 }
 
 void term_common_init(void)
@@ -148,6 +185,7 @@
 #ifdef SIGWINCH
 	struct sigaction act;
 #endif
+        settings_add_bool("lookandfeel", "term_mouse_xterm", TRUE);
 	settings_add_bool("lookandfeel", "colors", TRUE);
 	settings_add_bool("lookandfeel", "term_force_colors", FALSE);
         settings_add_bool("lookandfeel", "term_auto_detach", FALSE);
@@ -156,7 +194,11 @@
 
 	force_colors = FALSE;
 	term_use_colors = term_has_colors() && settings_get_bool("colors");
-        read_settings();
+	read_settings();
+
+	/* start xterm mouse tracking */
+	if (settings_get_bool("term_mouse_xterm") && term_is_xterm_compatible())
+		mouse_xterm_tracking(1);
 
 #if defined (HAVE_NL_LANGINFO) && defined(CODESET)
 	if (strcmp(nl_langinfo(CODESET), "UTF-8") == 0) {
@@ -180,6 +222,10 @@
 
 void term_common_deinit(void)
 {
+	/* stop xterm mouse tracking (whether term_mouse_xterm is on or off) */
+	if (term_is_xterm_compatible())
+		mouse_xterm_tracking(0);
+
 	command_unbind("resize", (SIGNAL_FUNC) cmd_resize);
 	command_unbind("redraw", (SIGNAL_FUNC) cmd_redraw);
 	signal_remove("beep", (SIGNAL_FUNC) term_beep);
