mirror of
https://gitlab.com/Theopse/fbi-i18n-zh.git
synced 2025-06-16 03:59:16 +08:00
Clean up file handling.
This commit is contained in:
parent
a20a389cd9
commit
8583d62ec3
@ -4,7 +4,8 @@
|
|||||||
#include <3ds.h>
|
#include <3ds.h>
|
||||||
|
|
||||||
#include "clipboard.h"
|
#include "clipboard.h"
|
||||||
#include "../task/task.h"
|
#include "util.h"
|
||||||
|
#include "../ui/section/task/task.h"
|
||||||
|
|
||||||
static bool clipboard_has = false;
|
static bool clipboard_has = false;
|
||||||
static bool clipboard_contents_only;
|
static bool clipboard_contents_only;
|
||||||
@ -28,30 +29,29 @@ bool clipboard_is_contents_only() {
|
|||||||
return clipboard_contents_only;
|
return clipboard_contents_only;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result clipboard_set_contents(FS_ArchiveID archiveId, FS_Path* archivePath, const char* path, bool contentsOnly) {
|
Result clipboard_set_contents(FS_Archive archive, const char* path, bool contentsOnly) {
|
||||||
clipboard_clear();
|
clipboard_clear();
|
||||||
|
|
||||||
clipboard_has = true;
|
|
||||||
clipboard_contents_only = contentsOnly;
|
|
||||||
|
|
||||||
strncpy(clipboard_path, path, FILE_PATH_MAX);
|
|
||||||
|
|
||||||
Result res = 0;
|
Result res = 0;
|
||||||
if(R_FAILED(res = FSUSER_OpenArchive(&clipboard_archive, archiveId, *archivePath))) {
|
if(R_SUCCEEDED(res = util_ref_archive(archive))) {
|
||||||
clipboard_clear();
|
clipboard_has = true;
|
||||||
|
clipboard_contents_only = contentsOnly;
|
||||||
|
|
||||||
|
clipboard_archive = archive;
|
||||||
|
strncpy(clipboard_path, path, FILE_PATH_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clipboard_clear() {
|
void clipboard_clear() {
|
||||||
|
if(clipboard_archive != 0) {
|
||||||
|
util_close_archive(clipboard_archive);
|
||||||
|
}
|
||||||
|
|
||||||
clipboard_has = false;
|
clipboard_has = false;
|
||||||
clipboard_contents_only = false;
|
clipboard_contents_only = false;
|
||||||
|
|
||||||
|
clipboard_archive = 0;
|
||||||
memset(clipboard_path, '\0', FILE_PATH_MAX);
|
memset(clipboard_path, '\0', FILE_PATH_MAX);
|
||||||
|
|
||||||
if(clipboard_archive != 0) {
|
|
||||||
FSUSER_CloseArchive(clipboard_archive);
|
|
||||||
clipboard_archive = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,12 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
typedef struct file_info_s file_info;
|
typedef struct file_info_s file_info;
|
||||||
|
|
||||||
bool clipboard_has_contents();
|
bool clipboard_has_contents();
|
||||||
FS_Archive clipboard_get_archive();
|
FS_Archive clipboard_get_archive();
|
||||||
char* clipboard_get_path();
|
char* clipboard_get_path();
|
||||||
bool clipboard_is_contents_only();
|
bool clipboard_is_contents_only();
|
||||||
Result clipboard_set_contents(FS_ArchiveID archiveId, FS_Path* archivePath, const char* path, bool contentsOnly);
|
Result clipboard_set_contents(FS_Archive archive, const char* path, bool contentsOnly);
|
||||||
void clipboard_clear();
|
void clipboard_clear();
|
@ -9,6 +9,7 @@
|
|||||||
#include "../ui/error.h"
|
#include "../ui/error.h"
|
||||||
#include "../ui/list.h"
|
#include "../ui/list.h"
|
||||||
#include "../ui/section/task/task.h"
|
#include "../ui/section/task/task.h"
|
||||||
|
#include "linkedlist.h"
|
||||||
|
|
||||||
extern void cleanup();
|
extern void cleanup();
|
||||||
|
|
||||||
@ -361,24 +362,111 @@ int util_compare_file_infos(const void** p1, const void** p2) {
|
|||||||
list_item* info1 = *(list_item**) p1;
|
list_item* info1 = *(list_item**) p1;
|
||||||
list_item* info2 = *(list_item**) p2;
|
list_item* info2 = *(list_item**) p2;
|
||||||
|
|
||||||
file_info* f1 = (file_info*) info1->data;
|
bool info1Base = strncmp(info1->name, "<current directory>", LIST_ITEM_NAME_MAX) == 0 || strncmp(info1->name, "<current file>", LIST_ITEM_NAME_MAX) == 0;
|
||||||
file_info* f2 = (file_info*) info2->data;
|
bool info2Base = strncmp(info2->name, "<current directory>", LIST_ITEM_NAME_MAX) == 0 || strncmp(info2->name, "<current file>", LIST_ITEM_NAME_MAX) == 0;
|
||||||
|
|
||||||
if(f1->isDirectory && !f2->isDirectory) {
|
if(info1Base && !info2Base) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if(!f1->isDirectory && f2->isDirectory) {
|
} else if(!info1Base && info2Base) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return strcasecmp(f1->name, f2->name);
|
file_info* f1 = (file_info*) info1->data;
|
||||||
|
file_info* f2 = (file_info*) info2->data;
|
||||||
|
|
||||||
|
if(f1->isDirectory && !f2->isDirectory) {
|
||||||
|
return -1;
|
||||||
|
} else if(!f1->isDirectory && f2->isDirectory) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return strncasecmp(f1->name, f2->name, FILE_NAME_MAX);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* path3dsx = NULL;
|
static const char* path_3dsx = NULL;
|
||||||
|
|
||||||
const char* util_get_3dsx_path() {
|
const char* util_get_3dsx_path() {
|
||||||
return path3dsx;
|
return path_3dsx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void util_set_3dsx_path(const char* path) {
|
void util_set_3dsx_path(const char* path) {
|
||||||
path3dsx = path;
|
path_3dsx = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
FS_Archive archive;
|
||||||
|
u32 refs;
|
||||||
|
} archive_ref;
|
||||||
|
|
||||||
|
static linked_list opened_archives;
|
||||||
|
|
||||||
|
static Result util_add_archive_ref(FS_Archive archive) {
|
||||||
|
Result res = 0;
|
||||||
|
|
||||||
|
archive_ref* ref = (archive_ref*) calloc(1, sizeof(archive_ref));
|
||||||
|
if(ref != NULL) {
|
||||||
|
ref->archive = archive;
|
||||||
|
ref->refs = 1;
|
||||||
|
|
||||||
|
linked_list_add(&opened_archives, ref);
|
||||||
|
} else {
|
||||||
|
res = R_FBI_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result util_open_archive(FS_Archive* archive, FS_ArchiveID id, FS_Path path) {
|
||||||
|
if(archive == NULL) {
|
||||||
|
return R_FBI_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result res = 0;
|
||||||
|
|
||||||
|
FS_Archive arch = 0;
|
||||||
|
if(R_SUCCEEDED(res = FSUSER_OpenArchive(&arch, id, path))) {
|
||||||
|
if(R_SUCCEEDED(res = util_add_archive_ref(arch))) {
|
||||||
|
*archive = arch;
|
||||||
|
} else {
|
||||||
|
FSUSER_CloseArchive(arch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result util_ref_archive(FS_Archive archive) {
|
||||||
|
linked_list_iter iter;
|
||||||
|
linked_list_iterate(&opened_archives, &iter);
|
||||||
|
|
||||||
|
while(linked_list_iter_has_next(&iter)) {
|
||||||
|
archive_ref* ref = (archive_ref*) linked_list_iter_next(&iter);
|
||||||
|
if(ref->archive == archive) {
|
||||||
|
ref->refs++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return util_add_archive_ref(archive);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result util_close_archive(FS_Archive archive) {
|
||||||
|
linked_list_iter iter;
|
||||||
|
linked_list_iterate(&opened_archives, &iter);
|
||||||
|
|
||||||
|
while(linked_list_iter_has_next(&iter)) {
|
||||||
|
archive_ref* ref = (archive_ref*) linked_list_iter_next(&iter);
|
||||||
|
if(ref->archive == archive) {
|
||||||
|
ref->refs--;
|
||||||
|
|
||||||
|
if(ref->refs == 0) {
|
||||||
|
linked_list_iter_remove(&iter);
|
||||||
|
free(ref);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FSUSER_CloseArchive(archive);
|
||||||
}
|
}
|
@ -66,3 +66,7 @@ int util_compare_file_infos(const void** p1, const void** p2);
|
|||||||
|
|
||||||
const char* util_get_3dsx_path();
|
const char* util_get_3dsx_path();
|
||||||
void util_set_3dsx_path(const char* path);
|
void util_set_3dsx_path(const char* path);
|
||||||
|
|
||||||
|
Result util_open_archive(FS_Archive* archive, FS_ArchiveID id, FS_Path path);
|
||||||
|
Result util_ref_archive(FS_Archive archive);
|
||||||
|
Result util_close_archive(FS_Archive archive);
|
@ -2,12 +2,12 @@
|
|||||||
|
|
||||||
#include <3ds.h>
|
#include <3ds.h>
|
||||||
|
|
||||||
|
#include "core/clipboard.h"
|
||||||
#include "core/screen.h"
|
#include "core/screen.h"
|
||||||
#include "core/util.h"
|
#include "core/util.h"
|
||||||
#include "svchax/svchax.h"
|
#include "svchax/svchax.h"
|
||||||
#include "ui/mainmenu.h"
|
#include "ui/mainmenu.h"
|
||||||
#include "ui/ui.h"
|
#include "ui/ui.h"
|
||||||
#include "ui/section/action/clipboard.h"
|
|
||||||
#include "ui/section/task/task.h"
|
#include "ui/section/task/task.h"
|
||||||
|
|
||||||
static void* soc_buffer;
|
static void* soc_buffer;
|
||||||
|
@ -22,10 +22,10 @@ typedef struct {
|
|||||||
linked_list contents;
|
linked_list contents;
|
||||||
|
|
||||||
data_op_data deleteInfo;
|
data_op_data deleteInfo;
|
||||||
} delete_contents_data;
|
} delete_data;
|
||||||
|
|
||||||
static void action_delete_contents_draw_top(ui_view* view, void* data, float x1, float y1, float x2, float y2) {
|
static void action_delete_draw_top(ui_view* view, void* data, float x1, float y1, float x2, float y2) {
|
||||||
delete_contents_data* deleteData = (delete_contents_data*) data;
|
delete_data* deleteData = (delete_data*) data;
|
||||||
|
|
||||||
u32 curr = deleteData->deleteInfo.processed;
|
u32 curr = deleteData->deleteInfo.processed;
|
||||||
if(curr < deleteData->deleteInfo.total) {
|
if(curr < deleteData->deleteInfo.total) {
|
||||||
@ -35,8 +35,8 @@ static void action_delete_contents_draw_top(ui_view* view, void* data, float x1,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Result action_delete_contents_delete(void* data, u32 index) {
|
static Result action_delete_delete(void* data, u32 index) {
|
||||||
delete_contents_data* deleteData = (delete_contents_data*) data;
|
delete_data* deleteData = (delete_data*) data;
|
||||||
|
|
||||||
Result res = 0;
|
Result res = 0;
|
||||||
|
|
||||||
@ -56,9 +56,6 @@ static Result action_delete_contents_delete(void* data, u32 index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(R_SUCCEEDED(res)) {
|
if(R_SUCCEEDED(res)) {
|
||||||
deleteData->target->containsCias = false;
|
|
||||||
deleteData->target->containsTickets = false;
|
|
||||||
|
|
||||||
linked_list_iter iter;
|
linked_list_iter iter;
|
||||||
linked_list_iterate(deleteData->items, &iter);
|
linked_list_iterate(deleteData->items, &iter);
|
||||||
|
|
||||||
@ -69,10 +66,6 @@ static Result action_delete_contents_delete(void* data, u32 index) {
|
|||||||
if(strncmp(currInfo->path, info->path, FILE_PATH_MAX) == 0) {
|
if(strncmp(currInfo->path, info->path, FILE_PATH_MAX) == 0) {
|
||||||
linked_list_iter_remove(&iter);
|
linked_list_iter_remove(&iter);
|
||||||
task_free_file(item);
|
task_free_file(item);
|
||||||
} else if(currInfo->isCia) {
|
|
||||||
deleteData->target->containsCias = true;
|
|
||||||
} else if(currInfo->isTicket) {
|
|
||||||
deleteData->target->containsTickets = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,23 +73,23 @@ static Result action_delete_contents_delete(void* data, u32 index) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Result action_delete_contents_suspend(void* data, u32 index) {
|
static Result action_delete_suspend(void* data, u32 index) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Result action_delete_contents_restore(void* data, u32 index) {
|
static Result action_delete_restore(void* data, u32 index) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool action_delete_contents_error(void* data, u32 index, Result res) {
|
static bool action_delete_error(void* data, u32 index, Result res) {
|
||||||
delete_contents_data* deleteData = (delete_contents_data*) data;
|
delete_data* deleteData = (delete_data*) data;
|
||||||
|
|
||||||
if(res == R_FBI_CANCELLED) {
|
if(res == R_FBI_CANCELLED) {
|
||||||
prompt_display("Failure", "Delete cancelled.", COLOR_TEXT, false, NULL, NULL, NULL);
|
prompt_display("Failure", "Delete cancelled.", COLOR_TEXT, false, NULL, NULL, NULL);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
volatile bool dismissed = false;
|
volatile bool dismissed = false;
|
||||||
error_display_res(&dismissed, data, action_delete_contents_draw_top, res, "Failed to delete content.");
|
error_display_res(&dismissed, data, action_delete_draw_top, res, "Failed to delete content.");
|
||||||
|
|
||||||
while(!dismissed) {
|
while(!dismissed) {
|
||||||
svcSleepThread(1000000);
|
svcSleepThread(1000000);
|
||||||
@ -106,14 +99,14 @@ static bool action_delete_contents_error(void* data, u32 index, Result res) {
|
|||||||
return index < deleteData->deleteInfo.total - 1;
|
return index < deleteData->deleteInfo.total - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void action_delete_contents_free_data(delete_contents_data* data) {
|
static void action_delete_free_data(delete_data* data) {
|
||||||
task_clear_files(&data->contents);
|
task_clear_files(&data->contents);
|
||||||
linked_list_destroy(&data->contents);
|
linked_list_destroy(&data->contents);
|
||||||
free(data);
|
free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void action_delete_contents_update(ui_view* view, void* data, float* progress, char* text) {
|
static void action_delete_update(ui_view* view, void* data, float* progress, char* text) {
|
||||||
delete_contents_data* deleteData = (delete_contents_data*) data;
|
delete_data* deleteData = (delete_data*) data;
|
||||||
|
|
||||||
if(deleteData->deleteInfo.finished) {
|
if(deleteData->deleteInfo.finished) {
|
||||||
FSUSER_ControlArchive(deleteData->target->archive, ARCHIVE_ACTION_COMMIT_SAVE_DATA, NULL, 0, NULL, 0);
|
FSUSER_ControlArchive(deleteData->target->archive, ARCHIVE_ACTION_COMMIT_SAVE_DATA, NULL, 0, NULL, 0);
|
||||||
@ -125,7 +118,7 @@ static void action_delete_contents_update(ui_view* view, void* data, float* prog
|
|||||||
prompt_display("Success", "Deleted.", COLOR_TEXT, false, NULL, NULL, NULL);
|
prompt_display("Success", "Deleted.", COLOR_TEXT, false, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
action_delete_contents_free_data(deleteData);
|
action_delete_free_data(deleteData);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -138,25 +131,25 @@ static void action_delete_contents_update(ui_view* view, void* data, float* prog
|
|||||||
snprintf(text, PROGRESS_TEXT_MAX, "%lu / %lu", deleteData->deleteInfo.processed, deleteData->deleteInfo.total);
|
snprintf(text, PROGRESS_TEXT_MAX, "%lu / %lu", deleteData->deleteInfo.processed, deleteData->deleteInfo.total);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void action_delete_contents_onresponse(ui_view* view, void* data, bool response) {
|
static void action_delete_onresponse(ui_view* view, void* data, bool response) {
|
||||||
delete_contents_data* deleteData = (delete_contents_data*) data;
|
delete_data* deleteData = (delete_data*) data;
|
||||||
|
|
||||||
if(response) {
|
if(response) {
|
||||||
Result res = task_data_op(&deleteData->deleteInfo);
|
Result res = task_data_op(&deleteData->deleteInfo);
|
||||||
if(R_SUCCEEDED(res)) {
|
if(R_SUCCEEDED(res)) {
|
||||||
info_display("Deleting", "Press B to cancel.", true, data, action_delete_contents_update, action_delete_contents_draw_top);
|
info_display("Deleting", "Press B to cancel.", true, data, action_delete_update, action_delete_draw_top);
|
||||||
} else {
|
} else {
|
||||||
error_display_res(NULL, deleteData->target, ui_draw_file_info, res, "Failed to initiate delete operation.");
|
error_display_res(NULL, deleteData->target, ui_draw_file_info, res, "Failed to initiate delete operation.");
|
||||||
|
|
||||||
action_delete_contents_free_data(deleteData);
|
action_delete_free_data(deleteData);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
action_delete_contents_free_data(deleteData);
|
action_delete_free_data(deleteData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void action_delete_contents_internal(linked_list* items, list_item* selected, const char* message, bool recursive, bool includeBase, bool ciasOnly, bool ticketsOnly) {
|
static void action_delete_internal(linked_list* items, list_item* selected, const char* message, bool recursive, bool includeBase, bool ciasOnly, bool ticketsOnly) {
|
||||||
delete_contents_data* data = (delete_contents_data*) calloc(1, sizeof(delete_contents_data));
|
delete_data* data = (delete_data*) calloc(1, sizeof(delete_data));
|
||||||
if(data == NULL) {
|
if(data == NULL) {
|
||||||
error_display(NULL, NULL, NULL, "Failed to allocate delete data.");
|
error_display(NULL, NULL, NULL, "Failed to allocate delete data.");
|
||||||
|
|
||||||
@ -170,12 +163,12 @@ static void action_delete_contents_internal(linked_list* items, list_item* selec
|
|||||||
|
|
||||||
data->deleteInfo.op = DATAOP_DELETE;
|
data->deleteInfo.op = DATAOP_DELETE;
|
||||||
|
|
||||||
data->deleteInfo.delete = action_delete_contents_delete;
|
data->deleteInfo.delete = action_delete_delete;
|
||||||
|
|
||||||
data->deleteInfo.suspend = action_delete_contents_suspend;
|
data->deleteInfo.suspend = action_delete_suspend;
|
||||||
data->deleteInfo.restore = action_delete_contents_restore;
|
data->deleteInfo.restore = action_delete_restore;
|
||||||
|
|
||||||
data->deleteInfo.error = action_delete_contents_error;
|
data->deleteInfo.error = action_delete_error;
|
||||||
|
|
||||||
data->deleteInfo.finished = false;
|
data->deleteInfo.finished = false;
|
||||||
|
|
||||||
@ -183,7 +176,8 @@ static void action_delete_contents_internal(linked_list* items, list_item* selec
|
|||||||
|
|
||||||
populate_files_data popData;
|
populate_files_data popData;
|
||||||
popData.items = &data->contents;
|
popData.items = &data->contents;
|
||||||
popData.base = data->target;
|
popData.archive = data->target->archive;
|
||||||
|
strncpy(popData.path, data->target->path, FILE_PATH_MAX);
|
||||||
popData.recursive = recursive;
|
popData.recursive = recursive;
|
||||||
popData.includeBase = includeBase;
|
popData.includeBase = includeBase;
|
||||||
popData.filter = ciasOnly ? util_filter_cias : ticketsOnly ? util_filter_tickets : NULL;
|
popData.filter = ciasOnly ? util_filter_cias : ticketsOnly ? util_filter_tickets : NULL;
|
||||||
@ -193,7 +187,7 @@ static void action_delete_contents_internal(linked_list* items, list_item* selec
|
|||||||
if(R_FAILED(listRes)) {
|
if(R_FAILED(listRes)) {
|
||||||
error_display_res(NULL, NULL, NULL, listRes, "Failed to initiate content list population.");
|
error_display_res(NULL, NULL, NULL, listRes, "Failed to initiate content list population.");
|
||||||
|
|
||||||
action_delete_contents_free_data(data);
|
action_delete_free_data(data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,32 +198,32 @@ static void action_delete_contents_internal(linked_list* items, list_item* selec
|
|||||||
if(R_FAILED(popData.result)) {
|
if(R_FAILED(popData.result)) {
|
||||||
error_display_res(NULL, NULL, NULL, popData.result, "Failed to populate content list.");
|
error_display_res(NULL, NULL, NULL, popData.result, "Failed to populate content list.");
|
||||||
|
|
||||||
action_delete_contents_free_data(data);
|
action_delete_free_data(data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->deleteInfo.total = linked_list_size(&data->contents);
|
data->deleteInfo.total = linked_list_size(&data->contents);
|
||||||
data->deleteInfo.processed = data->deleteInfo.total;
|
data->deleteInfo.processed = data->deleteInfo.total;
|
||||||
|
|
||||||
prompt_display("Confirmation", message, COLOR_TEXT, true, data, action_delete_contents_draw_top, action_delete_contents_onresponse);
|
prompt_display("Confirmation", message, COLOR_TEXT, true, data, action_delete_draw_top, action_delete_onresponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
void action_delete_file(linked_list* items, list_item* selected) {
|
void action_delete_file(linked_list* items, list_item* selected) {
|
||||||
action_delete_contents_internal(items, selected, "Delete the selected file?", false, true, false, false);
|
action_delete_internal(items, selected, "Delete the selected file?", false, true, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void action_delete_dir(linked_list* items, list_item* selected) {
|
void action_delete_dir(linked_list* items, list_item* selected) {
|
||||||
action_delete_contents_internal(items, selected, "Delete the current directory?", true, true, false, false);
|
action_delete_internal(items, selected, "Delete the current directory?", true, true, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void action_delete_dir_contents(linked_list* items, list_item* selected) {
|
void action_delete_dir_contents(linked_list* items, list_item* selected) {
|
||||||
action_delete_contents_internal(items, selected, "Delete all contents of the current directory?", true, false, false, false);
|
action_delete_internal(items, selected, "Delete all contents of the current directory?", true, false, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void action_delete_dir_cias(linked_list* items, list_item* selected) {
|
void action_delete_dir_cias(linked_list* items, list_item* selected) {
|
||||||
action_delete_contents_internal(items, selected, "Delete all CIAs in the current directory?", false, false, true, false);
|
action_delete_internal(items, selected, "Delete all CIAs in the current directory?", false, false, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void action_delete_dir_tickets(linked_list* items, list_item* selected) {
|
void action_delete_dir_tickets(linked_list* items, list_item* selected) {
|
||||||
action_delete_contents_internal(items, selected, "Delete all tickets in the current directory?", false, false, false, true);
|
action_delete_internal(items, selected, "Delete all tickets in the current directory?", false, false, false, true);
|
||||||
}
|
}
|
@ -46,10 +46,11 @@ static Result action_delete_pending_titles_delete(void* data, u32 index) {
|
|||||||
|
|
||||||
while(linked_list_iter_has_next(&iter)) {
|
while(linked_list_iter_has_next(&iter)) {
|
||||||
list_item* currItem = (list_item*) linked_list_iter_next(&iter);
|
list_item* currItem = (list_item*) linked_list_iter_next(&iter);
|
||||||
|
pending_title_info* currInfo = (pending_title_info*) currItem->data;
|
||||||
|
|
||||||
if(strncmp(currItem->name, item->name, LIST_ITEM_NAME_MAX) == 0) {
|
if(currInfo->titleId == info->titleId && currInfo->mediaType == info->mediaType) {
|
||||||
linked_list_iter_remove(&iter);
|
linked_list_iter_remove(&iter);
|
||||||
task_free_file(currItem);
|
task_free_pending_title(currItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,9 +78,6 @@ static Result action_install_cias_close_src(void* data, u32 index, bool succeede
|
|||||||
FS_Path* fsPath = util_make_path_utf8(info->path);
|
FS_Path* fsPath = util_make_path_utf8(info->path);
|
||||||
if(fsPath != NULL) {
|
if(fsPath != NULL) {
|
||||||
if(R_SUCCEEDED(FSUSER_DeleteFile(info->archive, *fsPath))) {
|
if(R_SUCCEEDED(FSUSER_DeleteFile(info->archive, *fsPath))) {
|
||||||
installData->target->containsCias = false;
|
|
||||||
installData->target->containsTickets = false;
|
|
||||||
|
|
||||||
linked_list_iter iter;
|
linked_list_iter iter;
|
||||||
linked_list_iterate(installData->items, &iter);
|
linked_list_iterate(installData->items, &iter);
|
||||||
|
|
||||||
@ -91,10 +88,6 @@ static Result action_install_cias_close_src(void* data, u32 index, bool succeede
|
|||||||
if(strncmp(currInfo->path, info->path, FILE_PATH_MAX) == 0) {
|
if(strncmp(currInfo->path, info->path, FILE_PATH_MAX) == 0) {
|
||||||
linked_list_iter_remove(&iter);
|
linked_list_iter_remove(&iter);
|
||||||
task_free_file(item);
|
task_free_file(item);
|
||||||
} else if(currInfo->isCia) {
|
|
||||||
installData->target->containsCias = true;
|
|
||||||
} else if(currInfo->isTicket) {
|
|
||||||
installData->target->containsTickets = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -303,7 +296,8 @@ static void action_install_cias_internal(linked_list* items, list_item* selected
|
|||||||
|
|
||||||
populate_files_data popData;
|
populate_files_data popData;
|
||||||
popData.items = &data->contents;
|
popData.items = &data->contents;
|
||||||
popData.base = data->target;
|
popData.archive = data->target->archive;
|
||||||
|
strncpy(popData.path, data->target->path, FILE_PATH_MAX);
|
||||||
popData.recursive = false;
|
popData.recursive = false;
|
||||||
popData.includeBase = !data->target->isDirectory;
|
popData.includeBase = !data->target->isDirectory;
|
||||||
popData.filter = util_filter_cias;
|
popData.filter = util_filter_cias;
|
||||||
|
@ -77,9 +77,6 @@ static Result action_install_tickets_close_src(void* data, u32 index, bool succe
|
|||||||
FS_Path* fsPath = util_make_path_utf8(info->path);
|
FS_Path* fsPath = util_make_path_utf8(info->path);
|
||||||
if(fsPath != NULL) {
|
if(fsPath != NULL) {
|
||||||
if(R_SUCCEEDED(FSUSER_DeleteFile(info->archive, *fsPath))) {
|
if(R_SUCCEEDED(FSUSER_DeleteFile(info->archive, *fsPath))) {
|
||||||
installData->target->containsCias = false;
|
|
||||||
installData->target->containsTickets = false;
|
|
||||||
|
|
||||||
linked_list_iter iter;
|
linked_list_iter iter;
|
||||||
linked_list_iterate(installData->items, &iter);
|
linked_list_iterate(installData->items, &iter);
|
||||||
|
|
||||||
@ -90,10 +87,6 @@ static Result action_install_tickets_close_src(void* data, u32 index, bool succe
|
|||||||
if(strncmp(currInfo->path, info->path, FILE_PATH_MAX) == 0) {
|
if(strncmp(currInfo->path, info->path, FILE_PATH_MAX) == 0) {
|
||||||
linked_list_iter_remove(&iter);
|
linked_list_iter_remove(&iter);
|
||||||
task_free_file(item);
|
task_free_file(item);
|
||||||
} else if(currInfo->isCia) {
|
|
||||||
installData->target->containsCias = true;
|
|
||||||
} else if(currInfo->isTicket) {
|
|
||||||
installData->target->containsTickets = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -280,7 +273,8 @@ static void action_install_tickets_internal(linked_list* items, list_item* selec
|
|||||||
|
|
||||||
populate_files_data popData;
|
populate_files_data popData;
|
||||||
popData.items = &data->contents;
|
popData.items = &data->contents;
|
||||||
popData.base = data->target;
|
popData.archive = data->target->archive;
|
||||||
|
strncpy(popData.path, data->target->path, FILE_PATH_MAX);
|
||||||
popData.recursive = false;
|
popData.recursive = false;
|
||||||
popData.includeBase = !data->target->isDirectory;
|
popData.includeBase = !data->target->isDirectory;
|
||||||
popData.filter = util_filter_tickets;
|
popData.filter = util_filter_tickets;
|
||||||
|
@ -5,13 +5,13 @@
|
|||||||
#include <3ds.h>
|
#include <3ds.h>
|
||||||
|
|
||||||
#include "action.h"
|
#include "action.h"
|
||||||
#include "clipboard.h"
|
|
||||||
#include "../task/task.h"
|
#include "../task/task.h"
|
||||||
#include "../../error.h"
|
#include "../../error.h"
|
||||||
#include "../../info.h"
|
#include "../../info.h"
|
||||||
#include "../../list.h"
|
#include "../../list.h"
|
||||||
#include "../../prompt.h"
|
#include "../../prompt.h"
|
||||||
#include "../../ui.h"
|
#include "../../ui.h"
|
||||||
|
#include "../../../core/clipboard.h"
|
||||||
#include "../../../core/linkedlist.h"
|
#include "../../../core/linkedlist.h"
|
||||||
#include "../../../core/screen.h"
|
#include "../../../core/screen.h"
|
||||||
#include "../../../core/util.h"
|
#include "../../../core/util.h"
|
||||||
@ -74,7 +74,14 @@ static Result action_paste_files_make_dst_directory(void* data, u32 index) {
|
|||||||
char parentPath[FILE_PATH_MAX];
|
char parentPath[FILE_PATH_MAX];
|
||||||
util_get_parent_path(parentPath, dstPath, FILE_PATH_MAX);
|
util_get_parent_path(parentPath, dstPath, FILE_PATH_MAX);
|
||||||
|
|
||||||
if(strncmp(parentPath, pasteData->target->path, FILE_PATH_MAX) == 0) {
|
char baseDstPath[FILE_PATH_MAX];
|
||||||
|
if(pasteData->target->isDirectory) {
|
||||||
|
strncpy(baseDstPath, pasteData->target->path, FILE_PATH_MAX);
|
||||||
|
} else {
|
||||||
|
util_get_parent_path(baseDstPath, pasteData->target->path, FILE_PATH_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strncmp(parentPath, baseDstPath, FILE_PATH_MAX) == 0) {
|
||||||
list_item* dstItem = NULL;
|
list_item* dstItem = NULL;
|
||||||
if(R_SUCCEEDED(res) && R_SUCCEEDED(task_create_file_item(&dstItem, pasteData->target->archive, dstPath))) {
|
if(R_SUCCEEDED(res) && R_SUCCEEDED(task_create_file_item(&dstItem, pasteData->target->archive, dstPath))) {
|
||||||
linked_list_add(pasteData->items, dstItem);
|
linked_list_add(pasteData->items, dstItem);
|
||||||
@ -152,18 +159,17 @@ static Result action_paste_files_close_dst(void* data, u32 index, bool succeeded
|
|||||||
char parentPath[FILE_PATH_MAX];
|
char parentPath[FILE_PATH_MAX];
|
||||||
util_get_parent_path(parentPath, dstPath, FILE_PATH_MAX);
|
util_get_parent_path(parentPath, dstPath, FILE_PATH_MAX);
|
||||||
|
|
||||||
if(strncmp(parentPath, pasteData->target->path, FILE_PATH_MAX) == 0) {
|
char baseDstPath[FILE_PATH_MAX];
|
||||||
|
if(pasteData->target->isDirectory) {
|
||||||
|
strncpy(baseDstPath, pasteData->target->path, FILE_PATH_MAX);
|
||||||
|
} else {
|
||||||
|
util_get_parent_path(baseDstPath, pasteData->target->path, FILE_PATH_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strncmp(parentPath, baseDstPath, FILE_PATH_MAX) == 0) {
|
||||||
list_item* dstItem = NULL;
|
list_item* dstItem = NULL;
|
||||||
if(R_SUCCEEDED(task_create_file_item(&dstItem, pasteData->target->archive, dstPath))) {
|
if(R_SUCCEEDED(task_create_file_item(&dstItem, pasteData->target->archive, dstPath))) {
|
||||||
linked_list_add(pasteData->items, dstItem);
|
linked_list_add(pasteData->items, dstItem);
|
||||||
|
|
||||||
file_info* dstInfo = (file_info*) dstItem->data;
|
|
||||||
|
|
||||||
if(dstInfo->isCia) {
|
|
||||||
pasteData->target->containsCias = true;
|
|
||||||
} else if(dstInfo->isTicket) {
|
|
||||||
pasteData->target->containsTickets = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -316,7 +322,8 @@ void action_paste_contents(linked_list* items, list_item* selected) {
|
|||||||
|
|
||||||
populate_files_data popData;
|
populate_files_data popData;
|
||||||
popData.items = &data->contents;
|
popData.items = &data->contents;
|
||||||
popData.base = (file_info*) clipboardItem->data;
|
popData.archive = ((file_info*) clipboardItem->data)->archive;
|
||||||
|
strncpy(popData.path, ((file_info*) clipboardItem->data)->path, FILE_PATH_MAX);
|
||||||
popData.recursive = true;
|
popData.recursive = true;
|
||||||
popData.includeBase = !clipboard_is_contents_only() || !util_is_dir(clipboard_get_archive(), clipboard_get_path());
|
popData.includeBase = !clipboard_is_contents_only() || !util_is_dir(clipboard_get_archive(), clipboard_get_path());
|
||||||
popData.filter = NULL;
|
popData.filter = NULL;
|
||||||
|
@ -59,7 +59,10 @@ static void action_rename_kbd_finished(void* data, char* input) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(R_SUCCEEDED(res)) {
|
if(R_SUCCEEDED(res)) {
|
||||||
strncpy(renameData->target->name, input, LIST_ITEM_NAME_MAX);
|
if(strncmp(renameData->target->name, "<current directory>", LIST_ITEM_NAME_MAX) != 0 && strncmp(renameData->target->name, "<current file>", LIST_ITEM_NAME_MAX) != 0) {
|
||||||
|
strncpy(renameData->target->name, input, LIST_ITEM_NAME_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
strncpy(targetInfo->name, input, FILE_NAME_MAX);
|
strncpy(targetInfo->name, input, FILE_NAME_MAX);
|
||||||
strncpy(targetInfo->path, dstPath, FILE_PATH_MAX);
|
strncpy(targetInfo->path, dstPath, FILE_PATH_MAX);
|
||||||
|
|
||||||
@ -88,5 +91,5 @@ void action_rename(linked_list* items, list_item* selected) {
|
|||||||
data->items = items;
|
data->items = items;
|
||||||
data->target = selected;
|
data->target = selected;
|
||||||
|
|
||||||
kbd_display("Enter New Name", data->target->name, data, NULL, action_rename_kbd_finished, action_rename_kbd_canceled);
|
kbd_display("Enter New Name", ((file_info*) selected->data)->name, data, NULL, action_rename_kbd_finished, action_rename_kbd_canceled);
|
||||||
}
|
}
|
@ -6,12 +6,12 @@
|
|||||||
|
|
||||||
#include "section.h"
|
#include "section.h"
|
||||||
#include "action/action.h"
|
#include "action/action.h"
|
||||||
#include "action/clipboard.h"
|
|
||||||
#include "task/task.h"
|
#include "task/task.h"
|
||||||
#include "../error.h"
|
#include "../error.h"
|
||||||
#include "../list.h"
|
#include "../list.h"
|
||||||
#include "../prompt.h"
|
#include "../prompt.h"
|
||||||
#include "../ui.h"
|
#include "../ui.h"
|
||||||
|
#include "../../core/clipboard.h"
|
||||||
#include "../../core/linkedlist.h"
|
#include "../../core/linkedlist.h"
|
||||||
#include "../../core/screen.h"
|
#include "../../core/screen.h"
|
||||||
#include "../../core/util.h"
|
#include "../../core/util.h"
|
||||||
@ -28,10 +28,10 @@ static list_item install_and_delete_cia = {"Install and delete CIA", COLOR_TEXT,
|
|||||||
static list_item install_ticket = {"Install ticket", COLOR_TEXT, action_install_ticket};
|
static list_item install_ticket = {"Install ticket", COLOR_TEXT, action_install_ticket};
|
||||||
static list_item install_and_delete_ticket = {"Install and delete ticket", COLOR_TEXT, action_install_ticket_delete};
|
static list_item install_and_delete_ticket = {"Install and delete ticket", COLOR_TEXT, action_install_ticket_delete};
|
||||||
|
|
||||||
static list_item new_folder = {"New folder", COLOR_TEXT, action_new_folder};
|
|
||||||
static list_item delete_dir = {"Delete", COLOR_TEXT, action_delete_dir};
|
static list_item delete_dir = {"Delete", COLOR_TEXT, action_delete_dir};
|
||||||
static list_item delete_all_contents = {"Delete all contents", COLOR_TEXT, action_delete_dir_contents};
|
static list_item delete_all_contents = {"Delete all contents", COLOR_TEXT, action_delete_dir_contents};
|
||||||
static list_item copy_all_contents = {"Copy all contents", COLOR_TEXT, NULL};
|
static list_item copy_all_contents = {"Copy all contents", COLOR_TEXT, NULL};
|
||||||
|
static list_item new_folder = {"New folder", COLOR_TEXT, action_new_folder};
|
||||||
|
|
||||||
static list_item install_all_cias = {"Install all CIAs", COLOR_TEXT, action_install_cias};
|
static list_item install_all_cias = {"Install all CIAs", COLOR_TEXT, action_install_cias};
|
||||||
static list_item install_and_delete_all_cias = {"Install and delete all CIAs", COLOR_TEXT, action_install_cias_delete};
|
static list_item install_and_delete_all_cias = {"Install and delete all CIAs", COLOR_TEXT, action_install_cias_delete};
|
||||||
@ -57,13 +57,15 @@ typedef struct {
|
|||||||
bool showTickets;
|
bool showTickets;
|
||||||
|
|
||||||
char currDir[FILE_PATH_MAX];
|
char currDir[FILE_PATH_MAX];
|
||||||
list_item* dirItem;
|
|
||||||
} files_data;
|
} files_data;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
linked_list* items;
|
linked_list* items;
|
||||||
list_item* selected;
|
list_item* selected;
|
||||||
files_data* parent;
|
files_data* parent;
|
||||||
|
|
||||||
|
bool containsCias;
|
||||||
|
bool containsTickets;
|
||||||
} files_action_data;
|
} files_action_data;
|
||||||
|
|
||||||
static void files_action_draw_top(ui_view* view, void* data, float x1, float y1, float x2, float y2, list_item* selected) {
|
static void files_action_draw_top(ui_view* view, void* data, float x1, float y1, float x2, float y2, list_item* selected) {
|
||||||
@ -92,7 +94,7 @@ static void files_action_update(ui_view* view, void* data, linked_list* items, l
|
|||||||
file_info* info = (file_info*) actionData->selected->data;
|
file_info* info = (file_info*) actionData->selected->data;
|
||||||
|
|
||||||
Result res = 0;
|
Result res = 0;
|
||||||
if(R_SUCCEEDED(res = clipboard_set_contents(actionData->parent->archiveId, &actionData->parent->archivePath, info->path, selected == ©_all_contents))) {
|
if(R_SUCCEEDED(res = clipboard_set_contents(actionData->parent->archive, info->path, selected == ©_all_contents))) {
|
||||||
prompt_display("Success", selected == ©_all_contents ? "Current directory contents copied to clipboard." : info->isDirectory ? "Current directory copied to clipboard." : "File copied to clipboard.", COLOR_TEXT, false, info, ui_draw_file_info, NULL);
|
prompt_display("Success", selected == ©_all_contents ? "Current directory contents copied to clipboard." : info->isDirectory ? "Current directory copied to clipboard." : "File copied to clipboard.", COLOR_TEXT, false, info, ui_draw_file_info, NULL);
|
||||||
} else {
|
} else {
|
||||||
error_display_res(NULL, info, ui_draw_file_info, res, "Failed to copy to clipboard.");
|
error_display_res(NULL, info, ui_draw_file_info, res, "Failed to copy to clipboard.");
|
||||||
@ -110,24 +112,24 @@ static void files_action_update(ui_view* view, void* data, linked_list* items, l
|
|||||||
file_info* info = (file_info*) actionData->selected->data;
|
file_info* info = (file_info*) actionData->selected->data;
|
||||||
|
|
||||||
if(info->isDirectory) {
|
if(info->isDirectory) {
|
||||||
if(info->containsCias) {
|
if(actionData->containsCias) {
|
||||||
linked_list_add(items, &install_all_cias);
|
linked_list_add(items, &install_all_cias);
|
||||||
linked_list_add(items, &install_and_delete_all_cias);
|
linked_list_add(items, &install_and_delete_all_cias);
|
||||||
linked_list_add(items, &delete_all_cias);
|
linked_list_add(items, &delete_all_cias);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(info->containsTickets) {
|
if(actionData->containsTickets) {
|
||||||
linked_list_add(items, &install_all_tickets);
|
linked_list_add(items, &install_all_tickets);
|
||||||
linked_list_add(items, &install_and_delete_all_tickets);
|
linked_list_add(items, &install_and_delete_all_tickets);
|
||||||
linked_list_add(items, &delete_all_tickets);
|
linked_list_add(items, &delete_all_tickets);
|
||||||
}
|
}
|
||||||
|
|
||||||
linked_list_add(items, &new_folder);
|
|
||||||
|
|
||||||
linked_list_add(items, &delete_all_contents);
|
linked_list_add(items, &delete_all_contents);
|
||||||
linked_list_add(items, ©_all_contents);
|
linked_list_add(items, ©_all_contents);
|
||||||
|
|
||||||
linked_list_add(items, &delete_dir);
|
linked_list_add(items, &delete_dir);
|
||||||
|
|
||||||
|
linked_list_add(items, &new_folder);
|
||||||
} else {
|
} else {
|
||||||
if(info->isCia) {
|
if(info->isCia) {
|
||||||
linked_list_add(items, &install_cia);
|
linked_list_add(items, &install_cia);
|
||||||
@ -160,6 +162,22 @@ static void files_action_open(linked_list* items, list_item* selected, files_dat
|
|||||||
data->selected = selected;
|
data->selected = selected;
|
||||||
data->parent = parent;
|
data->parent = parent;
|
||||||
|
|
||||||
|
data->containsCias = false;
|
||||||
|
data->containsTickets = false;
|
||||||
|
|
||||||
|
linked_list_iter iter;
|
||||||
|
linked_list_iterate(data->items, &iter);
|
||||||
|
|
||||||
|
while(linked_list_iter_has_next(&iter)) {
|
||||||
|
file_info* info = (file_info*) ((list_item*) linked_list_iter_next(&iter))->data;
|
||||||
|
|
||||||
|
if(info->isCia) {
|
||||||
|
data->containsCias = true;
|
||||||
|
} else if(info->isTicket) {
|
||||||
|
data->containsTickets = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
list_display(((file_info*) selected->data)->isDirectory ? "Directory Action" : "File Action", "A: Select, B: Return", data, files_action_update, files_action_draw_top);
|
list_display(((file_info*) selected->data)->isDirectory ? "Directory Action" : "File Action", "A: Select, B: Return", data, files_action_update, files_action_draw_top);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,19 +246,11 @@ static void files_repopulate(files_data* listData, linked_list* items) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(listData->dirItem != NULL) {
|
listData->populateData.items = items;
|
||||||
task_free_file(listData->dirItem);
|
listData->populateData.archive = listData->archive;
|
||||||
listData->dirItem = NULL;
|
strncpy(listData->populateData.path, listData->currDir, FILE_PATH_MAX);
|
||||||
}
|
|
||||||
|
|
||||||
Result res = 0;
|
|
||||||
if(R_SUCCEEDED(res = task_create_file_item(&listData->dirItem, listData->archive, listData->currDir))) {
|
|
||||||
listData->populateData.items = items;
|
|
||||||
listData->populateData.base = (file_info*) listData->dirItem->data;
|
|
||||||
|
|
||||||
res = task_populate_files(&listData->populateData);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Result res = task_populate_files(&listData->populateData);
|
||||||
if(R_FAILED(res)) {
|
if(R_FAILED(res)) {
|
||||||
error_display_res(NULL, NULL, NULL, res, "Failed to initiate file list population.");
|
error_display_res(NULL, NULL, NULL, res, "Failed to initiate file list population.");
|
||||||
}
|
}
|
||||||
@ -262,13 +272,8 @@ static void files_free_data(files_data* data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data->dirItem != NULL) {
|
|
||||||
task_free_file(data->dirItem);
|
|
||||||
data->dirItem = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(data->archive != 0) {
|
if(data->archive != 0) {
|
||||||
FSUSER_CloseArchive(data->archive);
|
util_close_archive(data->archive);
|
||||||
data->archive = 0;
|
data->archive = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,9 +288,12 @@ static void files_free_data(files_data* data) {
|
|||||||
static void files_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) {
|
static void files_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) {
|
||||||
files_data* listData = (files_data*) data;
|
files_data* listData = (files_data*) data;
|
||||||
|
|
||||||
// Detect whether the current directory was renamed by an action.
|
if(listData->populated) {
|
||||||
if(listData->populated && listData->dirItem != NULL && strncmp(listData->currDir, ((file_info*) listData->dirItem->data)->path, FILE_PATH_MAX) != 0) {
|
// Detect whether the current directory was renamed by an action.
|
||||||
strncpy(listData->currDir, ((file_info*) listData->dirItem->data)->path, FILE_PATH_MAX);
|
list_item* currDirItem = linked_list_get(items, 0);
|
||||||
|
if(currDirItem != NULL && strncmp(listData->currDir, ((file_info*) currDirItem->data)->path, FILE_PATH_MAX) != 0) {
|
||||||
|
strncpy(listData->currDir, ((file_info*) currDirItem->data)->path, FILE_PATH_MAX);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while(!util_is_dir(listData->archive, listData->currDir)) {
|
while(!util_is_dir(listData->archive, listData->currDir)) {
|
||||||
@ -318,15 +326,10 @@ static void files_update(ui_view* view, void* data, linked_list* items, list_ite
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((hidKeysDown() & KEY_Y) && listData->dirItem != NULL) {
|
|
||||||
files_action_open(items, listData->dirItem, listData);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(selected != NULL && selected->data != NULL && (selectedTouched || (hidKeysDown() & KEY_A))) {
|
if(selected != NULL && selected->data != NULL && (selectedTouched || (hidKeysDown() & KEY_A))) {
|
||||||
file_info* fileInfo = (file_info*) selected->data;
|
file_info* fileInfo = (file_info*) selected->data;
|
||||||
|
|
||||||
if(fileInfo->isDirectory) {
|
if(fileInfo->isDirectory && strncmp(selected->name, "<current directory>", LIST_ITEM_NAME_MAX) != 0) {
|
||||||
files_navigate(listData, items, fileInfo->path);
|
files_navigate(listData, items, fileInfo->path);
|
||||||
} else {
|
} else {
|
||||||
files_action_open(items, selected, listData);
|
files_action_open(items, selected, listData);
|
||||||
@ -376,7 +379,7 @@ void files_open(FS_ArchiveID archiveId, FS_Path archivePath) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data->populateData.recursive = false;
|
data->populateData.recursive = false;
|
||||||
data->populateData.includeBase = false;
|
data->populateData.includeBase = true;
|
||||||
|
|
||||||
data->populateData.filter = files_filter;
|
data->populateData.filter = files_filter;
|
||||||
data->populateData.filterData = data;
|
data->populateData.filterData = data;
|
||||||
@ -409,17 +412,16 @@ void files_open(FS_ArchiveID archiveId, FS_Path archivePath) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
snprintf(data->currDir, FILE_PATH_MAX, "/");
|
snprintf(data->currDir, FILE_PATH_MAX, "/");
|
||||||
data->dirItem = NULL;
|
|
||||||
|
|
||||||
Result res = 0;
|
Result res = 0;
|
||||||
if(R_FAILED(res = FSUSER_OpenArchive(&data->archive, archiveId, archivePath))) {
|
if(R_FAILED(res = util_open_archive(&data->archive, archiveId, archivePath))) {
|
||||||
error_display_res(NULL, NULL, NULL, res, "Failed to open file listing archive.");
|
error_display_res(NULL, NULL, NULL, res, "Failed to open file listing archive.");
|
||||||
|
|
||||||
files_free_data(data);
|
files_free_data(data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_display("Files", "A: Select, B: Back, X: Refresh, Y: Dir, Select: Filter", data, files_update, files_draw_top);
|
list_display("Files", "A: Select, B: Back, X: Refresh, Select: Filters", data, files_update, files_draw_top);
|
||||||
}
|
}
|
||||||
|
|
||||||
void files_open_sd() {
|
void files_open_sd() {
|
||||||
|
@ -153,8 +153,9 @@ void task_clear_ext_save_data(linked_list* items) {
|
|||||||
|
|
||||||
while(linked_list_iter_has_next(&iter)) {
|
while(linked_list_iter_has_next(&iter)) {
|
||||||
list_item* item = (list_item*) linked_list_iter_next(&iter);
|
list_item* item = (list_item*) linked_list_iter_next(&iter);
|
||||||
task_free_ext_save_data(item);
|
|
||||||
linked_list_iter_remove(&iter);
|
linked_list_iter_remove(&iter);
|
||||||
|
task_free_ext_save_data(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,11 +147,15 @@ static void task_populate_files_thread(void* arg) {
|
|||||||
|
|
||||||
Result res = 0;
|
Result res = 0;
|
||||||
|
|
||||||
data->base->containsCias = false;
|
|
||||||
data->base->containsTickets = false;
|
|
||||||
|
|
||||||
list_item* baseItem = NULL;
|
list_item* baseItem = NULL;
|
||||||
if(R_SUCCEEDED(res = task_create_file_item(&baseItem, data->base->archive, data->base->path))) {
|
if(R_SUCCEEDED(res = task_create_file_item(&baseItem, data->archive, data->path))) {
|
||||||
|
file_info* baseInfo = (file_info*) baseItem->data;
|
||||||
|
if(baseInfo->isDirectory) {
|
||||||
|
strncpy(baseItem->name, "<current directory>", LIST_ITEM_NAME_MAX);
|
||||||
|
} else {
|
||||||
|
strncpy(baseItem->name, "<current file>", LIST_ITEM_NAME_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
linked_list queue;
|
linked_list queue;
|
||||||
linked_list_init(&queue);
|
linked_list_init(&queue);
|
||||||
|
|
||||||
@ -195,16 +199,6 @@ static void task_populate_files_thread(void* arg) {
|
|||||||
|
|
||||||
list_item* item = NULL;
|
list_item* item = NULL;
|
||||||
if(R_SUCCEEDED(res = task_create_file_item(&item, curr->archive, path))) {
|
if(R_SUCCEEDED(res = task_create_file_item(&item, curr->archive, path))) {
|
||||||
if(currItem == baseItem) {
|
|
||||||
file_info* info = (file_info*) item->data;
|
|
||||||
|
|
||||||
if(info->isCia) {
|
|
||||||
data->base->containsCias = true;
|
|
||||||
} else if(info->isTicket) {
|
|
||||||
data->base->containsTickets = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(data->recursive && ((file_info*) item->data)->isDirectory) {
|
if(data->recursive && ((file_info*) item->data)->isDirectory) {
|
||||||
linked_list_add(&queue, item);
|
linked_list_add(&queue, item);
|
||||||
} else {
|
} else {
|
||||||
@ -275,7 +269,7 @@ void task_clear_files(linked_list* items) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result task_populate_files(populate_files_data* data) {
|
Result task_populate_files(populate_files_data* data) {
|
||||||
if(data == NULL || data->base == NULL || data->items == NULL) {
|
if(data == NULL || data->items == NULL) {
|
||||||
return R_FBI_INVALID_ARGUMENT;
|
return R_FBI_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,8 +118,9 @@ void task_clear_pending_titles(linked_list* items) {
|
|||||||
|
|
||||||
while(linked_list_iter_has_next(&iter)) {
|
while(linked_list_iter_has_next(&iter)) {
|
||||||
list_item* item = (list_item*) linked_list_iter_next(&iter);
|
list_item* item = (list_item*) linked_list_iter_next(&iter);
|
||||||
task_free_pending_title(item);
|
|
||||||
linked_list_iter_remove(&iter);
|
linked_list_iter_remove(&iter);
|
||||||
|
task_free_pending_title(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,8 +86,9 @@ void task_clear_system_save_data(linked_list* items) {
|
|||||||
|
|
||||||
while(linked_list_iter_has_next(&iter)) {
|
while(linked_list_iter_has_next(&iter)) {
|
||||||
list_item* item = (list_item*) linked_list_iter_next(&iter);
|
list_item* item = (list_item*) linked_list_iter_next(&iter);
|
||||||
task_free_system_save_data(item);
|
|
||||||
linked_list_iter_remove(&iter);
|
linked_list_iter_remove(&iter);
|
||||||
|
task_free_system_save_data(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,8 +92,9 @@ void task_clear_tickets(linked_list* items) {
|
|||||||
|
|
||||||
while(linked_list_iter_has_next(&iter)) {
|
while(linked_list_iter_has_next(&iter)) {
|
||||||
list_item* item = (list_item*) linked_list_iter_next(&iter);
|
list_item* item = (list_item*) linked_list_iter_next(&iter);
|
||||||
task_free_ticket(item);
|
|
||||||
linked_list_iter_remove(&iter);
|
linked_list_iter_remove(&iter);
|
||||||
|
task_free_ticket(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,8 +342,9 @@ void task_clear_titles(linked_list* items) {
|
|||||||
|
|
||||||
while(linked_list_iter_has_next(&iter)) {
|
while(linked_list_iter_has_next(&iter)) {
|
||||||
list_item* item = (list_item*) linked_list_iter_next(&iter);
|
list_item* item = (list_item*) linked_list_iter_next(&iter);
|
||||||
task_free_title(item);
|
|
||||||
linked_list_iter_remove(&iter);
|
linked_list_iter_remove(&iter);
|
||||||
|
task_free_title(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,14 +60,12 @@ typedef struct file_info_s {
|
|||||||
char path[FILE_PATH_MAX];
|
char path[FILE_PATH_MAX];
|
||||||
bool isDirectory;
|
bool isDirectory;
|
||||||
|
|
||||||
|
// Files only
|
||||||
u64 size;
|
u64 size;
|
||||||
bool isCia;
|
bool isCia;
|
||||||
cia_info ciaInfo;
|
cia_info ciaInfo;
|
||||||
bool isTicket;
|
bool isTicket;
|
||||||
ticket_info ticketInfo;
|
ticket_info ticketInfo;
|
||||||
|
|
||||||
bool containsCias;
|
|
||||||
bool containsTickets;
|
|
||||||
} file_info;
|
} file_info;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -148,7 +146,8 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
linked_list* items;
|
linked_list* items;
|
||||||
|
|
||||||
file_info* base;
|
FS_Archive archive;
|
||||||
|
char path[FILE_PATH_MAX];
|
||||||
|
|
||||||
bool recursive;
|
bool recursive;
|
||||||
bool includeBase;
|
bool includeBase;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user