catgirl/chat.h

235 lines
5.8 KiB
C
Raw Normal View History

2020-02-01 06:18:01 +00:00
/* Copyright (C) 2020 C. 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/>.
*/
2020-02-01 07:33:17 +00:00
#include <err.h>
#include <getopt.h>
2020-02-01 06:18:01 +00:00
#include <stdbool.h>
2020-02-02 07:31:20 +00:00
#include <stdint.h>
2020-02-01 07:33:17 +00:00
#include <string.h>
#include <sysexits.h>
#include <time.h>
#include <wchar.h>
2020-02-01 06:18:01 +00:00
#define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
#define BIT(x) x##Bit, x = 1 << x##Bit, x##Bit_ = x##Bit
typedef unsigned char byte;
2020-02-08 22:42:19 +00:00
int procPipe[2];
2020-02-02 08:27:50 +00:00
enum Color {
White, Black, Blue, Green, Red, Brown, Magenta, Orange,
Yellow, LightGreen, Cyan, LightCyan, LightBlue, Pink, Gray, LightGray,
Default = 99,
};
2020-02-01 07:33:17 +00:00
enum { None, Debug, Network, IDCap = 256 };
extern char *idNames[IDCap];
2020-02-02 08:27:50 +00:00
extern enum Color idColors[IDCap];
2020-02-01 07:33:17 +00:00
extern size_t idNext;
static inline size_t idFind(const char *name) {
for (size_t id = 0; id < idNext; ++id) {
if (!strcmp(idNames[id], name)) return id;
}
return None;
}
2020-02-02 08:27:50 +00:00
2020-02-01 07:33:17 +00:00
static inline size_t idFor(const char *name) {
size_t id = idFind(name);
if (id) return id;
if (idNext == IDCap) return Network;
2020-02-01 07:33:17 +00:00
idNames[idNext] = strdup(name);
if (!idNames[idNext]) err(EX_OSERR, "strdup");
2020-02-06 09:19:56 +00:00
idColors[idNext] = Default;
2020-02-01 07:33:17 +00:00
return idNext++;
}
2020-02-01 06:18:01 +00:00
#define ENUM_CAP \
X("extended-join", CapExtendedJoin) \
2020-02-01 06:18:01 +00:00
X("sasl", CapSASL) \
X("server-time", CapServerTime) \
X("userhost-in-names", CapUserhostInNames)
enum Cap {
#define X(name, id) BIT(id),
ENUM_CAP
#undef X
};
extern struct Self {
2020-02-01 07:26:35 +00:00
bool debug;
char *plain;
2020-02-01 07:26:35 +00:00
const char *join;
2020-02-01 06:18:01 +00:00
enum Cap caps;
char *network;
char *chanTypes;
char *prefixes;
2020-02-01 06:18:01 +00:00
char *nick;
2020-02-05 05:40:24 +00:00
char *user;
enum Color color;
2020-02-06 02:57:23 +00:00
char *quit;
2020-02-01 06:18:01 +00:00
} self;
static inline void set(char **field, const char *value) {
free(*field);
*field = strdup(value);
if (!*field) err(EX_OSERR, "strdup");
}
2020-02-01 06:18:01 +00:00
#define ENUM_TAG \
X("time", TagTime)
enum Tag {
#define X(name, id) id,
ENUM_TAG
#undef X
TagCap,
};
enum { ParamCap = 15 };
struct Message {
char *tags[TagCap];
char *nick;
char *user;
char *host;
char *cmd;
char *params[ParamCap];
};
void ircConfig(bool insecure, FILE *cert, FILE *priv);
2020-02-01 06:18:01 +00:00
int ircConnect(const char *host, const char *port);
void ircRecv(void);
void ircSend(const char *ptr, size_t len);
void ircFormat(const char *format, ...)
__attribute__((format(printf, 1, 2)));
2020-02-08 08:15:17 +00:00
extern struct Replies {
size_t topic;
size_t names;
2020-02-09 21:45:49 +00:00
size_t whois;
2020-02-08 08:15:17 +00:00
} replies;
2020-02-01 06:18:01 +00:00
void handle(struct Message msg);
void command(size_t id, char *input);
2020-02-06 00:00:54 +00:00
const char *commandIsPrivmsg(size_t id, const char *input);
const char *commandIsNotice(size_t id, const char *input);
const char *commandIsAction(size_t id, const char *input);
2020-02-08 02:30:25 +00:00
void commandComplete(void);
2020-02-01 06:18:01 +00:00
enum Heat { Cold, Warm, Hot };
void uiInit(void);
void uiShow(void);
void uiHide(void);
void uiDraw(void);
void uiShowID(size_t id);
2020-02-06 03:09:29 +00:00
void uiShowNum(size_t num);
2020-02-08 07:26:00 +00:00
void uiCloseID(size_t id);
void uiCloseNum(size_t id);
2020-02-04 08:58:56 +00:00
void uiRead(void);
2020-02-03 23:41:52 +00:00
void uiWrite(size_t id, enum Heat heat, const time_t *time, const char *str);
void uiFormat(
2020-02-03 23:41:52 +00:00
size_t id, enum Heat heat, const time_t *time, const char *format, ...
) __attribute__((format(printf, 4, 5)));
enum Edit {
EditHead,
EditTail,
EditPrev,
EditNext,
2020-02-09 09:20:07 +00:00
EditPrevWord,
EditNextWord,
2020-02-09 09:22:41 +00:00
EditDeleteHead,
EditDeleteTail,
EditDeletePrev,
EditDeleteNext,
2020-02-09 09:32:32 +00:00
EditDeletePrevWord,
EditDeleteNextWord,
EditPaste,
EditInsert,
2020-02-08 02:30:25 +00:00
EditComplete,
EditEnter,
};
void edit(size_t id, enum Edit op, wchar_t ch);
char *editBuffer(size_t *pos);
2020-02-08 02:30:25 +00:00
const char *complete(size_t id, const char *prefix);
void completeAccept(void);
void completeReject(void);
void completeAdd(size_t id, const char *str, enum Color color);
void completeTouch(size_t id, const char *str, enum Color color);
2020-02-08 05:01:59 +00:00
void completeReplace(size_t id, const char *old, const char *new);
void completeRemove(size_t id, const char *str);
2020-02-08 04:44:03 +00:00
void completeClear(size_t id);
size_t completeID(const char *str);
enum Color completeColor(size_t id, const char *str);
2020-02-08 02:30:25 +00:00
2020-02-09 02:21:21 +00:00
extern const char *urlOpenUtil;
2020-02-09 02:44:50 +00:00
extern const char *urlCopyUtil;
2020-02-08 23:29:01 +00:00
void urlScan(size_t id, const char *nick, const char *mesg);
void urlOpenCount(size_t id, size_t count);
void urlOpenMatch(size_t id, const char *str);
2020-02-09 02:44:50 +00:00
void urlCopyMatch(size_t id, const char *str);
2020-02-08 23:29:01 +00:00
FILE *configOpen(const char *path, const char *mode);
int getopt_config(
int argc, char *const *argv,
const char *optstring, const struct option *longopts, int *longindex
);
2020-02-10 10:50:28 +00:00
extern uint32_t hashInit;
2020-02-02 08:27:50 +00:00
static inline enum Color hash(const char *str) {
if (*str == '~') str++;
2020-02-10 10:50:28 +00:00
uint32_t hash = hashInit;
2020-02-02 08:27:50 +00:00
for (; *str; ++str) {
hash = (hash << 5) | (hash >> 27);
hash ^= *str;
hash *= 0x27220A95;
}
return 2 + hash % 74;
2020-02-02 08:27:50 +00:00
}
2020-02-01 06:18:01 +00:00
#define BASE64_SIZE(len) (1 + ((len) + 2) / 3 * 4)
static const char Base64[64] = {
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
};
static inline void base64(char *dst, const byte *src, size_t len) {
size_t i = 0;
while (len > 2) {
dst[i++] = Base64[0x3F & (src[0] >> 2)];
dst[i++] = Base64[0x3F & (src[0] << 4 | src[1] >> 4)];
dst[i++] = Base64[0x3F & (src[1] << 2 | src[2] >> 6)];
dst[i++] = Base64[0x3F & src[2]];
src += 3;
len -= 3;
}
if (len) {
dst[i++] = Base64[0x3F & (src[0] >> 2)];
if (len > 1) {
dst[i++] = Base64[0x3F & (src[0] << 4 | src[1] >> 4)];
dst[i++] = Base64[0x3F & (src[1] << 2)];
} else {
dst[i++] = Base64[0x3F & (src[0] << 4)];
dst[i++] = '=';
}
dst[i++] = '=';
}
dst[i] = '\0';
}
// Defined in libcrypto if missing from libc:
void explicit_bzero(void *b, size_t len);