summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--chat.h15
-rw-r--r--handle.c35
-rw-r--r--ui.c30
3 files changed, 39 insertions, 41 deletions
diff --git a/chat.h b/chat.h
index fd8f81a..023baf6 100644
--- a/chat.h
+++ b/chat.h
@@ -43,13 +43,20 @@
 typedef unsigned uint;
 typedef unsigned char byte;
 
-static inline void __attribute__((format(printf, 3, 4)))
-catf(char *buf, size_t cap, const char *format, ...) {
-	size_t len = strnlen(buf, cap);
+struct Cat {
+	char *buf;
+	size_t cap;
+	size_t len;
+};
+static inline void __attribute__((format(printf, 2, 3)))
+catf(struct Cat *cat, const char *format, ...) {
 	va_list ap;
 	va_start(ap, format);
-	assert(0 <= vsnprintf(&buf[len], cap - len, format, ap));
+	int len = vsnprintf(&cat->buf[cat->len], cat->cap - cat->len, format, ap);
+	assert(len >= 0);
 	va_end(ap);
+	cat->len += len;
+	if (cat->len >= cat->cap) cat->len = cat->cap - 1;
 }
 
 enum Color {
diff --git a/handle.c b/handle.c
index 5f29db2..cf9b296 100644
--- a/handle.c
+++ b/handle.c
@@ -65,9 +65,10 @@ static enum Cap capParse(const char *list) {
 static const char *capList(enum Cap caps) {
 	static char buf[1024];
 	buf[0] = '\0';
+	struct Cat cat = { buf, sizeof(buf), 0 };
 	for (size_t i = 0; i < ARRAY_LEN(CapNames); ++i) {
 		if (caps & (1 << i)) {
-			catf(buf, sizeof(buf), "%s%s", (buf[0] ? " " : ""), CapNames[i]);
+			catf(&cat, "%s%s", (buf[0] ? " " : ""), CapNames[i]);
 		}
 	}
 	return buf;
@@ -490,6 +491,7 @@ static void handleReplyNames(struct Message *msg) {
 	require(msg, false, 4);
 	uint id = idFor(msg->params[2]);
 	char buf[1024] = "";
+	struct Cat cat = { buf, sizeof(buf), 0 };
 	while (msg->params[3]) {
 		char *name = strsep(&msg->params[3], " ");
 		char *prefixes = strsep(&name, "!");
@@ -498,10 +500,7 @@ static void handleReplyNames(struct Message *msg) {
 		enum Color color = (user ? hash(user) : Default);
 		completeAdd(id, nick, color);
 		if (!replies.names) continue;
-		catf(
-			buf, sizeof(buf), "%s\3%02d%s\3",
-			(buf[0] ? ", " : ""), color, prefixes
-		);
+		catf(&cat, "%s\3%02d%s\3", (buf[0] ? ", " : ""), color, prefixes);
 	}
 	if (!replies.names) return;
 	uiFormat(
@@ -602,13 +601,11 @@ static void handleReplyUserModeIs(struct Message *msg) {
 	replies.mode--;
 
 	char buf[1024] = "";
+	struct Cat cat = { buf, sizeof(buf), 0 };
 	for (char *ch = msg->params[1]; *ch; ++ch) {
 		if (*ch == '+') continue;
 		const char *name = UserModes[(byte)*ch];
-		catf(
-			buf, sizeof(buf), ", +%c%s%s",
-			*ch, (name ? " " : ""), (name ?: "")
-		);
+		catf(&cat, ", +%c%s%s", *ch, (name ? " " : ""), (name ?: ""));
 	}
 	uiFormat(
 		Network, Warm, tagTime(msg),
@@ -639,6 +636,7 @@ static void handleReplyChannelModeIs(struct Message *msg) {
 
 	uint param = 3;
 	char buf[1024] = "";
+	struct Cat cat = { buf, sizeof(buf), 0 };
 	for (char *ch = msg->params[2]; *ch; ++ch) {
 		if (*ch == '+') continue;
 		const char *name = ChanModes[(byte)*ch];
@@ -648,13 +646,13 @@ static void handleReplyChannelModeIs(struct Message *msg) {
 		) {
 			assert(param < ParamCap);
 			catf(
-				buf, sizeof(buf), ", +%c%s%s %s",
+				&cat, ", +%c%s%s %s",
 				*ch, (name ? " " : ""), (name ?: ""),
 				msg->params[param++]
 			);
 		} else {
 			catf(
-				buf, sizeof(buf), ", +%c%s%s",
+				&cat, ", +%c%s%s",
 				*ch, (name ? " " : ""), (name ?: "")
 			);
 		}
@@ -987,13 +985,11 @@ static void handleReplyWhoisChannels(struct Message *msg) {
 	require(msg, false, 3);
 	if (!replies.whois) return;
 	char buf[1024] = "";
+	struct Cat cat = { buf, sizeof(buf), 0 };
 	while (msg->params[2]) {
 		char *channel = strsep(&msg->params[2], " ");
 		char *name = &channel[strspn(channel, network.prefixes)];
-		catf(
-			buf, sizeof(buf), "%s\3%02d%s\3",
-			(buf[0] ? ", " : ""), hash(name), channel
-		);
+		catf(&cat, "%s\3%02d%s\3", (buf[0] ? ", " : ""), hash(name), channel);
 	}
 	uiFormat(
 		Network, Warm, tagTime(msg),
@@ -1093,9 +1089,10 @@ static const char *colorMentions(uint id, struct Message *msg) {
 
 	static char buf[1024];
 	buf[0] = '\0';
+	struct Cat cat = { buf, sizeof(buf), 0 };
 	while (*mention) {
 		size_t skip = strspn(mention, ",<> ");
-		catf(buf, sizeof(buf), "%.*s", (int)skip, mention);
+		catf(&cat, "%.*s", (int)skip, mention);
 		mention += skip;
 
 		size_t len = strcspn(mention, ",<> ");
@@ -1103,14 +1100,14 @@ static const char *colorMentions(uint id, struct Message *msg) {
 		mention[len] = '\0';
 		enum Color color = completeColor(id, mention);
 		if (color != Default) {
-			catf(buf, sizeof(buf), "\3%02d%s\3", color, mention);
+			catf(&cat, "\3%02d%s\3", color, mention);
 		} else {
-			catf(buf, sizeof(buf), "%s", mention);
+			catf(&cat, "%s", mention);
 		}
 		mention[len] = punct;
 		mention += len;
 	}
-	catf(buf, sizeof(buf), "%c", delimit);
+	catf(&cat, "%c", delimit);
 	return buf;
 }
 
diff --git a/ui.c b/ui.c
index c92fb01..b6aaafc 100644
--- a/ui.c
+++ b/ui.c
@@ -465,45 +465,38 @@ static void statusUpdate(void) {
 			if (window->heat > others.heat) others.heat = window->heat;
 		}
 		char buf[256] = "";
+		struct Cat cat = { buf, sizeof(buf), 0 };
 		catf(
-			buf, sizeof(buf), "\3%d%s %u ",
+			&cat, "\3%d%s %u ",
 			idColors[window->id], (num == windows.show ? "\26" : ""), num
 		);
 		if (!window->ignore || window->mute) {
-			catf(
-				buf, sizeof(buf), "%s%s ",
-				&"-"[window->ignore], &"="[!window->mute]
-			);
+			catf(&cat, "%s%s ", &"-"[window->ignore], &"="[!window->mute]);
 		}
-		catf(buf, sizeof(buf), "%s ", idNames[window->id]);
+		catf(&cat, "%s ", idNames[window->id]);
 		if (window->mark && window->unreadWarm) {
 			catf(
-				buf, sizeof(buf), "\3%d+%d\3%d%s",
+				&cat, "\3%d+%d\3%d%s",
 				(window->heat > Warm ? White : idColors[window->id]),
 				window->unreadWarm, idColors[window->id],
 				(window->scroll ? "" : " ")
 			);
 		}
 		if (window->scroll) {
-			catf(buf, sizeof(buf), "~%d ", window->scroll);
+			catf(&cat, "~%d ", window->scroll);
 		}
 		statusAdd(buf);
 	}
 	wclrtoeol(status);
 
+	struct Cat cat = { title, sizeof(title), 0 };
 	const struct Window *window = windows.ptrs[windows.show];
-	snprintf(title, sizeof(title), "%s %s", network.name, idNames[window->id]);
+	catf(&cat, "%s %s", network.name, idNames[window->id]);
 	if (window->mark && window->unreadWarm) {
-		catf(
-			title, sizeof(title), " +%d%s",
-			window->unreadWarm, &"!"[window->heat < Hot]
-		);
+		catf(&cat, " +%d%s", window->unreadWarm, &"!"[window->heat < Hot]);
 	}
 	if (others.unread) {
-		catf(
-			title, sizeof(title), " (+%d%s)",
-			others.unread, &"!"[others.heat < Hot]
-		);
+		catf(&cat, " (+%d%s)", others.unread, &"!"[others.heat < Hot]);
 	}
 }
 
@@ -638,10 +631,11 @@ static void notify(uint id, const char *str) {
 	struct Util util = uiNotifyUtil;
 	utilPush(&util, idNames[id]);
 	char buf[1024] = "";
+	struct Cat cat = { buf, sizeof(buf), 0 };
 	while (*str) {
 		struct Style style = Reset;
 		size_t len = styleParse(&style, &str);
-		catf(buf, sizeof(buf), "%.*s", (int)len, str);
+		catf(&cat, "%.*s", (int)len, str);
 		str += len;
 	}
 	utilPush(&util, buf);