From 43eee8da713a7c7c3788238a6a5f301ae4672a79 Mon Sep 17 00:00:00 2001 From: Curtis McEnroe Date: Tue, 7 Aug 2018 22:40:05 -0400 Subject: Implement cycling tab complete Not properly hooked up to the UI yet. --- chat.h | 3 +++ tab.c | 43 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/chat.h b/chat.h index 838c51d..09f0d2c 100644 --- a/chat.h +++ b/chat.h @@ -64,6 +64,9 @@ void input(char *line); void tabTouch(const char *word); void tabRemove(const char *word); void tabReplace(const char *prev, const char *next); +const char *tabNext(const char *prefix); +void tabAccept(void); +void tabReject(void); wchar_t *ambstowcs(const char *src); char *awcstombs(const wchar_t *src); diff --git a/tab.c b/tab.c index 56fe649..45670ad 100644 --- a/tab.c +++ b/tab.c @@ -40,12 +40,16 @@ static void remove(struct Entry *entry) { if (head == entry) head = entry->next; } +static void touch(struct Entry *entry) { + if (head == entry) return; + remove(entry); + prepend(entry); +} + void tabTouch(const char *word) { for (struct Entry *entry = head; entry; entry = entry->next) { if (strcmp(entry->word, word)) continue; - if (head == entry) return; - remove(entry); - prepend(entry); + touch(entry); return; } @@ -55,18 +59,43 @@ void tabTouch(const char *word) { prepend(entry); } +void tabReplace(const char *prev, const char *next) { + tabTouch(prev); + free(head->word); + head->word = strdup(next); +} + +static struct Entry *match; + void tabRemove(const char *word) { for (struct Entry *entry = head; entry; entry = entry->next) { if (strcmp(entry->word, word)) continue; remove(entry); + if (match == entry) match = entry->next; free(entry->word); free(entry); return; } } -void tabReplace(const char *prev, const char *next) { - tabTouch(prev); - free(head->word); - head->word = strdup(next); +const char *tabNext(const char *prefix) { + size_t len = strlen(prefix); + struct Entry *start = (match ? match->next : head); + for (struct Entry *entry = start; entry; entry = entry->next) { + if (strncasecmp(entry->word, prefix, len)) continue; + match = entry; + return entry->word; + } + if (!match) return NULL; + match = NULL; + return tabNext(prefix); +} + +void tabAccept(void) { + if (match) touch(match); + match = NULL; +} + +void tabReject(void) { + match = NULL; } -- cgit 1.4.1