diff options
Diffstat (limited to 'chat.h')
-rw-r--r-- | chat.h | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/chat.h b/chat.h new file mode 100644 index 0000000..f47b244 --- /dev/null +++ b/chat.h @@ -0,0 +1,241 @@ +/* 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/>. + */ + +#include <err.h> +#include <getopt.h> +#include <stdbool.h> +#include <stdint.h> +#include <string.h> +#include <sysexits.h> +#include <time.h> +#include <wchar.h> + +#define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0])) +#define BIT(x) x##Bit, x = 1 << x##Bit, x##Bit_ = x##Bit + +#define XDG_SUBDIR "catgirl" + +typedef unsigned char byte; + +int procPipe[2]; + +enum Color { + White, Black, Blue, Green, Red, Brown, Magenta, Orange, + Yellow, LightGreen, Cyan, LightCyan, LightBlue, Pink, Gray, LightGray, + Default = 99, +}; + +enum { None, Debug, Network, IDCap = 256 }; +extern char *idNames[IDCap]; +extern enum Color idColors[IDCap]; +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; +} + +static inline size_t idFor(const char *name) { + size_t id = idFind(name); + if (id) return id; + if (idNext == IDCap) return Network; + idNames[idNext] = strdup(name); + if (!idNames[idNext]) err(EX_OSERR, "strdup"); + idColors[idNext] = Default; + return idNext++; +} + +#define ENUM_CAP \ + X("extended-join", CapExtendedJoin) \ + 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 { + bool debug; + char *plain; + const char *join; + enum Cap caps; + char *network; + char *chanTypes; + char *prefixes; + char *nick; + char *user; + enum Color color; + char *quit; +} self; + +static inline void set(char **field, const char *value) { + free(*field); + *field = strdup(value); + if (!*field) err(EX_OSERR, "strdup"); +} + +#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); +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))); + +extern struct Replies { + size_t join; + size_t topic; + size_t names; + size_t whois; +} replies; + +void handle(struct Message msg); +void command(size_t id, char *input); +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); +void commandComplete(void); + +enum Heat { Cold, Warm, Hot }; +void uiInit(void); +void uiShow(void); +void uiHide(void); +void uiDraw(void); +void uiShowID(size_t id); +void uiShowNum(size_t num); +void uiCloseID(size_t id); +void uiCloseNum(size_t id); +void uiRead(void); +void uiWrite(size_t id, enum Heat heat, const time_t *time, const char *str); +void uiFormat( + size_t id, enum Heat heat, const time_t *time, const char *format, ... +) __attribute__((format(printf, 4, 5))); +void uiLoad(const char *name); +int uiSave(const char *name); + +enum Edit { + EditHead, + EditTail, + EditPrev, + EditNext, + EditPrevWord, + EditNextWord, + EditDeleteHead, + EditDeleteTail, + EditDeletePrev, + EditDeleteNext, + EditDeletePrevWord, + EditDeleteNextWord, + EditPaste, + EditInsert, + EditComplete, + EditEnter, +}; +void edit(size_t id, enum Edit op, wchar_t ch); +char *editBuffer(size_t *pos); + +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); +void completeReplace(size_t id, const char *old, const char *new); +void completeRemove(size_t id, const char *str); +void completeClear(size_t id); +size_t completeID(const char *str); +enum Color completeColor(size_t id, const char *str); + +extern const char *urlOpenUtil; +extern const char *urlCopyUtil; +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); +void urlCopyMatch(size_t id, const char *str); + +FILE *configOpen(const char *path, const char *mode); +FILE *dataOpen(const char *path, const char *mode); + +int getopt_config( + int argc, char *const *argv, + const char *optstring, const struct option *longopts, int *longindex +); + +extern uint32_t hashInit; +static inline enum Color hash(const char *str) { + if (*str == '~') str++; + uint32_t hash = hashInit; + for (; *str; ++str) { + hash = (hash << 5) | (hash >> 27); + hash ^= *str; + hash *= 0x27220A95; + } + return 2 + hash % 74; +} + +#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); |