diff --git a/src/autocomplete.c b/src/autocomplete.c index e986e97..b21bdf9 100644 --- a/src/autocomplete.c +++ b/src/autocomplete.c @@ -35,6 +35,7 @@ #include "misc_tools.h" #include "line_info.h" #include "execute.h" +#include "configdir.h" static void print_matches(ToxWindow *self, Tox *m, const void *list, int n_items, int size) { @@ -62,11 +63,13 @@ static void get_str_match(ToxWindow *self, char *match, char (*matches)[MAX_STR_ int i; for (i = 0; i < MAX_STR_SIZE; ++i) { - char ch = matches[0][i]; + char ch1 = matches[0][i]; int j; for (j = 0; j < n; ++j) { - if (matches[j][i] != ch) { + char ch2 = matches[j][i]; + + if (ch1 != ch2 || !ch1) { strcpy(match, matches[0]); match[i] = '\0'; return; @@ -198,25 +201,58 @@ int complete_line(ToxWindow *self, const void *list, int n_items, int size) return diff; } -/* matches /sendfile "" line to matching directories. +/* transforms a sendfile tab complete contaning the shorthand "~/" into the full home directory.*/ +static void complt_home_dir(ToxWindow *self, char *path) +{ + ChatContext *ctx = self->chatwin; - if only one match, auto-complete line. - return diff between old len and new len of ctx->line, or -1 if no matches + char homedir[MAX_STR_SIZE]; + get_home_dir(homedir, sizeof(homedir)); + + char newline[MAX_STR_SIZE]; + const char *isqt = !strchr(path, '\"') ? "\"" : ""; + snprintf(newline, sizeof(newline), "/sendfile %s%s/", isqt, homedir); + + 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; +} + +/* attempts to match /sendfile "" line to matching directories. + + if only one match, auto-complete line. + return diff between old len and new len of ctx->line, -1 if no matches */ #define MAX_DIRS 256 -int dir_match(ToxWindow *self, Tox *m, const wchar_t *line) +int dir_match(ToxWindow *self, Tox *m, wchar_t *line) { char b_path[MAX_STR_SIZE]; char b_name[MAX_STR_SIZE]; if (wcs_to_mbs_buf(b_path, line, sizeof(b_path)) == -1) + return -1; + + if (!strncmp(b_path, "\"~/", 3) || !strncmp(b_path, "~/", 2)) { + complt_home_dir(self, b_path); return -1; + } int si = char_rfind(b_path, '/', strlen(b_path)); if (!b_path[0]) { /* list everything in pwd */ - strcpy(b_path, "."); + b_path[0] = '.'; + b_path[1] = '\0'; } else if (!si && b_path[0] != '/') { /* look for matches in pwd */ char tmp[MAX_STR_SIZE]; snprintf(tmp, sizeof(tmp), ".%s", b_path); diff --git a/src/configdir.c b/src/configdir.c index 251f0df..4c6ae4d 100644 --- a/src/configdir.c +++ b/src/configdir.c @@ -31,51 +31,53 @@ #include "configdir.h" -/** - * @brief Get the users config directory. - * - * This is without a trailing slash. - * - * @return The users config dir or NULL on error. - */ -char *get_user_config_dir(void) +/* get the user's home directory */ +void get_home_dir(char *home, int size) { - char *user_config_dir; - -#ifndef NSS_BUFLEN_PASSWD -#define NSS_BUFLEN_PASSWD 4096 -#endif /* NSS_BUFLEN_PASSWD */ - struct passwd pwd; struct passwd *pwdbuf; - const char *home; + const char *hmstr; char buf[NSS_BUFLEN_PASSWD]; - size_t len; int rc; rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf); if (rc == 0) { - home = pwd.pw_dir; + hmstr = pwd.pw_dir; } else { - home = getenv("HOME"); + hmstr = getenv("HOME"); - if (home == NULL) { - return NULL; - } + if (hmstr == NULL) + return; - /* env variables can be tainted */ - snprintf(buf, sizeof(buf), "%s", home); - home = buf; + snprintf(buf, sizeof(buf), "%s", hmstr); + hmstr = buf; } + snprintf(home, size, "%s", hmstr); +} + +/** + * @brief Get the user's config directory. + * + * This is without a trailing slash. Resulting string must be freed. + * + * @return The users config dir or NULL on error. + */ +char *get_user_config_dir(void) +{ + char home[NSS_BUFLEN_PASSWD]; + get_home_dir(home, sizeof(home)); + + char *user_config_dir; + size_t len; + # if defined(__APPLE__) len = strlen(home) + strlen("/Library/Application Support") + 1; user_config_dir = malloc(len); - if (user_config_dir == NULL) { + if (user_config_dir == NULL) return NULL; - } snprintf(user_config_dir, len, "%s/Library/Application Support", home); # else /* __APPLE__ */ @@ -86,9 +88,8 @@ char *get_user_config_dir(void) len = strlen(home) + strlen("/.config") + 1; user_config_dir = malloc(len); - if (user_config_dir == NULL) { + if (user_config_dir == NULL) return NULL; - } snprintf(user_config_dir, len, "%s/.config", home); } else { @@ -98,7 +99,6 @@ char *get_user_config_dir(void) # endif /* __APPLE__ */ return user_config_dir; -#undef NSS_BUFLEN_PASSWD } /* diff --git a/src/configdir.h b/src/configdir.h index 0a8b01d..deded0e 100644 --- a/src/configdir.h +++ b/src/configdir.h @@ -23,6 +23,10 @@ #ifndef _configdir_h #define _configdir_h +#ifndef NSS_BUFLEN_PASSWD +#define NSS_BUFLEN_PASSWD 4096 +#endif + #define CONFIGDIR "/tox/" #ifndef S_ISDIR @@ -30,7 +34,7 @@ #endif char *get_user_config_dir(void); - +void get_home_dir(char *home, int size); int create_user_config_dir(char *path); #endif /* #define _configdir_h */ diff --git a/src/prompt.c b/src/prompt.c index 0fdca1b..a333544 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -59,7 +59,6 @@ const char glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE] = { { "/exit" }, { "/groupchat" }, { "/help" }, - { "/join" }, { "/log" }, { "/myid" }, { "/nick" }, diff --git a/src/prompt.h b/src/prompt.h index b2b3620..edc758b 100644 --- a/src/prompt.h +++ b/src/prompt.h @@ -27,9 +27,9 @@ #include "windows.h" #ifdef _AUDIO -#define AC_NUM_GLOB_COMMANDS 17 +#define AC_NUM_GLOB_COMMANDS 16 #else -#define AC_NUM_GLOB_COMMANDS 15 +#define AC_NUM_GLOB_COMMANDS 14 #endif /* _AUDIO */ ToxWindow new_prompt(void); diff --git a/src/toxic.c b/src/toxic.c index 269e68f..68724be 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -568,7 +568,7 @@ int main(int argc, char *argv[]) /* Make sure all written files are read/writeable only by the current user. */ umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); -// signal(SIGINT, catch_SIGINT); + signal(SIGINT, catch_SIGINT); config_err = create_user_config_dir(user_config_dir);