Exemple #1
0
/* transforms a sendfile tab complete contaning the shorthand "~/" into the full home directory.*/
static void complt_home_dir(ToxWindow *self, char *path, int pathsize)
{
    ChatContext *ctx = self->chatwin;

    char homedir[MAX_STR_SIZE];
    get_home_dir(homedir, sizeof(homedir));

    char newline[MAX_STR_SIZE];
    snprintf(newline, sizeof(newline), "/sendfile \"%s%s", homedir, path + 1);
    snprintf(path, pathsize, "%s", &newline[11]);

    wchar_t wline[MAX_STR_SIZE];

    if (mbs_to_wcs_buf(wline, newline, sizeof(wline)) == -1)
        return;

    int newlen = wcslen(wline);

    if (ctx->len + newlen >= MAX_STR_SIZE)
        return;

    wmemcpy(ctx->line, wline, newlen + 1);
    ctx->pos = newlen;
    ctx->len = ctx->pos;
}
Exemple #2
0
/* Transforms a tab complete starting with the shorthand "~" into the full home directory. */
static void complete_home_dir(ToxWindow *self, char *path, int pathsize, const char *cmd, int cmdlen)
{
    ChatContext *ctx = self->chatwin;

    char homedir[MAX_STR_SIZE] = {0};
    get_home_dir(homedir, sizeof(homedir));

    char newline[MAX_STR_SIZE];
    snprintf(newline, sizeof(newline), "%s %s%s", cmd, homedir, path + 1);
    snprintf(path, pathsize, "%s", &newline[cmdlen-1]);

    wchar_t wline[MAX_STR_SIZE];

    if (mbs_to_wcs_buf(wline, newline, sizeof(wline) / sizeof(wchar_t)) == -1) {
        return;
    }

    int newlen = wcslen(wline);

    if (ctx->len + newlen >= MAX_STR_SIZE) {
        return;
    }

    wmemcpy(ctx->line, wline, newlen + 1);
    ctx->pos = newlen;
    ctx->len = ctx->pos;
}
Exemple #3
0
/* looks for all instances in list that begin with the last entered word in line according to pos,
   then fills line with the complete word. e.g. "Hello jo" would complete the line
   with "Hello john". If multiple matches, prints out all the matches and semi-completes line.

   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 line on success, -1 if error */
int complete_line(ToxWindow *self, const void *list, int n_items, int size)
{
    ChatContext *ctx = self->chatwin;

    if (ctx->pos <= 0 || ctx->len <= 0 || ctx->len >= MAX_STR_SIZE || size > MAX_STR_SIZE)
        return -1;

    const char *L = (char *) list;
    const char *endchrs = " ";
    char ubuf[MAX_STR_SIZE];

    /* work with multibyte string copy of buf for simplicity */
    if (wcs_to_mbs_buf(ubuf, ctx->line, sizeof(ubuf)) == -1)
        return -1;

    bool dir_search = strncmp(ubuf, "/sendfile", strlen("/sendfile")) == 0;

    /* isolate substring from space behind pos to pos */
    char tmp[MAX_STR_SIZE];
    snprintf(tmp, sizeof(tmp), "%s", ubuf);
    tmp[ctx->pos] = '\0';

    const char *s = dir_search ? strchr(tmp, '\"') : strrchr(tmp, ' ');
    char *sub = malloc(strlen(ubuf) + 1);

    if (sub == NULL)
        exit_toxic_err("failed in complete_line", FATALERR_MEMORY);

    if (!s && !dir_search) {
        strcpy(sub, tmp);

        if (sub[0] != '/')
            endchrs = ": ";
    } else if (s) {
        strcpy(sub, &s[1]);

        if (dir_search) {
            int sub_len = strlen(sub);
            int si = char_rfind(sub, '/', sub_len);

            if (si || *sub == '/')
                memmove(sub, &sub[si + 1], sub_len - si);
        }
    }

    if (string_is_empty(sub)) {
        free(sub);
        return -1;
    }

    int s_len = strlen(sub);
    const char *str;
    int n_matches = 0;
    char matches[n_items][MAX_STR_SIZE];
    int i = 0;

    /* put all list matches in matches array */
    for (i = 0; i < n_items; ++i) {
        str = &L[i * size];

        if (strncasecmp(str, sub, s_len) == 0)
            strcpy(matches[n_matches++], str);
    }

    free(sub);

    if (!n_matches)
        return -1;

    if (!dir_search && n_matches > 1)
        print_matches(self, NULL, matches, n_matches, MAX_STR_SIZE);

    char match[MAX_STR_SIZE];
    get_str_match(self, match, matches, n_matches);

    if (dir_search) {
        if (n_matches == 1)
            endchrs = char_rfind(match, '.', strlen(match)) ? "\"" : "/";
        else
            endchrs = "";
    } else if (n_matches > 1) {
        endchrs = "";
    }

    /* put match in correct spot in buf and append endchars */
    int n_endchrs = strlen(endchrs);
    int m_len = strlen(match);
    int strt = ctx->pos - s_len;
    int diff = m_len - s_len + n_endchrs;

    if (ctx->len + diff >= MAX_STR_SIZE)
        return -1;

    char tmpend[MAX_STR_SIZE];
    strcpy(tmpend, &ubuf[ctx->pos]);
    strcpy(&ubuf[strt], match);
    strcpy(&ubuf[strt + m_len], endchrs);
    strcpy(&ubuf[strt + m_len + n_endchrs], tmpend);

    /* convert to widechar and copy back to original buf */
    wchar_t newbuf[MAX_STR_SIZE];

    if (mbs_to_wcs_buf(newbuf, ubuf, MAX_STR_SIZE) == -1)
        return -1;

    wcscpy(ctx->line, newbuf);

    ctx->len += diff;
    ctx->pos += diff;

    return diff;
}
Exemple #4
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".

   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 on success, -1 if error */
