diff options
-rw-r--r-- | colors.h | 4 | ||||
-rw-r--r-- | filesystem-posix.c | 23 | ||||
-rw-r--r-- | filesystem-win.c | 20 | ||||
-rw-r--r-- | filesystem.h | 26 | ||||
-rw-r--r-- | menu.c | 54 | ||||
-rw-r--r-- | ted.cfg | 5 |
6 files changed, 98 insertions, 34 deletions
@@ -6,6 +6,8 @@ ENUM_U16 { COLOR_CURSOR_LINE_BG, COLOR_BORDER, COLOR_TEXT, + COLOR_TEXT_FOLDER, + COLOR_TEXT_OTHER, COLOR_SELECTION_BG, COLOR_MENU_BACKDROP, COLOR_MENU_BG, @@ -26,6 +28,8 @@ static ColorName const color_names[COLOR_COUNT] = { {COLOR_CURSOR_LINE_BG, "cursor-line-bg"}, {COLOR_BORDER, "border"}, {COLOR_TEXT, "text"}, + {COLOR_TEXT_FOLDER, "text-folder"}, + {COLOR_TEXT_OTHER, "text-other"}, {COLOR_SELECTION_BG, "selection-bg"}, {COLOR_MENU_BACKDROP, "menu-backdrop"}, {COLOR_MENU_BG, "menu-bg"}, diff --git a/filesystem-posix.c b/filesystem-posix.c index e2ff82e..1a23eff 100644 --- a/filesystem-posix.c +++ b/filesystem-posix.c @@ -1,21 +1,26 @@ +#include "filesystem.h" #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <dirent.h> #include <errno.h> -// Does this file exist? Returns false for directories. -static bool fs_file_exists(char const *path) { +FsType fs_path_type(char const *path) { struct stat statbuf = {0}; if (stat(path, &statbuf) != 0) - return false; - return S_ISREG(statbuf.st_mode); + return FS_NON_EXISTENT; + if (S_ISREG(statbuf.st_mode)) + return FS_FILE; + if (S_ISDIR(statbuf.st_mode)) + return FS_DIRECTORY; + return FS_OTHER; } -// Returns a NULL-terminated array of the files/directories in this directory, or NULL if the directory does not exist. -// When you're done with the file names, call free on each one, then on the array. -// NOTE: The files aren't returned in any particular order! -static char **fs_list_directory(char const *dirname) { +bool fs_file_exists(char const *path) { + return fs_path_type(path) == FS_FILE; +} + +char **fs_list_directory(char const *dirname) { char **ret = NULL; DIR *dir = opendir(dirname); if (dir) { @@ -43,7 +48,7 @@ static char **fs_list_directory(char const *dirname) { return ret; } -static int fs_mkdir(char const *path) { +int fs_mkdir(char const *path) { if (mkdir(path, 0755) == 0) { // directory created successfully return 1; diff --git a/filesystem-win.c b/filesystem-win.c index 25b8d95..7c40820 100644 --- a/filesystem-win.c +++ b/filesystem-win.c @@ -1,15 +1,23 @@ -// see filesystem-posix.c for function documentation +#include "filesystem.h" #include <sys/types.h> #include <sys/stat.h> -static bool fs_file_exists(char const *path) { +FsType fs_path_type(char const *path) { struct _stat statbuf = {0}; if (_stat(path, &statbuf) != 0) - return false; - return (statbuf.st_mode & _S_IFREG) != 0; + return FS_NON_EXISTENT; + if (statbuf.st_mode & _S_IFREG) + return FS_FILE; + if (statbuf.st_mode & _S_IFDIR) + return FS_DIRECTORY; + return FS_OTHER; } -static char **fs_list_directory(char const *dirname) { +bool fs_file_exists(char const *path) { + return fs_path_type(path) == FS_FILE; +} + +char **fs_list_directory(char const *dirname) { char file_pattern[256] = {0}; char **ret = NULL; WIN32_FIND_DATA find_data; @@ -46,7 +54,7 @@ static char **fs_list_directory(char const *dirname) { return ret; } -static int fs_mkdir(char const *path) { +int fs_mkdir(char const *path) { if (CreateDirectoryA(path, NULL)) { // directory created successfully return 1; diff --git a/filesystem.h b/filesystem.h new file mode 100644 index 0000000..424b824 --- /dev/null +++ b/filesystem.h @@ -0,0 +1,26 @@ +#ifndef FILESYSTEM_H_ +#define FILESYSTEM_H_ + +typedef enum { + FS_NON_EXISTENT, + FS_FILE, + FS_DIRECTORY, + FS_OTHER +} FsType; + +// returns what kind of thing this is. +FsType fs_path_type(char const *path); +// Does this file exist? Returns false for directories. +bool fs_file_exists(char const *path); +// Returns a NULL-terminated array of the files/directories in this directory, or NULL if the directory does not exist. +// When you're done with the file names, call free on each one, then on the array. +// NOTE: The files aren't returned in any particular order! +char **fs_list_directory(char const *dirname); +// create the directory specified by `path` +// returns: +// 1 if the directory was created successfully +// 0 if the directory already exists +// -1 if the path already exists, but it's not a directory, or if there's another error (e.g. don't have permission to create directory). +int fs_mkdir(char const *path); + +#endif // FILESYSTEM_H_
\ No newline at end of file @@ -67,30 +67,35 @@ static void menu_render(Ted *ted, Menu menu) { buffer_render(&ted->line_buffer, line_buffer_x1, line_buffer_y1, line_buffer_x2, line_buffer_y2); - char **files = fs_list_directory(directory); - if (files) { - - u32 nfiles = 0; - for (char **p = files; *p; ++p) ++nfiles; - + char **entries = fs_list_directory(directory); + u32 nentries = 0; + if (entries) { + for (char **p = entries; *p; ++p) + ++nentries; + } + FsType *entry_types = calloc(nentries, sizeof *entry_types); + if (entries && (entry_types || !nentries)) { if (search_term && *search_term) { - // filter files based on search term + // filter entries based on search term u32 in, out = 0; - for (in = 0; in < nfiles; ++in) { - if (stristr(files[in], search_term)) { - files[out++] = files[in]; + for (in = 0; in < nentries; ++in) { + if (stristr(entries[in], search_term)) { + entries[out++] = entries[in]; } } - nfiles = out; + nentries = out; + } + for (u32 i = 0; i < nentries; ++i) { + entry_types[i] = fs_path_type(entries[i]); } - qsort(files, nfiles, sizeof *files, str_qsort_case_insensitive_cmp); + qsort(entries, nentries, sizeof *entries, str_qsort_case_insensitive_cmp); char const *file_to_open = NULL; { // render file names float start_x = menu_x1, start_y = line_buffer_y2 + inner_padding; float x = start_x, y = start_y; - for (u32 i = 0; i < nfiles; ++i) { + for (u32 i = 0; i < nentries; ++i) { // highlight entry user is mousing over if (y >= menu_y2) break; Rect r = rect4(x, y, menu_x2, minf(y + char_height, menu_y2)); @@ -104,16 +109,26 @@ static void menu_render(Ted *ted, Menu menu) { for (u32 c = 0; c < ted->nmouse_clicks[SDL_BUTTON_LEFT]; ++c) { if (rect_contains_point(r, ted->mouse_clicks[SDL_BUTTON_LEFT][c])) { // this file got clicked on! - file_to_open = files[i]; + file_to_open = entries[i]; } } } x = start_x, y = start_y; TextRenderState text_render_state = {.min_x = menu_x1, .max_x = menu_x2, .min_y = menu_y1, .max_y = menu_y2, .render = true}; - gl_color_rgba(colors[COLOR_TEXT]); - for (u32 i = 0; i < nfiles; ++i) { + // render file names themselves + for (u32 i = 0; i < nentries; ++i) { if (y >= menu_y2) break; - text_render_with_state(font, &text_render_state, files[i], x, y); + switch (entry_types[i]) { + case FS_FILE: + gl_color_rgba(colors[COLOR_TEXT]); + break; + case FS_DIRECTORY: + gl_color_rgba(colors[COLOR_TEXT_FOLDER]); + default: + gl_color_rgba(colors[COLOR_TEXT_OTHER]); + break; + } + text_render_with_state(font, &text_render_state, entries[i], x, y); y += char_height; } } @@ -123,9 +138,10 @@ static void menu_render(Ted *ted, Menu menu) { menu_close(ted, false); } - for (u32 i = 0; i < nfiles; ++i) free(files[i]); - free(files); + for (u32 i = 0; i < nentries; ++i) free(entries[i]); } + free(entry_types); + free(entries); free(search_term); } } @@ -69,6 +69,11 @@ cursor-line-bg = #222 cursor = #3ff selection-bg = #36aa text = #fff +# For example, in the open menu it is nice to have a visual distinction between folders and files. +# This is the color used for folders. +text-folder = #88f +# Used for things that are neither files nor folders. +text-other = #8f8 bg = #001 # The entire screen gets filled with this color when a menu (e.g. the "open" menu) is shown. # By making it transparent, we can dim everything else while the menu is open. |