summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2021-01-22 19:38:37 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2021-01-22 19:38:37 -0500
commit8da3cb956b14a7644f815a1874bdcf29a4cb711d (patch)
treedabbaf21a927fb546cac5228767f7ffe975b380b
parentf2edda528a3babe16d9da48580bdcb696e5fa664 (diff)
got .. to work in the file selector
-rw-r--r--arr.c9
-rw-r--r--base.h3
-rw-r--r--ui.c51
3 files changed, 39 insertions, 24 deletions
diff --git a/arr.c b/arr.c
index 0491ef4..9d2220b 100644
--- a/arr.c
+++ b/arr.c
@@ -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) {
diff --git a/base.h b/base.h
index f6b0452..9ecbda4 100644
--- a/base.h
+++ b/base.h
@@ -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>
diff --git a/ui.c b/ui.c
index 5d31d29..d682e83 100644
--- a/ui.c
+++ b/ui.c
@@ -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;
}