int complete_line(wchar_t *buf, size_t *pos, size_t *len, const void *list, int n_items, int size)
{
    if (*pos <= 0 || *len <= 0 || *len >= MAX_STR_SIZE)
        return -1;

    const uint8_t *L = (uint8_t *) list;

    uint8_t ubuf[MAX_STR_SIZE];
    /* work with multibyte string copy of buf for simplicity */
    if (wcs_to_mbs_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, ' ');
    int n_endchrs = 1;    /* 1 = append space to end of match, 2 = append ": " */   

    if (!sub++) {
        sub = tmp;
        if (sub[0] != '/')    /* make sure it's not a command */
            n_endchrs = 2;
    }

    if (string_is_empty(sub))
        return -1;

    int s_len = strlen(sub);
    const uint8_t *match;
    bool is_match = false;
    int i;

    /* look for a match in list */
    for (i = 0; i < n_items; ++i) {
        match = &L[i*size];
        if (is_match = strncasecmp(match, sub, s_len) == 0)
            break;
    }

    if (!is_match)
        return -1;

    /* put match in correct spot in buf and append endchars (space or ": ") */
    const uint8_t *endchrs = n_endchrs == 1 ? " " : ": ";
    int m_len = strlen(match);
    int strt = (int) *pos - s_len;
    int diff = m_len - s_len + n_endchrs;

    if (*len + diff > MAX_STR_SIZE)
        return -1;

    uint8_t tmpend[MAX_STR_SIZE];
    strcpy(tmpend, &ubuf[*pos]);
    strcpy(&ubuf[strt], match);
    strcpy(&ubuf[strt+m_len], endchrs);
    strcpy(&ubuf[strt+m_len+n_endchrs], tmpend);

    /* convert to widechar and copy back to original buf */
    wchar_t newbuf[MAX_STR_SIZE];

    if (mbs_to_wcs_buf(newbuf, ubuf, MAX_STR_SIZE) == -1)
        return -1;

    wcscpy(buf, newbuf);

    *len += (size_t) diff;
    *pos += (size_t) diff;

    return diff;
}
Exemple #5
0
/*
 * Looks for all instances in list that begin with the last entered word in line according to pos,
 * then fills line with the complete word. e.g. "Hello jo" would complete the line
 * with "Hello john". If multiple matches, prints out all the matches and semi-completes line.
 *
 * 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.
 *
 * dir_search should be true if the line being completed is a file path.
 *
 * Returns the difference between the old len and new len of line on success.
 * Returns -1 on error.
 *
 * Note: This function should not be called directly. Use complete_line() and complete_path() instead.
 */
