1
0
mirror of https://github.com/Tha14/toxic.git synced 2024-06-26 20:37:46 +02:00

add tab auto-complete function for groupchat names

This commit is contained in:
Jfreegman 2013-12-07 22:10:32 -05:00
parent 3804233c21
commit 4c27df32b0
4 changed files with 135 additions and 8 deletions

View File

@ -308,6 +308,22 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key)
}
}
else if (key == '\t') { /* TAB key: completes peer name */
if (ctx->len >= 2) {
int diff = complete_line(ctx->line, &ctx->pos, &ctx->len, groupchats[self->num].peer_names,
groupchats[self->num].num_peers, TOX_MAX_NAME_LENGTH);
if (diff != -1 && (ctx->len < (x2 * (CHATBOX_HEIGHT - 1)-1))) {
if (x + diff > x2 - 1) {
int ofst = (x + diff - 1) - (x2 - 1);
wmove(self->window, y+1, ofst);
} else {
wmove(self->window, y, x+diff);
}
}
}
}
/* Scroll peerlist up and down one position if list overflows window */
else if (key == KEY_NPAGE) {
int L = y2 - CHATBOX_HEIGHT - SDBAR_OFST;

View File

@ -57,7 +57,36 @@ int string_is_empty(char *string)
return string[0] == '\0';
}
/* convert wide characters to null terminated string */
/* convert a multibyte string to a wide character string (must provide buffer) */
int char_to_wcs_buf(wchar_t *buf, const uint8_t *string, size_t n)
{
size_t len = mbstowcs(NULL, string, 0) + 1;
if (n < len)
return -1;
if ((len = mbstowcs(buf, string, n)) == (size_t) -1)
return -1;
return len;
}
/* converts wide character string into a multibyte string.
Same thing as wcs_to_char() but caller must provide its own buffer */
int wcs_to_char_buf(uint8_t *buf, const wchar_t *string, size_t n)
{
size_t len = wcstombs(NULL, string, 0) + 1;
if (n < len)
return -1;
if ((len = wcstombs(buf, string, n)) == (size_t) -1)
return -1;
return len;
}
/* convert wide characters to multibyte string */
uint8_t *wcs_to_char(wchar_t *string)
{
uint8_t *ret = NULL;
@ -66,8 +95,10 @@ uint8_t *wcs_to_char(wchar_t *string)
if (len != (size_t) -1) {
ret = malloc(++len);
if (ret != NULL)
wcstombs(ret, string, len);
if (ret != NULL) {
if (wcstombs(ret, string, len) == (size_t) -1)
return NULL;
}
} else {
ret = malloc(2);
@ -86,7 +117,7 @@ uint8_t *wcs_to_char(wchar_t *string)
return ret;
}
/* convert a wide char to null terminated string */
/* convert a wide char to multibyte string */
char *wc_to_char(wchar_t ch)
{
static char ret[MB_LEN_MAX + 1];
@ -251,3 +282,67 @@ void reset_buf(wchar_t *buf, size_t *pos, size_t *len)
*pos = 0;
*len = 0;
}
/* looks for the first instance in list that begins with the last entered word in buf according to pos,
then fills buf with the complete word. e.g. "Hello jo" would complete the buffer
with "Hello john". It shouldn't matter where pos is within buf.
list is a pointer to the list of strings being compared, n_items is the number of items
in the list, and size is the size of each item in the list.
Returns the difference between the old len and new len of buf */
int complete_line(wchar_t *buf, size_t *pos, size_t *len, const uint8_t *list, int n_items, int size)
{
if (*pos <= 0 || *len < 2 || *len > MAX_STR_SIZE)
return -1;
uint8_t ubuf[MAX_STR_SIZE];
if (wcs_to_char_buf(ubuf, buf, MAX_STR_SIZE) == -1)
return -1;
/* isolate substring from space behind pos to pos */
uint8_t tmp[MAX_STR_SIZE];
snprintf(tmp, sizeof(tmp), "%s", ubuf);
tmp[*pos] = '\0';
uint8_t *sub = strrchr(tmp, ' ');
if (!sub++)
sub = tmp;
const uint8_t *match;
int i;
/* look for a match in list */
for (i = 0; i < n_items; ++i) {
if (match = strstr(&list[i*size], sub))
break;
}
if (!match)
return -1;
/* put match in correct spot in buf */
int s_len = strlen(sub);
int m_len = strlen(match);
int strt = *pos - s_len;
uint8_t tmpend[MAX_STR_SIZE];
strcpy(tmpend, &ubuf[*pos]);
strcpy(&ubuf[strt], match);
strcpy(&ubuf[strt+m_len], tmpend);
/* convert to widechar and copy back to original buf */
wchar_t newbuf[MAX_STR_SIZE];
if (char_to_wcs_buf(newbuf, ubuf, MAX_STR_SIZE) == -1)
return -1;
int diff = m_len - s_len;
*len += diff;
*pos += diff;
wmemcpy(buf, newbuf, MAX_STR_SIZE);
return diff;
}

View File

@ -16,10 +16,17 @@ void print_time(WINDOW *window);
/* Returns 1 if the string is empty, 0 otherwise */
int string_is_empty(char *string);
/* convert wide characters to null terminated string */
/* convert a multibyte string to a wide character string (must provide buffer) */
int char_to_wcs_buf(wchar_t *buf, const uint8_t *string, size_t n);
/* converts wide character string into a multibyte string.
Same thing as wcs_to_char() but caller must provide its own buffer */
int wcs_to_char_buf(uint8_t *buf, const wchar_t *string, size_t n);
/* convert wide characters to multibyte string string */
uint8_t *wcs_to_char(wchar_t *string);
/* convert a wide char to null terminated string */
/* convert a wide char to multibyte string string */
char *wc_to_char(wchar_t ch);
/* Returns true if connection has timed out, false otherwise */
@ -58,3 +65,12 @@ void kill_buf(wchar_t *buf, size_t *pos, size_t *len);
/* nulls buf and sets pos and len to 0 */
void reset_buf(wchar_t *buf, size_t *pos, size_t *len);
/* looks for the first instance in list that begins with the last entered word in buf,
then completes the word. e.g. "Hello jo" would complete the buffer with "Hello john".
list is a pointer to the list of strings being compared, n_items is the number of items
in the list, and size is the size of each item in the list.
Returns the difference between the old len and new len of buf */
int complete_line(wchar_t *buf, size_t *pos, size_t *len, const uint8_t *list, int n_items, int size);

View File

@ -221,7 +221,7 @@ void set_next_window(int ch)
ToxWindow *inf = active_window;
while (true) {
if (ch == '\t' || ch == T_KEY_NEXT) {
if (ch == T_KEY_NEXT) {
if (++active_window > end)
active_window = windows;
} else if (--active_window < windows)
@ -348,7 +348,7 @@ void draw_active_window(Tox *m)
ch = getch();
#endif
if (ch == '\t' || ch == KEY_BTAB || ch == T_KEY_NEXT || ch == T_KEY_PREV)
if (ch == T_KEY_NEXT || ch == T_KEY_PREV)
set_next_window((int) ch);
else if (ch != ERR)
a->onKey(a, m, ch);