changeset 113:2a53156e7e12

Yay, tab-completion cycling now works (except for usernames with whitespaces, of course ...)
author Matti Hamalainen <ccr@tnsp.org>
date Sun, 24 Oct 2010 21:38:47 +0300
parents c4865ac2386c
children 256cca8cc086
files nnchat.c
diffstat 1 files changed, 57 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/nnchat.c	Sun Oct 24 21:38:17 2010 +0300
+++ b/nnchat.c	Sun Oct 24 21:38:47 2010 +0300
@@ -641,55 +641,85 @@
     return TRUE;
 }
 
-void performTabCompletion(nn_editbuf_t *buf)
+/*
+Different tab completion scenarios:
+
+Line start
+"foo<tab>" ->
+    * store "foo" as pattern
+    * find match: "Foobar"
+    * replace "foo" with match
+
+"Foobar: <tab>" ->
+    * ": " -> cycle to next match
+    * "Foorulez"
+    * replace "Foobar: " with "Foorulez: "
+
+Same when completing in middle of line, but " " instead of ": ".
+*/
+BOOL performTabCompletion(nn_editbuf_t *buf)
 {
     static char *previous = NULL;
-    static char *matsi = NULL;
-    char *b = buf->data;
-    ssize_t pos2 = 0, pos1 = buf->pos;
-    
-    if (pos1 > 0) pos1--;
+    static char *pattern = NULL;
+    int mode = 0;
+    char *str = buf->data;
+    ssize_t endPos = 0, startPos = buf->pos;
 
-    if (pos1 > 0 && b[pos1 - 1] == ':') {
-        pos1 -= 2;
-        pos2 = pos1;
-        while (pos1 > 0 && b[pos1 - 1] != ' ') pos1--;
+    if (startPos > 1 && str[startPos - 1] == ' ') {
+        startPos -= 2;
+        if (str[startPos] == ':')
+            startPos--;
+        if (startPos <= 0 || str[startPos] == ' ')
+            return FALSE;
+        endPos = startPos;
+        while (startPos > 0 && str[startPos - 1] != ' ') startPos--;
+        mode = 1;
     } else
-    if (b[pos1] != ' ' && b[pos1] != ':') {
-        pos2 = pos1;
-        while (pos1 > 0 && b[pos1 - 1] != ' ') pos1--;
-        while (pos2 < buf->len && b[pos2] != ' ') pos2++;
-        while (pos2 > 0 && b[pos2] == ' ') pos2--;
-        th_free(matsi);
-        matsi = nn_editbuf_get_string(buf, pos1, pos2);
+    if (str[startPos - 1] != ' ' && (startPos == buf->len || str[startPos] == ' ')) {
+        endPos = startPos;
+        while (startPos > 0 && str[startPos - 1] != ' ') startPos--;
+        while (endPos < buf->len && str[endPos] != ' ') endPos++;
+        while (endPos > 0 && str[endPos] == ' ') endPos--;
+        if (str[endPos] == ':')
+            return FALSE;
+        th_free(pattern);
+        pattern = nn_editbuf_get_string(buf, startPos, endPos);
         th_free(previous); previous = NULL;
-    }
+        mode = 2;
+    } 
+//    printMsg("%d, %d <-> %d : '%s' (%d)\n", startPos, endPos, buf->len, pattern, mode);
 
-    if (matsi) {
-        nn_user_t *user = nn_user_match(nnUsers, matsi, previous);
-//        printMsg("pattern '%s'\n", matsi);
+    if (pattern) {
+        nn_user_t *user = nn_user_match(nnUsers, pattern, previous);
 
         if (user) {
             int i;
             char *c = user->name;
 //            printMsg("match '%s'\n", user->name);
 
-            for (i = pos1; i <= pos2; i++)
-                nn_editbuf_delete(buf, pos1);
+            for (i = startPos; i <= endPos; i++)
+                nn_editbuf_delete(buf, startPos);
                 
-            for (i = pos1; *c; i++, c++)
+            for (i = startPos; *c; i++, c++)
                 nn_editbuf_insert(buf, i, *c);
 
             if (previous == NULL) {
-                nn_editbuf_insert(buf, i+1, ':');
-                nn_editbuf_insert(buf, i+2, ' ');
+                if (startPos == 0) {
+                    nn_editbuf_insert(buf, i++, ':');
+                    startPos++;
+                }
+                nn_editbuf_insert(buf, i++, ' ');
             }
-            nn_editbuf_setpos(buf, pos1 + 2 + strlen(user->name));
+            nn_editbuf_setpos(buf, startPos + 2 + strlen(user->name));
 
             th_free(previous);
             previous = th_strdup(user->name);
+            
+            return TRUE;
         }
     }
+    
+    return FALSE;
 }
 
 int main(int argc, char *argv[])