Switch to cache interfaces
parent
c0be6fe4b2
commit
14a6486b9b
1
Makefile
1
Makefile
|
@ -16,7 +16,6 @@ OBJS += buffer.o
|
||||||
OBJS += cache.o
|
OBJS += cache.o
|
||||||
OBJS += chat.o
|
OBJS += chat.o
|
||||||
OBJS += command.o
|
OBJS += command.o
|
||||||
OBJS += complete.o
|
|
||||||
OBJS += config.o
|
OBJS += config.o
|
||||||
OBJS += edit.o
|
OBJS += edit.o
|
||||||
OBJS += filter.o
|
OBJS += filter.o
|
||||||
|
|
14
README.7
14
README.7
|
@ -1,5 +1,5 @@
|
||||||
.\" To view this file, run: man ./README.7
|
.\" To view this file: $ man ./README.7
|
||||||
.Dd March 31, 2022
|
.Dd July 30, 2022
|
||||||
.Dt README 7
|
.Dt README 7
|
||||||
.Os "Causal Agency"
|
.Os "Causal Agency"
|
||||||
.
|
.
|
||||||
|
@ -9,7 +9,7 @@
|
||||||
.
|
.
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Xr catgirl 1
|
.Xr catgirl 1
|
||||||
is a TLS-only terminal IRC client.
|
is a terminal IRC client.
|
||||||
.
|
.
|
||||||
.Pp
|
.Pp
|
||||||
Screenshot:
|
Screenshot:
|
||||||
|
@ -180,7 +180,7 @@ $ make -C scripts sandman
|
||||||
.Ed
|
.Ed
|
||||||
.
|
.
|
||||||
.Sh FILES
|
.Sh FILES
|
||||||
.Bl -tag -width "complete.c" -compact
|
.Bl -tag -width "command.c" -compact
|
||||||
.It Pa chat.h
|
.It Pa chat.h
|
||||||
global state and declarations
|
global state and declarations
|
||||||
.It Pa chat.c
|
.It Pa chat.c
|
||||||
|
@ -201,8 +201,8 @@ command handling
|
||||||
line wrapping
|
line wrapping
|
||||||
.It Pa edit.c
|
.It Pa edit.c
|
||||||
line editing
|
line editing
|
||||||
.It Pa complete.c
|
.It Pa cache.c
|
||||||
tab complete
|
ordered cache
|
||||||
.It Pa url.c
|
.It Pa url.c
|
||||||
URL detection
|
URL detection
|
||||||
.It Pa filter.c
|
.It Pa filter.c
|
||||||
|
@ -270,4 +270,4 @@ IRC bouncer:
|
||||||
.%D June 19, 2020
|
.%D June 19, 2020
|
||||||
.Re
|
.Re
|
||||||
.
|
.
|
||||||
.\" To view this file, run: man ./README.7
|
.\" To view this file: $ man ./README.7
|
||||||
|
|
2
chat.c
2
chat.c
|
@ -374,7 +374,7 @@ int main(int argc, char *argv[]) {
|
||||||
set(&network.name, host);
|
set(&network.name, host);
|
||||||
set(&self.nick, "*");
|
set(&self.nick, "*");
|
||||||
|
|
||||||
inputCompleteAdd();
|
inputCache();
|
||||||
|
|
||||||
ircConfig(insecure, trust, cert, priv);
|
ircConfig(insecure, trust, cert, priv);
|
||||||
|
|
||||||
|
|
16
chat.h
16
chat.h
|
@ -292,7 +292,7 @@ const char *commandIsPrivmsg(uint id, const char *input);
|
||||||
const char *commandIsNotice(uint id, const char *input);
|
const char *commandIsNotice(uint id, const char *input);
|
||||||
const char *commandIsAction(uint id, const char *input);
|
const char *commandIsAction(uint id, const char *input);
|
||||||
size_t commandWillSplit(uint id, const char *input);
|
size_t commandWillSplit(uint id, const char *input);
|
||||||
void commandCompleteAdd(void);
|
void commandCache(void);
|
||||||
|
|
||||||
enum Heat {
|
enum Heat {
|
||||||
Ice,
|
Ice,
|
||||||
|
@ -334,7 +334,7 @@ void inputWait(void);
|
||||||
void inputUpdate(void);
|
void inputUpdate(void);
|
||||||
bool inputPending(uint id);
|
bool inputPending(uint id);
|
||||||
void inputRead(void);
|
void inputRead(void);
|
||||||
void inputCompleteAdd(void);
|
void inputCache(void);
|
||||||
int inputSave(FILE *file);
|
int inputSave(FILE *file);
|
||||||
void inputLoad(FILE *file, size_t version);
|
void inputLoad(FILE *file, size_t version);
|
||||||
|
|
||||||
|
@ -412,18 +412,6 @@ void cacheReject(struct Cursor *curs);
|
||||||
void cacheRemove(uint id, const char *key);
|
void cacheRemove(uint id, const char *key);
|
||||||
void cacheClear(uint id);
|
void cacheClear(uint id);
|
||||||
|
|
||||||
const char *complete(uint id, const char *prefix);
|
|
||||||
const char *completeSubstr(uint id, const char *substr);
|
|
||||||
void completeAccept(void);
|
|
||||||
void completeReject(void);
|
|
||||||
void completeAdd(uint id, const char *str, enum Color color);
|
|
||||||
void completeTouch(uint id, const char *str, enum Color color);
|
|
||||||
void completeReplace(uint id, const char *old, const char *new);
|
|
||||||
void completeRemove(uint id, const char *str);
|
|
||||||
void completeClear(uint id);
|
|
||||||
uint completeID(const char *str);
|
|
||||||
enum Color completeColor(uint id, const char *str);
|
|
||||||
|
|
||||||
extern struct Util urlOpenUtil;
|
extern struct Util urlOpenUtil;
|
||||||
extern struct Util urlCopyUtil;
|
extern struct Util urlCopyUtil;
|
||||||
void urlScan(uint id, const char *nick, const char *mesg);
|
void urlScan(uint id, const char *nick, const char *mesg);
|
||||||
|
|
19
command.c
19
command.c
|
@ -139,7 +139,7 @@ static void commandMsg(uint id, char *params) {
|
||||||
char *nick = strsep(¶ms, " ");
|
char *nick = strsep(¶ms, " ");
|
||||||
uint msg = idFor(nick);
|
uint msg = idFor(nick);
|
||||||
if (idColors[msg] == Default) {
|
if (idColors[msg] == Default) {
|
||||||
idColors[msg] = completeColor(id, nick);
|
idColors[msg] = cacheColor(id, nick);
|
||||||
}
|
}
|
||||||
if (params) {
|
if (params) {
|
||||||
splitMessage("PRIVMSG", msg, params);
|
splitMessage("PRIVMSG", msg, params);
|
||||||
|
@ -380,7 +380,7 @@ static void commandQuery(uint id, char *params) {
|
||||||
if (!params) return;
|
if (!params) return;
|
||||||
uint query = idFor(params);
|
uint query = idFor(params);
|
||||||
if (idColors[query] == Default) {
|
if (idColors[query] == Default) {
|
||||||
idColors[query] = completeColor(id, params);
|
idColors[query] = cacheColor(id, params);
|
||||||
}
|
}
|
||||||
windowShow(windowFor(query));
|
windowShow(windowFor(query));
|
||||||
}
|
}
|
||||||
|
@ -396,10 +396,11 @@ static void commandWindow(uint id, char *params) {
|
||||||
windowShow(windowFor(id));
|
windowShow(windowFor(id));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (const char *match; (match = completeSubstr(None, params));) {
|
struct Cursor curs = {0};
|
||||||
|
for (const char *match; (match = cacheSubstr(&curs, None, params));) {
|
||||||
id = idFind(match);
|
id = idFind(match);
|
||||||
if (!id) continue;
|
if (!id) continue;
|
||||||
completeAccept();
|
cacheAccept(&curs);
|
||||||
windowShow(windowFor(id));
|
windowShow(windowFor(id));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -669,11 +670,11 @@ void command(uint id, char *input) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Cursor curs = {0};
|
||||||
const char *cmd = strsep(&input, " ");
|
const char *cmd = strsep(&input, " ");
|
||||||
const char *unique = complete(None, cmd);
|
const char *unique = cachePrefix(&curs, None, cmd);
|
||||||
if (unique && !complete(None, cmd)) {
|
if (unique && !cachePrefix(&curs, None, cmd)) {
|
||||||
cmd = unique;
|
cmd = unique;
|
||||||
completeReject();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct Handler *handler = bsearch(
|
const struct Handler *handler = bsearch(
|
||||||
|
@ -700,9 +701,9 @@ void command(uint id, char *input) {
|
||||||
handler->fn(id, input);
|
handler->fn(id, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
void commandCompleteAdd(void) {
|
void commandCache(void) {
|
||||||
for (size_t i = 0; i < ARRAY_LEN(Commands); ++i) {
|
for (size_t i = 0; i < ARRAY_LEN(Commands); ++i) {
|
||||||
if (!commandAvailable(&Commands[i])) continue;
|
if (!commandAvailable(&Commands[i])) continue;
|
||||||
completeAdd(None, Commands[i].cmd, Default);
|
cacheInsert(false, None, Commands[i].cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
187
complete.c
187
complete.c
|
@ -1,187 +0,0 @@
|
||||||
/* Copyright (C) 2020 June McEnroe <june@causal.agency>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Additional permission under GNU GPL version 3 section 7:
|
|
||||||
*
|
|
||||||
* If you modify this Program, or any covered work, by linking or
|
|
||||||
* combining it with OpenSSL (or a modified version of that library),
|
|
||||||
* containing parts covered by the terms of the OpenSSL License and the
|
|
||||||
* original SSLeay license, the licensors of this Program grant you
|
|
||||||
* additional permission to convey the resulting work. Corresponding
|
|
||||||
* Source for a non-source form of such a combination shall include the
|
|
||||||
* source code for the parts of OpenSSL used as well as that of the
|
|
||||||
* covered work.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <err.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sysexits.h>
|
|
||||||
|
|
||||||
#include "chat.h"
|
|
||||||
|
|
||||||
struct Node {
|
|
||||||
uint id;
|
|
||||||
char *str;
|
|
||||||
enum Color color;
|
|
||||||
struct Node *prev;
|
|
||||||
struct Node *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct Node *alloc(uint id, const char *str, enum Color color) {
|
|
||||||
struct Node *node = malloc(sizeof(*node));
|
|
||||||
if (!node) err(EX_OSERR, "malloc");
|
|
||||||
node->id = id;
|
|
||||||
node->str = strdup(str);
|
|
||||||
node->color = color;
|
|
||||||
node->prev = NULL;
|
|
||||||
node->next = NULL;
|
|
||||||
if (!node->str) err(EX_OSERR, "strdup");
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct Node *head;
|
|
||||||
static struct Node *tail;
|
|
||||||
|
|
||||||
static struct Node *detach(struct Node *node) {
|
|
||||||
if (node->prev) node->prev->next = node->next;
|
|
||||||
if (node->next) node->next->prev = node->prev;
|
|
||||||
if (head == node) head = node->next;
|
|
||||||
if (tail == node) tail = node->prev;
|
|
||||||
node->prev = NULL;
|
|
||||||
node->next = NULL;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct Node *prepend(struct Node *node) {
|
|
||||||
node->prev = NULL;
|
|
||||||
node->next = head;
|
|
||||||
if (head) head->prev = node;
|
|
||||||
head = node;
|
|
||||||
tail = (tail ?: node);
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct Node *append(struct Node *node) {
|
|
||||||
node->next = NULL;
|
|
||||||
node->prev = tail;
|
|
||||||
if (tail) tail->next = node;
|
|
||||||
tail = node;
|
|
||||||
head = (head ?: node);
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct Node *find(uint id, const char *str) {
|
|
||||||
for (struct Node *node = head; node; node = node->next) {
|
|
||||||
if (node->id != id) continue;
|
|
||||||
if (strcmp(node->str, str)) continue;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void completeAdd(uint id, const char *str, enum Color color) {
|
|
||||||
if (!find(id, str)) append(alloc(id, str, color));
|
|
||||||
}
|
|
||||||
|
|
||||||
void completeTouch(uint id, const char *str, enum Color color) {
|
|
||||||
struct Node *node = find(id, str);
|
|
||||||
if (node) node->color = color;
|
|
||||||
prepend(node ? detach(node) : alloc(id, str, color));
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Color completeColor(uint id, const char *str) {
|
|
||||||
struct Node *node = find(id, str);
|
|
||||||
return (node ? node->color : Default);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct Node *match;
|
|
||||||
|
|
||||||
const char *complete(uint id, const char *prefix) {
|
|
||||||
for (match = (match ? match->next : head); match; match = match->next) {
|
|
||||||
if (match->id && match->id != id) continue;
|
|
||||||
if (strncasecmp(match->str, prefix, strlen(prefix))) continue;
|
|
||||||
return match->str;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *completeSubstr(uint id, const char *substr) {
|
|
||||||
for (match = (match ? match->next : head); match; match = match->next) {
|
|
||||||
if (match->id && match->id != id) continue;
|
|
||||||
if (!strstr(match->str, substr)) continue;
|
|
||||||
return match->str;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void completeAccept(void) {
|
|
||||||
if (match) prepend(detach(match));
|
|
||||||
match = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void completeReject(void) {
|
|
||||||
match = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct Node *iter;
|
|
||||||
|
|
||||||
uint completeID(const char *str) {
|
|
||||||
for (iter = (iter ? iter->next : head); iter; iter = iter->next) {
|
|
||||||
if (iter->id && !strcmp(iter->str, str)) return iter->id;
|
|
||||||
}
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
void completeReplace(uint id, const char *old, const char *new) {
|
|
||||||
struct Node *next = NULL;
|
|
||||||
for (struct Node *node = head; node; node = next) {
|
|
||||||
next = node->next;
|
|
||||||
if (id && node->id != id) continue;
|
|
||||||
if (strcmp(node->str, old)) continue;
|
|
||||||
free(node->str);
|
|
||||||
node->str = strdup(new);
|
|
||||||
prepend(detach(node));
|
|
||||||
if (!node->str) err(EX_OSERR, "strdup");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void completeRemove(uint id, const char *str) {
|
|
||||||
struct Node *next = NULL;
|
|
||||||
for (struct Node *node = head; node; node = next) {
|
|
||||||
next = node->next;
|
|
||||||
if (id && node->id != id) continue;
|
|
||||||
if (strcmp(node->str, str)) continue;
|
|
||||||
if (match == node) match = NULL;
|
|
||||||
if (iter == node) iter = NULL;
|
|
||||||
detach(node);
|
|
||||||
free(node->str);
|
|
||||||
free(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void completeClear(uint id) {
|
|
||||||
struct Node *next = NULL;
|
|
||||||
for (struct Node *node = head; node; node = next) {
|
|
||||||
next = node->next;
|
|
||||||
if (node->id != id) continue;
|
|
||||||
if (match == node) match = NULL;
|
|
||||||
if (iter == node) iter = NULL;
|
|
||||||
detach(node);
|
|
||||||
free(node->str);
|
|
||||||
free(node);
|
|
||||||
}
|
|
||||||
}
|
|
86
handle.c
86
handle.c
|
@ -266,7 +266,7 @@ static void handleErrorSASLFail(struct Message *msg) {
|
||||||
static void handleReplyWelcome(struct Message *msg) {
|
static void handleReplyWelcome(struct Message *msg) {
|
||||||
require(msg, false, 1);
|
require(msg, false, 1);
|
||||||
set(&self.nick, msg->params[0]);
|
set(&self.nick, msg->params[0]);
|
||||||
completeTouch(Network, self.nick, Default);
|
cacheInsert(true, Network, self.nick);
|
||||||
if (self.mode) ircFormat("MODE %s %s\r\n", self.nick, self.mode);
|
if (self.mode) ircFormat("MODE %s %s\r\n", self.nick, self.mode);
|
||||||
if (self.join) {
|
if (self.join) {
|
||||||
uint count = 1;
|
uint count = 1;
|
||||||
|
@ -278,7 +278,7 @@ static void handleReplyWelcome(struct Message *msg) {
|
||||||
replies[ReplyTopicAuto] += count;
|
replies[ReplyTopicAuto] += count;
|
||||||
replies[ReplyNamesAuto] += count;
|
replies[ReplyNamesAuto] += count;
|
||||||
}
|
}
|
||||||
commandCompleteAdd();
|
commandCache();
|
||||||
handleReplyGeneric(msg);
|
handleReplyGeneric(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,13 +372,13 @@ static void handleJoin(struct Message *msg) {
|
||||||
set(&self.host, msg->host);
|
set(&self.host, msg->host);
|
||||||
}
|
}
|
||||||
idColors[id] = hash(msg->params[0]);
|
idColors[id] = hash(msg->params[0]);
|
||||||
completeTouch(None, msg->params[0], idColors[id]);
|
cacheInsertColor(true, None, msg->params[0], idColors[id]);
|
||||||
if (replies[ReplyJoin]) {
|
if (replies[ReplyJoin]) {
|
||||||
windowShow(windowFor(id));
|
windowShow(windowFor(id));
|
||||||
replies[ReplyJoin]--;
|
replies[ReplyJoin]--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
completeTouch(id, msg->nick, hash(msg->user));
|
cacheInsertColor(true, id, msg->nick, hash(msg->user));
|
||||||
if (msg->params[2] && !strcasecmp(msg->params[2], msg->nick)) {
|
if (msg->params[2] && !strcasecmp(msg->params[2], msg->nick)) {
|
||||||
msg->params[2] = NULL;
|
msg->params[2] = NULL;
|
||||||
}
|
}
|
||||||
|
@ -410,9 +410,9 @@ static void handlePart(struct Message *msg) {
|
||||||
require(msg, true, 1);
|
require(msg, true, 1);
|
||||||
uint id = idFor(msg->params[0]);
|
uint id = idFor(msg->params[0]);
|
||||||
if (!strcmp(msg->nick, self.nick)) {
|
if (!strcmp(msg->nick, self.nick)) {
|
||||||
completeClear(id);
|
cacheClear(id);
|
||||||
}
|
}
|
||||||
completeRemove(id, msg->nick);
|
cacheRemove(id, msg->nick);
|
||||||
enum Heat heat = filterCheck(Cold, id, msg);
|
enum Heat heat = filterCheck(Cold, id, msg);
|
||||||
if (heat > Ice) urlScan(id, msg->nick, msg->params[1]);
|
if (heat > Ice) urlScan(id, msg->nick, msg->params[1]);
|
||||||
uiFormat(
|
uiFormat(
|
||||||
|
@ -432,14 +432,14 @@ static void handleKick(struct Message *msg) {
|
||||||
require(msg, true, 2);
|
require(msg, true, 2);
|
||||||
uint id = idFor(msg->params[0]);
|
uint id = idFor(msg->params[0]);
|
||||||
bool kicked = !strcmp(msg->params[1], self.nick);
|
bool kicked = !strcmp(msg->params[1], self.nick);
|
||||||
completeTouch(id, msg->nick, hash(msg->user));
|
cacheInsertColor(true, id, msg->nick, hash(msg->user));
|
||||||
urlScan(id, msg->nick, msg->params[2]);
|
urlScan(id, msg->nick, msg->params[2]);
|
||||||
uiFormat(
|
uiFormat(
|
||||||
id, (kicked ? Hot : Cold), tagTime(msg),
|
id, (kicked ? Hot : Cold), tagTime(msg),
|
||||||
"%s\3%02d%s\17\tkicks \3%02d%s\3 out of \3%02d%s\3%s%s",
|
"%s\3%02d%s\17\tkicks \3%02d%s\3 out of \3%02d%s\3%s%s",
|
||||||
(kicked ? "\26" : ""),
|
(kicked ? "\26" : ""),
|
||||||
hash(msg->user), msg->nick,
|
hash(msg->user), msg->nick,
|
||||||
completeColor(id, msg->params[1]), msg->params[1],
|
cacheColor(id, msg->params[1]), msg->params[1],
|
||||||
hash(msg->params[0]), msg->params[0],
|
hash(msg->params[0]), msg->params[0],
|
||||||
(msg->params[2] ? ": " : ""), (msg->params[2] ?: "")
|
(msg->params[2] ? ": " : ""), (msg->params[2] ?: "")
|
||||||
);
|
);
|
||||||
|
@ -448,8 +448,8 @@ static void handleKick(struct Message *msg) {
|
||||||
msg->nick, msg->params[1], msg->params[0],
|
msg->nick, msg->params[1], msg->params[0],
|
||||||
(msg->params[2] ? ": " : ""), (msg->params[2] ?: "")
|
(msg->params[2] ? ": " : ""), (msg->params[2] ?: "")
|
||||||
);
|
);
|
||||||
completeRemove(id, msg->params[1]);
|
cacheRemove(id, msg->params[1]);
|
||||||
if (kicked) completeClear(id);
|
if (kicked) cacheClear(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleNick(struct Message *msg) {
|
static void handleNick(struct Message *msg) {
|
||||||
|
@ -458,7 +458,8 @@ static void handleNick(struct Message *msg) {
|
||||||
set(&self.nick, msg->params[0]);
|
set(&self.nick, msg->params[0]);
|
||||||
inputUpdate();
|
inputUpdate();
|
||||||
}
|
}
|
||||||
for (uint id; (id = completeID(msg->nick));) {
|
struct Cursor curs = {0};
|
||||||
|
for (uint id; (id = cacheID(&curs, msg->nick));) {
|
||||||
if (!strcmp(idNames[id], msg->nick)) {
|
if (!strcmp(idNames[id], msg->nick)) {
|
||||||
set(&idNames[id], msg->params[0]);
|
set(&idNames[id], msg->params[0]);
|
||||||
}
|
}
|
||||||
|
@ -473,12 +474,13 @@ static void handleNick(struct Message *msg) {
|
||||||
msg->nick, msg->params[0]
|
msg->nick, msg->params[0]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
completeReplace(None, msg->nick, msg->params[0]);
|
cacheReplace(true, msg->nick, msg->params[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleSetname(struct Message *msg) {
|
static void handleSetname(struct Message *msg) {
|
||||||
require(msg, true, 1);
|
require(msg, true, 1);
|
||||||
for (uint id; (id = completeID(msg->nick));) {
|
struct Cursor curs = {0};
|
||||||
|
for (uint id; (id = cacheID(&curs, msg->nick));) {
|
||||||
uiFormat(
|
uiFormat(
|
||||||
id, filterCheck(Cold, id, msg), tagTime(msg),
|
id, filterCheck(Cold, id, msg), tagTime(msg),
|
||||||
"\3%02d%s\3\tis now known as \3%02d%s\3 (%s\17)",
|
"\3%02d%s\3\tis now known as \3%02d%s\3 (%s\17)",
|
||||||
|
@ -490,7 +492,8 @@ static void handleSetname(struct Message *msg) {
|
||||||
|
|
||||||
static void handleQuit(struct Message *msg) {
|
static void handleQuit(struct Message *msg) {
|
||||||
require(msg, true, 0);
|
require(msg, true, 0);
|
||||||
for (uint id; (id = completeID(msg->nick));) {
|
struct Cursor curs = {0};
|
||||||
|
for (uint id; (id = cacheID(&curs, msg->nick));) {
|
||||||
enum Heat heat = filterCheck(Cold, id, msg);
|
enum Heat heat = filterCheck(Cold, id, msg);
|
||||||
if (heat > Ice) urlScan(id, msg->nick, msg->params[0]);
|
if (heat > Ice) urlScan(id, msg->nick, msg->params[0]);
|
||||||
uiFormat(
|
uiFormat(
|
||||||
|
@ -506,7 +509,7 @@ static void handleQuit(struct Message *msg) {
|
||||||
(msg->params[0] ? ": " : ""), (msg->params[0] ?: "")
|
(msg->params[0] ? ": " : ""), (msg->params[0] ?: "")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
completeRemove(None, msg->nick);
|
cacheRemove(None, msg->nick);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleInvite(struct Message *msg) {
|
static void handleInvite(struct Message *msg) {
|
||||||
|
@ -552,7 +555,7 @@ static void handleErrorUserOnChannel(struct Message *msg) {
|
||||||
uiFormat(
|
uiFormat(
|
||||||
id, Warm, tagTime(msg),
|
id, Warm, tagTime(msg),
|
||||||
"\3%02d%s\3 is already in \3%02d%s\3",
|
"\3%02d%s\3 is already in \3%02d%s\3",
|
||||||
completeColor(id, msg->params[1]), msg->params[1],
|
cacheColor(id, msg->params[1]), msg->params[1],
|
||||||
hash(msg->params[2]), msg->params[2]
|
hash(msg->params[2]), msg->params[2]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -568,7 +571,7 @@ static void handleReplyNames(struct Message *msg) {
|
||||||
char *nick = &prefixes[strspn(prefixes, network.prefixes)];
|
char *nick = &prefixes[strspn(prefixes, network.prefixes)];
|
||||||
char *user = strsep(&name, "@");
|
char *user = strsep(&name, "@");
|
||||||
enum Color color = (user ? hash(user) : Default);
|
enum Color color = (user ? hash(user) : Default);
|
||||||
completeAdd(id, nick, color);
|
cacheInsertColor(false, id, nick, color);
|
||||||
if (!replies[ReplyNames] && !replies[ReplyNamesAuto]) continue;
|
if (!replies[ReplyNames] && !replies[ReplyNamesAuto]) continue;
|
||||||
ptr = seprintf(
|
ptr = seprintf(
|
||||||
ptr, end, "%s\3%02d%s\3", (ptr > buf ? ", " : ""), color, prefixes
|
ptr, end, "%s\3%02d%s\3", (ptr > buf ? ", " : ""), color, prefixes
|
||||||
|
@ -635,23 +638,24 @@ static void handleReplyNoTopic(struct Message *msg) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void topicComplete(uint id, const char *topic) {
|
static void topicCache(uint id, const char *topic) {
|
||||||
char buf[512];
|
char buf[512];
|
||||||
const char *prev = complete(id, "/topic ");
|
struct Cursor curs = {0};
|
||||||
|
const char *prev = cachePrefix(&curs, id, "/topic ");
|
||||||
if (prev) {
|
if (prev) {
|
||||||
snprintf(buf, sizeof(buf), "%s", prev);
|
snprintf(buf, sizeof(buf), "%s", prev);
|
||||||
completeRemove(id, buf);
|
cacheRemove(id, buf);
|
||||||
}
|
}
|
||||||
if (topic) {
|
if (topic) {
|
||||||
snprintf(buf, sizeof(buf), "/topic %s", topic);
|
snprintf(buf, sizeof(buf), "/topic %s", topic);
|
||||||
completeAdd(id, buf, Default);
|
cacheInsert(false, id, buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleReplyTopic(struct Message *msg) {
|
static void handleReplyTopic(struct Message *msg) {
|
||||||
require(msg, false, 3);
|
require(msg, false, 3);
|
||||||
uint id = idFor(msg->params[1]);
|
uint id = idFor(msg->params[1]);
|
||||||
topicComplete(id, msg->params[2]);
|
topicCache(id, msg->params[2]);
|
||||||
if (!replies[ReplyTopic] && !replies[ReplyTopicAuto]) return;
|
if (!replies[ReplyTopic] && !replies[ReplyTopicAuto]) return;
|
||||||
urlScan(id, NULL, msg->params[2]);
|
urlScan(id, NULL, msg->params[2]);
|
||||||
uiFormat(
|
uiFormat(
|
||||||
|
@ -702,7 +706,7 @@ static void handleTopic(struct Message *msg) {
|
||||||
require(msg, true, 2);
|
require(msg, true, 2);
|
||||||
uint id = idFor(msg->params[0]);
|
uint id = idFor(msg->params[0]);
|
||||||
if (!msg->params[1][0]) {
|
if (!msg->params[1][0]) {
|
||||||
topicComplete(id, NULL);
|
topicCache(id, NULL);
|
||||||
uiFormat(
|
uiFormat(
|
||||||
id, Warm, tagTime(msg),
|
id, Warm, tagTime(msg),
|
||||||
"\3%02d%s\3\tremoves the sign in \3%02d%s\3",
|
"\3%02d%s\3\tremoves the sign in \3%02d%s\3",
|
||||||
|
@ -715,8 +719,8 @@ static void handleTopic(struct Message *msg) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *prev = complete(id, "/topic ");
|
struct Cursor curs = {0};
|
||||||
completeReject();
|
const char *prev = cachePrefix(&curs, id, "/topic ");
|
||||||
if (prev) {
|
if (prev) {
|
||||||
prev += 7;
|
prev += 7;
|
||||||
} else {
|
} else {
|
||||||
|
@ -766,7 +770,7 @@ log:
|
||||||
id, tagTime(msg), "%s places a new sign in %s: %s",
|
id, tagTime(msg), "%s places a new sign in %s: %s",
|
||||||
msg->nick, msg->params[0], msg->params[1]
|
msg->nick, msg->params[0], msg->params[1]
|
||||||
);
|
);
|
||||||
topicComplete(id, msg->params[1]);
|
topicCache(id, msg->params[1]);
|
||||||
urlScan(id, msg->nick, msg->params[1]);
|
urlScan(id, msg->nick, msg->params[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -893,7 +897,7 @@ static void handleMode(struct Message *msg) {
|
||||||
id, Cold, tagTime(msg),
|
id, Cold, tagTime(msg),
|
||||||
"\3%02d%s\3\t%s \3%02d%c%s\3 %s%s in \3%02d%s\3",
|
"\3%02d%s\3\t%s \3%02d%c%s\3 %s%s in \3%02d%s\3",
|
||||||
hash(msg->user), msg->nick, verb,
|
hash(msg->user), msg->nick, verb,
|
||||||
completeColor(id, nick), prefix, nick,
|
cacheColor(id, nick), prefix, nick,
|
||||||
mode, name, hash(msg->params[0]), msg->params[0]
|
mode, name, hash(msg->params[0]), msg->params[0]
|
||||||
);
|
);
|
||||||
logFormat(
|
logFormat(
|
||||||
|
@ -1031,7 +1035,7 @@ static void handleReplyBanList(struct Message *msg) {
|
||||||
id, Warm, tagTime(msg),
|
id, Warm, tagTime(msg),
|
||||||
"Banned from \3%02d%s\3 since %s by \3%02d%s\3: %s",
|
"Banned from \3%02d%s\3 since %s by \3%02d%s\3: %s",
|
||||||
hash(msg->params[1]), msg->params[1],
|
hash(msg->params[1]), msg->params[1],
|
||||||
since, completeColor(id, msg->params[3]), msg->params[3],
|
since, cacheColor(id, msg->params[3]), msg->params[3],
|
||||||
msg->params[2]
|
msg->params[2]
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1054,7 +1058,7 @@ static void onList(const char *list, struct Message *msg) {
|
||||||
id, Warm, tagTime(msg),
|
id, Warm, tagTime(msg),
|
||||||
"On the \3%02d%s\3 %s list since %s by \3%02d%s\3: %s",
|
"On the \3%02d%s\3 %s list since %s by \3%02d%s\3: %s",
|
||||||
hash(msg->params[1]), msg->params[1], list,
|
hash(msg->params[1]), msg->params[1], list,
|
||||||
since, completeColor(id, msg->params[3]), msg->params[3],
|
since, cacheColor(id, msg->params[3]), msg->params[3],
|
||||||
msg->params[2]
|
msg->params[2]
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1087,7 +1091,7 @@ static void handleReplyList(struct Message *msg) {
|
||||||
|
|
||||||
static void handleReplyWhoisUser(struct Message *msg) {
|
static void handleReplyWhoisUser(struct Message *msg) {
|
||||||
require(msg, false, 6);
|
require(msg, false, 6);
|
||||||
completeTouch(Network, msg->params[1], hash(msg->params[2]));
|
cacheInsertColor(true, Network, msg->params[1], hash(msg->params[2]));
|
||||||
uiFormat(
|
uiFormat(
|
||||||
Network, Warm, tagTime(msg),
|
Network, Warm, tagTime(msg),
|
||||||
"\3%02d%s\3\tis %s!%s@%s (%s\17)",
|
"\3%02d%s\3\tis %s!%s@%s (%s\17)",
|
||||||
|
@ -1102,7 +1106,7 @@ static void handleReplyWhoisServer(struct Message *msg) {
|
||||||
uiFormat(
|
uiFormat(
|
||||||
Network, Warm, tagTime(msg),
|
Network, Warm, tagTime(msg),
|
||||||
"\3%02d%s\3\t%s connected to %s (%s)",
|
"\3%02d%s\3\t%s connected to %s (%s)",
|
||||||
completeColor(Network, msg->params[1]), msg->params[1],
|
cacheColor(Network, msg->params[1]), msg->params[1],
|
||||||
(replies[ReplyWhowas] ? "was" : "is"), msg->params[2], msg->params[3]
|
(replies[ReplyWhowas] ? "was" : "is"), msg->params[2], msg->params[3]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1126,7 +1130,7 @@ static void handleReplyWhoisIdle(struct Message *msg) {
|
||||||
uiFormat(
|
uiFormat(
|
||||||
Network, Warm, tagTime(msg),
|
Network, Warm, tagTime(msg),
|
||||||
"\3%02d%s\3\tis idle for %lu %s%s%s%s",
|
"\3%02d%s\3\tis idle for %lu %s%s%s%s",
|
||||||
completeColor(Network, msg->params[1]), msg->params[1],
|
cacheColor(Network, msg->params[1]), msg->params[1],
|
||||||
idle, unit, (idle != 1 ? "s" : ""),
|
idle, unit, (idle != 1 ? "s" : ""),
|
||||||
(msg->params[3] ? ", signed on " : ""), (msg->params[3] ? signon : "")
|
(msg->params[3] ? ", signed on " : ""), (msg->params[3] ? signon : "")
|
||||||
);
|
);
|
||||||
|
@ -1148,7 +1152,7 @@ static void handleReplyWhoisChannels(struct Message *msg) {
|
||||||
uiFormat(
|
uiFormat(
|
||||||
Network, Warm, tagTime(msg),
|
Network, Warm, tagTime(msg),
|
||||||
"\3%02d%s\3\tis in %s",
|
"\3%02d%s\3\tis in %s",
|
||||||
completeColor(Network, msg->params[1]), msg->params[1], buf
|
cacheColor(Network, msg->params[1]), msg->params[1], buf
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1162,7 +1166,7 @@ static void handleReplyWhoisGeneric(struct Message *msg) {
|
||||||
uiFormat(
|
uiFormat(
|
||||||
Network, Warm, tagTime(msg),
|
Network, Warm, tagTime(msg),
|
||||||
"\3%02d%s\3\t%s%s%s",
|
"\3%02d%s\3\t%s%s%s",
|
||||||
completeColor(Network, msg->params[1]), msg->params[1],
|
cacheColor(Network, msg->params[1]), msg->params[1],
|
||||||
msg->params[2], (msg->params[3] ? " " : ""), (msg->params[3] ?: "")
|
msg->params[2], (msg->params[3] ? " " : ""), (msg->params[3] ?: "")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1170,13 +1174,13 @@ static void handleReplyWhoisGeneric(struct Message *msg) {
|
||||||
static void handleReplyEndOfWhois(struct Message *msg) {
|
static void handleReplyEndOfWhois(struct Message *msg) {
|
||||||
require(msg, false, 2);
|
require(msg, false, 2);
|
||||||
if (strcmp(msg->params[1], self.nick)) {
|
if (strcmp(msg->params[1], self.nick)) {
|
||||||
completeRemove(Network, msg->params[1]);
|
cacheRemove(Network, msg->params[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleReplyWhowasUser(struct Message *msg) {
|
static void handleReplyWhowasUser(struct Message *msg) {
|
||||||
require(msg, false, 6);
|
require(msg, false, 6);
|
||||||
completeTouch(Network, msg->params[1], hash(msg->params[2]));
|
cacheInsertColor(true, Network, msg->params[1], hash(msg->params[2]));
|
||||||
uiFormat(
|
uiFormat(
|
||||||
Network, Warm, tagTime(msg),
|
Network, Warm, tagTime(msg),
|
||||||
"\3%02d%s\3\twas %s!%s@%s (%s)",
|
"\3%02d%s\3\twas %s!%s@%s (%s)",
|
||||||
|
@ -1188,7 +1192,7 @@ static void handleReplyWhowasUser(struct Message *msg) {
|
||||||
static void handleReplyEndOfWhowas(struct Message *msg) {
|
static void handleReplyEndOfWhowas(struct Message *msg) {
|
||||||
require(msg, false, 2);
|
require(msg, false, 2);
|
||||||
if (strcmp(msg->params[1], self.nick)) {
|
if (strcmp(msg->params[1], self.nick)) {
|
||||||
completeRemove(Network, msg->params[1]);
|
cacheRemove(Network, msg->params[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1196,7 +1200,7 @@ static void handleReplyAway(struct Message *msg) {
|
||||||
require(msg, false, 3);
|
require(msg, false, 3);
|
||||||
// Might be part of a WHOIS response.
|
// Might be part of a WHOIS response.
|
||||||
uint id;
|
uint id;
|
||||||
if (completeColor(Network, msg->params[1]) != Default) {
|
if (cacheColor(Network, msg->params[1]) != Default) {
|
||||||
id = Network;
|
id = Network;
|
||||||
} else {
|
} else {
|
||||||
id = idFor(msg->params[1]);
|
id = idFor(msg->params[1]);
|
||||||
|
@ -1204,7 +1208,7 @@ static void handleReplyAway(struct Message *msg) {
|
||||||
uiFormat(
|
uiFormat(
|
||||||
id, (id == Network ? Warm : Cold), tagTime(msg),
|
id, (id == Network ? Warm : Cold), tagTime(msg),
|
||||||
"\3%02d%s\3\tis away: %s",
|
"\3%02d%s\3\tis away: %s",
|
||||||
completeColor(id, msg->params[1]), msg->params[1], msg->params[2]
|
cacheColor(id, msg->params[1]), msg->params[1], msg->params[2]
|
||||||
);
|
);
|
||||||
logFormat(
|
logFormat(
|
||||||
id, tagTime(msg), "%s is away: %s",
|
id, tagTime(msg), "%s is away: %s",
|
||||||
|
@ -1275,7 +1279,7 @@ static char *colorMentions(char *ptr, char *end, uint id, const char *msg) {
|
||||||
|
|
||||||
size_t len = strcspn(msg, ",:<> ");
|
size_t len = strcspn(msg, ",:<> ");
|
||||||
char *p = seprintf(ptr, end, "%.*s", (int)len, msg);
|
char *p = seprintf(ptr, end, "%.*s", (int)len, msg);
|
||||||
enum Color color = completeColor(id, ptr);
|
enum Color color = cacheColor(id, ptr);
|
||||||
if (color != Default) {
|
if (color != Default) {
|
||||||
ptr = seprintf(ptr, end, "\3%02d%.*s\3", color, (int)len, msg);
|
ptr = seprintf(ptr, end, "\3%02d%.*s\3", color, (int)len, msg);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1315,7 +1319,7 @@ static void handlePrivmsg(struct Message *msg) {
|
||||||
heat = filterCheck(heat, id, msg);
|
heat = filterCheck(heat, id, msg);
|
||||||
if (heat > Warm && !mine && !query) highlight = true;
|
if (heat > Warm && !mine && !query) highlight = true;
|
||||||
if (!notice && !mine && heat > Ice) {
|
if (!notice && !mine && heat > Ice) {
|
||||||
completeTouch(id, msg->nick, hash(msg->user));
|
cacheInsertColor(true, id, msg->nick, hash(msg->user));
|
||||||
}
|
}
|
||||||
if (heat > Ice) urlScan(id, msg->nick, msg->params[1]);
|
if (heat > Ice) urlScan(id, msg->nick, msg->params[1]);
|
||||||
|
|
||||||
|
|
13
input.c
13
input.c
|
@ -261,12 +261,12 @@ static const struct {
|
||||||
{ L"\\wave", L"ヾ(^∇^)" },
|
{ L"\\wave", L"ヾ(^∇^)" },
|
||||||
};
|
};
|
||||||
|
|
||||||
void inputCompleteAdd(void) {
|
void inputCache(void) {
|
||||||
char mbs[256];
|
char mbs[256];
|
||||||
for (size_t i = 0; i < ARRAY_LEN(Macros); ++i) {
|
for (size_t i = 0; i < ARRAY_LEN(Macros); ++i) {
|
||||||
size_t n = wcstombs(mbs, Macros[i].name, sizeof(mbs));
|
size_t n = wcstombs(mbs, Macros[i].name, sizeof(mbs));
|
||||||
assert(n != (size_t)-1);
|
assert(n != (size_t)-1);
|
||||||
completeAdd(None, mbs, Default);
|
cacheInsert(false, None, mbs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,15 +296,16 @@ static struct {
|
||||||
size_t pos;
|
size_t pos;
|
||||||
size_t len;
|
size_t len;
|
||||||
bool suffix;
|
bool suffix;
|
||||||
|
struct Cursor curs;
|
||||||
} tab;
|
} tab;
|
||||||
|
|
||||||
static void tabAccept(void) {
|
static void tabAccept(void) {
|
||||||
completeAccept();
|
cacheAccept(&tab.curs);
|
||||||
tab.len = 0;
|
tab.len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tabReject(void) {
|
static void tabReject(void) {
|
||||||
completeReject();
|
cacheReject(&tab.curs);
|
||||||
tab.len = 0;
|
tab.len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,9 +333,9 @@ static int tabComplete(struct Edit *e, uint id) {
|
||||||
tab.suffix = true;
|
tab.suffix = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *comp = complete(id, tab.pre);
|
const char *comp = cachePrefix(&tab.curs, id, tab.pre);
|
||||||
if (!comp) {
|
if (!comp) {
|
||||||
comp = complete(id, tab.pre);
|
comp = cachePrefix(&tab.curs, id, tab.pre);
|
||||||
tab.suffix ^= true;
|
tab.suffix ^= true;
|
||||||
}
|
}
|
||||||
if (!comp) {
|
if (!comp) {
|
||||||
|
|
6
window.c
6
window.c
|
@ -93,7 +93,7 @@ static struct Window *windowRemove(uint num) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void windowFree(struct Window *window) {
|
static void windowFree(struct Window *window) {
|
||||||
completeRemove(None, idNames[window->id]);
|
cacheRemove(None, idNames[window->id]);
|
||||||
bufferFree(window->buffer);
|
bufferFree(window->buffer);
|
||||||
free(window);
|
free(window);
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,7 @@ uint windowFor(uint id) {
|
||||||
window->thresh = windowThreshold;
|
window->thresh = windowThreshold;
|
||||||
}
|
}
|
||||||
window->buffer = bufferAlloc();
|
window->buffer = bufferAlloc();
|
||||||
completeAdd(None, idNames[id], idColors[id]);
|
cacheInsertColor(false, None, idNames[id], idColors[id]);
|
||||||
|
|
||||||
return windowPush(window);
|
return windowPush(window);
|
||||||
}
|
}
|
||||||
|
@ -477,7 +477,7 @@ void windowClose(uint num) {
|
||||||
if (num >= count) return;
|
if (num >= count) return;
|
||||||
if (windows[num]->id == Network) return;
|
if (windows[num]->id == Network) return;
|
||||||
struct Window *window = windowRemove(num);
|
struct Window *window = windowRemove(num);
|
||||||
completeClear(window->id);
|
cacheClear(window->id);
|
||||||
windowFree(window);
|
windowFree(window);
|
||||||
if (swap >= num) swap--;
|
if (swap >= num) swap--;
|
||||||
if (show == num) {
|
if (show == num) {
|
||||||
|
|
Loading…
Reference in New Issue