summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--chat.h3
-rw-r--r--handle.c73
-rw-r--r--weechat_nick_colors.c204
4 files changed, 250 insertions, 31 deletions
diff --git a/Makefile b/Makefile
index e8ef63a..27fa332 100644
--- a/Makefile
+++ b/Makefile
@@ -27,6 +27,7 @@ OBJS += ui.o
 OBJS += url.o
 OBJS += window.o
 OBJS += xdg.o
+OBJS += weechat_nick_colors.o
 
 TESTS += edit.t
 
diff --git a/chat.h b/chat.h
index 15c757f..c473f65 100644
--- a/chat.h
+++ b/chat.h
@@ -465,3 +465,6 @@ int getopt_config(
 	int argc, char *const *argv,
 	const char *optstring, const struct option *longopts, int *longindex
 );
+
+uint32_t weechat_nick_colors(const char *nick);
+#define hash weechat_nick_colors
diff --git a/handle.c b/handle.c
index 74c3a28..bd3ef0d 100644
--- a/handle.c
+++ b/handle.c
@@ -366,7 +366,7 @@ static void handleJoin(struct Message *msg) {
 	if (!strcmp(msg->nick, self.nick)) {
 		if (!self.user || strcmp(self.user, msg->user)) {
 			set(&self.user, msg->user);
-			self.color = hash(msg->user);
+			self.color = hash(msg->nick);
 		}
 		if (!self.host || strcmp(self.host, msg->host)) {
 			set(&self.host, msg->host);
@@ -378,14 +378,14 @@ static void handleJoin(struct Message *msg) {
 			replies[ReplyJoin]--;
 		}
 	}
-	cacheInsert(true, id, msg->nick)->color = hash(msg->user);
+	cacheInsert(true, id, msg->nick)->color = hash(msg->nick);
 	if (msg->params[2] && !strcasecmp(msg->params[2], msg->nick)) {
 		msg->params[2] = NULL;
 	}
 	uiFormat(
 		id, filterCheck(Cold, id, msg), tagTime(msg),
 		"\3%02d%s\3\t%s%s%sarrives in \3%02d%s\3",
-		hash(msg->user), msg->nick,
+		hash(msg->nick), msg->nick,
 		(msg->params[2] ? "(" : ""),
 		(msg->params[2] ?: ""),
 		(msg->params[2] ? "\17) " : ""),
@@ -418,7 +418,7 @@ static void handlePart(struct Message *msg) {
 	uiFormat(
 		id, heat, tagTime(msg),
 		"\3%02d%s\3\tleaves \3%02d%s\3%s%s",
-		hash(msg->user), msg->nick, hash(msg->params[0]), msg->params[0],
+		hash(msg->nick), msg->nick, hash(msg->params[0]), msg->params[0],
 		(msg->params[1] ? ": " : ""), (msg->params[1] ?: "")
 	);
 	logFormat(
@@ -432,13 +432,13 @@ static void handleKick(struct Message *msg) {
 	require(msg, true, 2);
 	uint id = idFor(msg->params[0]);
 	bool kicked = !strcmp(msg->params[1], self.nick);
-	cacheInsert(true, id, msg->nick)->color = hash(msg->user);
+	cacheInsert(true, id, msg->nick)->color = hash(msg->nick);
 	urlScan(id, msg->nick, msg->params[2]);
 	uiFormat(
 		id, (kicked ? Hot : Cold), tagTime(msg),
 		"%s\3%02d%s\17\tkicks \3%02d%s\3 out of \3%02d%s\3%s%s",
 		(kicked ? "\26" : ""),
-		hash(msg->user), msg->nick,
+		hash(msg->nick), msg->nick,
 		cacheGet(id, msg->params[1])->color, msg->params[1],
 		hash(msg->params[0]), msg->params[0],
 		(msg->params[2] ? ": " : ""), (msg->params[2] ?: "")
@@ -466,7 +466,7 @@ static void handleNick(struct Message *msg) {
 		uiFormat(
 			id, filterCheck(Cold, id, msg), tagTime(msg),
 			"\3%02d%s\3\tis now known as \3%02d%s\3",
-			hash(msg->user), msg->nick, hash(msg->user), msg->params[0]
+			hash(msg->nick), msg->nick, hash(msg->nick), msg->params[0]
 		);
 		if (id == Network) continue;
 		logFormat(
@@ -484,7 +484,7 @@ static void handleSetname(struct Message *msg) {
 		uiFormat(
 			id, filterCheck(Cold, id, msg), tagTime(msg),
 			"\3%02d%s\3\tis now known as \3%02d%s\3 (%s\17)",
-			hash(msg->user), msg->nick, hash(msg->user), msg->nick,
+			hash(msg->nick), msg->nick, hash(msg->nick), msg->nick,
 			msg->params[0]
 		);
 	}
@@ -499,7 +499,7 @@ static void handleQuit(struct Message *msg) {
 		uiFormat(
 			id, heat, tagTime(msg),
 			"\3%02d%s\3\tleaves%s%s",
-			hash(msg->user), msg->nick,
+			hash(msg->nick), msg->nick,
 			(msg->params[0] ? ": " : ""), (msg->params[0] ?: "")
 		);
 		if (id == Network) continue;
@@ -519,14 +519,14 @@ static void handleInvite(struct Message *msg) {
 		uiFormat(
 			Network, filterCheck(Hot, Network, msg), tagTime(msg),
 			"\3%02d%s\3\tinvites you to \3%02d%s\3",
-			hash(msg->user), msg->nick, hash(msg->params[1]), msg->params[1]
+			hash(msg->nick), msg->nick, hash(msg->params[1]), msg->params[1]
 		);
 	} else {
 		uint id = idFor(msg->params[1]);
 		uiFormat(
 			id, Cold, tagTime(msg),
 			"\3%02d%s\3\tinvites %s to \3%02d%s\3",
-			hash(msg->user), msg->nick,
+			hash(msg->nick), msg->nick,
 			msg->params[0],
 			hash(msg->params[1]), msg->params[1]
 		);
@@ -570,7 +570,7 @@ static void handleReplyNames(struct Message *msg) {
 		char *prefixes = strsep(&name, "!");
 		char *nick = &prefixes[strspn(prefixes, network.prefixes)];
 		char *user = strsep(&name, "@");
-		enum Color color = (user ? hash(user) : Default);
+		enum Color color = (user ? hash(nick) : Default); /* NOTE(bx): changed this from user to nick, bc it was getting gur wrong hash and color for people using bouncers + bots */
 		uint bits = 0;
 		for (char *p = prefixes; p < nick; ++p) {
 			bits |= prefixBit(*p);
@@ -681,7 +681,7 @@ static void handleTopic(struct Message *msg) {
 		uiFormat(
 			id, Warm, tagTime(msg),
 			"\3%02d%s\3\tremoves the sign in \3%02d%s\3",
-			hash(msg->user), msg->nick, hash(msg->params[0]), msg->params[0]
+			hash(msg->nick), msg->nick, hash(msg->params[0]), msg->params[0]
 		);
 		logFormat(
 			id, tagTime(msg), "%s removes the sign in %s",
@@ -716,14 +716,14 @@ static void handleTopic(struct Message *msg) {
 	char *ptr = buf, *end = &buf[sizeof(buf)];
 	ptr = seprintf(
 		ptr, end, "\3%02d%s\3\ttakes down the sign in \3%02d%s\3: ",
-		hash(msg->user), msg->nick, hash(msg->params[0]), msg->params[0]
+		hash(msg->nick), msg->nick, hash(msg->params[0]), msg->params[0]
 	);
 	ptr = highlightMiddle(ptr, end, Brown, old, pre, osuf);
 	if (osuf != pre) uiWrite(id, Cold, tagTime(msg), buf);
 	ptr = buf;
 	ptr = seprintf(
 		ptr, end, "\3%02d%s\3\tplaces a new sign in \3%02d%s\3: ",
-		hash(msg->user), msg->nick, hash(msg->params[0]), msg->params[0]
+		hash(msg->nick), msg->nick, hash(msg->params[0]), msg->params[0]
 	);
 	ptr = highlightMiddle(ptr, end, Green, new, pre, nsuf);
 	uiWrite(id, Warm, tagTime(msg), buf);
@@ -733,7 +733,7 @@ plain:
 	uiFormat(
 		id, Warm, tagTime(msg),
 		"\3%02d%s\3\tplaces a new sign in \3%02d%s\3: %s",
-		hash(msg->user), msg->nick, hash(msg->params[0]), msg->params[0],
+		hash(msg->nick), msg->nick, hash(msg->params[0]), msg->params[0],
 		msg->params[1]
 	);
 log:
@@ -831,7 +831,7 @@ static void handleMode(struct Message *msg) {
 			uiFormat(
 				Network, Warm, tagTime(msg),
 				"\3%02d%s\3\t%ssets \3%02d%s\3 %c%c%s%s",
-				hash(msg->user), msg->nick,
+				hash(msg->nick), msg->nick,
 				(set ? "" : "un"),
 				self.color, msg->params[0],
 				set["-+"], *ch, (name ? " " : ""), (name ?: "")
@@ -872,7 +872,7 @@ static void handleMode(struct Message *msg) {
 			uiFormat(
 				id, Cold, tagTime(msg),
 				"\3%02d%s\3\t%s \3%02d%c%s\3 %s%s in \3%02d%s\3",
-				hash(msg->user), msg->nick, verb,
+				hash(msg->nick), msg->nick, verb,
 				cacheGet(id, nick)->color, prefix, nick,
 				mode, name, hash(msg->params[0]), msg->params[0]
 			);
@@ -892,7 +892,7 @@ static void handleMode(struct Message *msg) {
 				uiFormat(
 					id, Cold, tagTime(msg),
 					"\3%02d%s\3\t%s %c%c %s from \3%02d%s\3",
-					hash(msg->user), msg->nick, verb, set["-+"], *ch, mask,
+					hash(msg->nick), msg->nick, verb, set["-+"], *ch, mask,
 					hash(msg->params[0]), msg->params[0]
 				);
 				logFormat(
@@ -905,7 +905,7 @@ static void handleMode(struct Message *msg) {
 				uiFormat(
 					id, Cold, tagTime(msg),
 					"\3%02d%s\3\t%s %s %s the \3%02d%s\3 %s%s list",
-					hash(msg->user), msg->nick, verb, mask, to,
+					hash(msg->nick), msg->nick, verb, mask, to,
 					hash(msg->params[0]), msg->params[0], mode, name
 				);
 				logFormat(
@@ -923,7 +923,7 @@ static void handleMode(struct Message *msg) {
 			uiFormat(
 				id, Cold, tagTime(msg),
 				"\3%02d%s\3\t%s \3%02d%s\3 %s%s %s",
-				hash(msg->user), msg->nick, verb,
+				hash(msg->nick), msg->nick, verb,
 				hash(msg->params[0]), msg->params[0], mode, name, param
 			);
 			logFormat(
@@ -940,7 +940,7 @@ static void handleMode(struct Message *msg) {
 			uiFormat(
 				id, Cold, tagTime(msg),
 				"\3%02d%s\3\t%s \3%02d%s\3 %s%s %s",
-				hash(msg->user), msg->nick, verb,
+				hash(msg->nick), msg->nick, verb,
 				hash(msg->params[0]), msg->params[0], mode, name, param
 			);
 			logFormat(
@@ -951,7 +951,7 @@ static void handleMode(struct Message *msg) {
 			uiFormat(
 				id, Cold, tagTime(msg),
 				"\3%02d%s\3\t%s \3%02d%s\3 %s%s",
-				hash(msg->user), msg->nick, verb,
+				hash(msg->nick), msg->nick, verb,
 				hash(msg->params[0]), msg->params[0], mode, name
 			);
 			logFormat(
@@ -964,7 +964,7 @@ static void handleMode(struct Message *msg) {
 			uiFormat(
 				id, Cold, tagTime(msg),
 				"\3%02d%s\3\t%s \3%02d%s\3 %s%s",
-				hash(msg->user), msg->nick, verb,
+				hash(msg->nick), msg->nick, verb,
 				hash(msg->params[0]), msg->params[0], mode, name
 			);
 			logFormat(
@@ -1278,7 +1278,7 @@ static void handlePrivmsg(struct Message *msg) {
 		id = Network;
 	} else if (query && !mine) {
 		id = idFor(msg->nick);
-		idColors[id] = hash(msg->user);
+		idColors[id] = hash(msg->nick);
 	} else {
 		id = idFor(msg->params[0]);
 	}
@@ -1290,10 +1290,13 @@ static void handlePrivmsg(struct Message *msg) {
 	heat = filterCheck(heat, id, msg);
 	if (heat > Warm && !mine && !query) highlight = true;
 	if (!notice && !mine && heat > Ice) {
-		cacheInsert(true, id, msg->nick)->color = hash(msg->user);
+		cacheInsert(true, id, msg->nick)->color = hash(msg->nick);
 	}
 	if (heat > Ice) urlScan(id, msg->nick, msg->params[1]);
 
+	static char last_nick[128] = "";
+	int reset_last_nick = 1;
+
 	char buf[1024];
 	char *ptr = buf, *end = &buf[sizeof(buf)];
 	if (statusmsg) {
@@ -1307,20 +1310,22 @@ static void handlePrivmsg(struct Message *msg) {
 		}
 		ptr = seprintf(
 			ptr, end, "\3%d-%s-\3%d\t",
-			hash(msg->user), msg->nick, LightGray
+			hash(msg->nick), msg->nick, LightGray
 		);
 	} else if (action) {
 		logFormat(id, tagTime(msg), "* %s %s", msg->nick, msg->params[1]);
 		ptr = seprintf(
-			ptr, end, "%s\35\3%d* %s\17\35\t",
-			(highlight ? "\26" : ""), hash(msg->user), msg->nick
+			ptr, end, "%s\35\3%d            * %s\17\35\t",
+			(highlight ? "\26" : ""), hash(msg->nick), msg->nick
 		);
 	} else {
 		logFormat(id, tagTime(msg), "<%s> %s", msg->nick, msg->params[1]);
 		ptr = seprintf(
-			ptr, end, "%s\3%d<%s>\17\t",
-			(highlight ? "\26" : ""), hash(msg->user), msg->nick
+			ptr, end, "%s\3%d %12.12s\17\t", /* NOTE(bx): i changed this cause i like things to line up */
+			(highlight ? "\26" : ""), hash(msg->nick),
+			(strncmp(msg->nick, last_nick, sizeof(last_nick) - 1) != 0) ? msg->nick : ""
 		);
+		reset_last_nick = 0;
 	}
 	if (notice) {
 		ptr = seprintf(ptr, end, "%s", msg->params[1]);
@@ -1328,6 +1333,12 @@ static void handlePrivmsg(struct Message *msg) {
 		ptr = colorMentions(ptr, end, id, msg->params[1]);
 	}
 	uiWrite(id, heat, tagTime(msg), buf);
+
+	if (reset_last_nick) {
+		strncpy(last_nick, "", sizeof(last_nick) - 1);
+	} else {
+		strncpy(last_nick, msg->nick, sizeof(last_nick) - 1);
+	}
 }
 
 static void handlePing(struct Message *msg) {
diff --git a/weechat_nick_colors.c b/weechat_nick_colors.c
new file mode 100644
index 0000000..c4011ad
--- /dev/null
+++ b/weechat_nick_colors.c
@@ -0,0 +1,204 @@
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <curses.h>
+
+#include "chat.h"
+
+int utf8_char_int (const char *string);
+const char *utf8_next_char (const char *string);
+void gui_nick_hash_djb2_64 (const char *nickname, uint64_t *color_64);
+int gui_nick_hash_color (const char *nickname);
+enum Color bx_weechat_nick_colors(const char *nick);
+
+int
+utf8_char_int (const char *string)
+{
+    const unsigned char *ptr_string;
+
+    if (!string)
+        return 0;
+
+    ptr_string = (unsigned char *)string;
+
+    /* UTF-8, 2 bytes: 110vvvvv 10vvvvvv */
+    if ((ptr_string[0] & 0xE0) == 0xC0)
+    {
+        if (!ptr_string[1])
+            return (int)(ptr_string[0] & 0x1F);
+        return ((int)(ptr_string[0] & 0x1F) << 6) +
+            ((int)(ptr_string[1] & 0x3F));
+    }
+    /* UTF-8, 3 bytes: 1110vvvv 10vvvvvv 10vvvvvv */
+    else if ((ptr_string[0] & 0xF0) == 0xE0)
+    {
+        if (!ptr_string[1])
+            return (int)(ptr_string[0] & 0x0F);
+        if (!ptr_string[2])
+            return (((int)(ptr_string[0] & 0x0F)) << 6) +
+                ((int)(ptr_string[1] & 0x3F));
+        return (((int)(ptr_string[0] & 0x0F)) << 12) +
+            (((int)(ptr_string[1] & 0x3F)) << 6) +
+            ((int)(ptr_string[2] & 0x3F));
+    }
+    /* UTF-8, 4 bytes: 11110vvv 10vvvvvv 10vvvvvv 10vvvvvv */
+    else if ((ptr_string[0] & 0xF8) == 0xF0)
+    {
+        if (!ptr_string[1])
+            return (int)(ptr_string[0] & 0x07);
+        if (!ptr_string[2])
+            return (((int)(ptr_string[0] & 0x07)) << 6) +
+                ((int)(ptr_string[1] & 0x3F));
+        if (!ptr_string[3])
+            return (((int)(ptr_string[0] & 0x07)) << 12) +
+                (((int)(ptr_string[1] & 0x3F)) << 6) +
+                ((int)(ptr_string[2] & 0x3F));
+        return (((int)(ptr_string[0] & 0x07)) << 18) +
+            (((int)(ptr_string[1] & 0x3F)) << 12) +
+            (((int)(ptr_string[2] & 0x3F)) << 6) +
+            ((int)(ptr_string[3] & 0x3F));
+    }
+    /* UTF-8, 1 byte: 0vvvvvvv */
+    return (int)ptr_string[0];
+}
+
+const char *
+utf8_next_char (const char *string)
+{
+    if (!string)
+        return NULL;
+
+    /* UTF-8, 2 bytes: 110vvvvv 10vvvvvv */
+    if (((unsigned char)(string[0]) & 0xE0) == 0xC0)
+    {
+        if (!string[1])
+            return (char *)string + 1;
+        return (char *)string + 2;
+    }
+    /* UTF-8, 3 bytes: 1110vvvv 10vvvvvv 10vvvvvv */
+    else if (((unsigned char)(string[0]) & 0xF0) == 0xE0)
+    {
+        if (!string[1])
+            return (char *)string + 1;
+        if (!string[2])
+            return (char *)string + 2;
+        return (char *)string + 3;
+    }
+    /* UTF-8, 4 bytes: 11110vvv 10vvvvvv 10vvvvvv 10vvvvvv */
+    else if (((unsigned char)(string[0]) & 0xF8) == 0xF0)
+    {
+        if (!string[1])
+            return (char *)string + 1;
+        if (!string[2])
+            return (char *)string + 2;
+        if (!string[3])
+            return (char *)string + 3;
+        return (char *)string + 4;
+    }
+    /* UTF-8, 1 byte: 0vvvvvvv */
+    return (char *)string + 1;
+}
+
+void
+gui_nick_hash_djb2_64 (const char *nickname, uint64_t *color_64)
+{
+    while (nickname && nickname[0])
+    {
+        *color_64 ^= (*color_64 << 5) + (*color_64 >> 2) +
+            utf8_char_int (nickname);
+        nickname = utf8_next_char (nickname);
+    }
+}
+
+/* cyan, magenta, green, brown, lightblue,
+default, lightcyan, lightmagenta, lightgreen, blue */
+
+/*
+ * Hashes a nickname to find color.
+ *
+ * Returns a number which is the index of color in the nicks colors of option
+ * "weechat.color.chat_nick_colors".
+ */
+
+int
+gui_nick_hash_color (const char *nickname)
+{
+    const char *ptr_salt;
+    uint64_t color_64;
+
+    ptr_salt = "";
+
+    color_64 = 0;
+
+    switch (1)
+    {
+        default:
+            /* variant of djb2 hash */
+            color_64 = 5381;
+            gui_nick_hash_djb2_64 (ptr_salt, &color_64);
+            gui_nick_hash_djb2_64 (nickname, &color_64);
+            break;
+    }
+
+    return (color_64 % 10);
+}
+
+/*
+	cyan, magenta, green, brown, lightblue,
+	default, lightcyan, lightmagenta, lightgreen, blue
+*/
+
+/*
+struct t_gui_color gui_weechat_colors_bold[GUI_CURSES_NUM_WEECHAT_COLORS + 1] =
+{ { -1,                -1,                0,      "default"      },
+{ COLOR_BLACK,       COLOR_BLACK,       0,      "black"        },
+{ COLOR_BLACK,       COLOR_BLACK + 8,   A_BOLD, "darkgray"     },
+{ COLOR_RED,         COLOR_RED,         0,      "red"          },
+{ COLOR_RED,         COLOR_RED + 8,     A_BOLD, "lightred"     },
+{ COLOR_GREEN,       COLOR_GREEN,       0,      "green"        },
+{ COLOR_GREEN,       COLOR_GREEN + 8,   A_BOLD, "lightgreen"   },
+{ COLOR_YELLOW,      COLOR_YELLOW,      0,      "brown"        },
+{ COLOR_YELLOW,      COLOR_YELLOW + 8,  A_BOLD, "yellow"       },
+{ COLOR_BLUE,        COLOR_BLUE,        0,      "blue"         },
+{ COLOR_BLUE,        COLOR_BLUE + 8,    A_BOLD, "lightblue"    },
+{ COLOR_MAGENTA,     COLOR_MAGENTA,     0,      "magenta"      },
+{ COLOR_MAGENTA,     COLOR_MAGENTA + 8, A_BOLD, "lightmagenta" },
+{ COLOR_CYAN,        COLOR_CYAN,        0,      "cyan"         },
+{ COLOR_CYAN,        COLOR_CYAN + 8,    A_BOLD, "lightcyan"    },
+{ COLOR_WHITE,       COLOR_WHITE,       0,      "gray"         },
+{ COLOR_WHITE,       COLOR_WHITE + 8,   A_BOLD, "white"        },
+{ 0,                 0,                 0,      NULL           }
+};
+*/
+
+/*
+	[Default]    = -1,
+	[White]      = 8 + COLOR_WHITE,
+	[Black]      = 0 + COLOR_BLACK,
+	[Blue]       = 0 + COLOR_BLUE,
+	[Green]      = 0 + COLOR_GREEN,
+	[Red]        = 8 + COLOR_RED,
+	[Brown]      = 0 + COLOR_RED,
+	[Magenta]    = 0 + COLOR_MAGENTA,
+	[Orange]     = 0 + COLOR_YELLOW,
+	[Yellow]     = 8 + COLOR_YELLOW,
+	[LightGreen] = 8 + COLOR_GREEN,
+	[Cyan]       = 0 + COLOR_CYAN,
+	[LightCyan]  = 8 + COLOR_CYAN,
+	[LightBlue]  = 8 + COLOR_BLUE,
+	[Pink]       = 8 + COLOR_MAGENTA,
+	[Gray]       = 8 + COLOR_BLACK,
+	[LightGray]  = 0 + COLOR_WHITE,
+*/
+
+// enum Color bx_weechat_nick_colors(const char *nick) {
+uint32_t weechat_nick_colors(const char *nick) {
+	enum Color weechat_colors[] = {
+		Cyan, Magenta, Green, Orange, LightBlue,
+		Default, LightCyan, Pink, LightGreen, Blue,
+	};
+
+	int color = gui_nick_hash_color(nick);
+
+	return (uint32_t) weechat_colors[color];
+}