# HG changeset patch # User Matti Hamalainen # Date 1289928511 -7200 # Node ID b0d64dde62af09f03b3006168d0fab7637c36c59 # Parent 6b399b7ce40b43c5018e0522d3ce55f3d60521fe Fix username tab completion. Should now work like in Irssi, though the problem with usernames with whitespace still exists. diff -r 6b399b7ce40b -r b0d64dde62af nnchat.c --- a/nnchat.c Tue Nov 16 02:40:17 2010 +0200 +++ b/nnchat.c Tue Nov 16 19:28:31 2010 +0200 @@ -732,48 +732,78 @@ BOOL performTabCompletion(nn_editbuf_t *buf) { - static char *previous = NULL; - static char *pattern = NULL; + static char *previous = NULL, *pattern = NULL; + BOOL again = FALSE, hasSeparator = FALSE, newPattern = FALSE, hasSpace = FALSE; + char *str = buf->data; int mode = 0; - BOOL again = FALSE; - char *str = buf->data; - ssize_t endPos = 0, startPos = buf->pos; + ssize_t endPos, startPos = buf->pos; - if (startPos > 1 && str[startPos - 1] == ' ') { + /* previous word */ + if (startPos >= 2 && str[startPos - 1] == ' ' && str[startPos - 2] != ' ') { startPos -= 2; - if (str[startPos] == optNickSep) - startPos--; - if (startPos <= 0 || str[startPos] == ' ') - return FALSE; endPos = startPos; while (startPos > 0 && str[startPos - 1] != ' ') startPos--; mode = 1; } else - if (str[startPos - 1] != ' ' && (startPos == buf->len || str[startPos] == ' ')) { - char *npattern; - + /* middle of a word, new pattern */ + if (startPos < buf->len && str[startPos] != ' ') { + endPos = startPos; + while (startPos > 0 && str[startPos - 1] != ' ') startPos--; + while (endPos < buf->len - 1 && str[endPos + 1] != ' ') endPos++; + newPattern = TRUE; + mode = 2; + } else + /* previous word, new pattern */ + if (startPos >= 1 && str[startPos - 1] != ' ') { + startPos -= 1; 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] == optNickSep) + newPattern = TRUE; + mode = 3; + } else { + if (optDebug) + printMsg("no mode\n"); + return FALSE; + } + + if (str[endPos] == optNickSep) { + endPos--; + if (startPos > 0) { + if (optDebug) + printMsg("str[endPos] == optNickSep && startPos > 0 (%d)\n", startPos); return FALSE; - + } + hasSeparator = TRUE; + } + + if (buf->pos > 0 && str[buf->pos - 1] == ' ') + hasSpace = TRUE; + if (buf->pos <= buf->len && str[buf->pos] == ' ') + hasSpace = TRUE; + + if (newPattern) { /* Get pattern, check if it matches previous pattern and set 'again' flag */ - npattern = nn_editbuf_get_string(buf, startPos, endPos); + char *npattern = nn_editbuf_get_string(buf, startPos, endPos); if (pattern && npattern && strcasecmp(npattern, pattern) == 0) again = TRUE; - th_free(pattern); pattern = npattern; + + th_free(pattern); + pattern = npattern; + if (!again) { th_free(previous); previous = NULL; } - mode = 2; - } + } - if (optDebug) - printMsg("sPos=%d, ePos=%d <-> bLen=%d : pat='%s' (mode=%d, again=%s)\n", - startPos, endPos, buf->len, pattern, mode, again ? "yes" : "no"); + if (optDebug) { + printMsg("sPos=%d, ePos=%d <-> bPos=%d, bufLen=%d : pat='%s' (again=%s, hassep=%s, hasspc=%s, newpat=%s, mode=%d)\n", + startPos, endPos, buf->pos, buf->len, pattern, + again ? "yes" : "no", + hasSeparator ? "yes" : "no", + hasSpace ? "yes" : "no", + newPattern ? "yes" : "no", mode); + } if (pattern) { nn_user_t *user = nn_user_match(nnUsers, pattern, previous, again); @@ -790,14 +820,16 @@ for (i = startPos; *c; i++, c++) nn_editbuf_insert(buf, i, *c); - if (previous == NULL || again) { - if (startPos == 0) { - nn_editbuf_insert(buf, i++, optNickSep); - startPos++; - } + if (!hasSeparator && startPos == 0) { + nn_editbuf_insert(buf, i++, optNickSep); + startPos++; + } + if (hasSeparator) + startPos++; + if (!hasSpace) nn_editbuf_insert(buf, i++, ' '); - } - nn_editbuf_setpos(buf, startPos + 2 + strlen(user->name)); + + nn_editbuf_setpos(buf, startPos + 1 + strlen(user->name)); th_free(previous); previous = th_strdup(user->name);