summaryrefslogtreecommitdiff
path: root/ui.c
diff options
context:
space:
mode:
authorCurtis McEnroe2018-08-08 16:59:26 -0400
committerCurtis McEnroe2018-08-08 16:59:26 -0400
commiteac0f83efa3d6b1db2715c21d60b170a546ebc0a (patch)
treec8db1326e24716e29d3c9b06e42527178d030fa1 /ui.c
parentb66c8abf707e6574f6867b646dfb2549a5a7147f (diff)
Factor out line editing to edit.c
Diffstat (limited to 'ui.c')
-rw-r--r--ui.c213
1 files changed, 39 insertions, 174 deletions
diff --git a/ui.c b/ui.c
index 937fa63..72996c1 100644
--- a/ui.c
+++ b/ui.c
@@ -34,7 +34,8 @@
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
-#define CTRL(c) ((c) & 037)
+#define CTRL(c) ((c) & 037)
+#define UNCTRL(c) ((c) + '@')
#ifndef A_ITALIC
#define A_ITALIC A_NORMAL
@@ -235,14 +236,6 @@ static void wordWrap(WINDOW *win, const wchar_t *str) {
}
}
-enum {
- IRC_BOLD = 0x02,
- IRC_COLOR = 0x03,
- IRC_REVERSE = 0x16,
- IRC_RESET = 0x0F,
- IRC_ITALIC = 0x1D,
- IRC_UNDERLINE = 0x1F,
-};
static const wchar_t IRC_CODES[] = {
L' ',
IRC_BOLD,
@@ -324,199 +317,71 @@ static void logDown(void) {
ui.scroll = MIN(ui.scroll + logHeight() / 2, LOG_LINES);
}
-enum { BUF_LEN = 512 };
-static struct {
- wchar_t buf[BUF_LEN];
- wchar_t *ptr;
- wchar_t *end;
-} line = { .ptr = line.buf, .end = line.buf };
-
-static void left(void) {
- if (line.ptr > line.buf) line.ptr--;
-}
-static void right(void) {
- if (line.ptr < line.end) line.ptr++;
-}
-static void home(void) {
- line.ptr = line.buf;
-}
-static void end(void) {
- line.ptr = line.end;
-}
-
-static void kill(void) {
- line.end = line.ptr;
-}
-
-static void insert(wchar_t ch) {
- if (line.end == &line.buf[BUF_LEN - 1]) return;
- if (line.ptr != line.end) {
- wmemmove(line.ptr + 1, line.ptr, line.end - line.ptr);
- }
- *line.ptr++ = ch;
- line.end++;
-}
-
-static void backspace(void) {
- if (line.ptr == line.buf) return;
- if (line.ptr != line.end) {
- wmemmove(line.ptr - 1, line.ptr, line.end - line.ptr);
- }
- line.ptr--;
- line.end--;
-}
-
-static void delete(void) {
- if (line.ptr == line.end) return;
- right();
- backspace();
-}
-
-static void enter(void) {
- if (line.end == line.buf) return;
- *line.end = L'\0';
- char *str = awcstombs(line.buf);
- if (!str) err(EX_DATAERR, "awcstombs");
- input(str);
- free(str);
- line.ptr = line.buf;
- line.end = line.buf;
-}
-
-static struct {
- wchar_t *word;
- char *prefix;
-} tab;
-
-static void accept(void) {
- if (!tab.word) return;
- tab.word = NULL;
- free(tab.prefix);
- tabAccept();
-}
-
-static void reject(void) {
- if (!tab.word) return;
- tab.word = NULL;
- free(tab.prefix);
- tabReject();
-}
-
-static void complete(void) {
- if (!tab.word) {
- wchar_t ch = *line.ptr;
- *line.ptr = L'\0';
- tab.word = wcsrchr(line.buf, L' ');
- tab.word = (tab.word ? &tab.word[1] : line.buf);
- tab.prefix = awcstombs(tab.word);
- if (!tab.prefix) err(EX_DATAERR, "awcstombs");
- *line.ptr = ch;
- }
-
- const char *complete = tabNext(tab.prefix);
- if (!complete) {
- reject();
- return;
- }
-
- wchar_t *wcs = ambstowcs(complete);
- if (!wcs) err(EX_DATAERR, "ambstowcs");
-
- size_t i;
- for (i = 0; wcs[i] && line.ptr > &tab.word[i]; ++i) {
- tab.word[i] = wcs[i];
- }
- while (line.ptr > &tab.word[i]) {
- backspace();
- }
- for (; wcs[i]; ++i) {
- insert(wcs[i]);
- }
- free(wcs);
-
- if (tab.word == line.buf) insert(L':');
- insert(L' ');
-}
-
-static void keyChar(wint_t ch) {
+static bool keyChar(wint_t ch) {
static bool esc, csi;
-
- if (csi) {
- csi = false;
- if (ch == L'O') logMark();
- return;
- }
- csi = (esc && ch == L'[');
- esc = (ch == L'\33');
- if (csi) return;
-
+ bool update = false;
switch (ch) {
break; case CTRL('L'): uiRedraw();
- break; case CTRL('B'): reject(); left();
- break; case CTRL('F'): reject(); right();
- break; case CTRL('A'): reject(); home();
- break; case CTRL('E'): reject(); end();
- break; case CTRL('D'): reject(); delete();
- break; case CTRL('K'): reject(); kill();
- break; case L'\b': reject(); backspace();
- break; case L'\177': reject(); backspace();
- break; case L'\t': complete();
- break; case L'\n': accept(); enter();
- break; case CTRL('C'): accept(); insert(IRC_COLOR);
- break; case CTRL('N'): accept(); insert(IRC_RESET);
- break; case CTRL('O'): accept(); insert(IRC_BOLD);
- break; case CTRL('R'): accept(); insert(IRC_COLOR);
- break; case CTRL('T'): accept(); insert(IRC_ITALIC);
- break; case CTRL('U'): accept(); insert(IRC_UNDERLINE);
- break; case CTRL('V'): accept(); insert(IRC_REVERSE);
+ break; case CTRL('['): esc = true; return false;
+ break; case L'\b': update = edit(esc, false, L'\b');
+ break; case L'\177': update = edit(esc, false, L'\b');
+ break; case L'\t': update = edit(esc, false, L'\t');
+ break; case L'\n': update = edit(esc, false, L'\n');
break; default: {
- if (iswprint(ch)) {
- accept();
- insert(ch);
+ if (esc && ch == L'[') {
+ csi = true;
+ return false;
+ } else if (csi) {
+ if (ch == L'O') logMark();
+ } else if (iswcntrl(ch)) {
+ update = edit(esc, true, UNCTRL(ch));
+ } else {
+ update = edit(esc, false, ch);
}
}
}
+ esc = false;
+ csi = false;
+ return update;
}
-static void keyCode(wint_t ch) {
+static bool keyCode(wint_t ch) {
switch (ch) {
break; case KEY_RESIZE: uiResize();
break; case KEY_PPAGE: logUp();
break; case KEY_NPAGE: logDown();
- break; case KEY_LEFT: left();
- break; case KEY_RIGHT: right();
- break; case KEY_HOME: home();
- break; case KEY_END: end();
- break; case KEY_BACKSPACE: backspace();
- break; case KEY_DC: delete();
- break; case KEY_ENTER: enter();
+ break; case KEY_LEFT: return edit(false, true, 'B');
+ break; case KEY_RIGHT: return edit(false, true, 'F');
+ break; case KEY_HOME: return edit(false, true, 'A');
+ break; case KEY_END: return edit(false, true, 'E');
+ break; case KEY_DC: return edit(false, true, 'D');
+ break; case KEY_BACKSPACE: return edit(false, false, '\b');
+ break; case KEY_ENTER: return edit(false, false, '\n');
}
+ return false;
}
void uiRead(void) {
+ bool update = false;
int ret;
wint_t ch;
while (ERR != (ret = wget_wch(ui.input, &ch))) {
if (ret == KEY_CODE_YES) {
- keyCode(ch);
+ update |= keyCode(ch);
} else {
- keyChar(ch);
+ update |= keyChar(ch);
}
}
+ if (!update) return;
wmove(ui.input, 1, 0);
+ addIRC(ui.input, editHead());
- ch = *line.ptr;
- *line.ptr = L'\0';
- addIRC(ui.input, line.buf);
- *line.ptr = ch;
-
- int _, x;
- getyx(ui.input, _, x);
+ int y, x;
+ getyx(ui.input, y, x);
- *line.end = L'\0';
- addIRC(ui.input, line.ptr);
+ addIRC(ui.input, editTail());
wclrtoeol(ui.input);
- wmove(ui.input, 1, x);
+ wmove(ui.input, y, x);
}