commit a79224751a669462fc565a04389b0e260af3b446
parent 3d761f0d1d20a77af311bf26832df16365548e00
Author: hhvn <dev@hhvn.uk>
Date: Sat, 27 Nov 2021 18:17:50 +0000
config.c hirc.h main.c ui.c: basic format parsing
Diffstat:
M | config.c | | | 5 | +++++ |
M | hirc.h | | | 1 | + |
M | main.c | | | 1 | + |
M | ui.c | | | 163 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- |
4 files changed, 167 insertions(+), 3 deletions(-)
diff --git a/config.c b/config.c
@@ -144,6 +144,11 @@ struct Config config[] = {
.strhandle = NULL,
.description = {
"Message to send on /part", NULL}},
+ {"format.ui.topic", 1, Val_string,
+ .str = "%{c:99,89}${topic}",
+ .strhandle = NULL,
+ .description = {
+ "Format of topic at top of main window", NULL}},
{NULL},
};
diff --git a/hirc.h b/hirc.h
@@ -108,6 +108,7 @@ int ui_strlenc(struct Window *window, char *s, int *lines);
void ui_select(struct Server *server, struct Channel *channel);
void ui_filltoeol(struct Window *window, char c);
void ui_wclear(struct Window *window);
+char * ui_format(char *format, struct History *hist);
void ui_error_(char *file, int line, char *format, ...);
#define ui_error(format, ...) ui_error_(__FILE__, __LINE__, format, __VA_ARGS__);
void ui_perror_(char *file, int line, char *str);
diff --git a/main.c b/main.c
@@ -211,6 +211,7 @@ main(int argc, char *argv[]) {
FILE *file;
int i, j, refreshed, inputrefreshed;
long pinginact, reconnectinterval, maxreconnectinterval;
+ char *tmp;
if (argc > 2) {
fprintf(stderr, "usage: %s [configfile]", dirname(argv[0]));
diff --git a/ui.c b/ui.c
@@ -692,7 +692,6 @@ void
ui_draw_main(void) {
struct History *p;
int y, lines;
- long fg, bg;
ui_wclear(&windows[Win_main]);
@@ -712,9 +711,8 @@ ui_draw_main(void) {
}
if (selected.channel && selected.channel->topic) {
- config_getr("misc.topiccolour", &fg, &bg);
wmove(windows[Win_main].window, 0, 0);
- ui_wprintc(&windows[Win_main], 1, "%c%02d,%02d%s\n", 3 /* ^C */, fg, bg, selected.channel->topic);
+ ui_wprintc(&windows[Win_main], 0, "%s\n", ui_format(config_gets("format.ui.topic"), NULL));
}
}
@@ -725,3 +723,162 @@ ui_select(struct Server *server, struct Channel *channel) {
selected.history = channel ? channel->history : server ? server->history : main_buf;
selected.name = channel ? channel->name : server ? server->name : "hirc";
}
+
+char *
+ui_format(char *format, struct History *hist) {
+ static char ret[8192];
+ int rc, escape, pn, i;
+ char **params;
+ char *tmp, *p;
+ char colourbuf[2][3];
+ enum {
+ sub_cmd,
+ sub_nick,
+ sub_ident,
+ sub_host,
+ sub_channel,
+ sub_topic,
+ sub_server,
+ };
+ struct {
+ char *name;
+ char *val;
+ } subs[] = {
+ [sub_cmd] = {"cmd"},
+ [sub_nick] = {"nick"},
+ [sub_ident] = {"ident"},
+ [sub_host] = {"host"},
+ [sub_channel] = {"channel"},
+ [sub_topic] = {"topic"},
+ [sub_server] = {"server"},
+ {NULL, NULL},
+ };
+
+ 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_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->origin) {
+ if (hist->origin->channel) {
+ 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;
+ }
+ }
+
+ if (**(params = hist->params) == ':')
+ params++;
+
+ subs[sub_cmd].val = *params;
+ params++;
+ }
+
+ for (rc = 0; format && *format && rc < sizeof(ret); ) {
+ if (!escape && *format == '$' && *(format+1) == '{' && strchr(format, '}')) {
+ escape = 0;
+ tmp = struntil(format+2, '}');
+
+ for (p = tmp; *p && isdigit(*p); p++);
+ /* If all are digits, *p == '\0' */
+ if (!*p && hist) {
+ pn = strtol(tmp, NULL, 10) - 1;
+ if (pn >= 0 && param_len(params) >= pn) {
+ rc += snprintf(&ret[rc], sizeof(ret) - rc, "%s", *(params+pn));
+ format = strchr(format, '}') + 1;
+ continue;
+ }
+ }
+
+ for (i=0; subs[i].name; i++) {
+ if (subs[i].val && strcmp_n(subs[i].name, tmp) == 0) {
+ rc += snprintf(&ret[rc], sizeof(ret) - rc, "%s", subs[i].val);
+ format = strchr(format, '}') + 1;
+ continue;
+ }
+ }
+ }
+
+ if (!escape && *format == '%' && *(format+1) == '{' && strchr(format, '}')) {
+ escape = 0;
+ tmp = struntil(format+2, '}');
+
+ switch (*tmp) {
+ case 'b':
+ case 'B':
+ ret[rc++] = 2; /* ^B */
+ format = strchr(format, '}') + 1;
+ continue;
+ case 'c':
+ case 'C':
+ tmp++;
+ if (*tmp == ':' && isdigit(*(tmp+1))) {
+ tmp++;
+ memset(colourbuf, 0, sizeof(colourbuf));
+ colourbuf[0][0] = *tmp;
+ tmp++;
+ if (isdigit(*tmp)) {
+ colourbuf[0][1] = *tmp;
+ tmp += 1;
+ }
+ if (*tmp == ',' && isdigit(*(tmp+1))) {
+ colourbuf[1][0] = *(tmp+1);
+ tmp += 2;
+ }
+ if (colourbuf[1][0] && isdigit(*tmp)) {
+ colourbuf[1][1] = *(tmp);
+ tmp += 1;
+ }
+ if (*tmp == '\0') {
+ rc += snprintf(&ret[rc], sizeof(ret) - 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':
+ ret[rc++] = 9; /* ^I */
+ format = strchr(format, '}') + 1;
+ continue;
+ case 'o':
+ case 'O':
+ ret[rc++] = 15; /* ^O */
+ format = strchr(format, '}') + 1;
+ continue;
+ case 'r':
+ case 'R':
+ ret[rc++] = 18; /* ^R */
+ format = strchr(format, '}') + 1;
+ continue;
+ case 'u':
+ case 'U':
+ ret[rc++] = 21; /* ^U */
+ format = strchr(format, '}') + 1;
+ continue;
+ }
+ }
+
+ if (escape) {
+ ret[rc++] = '\\';
+ escape = 0;
+ }
+
+ if (*format == '\\') {
+ escape = 1;
+ } else {
+ ret[rc++] = *format;
+ format++;
+ }
+ }
+
+ ret[rc] = '\0';
+ return ret;
+}