diff options
-rw-r--r-- | arr.c | 9 | ||||
-rw-r--r-- | base.h | 3 | ||||
-rw-r--r-- | ui.c | 51 |
3 files changed, 39 insertions, 24 deletions
@@ -226,10 +226,19 @@ static void arrcstr_append_strn_(char **a, char const *s, size_t s_len) { memcpy(*a + curr_len, s, s_len + 1); } +static void arrcstr_shrink_(char **a, u32 new_len) { + ArrHeader *hdr = arr_hdr_(*a); + assert(hdr->cap > new_len); + hdr->len = new_len; + (*a)[new_len] = '\0'; +} + // append to a C-string array #define arrcstr_append_str(a, s) arrcstr_append_strn_(&(a), (s), strlen(s)) // take at most n bytes from s #define arrcstr_append_strn(a, s, n) arrcstr_append_strn_(&(a), (s), (n)) +// make the string smaller +#define arrcstr_shrink(a, n) arrcstr_shrink_(&(a), (n)) static void arr_test(void) { @@ -10,9 +10,12 @@ #include <shlobj.h> #define PATH_SEPARATOR '\\' #define PATH_SEPARATOR_STR "\\" +// on windows, let the user use forwards slashes as well as backslashes +#define ALL_PATH_SEPARATORS "\\/" #else #define PATH_SEPARATOR '/' #define PATH_SEPARATOR_STR "/" +#define ALL_PATH_SEPARATORS "/" #endif #include <stdbool.h> @@ -42,30 +42,33 @@ static int qsort_file_entry_cmp(void const *av, void const *bv) { return strcmp_case_insensitive(a->name, b->name); } -// change directory of file selector. -void file_selector_cd(Ted *ted, FileSelector *fs, char const *path) { - // @TODO: handle .. properly - if (path[0] == PATH_SEPARATOR -#if _WIN32 - // check for, e.g. C:\ at start of path - || (strlen(path) >= 3 && path[1] == ':' && path[2] == '\\') -#endif - ) { - // this is an absolute path. discard our previous cwd. - arr_clear(fs->cwd); +// cd to the directory `name`. `name` cannot include any path separators. +static void file_selector_cd(FileSelector *fs, char const *name) { + if (*name == '\0' || streq(name, ".")) { + // no name, or . + return; } - size_t path_len = strlen(path); - if (!path_len) return; - if (path_len > 1 && path[path_len - 1] == PATH_SEPARATOR) - --path_len; - - // add path separator to end - arrcstr_append_str(fs->cwd, PATH_SEPARATOR_STR); - arrcstr_append_strn(fs->cwd, path, path_len); - - // clear search term - buffer_clear(&ted->line_buffer); + if (streq(name, "..")) { + // .. + char *last_sep = strrchr(fs->cwd, PATH_SEPARATOR); + if (last_sep) { + if (last_sep == fs->cwd // this is the starting "/" of a path + #if _WIN32 + || (last_sep == fs->cwd + 2 && fs->cwd[1] == ':') // this is the \ of C:\ . + #endif + ) { + arrcstr_shrink(fs->cwd, (u32)(last_sep + 1 - fs->cwd)); // include the last separator + } else { + arrcstr_shrink(fs->cwd, (u32)(last_sep - fs->cwd)); + } + } + } else { + // add path separator to end + arrcstr_append_str(fs->cwd, PATH_SEPARATOR_STR); + // add name itself + arrcstr_append_str(fs->cwd, name); + } } // returns the name of the selected file, or NULL @@ -99,7 +102,7 @@ static char *file_selector_update(Ted *ted, FileSelector *fs) { if (path) return str_dup(path); break; case FS_DIRECTORY: - file_selector_cd(ted, fs, name); + file_selector_cd(fs, name); break; default: break; } @@ -115,7 +118,7 @@ static char *file_selector_update(Ted *ted, FileSelector *fs) { if (path) return str_dup(path); break; case FS_DIRECTORY: - file_selector_cd(ted, fs, name); + file_selector_cd(fs, name); break; default: break; } |