summary refs log tree commit diff
diff options
context:
space:
mode:
authorCurtis McEnroe2018-08-07 22:40:05 -0400
committerCurtis McEnroe2018-08-07 22:40:05 -0400
commit43eee8da713a7c7c3788238a6a5f301ae4672a79 (patch)
treedbea290ee50c63340b63d2ab8af8a5cea714cb2d
parentee49c3665523f89262d39bccf50e2c1f5b9c2e91 (diff)
Implement cycling tab complete
Not properly hooked up to the UI yet.
-rw-r--r--chat.h3
-rw-r--r--tab.c43
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;
 }