hirc

IRC client
Log | Files | Refs

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:
Mconfig.c | 5+++++
Mhirc.h | 1+
Mmain.c | 1+
Mui.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; +}