Replace catf with seprintf

weechat-hashes
C. McEnroe 2021-06-07 00:09:58 -04:00
parent 5c3cd59af6
commit e066a954f5
6 changed files with 104 additions and 79 deletions

View File

@ -82,17 +82,18 @@ const struct Line *bufferHard(const struct Buffer *buffer, size_t i) {
} }
enum { StyleCap = 10 }; enum { StyleCap = 10 };
static void styleCat(struct Cat *cat, struct Style style) { static char *styleCopy(char *ptr, char *end, struct Style style) {
catf( ptr = seprintf(
cat, "%s%s%s%s", ptr, end, "%s%s%s%s",
(style.attr & Bold ? (const char []) { B, '\0' } : ""), (style.attr & Bold ? (const char []) { B, '\0' } : ""),
(style.attr & Reverse ? (const char []) { R, '\0' } : ""), (style.attr & Reverse ? (const char []) { R, '\0' } : ""),
(style.attr & Italic ? (const char []) { I, '\0' } : ""), (style.attr & Italic ? (const char []) { I, '\0' } : ""),
(style.attr & Underline ? (const char []) { U, '\0' } : "") (style.attr & Underline ? (const char []) { U, '\0' } : "")
); );
if (style.fg != Default || style.bg != Default) { if (style.fg != Default || style.bg != Default) {
catf(cat, "\3%02d,%02d", style.fg, style.bg); ptr = seprintf(ptr, end, "\3%02d,%02d", style.fg, style.bg);
} }
return ptr;
} }
static const wchar_t ZWS = L'\u200B'; static const wchar_t ZWS = L'\u200B';
@ -186,12 +187,11 @@ static int flow(struct Lines *hard, int cols, const struct Line *soft) {
line->str = malloc(cap); line->str = malloc(cap);
if (!line->str) err(EX_OSERR, "malloc"); if (!line->str) err(EX_OSERR, "malloc");
struct Cat cat = { line->str, cap, 0 }; char *end = &line->str[cap];
catf(&cat, "%*s", (width = align), ""); str = seprintf(line->str, end, "%*s", (width = align), "");
styleCat(&cat, wrapStyle); str = styleCopy(str, end, wrapStyle);
str = &line->str[cat.len];
style = wrapStyle; style = wrapStyle;
catf(&cat, "%s", &wrap[n]); seprintf(str, end, "%s", &wrap[n]);
*wrap = '\0'; *wrap = '\0';
wrap = NULL; wrap = NULL;

8
chat.c
View File

@ -313,14 +313,14 @@ int main(int argc, char *argv[]) {
if (self.restricted) unveilAll(trust, cert, priv); if (self.restricted) unveilAll(trust, cert, priv);
char promises[64] = "stdio tty"; char promises[64] = "stdio tty";
struct Cat cat = { promises, sizeof(promises), strlen(promises) }; char *ptr = &promises[strlen(promises)], *end = &promises[sizeof(promises)];
if (save || logEnable) catf(&cat, " rpath wpath cpath"); if (save || logEnable) ptr = seprintf(ptr, end, " rpath wpath cpath");
if (!self.restricted) catf(&cat, " proc exec"); if (!self.restricted) ptr = seprintf(ptr, end, " proc exec");
char *promisesFinal = strdup(promises); char *promisesFinal = strdup(promises);
if (!promisesFinal) err(EX_OSERR, "strdup"); if (!promisesFinal) err(EX_OSERR, "strdup");
catf(&cat, " rpath inet dns"); seprintf(ptr, end, " rpath inet dns");
int error = pledge(promises, NULL); int error = pledge(promises, NULL);
if (error) err(EX_OSERR, "pledge"); if (error) err(EX_OSERR, "pledge");
#endif #endif

6
chat.h
View File

@ -117,11 +117,13 @@ static inline size_t styleParse(struct Style *style, const char **str) {
return strcspn(*str, (const char[]) { B, C, O, R, I, U, '\0' }); return strcspn(*str, (const char[]) { B, C, O, R, I, U, '\0' });
} }
static inline void styleStrip(struct Cat *cat, const char *str) { static inline void styleStrip(char *buf, size_t cap, const char *str) {
*buf = '\0';
char *ptr = buf, *end = &buf[cap];
struct Style style = StyleDefault; struct Style style = StyleDefault;
while (*str) { while (*str) {
size_t len = styleParse(&style, &str); size_t len = styleParse(&style, &str);
catf(cat, "%.*s", (int)len, str); ptr = seprintf(ptr, end, "%.*s", (int)len, str);
str += len; str += len;
} }
} }

118
handle.c
View File

@ -63,13 +63,16 @@ static enum Cap capParse(const char *list) {
return caps; return caps;
} }
static const char *capList(struct Cat *cat, enum Cap caps) { static void capList(char *buf, size_t cap, enum Cap caps) {
*buf = '\0';
char *ptr = buf, *end = &buf[cap];
for (size_t i = 0; i < ARRAY_LEN(CapNames); ++i) { for (size_t i = 0; i < ARRAY_LEN(CapNames); ++i) {
if (caps & (1 << i)) { if (caps & (1 << i)) {
catf(cat, "%s%s", (cat->len ? " " : ""), CapNames[i]); ptr = seprintf(
ptr, end, "%s%s", (ptr > buf ? " " : ""), CapNames[i]
);
} }
} }
return cat->buf;
} }
static void require(struct Message *msg, bool origin, uint len) { static void require(struct Message *msg, bool origin, uint len) {
@ -152,9 +155,9 @@ static void handleCap(struct Message *msg) {
caps &= ~CapConsumer; caps &= ~CapConsumer;
} }
if (caps) { if (caps) {
char buf[512] = ""; char buf[512];
struct Cat cat = { buf, sizeof(buf), 0 }; capList(buf, sizeof(buf), caps);
ircFormat("CAP REQ :%s\r\n", capList(&cat, caps)); ircFormat("CAP REQ :%s\r\n", buf);
} else { } else {
if (!(self.caps & CapSASL)) ircFormat("CAP END\r\n"); if (!(self.caps & CapSASL)) ircFormat("CAP END\r\n");
} }
@ -522,8 +525,8 @@ static void handleErrorUserOnChannel(struct Message *msg) {
static void handleReplyNames(struct Message *msg) { static void handleReplyNames(struct Message *msg) {
require(msg, false, 4); require(msg, false, 4);
uint id = idFor(msg->params[2]); uint id = idFor(msg->params[2]);
char buf[1024] = ""; char buf[1024];
struct Cat cat = { buf, sizeof(buf), 0 }; char *ptr = buf, *end = &buf[sizeof(buf)];
while (msg->params[3]) { while (msg->params[3]) {
char *name = strsep(&msg->params[3], " "); char *name = strsep(&msg->params[3], " ");
char *prefixes = strsep(&name, "!"); char *prefixes = strsep(&name, "!");
@ -532,9 +535,11 @@ static void handleReplyNames(struct Message *msg) {
enum Color color = (user ? hash(user) : Default); enum Color color = (user ? hash(user) : Default);
completeAdd(id, nick, color); completeAdd(id, nick, color);
if (!replies[ReplyNames] && !replies[ReplyNamesAuto]) continue; if (!replies[ReplyNames] && !replies[ReplyNamesAuto]) continue;
catf(&cat, "%s\3%02d%s\3", (buf[0] ? ", " : ""), color, prefixes); ptr = seprintf(
ptr, end, "%s\3%02d%s\3", (ptr > buf ? ", " : ""), color, prefixes
);
} }
if (!cat.len) return; if (ptr == buf) return;
uiFormat( uiFormat(
id, (replies[ReplyNamesAuto] ? Cold : Warm), tagTime(msg), id, (replies[ReplyNamesAuto] ? Cold : Warm), tagTime(msg),
"In \3%02d%s\3 are %s", "In \3%02d%s\3 are %s",
@ -551,14 +556,20 @@ static void handleReplyEndOfNames(struct Message *msg) {
} }
} }
static char whoBuf[1024]; static struct {
static struct Cat whoCat = { whoBuf, sizeof(whoBuf), 0 }; char buf[1024];
char *ptr;
char *end;
} who = {
.ptr = who.buf,
.end = &who.buf[sizeof(who.buf)],
};
static void handleReplyWho(struct Message *msg) { static void handleReplyWho(struct Message *msg) {
require(msg, false, 7); require(msg, false, 7);
if (!whoCat.len) { if (who.ptr == who.buf) {
catf( who.ptr = seprintf(
&whoCat, "The operators of \3%02d%s\3 are ", who.ptr, who.end, "The operators of \3%02d%s\3 are ",
hash(msg->params[1]), msg->params[1] hash(msg->params[1]), msg->params[1]
); );
} }
@ -566,9 +577,9 @@ static void handleReplyWho(struct Message *msg) {
if (prefixes[0] == '*') prefixes++; if (prefixes[0] == '*') prefixes++;
prefixes[strspn(prefixes, network.prefixes)] = '\0'; prefixes[strspn(prefixes, network.prefixes)] = '\0';
if (!prefixes[0] || prefixes[0] == '+') return; if (!prefixes[0] || prefixes[0] == '+') return;
catf( who.ptr = seprintf(
&whoCat, "%s\3%02d%s%s\3%s", who.ptr, who.end, "%s\3%02d%s%s\3%s",
(whoCat.buf[whoCat.len - 1] == ' ' ? "" : ", "), (who.ptr[-1] == ' ' ? "" : ", "),
hash(msg->params[2]), prefixes, msg->params[5], hash(msg->params[2]), prefixes, msg->params[5],
(msg->params[6][0] == 'H' ? "" : " (away)") (msg->params[6][0] == 'H' ? "" : " (away)")
); );
@ -576,8 +587,8 @@ static void handleReplyWho(struct Message *msg) {
static void handleReplyEndOfWho(struct Message *msg) { static void handleReplyEndOfWho(struct Message *msg) {
require(msg, false, 2); require(msg, false, 2);
uiWrite(idFor(msg->params[1]), Warm, tagTime(msg), whoBuf); uiWrite(idFor(msg->params[1]), Warm, tagTime(msg), who.buf);
whoCat.len = 0; who.ptr = who.buf;
} }
static void handleReplyNoTopic(struct Message *msg) { static void handleReplyNoTopic(struct Message *msg) {
@ -648,7 +659,7 @@ static void handleTopic(struct Message *msg) {
} }
char buf[1024]; char buf[1024];
struct Cat cat = { buf, sizeof(buf), 0 }; char *ptr = buf, *end = &buf[sizeof(buf)];
const char *prev = complete(id, "/topic "); const char *prev = complete(id, "/topic ");
completeReject(); completeReject();
if (prev) { if (prev) {
@ -663,7 +674,7 @@ static void handleTopic(struct Message *msg) {
if (swprintf(new, ARRAY_LEN(new), L"%s", msg->params[1]) < 0) goto plain; if (swprintf(new, ARRAY_LEN(new), L"%s", msg->params[1]) < 0) goto plain;
if (!hashBound) { if (!hashBound) {
catf(&cat, "%c%ls%c -> %c%ls%c", R, old, O, R, new, O); ptr = seprintf(ptr, end, "%c%ls%c -> %c%ls%c", R, old, O, R, new, O);
goto plain; goto plain;
} }
@ -678,15 +689,15 @@ static void handleTopic(struct Message *msg) {
wchar_t nul = L'\0'; wchar_t nul = L'\0';
swap(&new[pre], &nul); swap(&new[pre], &nul);
catf(&cat, "%ls", new); ptr = seprintf(ptr, end, "%ls", new);
swap(&new[pre], &nul); swap(&new[pre], &nul);
swap(osuf, &nul); swap(osuf, &nul);
catf(&cat, "\3%02d,%02d%ls", Default, Brown, &old[pre]); ptr = seprintf(ptr, end, "\3%02d,%02d%ls", Default, Brown, &old[pre]);
swap(osuf, &nul); swap(osuf, &nul);
swap(nsuf, &nul); swap(nsuf, &nul);
catf(&cat, "\3%02d,%02d%ls", Default, Green, &new[pre]); ptr = seprintf(ptr, end, "\3%02d,%02d%ls", Default, Green, &new[pre]);
swap(nsuf, &nul); swap(nsuf, &nul);
catf(&cat, "\3%02d,%02d%ls", Default, Default, nsuf); ptr = seprintf(ptr, end, "\3%02d,%02d%ls", Default, Default, nsuf);
plain: plain:
topicComplete(id, msg->params[1]); topicComplete(id, msg->params[1]);
@ -695,7 +706,7 @@ plain:
id, Warm, tagTime(msg), id, Warm, tagTime(msg),
"\3%02d%s\3\tplaces a new sign in \3%02d%s\3: %s", "\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->user), msg->nick, hash(msg->params[0]), msg->params[0],
(cat.len ? cat.buf : msg->params[1]) (ptr > buf ? buf : msg->params[1])
); );
logFormat( logFormat(
id, tagTime(msg), "%s places a new sign in %s: %s", id, tagTime(msg), "%s places a new sign in %s: %s",
@ -713,17 +724,19 @@ static const char *UserModes[256] = {
static void handleReplyUserModeIs(struct Message *msg) { static void handleReplyUserModeIs(struct Message *msg) {
require(msg, false, 2); require(msg, false, 2);
char buf[1024] = ""; char buf[1024];
struct Cat cat = { buf, sizeof(buf), 0 }; char *ptr = buf, *end = &buf[sizeof(buf)];
for (char *ch = msg->params[1]; *ch; ++ch) { for (char *ch = msg->params[1]; *ch; ++ch) {
if (*ch == '+') continue; if (*ch == '+') continue;
const char *name = UserModes[(byte)*ch]; const char *name = UserModes[(byte)*ch];
catf(&cat, ", +%c%s%s", *ch, (name ? " " : ""), (name ?: "")); ptr = seprintf(
ptr, end, ", +%c%s%s", *ch, (name ? " " : ""), (name ?: "")
);
} }
uiFormat( uiFormat(
Network, Warm, tagTime(msg), Network, Warm, tagTime(msg),
"\3%02d%s\3\tis %s", "\3%02d%s\3\tis %s",
self.color, self.nick, (buf[0] ? &buf[2] : "modeless") self.color, self.nick, (ptr > buf ? &buf[2] : "modeless")
); );
} }
@ -745,8 +758,8 @@ static const char *ChanModes[256] = {
static void handleReplyChannelModeIs(struct Message *msg) { static void handleReplyChannelModeIs(struct Message *msg) {
require(msg, false, 3); require(msg, false, 3);
uint param = 3; uint param = 3;
char buf[1024] = ""; char buf[1024];
struct Cat cat = { buf, sizeof(buf), 0 }; char *ptr = buf, *end = &buf[sizeof(buf)];
for (char *ch = msg->params[2]; *ch; ++ch) { for (char *ch = msg->params[2]; *ch; ++ch) {
if (*ch == '+') continue; if (*ch == '+') continue;
const char *name = ChanModes[(byte)*ch]; const char *name = ChanModes[(byte)*ch];
@ -755,14 +768,14 @@ static void handleReplyChannelModeIs(struct Message *msg) {
strchr(network.setParamModes, *ch) strchr(network.setParamModes, *ch)
) { ) {
assert(param < ParamCap); assert(param < ParamCap);
catf( ptr = seprintf(
&cat, ", +%c%s%s %s", ptr, end, ", +%c%s%s %s",
*ch, (name ? " " : ""), (name ?: ""), *ch, (name ? " " : ""), (name ?: ""),
msg->params[param++] msg->params[param++]
); );
} else { } else {
catf( ptr = seprintf(
&cat, ", +%c%s%s", ptr, end, ", +%c%s%s",
*ch, (name ? " " : ""), (name ?: "") *ch, (name ? " " : ""), (name ?: "")
); );
} }
@ -771,7 +784,7 @@ static void handleReplyChannelModeIs(struct Message *msg) {
idFor(msg->params[1]), Warm, tagTime(msg), idFor(msg->params[1]), Warm, tagTime(msg),
"\3%02d%s\3\tis %s", "\3%02d%s\3\tis %s",
hash(msg->params[1]), msg->params[1], hash(msg->params[1]), msg->params[1],
(buf[0] ? &buf[2] : "modeless") (ptr > buf ? &buf[2] : "modeless")
); );
} }
@ -1065,12 +1078,15 @@ static void handleReplyWhoisIdle(struct Message *msg) {
static void handleReplyWhoisChannels(struct Message *msg) { static void handleReplyWhoisChannels(struct Message *msg) {
require(msg, false, 3); require(msg, false, 3);
char buf[1024] = ""; char buf[1024];
struct Cat cat = { buf, sizeof(buf), 0 }; char *ptr = buf, *end = &buf[sizeof(buf)];
while (msg->params[2]) { while (msg->params[2]) {
char *channel = strsep(&msg->params[2], " "); char *channel = strsep(&msg->params[2], " ");
char *name = &channel[strspn(channel, network.prefixes)]; char *name = &channel[strspn(channel, network.prefixes)];
catf(&cat, "%s\3%02d%s\3", (buf[0] ? ", " : ""), hash(name), channel); ptr = seprintf(
ptr, end, "%s\3%02d%s\3",
(ptr > buf ? ", " : ""), hash(name), channel
);
} }
uiFormat( uiFormat(
Network, Warm, tagTime(msg), Network, Warm, tagTime(msg),
@ -1166,7 +1182,9 @@ static bool isMention(const struct Message *msg) {
return false; return false;
} }
static void colorMentions(struct Cat *cat, uint id, struct Message *msg) { static void colorMentions(char *buf, size_t cap, uint id, struct Message *msg) {
*buf = '\0';
char *split = strstr(msg->params[1], ": "); char *split = strstr(msg->params[1], ": ");
if (!split) { if (!split) {
split = strchr(msg->params[1], ' '); split = strchr(msg->params[1], ' ');
@ -1181,9 +1199,10 @@ static void colorMentions(struct Cat *cat, uint id, struct Message *msg) {
msg->params[1] = (delimit ? &split[1] : split); msg->params[1] = (delimit ? &split[1] : split);
*split = '\0'; *split = '\0';
char *ptr = buf, *end = &buf[cap];
while (*mention) { while (*mention) {
size_t skip = strspn(mention, ",<> "); size_t skip = strspn(mention, ",<> ");
catf(cat, "%.*s", (int)skip, mention); ptr = seprintf(ptr, end, "%.*s", (int)skip, mention);
mention += skip; mention += skip;
size_t len = strcspn(mention, ",<> "); size_t len = strcspn(mention, ",<> ");
@ -1191,14 +1210,14 @@ static void colorMentions(struct Cat *cat, uint id, struct Message *msg) {
mention[len] = '\0'; mention[len] = '\0';
enum Color color = completeColor(id, mention); enum Color color = completeColor(id, mention);
if (color != Default) { if (color != Default) {
catf(cat, "\3%02d%s\3", color, mention); ptr = seprintf(ptr, end, "\3%02d%s\3", color, mention);
} else { } else {
catf(cat, "%s", mention); ptr = seprintf(ptr, end, "%s", mention);
} }
mention[len] = punct; mention[len] = punct;
mention += len; mention += len;
} }
catf(cat, "%c", delimit); seprintf(ptr, end, "%c", delimit);
} }
static void handlePrivmsg(struct Message *msg) { static void handlePrivmsg(struct Message *msg) {
@ -1229,8 +1248,7 @@ static void handlePrivmsg(struct Message *msg) {
} }
if (heat > Ice) urlScan(id, msg->nick, msg->params[1]); if (heat > Ice) urlScan(id, msg->nick, msg->params[1]);
char buf[1024] = ""; char buf[1024];
struct Cat cat = { buf, sizeof(buf), 0 };
if (notice) { if (notice) {
if (id != Network) { if (id != Network) {
logFormat(id, tagTime(msg), "-%s- %s", msg->nick, msg->params[1]); logFormat(id, tagTime(msg), "-%s- %s", msg->nick, msg->params[1]);
@ -1242,7 +1260,7 @@ static void handlePrivmsg(struct Message *msg) {
); );
} else if (action) { } else if (action) {
logFormat(id, tagTime(msg), "* %s %s", msg->nick, msg->params[1]); logFormat(id, tagTime(msg), "* %s %s", msg->nick, msg->params[1]);
colorMentions(&cat, id, msg); colorMentions(buf, sizeof(buf), id, msg);
uiFormat( uiFormat(
id, heat, tagTime(msg), id, heat, tagTime(msg),
"%s\35\3%d* %s\17\35\t%s%s", "%s\35\3%d* %s\17\35\t%s%s",
@ -1251,7 +1269,7 @@ static void handlePrivmsg(struct Message *msg) {
); );
} else { } else {
logFormat(id, tagTime(msg), "<%s> %s", msg->nick, msg->params[1]); logFormat(id, tagTime(msg), "<%s> %s", msg->nick, msg->params[1]);
colorMentions(&cat, id, msg); colorMentions(buf, sizeof(buf), id, msg);
uiFormat( uiFormat(
id, heat, tagTime(msg), id, heat, tagTime(msg),
"%s\3%d<%s>\17\t%s%s", "%s\3%d<%s>\17\t%s%s",

31
ui.c
View File

@ -403,37 +403,42 @@ static void statusUpdate(void) {
others.unread += window->unreadWarm; others.unread += window->unreadWarm;
if (window->heat > others.heat) others.heat = window->heat; if (window->heat > others.heat) others.heat = window->heat;
} }
char buf[256] = ""; char buf[256], *end = &buf[sizeof(buf)];
struct Cat cat = { buf, sizeof(buf), 0 }; char *ptr = seprintf(
catf( buf, end, "\3%d%s %u%s%s %s ",
&cat, "\3%d%s %u%s%s %s ",
idColors[window->id], (num == windows.show ? "\26" : ""), idColors[window->id], (num == windows.show ? "\26" : ""),
num, window->thresh[(const char *[]) { "-", "", "+", "++" }], num, window->thresh[(const char *[]) { "-", "", "+", "++" }],
&"="[!window->mute], idNames[window->id] &"="[!window->mute], idNames[window->id]
); );
if (window->mark && window->unreadWarm) { if (window->mark && window->unreadWarm) {
catf( ptr = seprintf(
&cat, "\3%d+%d\3%d%s", ptr, end, "\3%d+%d\3%d%s",
(window->heat > Warm ? White : idColors[window->id]), (window->heat > Warm ? White : idColors[window->id]),
window->unreadWarm, idColors[window->id], window->unreadWarm, idColors[window->id],
(window->scroll ? "" : " ") (window->scroll ? "" : " ")
); );
} }
if (window->scroll) { if (window->scroll) {
catf(&cat, "~%d ", window->scroll); ptr = seprintf(ptr, end, "~%d ", window->scroll);
} }
if (styleAdd(status, buf) < 0) break; if (styleAdd(status, buf) < 0) break;
} }
wclrtoeol(status); wclrtoeol(status);
struct Cat cat = { title, sizeof(title), 0 };
const struct Window *window = windows.ptrs[windows.show]; const struct Window *window = windows.ptrs[windows.show];
catf(&cat, "%s %s", network.name, idNames[window->id]); char *end = &title[sizeof(title)];
char *ptr = seprintf(
title, end, "%s %s", network.name, idNames[window->id]
);
if (window->mark && window->unreadWarm) { if (window->mark && window->unreadWarm) {
catf(&cat, " +%d%s", window->unreadWarm, &"!"[window->heat < Hot]); ptr = seprintf(
ptr, end, " +%d%s", window->unreadWarm, &"!"[window->heat < Hot]
);
} }
if (others.unread) { if (others.unread) {
catf(&cat, " (+%d%s)", others.unread, &"!"[others.heat < Hot]); ptr = seprintf(
ptr, end, " (+%d%s)", others.unread, &"!"[others.heat < Hot]
);
} }
} }
@ -550,8 +555,8 @@ static void notify(uint id, const char *str) {
if (self.restricted) return; if (self.restricted) return;
if (!uiNotifyUtil.argc) return; if (!uiNotifyUtil.argc) return;
char buf[1024] = ""; char buf[1024];
styleStrip(&(struct Cat) { buf, sizeof(buf), 0 }, str); styleStrip(buf, sizeof(buf), str);
struct Util util = uiNotifyUtil; struct Util util = uiNotifyUtil;
utilPush(&util, idNames[id]); utilPush(&util, idNames[id]);

2
url.c
View File

@ -98,7 +98,7 @@ static void push(uint id, const char *nick, const char *str, size_t len) {
char buf[1024]; char buf[1024];
snprintf(buf, sizeof(buf), "%.*s", (int)len, str); snprintf(buf, sizeof(buf), "%.*s", (int)len, str);
styleStrip(&(struct Cat) { url->url, len + 1, 0 }, buf); styleStrip(url->url, len + 1, buf);
} }
void urlScan(uint id, const char *nick, const char *mesg) { void urlScan(uint id, const char *nick, const char *mesg) {