diff --git a/source/core/fs.c b/source/core/fs.c index 0c9d706..d68f3c5 100644 --- a/source/core/fs.c +++ b/source/core/fs.c @@ -197,6 +197,13 @@ FS_MediaType fs_get_title_destination(u64 titleId) { } bool fs_filter_cias(void* data, const char* name, u32 attributes) { + if(data != NULL) { + fs_filter_data* filterData = (fs_filter_data*) data; + if(filterData->parentFilter != NULL && !filterData->parentFilter(filterData->parentFilterData, name, attributes)) { + return false; + } + } + if((attributes & FS_ATTRIBUTE_DIRECTORY) != 0) { return false; } @@ -206,6 +213,13 @@ bool fs_filter_cias(void* data, const char* name, u32 attributes) { } bool fs_filter_tickets(void* data, const char* name, u32 attributes) { + if(data != NULL) { + fs_filter_data* filterData = (fs_filter_data*) data; + if(filterData->parentFilter != NULL && !filterData->parentFilter(filterData->parentFilterData, name, attributes)) { + return false; + } + } + if((attributes & FS_ATTRIBUTE_DIRECTORY) != 0) { return false; } diff --git a/source/core/fs.h b/source/core/fs.h index 087abbc..2356794 100644 --- a/source/core/fs.h +++ b/source/core/fs.h @@ -3,6 +3,11 @@ #define FILE_NAME_MAX 256 #define FILE_PATH_MAX 512 +typedef struct fs_filter_data_s { + bool (*parentFilter)(void* data, const char* name, u32 attributes); + void* parentFilterData; +} fs_filter_data; + bool fs_is_dir(FS_Archive archive, const char* path); Result fs_ensure_dir(FS_Archive archive, const char* path); diff --git a/source/fbi/action/action.h b/source/fbi/action/action.h index c3c7550..c39fef8 100644 --- a/source/fbi/action/action.h +++ b/source/fbi/action/action.h @@ -16,12 +16,12 @@ void action_delete_system_save_data(linked_list* items, list_item* selected); void action_install_cia(linked_list* items, list_item* selected); void action_install_cia_delete(linked_list* items, list_item* selected); -void action_install_cias(linked_list* items, list_item* selected); -void action_install_cias_delete(linked_list* items, list_item* selected); +void action_install_cias(linked_list* items, list_item* selected, bool (*filter)(void* data, const char* name, u32 attributes), void* filterData); +void action_install_cias_delete(linked_list* items, list_item* selected, bool (*filter)(void* data, const char* name, u32 attributes), void* filterData); void action_install_ticket(linked_list* items, list_item* selected); void action_install_ticket_delete(linked_list* items, list_item* selected); -void action_install_tickets(linked_list* items, list_item* selected); -void action_install_tickets_delete(linked_list* items, list_item* selected); +void action_install_tickets(linked_list* items, list_item* selected, bool (*filter)(void* data, const char* name, u32 attributes), void* filterData); +void action_install_tickets_delete(linked_list* items, list_item* selected, bool (*filter)(void* data, const char* name, u32 attributes), void* filterData); void action_delete_file(linked_list* items, list_item* selected); void action_delete_dir(linked_list* items, list_item* selected); void action_delete_dir_contents(linked_list* items, list_item* selected); diff --git a/source/fbi/action/installcias.c b/source/fbi/action/installcias.c index 5f4062e..2ef0870 100644 --- a/source/fbi/action/installcias.c +++ b/source/fbi/action/installcias.c @@ -262,6 +262,7 @@ typedef struct { const char* message; + fs_filter_data filterData; populate_files_data popData; } install_cias_loading_data; @@ -298,7 +299,7 @@ static void action_install_cias_loading_update(ui_view* view, void* data, float* snprintf(text, PROGRESS_TEXT_MAX, "Fetching CIA list..."); } -static void action_install_cias_internal(linked_list* items, list_item* selected, const char* message, bool delete) { +static void action_install_cias_internal(linked_list* items, list_item* selected, bool (*filter)(void* data, const char* name, u32 attributes), void* filterData, const char* message, bool delete) { install_cias_data* data = (install_cias_data*) calloc(1, sizeof(install_cias_data)); if(data == NULL) { error_display(NULL, NULL, "Failed to allocate install CIAs data."); @@ -365,6 +366,9 @@ static void action_install_cias_internal(linked_list* items, list_item* selected loadingData->installData = data; loadingData->message = message; + loadingData->filterData.parentFilter = filter; + loadingData->filterData.parentFilterData = filterData; + loadingData->popData.items = &data->contents; loadingData->popData.archive = data->target->archive; string_copy(loadingData->popData.path, data->target->path, FILE_PATH_MAX); @@ -372,7 +376,7 @@ static void action_install_cias_internal(linked_list* items, list_item* selected loadingData->popData.includeBase = !(data->target->attributes & FS_ATTRIBUTE_DIRECTORY); loadingData->popData.meta = true; loadingData->popData.filter = fs_filter_cias; - loadingData->popData.filterData = NULL; + loadingData->popData.filterData = &loadingData->filterData; Result listRes = task_populate_files(&loadingData->popData); if(R_FAILED(listRes)) { @@ -387,17 +391,17 @@ static void action_install_cias_internal(linked_list* items, list_item* selected } void action_install_cia(linked_list* items, list_item* selected) { - action_install_cias_internal(items, selected, "Install the selected CIA?", false); + action_install_cias_internal(items, selected, NULL, NULL, "Install the selected CIA?", false); } void action_install_cia_delete(linked_list* items, list_item* selected) { - action_install_cias_internal(items, selected, "Install and delete the selected CIA?", true); + action_install_cias_internal(items, selected, NULL, NULL, "Install and delete the selected CIA?", true); } -void action_install_cias(linked_list* items, list_item* selected) { - action_install_cias_internal(items, selected, "Install all CIAs in the current directory?", false); +void action_install_cias(linked_list* items, list_item* selected, bool (*filter)(void* data, const char* name, u32 attributes), void* filterData) { + action_install_cias_internal(items, selected, filter, filterData, "Install all CIAs in the current directory?", false); } -void action_install_cias_delete(linked_list* items, list_item* selected) { - action_install_cias_internal(items, selected, "Install and delete all CIAs in the current directory?", true); +void action_install_cias_delete(linked_list* items, list_item* selected, bool (*filter)(void* data, const char* name, u32 attributes), void* filterData) { + action_install_cias_internal(items, selected, filter, filterData, "Install and delete all CIAs in the current directory?", true); } \ No newline at end of file diff --git a/source/fbi/action/installtickets.c b/source/fbi/action/installtickets.c index 0d3f9b6..07db371 100644 --- a/source/fbi/action/installtickets.c +++ b/source/fbi/action/installtickets.c @@ -211,6 +211,7 @@ typedef struct { const char* message; + fs_filter_data filterData; populate_files_data popData; } install_tickets_loading_data; @@ -247,7 +248,7 @@ static void action_install_tickets_loading_update(ui_view* view, void* data, flo snprintf(text, PROGRESS_TEXT_MAX, "Fetching ticket list..."); } -static void action_install_tickets_internal(linked_list* items, list_item* selected, const char* message, bool delete) { +static void action_install_tickets_internal(linked_list* items, list_item* selected, bool (*filter)(void* data, const char* name, u32 attributes), void* filterData, const char* message, bool delete) { install_tickets_data* data = (install_tickets_data*) calloc(1, sizeof(install_tickets_data)); if(data == NULL) { error_display(NULL, NULL, "Failed to allocate install tickets data."); @@ -312,6 +313,9 @@ static void action_install_tickets_internal(linked_list* items, list_item* selec loadingData->installData = data; loadingData->message = message; + loadingData->filterData.parentFilter = filter; + loadingData->filterData.parentFilterData = filterData; + loadingData->popData.items = &data->contents; loadingData->popData.archive = data->target->archive; string_copy(loadingData->popData.path, data->target->path, FILE_PATH_MAX); @@ -319,7 +323,7 @@ static void action_install_tickets_internal(linked_list* items, list_item* selec loadingData->popData.includeBase = !(data->target->attributes & FS_ATTRIBUTE_DIRECTORY); loadingData->popData.meta = true; loadingData->popData.filter = fs_filter_tickets; - loadingData->popData.filterData = NULL; + loadingData->popData.filterData = &loadingData->filterData; Result listRes = task_populate_files(&loadingData->popData); if(R_FAILED(listRes)) { @@ -334,17 +338,17 @@ static void action_install_tickets_internal(linked_list* items, list_item* selec } void action_install_ticket(linked_list* items, list_item* selected) { - action_install_tickets_internal(items, selected, "Install the selected ticket?", false); + action_install_tickets_internal(items, selected, NULL, NULL, "Install the selected ticket?", false); } void action_install_ticket_delete(linked_list* items, list_item* selected) { - action_install_tickets_internal(items, selected, "Install and delete the selected ticket?", true); + action_install_tickets_internal(items, selected, NULL, NULL, "Install and delete the selected ticket?", true); } -void action_install_tickets(linked_list* items, list_item* selected) { - action_install_tickets_internal(items, selected, "Install all tickets in the current directory?", false); +void action_install_tickets(linked_list* items, list_item* selected, bool (*filter)(void* data, const char* name, u32 attributes), void* filterData) { + action_install_tickets_internal(items, selected, filter, filterData, "Install all tickets in the current directory?", false); } -void action_install_tickets_delete(linked_list* items, list_item* selected) { - action_install_tickets_internal(items, selected, "Install and delete all tickets in the current directory?", true); +void action_install_tickets_delete(linked_list* items, list_item* selected, bool (*filter)(void* data, const char* name, u32 attributes), void* filterData) { + action_install_tickets_internal(items, selected, filter, filterData, "Install and delete all tickets in the current directory?", true); } \ No newline at end of file diff --git a/source/fbi/files.c b/source/fbi/files.c index 60ac921..90ecd94 100644 --- a/source/fbi/files.c +++ b/source/fbi/files.c @@ -62,6 +62,24 @@ typedef struct { bool containsTickets; } files_action_data; +static bool files_filter(void* data, const char* name, u32 attributes) { + files_data* listData = (files_data*) data; + + if((attributes & FS_ATTRIBUTE_HIDDEN) != 0 && !listData->showHidden) { + return false; + } + + if((attributes & FS_ATTRIBUTE_DIRECTORY) != 0) { + return listData->showDirectories; + } else { + if((fs_filter_cias(NULL, name, attributes) && !listData->showCias) || (fs_filter_tickets(NULL, name, attributes) && !listData->showTickets)) { + return false; + } + + return listData->showFiles; + } +} + static void files_action_draw_top(ui_view* view, void* data, float x1, float y1, float x2, float y2, list_item* selected) { task_draw_file_info(view, ((files_action_data*) data)->selected->data, x1, y1, x2, y2); } @@ -79,7 +97,7 @@ static void files_action_update(ui_view* view, void* data, linked_list* items, l } if(selected != NULL && (selected->data != NULL || selected == © || selected == ©_all_contents) && (selectedTouched || (hidKeysDown() & KEY_A))) { - void(*action)(linked_list*, list_item*) = (void(*)(linked_list*, list_item*)) selected->data; + void* action = selected->data; ui_pop(); list_destroy(view); @@ -93,8 +111,14 @@ static void files_action_update(ui_view* view, void* data, linked_list* items, l } else { error_display_res(info, task_draw_file_info, res, "Failed to copy to clipboard."); } + } else if(selected == &install_all_cias || selected == &install_and_delete_all_cias || selected == &install_all_tickets || selected == &install_and_delete_all_tickets) { + void (*filteredAction)(linked_list*, list_item*, bool (*)(void*, const char*, u32), void*) = action; + + filteredAction(actionData->items, actionData->selected, files_filter, actionData->parent); } else { - action(actionData->items, actionData->selected); + void (*normalAction)(linked_list*, list_item*) = action; + + normalAction(actionData->items, actionData->selected); } free(data); @@ -342,24 +366,6 @@ static void files_update(ui_view* view, void* data, linked_list* items, list_ite } } -static bool files_filter(void* data, const char* name, u32 attributes) { - files_data* listData = (files_data*) data; - - if((attributes & FS_ATTRIBUTE_HIDDEN) != 0 && !listData->showHidden) { - return false; - } - - if((attributes & FS_ATTRIBUTE_DIRECTORY) != 0) { - return listData->showDirectories; - } else { - if((fs_filter_cias(NULL, name, attributes) && !listData->showCias) || (fs_filter_tickets(NULL, name, attributes) && !listData->showTickets)) { - return false; - } - - return listData->showFiles; - } -} - void files_open(FS_ArchiveID archiveId, FS_Path archivePath) { files_data* data = (files_data*) calloc(1, sizeof(files_data)); if(data == NULL) {