static int complete_line_helper(ToxWindow *self, const void *list, size_t n_items, size_t size, bool dir_search)
{
    ChatContext *ctx = self->chatwin;

    if (ctx->pos <= 0 || ctx->len <= 0 || ctx->pos > ctx->len) {
        return -1;
    }

    if (ctx->len >= MAX_STR_SIZE || size > MAX_STR_SIZE) {
        return -1;
    }

    const char *L = (const char *) list;
    const char *endchrs = " ";
    char ubuf[MAX_STR_SIZE] = {0};

    /* work with multibyte string copy of buf for simplicity */
    if (wcs_to_mbs_buf(ubuf, ctx->line, sizeof(ubuf)) == -1) {
        return -1;
    }

    /* isolate substring from space behind pos to pos */
    char tmp[MAX_STR_SIZE];
    snprintf(tmp, sizeof(tmp), "%s", ubuf);
    tmp[ctx->pos] = '\0';

    const char *s = dir_search ? strchr(tmp, ' ') : strrchr(tmp, ' ');
    char *sub = calloc(1, strlen(ubuf) + 1);

    if (sub == NULL) {
        exit_toxic_err("failed in complete_line_helper", FATALERR_MEMORY);
    }

    if (!s && !dir_search) {
        strcpy(sub, tmp);

        if (sub[0] != '/') {
            endchrs = ": ";
        }
    } else if (s) {
        strcpy(sub, &s[1]);

        if (dir_search) {
            int sub_len = strlen(sub);
            int si = char_rfind(sub, '/', sub_len);

            if (si || *sub == '/') {
                memmove(sub, &sub[si + 1], sub_len - si);
            }
        }
    }

    if (!sub[0]) {
        free(sub);
        return 0;
    }

    int s_len = strlen(sub);
    size_t n_matches = 0;
    char matches[n_items][MAX_STR_SIZE];
    int i = 0;

    /* put all list matches in matches array */
    for (i = 0; i < n_items; ++i) {
        char str[MAX_CMDNAME_SIZE + 1];
        snprintf(str, sizeof(str), "%s", &L[i * size]);

        if (strncasecmp(str, sub, s_len) == 0) {
            strcpy(matches[n_matches++], str);
        }
    }

    free(sub);

    if (!n_matches) {
        return -1;
    }

    if (!dir_search && n_matches > 1) {
        print_matches(self, NULL, matches, n_matches, MAX_STR_SIZE);
    }

    char match[MAX_STR_SIZE];
    size_t match_len = get_str_match(self, match, sizeof(match), matches, n_matches);

    if (match_len == 0) {
        return 0;
    }

    if (dir_search) {
        if (n_matches == 1) {
            endchrs = char_rfind(match, '.', match_len) ? "" : "/";
        } else {
            endchrs = "";
        }
    } else if (n_matches > 1) {
        endchrs = "";
    }

    /* put match in correct spot in buf and append endchars */
    int n_endchrs = strlen(endchrs);
    int strt = ctx->pos - s_len;
    int diff = match_len - s_len + n_endchrs;

    if (ctx->len + diff >= MAX_STR_SIZE) {
        return -1;
    }

    char tmpend[MAX_STR_SIZE];
    snprintf(tmpend, sizeof(tmpend), "%s", &ubuf[ctx->pos]);

    if (match_len + n_endchrs + strlen(tmpend) >= sizeof(ubuf)) {
        return -1;
    }

    strcpy(&ubuf[strt], match);

    /* If path points to a file with no extension don't append a forward slash */
    if (dir_search && *endchrs == '/') {
        const char *path_start = strchr(ubuf+1, '/');

        if (!path_start) {
            path_start = strchr(ubuf+1, ' ');

            if (!path_start) {
                return -1;
            }
        }

        if (strlen(path_start) < 2) {
            return -1;
        }

        ++path_start;

        if (file_type(path_start) == FILE_TYPE_REGULAR) {
            endchrs = "";
            diff -= n_endchrs;
        }
    }

    strcpy(&ubuf[strt + match_len], endchrs);
    strcpy(&ubuf[strt + match_len + n_endchrs], tmpend);

    /* convert to widechar and copy back to original buf */
    wchar_t newbuf[MAX_STR_SIZE];

    if (mbs_to_wcs_buf(newbuf, ubuf, sizeof(newbuf) / sizeof(wchar_t)) == -1) {
        return -1;
    }

    wcscpy(ctx->line, newbuf);

    ctx->len += diff;
    ctx->pos += diff;

    return diff;
}