commit 0c655c6feaffd0c6d4a22c8b5e49a5aeed068360
parent de6f994e5eff48db8bc3738ad3a7cb48a8348a95
Author: hhvn <dev@hhvn.uk>
Date: Sat, 14 May 2022 18:28:02 +0100
yacc parser for formats
Diffstat:
11 files changed, 891 insertions(+), 812 deletions(-)
diff --git a/Makefile b/Makefile
@@ -18,10 +18,11 @@ PREFIX = /usr/local
BINDIR = $(PREFIX)/bin
MANDIR = $(PREFIX)/share/man
BIN = hirc
+PARSE = src/format.y
SRC = src/main.c src/mem.c src/handle.c src/hist.c \
src/nick.c src/chan.c src/serv.c src/ui.c \
- src/format.c src/complete.c src/commands.c \
- src/config.c src/str.c src/params.c
+ src/complete.c src/commands.c src/config.c \
+ src/str.c src/params.c $(PARSE:.y=.c)
OBJ = $(SRC:.c=.o)
MAN = doc/hirc.1
COMMIT = $(shell git log HEAD...HEAD~1 --pretty=format:%h)
diff --git a/configure b/configure
@@ -74,6 +74,22 @@ ${CC} -o test test.c >/dev/null 2>/dev/null && ./test >/dev/null 2>/dev/null &&
EOF
}
+printf '%s' "checking for strlcat... "
+cat > test.c <<- EOF
+ #include <string.h>
+ int main(void) { char a[3] = {'a', '\0', '\0'}; strlcat(a, "bc", sizeof(a)); return 0; }
+EOF
+${CC} -o test test.c >/dev/null 2>/dev/null && ./test >/dev/null 2>/dev/null && {
+ printf '%s\n' "yes"
+} || {
+ printf '%s\n' "no"
+ cat >> config.mk <<- EOF
+ # linking an included version of strlcat, as your system doesn't have it
+ CFLAGS += -DHIRC_STRLCAT
+ SRC += src/openbsd/strlcat.c
+ EOF
+}
+
printf '%s' "checking for wcslcpy... "
cat > test.c <<- EOF
#include <wchar.h>
diff --git a/doc/hirc.1.header b/doc/hirc.1.header
@@ -43,9 +43,14 @@ executing any that are begin with '/' as commands.
Any line beginning with a character other than '/' are ignored.
.Ss Formats
Variables beginning with format.* are used to customize the way that messages and ui elements are formatted.
-The parser is designed to never report any errors, and simply print verbatim if it cannot understand the format.
-The following styling may be used:
-.Bl -tag -compact -width "%{c:fg[,bg]}"
+
+Previously a custom parser was used, but now one generated by
+.Xr yacc 1
+is used. This means that formats are now checked for syntax errors on /set or /format,
+although I tried to make it as lenient as possible to mimic the old parser.
+
+The following styling may be used (variables and other styles may be passed as arguments):
+.Bl -tag -compact -width "%{split:n,c,s}"
.It %{b}
Set/reset boldness.
.It %{c:fg[,bg]}
@@ -61,12 +66,6 @@ Reverse foreground/background.
Set/reset underline.
.It %{=}
Place divider here. If disabled, acts like space.
-.El
-
-The following formats behave the same as above,
-but the string 's' is re-evaluated,
-and can so contain other stylings and variables within:
-.Bl -tag -compact -width "%{split:n,c,s}"
.It %{nick:s}
Set foreground colour to the string's hashed colour.
.It %{pad:n,s}
@@ -138,6 +137,14 @@ hello world
If a variable does not exist, it will be printed verbatim.
If a variable does exist, but is empty, nothing is printed.
+
+Symbols may be escaped by placing a '\e' before them.
+This includes '$' and '%' starting variables and styling, respectively,
+as well as ':' and ',' seperating arguments to stylings.
+
+These characters do not always have to be escaped.
+For example "$a" prints "$a" as it is not followed by a brace,
+and any attempt to escape a character that does not need to be escaped will result in a backslash being printed.
.Ss CTCP
CTCP control characters are automatically stripped when using ${n} and ${n-} formats.
diff --git a/src/config.c b/src/config.c
@@ -24,6 +24,12 @@
#include <limits.h>
#include "hirc.h"
+/*
+ * Handlers.
+ * These can be attached to a config variable in order to performs actions
+ * when changing the value, or validate the new value before setting.
+ * A non-zero return value sets the variable, whilst a 0 keeps the old value.
+ */
static int config_window_hide(struct Config *conf, long num);
static int config_window_location(struct Config *conf, long num);
static int config_window_width(struct Config *conf, long num);
@@ -31,6 +37,7 @@ static int config_nickcolour_self(struct Config *conf, long num);
static int config_nickcolour_range(struct Config *conf, long a, long b);
static int config_redrawl(struct Config *conf, long num);
static int config_redraws(struct Config *conf, char *str);
+static int config_formats(struct Config *conf, char *str);
static char *strbool[] = { "true", "false", NULL };
static char *strlocation[] = {
@@ -321,6 +328,7 @@ config_window_hide(struct Config *conf, long num) {
return 1;
}
+/* prevent nicklist/buflist being drawn in same location */
static int
config_window_location(struct Config *conf, long num) {
struct Config *otherloc, *otherhide;
@@ -387,3 +395,13 @@ config_redrawl(struct Config *conf, long num) {
ui_redraw();
return 1;
}
+
+/* Don't set formats with syntax errors */
+static int
+config_formats(struct Config *conf, char *str) {
+ if (format(NULL, str, NULL)) {
+ ui_redraw();
+ return 1;
+ }
+ return 0;
+}
diff --git a/src/data/config.h b/src/data/config.h
@@ -222,1053 +222,1053 @@ struct Config config[] = {
"Turn on/off timestamps", NULL}},
{"format.ui.timestamp", 1, Val_string,
.str = "%{c:92}%{time:%H:%M:%S,${time}}%{o} ",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of timestamps",
"Only shown if timestamp.toggle is on.",
"This format is special as it is included in others.", NULL}},
{"format.ui.topic", 1, Val_string,
.str = "%{c:99,89}${topic}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of topic at top of main window", NULL}},
{"format.ui.error", 1, Val_string,
.str = "%{c:28}%{b}${4} %{b}(${3} at ${1}:${2})",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of SELF_ERROR messages", NULL}},
{"format.ui.misc", 1, Val_string,
.str = "${1}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of SELF_UI messages", NULL}},
{"format.ui.connectlost", 1, Val_string,
.str = "Connection to ${1} (${2}:${3}) lost: ${4}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of SELF_CONNECTLOST messages", NULL}},
{"format.ui.connecting", 1, Val_string,
.str = "Connecting to ${1}:${2}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of SELF_CONNECTING messages", NULL}},
{"format.ui.connected", 1, Val_string,
.str = "Connection to ${1} established",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of SELF_CONNECTED messages", NULL}},
{"format.ui.lookupfail", 1, Val_string,
.str = "Failed to lookup ${2}: ${4}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of SELF_LOOKUPFAIL messages", NULL}},
{"format.ui.connectfail", 1, Val_string,
.str = "Failed to connect to ${2}:${3}: ${4}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of SELF_CONNECTFAIL messages", NULL}},
#ifndef TLS
{"format.ui.tls.notcompiled", 1, Val_string,
.str = "TLS not compiled into hirc",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of SELF_TLSNOTCOMPILED messages", NULL}},
#else
{"format.ui.tls.version", 1, Val_string,
.str = "Protocol: %{b}${2}%{b} (%{b}${3}%{b} bits, %{b}${4}%{b})",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"TLS version and crypto information.", NULL}},
{"format.ui.tls.sni", 1, Val_string,
.str = "SNI name: %{b}${2}%{b}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"TLS server name indication.", NULL}},
{"format.ui.tls.issuer", 1, Val_string,
.str = "Cert issuer: %{b}${2}%{b}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"TLS certificate issuer.", NULL}},
{"format.ui.tls.subject", 1, Val_string,
.str = "Cert subject: %{b}${2}%{b}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"TLS certificate subject.", NULL}},
#endif /* TLS */
{"format.ui.keybind", 1, Val_string,
.str = " ${1}: ${2}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of /bind output", NULL}},
{"format.ui.keybind.start", 1, Val_string,
.str = "Keybindings:",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of header of /bind output", NULL}},
{"format.ui.keybind.end", 1, Val_string,
.str = "",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of footer of /bind output", NULL}},
{"format.ui.autocmds", 1, Val_string,
.str = " ${2}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of /server -auto output", NULL}},
{"format.ui.autocmds.start", 1, Val_string,
.str = "Autocmds for ${1}:",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of header of /server -auto output", NULL}},
{"format.ui.autocmds.end", 1, Val_string,
.str = "",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of footer of /server -auto output", NULL}},
{"format.ui.logrestore", 1, Val_string,
.str = "%{c:93}---%{=}%{c:93}Restored log up until %{b}%{time:%c,${1}}%{b} ---",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of log restore footer.", NULL}},
{"format.ui.unread", 1, Val_string,
.str = "%{c:93}---%{=}%{c:93}%{b}${1}%{b} unread (%{b}${2}%{b} ignored) ---",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of unread message indicator.", NULL}},
{"format.ui.newday", 1, Val_string,
.str = "%{c:93}---%{=}%{c:93}%{b}%{time:%A %d %B %Y,${1}}%{b} ---",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of indicator placed between messages on different days.", NULL}},
{"format.ui.ignores.start", 1, Val_string,
.str = "Ignoring:",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ignore list header.", NULL}},
{"format.ui.ignores", 1, Val_string,
.str = " %{pad:-3,${1}} (server: ${2}, noact: ${3}, format: ${4}, regex: ${5}) ${6}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ignore list messages.", NULL}},
{"format.ui.ignores.end", 1, Val_string,
.str = "",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ignore list footer.", NULL}},
{"format.ui.ignores.added", 1, Val_string,
.str = "Ignore added: ${5} (server: ${1}, noact: ${2}, format: ${3}, regex: ${4})",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of new ignores.", NULL}},
{"format.ui.grep.start", 1, Val_string,
.str = "%{b}%{c:94}Results of ${1}:",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of start of /grep output", NULL}},
{"format.ui.grep.end", 1, Val_string,
.str = "",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of end of /grep output", NULL}},
{"format.ui.alias", 1, Val_string,
.str = " ${1}: ${2}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of /alias output", NULL}},
{"format.ui.alias.start", 1, Val_string,
.str = "Aliases:",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of header of /alias output", NULL}},
{"format.ui.alias.end", 1, Val_string,
.str = "",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of footer of /alias output", NULL}},
{"format.ui.help", 1, Val_string,
.str = " ${1}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of /alias output", NULL}},
{"format.ui.help.start", 1, Val_string,
.str = "${1} help:",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of header of /alias output", NULL}},
{"format.ui.help.end", 1, Val_string,
.str = "",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of footer of /alias output", NULL}},
{"format.ui.buflist.old", 1, Val_string,
.str = "%{c:91}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Indicator for disconnected servers or parted channels", NULL}},
{"format.ui.buflist.activity.none", 1, Val_string,
.str = "",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Indicator for buffer with activity of level `none`", NULL}},
{"format.ui.buflist.activity.status", 1, Val_string,
.str = "%{c:95}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Indicator for buffer with activity of level `status`", NULL}},
{"format.ui.buflist.activity.error", 1, Val_string,
.str = "%{c:28}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Indicator for buffer with activity of level `error`", NULL}},
{"format.ui.buflist.activity.message", 1, Val_string,
.str = "%{c:45}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Indicator for buffer with activity of level `message`", NULL}},
{"format.ui.buflist.activity.hilight", 1, Val_string,
.str = "%{c:45}%{r}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Indicator for buffer with activity of level `hilight`", NULL}},
{"format.ui.buflist.more", 1, Val_string,
.str = "%{c:92}...",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Shown if there are more nicks that must be scrolled to see.", NULL}},
{"format.ui.nicklist.more", 1, Val_string,
.str = "%{c:92}...",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Shown if there are more nicks that must be scrolled to see.", NULL}},
{"format.ui.separator.vertical", 1, Val_string,
.str = "│",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Used for vertical line seperating windows", NULL}},
{"format.ui.separator.split.left", 1, Val_string,
.str = "├",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Joins left vertical separator to input seperator", NULL}},
{"format.ui.separator.split.right", 1, Val_string,
.str = "┤",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Joins right vertical separator to input seperator", NULL}},
{"format.ui.separator.horizontal", 1, Val_string,
.str = "─",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Used for horizontal line separating input and main window", NULL}},
{"format.privmsg", 1, Val_string,
.str = "%{nick:${nick}}${priv}${nick}%{o}%{=}${2}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of messages", NULL}},
{"format.action", 1, Val_string,
.str = "%{nick:${nick}}*%{b}${nick}%{b}%{=}${2}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of actions", NULL}},
{"format.ctcp.request", 1, Val_string,
.str = "%{nick:${nick}}${nick}%{o} %{c:94}%{b}q%{o}%{=}${2}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of CTCP requests", NULL}},
{"format.ctcp.answer", 1, Val_string,
.str = "%{nick:${nick}}${nick}%{o} %{c:94}%{b}a%{o}%{=}${2}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of CTCP answers", NULL}},
{"format.notice", 1, Val_string,
.str = "%{nick:${nick}}-${priv}${nick}-%{o}%{=}${2}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of notices", NULL}},
{"format.nick", 1, Val_string,
.str = "%{nick:${nick}}${nick}%{o}%{=}is now known as %{nick:${1}}${1}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of NICK messages", NULL}},
{"format.join", 1, Val_string,
.str = "%{b}%{c:44}+%{o}%{=}%{nick:${nick}}${nick}%{o} (${ident}@${host})",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of JOIN messages", NULL}},
{"format.quit", 1, Val_string,
.str = "%{b}%{c:40}<%{o}%{=}%{nick:${nick}}${nick}%{o} (${ident}@${host}): ${1}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of QUIT messages", NULL}},
{"format.part", 1, Val_string,
.str = "%{b}%{c:40}-%{o}%{=}%{nick:${nick}}${nick}%{o} (${ident}@${host}): ${2}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of PART messages", NULL}},
{"format.kick", 1, Val_string,
.str = "%{b}%{c:40}!%{o}%{=}%{nick:${2}}${2}${o} by %{nick:${nick}}${nick}%{o} (${ident}@${host}): ${3}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of PART messages", NULL}},
{"format.mode.nick.self", 1, Val_string,
.str = "${1} set %{c:94}${2-}%{o}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of modes being set on self by server/self", NULL}},
{"format.mode.nick", 1, Val_string,
.str = "${1} set %{c:94}${2-}%{o} by ${nick} (${ident}@${host})",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of modes being on nicks", NULL}},
{"format.mode.channel", 1, Val_string,
.str = "mode%{=}%{c:94}${2-}%{o} by %{nick:${nick}}${nick}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of modes being set on channels", NULL}},
{"format.topic", 1, Val_string,
.str = "topic%{=}${2}\\nset by %{nick:${nick}}${nick}%{o} now",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of topic being set", NULL}},
{"format.invite", 1, Val_string,
.str = "%{nick:${nick}}${nick}%{o} invited you to ${2}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of an invitation being received.", NULL}},
{"format.pong", 1, Val_string,
.str = "PONG from %{nick:${nick}}${nick}%{o}: ${2}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of replies to /ping", NULL}},
{"format.error", 1, Val_string,
.str = "%{c:28}ERROR:%{o} ${1}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of generic ERROR messages.",
"Most commonly seen when being /kill'd.", NULL}},
/* Generic numerics (bit boring) */
{"format.rpl.welcome", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_WELCOME (001) numeric", NULL}},
{"format.rpl.yourhost", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_YOURHOST (002) numeric", NULL}},
{"format.rpl.created", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_CREATED (003) numeric", NULL}},
{"format.rpl.myinfo", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_MYINFO (004) numeric", NULL}},
{"format.rpl.isupport", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_MYSUPPORT (005) numeric", NULL}},
{"format.rpl.map", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_MAP (006) numeric", NULL}},
{"format.rpl.mapend", 1, Val_string,
.str = "",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_MAPEND (007) numeric", NULL}},
/* START: misc/rpl-conf-gen.awk */
{"format.rpl.tracelink", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_TRACELINK (200) numeric", NULL}},
{"format.rpl.traceconnecting", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_TRACECONNECTING (201) numeric", NULL}},
{"format.rpl.tracehandshake", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_TRACEHANDSHAKE (202) numeric", NULL}},
{"format.rpl.traceunknown", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_TRACEUNKNOWN (203) numeric", NULL}},
{"format.rpl.traceoperator", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_TRACEOPERATOR (204) numeric", NULL}},
{"format.rpl.traceuser", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_TRACEUSER (205) numeric", NULL}},
{"format.rpl.traceserver", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_TRACESERVER (206) numeric", NULL}},
{"format.rpl.tracenewtype", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_TRACENEWTYPE (208) numeric", NULL}},
{"format.rpl.traceclass", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_TRACECLASS (209) numeric", NULL}},
{"format.rpl.statslinkinfo", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_STATSLINKINFO (211) numeric", NULL}},
{"format.rpl.statscommands", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_STATSCOMMANDS (212) numeric", NULL}},
{"format.rpl.statscline", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_STATSCLINE (213) numeric", NULL}},
{"format.rpl.statsnline", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_STATSNLINE (214) numeric", NULL}},
{"format.rpl.statsiline", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_STATSILINE (215) numeric", NULL}},
{"format.rpl.statskline", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_STATSKLINE (216) numeric", NULL}},
{"format.rpl.statsyline", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_STATSYLINE (218) numeric", NULL}},
{"format.rpl.endofstats", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_ENDOFSTATS (219) numeric", NULL}},
{"format.rpl.umodeis", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_UMODEIS (221) numeric", NULL}},
{"format.rpl.serviceinfo", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_SERVICEINFO (231) numeric", NULL}},
{"format.rpl.service", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_SERVICE (233) numeric", NULL}},
{"format.rpl.servlistend", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_SERVLISTEND (235) numeric", NULL}},
{"format.rpl.statslline", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_STATSLLINE (241) numeric", NULL}},
{"format.rpl.statsuptime", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_STATSUPTIME (242) numeric", NULL}},
{"format.rpl.statsoline", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_STATSOLINE (243) numeric", NULL}},
{"format.rpl.statshline", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_STATSHLINE (244) numeric", NULL}},
{"format.rpl.luserclient", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_LUSERCLIENT (251) numeric", NULL}},
{"format.rpl.luserop", 1, Val_string,
.str = "There are ${2} opers online",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_LUSEROP (252) numeric", NULL}},
{"format.rpl.luserunknown", 1, Val_string,
.str = "There are ${2} unknown connections",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_LUSERUNKNOWN (253) numeric", NULL}},
{"format.rpl.luserchannels", 1, Val_string,
.str = "There are ${2} channels formed",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_LUSERCHANNELS (254) numeric", NULL}},
{"format.rpl.luserme", 1, Val_string,
.str = "There are %{split:3, ,${2}} clients and %{split:6, ,${2}} servers connected to this server",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_LUSERME (255) numeric", NULL}},
{"format.rpl.adminme", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_ADMINME (256) numeric", NULL}},
{"format.rpl.adminloc1", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_ADMINLOC1 (257) numeric", NULL}},
{"format.rpl.adminloc2", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_ADMINLOC2 (258) numeric", NULL}},
{"format.rpl.adminemail", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_ADMINEMAIL (259) numeric", NULL}},
{"format.rpl.tracelog", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_TRACELOG (261) numeric", NULL}},
{"format.rpl.none", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_NONE (300) numeric", NULL}},
{"format.rpl.away", 1, Val_string,
.str = "away%{=}%{nick:${2}}${2}%{o}: ${3}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_AWAY (301) numeric", NULL}},
{"format.rpl.userhost", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_USERHOST (302) numeric", NULL}},
{"format.rpl.ison", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_ISON (303) numeric", NULL}},
{"format.rpl.unaway", 1, Val_string,
.str = "%{c:40}<--%{o}%{=}No longer %{b}away%{b}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_UNAWAY (305) numeric", NULL}},
{"format.rpl.nowaway", 1, Val_string,
.str = "%{c:32}-->%{o}%{=}Set %{b}away%{b}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_NOWAWAY (306) numeric", NULL}},
{"format.rpl.whoisuser", 1, Val_string,
.str = "%{b}${2}!${3}@${4}%{b} (${6}):",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_WHOISUSER (311) numeric", NULL}},
{"format.rpl.whoisserver", 1, Val_string,
.str = " %{b}server %{b}: ${3} (${4})",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_WHOISSERVER (312) numeric", NULL}},
{"format.rpl.whoisoperator", 1, Val_string,
.str = " %{b}oper %{b}: ${3}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_WHOISOPERATOR (313) numeric", NULL}},
{"format.rpl.whowasuser", 1, Val_string,
.str = "%{b}${2}!${3}@${4}%{b} (${6}) was on:",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_WHOWASUSER (314) numeric", NULL}},
{"format.rpl.endofwho", 1, Val_string,
.str = "End of WHO results for ${2}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_ENDOFWHO (315) numeric", NULL}},
{"format.rpl.whoisidle", 1, Val_string,
.str = " %{b}signon %{b}: %{time:%c,${4}}, idle: %{rdate:${3}}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_WHOISIDLE (317) numeric", NULL}},
{"format.rpl.endofwhois", 1, Val_string,
.str = "",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_ENDOFWHOIS (318) numeric", NULL}},
{"format.rpl.whoischannels", 1, Val_string,
.str = " %{b}channels%{b}: ${3}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_WHOISCHANNELS (319) numeric", NULL}},
{"format.rpl.liststart", 1, Val_string,
.str = "%{pad:-15,Channel} %{pad:-5,Nicks} Topic",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_LISTSTART (321) numeric", NULL}},
{"format.rpl.list", 1, Val_string,
.str = "%{pad:-15,${2}} %{pad:-5,${3}} ${4}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_LIST (322) numeric", NULL}},
{"format.rpl.listend", 1, Val_string,
.str = "",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_LISTEND (323) numeric", NULL}},
{"format.rpl.channelmodeis", 1, Val_string,
.str = "mode%{=}%{c:94}${3-}%{o}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_CHANNELMODEIS (324) numeric", NULL}},
{"format.rpl.notopic", 1, Val_string,
.str = "topic%{=}no topic set",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_NOTOPIC (331) numeric", NULL}},
{"format.rpl.topic", 1, Val_string,
.str = "topic%{=}${3}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_TOPIC (332) numeric", NULL}},
{"format.rpl.inviting", 1, Val_string,
.str = "invite%{=}${2}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_INVITING (341) numeric", NULL}},
{"format.rpl.summoning", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_SUMMONING (342) numeric", NULL}},
{"format.rpl.version", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_VERSION (351) numeric", NULL}},
{"format.rpl.whoreply", 1, Val_string,
.str = "%{b}${6}!${3}@${4}%{b} (%{split:2, ,${8}}): ${7} %{split:1, ,${8}}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_WHOREPLY (352) numeric", NULL}},
{"format.rpl.namreply", 1, Val_string,
.str = "names%{=}${4-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_NAMREPLY (353) numeric", NULL}},
{"format.rpl.closing", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_CLOSING (362) numeric", NULL}},
{"format.rpl.links", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_LINKS (364) numeric", NULL}},
{"format.rpl.endoflinks", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_ENDOFLINKS (365) numeric", NULL}},
{"format.rpl.endofnames", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_ENDOFNAMES (366) numeric", NULL}},
{"format.rpl.banlist", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_BANLIST (367) numeric", NULL}},
{"format.rpl.endofbanlist", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_ENDOFBANLIST (368) numeric", NULL}},
{"format.rpl.endofwhowas", 1, Val_string,
.str = "",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_ENDOFWHOWAS (369) numeric", NULL}},
{"format.rpl.info", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_INFO (371) numeric", NULL}},
{"format.rpl.motd", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_MOTD (372) numeric", NULL}},
{"format.rpl.infostart", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_INFOSTART (373) numeric", NULL}},
{"format.rpl.endofinfo", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_ENDOFINFO (374) numeric", NULL}},
{"format.rpl.motdstart", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_MOTDSTART (375) numeric", NULL}},
{"format.rpl.endofmotd", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_ENDOFMOTD (376) numeric", NULL}},
{"format.rpl.youreoper", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_YOUREOPER (381) numeric", NULL}},
{"format.rpl.rehashing", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_REHASHING (382) numeric", NULL}},
{"format.rpl.time", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_TIME (391) numeric", NULL}},
{"format.rpl.usersstart", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_USERSSTART (392) numeric", NULL}},
{"format.rpl.users", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_USERS (393) numeric", NULL}},
{"format.rpl.endofusers", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_ENDOFUSERS (394) numeric", NULL}},
{"format.rpl.nousers", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_NOUSERS (395) numeric", NULL}},
{"format.err.nosuchnick", 1, Val_string,
.str = "No such nick: ${2}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_NOSUCHNICK (401) numeric", NULL}},
{"format.err.nosuchserver", 1, Val_string,
.str = "No such server: ${2}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_NOSUCHSERVER (402) numeric", NULL}},
{"format.err.nosuchchannel", 1, Val_string,
.str = "No such channel: ${2}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_NOSUCHCHANNEL (403) numeric", NULL}},
{"format.err.cannotsendtochan", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_CANNOTSENDTOCHAN (404) numeric", NULL}},
{"format.err.toomanychannels", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_TOOMANYCHANNELS (405) numeric", NULL}},
{"format.err.wasnosuchnick", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_WASNOSUCHNICK (406) numeric", NULL}},
{"format.err.toomanytargets", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_TOOMANYTARGETS (407) numeric", NULL}},
{"format.err.noorigin", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_NOORIGIN (409) numeric", NULL}},
{"format.err.norecipient", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_NORECIPIENT (411) numeric", NULL}},
{"format.err.notexttosend", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_NOTEXTTOSEND (412) numeric", NULL}},
{"format.err.notoplevel", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_NOTOPLEVEL (413) numeric", NULL}},
{"format.err.wildtoplevel", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_WILDTOPLEVEL (414) numeric", NULL}},
{"format.err.unknowncommand", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_UNKNOWNCOMMAND (421) numeric", NULL}},
{"format.err.nomotd", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_NOMOTD (422) numeric", NULL}},
{"format.err.noadmininfo", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_NOADMININFO (423) numeric", NULL}},
{"format.err.fileerror", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_FILEERROR (424) numeric", NULL}},
{"format.err.nonicknamegiven", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_NONICKNAMEGIVEN (431) numeric", NULL}},
{"format.err.erroneusnickname", 1, Val_string,
.str = "Erroneous nickname: ${2}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_ERRONEUSNICKNAME (432) numeric", NULL}},
{"format.err.nicknameinuse", 1, Val_string,
.str = "Nickname already in use: ${2}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_NICKNAMEINUSE (433) numeric", NULL}},
{"format.err.nickcollision", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_NICKCOLLISION (436) numeric", NULL}},
{"format.err.usernotinchannel", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_USERNOTINCHANNEL (441) numeric", NULL}},
{"format.err.notonchannel", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_NOTONCHANNEL (442) numeric", NULL}},
{"format.err.useronchannel", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_USERONCHANNEL (443) numeric", NULL}},
{"format.err.nologin", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_NOLOGIN (444) numeric", NULL}},
{"format.err.summondisabled", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_SUMMONDISABLED (445) numeric", NULL}},
{"format.err.usersdisabled", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_USERSDISABLED (446) numeric", NULL}},
{"format.err.notregistered", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_NOTREGISTERED (451) numeric", NULL}},
{"format.err.needmoreparams", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_NEEDMOREPARAMS (461) numeric", NULL}},
{"format.err.alreadyregistred", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_ALREADYREGISTRED (462) numeric", NULL}},
{"format.err.nopermforhost", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_NOPERMFORHOST (463) numeric", NULL}},
{"format.err.passwdmismatch", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_PASSWDMISMATCH (464) numeric", NULL}},
{"format.err.yourebannedcreep", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_YOUREBANNEDCREEP (465) numeric", NULL}},
{"format.err.youwillbebanned", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_YOUWILLBEBANNED (466) numeric", NULL}},
{"format.err.keyset", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_KEYSET (467) numeric", NULL}},
{"format.err.channelisfull", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_CHANNELISFULL (471) numeric", NULL}},
{"format.err.unknownmode", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_UNKNOWNMODE (472) numeric", NULL}},
{"format.err.inviteonlychan", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_INVITEONLYCHAN (473) numeric", NULL}},
{"format.err.bannedfromchan", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_BANNEDFROMCHAN (474) numeric", NULL}},
{"format.err.badchannelkey", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_BADCHANNELKEY (475) numeric", NULL}},
{"format.err.noprivileges", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_NOPRIVILEGES (481) numeric", NULL}},
{"format.err.chanoprivsneeded", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_CHANOPRIVSNEEDED (482) numeric", NULL}},
{"format.err.cantkillserver", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_CANTKILLSERVER (483) numeric", NULL}},
{"format.err.nooperhost", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_NOOPERHOST (491) numeric", NULL}},
{"format.err.noservicehost", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_NOSERVICEHOST (492) numeric", NULL}},
{"format.err.umodeunknownflag", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_UMODEUNKNOWNFLAG (501) numeric", NULL}},
{"format.err.usersdontmatch", 1, Val_string,
.str = "${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of ERR_USERSDONTMATCH (502) numeric", NULL}},
/* END: misc/rpl-conf-gen.awk */
/* Modern numerics */
{"format.rpl.localusers", 1, Val_string,
.str = "There are ${2} current local users, record of ${3}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPLS_LOCALUSERS (265) numeric", NULL}},
{"format.rpl.globalusers", 1, Val_string,
.str = "There are ${2} current global users, record of ${3}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_GLOBALUSERS (266) numeric", NULL}},
{"format.rpl.whoisspecial", 1, Val_string,
.str = " %{b}info %{b}: ${3}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_WHOISSPECIAL (320) numeric", NULL}},
{"format.rpl.whoisaccount", 1, Val_string,
.str = " %{b}account %{b}: ${3}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_WHOISACCOUNT (330) numeric", NULL}},
{"format.rpl.topicwhotime", 1, Val_string,
.str = "set by %{nick:${3}}${3}%{o} at %{time:%Y-%m-%d %H:%M:%S,${4}}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_TOPICWHOTIME (333) numeric", NULL}},
{"format.rpl.whoisactually", 1, Val_string,
.str = " %{b}actually%{b}: ${3-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_WHOISACTUALLY (338) numeric", NULL}},
{"format.rpl.whoishost", 1, Val_string,
.str = " %{b}info %{b}: ${3}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_WHOISHOST (378) numeric", NULL}},
{"format.rpl.whoismodes", 1, Val_string,
.str = " %{b}modes %{b}: ${3}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_WHOISMODES (379) numeric", NULL}},
{"format.rpl.whoissecure", 1, Val_string,
.str = " %{b}secure %{b}: ${3}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of RPL_WHOISSECURE (671) numeric", NULL}},
/* Default formats */
{"format.rpl.other", 1, Val_string,
.str = "${cmd} ${2-}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of numerics without formats", NULL}},
{"format.other", 1, Val_string,
.str = "${raw}",
- .strhandle = config_redraws,
+ .strhandle = config_formats,
.description = {
"Format of other messages without formats", NULL}},
{NULL},
diff --git a/src/format.c b/src/format.c
@@ -1,553 +0,0 @@
-/*
- * src/format.c from hirc
- *
- * Copyright (c) 2021-2022 hhvn <dev@hhvn.uk>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include "hirc.h"
-#include "data/formats.h"
-
-char *
-format_get_bufact(int activity) {
- switch (activity) {
- case Activity_status:
- return format(NULL, config_gets("format.ui.buflist.activity.status"), NULL);
- case Activity_error:
- return format(NULL, config_gets("format.ui.buflist.activity.error"), NULL);
- case Activity_message:
- return format(NULL, config_gets("format.ui.buflist.activity.message"), NULL);
- case Activity_hilight:
- return format(NULL, config_gets("format.ui.buflist.activity.hilight"), NULL);
- default:
- return format(NULL, config_gets("format.ui.buflist.activity.none"), NULL);
- }
-
- return NULL; /* shouldn't be possible *shrug*/
-}
-
-char *
-format_get(struct History *hist) {
- char *cmd, *p1, *p2;
- int i;
-
- assert_warn(hist, NULL);
-
- if (!hist->params)
- goto raw;
-
- cmd = *(hist->params);
- p1 = *(hist->params+1);
- p2 = *(hist->params+2);
-
- if (strcmp_n(cmd, "MODE") == 0) {
- if (p1 && serv_ischannel(hist->origin->server, p1))
- cmd = "MODE-CHANNEL";
- else if (hist->from && nick_isself(hist->from) && strcmp_n(hist->from->nick, p1) == 0)
- cmd = "MODE-NICK-SELF";
- else
- cmd = "MODE-NICK";
- } else if (strcmp_n(cmd, "PRIVMSG") == 0) {
- /* ascii 1 is ^A */
- if (*p2 == 1 && strncmp(p2 + 1, "ACTION", CONSTLEN("ACTION")) == 0)
- cmd = "PRIVMSG-ACTION";
- else if (*p2 == 1)
- cmd = "PRIVMSG-CTCP";
- } else if (strcmp_n(cmd, "NOTICE") == 0 && *p2 == 1) {
- cmd = "NOTICE-CTCP";
- }
-
- for (i=0; formatmap[i].cmd; i++)
- if (formatmap[i].format && strcmp_n(formatmap[i].cmd, cmd) == 0)
- return formatmap[i].format;
-
- if (isdigit(*cmd) && isdigit(*(cmd+1)) && isdigit(*(cmd+2)) && !*(cmd+3))
- return "format.rpl.other";
-
-raw:
- return "format.other";
-}
-
-static char *
-format_get_content(char *sstr, int nesting) {
- static char ret[8192];
- int layer, rc;
-
- for (layer = 0, rc = 0; sstr && *sstr && rc < sizeof(ret); sstr++) {
- switch (*sstr) {
- case '}':
- if (nesting && layer) {
- ret[rc++] = '}';
- layer--;
- } else {
- goto end;
- }
- break;
- case '{':
- if (nesting)
- layer++;
- ret[rc++] = '{';
- break;
- default:
- ret[rc++] = *sstr;
- break;
- }
- }
-
-end:
- ret[rc] = '\0';
- return ret;
-}
-
-char *
-format_(struct Window *window, char *format, struct History *hist, int recursive) {
- static char *ret;
- struct Nick *nick;
- size_t rs = BUFSIZ;
- size_t rc, pc;
- int escape, i;
- long long pn;
- int rhs = 0;
- int divider = 0;
- char **params;
- char *content, *p, *p2;
- char *ts, *save;
- char colourbuf[2][3];
- char priv[2];
- char chs[2];
- size_t len;
- enum {
- sub_raw,
- sub_cmd,
- sub_nick,
- sub_ident,
- sub_host,
- sub_priv,
- sub_channel,
- sub_topic,
- sub_server,
- sub_time,
- };
- struct {
- char *name;
- char *val;
- } subs[] = {
- [sub_raw] = {"raw", NULL},
- [sub_cmd] = {"cmd", NULL},
- [sub_nick] = {"nick", NULL},
- [sub_ident] = {"ident", NULL},
- [sub_host] = {"host", NULL},
- [sub_priv] = {"priv", NULL},
- [sub_channel] = {"channel", NULL},
- [sub_topic] = {"topic", NULL},
- [sub_server] = {"server", NULL},
- [sub_time] = {"time", NULL},
- {NULL, NULL},
- };
-
- if (!format)
- format = config_gets(format_get(hist));
- assert_warn(format, NULL);
-
- pfree(&ret);
- ret = emalloc(rs);
-
- subs[sub_channel].val = selected.channel ? selected.channel->name : NULL;
- subs[sub_topic].val = selected.channel ? selected.channel->topic : NULL;
- subs[sub_server].val = selected.server ? selected.server->name : NULL;
-
- if (hist) {
- subs[sub_raw].val = hist->raw;
- subs[sub_nick].val = hist->from ? hist->from->nick : NULL;
- subs[sub_ident].val = hist->from ? hist->from->ident : NULL;
- subs[sub_host].val = hist->from ? hist->from->host : NULL;
-
- if (hist->from) {
- priv[0] = hist->from->priv;
- priv[priv[0] != ' '] = '\0';
- subs[sub_priv].val = priv;
- }
-
- if (hist->origin) {
- if (hist->origin->channel) {
- if (!recursive)
- divider = config_getl("divider.toggle");
- subs[sub_channel].val = hist->origin->channel->name;
- subs[sub_topic].val = hist->origin->channel->topic;
- }
- if (hist->origin->server) {
- subs[sub_server].val = hist->origin->server->name;
- }
- }
-
- len = snprintf(subs[sub_time].val, 0, "%lld", (long long)hist->timestamp) + 1;
- subs[sub_time].val = emalloc(len);
- snprintf(subs[sub_time].val, len, "%lld", (long long)hist->timestamp);
-
- params = hist->params;
- subs[sub_cmd].val = *params;
- params++;
- }
-
- if (!recursive && hist && config_getl("timestamp.toggle")) {
- ts = estrdup(format_(NULL, config_gets("format.ui.timestamp"), hist, 1));
- } else {
- ts = "";
- }
-
- for (escape = 0, rc = 0; format && *format && rc < rs; ) {
-outcont:
- if (rc > rs / 2) {
- rs *= 2;
- ret = erealloc(ret, rs);
- }
-
- if (!escape && *format == '$' && *(format+1) == '{' && strchr(format, '}')) {
- escape = 0;
- content = format_get_content(format+2, 0);
-
- for (p = content; *p && isdigit(*p); p++);
- /* If all are digits, *p == '\0' */
- if (!*p && hist) {
- pn = strtol(content, NULL, 10) - 1;
- if (pn >= 0 && param_len(params) > pn) {
- if (**(params+pn) == 1 && strncmp((*(params+pn))+1, "ACTION", CONSTLEN("ACTION")) == 0 && strchr(*(params+pn), ' '))
- rc += snprintf(&ret[rc], rs - rc, "%s", struntil(strchr(*(params+pn), ' ') + 1, 1));
- else if (**(params+pn) == 1)
- rc += snprintf(&ret[rc], rs - rc, "%s", struntil((*(params+pn)) + 1, 1));
- else
- rc += snprintf(&ret[rc], rs - rc, "%s", *(params+pn));
- format = strchr(format, '}') + 1;
- continue;
- }
- }
- /* All are digits except a trailing '-' */
- if (*p == '-' && *(p+1) == '\0' && hist) {
- pn = strtol(content, NULL, 10) - 1;
- if (pn >= 0 && param_len(params) > pn) {
- for (; *(params+pn) != NULL; pn++) {
- if (**(params+pn) == 1 && strncmp((*(params+pn))+1, "ACTION", CONSTLEN("ACTION")) == 0 && strchr(*(params+pn), ' ')) {
- rc += snprintf(&ret[rc], rs - rc, "%s%s",
- struntil(strchr(*(params+pn), ' ') + 1, 1),
- *(params+pn+1) ? " " : "");
- } else if (**(params+pn) == 1) {
- rc += snprintf(&ret[rc], rs - rc, "%s%s",
- struntil((*(params+pn)) + 1, 1),
- *(params+pn+1) ? " " : "");
- } else {
- rc += snprintf(&ret[rc], rs - rc, "%s%s",
- *(params+pn), *(params+pn+1) ? " " : "");
- }
- }
- format = strchr(format, '}') + 1;
- continue;
- }
- }
-
- for (i=0; subs[i].name; i++) {
- if (strcmp_n(subs[i].name, content) == 0) {
- if (subs[i].val)
- rc += snprintf(&ret[rc], rs - rc, "%s", subs[i].val);
- format = strchr(format, '}') + 1;
- goto outcont; /* unfortunately, need to use a goto as we are already in a loop */
- }
- }
- }
-
- if (!escape && *format == '%' && *(format+1) == '{' && strchr(format, '}')) {
- escape = 0;
- content = format_get_content(format+2, 0);
-
- switch (*content) {
- case 'b':
- case 'B':
- ret[rc++] = 2; /* ^B */
- format = strchr(format, '}') + 1;
- continue;
- case 'c':
- case 'C':
- if (*(content+1) == ':' && isdigit(*(content+2))) {
- content += 2;
- memset(colourbuf, 0, sizeof(colourbuf));
- colourbuf[0][0] = *content;
- content++;
- if (isdigit(*content)) {
- colourbuf[0][1] = *content;
- content += 1;
- }
- if (*content == ',' && isdigit(*(content+1))) {
- colourbuf[1][0] = *(content+1);
- content += 2;
- }
- if (colourbuf[1][0] && isdigit(*content)) {
- colourbuf[1][1] = *(content);
- content += 1;
- }
- if (*content == '\0') {
- rc += snprintf(&ret[rc], rs - rc, "%c%02d,%02d", 3 /* ^C */,
- atoi(colourbuf[0]), colourbuf[1][0] ? atoi(colourbuf[1]) : 99);
- format = strchr(format, '}') + 1;
- continue;
- }
- }
- break;
- case 'i':
- case 'I':
- if (*(content+1) == '\0') {
- ret[rc++] = 9; /* ^I */
- format = strchr(format, '}') + 1;
- continue;
- }
- break;
- case 'o':
- case 'O':
- if (*(content+1) == '\0') {
- ret[rc++] = 15; /* ^O */
- format = strchr(format, '}') + 1;
- continue;
- }
- break;
- case 'r':
- case 'R':
- if (*(content+1) == '\0') {
- ret[rc++] = 18; /* ^R */
- format = strchr(format, '}') + 1;
- continue;
- }
- break;
- case 'u':
- case 'U':
- if (*(content+1) == '\0') {
- ret[rc++] = 21; /* ^U */
- format = strchr(format, '}') + 1;
- continue;
- }
- break;
- case '=':
- if (*(content+1) == '\0' && divider) {
- rhs = 1;
- ret[rc] = '\0';
- /* strlen(ret) - ui_strlenc(window, ret, NULL) should get
- * the length of hidden characters. Add this onto the
- * margin to pad out properly. */
- /* Save ret for use in snprintf */
- save = estrdup(ret);
- rc = snprintf(ret, rs, "%1$*3$s%2$s", save, config_gets("divider.string"),
- (int)(config_getl("divider.margin") + (strlen(ret) - ui_strlenc(window, ret, NULL))));
- pfree(&save);
- format = strchr(format, '}') + 1;
- continue;
- } else if (*(content+1) == '\0') {
- ret[rc++] = ' ';
- format = strchr(format, '}') + 1;
- continue;
- }
- break;
- }
-
- /* pad, nick, split, rdate and time, must then continue as they modify content
- *
- * These styling formatters are quite ugly and repetitive.
- * %{nick:...} was implemented first, and has the most (all of them :)) comments */
- if (strncmp(content, "pad:", CONSTLEN("pad:")) == 0 && strchr(content, ',')) {
- pn = strtol(content + CONSTLEN("pad:"), NULL, 10);
- content = estrdup(format_get_content(strchr(format+2+CONSTLEN("pad:"), ',') + 1, 1));
- save = ret;
- ret = NULL;
- format_(NULL, content, hist, 1);
- rc += snprintf(&save[rc], rs - rc, "%1$*2$s", ret, (int)pn);
- pfree(&ret);
- ret = save;
- format = strchr(format+2+CONSTLEN("pad:"), ',') + strlen(content) + 2;
-
- pfree(&content);
- continue;
- }
-
- if (strncmp(content, "rdate:", CONSTLEN("rdate:")) == 0) {
- content = estrdup(format_get_content(format+2+CONSTLEN("rdate:"), 1));
- save = ret;
- ret = NULL;
- format_(NULL, content, hist, 1);
- pn = strtoll(ret, NULL, 10);
- rc += snprintf(&save[rc], rs - rc, "%s", strrdate((time_t)pn));
- format += 3 + CONSTLEN("rdate:") + strlen(content);
-
- pfree(&ret);
- ret = save;
- pfree(&content);
- continue;
- }
-
- if (strncmp(content, "time:", CONSTLEN("time:")) == 0 && strchr(content, ',')) {
- content = estrdup(format_get_content(strchr(format+2+CONSTLEN("time:"), ',') + 1, 1));
- save = ret;
- ret = NULL;
- format_(NULL, content, hist, 1);
- pn = strtoll(ret, NULL, 10);
- p = struntil(format+2+CONSTLEN("time:"), ',');
-
- rc += strftime(&save[rc], rs - rc, p, localtime((time_t *)&pn));
- format = strchr(format+2+CONSTLEN("time:"), ',') + strlen(content) + 2;
-
- pfree(&ret);
- ret = save;
- pfree(&content);
- continue;
- }
-
- /* second comma ptr - second comma ptr = distance.
- * If the distance is 2, then there is one non-comma char between. */
- p = strchr(content, ',');
- if (p)
- p2 = strchr(p + 1, ',');
- if (strncmp(content, "split:", CONSTLEN("split:")) == 0 && p2 - p == 2) {
- pn = strtol(content + CONSTLEN("split:"), NULL, 10);
- chs[0] = *(strchr(content, ',') + 1);
- chs[1] = '\0';
- content = estrdup(format_get_content(
- strchr(
- strchr(format+2+CONSTLEN("split:"), ',') + 1,
- ',') + 1,
- 1));
- save = ret;
- ret = NULL;
- format_(NULL, content, hist, 1);
- rc += snprintf(&save[rc], rs - rc, "%s", strntok(ret, chs, pn));
- format = strchr(
- strchr(format+2+CONSTLEN("split:"), ',') + 1,
- ',') + strlen(content) + 2;
-
- pfree(&ret);
- ret = save;
- pfree(&content);
- continue;
- }
-
- if (hist && !recursive && strncmp(content, "nick:", CONSTLEN("nick:")) == 0) {
- content = estrdup(format_get_content(format+2+CONSTLEN("nick:"), 1));
- save = ret;
- ret = NULL;
- format_(NULL, content, hist, 1);
- nick = nick_create(ret, ' ', hist->origin ? hist->origin->server : NULL);
- rc += snprintf(&save[rc], rs - rc, "%c%02d", 3 /* ^C */, nick_getcolour(nick));
- format += 3 + CONSTLEN("nick:") + strlen(content);
-
- pfree(&ret);
- ret = save;
- nick_free(nick);
- pfree(&content);
- continue;
- }
- }
-
- if (escape && *format == 'n') {
- ret[rc++] = '\n';
- rc += snprintf(&ret[rc], rs - rc, "%1$*3$s%2$s", "", config_gets("divider.string"),
- (int)(ui_strlenc(NULL, ts, NULL) + config_getl("divider.margin")));
- escape = 0;
- format++;
- continue;
- }
-
- if (escape && (*format == '%' || *format == '$') && *(format+1) == '{' && strchr(format, '}'))
- escape = 0;
-
- if (escape) {
- ret[rc++] = '\\';
- escape = 0;
- }
-
- if (*format == '\\') {
- escape = 1;
- format++;
- } else {
- ret[rc++] = *format;
- format++;
- }
- }
-
- ret[rc] = '\0';
- if (!recursive && divider && !rhs) {
- save = estrdup(ret);
- rc = snprintf(ret, rs, "%1$*4$s%2$s%3$s", "", config_gets("divider.string"), save, (int)config_getl("divider.margin"));
- pfree(&save);
- }
-
- save = estrdup(ret);
- rc = snprintf(ret, rs, "%s%s", ts, save);
- pfree(&save);
-
- if (!recursive && window) {
- for (p = ret, pc = 0; p && p <= (ret + rs); p++) {
- /* lifted from ui_strlenc */
- switch (*p) {
- case 2: /* ^B */
- case 9: /* ^I */
- case 15: /* ^O */
- case 18: /* ^R */
- case 21: /* ^U */
- break;
- case 3: /* ^C */
- if (*p && isdigit(*(p+1)))
- p += 1;
- if (*p && isdigit(*(p+1)))
- p += 1;
- if (*p && *(p+1) == ',' && isdigit(*(p+2)))
- p += 2;
- if (*p && *(p-1) == ',' && isdigit(*(p+1)))
- p += 1;
- break;
- default:
- /* naive utf-8 handling:
- * the 2-nth byte always
- * follows 10xxxxxxx, so
- * don't count it. */
- if ((*p & 0xC0) != 0x80)
- pc++;
-
- if (*p == '\n') {
- p++;
- pc = 0;
- }
-
- if (pc == window->w) {
- save = estrdup(p);
-
- if (divider) {
- p += snprintf(p, rs - ((size_t)(p - ret)), "%1$*4$s %2$s%3$s",
- "", config_gets("divider.string"), save,
- (int)config_getl("divider.margin") + ui_strlenc(NULL, ts, NULL));
- } else {
- p += snprintf(p, rs - ((size_t)(p - ret)), "%1$*3$s %2$s", "", save, ui_strlenc(NULL, ts, NULL));
- }
-
- pfree(&save);
- pc = 0;
- }
- }
- }
- }
-
- if (subs[sub_time].val)
- pfree(&subs[sub_time].val);
- if (ts[0] != '\0')
- pfree(&ts);
-
- return ret;
-}
diff --git a/src/format.y b/src/format.y
@@ -0,0 +1,540 @@
+%{
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include "hirc.h"
+#include "data/formats.h"
+
+#define YYSTYPE char *
+
+static void parse_append(char **dest, char *str);
+static char *parse_dup(char *str);
+static char *parse_printf(char *fmt, ...);
+static void yyerror(char *fmt, ...);
+static int yylex(void);
+
+#define BRACEMAX 16
+#define RETURN(s) do {if (s == STRING) fprintf(stderr, "[lex \"%s\"]\n", yylval); else fprintf(stderr, "[lex %s]\n", #s); prev = s; return s;} while (0)
+#define ISSPECIAL(s) isspecial(s, prev, bracelvl, bracetype, styleseg)
+
+enum {
+ PARSE_TIME,
+ PARSE_LEFT,
+ PARSE_RIGHT,
+ PARSE_LAST
+};
+
+static char *parse_in = NULL;
+static char *parse_out[PARSE_LAST] = {NULL, NULL, NULL};
+static int parse_pos = PARSE_LEFT;
+static char **parse_params = NULL;
+
+enum {
+ var_raw,
+ var_cmd,
+ var_nick,
+ var_ident,
+ var_host,
+ var_priv,
+ var_channel,
+ var_topic,
+ var_server,
+ var_time,
+};
+static struct {
+ char *name;
+ char *val;
+} vars[] = {
+ [var_raw] = {"raw", NULL},
+ [var_cmd] = {"cmd", NULL},
+ [var_nick] = {"nick", NULL},
+ [var_ident] = {"ident", NULL},
+ [var_host] = {"host", NULL},
+ [var_priv] = {"priv", NULL},
+ [var_channel] = {"channel", NULL},
+ [var_topic] = {"topic", NULL},
+ [var_server] = {"server", NULL},
+ [var_time] = {"time", NULL},
+ {NULL, NULL},
+};
+%}
+
+%token VAR STYLE LBRACE RBRACE COLON COMMA
+%token STRING
+
+%%
+
+grammar: /* empty */ { parse_append(&parse_out[parse_pos], ""); }
+ | grammar var { parse_append(&parse_out[parse_pos], $2); }
+ | grammar style { parse_append(&parse_out[parse_pos], $2); }
+ | grammar STRING { parse_append(&parse_out[parse_pos], $2); }
+ ;
+
+var: VAR LBRACE STRING RBRACE {
+ char buf[8192];
+ int i, num;
+ if (strisnum($3, 0) && (num = strtoll($3, NULL, 10)) && param_len(parse_params) >= num) {
+ $$ = *(parse_params + num - 1);
+ goto varfin;
+ }
+ fprintf(stderr, "{var: %s}\n", $3);
+ if (*$3 && *($3 + strlen($3) - 1) == '-') {
+ *($3 + strlen($3) - 1) = '\0';
+ fprintf(stderr, "{var without -: %s}\n", $3);
+ if (strisnum($3, 0) && (num = strtoll($3, NULL, 10)) && param_len(parse_params) >= num) {
+ buf[0] = '\0';
+ for (i = num; i <= param_len(parse_params); i++) {
+ strlcat(buf, *(parse_params + i - 1), sizeof(buf));
+ strlcat(buf, " ", sizeof(buf));
+ }
+ $$ = parse_dup(buf);
+ goto varfin;
+ } else {
+ *($3 + strlen($3) - 1) = '\0';
+ }
+ }
+ for (i = 0; vars[i].name; i++) {
+ if (vars[i].val && strcmp(vars[i].name, $3) == 0) {
+ $$ = parse_printf("%s", vars[i].val);
+ goto varfin;
+ }
+ }
+ $$ = parse_printf("${%s}", $3);
+varfin:
+ ((void)0);
+ }
+ ;
+
+style: STYLE LBRACE STRING RBRACE {
+ if (strcmp($3, "b") == 0) {
+ $$ = parse_printf("%c", 2 /* ^B */);
+ } else if (strcmp($3, "c") == 0) {
+ $$ = parse_printf("%c99,99", 3 /* ^C */);
+ } else if (strcmp($3, "i") == 0) {
+ $$ = parse_printf("%c", 9 /* ^I */);
+ } else if (strcmp($3, "o") == 0) {
+ $$ = parse_printf("%c", 15 /* ^O */);
+ } else if (strcmp($3, "r") == 0) {
+ $$ = parse_printf("%c", 18 /* ^R */);
+ } else if (strcmp($3, "u") == 0) {
+ $$ = parse_printf("%c", 21 /* ^U */);
+ } else if (strcmp($3, "=") == 0) {
+ if (parse_pos == PARSE_LEFT) {
+ parse_pos = PARSE_RIGHT;
+ $$ = parse_dup("");
+ } else {
+ $$ = parse_dup(" ");
+ }
+ } else if (strcmp($3, "_time") == 0) { /* special style to mark end of timestamp */
+ if (parse_pos == PARSE_TIME) {
+ parse_pos = PARSE_LEFT; /* let's hope no-one puts it in format.ui.timestamp */
+ $$ = parse_dup("");
+ } else {
+ $$ = parse_dup("%{_time}"); /* in the unlikely event some uses it somewhere else.. */
+ }
+ } else {
+ $$ = parse_printf("%%{%s}", $3);
+ }
+ }
+ | STYLE LBRACE STRING COLON sstring RBRACE {
+ struct Nick *nick;
+ if (strcmp($3, "c") == 0) {
+ if (strlen($5) <= 2 && isdigit(*$5) && (!*($5+1) || isdigit(*($5+1))))
+ $$ = parse_printf("%c%02d", 3 /* ^C */, atoi($5));
+ } else if (strcmp($3, "nick") == 0) {
+ nick = nick_create($5, ' ', NULL);
+ $$ = parse_printf("%c%02d", 3 /* ^C */, nick_getcolour(nick));
+ nick_free(nick);
+ } else if (strcmp($3, "rdate") == 0) {
+ if (strisnum($5, 0))
+ $$ = parse_printf("%s", strrdate((time_t)strtoll($5, NULL, 10)));
+ else
+ $$ = parse_printf("%%{%s:%s}", $3, $5);
+ } else {
+ $$ = parse_printf("%%{%s:%s}", $3, $5);
+ }
+ }
+ | STYLE LBRACE STRING COLON sstring COMMA sstring RBRACE {
+ char stime[1024];
+ time_t dtime;
+ if (strcmp($3, "c") == 0) {
+ if (strlen($5) <= 2 && isdigit(*$5) && (!*($5+1) || isdigit(*($5+1))) &&
+ strlen($7) <= 2 && isdigit(*$7) && (!*($7+1) || isdigit(*($5+1))))
+ $$ = parse_printf("%c%02d,%02d", 3 /* ^C */, atoi($5), atoi($7));
+ else
+ $$ = parse_printf("%%{%s:%s,%s}", $3, $5, $7);
+ } else if (strcmp($3, "pad") == 0) {
+ if (strisnum($5, 1))
+ $$ = parse_printf("%1$*2$s", $7, (int)strtoll($5, NULL, 0));
+ else
+ $$ = parse_printf("%%{%s:%s,%s}", $3, $5, $7);
+ } else if (strcmp($3, "time") == 0) {
+ if (strisnum($7, 0)) {
+ dtime = (time_t)strtoll($7, NULL, 0);
+ strftime(stime, sizeof(stime), $5, localtime(&dtime));
+ $$ = parse_dup(stime);
+ } else {
+ $$ = parse_printf("%%{%s:%s,%s}", $3, $5, $7);
+ }
+ } else {
+ $$ = parse_printf("%%{%s:%s,%s}", $3, $5, $7);
+ }
+ }
+ | STYLE LBRACE STRING COLON sstring COMMA sstring COMMA sstring RBRACE {
+ int num;
+ char *val;
+ if (strcmp($3, "split") == 0) {
+ num = strtoll($5, NULL, 10);
+ val = strntok($9, $7, num);
+ if (strisnum($5, 0) && val) {
+ $$ = parse_dup(val);
+ } else {
+ $$ = parse_printf("%%{%s:%s,%s,%s}", $3, $5, $7, $9);
+ }
+ } else {
+ $$ = parse_printf("%%{%s:%s,%s,%s}", $3, $5, $7, $9);
+ }
+ }
+ ;
+
+sstring: STRING
+ | var
+ | style
+ ;
+
+%%
+
+static void
+yyerror(char *fmt, ...) {
+ char msg[1024];
+ va_list ap;
+
+ va_start(ap, fmt);
+ vsnprintf(msg, sizeof(msg), fmt, ap);
+ va_end(ap);
+
+ pfree(&parse_out); /* format() will return NULL */
+ ui_error("parsing '%s': %s", parse_in, msg);
+}
+
+/* Keep in mind: parse_append doesn't use parse_dup. */
+static void
+parse_append(char **dest, char *str) {
+ size_t size;
+ size_t len;
+
+ if (*dest)
+ len = strlen(*dest);
+ else
+ len = 0;
+
+ size = len + strlen(str) + 1;
+ if (!*dest)
+ *dest = emalloc(size);
+ else
+ *dest = erealloc(*dest, size);
+
+ (len ? strlcat : strlcpy)(*dest, str, size);
+}
+
+/* alloc memory to be free'd all at once when parsing is complete
+ * pfree() must not be called on anything returned */
+static char *
+parse_dup(char *str) {
+ static void **mema = NULL;
+ static size_t mems = 0;
+ void *mem = NULL;
+ size_t i;
+
+ if (str) {
+ mem = strdup(str);
+ if (!mems)
+ mema = emalloc((sizeof(char *)) * (mems + 1));
+ else
+ mema = erealloc(mema, (sizeof(char *)) * (mems + 1));
+
+ *(mema + mems) = mem;
+ mems++;
+ } else if (mema && mems) {
+ for (i = 0; i < mems; i++)
+ pfree(mema + i); /* already a double pointer */
+ pfree(&mema);
+ mems = 0;
+ mema = NULL;
+ }
+
+ return mem;
+}
+
+static char *
+parse_printf(char *format, ...) {
+ va_list ap;
+ char buf[8192];
+
+ va_start(ap, format);
+ vsnprintf(buf, sizeof(buf), format, ap);
+ va_end(ap);
+ return parse_dup(buf);
+}
+
+static int
+isspecial(char *s, int prev, int bracelvl, int bracetype[static BRACEMAX], int styleseg[static BRACEMAX]) {
+ if ((*s == '$' && (*(s+1) == '{' && bracelvl != BRACEMAX)) ||
+ (*s == '%' && (*(s+1) == '{' && bracelvl != BRACEMAX)) ||
+ (*s == '{' && (prev == VAR || prev == STYLE)) ||
+ (*s == '}' && (bracelvl)) ||
+ (*s == ',' && (bracelvl && bracetype[bracelvl - 1] == STYLE && styleseg[bracelvl - 1])) ||
+ (*s == ':' && (bracelvl && bracetype[bracelvl - 1] == STYLE && !styleseg[bracelvl - 1])))
+ return 1;
+ else
+ return 0;
+}
+
+static int
+yylex(void) {
+ static char *s = NULL, *p = NULL;
+ static int bracelvl;
+ static int bracetype[BRACEMAX];
+ static int styleseg[BRACEMAX];
+ static int prev = 0;
+ char strlval[8192];
+ int i;
+
+ if (!s || prev == 0) {
+ s = parse_in;
+ bracelvl = 0;
+ prev = -1;
+ }
+
+ if (!*s)
+ RETURN(0);
+
+ fprintf(stderr, "s (lex): %s\n", s);
+
+ if (ISSPECIAL(s)) {
+ switch (*s) {
+ case '$':
+ s++;
+ RETURN(VAR);
+ case '%':
+ s++;
+ RETURN(STYLE);
+ case '{':
+ bracelvl++;
+ bracetype[bracelvl - 1] = prev;
+ if (prev == STYLE)
+ styleseg[bracelvl - 1] = 0;
+ s++;
+ RETURN(LBRACE);
+ case '}':
+ bracelvl--;
+ s++;
+ RETURN(RBRACE);
+ case ',':
+ styleseg[bracelvl - 1]++;
+ s++;
+ RETURN(COMMA);
+ case ':':
+ styleseg[bracelvl - 1]++;
+ s++;
+ RETURN(COLON);
+ }
+ }
+
+ /* first char guaranteed due to previous ISSPECIAL() */
+ strlval[0] = *s;
+
+ for (p = s + 1, i = 1; *p && i < sizeof(strlval); p++) {
+ fprintf(stderr, "p (lex): %s\n", s);
+ if (ISSPECIAL(p)) {
+ fprintf(stderr, "<breaking in lex due to special>\n");
+ break;
+ }
+ if (*p == '\\' && ISSPECIAL(p+1)) {
+ fprintf(stderr, "<escaping special in lex>\n");
+ strlval[i++] = *(p+1);
+ p++;
+ } else if (*p == '\\' && *(p+1) == 'n') {
+ strlval[i++] = '\n';
+ p++;
+ } else {
+ strlval[i++] = *p;
+ }
+ }
+
+ strlval[i] = '\0';
+ yylval = parse_dup(strlval);
+ s = p;
+ RETURN(STRING);
+}
+
+/*
+ * Exposed functions
+ */
+
+char *
+format_get(struct History *hist) {
+ char *cmd, *p1, *p2;
+ int i;
+
+ assert_warn(hist, NULL);
+
+ if (!hist->params)
+ goto raw;
+
+ cmd = *(hist->params);
+ p1 = *(hist->params+1);
+ p2 = *(hist->params+2);
+
+ if (strcmp_n(cmd, "MODE") == 0) {
+ if (p1 && serv_ischannel(hist->origin->server, p1))
+ cmd = "MODE-CHANNEL";
+ else if (hist->from && nick_isself(hist->from) && strcmp_n(hist->from->nick, p1) == 0)
+ cmd = "MODE-NICK-SELF";
+ else
+ cmd = "MODE-NICK";
+ } else if (strcmp_n(cmd, "PRIVMSG") == 0) {
+ /* ascii 1 is ^A */
+ if (*p2 == 1 && strncmp(p2 + 1, "ACTION", CONSTLEN("ACTION")) == 0)
+ cmd = "PRIVMSG-ACTION";
+ else if (*p2 == 1)
+ cmd = "PRIVMSG-CTCP";
+ } else if (strcmp_n(cmd, "NOTICE") == 0 && *p2 == 1) {
+ cmd = "NOTICE-CTCP";
+ }
+
+ for (i=0; formatmap[i].cmd; i++)
+ if (formatmap[i].format && strcmp_n(formatmap[i].cmd, cmd) == 0)
+ return formatmap[i].format;
+
+ if (isdigit(*cmd) && isdigit(*(cmd+1)) && isdigit(*(cmd+2)) && !*(cmd+3))
+ return "format.rpl.other";
+
+raw:
+ return "format.other";
+}
+
+char *
+format(struct Window *window, char *format, struct History *hist) {
+ static char *ret;
+ char *ts;
+ char *rformat;
+ size_t len;
+ int clen[PARSE_LAST]; /* ui_strlenc */
+ int alen[PARSE_LAST]; /* strlen */
+ int divlen = config_getl("divider.margin");
+ int divbool = 0;
+ char *divstr = config_gets("divider.string");
+ char priv[2];
+ int i;
+
+ assert_warn(format || hist, NULL);
+ if (!format)
+ format = config_gets(format_get(hist));
+ assert_warn(format, NULL);
+
+ if (hist && config_getl("timestamp.toggle")) {
+ ts = config_gets("format.ui.timestamp");
+ len = strlen(ts) + strlen(format) + CONSTLEN("%{_time}") + 1;
+ rformat = emalloc(len);
+ snprintf(rformat, len, "%s%%{_time}%s", ts, format);
+ parse_pos = PARSE_TIME;
+ } else {
+ rformat = strdup(format);
+ parse_pos = PARSE_LEFT;
+ }
+
+ vars[var_channel].val = selected.channel ? selected.channel->name : NULL;
+ vars[var_topic].val = selected.channel ? selected.channel->topic : NULL;
+ vars[var_server].val = selected.server ? selected.server->name : NULL;
+
+ if (hist) {
+ vars[var_raw].val = hist->raw;
+ vars[var_nick].val = hist->from ? hist->from->nick : NULL;
+ vars[var_ident].val = hist->from ? hist->from->ident : NULL;
+ vars[var_host].val = hist->from ? hist->from->host : NULL;
+
+ if (hist->from) {
+ priv[0] = hist->from->priv;
+ priv[priv[0] != ' '] = '\0';
+ vars[var_priv].val = priv;
+ }
+
+ if (hist->origin) {
+ if (hist->origin->channel) {
+ divbool = config_getl("divider.toggle");
+ vars[var_channel].val = hist->origin->channel->name;
+ vars[var_topic].val = hist->origin->channel->topic;
+ }
+ if (hist->origin->server) {
+ vars[var_server].val = hist->origin->server->name;
+ }
+ }
+
+ len = snprintf(vars[var_time].val, 0, "%lld", (long long)hist->timestamp) + 1;
+ vars[var_time].val = emalloc(len);
+ snprintf(vars[var_time].val, len, "%lld", (long long)hist->timestamp);
+
+ vars[var_cmd].val = *hist->params;
+ if (hist->params)
+ parse_params = hist->params + 1;
+ } else parse_params = NULL;
+
+ fprintf(stderr, "---\nrformat: %s\n", rformat);
+
+ parse_dup(0); /* free memory in use for last parse_ */
+ for (i = 0; i < PARSE_LAST; i++)
+ pfree(&parse_out[i]);
+ pfree(&ret);
+ parse_in = rformat;
+
+ yyparse();
+
+ if (config_getl("timestamp.toggle"))
+ pfree(&rformat);
+
+ /* TODO: remove DEBUG */
+ fprintf(stderr, "format: %s\n", format);
+ if (hist) {
+ fprintf(stderr, "hist->raw: %s\n", hist->raw);
+ for (i = 0; i < param_len(hist->params); i++)
+ fprintf(stderr, "hist->params[%d]: %s\n", i, *(hist->params + i));
+ }
+ fprintf(stderr, "parse_out[PARSE_TIME]: %s\n", parse_out[PARSE_TIME]);
+ fprintf(stderr, "parse_out[PARSE_LEFT]: %s\n", parse_out[PARSE_LEFT]);
+ fprintf(stderr, "parse_out[PARSE_RIGHT]: %s\n", parse_out[PARSE_RIGHT]);
+
+ /* If there is no %{=}, then it's on the right */
+ if (hist && parse_out[PARSE_LEFT] && !parse_out[PARSE_RIGHT]) {
+ parse_out[PARSE_RIGHT] = parse_out[PARSE_LEFT];
+ parse_out[PARSE_LEFT] = NULL;
+ }
+
+ for (i = 0; i < PARSE_LAST; i++) {
+ if (parse_out[i]) {
+ clen[i] = ui_strlenc(&windows[Win_main], parse_out[i], NULL);
+ alen[i] = strlen(parse_out[i]);
+ }
+ }
+
+ if (divbool) {
+ ret = estrdup(parse_printf("%1$s %2$*3$s%4$s%5$s",
+ parse_out[PARSE_TIME] ? parse_out[PARSE_TIME] : "",
+ parse_out[PARSE_LEFT] ? parse_out[PARSE_LEFT] : "", divlen + alen[PARSE_LEFT] - clen[PARSE_LEFT],
+ divstr,
+ parse_out[PARSE_RIGHT]));
+ } else {
+ if (parse_out[PARSE_TIME])
+ parse_append(&ret, parse_out[PARSE_TIME]);
+ if (parse_out[PARSE_LEFT])
+ parse_append(&ret, parse_out[PARSE_LEFT]);
+ if (parse_out[PARSE_RIGHT])
+ parse_append(&ret, parse_out[PARSE_RIGHT]);
+ }
+
+ fprintf(stderr, "ret: %s\n", ret);
+
+ return ret;
+}
diff --git a/src/hirc.h b/src/hirc.h
@@ -187,8 +187,7 @@ void ui_tls_error_(char *file, int line, const char *func, struct tls *ctx, cha
/* format.c */
char * format_get_bufact(int activity);
char * format_get(struct History *hist);
-char * format_(struct Window *window, char *format, struct History *hist, int recursive);
-#define format(window, format, hist) format_(window, format, hist, 0)
+char * format(struct Window *window, char *format, struct History *hist);
/* commands.c */
void command_eval(struct Server *server, char *str);
diff --git a/src/openbsd/strlcat.c b/src/openbsd/strlcat.c
@@ -0,0 +1,57 @@
+#ifndef __OpenBSD__
+/* $OpenBSD: strlcat.c,v 1.19 2019/01/25 00:19:25 millert Exp $ */
+
+/*
+ * Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <string.h>
+
+/*
+ * Appends src to string dst of size dsize (unlike strncat, dsize is the
+ * full size of dst, not space left). At most dsize-1 characters
+ * will be copied. Always NUL terminates (unless dsize <= strlen(dst)).
+ * Returns strlen(src) + MIN(dsize, strlen(initial dst)).
+ * If retval >= dsize, truncation occurred.
+ */
+size_t
+strlcat(char *dst, const char *src, size_t dsize)
+{
+ const char *odst = dst;
+ const char *osrc = src;
+ size_t n = dsize;
+ size_t dlen;
+
+ /* Find the end of dst and adjust bytes left but don't go past end. */
+ while (n-- != 0 && *dst != '\0')
+ dst++;
+ dlen = dst - odst;
+ n = dsize - dlen;
+
+ if (n-- == 0)
+ return(dlen + strlen(src));
+ while (*src != '\0') {
+ if (n != 0) {
+ *dst++ = *src;
+ n--;
+ }
+ src++;
+ }
+ *dst = '\0';
+
+ return(dlen + (src - osrc)); /* count does not include NUL */
+}
+#endif
diff --git a/src/struct.h b/src/struct.h
@@ -44,6 +44,7 @@ enum Activity {
Activity_error = 3,
Activity_message = 4,
Activity_hilight = 5,
+ Activity_last = 6
};
enum HistOpt {
diff --git a/src/ui.c b/src/ui.c
@@ -54,12 +54,12 @@ struct Selected selected;
struct Keybind *keybinds = NULL;
void
-ui_error_(char *file, int line, const char *func, char *format, ...) {
+ui_error_(char *file, int line, const char *func, char *fmt, ...) {
char msg[1024];
va_list ap;
- va_start(ap, format);
- vsnprintf(msg, sizeof(msg), format, ap);
+ va_start(ap, fmt);
+ vsnprintf(msg, sizeof(msg), fmt, ap);
va_end(ap);
hist_format(selected.history, Activity_error, HIST_UI|HIST_ERR|HIST_NIGN,
@@ -286,7 +286,7 @@ ui_read(void) {
void
ui_redraw(void) {
struct History *p;
- char *format;
+ char *fmt;
long nicklistwidth, buflistwidth;
int x = 0, rx = 0;
int i;
@@ -337,34 +337,34 @@ ui_redraw(void) {
windows[Win_dummy].h = LINES;
windows[Win_dummy].w = COLS;
- format = format(NULL, config_gets("format.ui.separator.horizontal"), NULL);
+ fmt = format(NULL, config_gets("format.ui.separator.horizontal"), NULL);
for (i = x; i <= COLS - rx; i++) {
wmove(windows[Win_dummy].window, LINES - 2, i);
- ui_wprintc(&windows[Win_dummy], 1, "%s", format);
+ ui_wprintc(&windows[Win_dummy], 1, "%s", fmt);
}
if (x) {
- format = format(NULL, config_gets("format.ui.separator.vertical"), NULL);
+ fmt = format(NULL, config_gets("format.ui.separator.vertical"), NULL);
for (i = 0; i <= LINES; i++) {
wmove(windows[Win_dummy].window, i, x - 1);
- ui_wprintc(&windows[Win_dummy], 1, "%s", format);
+ ui_wprintc(&windows[Win_dummy], 1, "%s", fmt);
}
- format = format(NULL, config_gets("format.ui.separator.split.left"), NULL);
+ fmt = format(NULL, config_gets("format.ui.separator.split.left"), NULL);
wmove(windows[Win_dummy].window, LINES - 2, x - 1);
- ui_wprintc(&windows[Win_dummy], 1, "%s", format);
+ ui_wprintc(&windows[Win_dummy], 1, "%s", fmt);
}
if (rx) {
- format = format(NULL, config_gets("format.ui.separator.vertical"), NULL);
+ fmt = format(NULL, config_gets("format.ui.separator.vertical"), NULL);
for (i = 0; i <= LINES; i++) {
wmove(windows[Win_dummy].window, i, COLS - rx);
- ui_wprintc(&windows[Win_dummy], 1, "%s", format);
+ ui_wprintc(&windows[Win_dummy], 1, "%s", fmt);
}
- format = format(NULL, config_gets("format.ui.separator.split.right"), NULL);
+ fmt = format(NULL, config_gets("format.ui.separator.split.right"), NULL);
wmove(windows[Win_dummy].window, LINES - 2, COLS - rx);
- ui_wprintc(&windows[Win_dummy], 1, "%s", format);
+ ui_wprintc(&windows[Win_dummy], 1, "%s", fmt);
}
refresh();
@@ -520,7 +520,15 @@ ui_draw_buflist(void) {
struct Server *sp;
struct Channel *chp, *prp;
int i = 1, scroll;
- char *indicator;
+ char *actind[Activity_last];
+ char *oldind, *indicator;
+
+ oldind = estrdup(format(NULL, config_gets("format.ui.buflist.old"), NULL));
+ actind[Activity_none] = estrdup(format(NULL, config_gets("format.ui.buflist.activity.none"), NULL));
+ actind[Activity_status] = estrdup(format(NULL, config_gets("format.ui.buflist.activity.status"), NULL));
+ actind[Activity_error] = estrdup(format(NULL, config_gets("format.ui.buflist.activity.error"), NULL));
+ actind[Activity_message] = estrdup(format(NULL, config_gets("format.ui.buflist.activity.message"), NULL));
+ actind[Activity_hilight] = estrdup(format(NULL, config_gets("format.ui.buflist.activity.hilight"), NULL));
werase(windows[Win_buflist].window);
@@ -546,12 +554,7 @@ ui_draw_buflist(void) {
if (scroll < i - 1) {
if (selected.server == sp && !selected.channel)
wattron(windows[Win_buflist].window, A_BOLD);
-
- if (sp->status == ConnStatus_notconnected)
- indicator = format(NULL, config_gets("format.ui.buflist.old"), NULL);
- else
- indicator = format_get_bufact(sp->history->activity);
-
+ indicator = (sp->status == ConnStatus_notconnected) ? oldind : actind[sp->history->activity];
ui_wprintc(&windows[Win_buflist], 1, "%02d: %s─ %s%s\n", i, sp->next ? "├" : "└", indicator, sp->name);
wattrset(windows[Win_buflist].window, A_NORMAL);
}
@@ -561,12 +564,7 @@ ui_draw_buflist(void) {
if (scroll < i - 1) {
if (selected.channel == chp)
wattron(windows[Win_buflist].window, A_BOLD);
-
- if (chp->old)
- indicator = format(NULL, config_gets("format.ui.buflist.old"), NULL);
- else
- indicator = format_get_bufact(chp->history->activity);
-
+ indicator = (chp->old) ? oldind : actind[chp->history->activity];
ui_wprintc(&windows[Win_buflist], 1, "%02d: %s %s─ %s%s\n", i,
sp->next ? "│" : " ", chp->next || sp->queries ? "├" : "└", indicator, chp->name);
wattrset(windows[Win_buflist].window, A_NORMAL);
@@ -578,12 +576,7 @@ ui_draw_buflist(void) {
if (scroll < i - 1) {
if (selected.channel == prp)
wattron(windows[Win_buflist].window, A_BOLD);
-
- if (prp->old)
- indicator = format(NULL, config_gets("format.ui.buflist.old"), NULL);
- else
- indicator = format_get_bufact(prp->history->activity);
-
+ indicator = (prp->old) ? oldind : actind[prp->history->activity];
ui_wprintc(&windows[Win_buflist], 1, "%02d: %s %s─ %s%s\n", i,
sp->next ? "│" : " ", prp->next ? "├" : "└", indicator, prp->name);
wattrset(windows[Win_buflist].window, A_NORMAL);
@@ -600,7 +593,7 @@ ui_draw_buflist(void) {
}
int
-ui_wprintc(struct Window *window, int lines, char *format, ...) {
+ui_wprintc(struct Window *window, int lines, char *fmt, ...) {
char *str;
wchar_t *wcs, *s;
va_list ap;
@@ -616,13 +609,13 @@ ui_wprintc(struct Window *window, int lines, char *format, ...) {
int reverse = 0;
int italic = 0;
- va_start(ap, format);
- ret = vsnprintf(str, 0, format, ap) + 1;
+ va_start(ap, fmt);
+ ret = vsnprintf(str, 0, fmt, ap) + 1;
va_end(ap);
str = emalloc(ret);
- va_start(ap, format);
- ret = vsnprintf(str, ret, format, ap);
+ va_start(ap, fmt);
+ ret = vsnprintf(str, ret, fmt, ap);
va_end(ap);
if (ret < 0)
return ret;