$NetBSD: patch-af,v 1.2 2010/08/10 20:26:36 sketch Exp $

--- src/core/icb-protocol.c	(revision 5174)
+++ src/core/icb-protocol.c	(working copy)
@@ -27,19 +27,19 @@
 #include "icb-servers.h"
 
 static char *signal_names[] = {
-	"login",
-	"open",
-	"personal",
-	"status",
-	"error",
-	"important",
-	"exit",
-	"command",
-	"cmdout",
-	"protocol",
-	"beep",
-	"ping",
-        "pong"
+	"login",	/* a */
+	"open",		/* b */
+	"personal",	/* c */
+	"status",	/* d */
+	"error",	/* e */
+	"important",	/* f */
+	"exit",		/* g */
+	"command",	/* h */
+	"cmdout",	/* i */
+	"protocol",	/* j */
+	"beep",		/* k */
+	"ping",		/* l */
+	"pong"		/* m */
 };
 
 #define SIGNAL_FIRST 'a'
@@ -121,9 +121,93 @@
 
 void icb_send_open_msg(ICB_SERVER_REC *server, const char *text)
 {
-        icb_send_cmd(server, 'b', text, NULL);
+	size_t remain;
+
+	/*
+	 * ICB has 255 byte line length limit, and public messages are sent
+	 * out with our nickname, so split text accordingly.
+	 *
+	 * 250 = 255 - 'b' - 1 space after nick - ^A - nul - extra
+	 *
+	 * Taken from ircII's icb.c, thanks phone :-)
+	 */
+	remain = 250 - strlen(server->connrec->nick);
+
+	while(*text) {
+		char buf[256], *sendbuf;
+		size_t len, copylen;
+
+		len = strlen(text);
+		copylen = remain;
+		if (len > remain) {
+			int i;
+
+			/* try to split on a word boundary */
+			for (i = 1; i < 128 && i < len; i++) {
+				if (isspace(text[remain - i])) {
+					copylen -= i - 1;
+					break;
+				}
+			}
+			strncpy(buf, text, copylen);
+			buf[copylen] = 0;
+			sendbuf = buf;
+		} else {
+			sendbuf = (char *)text;
+		}
+		icb_send_cmd(server, 'b', sendbuf, NULL);
+		text += len > copylen ? copylen : len;
+	}
 }
 
+void icb_send_private_msg(ICB_SERVER_REC *server, const char *target,
+		const char *text)
+{
+	size_t mylen, targlen, remain;
+
+	/*
+	 * ICB has 255 byte line length limit.  Private messages are sent
+	 * out with our nickname, but received with the target nickname,
+	 * so deduct the larger of the two in addition to other parts.
+	 *
+	 * 248 = 255 - 'hm' - 1 space after nick - ^A's - nul - extra
+	 *
+	 * Taken from ircII's icb.c, thanks phone :-)
+	 */
+	mylen = strlen(server->connrec->nick);
+	targlen = strlen(target);
+	if (mylen > targlen) {
+		remain = 248 - mylen;
+	} else {
+		remain = 248 - targlen;
+	}
+	while(*text) {
+		char buf[256], *sendbuf;
+		size_t len, copylen;
+
+		len = strlen(text);
+		copylen = remain;
+		if (len > remain) {
+			int i;
+
+			/* try to split on a word boundary */
+			for (i = 1; i < 128 && i < len; i++) {
+				if (isspace(text[remain - i])) {
+					copylen -= i - 1;
+					break;
+				}
+			}
+			strncpy(buf, text, copylen);
+			buf[copylen] = 0;
+			sendbuf = g_strconcat(target, " ", buf, NULL);
+		} else {
+			sendbuf = g_strconcat(target, " ", text, NULL);
+		}
+		icb_send_cmd(server, 'h', "m", sendbuf, NULL);
+		text += len > copylen ? copylen : len;
+	}
+}
+
 void icb_command(ICB_SERVER_REC *server, const char *cmd,
 		 const char *args, const char *id)
 {
@@ -293,6 +377,20 @@
         g_strfreev(args);
 }
 
+static void event_status(ICB_SERVER_REC *server, const char *data)
+{
+	char **args, *event;
+
+	args = g_strsplit(data, "\001", -1);
+	if (args[0] != NULL) {
+		event = g_strdup_printf("icb status %s", g_ascii_strdown(args[0], strlen(args[0])));
+		if (!signal_emit(event, 2, server, args))
+                        signal_emit("default icb status", 2, server, args);
+                g_free(event);
+	}
+        g_strfreev(args);
+}
+
 void icb_protocol_init(void)
 {
         signal_add("server connected", (SIGNAL_FUNC) sig_server_connected);
@@ -300,6 +398,7 @@
         signal_add("icb event login", (SIGNAL_FUNC) event_login);
         signal_add("icb event ping", (SIGNAL_FUNC) event_ping);
         signal_add("icb event cmdout", (SIGNAL_FUNC) event_cmdout);
+	signal_add("icb event status", (SIGNAL_FUNC) event_status);
 }
 
 void icb_protocol_deinit(void)
@@ -309,4 +408,5 @@
         signal_remove("icb event login", (SIGNAL_FUNC) event_login);
         signal_remove("icb event ping", (SIGNAL_FUNC) event_ping);
         signal_remove("icb event cmdout", (SIGNAL_FUNC) event_cmdout);
+        signal_remove("icb event status", (SIGNAL_FUNC) event_status);
 }
