diff options
author | Curtis McEnroe | 2018-08-03 23:54:28 -0400 |
---|---|---|
committer | Curtis McEnroe | 2018-08-03 23:54:28 -0400 |
commit | 269662d9ca3c178fcc0e1c340391ca1cf0818264 (patch) | |
tree | d26cfa10605507e99663d3c8dcbf17aa6a18e98d | |
parent | 9f17adce8005dfb7a005dc327cafa13ca4c7b379 (diff) |
Handle input
This turned out a lot better than expected. Still a long way to go in terms of line-editing, but at least backspace works!
-rw-r--r-- | chat.c | 93 |
1 files changed, 72 insertions, 21 deletions
diff --git a/chat.c b/chat.c index c0a8231..711f2c2 100644 --- a/chat.c +++ b/chat.c @@ -14,6 +14,8 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#define _XOPEN_SOURCE_EXTENDED + #include <curses.h> #include <err.h> #include <errno.h> @@ -30,10 +32,23 @@ #include <sysexits.h> #include <tls.h> #include <unistd.h> +#include <wchar.h> +#include <wctype.h> #define err(...) do { endwin(); err(__VA_ARGS__); } while (0) #define errx(...) do { endwin(); errx(__VA_ARGS__); } while (0) +static wchar_t *wcssep(wchar_t **stringp, const wchar_t *delim) { + wchar_t *orig = *stringp; + size_t i = wcscspn(orig, delim); + *stringp = NULL; + if (orig[i]) { + orig[i] = '\0'; + *stringp = &orig[i + 1]; + } + return orig; +} + static void curse(void) { setlocale(LC_CTYPE, ""); initscr(); @@ -51,6 +66,7 @@ static void curse(void) { static const int TOPIC_COLS = 512; static const int CHAT_LINES = 100; +static const int INPUT_COLS = 512; static struct { WINDOW *topic; WINDOW *chat; @@ -66,8 +82,8 @@ static void uiInit(void) { scrollok(ui.chat, true); wmove(ui.chat, CHAT_LINES - (LINES - 4) - 1, 0); - ui.input = newwin(2, COLS, LINES - 2, 0); - mvwhline(ui.input, 0, 0, ACS_HLINE, COLS); + ui.input = newpad(2, INPUT_COLS); + mvwhline(ui.input, 0, 0, ACS_HLINE, INPUT_COLS); wmove(ui.input, 1, 0); cbreak(); noecho(); @@ -80,7 +96,12 @@ static void uiDraw(void) { CHAT_LINES - (LINES - 4), 0, 2, 0, LINES - 1, COLS - 1 ); - wnoutrefresh(ui.input); + pnoutrefresh( + ui.input, + 0, 0, + LINES - 2, 0, + LINES - 1, COLS - 1 + ); doupdate(); } @@ -431,29 +452,59 @@ static void clientRead(void) { memmove(buf, line, fill); } -static void uiRead(void) { - static char buf[256]; - static size_t fill; +static void privmsg(bool action, const wchar_t *mesg) { + char *line; + int send; + asprintf( + &line, ":%s!%s %nPRIVMSG %s :%s%ls%s", + client.nick, client.user, &send, client.chan, + (action ? "\1ACTION " : ""), mesg, (action ? "\1" : "") + ); + if (!line) err(EX_OSERR, "asprintf"); + clientFmt("%s\r\n", &line[send]); + handle(line); + free(line); +} - // TODO: - int ch = wgetch(ui.input); - if (ch == '\n') { - buf[fill] = '\0'; - char *params; - asprintf(¶ms, "%s :%s", client.chan, buf); - if (!params) err(EX_OSERR, "asprintf"); - clientFmt("PRIVMSG %s\r\n", params); - handlePrivmsg(client.nick, params); // FIXME: username - free(params); - fill = 0; - wmove(ui.input, 1, 0); - wclrtoeol(ui.input); +static void input(wchar_t *input) { + if (input[0] != '/') { + privmsg(false, input); + return; + } + input++; + wchar_t *cmd = wcssep(&input, L" "); + if (!wcscmp(cmd, L"me")) { + privmsg(true, input ? input : L""); } else { - buf[fill++] = ch; - waddch(ui.input, ch); + uiFmt("/%ls isn't a recognized command", cmd); } } +static void uiRead(void) { + static wchar_t buf[512]; + static size_t len; + + wint_t ch; + wget_wch(ui.input, &ch); + switch (ch) { + break; case '\b': case '\177': { + if (len) len--; + } + break; case '\n': { + if (!len) break; + buf[len] = '\0'; + input(buf); + len = 0; + } + break; default: { + if (iswprint(ch)) buf[len++] = ch; + } + } + wmove(ui.input, 1, 0); + waddnwstr(ui.input, buf, len); + wclrtoeol(ui.input); +} + static void webirc(const char *pass) { const char *ssh = getenv("SSH_CLIENT"); if (!ssh) return; |