commit 81822db61acc0b67bb48ce44a2e2a6930e5093d9
parent 2c44097439323618f6df8277b348bb597a0df756
Author: hhvn <dev@hhvn.uk>
Date: Thu, 11 Nov 2021 19:48:11 +0000
config.{c,h} Makefile {commands,handle,hist,main,nick,serv,ui}.c {hirc,struct}.h: /set
Diffstat:
M | Makefile | | | 5 | +++-- |
M | commands.c | | | 17 | +++++++++++++---- |
M | config.c | | | 285 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------- |
D | config.h | | | 155 | ------------------------------------------------------------------------------- |
M | handle.c | | | 2 | +- |
M | hirc.h | | | 22 | +++++++++++++++++++++- |
M | hist.c | | | 9 | ++++++++- |
M | main.c | | | 30 | ++++++++++++++++++++++++++++-- |
M | nick.c | | | 15 | +++++++++++---- |
M | serv.c | | | 8 | ++++---- |
M | struct.h | | | 28 | +++++++++++++++++++--------- |
M | ui.c | | | 42 | ++++++++++++++++++++++++++++++++---------- |
12 files changed, 347 insertions(+), 271 deletions(-)
diff --git a/Makefile b/Makefile
@@ -2,7 +2,8 @@ PREFIX = /usr/local
BINDIR = $(PREFIX)/bin
BIN = hirc
OBJ = main.o handle.o hist.o nick.o \
- chan.o serv.o ui.o commands.o
+ chan.o serv.o ui.o commands.o \
+ config.o
# Comment to disable TLS
LDTLS = -ltls
@@ -20,4 +21,4 @@ clean:
.c.o:
$(CC) $(CFLAGS) -c $<
-$(OBJ): config.h
+$(OBJ):
diff --git a/commands.c b/commands.c
@@ -18,12 +18,13 @@ static struct Command commands[] = {
{"quit", command_quit},
{"connect", command_connect},
{"select", command_select},
+ {"set", command_set},
{NULL, NULL},
};
void
command_quit(char *str) {
- cleanup(str ? str : quitmessage);
+ cleanup(str ? str : config_gets("misc.quitmessage"));
exit(EXIT_SUCCESS);
}
@@ -33,9 +34,9 @@ command_connect(char *str) {
char *network = NULL;
char *host = NULL;
char *port = NULL;
- char *nick = NULL;
- char *username = NULL;
- char *realname = NULL;
+ char *nick = config_gets("def.nick");
+ char *username = config_gets("def.user");
+ char *realname = config_gets("def.real");
int tls = 0, tls_verify = 0;
int ret;
struct passwd *user;
@@ -189,6 +190,14 @@ command_select(char *str) {
}
}
+void
+command_set(char *str) {
+ char *name, *val;
+
+ name = strtok_r(str, " ", &val);
+ config_set(name, val);
+}
+
int
command_getopt(char **str, struct CommandOpts *opts) {
char *opt;
diff --git a/config.c b/config.c
@@ -1,19 +1,29 @@
+#include <ncurses.h>
#include <string.h>
#include <stdlib.h>
#include "hirc.h"
+char *valname[] = {
+ [Val_string] = "a string",
+ [Val_bool] = "boolean",
+ [Val_signed] = "a numeric value",
+ [Val_unsigned] = "positive",
+ [Val_nzunsigned] = "greater than zero",
+ [Val_range] = "a range",
+};
+
struct Config config[] = {
{"log.dir", 1, Val_string,
.str = "~/.local/hirc",
.strhandle = NULL,
.description =
- "Directory for hirc to log to."
- "Can contain ~ to refer to $HOME"},
+ "Directory for hirc to log to.\n"
+ "Can contain ~ to refer to $HOME\n"},
{"log.toggle", 1, Val_bool,
.num = 1,
.numhandle = NULL,
.description =
- "Simple: to log, or not to log"},
+ "Simple: to log, or not to log\n"},
{"def.nick", 1, Val_string,
.str = NULL,
.strhandle = NULL,
@@ -23,100 +33,100 @@ struct Config config[] = {
.str = NULL,
.strhandle = NULL,
.description =
- "Default username (nick!..here..@host), "
- "may be replaced by identd response"},
+ "Default username (nick!..here..@host), \n"
+ "may be replaced by identd response\n"},
{"def.real", 1, Val_string,
.str = NULL,
.strhandle = NULL,
.description =
- "Default \"realname\", seen in /whois"},
+ "Default \"realname\", seen in /whois\n"},
{"def.chantypes", 1, Val_string,
.str = "#&!+",
.strhandle = NULL,
.description =
- "You most likely don't want to touch this."
- "If a server does not supply this in RPL_ISUPPORT,"
- "hirc assumes it will use these channel types."},
+ "You most likely don't want to touch this.\n"
+ "If a server does not supply this in RPL_ISUPPORT,\n"
+ "hirc assumes it will use these channel types.\n"},
{"def.prefixes", 1, Val_string,
.str = "(ov)@+",
.strhandle = NULL,
.description =
- "You most likely don't want to touch this."
- "If a server doesn't supply this in the nonstandard"
- "RPL_ISUPPORT, it likely won't support nonstandard"
- "prefixes."},
+ "You most likely don't want to touch this.\n"
+ "If a server doesn't supply this in the nonstandard\n"
+ "RPL_ISUPPORT, it likely won't support nonstandard\n"
+ "prefixes.\n"},
{"reconnect.interval", 1, Val_nzunsigned,
.num = 10,
.numhandle = NULL,
.description =
- "Starting reconnect interval in seconds."
- "In reality, for each attempt this will be multipled"
- "by the number of failed attemps until it reaches"
- "reconnect.maxinterval"},
+ "Starting reconnect interval in seconds.\n"
+ "In reality, for each attempt this will be multipled\n"
+ "by the number of failed attemps until it reaches\n"
+ "reconnect.maxinterval\n"},
{"reconnect.maxinterval", 1, Val_nzunsigned,
.num = 600,
.numhandle = NULL,
.description =
- "Maximum reconnect interval in seconds."
- "See reconnect.interval"},
+ "Maximum reconnect interval in seconds.\n"
+ "See reconnect.interval\n"},
{"nickcolour.self", 1, Val_nzunsigned,
.num = 90,
.numhandle = config_colour_self,
.description =
- "Colour to use for onself."
- "Must be 0, 99 or anywhere between. 99 is no colours."},
+ "Colour to use for onself.\n"
+ "Must be 0, 99 or anywhere between. 99 is no colours.\n"},
{"nickcolour.range", 1, Val_range,
.range = {28, 63},
.rangehandle = config_colour_range,
.description =
- "Range of (mirc extended) colours used to colour nicks"
- "Must be 0, 99 or anywhere between. 99 is no colour"
- "Giving a single value or two identical values will"
- "use that colour only"},
+ "Range of (mirc extended) colours used to colour nicks\n"
+ "Must be 0, 99 or anywhere between. 99 is no colour\n"
+ "Giving a single value or two identical values will\n"
+ "use that colour only\n"},
{"nicklist.location", 1, Val_unsigned,
.num = RIGHT,
.numhandle = config_nicklist_location,
.description =
- "Location of nicklist. May be:"
- " - Hidden (0)"
- " - Left (1)"
- " - Right (2)"},
+ "Location of nicklist. May be:\n"
+ " 0 - Hidden\n"
+ " 1 - Left\n"
+ " 2 - Right\n"},
{"nicklist.width", 1, Val_nzunsigned,
.num = 15,
.numhandle = config_nicklist_width,
.description =
- "Number of columns nicklist will take up."},
+ "Number of columns nicklist will take up.\n"},
{"buflist.location", 1, Val_unsigned,
.num = LEFT,
.numhandle = config_buflist_location,
.description =
- "Location of nicklist. May be:"
- " - Hidden (0)"
- " - Left (1)"
- " - Right (2)"},
+ "Location of nicklist. May be:\n"
+ " 0 - Hidden\n"
+ " 1 - Left\n"
+ " 2 - Right\n"},
{"buflist.width", 1, Val_nzunsigned,
.num = 25,
.numhandle = config_buflist_width,
.description =
- "Number of columns buflist will take up."},
+ "Number of columns buflist will take up.\n"},
{"misc.pingtime", 1, Val_nzunsigned,
.num = 200,
.numhandle = NULL,
.description =
- "Wait this many seconds since last received message"
- "from server to send PING. If ping.wait seconds"
- "elapses since sending a PING, hirc will consider"
- "the server disconnected."},
+ "Wait this many seconds since last received message\n"
+ "from server to send PING. If ping.wait seconds\n"
+ "elapses since sending a PING, hirc will consider\n"
+ "the server disconnected.\n"},
{"misc.quitmessage", 1, Val_string,
.str = "pain is temporary",
.strhandle = NULL,
.description =
- "Message to send on /quit"},
+ "Message to send on /quit\n"},
{"misc.partmessage", 1, Val_string,
.str = "pain is temporary",
.strhandle = NULL,
.description =
- "Message to send on /part"},
+ "Message to send on /part\n"},
{NULL},
};
@@ -136,6 +146,28 @@ config_getl(char *name) {
return 0;
}
+void
+config_get_print(char *name) {
+ int i;
+
+ for (i=0; config[i].name; i++) {
+ if (strcmp(config[i].name, name) == 0) {
+ if (config[i].valtype == Val_string)
+ hist_format(main_buf, Activity_status, HIST_SHOW, "%s: %s",
+ name, config[i].str);
+ else if (config[i].valtype == Val_range)
+ hist_format(main_buf, Activity_status, HIST_SHOW, "%s: {%ld, %ld}",
+ name, config[i].range[0], config[i].range[1]);
+ else
+ hist_format(main_buf, Activity_status, HIST_SHOW, "%s: %ld",
+ name, config[i].num);
+ return;
+ }
+ }
+
+ ui_error("no such configuration variable: '%s'", name);
+}
+
char *
config_gets(char *name) {
int i;
@@ -168,20 +200,24 @@ config_setl(char *name, long num) {
int i;
for (i=0; config[i].name; i++) {
- if (strcmp(config[i].name, name) == 0 && (
- config[i].valtype == Val_bool ||
- config[i].valtype == Val_signed ||
- config[i].valtype == Val_unsigned ||
- config[i].valtype == Val_nzunsigned)) {
- if (config[i].numhandle) {
- config[i].numhandle(num);
- } else {
+ if (strcmp(config[i].name, name) == 0) {
+ if ((config[i].valtype == Val_bool && (num == 1 || num == 0)) ||
+ (config[i].valtype == Val_signed) ||
+ (config[i].valtype == Val_unsigned && num >= 0) ||
+ (config[i].valtype == Val_nzunsigned && num > 0)) {
+ if (config[i].numhandle)
+ if (!config[i].numhandle(num))
+ return;
config[i].isdef = 0;
config[i].num = num;
+ } else {
+ ui_error("%s must be %s", name, valname[config[i].valtype]);
}
return;
}
}
+
+ ui_error("no such configuration variable: '%s'", name);
}
void
@@ -189,20 +225,24 @@ config_sets(char *name, char *str) {
int i;
for (i=0; config[i].name; i++) {
- if (strcmp(config[i].name, name) == 0 &&
- config[i].valtype == Val_string) {
- if (config[i].strhandle) {
- config[i].strhandle(str);
- } else {
- if (!config[i].isdef)
- free(config[i].str);
- else
- config[i].isdef = 0;
- config[i].str = estrdup(str);
+ if (strcmp(config[i].name, name) == 0) {
+ if (config[i].valtype != Val_string) {
+ ui_error("%s must be %s", name, valname[config[i].valtype]);
+ return;
}
+ if (config[i].strhandle)
+ if (!config[i].strhandle(str))
+ return;
+ if (!config[i].isdef)
+ free(config[i].str);
+ else
+ config[i].isdef = 0;
+ config[i].str = estrdup(str);
return;
}
}
+
+ ui_error("no such configuration variable: '%s'", name);
}
void
@@ -210,41 +250,130 @@ config_setr(char *name, long a, long b) {
int i;
for (i=0; config[i].name; i++) {
- if (strcmp(config[i].name, name) == 0 &&
- config[i].valtype == Val_range) {
- if (config[i].strhandle) {
- config[i].rangehandle(a, b);
- } else {
- config[i].isdef = 0;
- config[i].range[0] = a;
- config[i].range[1] = b;
+ if (strcmp(config[i].name, name) == 0 ) {
+ if (config[i].valtype != Val_range) {
+ ui_error("%s must be %s", name, valname[config[i].valtype]);
+ return;
}
+ if (config[i].rangehandle)
+ if (!config[i].rangehandle(a, b))
+ return;
+ config[i].isdef = 0;
+ config[i].range[0] = a;
+ config[i].range[1] = b;
return;
}
}
+
+ ui_error("no such configuration variable: '%s'", name);
}
void
+config_set(char *name, char *val) {
+ char *str = val ? strdup(val) : NULL;
+ char *tok[3], *save, *p;
+
+ tok[0] = strtok_r(val, " ", &save);
+ tok[1] = strtok_r(NULL, " ", &save);
+ tok[2] = strtok_r(NULL, " ", &save);
+
+ if (strisnum(tok[0]) && strisnum(tok[1]) && !tok[2])
+ config_setr(name, strtol(tok[0], NULL, 10), strtol(tok[1], NULL, 10));
+ else if (strisnum(tok[0]) && !tok[1])
+ config_setl(name, strtol(tok[0], NULL, 10));
+ else if (tok[0])
+ config_sets(name, str);
+ else
+ config_get_print(name);
+
+ free(str);
+}
+
+int
config_colour_self(long num) {
- return;
+ if (num >= 0 && num <= 99)
+ return 1;
+
+ ui_error("nickcolour.self must be between 0 and 99 (including both)", NULL);
+ return 0;
}
-void
+
+int
config_colour_range(long a, long b) {
- return;
+ if (a >= 0 && a <= 0 &&
+ b >= 0 && b <= 0)
+ return 1;
+
+ ui_error("nickcolour.range must have numbers between 0 and 99 (including both)", NULL);
}
-void
+
+int
config_nicklist_location(long num) {
- return;
+ int i;
+
+ if (num != HIDDEN && num != LEFT && num != RIGHT) {
+ ui_error("nicklist.location must be 0, 1 or 2", NULL);
+ return 0;
+ }
+
+ if (num == windows[Win_buflist].location != HIDDEN)
+ windows[Win_buflist].location = num == LEFT ? RIGHT : LEFT;
+ windows[Win_nicklist].location = num;
+
+ ui_redraw();
+
+ for (i=0; config[i].name; i++) {
+ if (strcmp(config[i].name, "nicklist.location") == 0)
+ config[i].num = num;
+ if (strcmp(config[i].name, "buflist.location") == 0)
+ config[i].num = windows[Win_buflist].location;
+ }
+
+ return 0;
}
-void
+
+int
config_nicklist_width(long num) {
- return;
+ if (num <= COLS - (windows[Win_buflist].location ? windows[Win_buflist].w : 0) - 2) {
+ uineedredraw = 1;
+ return 1;
+ }
+
+ ui_error("nicklist will be too big", NULL);
+ return 0;
}
-void
+
+int
config_buflist_location(long num) {
- return;
+ int i;
+
+ if (num != HIDDEN && num != LEFT && num != RIGHT) {
+ ui_error("buflist.location must be 0, 1 or 2", NULL);
+ return 0;
+ }
+
+ if (num == windows[Win_buflist].location != HIDDEN)
+ windows[Win_nicklist].location = num == LEFT ? RIGHT : LEFT;
+ windows[Win_buflist].location = num;
+
+ ui_redraw();
+
+ for (i=0; config[i].name; i++) {
+ if (strcmp(config[i].name, "buflist.location") == 0)
+ config[i].num = num;
+ if (strcmp(config[i].name, "nicklist.location") == 0)
+ config[i].num = windows[Win_nicklist].location;
+ }
+
+ return 0;
}
-void
+int
config_buflist_width(long num) {
- return;
+ if (num <= COLS - (windows[Win_nicklist].location ? windows[Win_nicklist].w : 0) - 2) {
+ uineedredraw = 1;
+ return 1;
+ }
+
+ ui_error("buflist will be too big", NULL);
+ return 0;
}
diff --git a/config.h b/config.h
@@ -1,155 +0,0 @@
-#ifndef H_CONFIG
-#define H_CONFIG
-
-#include "struct.h"
-
-#define MAIN_NICK "hhvn"
-#define MAIN_USERNAME "Fanatic"
-#define MAIN_REALNAME "gopher://hhvn.uk"
-
-static char *logdir = "~/.local/hirc";
-static struct Netconfig netconfig[] = {
- {
- .name = "test",
- .host = "localhost",
- .port = "6667",
- .nick = MAIN_NICK,
- .user = MAIN_USERNAME,
- .real = MAIN_REALNAME,
- .join = { "#test", "#test2", NULL },
- .tls = 0,
- .tls_verify = 0,
- },
- /*
- {
- .name = "hlircnet",
- .host = "irc.hhvn.uk",
- .port = "6667",
- .nick = MAIN_NICK,
- .user = MAIN_USERNAME,
- .real = MAIN_REALNAME,
- .join = {
- "#hlircnet", "#help", "#gopher", "#vhosts",
- "#hlfm", "#cgo", "#distrotube", NULL
- },
- },
- {
- .name = "dataswamp",
- .host = "irc.dataswamp.org",
- .port = "6667",
- .nick = MAIN_NICK,
- .user = MAIN_USERNAME,
- .real = MAIN_REALNAME,
- .join = { "#dataswamp", NULL },
- },
- {
- .name = "efnet",
- .host = "efnet.port80.se",
- .port = "6667",
- .nick = MAIN_NICK,
- .user = MAIN_USERNAME,
- .real = MAIN_REALNAME,
- .join = { "#asciiart", "#LRH", "#thepiratebay.org", NULL },
- },
- {
- .name = "ikteam",
- .host = "irc.nk.ax",
- .port = "6667",
- .nick = MAIN_NICK,
- .user = MAIN_USERNAME,
- .real = MAIN_REALNAME,
- .join = { "#chat", NULL },
- },
- {
- .name = "nebulacentre",
- .host = "irc.nebulacentre.net",
- .port = "6667",
- .nick = MAIN_NICK,
- .user = MAIN_USERNAME,
- .real = MAIN_REALNAME,
- .join = { "#general", NULL },
- },
- {
- .name = "sdf",
- .host = "irc.sdf.org",
- .port = "6667",
- .nick = MAIN_NICK,
- .user = MAIN_USERNAME,
- .real = MAIN_REALNAME,
- .join = { "#sdf", "#gopher", "#helpdesk", NULL },
- }
- */
-};
-
-/* real maximum = MAX_HISTORY * (channels + servers + queries) */
-#define MAX_HISTORY 1024
-
-#define HIRC_COLOURS 100
-static unsigned short colourmap[HIRC_COLOURS] = {
- /* original 16 mirc colours
- * some clients use the first 16 ansi colours for this,
- * but here I use the 256 colours to ensure terminal-agnosticism */
- [0] = 255, 16, 19, 46, 124, 88, 127, 184,
- [8] = 208, 46, 45, 51, 21, 201, 240, 255,
-
- /* extended */
- [16] = 52, 94, 100, 58, 22, 29, 23, 24, 17, 54, 53, 89,
- [28] = 88, 130, 142, 64, 28, 35, 30, 25, 18, 91, 90, 125,
- [40] = 124, 166, 184, 106, 34, 49, 37, 33, 19, 129, 127, 161,
- [52] = 196, 208, 226, 154, 46, 86, 51, 75, 21, 171, 201, 198,
- [64] = 203, 215, 227, 191, 83, 122, 87, 111, 63, 177, 207, 205,
- [76] = 217, 223, 229, 193, 157, 158, 159, 153, 147, 183, 219, 212,
- [88] = 16, 233, 235, 237, 239, 241, 244, 247, 250, 254, 231,
-
- /* transparency */
- [99] = -1
-};
-
-/* (mIRC) colour for any messages sent by oneself */
-static unsigned short selfcolour = 90;
-
-/* (mIRC) inclusive colour range for any messages sent
- * by others. Use same number twice for constant colour */
-static unsigned short othercolour[2] = {28, 63};
-
-/* default channel types */
-static char *default_chantypes = "#&!+";
-
-/* default prefixes/priveledges, (symbols)modes */
-static char *default_prefixes = "(ov)@+";
-
-/* send ping to server after n seconds of inactivity */
-static int pinginact = 200;
-
-/* max seconds to wait between reconnects */
-static long maxreconnectinterval = 600;
-
-/* number of seconds between reconnects,
- * multiplied by amount of failed reconnects.
- * Example: reconnectinterval = 10, maxreconnectinterval = 600
- * 1st: 0 * 10 = 0
- * 2nd: 1 * 10 = 10
- * 3rd: 2 * 10 = 20
- * 10th: 10 * 10 = 100
- * 60th: 60 * 10 = 600
- * 61st: 600, maxreconnectinterval reached */
-static long reconnectinterval = 10;
-
-/* nicklist location:
- * HIDDEN, LEFT, RIGHT */
-static short nicklistlocation = RIGHT;
-
-/* width of nicklist in columns */
-static int nicklistwidth = 15;
-
-/* buffer list location:
- * HIDDEN, LEFT, RIGHT */
-static short buflistlocation = LEFT;
-
-/* width of buffer list in columns */
-static int buflistwidth = 25;
-
-/* default quit message */
-static char *quitmessage = "pain is temporary";
-
-#endif /* H_CONFIG */
diff --git a/handle.c b/handle.c
@@ -297,7 +297,7 @@ handle(int rfd, struct Server *server) {
if (!read_line(rfd, buf, sizeof(buf))) {
if (buf[0] == EOF || buf[0] == 3 || buf[0] == 4) {
- serv_disconnect(server, 1);
+ serv_disconnect(server, 1, "EOF");
hist_format(server->history, Activity_error, HIST_SHOW,
"SELF_CONNECTLOST %s %s %s :EOF received",
server->name, server->host, server->port);
diff --git a/hirc.h b/hirc.h
@@ -2,12 +2,13 @@
#define H_HIRC
#include "struct.h"
-#include "config.h"
#define PARAM_MAX 64
#define INPUT_MAX 8192
#define COMMANDARG_MAX (INPUT_MAX / 5)
/* Theoretical max: -a o -b o -c o *
* 12345 */
+#define MAX_HISTORY 8192
+ /* real maximum = MAX_HISTORY * (channels + servers + queries) */
/* main.c */
void * emalloc(size_t size);
@@ -21,6 +22,7 @@ int ircprintf(struct Server *server, char *format, ...);
char * homepath(char *path);
char chrcmp(char c, char *s);
char * struntil(char *str, char until);
+int strisnum(char *str);
/* chan.c */
void chan_free(struct Channel *channel);
@@ -127,6 +129,23 @@ int command_getopt(char **str, struct CommandOpts *opts);
void command_quit(char *str);
void command_connect(char *str);
void command_select(char *str);
+void command_set(char *str);
+
+/* config.h */
+void config_get_print(char *name);
+long config_getl(char *name);
+char * config_gets(char *name);
+void config_getr(char *name, long *a, long *b);
+void config_set(char *name, char *str);
+void config_setl(char *name, long num);
+void config_sets(char *name, char *str);
+void config_setr(char *name, long a, long b);
+int config_colour_self(long num);
+int config_colour_range(long a, long b);
+int config_nicklist_location(long num);
+int config_nicklist_width(long num);
+int config_buflist_location(long num);
+int config_buflist_width(long num);
/* main.c */
extern struct Server *servers;
@@ -135,5 +154,6 @@ extern struct HistInfo *main_buf;
/* ui.c */
extern struct Selected selected;
extern struct Window windows[Win_last];
+extern int uineedredraw;
#endif /* H_HIRC */
diff --git a/hist.c b/hist.c
@@ -128,8 +128,15 @@ hist_format(struct HistInfo *histinfo, enum Activity activity, enum HistOpt opti
int
hist_log(char *msg, struct Nick *from, time_t timestamp, struct Server *server) {
char filename[2048];
+ char *logdir;
int ret, serrno;
+ if (!config_getl("log.toggle"))
+ return -2;
+
+ if ((logdir = config_gets("log.dir")) == NULL)
+ return -3;
+
if (*msg == ':' && strchr(msg, ' '))
msg = strchr(msg, ' ') + 1;
@@ -157,7 +164,7 @@ hist_log(char *msg, struct Nick *from, time_t timestamp, struct Server *server)
ui_error("Failed to write to log of server '%s': %s", server->name, strerror(errno));
return -1;
}
-
+
return 1;
}
diff --git a/main.c b/main.c
@@ -137,7 +137,7 @@ ircprintf(struct Server *server, char *format, ...) {
ret = write(server->wfd, msg, strlen(msg));
if (ret == -1 && server->status == ConnStatus_connected) {
- serv_disconnect(server, 1);
+ serv_disconnect(server, 1, "Eead Rrror");
hist_format(server->history, Activity_error, HIST_SHOW,
"SELF_CONNECTLOST %s %s %s :%s",
server->name, server->host, server->port, strerror(errno));
@@ -182,6 +182,20 @@ struntil(char *str, char until) {
return ret;
}
+int
+strisnum(char *str) {
+ if (!str)
+ return 0;
+
+ if (*str == '-' || *str == '+')
+ str += 1;
+
+ for (; *str; str++)
+ if (*str > '9' || *str < '0')
+ return 0;
+ return 1;
+}
+
void
sighandler(int signal) {
return;
@@ -193,6 +207,7 @@ main(int argc, char **argv) {
struct Server *sp;
FILE *file;
int i, refreshed, inputrefreshed;
+ long pinginact, reconnectinterval, maxreconnectinterval;
struct pollfd fds[] = {
{ .fd = fileno(stdin), .events = POLLIN },
};
@@ -216,6 +231,9 @@ main(int argc, char **argv) {
exit(EXIT_FAILURE);
}
+ pinginact = config_getl("misc.pingtime");
+ reconnectinterval = config_getl("reconnect.interval");
+ maxreconnectinterval = config_getl("reconnect.maxinterval");
for (sp = servers; sp; sp = sp->next) {
if (sp->rpollfd->revents) {
/* received an event */
@@ -230,7 +248,7 @@ main(int argc, char **argv) {
} else if (sp->pingsent && (time(NULL) - sp->pingsent) >= pinginact) {
/* haven't gotten a response in pinginact seconds since
* sending ping, this connexion is probably dead now */
- serv_disconnect(sp, 1);
+ serv_disconnect(sp, 1, "Eead Rror");
hist_format(sp->history, Activity_error, HIST_SHOW,
"SELF_CONNECTLOST %s %s %s :No ping reply in %d seconds",
sp->name, sp->host, sp->port, pinginact);
@@ -256,6 +274,14 @@ main(int argc, char **argv) {
oldselected.history = selected.history;
oldselected.name = selected.name;
+ if (uineedredraw) {
+ uineedredraw = 0;
+ ui_redraw();
+ for (i=0; i < Win_last; i++)
+ windows[i].redraw = 0;
+ continue;
+ }
+
refreshed = inputrefreshed = 0;
for (i=0; i < Win_last; i++) {
if (windows[i].redraw) {
diff --git a/nick.c b/nick.c
@@ -10,13 +10,20 @@
#define MAXA(array) MAX(array[0], array[1])
#define MINA(array) MIN(array[0], array[1])
-unsigned short
+short
nick_getcolour(char *nick) {
unsigned short ret, sum;
int i;
+ long range[2];
- if (othercolour[0] == othercolour[1])
- return othercolour[0];
+ config_getr("nickcolour.range", &range[0], &range[1]);
+
+ if (range[0] < 0 || range[0] > 99 ||
+ range[1] < 0 || range[1] > 99)
+ return -1;
+
+ if (range[0] == range[1])
+ return range[0];
for (sum=i=0; nick && *nick; nick++, i++) {
/* don't count certain trailing characters. The following:
@@ -31,7 +38,7 @@ nick_getcolour(char *nick) {
sum ^= *nick;
}
- return (sum % (MAXA(othercolour) - MINA(othercolour)) + MINA(othercolour) - 1);
+ return (sum % (MAXA(range) - MINA(range)) + MINA(range) - 1);
}
void
diff --git a/serv.c b/serv.c
@@ -63,8 +63,8 @@ serv_create(char *name, char *host, char *port, char *nick,
server->host = estrdup(host);
server->port = estrdup(port);
server->supports = NULL;
- support_set(server, "CHANTYPES", default_chantypes);
- support_set(server, "PREFIX", default_prefixes);
+ support_set(server, "CHANTYPES", config_gets("def.chantypes"));
+ support_set(server, "PREFIX", config_gets("def.prefixes"));
server->self = nick_create(nick, ' ', NULL);
server->self->self = 1;
server->history = emalloc(sizeof(struct HistInfo));
@@ -229,8 +229,8 @@ serv_connect(struct Server *server) {
return;
fail:
- serv_disconnect(server, 1);
- if (server->connectfail * reconnectinterval < maxreconnectinterval)
+ serv_disconnect(server, 1, "Eead Rrror");
+ if (server->connectfail * config_getl("reconnect.interval") < config_getl("reconnect.maxinterval"))
server->connectfail += 1;
freeaddrinfo(ai);
}
diff --git a/struct.h b/struct.h
@@ -130,16 +130,26 @@ struct CommandOpts {
int ret;
};
-struct Netconfig {
+enum Valtype {
+ Val_string,
+ Val_bool,
+ Val_signed,
+ Val_unsigned,
+ Val_nzunsigned,
+ Val_range,
+};
+
+struct Config {
char *name;
- char *host;
- char *port;
- char *nick;
- char *user;
- char *real;
- char *join[64];
- int tls;
- int tls_verify;
+ int isdef;
+ enum Valtype valtype;
+ char *description;
+ char *str;
+ long num;
+ long range[2];
+ int (*strhandle)(char *string);
+ int (*numhandle)(long num);
+ int (*rangehandle)(long a, long b);
};
enum WindowLocation {
diff --git a/ui.c b/ui.c
@@ -10,6 +10,29 @@
#endif /* TLS */
#include "hirc.h"
+int uineedredraw = 0;
+
+#define HIRC_COLOURS 100
+static unsigned short colourmap[HIRC_COLOURS] = {
+ /* original 16 mirc colours
+ * some clients use the first 16 ansi colours for this,
+ * but here I use the 256 colours to ensure terminal-agnosticism */
+ [0] = 255, 16, 19, 46, 124, 88, 127, 184,
+ [8] = 208, 46, 45, 51, 21, 201, 240, 255,
+
+ /* extended */
+ [16] = 52, 94, 100, 58, 22, 29, 23, 24, 17, 54, 53, 89,
+ [28] = 88, 130, 142, 64, 28, 35, 30, 25, 18, 91, 90, 125,
+ [40] = 124, 166, 184, 106, 34, 49, 37, 33, 19, 129, 127, 161,
+ [52] = 196, 208, 226, 154, 46, 86, 51, 75, 21, 171, 201, 198,
+ [64] = 203, 215, 227, 191, 83, 122, 87, 111, 63, 177, 207, 205,
+ [76] = 217, 223, 229, 193, 157, 158, 159, 153, 147, 183, 219, 212,
+ [88] = 16, 233, 235, 237, 239, 241, 244, 247, 250, 254, 231,
+
+ /* transparency */
+ [99] = -1
+};
+
struct Window windows[Win_last] = {
[Win_main] = {.handler = ui_draw_main},
[Win_input] = {.handler = ui_draw_input},
@@ -72,14 +95,8 @@ ui_init(void) {
memset(input.string, '\0', sizeof(input.string));
input.counter = 0;
- if (nicklistlocation != 0 && nicklistlocation == buflistlocation) {
- ui_error("nicklist and buflist can't be set to same location in config.h", NULL);
- windows[Win_buflist].location = LEFT;
- windows[Win_nicklist].location = RIGHT;
- } else {
- windows[Win_buflist].location = buflistlocation;
- windows[Win_nicklist].location = nicklistlocation;
- }
+ windows[Win_nicklist].location = config_getl("nicklist.location");
+ windows[Win_buflist].location = config_getl("buflist.location");
windows[Win_main].window = newwin(0, 0, 0, 0);
windows[Win_input].window = newwin(0, 0, 0, 0);
@@ -152,8 +169,8 @@ ui_read(void) {
needredraw = 0;
}
return;
- case KEY_RESIZE:
- ui_redraw();
+ case KEY_RESIZE:
+ ui_redraw();
return;
case KEY_BACKSPACE:
if (input.counter) {
@@ -239,9 +256,14 @@ ui_input_delete(int num, int counter) {
void
ui_redraw(void) {
+ long nicklistwidth, buflistwidth;
int x = 0, rx = 0;
int i;
+ nicklistwidth = config_getl("nicklist.width");
+ buflistwidth = config_getl("buflist.width");
+
+ /* TODO: what if nicklistwidth or buflistwidth is too big? */
if (windows[Win_buflist].location == LEFT) {
windows[Win_buflist].x = windows[Win_buflist].y = 0;
windows[Win_buflist].h = LINES;