From 95a9445ae01764b235fa0e9af4a877eef770f78c Mon Sep 17 00:00:00 2001 From: hgn Date: Thu, 20 Mar 2025 16:48:10 +0000 Subject: [PATCH] Users home drive & sort files using radix tree --- .gitmodules | 3 ++ submodules/rax | 1 + vg_log.h | 2 +- vg_msg.c | 4 +-- vg_string.h | 3 +- vg_ui/filebrowser.c | 83 ++++++++++++++++++++++++++++++++++++--------- 6 files changed, 75 insertions(+), 21 deletions(-) create mode 160000 submodules/rax diff --git a/.gitmodules b/.gitmodules index 13a708d..00137dc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ [submodule "submodules/SDL_GameControllerDB"] path = submodules/SDL_GameControllerDB url = https://github.com/gabomdq/SDL_GameControllerDB.git +[submodule "submodules/rax"] + path = submodules/rax + url = https://github.com/antirez/rax.git diff --git a/submodules/rax b/submodules/rax new file mode 160000 index 0000000..1927550 --- /dev/null +++ b/submodules/rax @@ -0,0 +1 @@ +Subproject commit 1927550cb218ec3c3dda8b39d82d1d019bf0476d diff --git a/vg_log.h b/vg_log.h index 1af7872..37e827e 100644 --- a/vg_log.h +++ b/vg_log.h @@ -33,7 +33,7 @@ #define PRINTF_v3f( V3 ) "%.4f %.4f %.4f\n", V3[0], V3[1], V3[2] #define PRINTF_v4f( V4 ) "%.4f %.4f %.4f %.4f\n", V4[0], V4[1], V4[2], V4[3] -#if VG_32 +#ifdef _WIN32 #define PRINTF_U64 "%llu" #else #define PRINTF_U64 "%lu" diff --git a/vg_msg.c b/vg_msg.c index facd66b..7e1eee1 100644 --- a/vg_msg.c +++ b/vg_msg.c @@ -472,7 +472,7 @@ void vg_msg_print( vg_msg *msg, u32 len ) if( base == k_vg_msg_unsigned ){ printf( -#ifdef VG_32 +#ifdef _WIN32 "%llu" #else "%lu" @@ -481,7 +481,7 @@ void vg_msg_print( vg_msg *msg, u32 len ) } else if( base == k_vg_msg_signed ){ printf( -#ifdef VG_32 +#ifdef _WIN32 "%lld" #else "%ld" diff --git a/vg_string.h b/vg_string.h index b8aa209..767f40d 100644 --- a/vg_string.h +++ b/vg_string.h @@ -59,8 +59,7 @@ enum strncpy_behaviour k_strncpy_overflow_fatal = 2 }; -u32 vg_strncpy( const char *src, char *dst, u32 len, - enum strncpy_behaviour behaviour ); +u32 vg_strncpy( const char *src, char *dst, u32 len, enum strncpy_behaviour behaviour ); u32 vg_strdjb2( const char *str ); int vg_strdjb2_eq( const char *s1, u32 h1, const char *s2, u32 h2 ); diff --git a/vg_ui/filebrowser.c b/vg_ui/filebrowser.c index 94cc9e7..64fd295 100644 --- a/vg_ui/filebrowser.c +++ b/vg_ui/filebrowser.c @@ -1,4 +1,11 @@ #include "vg/vg_ui/filebrowser.h" +#ifdef _WIN32 +#include +#include +#endif + +#include "vg/submodules/rax/rax.h" +#include "vg/submodules/rax/rax.c" void vg_filebrowser_init( struct vg_filebrowser *browser ) { @@ -16,8 +23,25 @@ void vg_filebrowser_init( struct vg_filebrowser *browser ) void vg_filebrowser_set_path_to_home( struct vg_filebrowser *browser ) { - // TODO - strcpy( browser->current_path, "/home/harry" ); +#ifdef _WIN32 + u16 *path = NULL; + if( SHGetKnownFolderPath( &FOLDERID_Documents, 0, NULL, &path ) == S_OK ) + { + if( !WideCharToMultiByte( CP_UTF8, 0, path, -1, browser->current_path, sizeof(browser->current_path), NULL, NULL ) ) + { + vg_error( "WideCharToMultiByte failed... defaulting to C:/\n" ); + vg_strncpy( "C:/", browser->current_path, sizeof(browser->current_path), k_strncpy_always_add_null ); + } + } + else + { + vg_error( "SHGetKnownFolderPath failed... defaulting to C:/\n" ); + vg_strncpy( "C:/", browser->current_path, sizeof(browser->current_path), k_strncpy_always_add_null ); + } + CoTaskMemFree( path ); +#else + vg_strncpy( getenv("HOME"), browser->current_path, sizeof(browser->current_path), k_strncpy_always_add_null ); +#endif } static bool vg_filebrowser_up( struct vg_filebrowser *browser ) @@ -322,10 +346,6 @@ void vg_filebrowser_populate( struct vg_filebrowser *browser ) browser->view_top_index = 0; browser->slider_value = 0.0f; - struct vg_filebrowser_entry *folder_list_head = NULL, - *folder_list_tail = NULL, - *file_list_head = NULL; - if( browser->open_result == k_dir_open_is_file ) { if( vg_filebrowser_up( browser ) ) @@ -339,6 +359,9 @@ void vg_filebrowser_populate( struct vg_filebrowser *browser ) return; } + rax *rt_files = raxNew(), + *rt_dirs = raxNew(); + while( vg_dir_next_entry( &dir ) ) { enum vg_entry_type type = vg_dir_entry_type( &dir ); @@ -391,31 +414,56 @@ void vg_filebrowser_populate( struct vg_filebrowser *browser ) u32 len = strlen( entry_name ); struct vg_filebrowser_entry *entry = malloc( sizeof(struct vg_filebrowser_entry) + len + 1 ); entry->next = NULL; + entry->prev = NULL; entry->type = type; entry->media_type = media_type; strcpy( entry->name, entry_name ); if( type == k_vg_entry_type_dir ) { - entry->prev = folder_list_head; - if( folder_list_head ) - folder_list_head->next = entry; - else - folder_list_tail = entry; - folder_list_head = entry; + raxInsert( rt_dirs, (u8 *)entry->name, strlen(entry->name), entry, NULL ); } else if( type == k_vg_entry_type_file ) { - entry->prev = file_list_head; - if( file_list_head ) - file_list_head->next = entry; - file_list_head = entry; + raxInsert( rt_files, (u8 *)entry->name, strlen(entry->name), entry, NULL ); } + else + continue; browser->entry_count ++; } vg_dir_close( &dir ); + /* compile lists */ + struct vg_filebrowser_entry *folder_list_head = NULL, + *folder_list_tail = NULL, + *file_list_head = NULL; + raxIterator rt_iter; + raxStart( &rt_iter, rt_files ); + raxSeek( &rt_iter, "$", NULL, 0 ); + while( raxPrev( &rt_iter ) ) + { + struct vg_filebrowser_entry *entry = rt_iter.data; + entry->prev = file_list_head; + if( file_list_head ) + file_list_head->next = entry; + file_list_head = entry; + } + + raxStart( &rt_iter, rt_dirs ); + raxSeek( &rt_iter, "$", NULL, 0 ); + while( raxPrev( &rt_iter ) ) + { + struct vg_filebrowser_entry *entry = rt_iter.data; + entry->prev = folder_list_head; + if( folder_list_head ) + folder_list_head->next = entry; + else + folder_list_tail = entry; + folder_list_head = entry; + } + + /* attatch the two lists */ if( folder_list_head ) { browser->whole_list = folder_list_head; @@ -430,4 +478,7 @@ void vg_filebrowser_populate( struct vg_filebrowser *browser ) } browser->view_top_entry = browser->whole_list; + + raxFree( rt_files ); + raxFree( rt_dirs ); } -- 2.25.1