static void titles_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) { titles_data* listData = (titles_data*) data; if(hidKeysDown() & KEY_B) { if(!listData->populateData.finished) { svcSignalEvent(listData->populateData.cancelEvent); while(!listData->populateData.finished) { svcSleepThread(1000000); } } ui_pop(); task_clear_titles(items); list_destroy(view); free(listData); return; } if(hidKeysDown() & KEY_SELECT) { titles_options_open(listData); return; } if(!listData->populated || (hidKeysDown() & KEY_X)) { if(!listData->populateData.finished) { svcSignalEvent(listData->populateData.cancelEvent); while(!listData->populateData.finished) { svcSleepThread(1000000); } } listData->populateData.items = items; Result res = task_populate_titles(&listData->populateData); if(R_FAILED(res)) { error_display_res(NULL, NULL, res, "Failed to initiate title list population."); } listData->populated = true; } if(listData->populateData.finished && R_FAILED(listData->populateData.result)) { error_display_res(NULL, NULL, listData->populateData.result, "Failed to populate title list."); listData->populateData.result = 0; } if(selected != NULL && selected->data != NULL && (selectedTouched || (hidKeysDown() & KEY_A))) { titles_action_open(items, selected); return; } }
static void action_delete_system_save_data_update(ui_view* view, void* data, float* progress, char* progressText) { delete_system_save_data_data* deleteData = (delete_system_save_data_data*) data; FS_SystemSaveDataInfo sysInfo = {.mediaType = MEDIATYPE_NAND, .saveId = deleteData->info->systemSaveDataId}; Result res = FSUSER_DeleteSystemSaveData(sysInfo); progressbar_destroy(view); ui_pop(); if(R_FAILED(res)) { error_display_res(deleteData->info, ui_draw_system_save_data_info, res, "Failed to delete system save data."); } else { *deleteData->populated = false; ui_push(prompt_create("Success", "System save data deleted.", COLOR_TEXT, false, deleteData->info, NULL, ui_draw_system_save_data_info, action_delete_system_save_data_success_onresponse)); } free(data); } static void action_delete_system_save_data_onresponse(ui_view* view, void* data, bool response) { prompt_destroy(view); if(response) { ui_push(progressbar_create("Deleting System Save Data", "", data, action_delete_system_save_data_update, action_delete_system_save_data_draw_top)); } else { free(data); } }
static void files_repopulate(files_data* listData, linked_list* items) { if(!listData->populateData.finished) { svcSignalEvent(listData->populateData.cancelEvent); while(!listData->populateData.finished) { svcSleepThread(1000000); } } if(listData->dirItem != NULL) { task_free_file(listData->dirItem); listData->dirItem = NULL; } 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); } if(R_FAILED(res)) { error_display_res(NULL, NULL, NULL, res, "Failed to initiate file list population."); } listData->populated = true; }
static void action_delete_title_update(ui_view* view, void* data, float* progress, char* text) { delete_title_data* deleteData = (delete_title_data*) data; title_info* info = (title_info*) deleteData->selected->data; Result res = 0; if(R_SUCCEEDED(res = AM_DeleteTitle(info->mediaType, info->titleId)) && deleteData->ticket) { res = AM_DeleteTicket(info->titleId); } ui_pop(); info_destroy(view); if(R_FAILED(res)) { error_display_res(info, ui_draw_title_info, res, "Failed to delete title."); } else { linked_list_remove(deleteData->items, deleteData->selected); task_free_title(deleteData->selected); prompt_display("Success", "Title deleted.", COLOR_TEXT, false, NULL, NULL, NULL); } free(data); }
Handle task_populate_pending_titles(list_item* items, u32* count, u32 max) { if(items == NULL || count == NULL || max == 0) { return 0; } task_clear_pending_titles(items, count); populate_pending_titles_data* data = (populate_pending_titles_data*) calloc(1, sizeof(populate_pending_titles_data)); data->items = items; data->count = count; data->max = max; Result eventRes = svcCreateEvent(&data->cancelEvent, 1); if(R_FAILED(eventRes)) { error_display_res(NULL, NULL, eventRes, "Failed to create pending title list cancel event."); free(data); return 0; } if(threadCreate(task_populate_pending_titles_thread, data, 0x4000, 0x18, 1, true) == NULL) { error_display(NULL, NULL, "Failed to create pending title list thread."); svcCloseHandle(data->cancelEvent); free(data); return 0; } return data->cancelEvent; }
static void files_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) { files_data* listData = (files_data*) data; while(!util_is_dir(listData->archive, listData->currDir)) { char parentDir[FILE_PATH_MAX] = {'\0'}; util_get_parent_path(parentDir, listData->currDir, FILE_PATH_MAX); files_navigate(listData, items, parentDir); } if(hidKeysDown() & KEY_B) { if(strncmp(listData->currDir, "/", FILE_PATH_MAX) == 0) { ui_pop(); files_free_data(listData); task_clear_files(items); list_destroy(view); return; } else { char parentDir[FILE_PATH_MAX] = {'\0'}; util_get_parent_path(parentDir, listData->currDir, FILE_PATH_MAX); files_navigate(listData, items, parentDir); } } if(hidKeysDown() & KEY_SELECT) { files_filters_open(listData); 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))) { file_info* fileInfo = (file_info*) selected->data; if(fileInfo->isDirectory) { files_navigate(listData, items, fileInfo->path); } else { files_action_open(items, selected, listData); return; } } if(!listData->populated || (hidKeysDown() & KEY_X)) { files_repopulate(listData, items); } if(listData->populateData.finished && R_FAILED(listData->populateData.result)) { error_display_res(NULL, NULL, NULL, listData->populateData.result, "Failed to populate file list."); listData->populateData.result = 0; } }
static bool dumpnand_error(void* data, u32 index, Result res) { if(res == R_FBI_CANCELLED) { prompt_display("Failure", "Dump cancelled.", COLOR_TEXT, false, NULL, NULL, NULL, NULL); } else { error_display_res(NULL, NULL, NULL, res, "Failed to dump NAND."); } return false; }
void action_copy_contents(file_info* info, bool* populated) { Result res = 0; if(R_FAILED(res = clipboard_set_contents(*info->archive, info->path))) { error_display_res(info, ui_draw_file_info, res, "Failed to copy contents to clipboard."); return; } ui_push(prompt_create("Success", "Content copied to clipboard.", COLOR_TEXT, false, info, NULL, ui_draw_file_info, action_copy_files_success_onresponse)); }
static void action_rename_kbd_finished(void* data, char* input) { rename_data* renameData = (rename_data*) data; if(strlen(input) == 0) { error_display(NULL, NULL, NULL, "No name specified."); } file_info* targetInfo = (file_info*) renameData->target->data; Result res = 0; char parentPath[FILE_PATH_MAX] = {'\0'}; util_get_parent_path(parentPath, targetInfo->path, FILE_PATH_MAX); char dstPath[FILE_PATH_MAX] = {'\0'}; snprintf(dstPath, FILE_PATH_MAX, "%s%s", parentPath, input); FS_Path* srcFsPath = util_make_path_utf8(targetInfo->path); if(srcFsPath != NULL) { FS_Path* dstFsPath = util_make_path_utf8(dstPath); if(dstFsPath != NULL) { if(targetInfo->isDirectory) { res = FSUSER_RenameDirectory(targetInfo->archive, *srcFsPath, targetInfo->archive, *dstFsPath); } else { res = FSUSER_RenameFile(targetInfo->archive, *srcFsPath, targetInfo->archive, *dstFsPath); } util_free_path_utf8(dstFsPath); } else { res = R_FBI_OUT_OF_MEMORY; } util_free_path_utf8(srcFsPath); } else { res = R_FBI_OUT_OF_MEMORY; } if(R_SUCCEEDED(res)) { 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->path, dstPath, FILE_PATH_MAX); linked_list_sort(renameData->items, util_compare_file_infos); prompt_display("Success", "Renamed.", COLOR_TEXT, false, NULL, NULL, NULL); } else { error_display_res(NULL, NULL, NULL, res, "Failed to perform rename."); } free(data); }
static void task_populate_pending_titles_thread(void* arg) { populate_pending_titles_data* data = (populate_pending_titles_data*) arg; Result res = 0; if(R_FAILED(res = task_populate_pending_titles_from(data, MEDIATYPE_SD)) || R_FAILED(res = task_populate_pending_titles_from(data, MEDIATYPE_NAND))) { error_display_res(NULL, NULL, res, "Failed to load pending title listing."); } svcCloseHandle(data->cancelEvent); free(data); }
static bool action_import_twl_save_error(void* data, u32 index, Result res) { import_twl_save_data* importData = (import_twl_save_data*) data; if(res == R_FBI_CANCELLED) { prompt_display("Failure", "Import cancelled.", COLOR_TEXT, false, importData->title, ui_draw_title_info, NULL); } else { error_display_res(importData->title, ui_draw_title_info, res, "Failed to import save."); } return false; }
void files_open(FS_ArchiveID archiveId, FS_Path archivePath) { files_data* data = (files_data*) calloc(1, sizeof(files_data)); if(data == NULL) { error_display(NULL, NULL, NULL, "Failed to allocate files data."); return; } data->populateData.recursive = false; data->populateData.includeBase = false; data->populateData.dirsFirst = true; data->populateData.filter = files_filter; data->populateData.filterData = data; data->populateData.finished = true; data->populated = false; data->showDirectories = true; data->showCias = true; data->showTickets = true; data->showMisc = true; data->archiveId = archiveId; data->archivePath.type = archivePath.type; data->archivePath.size = archivePath.size; if(archivePath.data != NULL) { data->archivePath.data = calloc(1, data->archivePath.size); if(data->archivePath.data == NULL) { error_display(NULL, NULL, NULL, "Failed to allocate files data."); files_free_data(data); return; } memcpy((void*) data->archivePath.data, archivePath.data, data->archivePath.size); } else { data->archivePath.data = NULL; } snprintf(data->currDir, FILE_PATH_MAX, "/"); data->dirItem = NULL; Result res = 0; if(R_FAILED(res = FSUSER_OpenArchive(&data->archive, archiveId, archivePath))) { error_display_res(NULL, NULL, NULL, res, "Failed to open file listing archive."); files_free_data(data); return; } list_display("Files", "A: Select, B: Back, X: Refresh, Y: Dir, Select: Filter", data, files_update, files_draw_top); }
bool action_install_cdn_error(void* data, u32 index, Result res) { install_cdn_data* installData = (install_cdn_data*) data; if(res == R_FBI_CANCELLED) { prompt_display("Failure", "Install cancelled.", COLOR_TEXT, false, installData->ticket, NULL, ui_draw_ticket_info, NULL); } else if(res == R_FBI_HTTP_RESPONSE_CODE) { error_display(NULL, installData->ticket, ui_draw_ticket_info, "Failed to install CDN title.\nHTTP server returned response code %d", installData->responseCode); } else { error_display_res(NULL, installData->ticket, ui_draw_ticket_info, res, "Failed to install CDN title."); } return false; }
static void dumpnand_onresponse(ui_view* view, void* data, bool response) { if(response) { data_op_data* dumpData = (data_op_data*) data; Result res = task_data_op(dumpData); if(R_SUCCEEDED(res)) { info_display("Dumping NAND", "Press B to cancel.", true, data, dumpnand_update, NULL); } else { error_display_res(NULL, NULL, NULL, res, "Failed to initiate NAND dump."); } } else { free(data); } }
static bool action_install_tickets_error(void* data, u32 index, Result res) { install_tickets_data* installData = (install_tickets_data*) data; if(res == R_FBI_CANCELLED) { prompt_display("Failure", "Install cancelled.", COLOR_TEXT, false, installData->base, NULL, ui_draw_file_info, NULL); return false; } else { char* path = installData->contents[index]; volatile bool dismissed = false; if(strlen(path) > 48) { error_display_res(&dismissed, installData->base, ui_draw_file_info, res, "Failed to install ticket.\n%.45s...", path); } else { error_display_res(&dismissed, installData->base, ui_draw_file_info, res, "Failed to install ticket.\n%.48s", path); } while(!dismissed) { svcSleepThread(1000000); } } return index < installData->installInfo.total - 1; }
static void action_import_seed_update(ui_view* view, void* data, float* progress, char* text) { title_info* info = (title_info*) data; Result res = util_import_seed(info->titleId); ui_pop(); info_destroy(view); if(R_SUCCEEDED(res)) { prompt_display("Success", "Seed imported.", COLOR_TEXT, false, info, NULL, ui_draw_title_info, NULL); } else { error_display_res(NULL, info, ui_draw_title_info, res, "Failed to import seed."); } }
static void action_paste_files_onresponse(ui_view* view, void* data, bool response) { paste_files_data* pasteData = (paste_files_data*) data; if(response) { Result res = task_data_op(&pasteData->pasteInfo); if(R_SUCCEEDED(res)) { info_display("Pasting Contents", "Press B to cancel.", true, data, action_paste_files_update, action_paste_files_draw_top); } else { error_display_res(pasteData->target, ui_draw_file_info, res, "Failed to initiate paste operation."); action_paste_files_free_data(pasteData); } } else { action_paste_files_free_data(pasteData); } }
static bool action_paste_files_error(void* data, u32 index, Result res) { paste_files_data* pasteData = (paste_files_data*) data; if(res == R_FBI_CANCELLED) { prompt_display("Failure", "Paste cancelled.", COLOR_TEXT, false, NULL, NULL, NULL); return false; } else { ui_view* view = error_display_res(data, action_paste_files_draw_top, res, "Failed to paste content."); if(view != NULL) { svcWaitSynchronization(view->active, U64_MAX); } } return index < pasteData->pasteInfo.total - 1; }
static void action_import_twl_save_onresponse(ui_view* view, void* data, bool response) { if(response) { import_twl_save_data* importData = (import_twl_save_data*) data; Result res = task_data_op(&importData->importInfo); if(R_SUCCEEDED(res)) { info_display("Importing Save", "Press B to cancel.", true, data, action_import_twl_save_update, action_import_twl_save_draw_top); } else { error_display_res(importData->title, ui_draw_title_info, res, "Failed to initiate save import."); free(data); } } else { free(data); } }
static void action_delete_secure_value_update(ui_view* view, void* data, float* progress, char* text) { title_info* info = (title_info*) data; u64 param = ((u64) SECUREVALUE_SLOT_SD << 32) | (info->titleId & 0xFFFFFFF); u8 out = 0; Result res = FSUSER_ControlSecureSave(SECURESAVE_ACTION_DELETE, ¶m, sizeof(param), &out, sizeof(out)); ui_pop(); info_destroy(view); if(R_FAILED(res)) { error_display_res(info, ui_draw_title_info, res, "Failed to delete secure value."); } else { prompt_display("Success", "Secure value deleted.", COLOR_TEXT, false, info, ui_draw_title_info, NULL); } }
static void action_delete_title_update(ui_view* view, void* data, float* progress, char* text) { delete_title_data* deleteData = (delete_title_data*) data; Result res = AM_DeleteTitle(deleteData->info->mediaType, deleteData->info->titleId); ui_pop(); info_destroy(view); if(R_FAILED(res)) { error_display_res(NULL, deleteData->info, ui_draw_title_info, res, "Failed to delete title."); } else { *deleteData->populated = false; prompt_display("Success", "Title deleted.", COLOR_TEXT, false, deleteData->info, NULL, ui_draw_title_info, NULL); } free(data); }
static void action_delete_system_save_data_update(ui_view* view, void* data, float* progress, char* text) { delete_system_save_data_data* deleteData = (delete_system_save_data_data*) data; system_save_data_info* info = (system_save_data_info*) deleteData->selected->data; FS_SystemSaveDataInfo sysInfo = {.mediaType = MEDIATYPE_NAND, .saveId = info->systemSaveDataId}; Result res = FSUSER_DeleteSystemSaveData(sysInfo); ui_pop(); info_destroy(view); if(R_FAILED(res)) { error_display_res(info, ui_draw_system_save_data_info, res, "Failed to delete system save data."); } else { linked_list_remove(deleteData->items, deleteData->selected); task_free_system_save_data(deleteData->selected); prompt_display("Success", "System save data deleted.", COLOR_TEXT, false, NULL, NULL, NULL); } free(data); } static void action_delete_system_save_data_onresponse(ui_view* view, void* data, bool response) { if(response) { info_display("Deleting System Save Data", "", false, data, action_delete_system_save_data_update, action_delete_system_save_data_draw_top); } else { free(data); } } void action_delete_system_save_data(linked_list* items, list_item* selected) { delete_system_save_data_data* data = (delete_system_save_data_data*) calloc(1, sizeof(delete_system_save_data_data)); if(data == NULL) { error_display(NULL, NULL, "Failed to allocate delete system save data data."); return; } data->items = items; data->selected = selected; prompt_display("Confirmation", "Delete the selected system save data?", COLOR_TEXT, true, data, action_delete_system_save_data_draw_top, action_delete_system_save_data_onresponse); }
static void files_repopulate(files_data* listData, linked_list* items) { if(!listData->populateData.finished) { svcSignalEvent(listData->populateData.cancelEvent); while(!listData->populateData.finished) { svcSleepThread(1000000); } } listData->populateData.items = items; listData->populateData.archive = listData->archive; strncpy(listData->populateData.path, listData->currDir, FILE_PATH_MAX); Result res = task_populate_files(&listData->populateData); if(R_FAILED(res)) { error_display_res(NULL, NULL, res, "Failed to initiate file list population."); } listData->populated = true; }
static void action_launch_title_update(ui_view* view, void* data, float* progress, char* text) { title_info* info = (title_info*) data; Result res = 0; aptOpenSession(); if(R_SUCCEEDED(res = APT_PrepareToDoAppJump(0, info->titleId, info->mediaType))) { u8 buf0[0x300]; u8 buf1[0x20]; res = APT_DoAppJump(0x300, 0x20, buf0, buf1); } aptCloseSession(); if(R_FAILED(res)) { ui_pop(); info_destroy(view); error_display_res(NULL, info, ui_draw_title_info, res, "Failed to launch title."); } }
static void action_install_cdn_update(ui_view* view, void* data, float* progress, char* text) { install_cdn_data* installData = (install_cdn_data*) data; if(installData->installInfo.finished) { ui_pop(); info_destroy(view); Result res = 0; if(R_SUCCEEDED(installData->installInfo.result)) { if(R_SUCCEEDED(res = AM_InstallTitleFinish()) && R_SUCCEEDED(res = AM_CommitImportTitles(((installData->ticket->titleId >> 32) & 0x8010) != 0 ? MEDIATYPE_NAND : MEDIATYPE_SD, 1, false, &installData->ticket->titleId))) { util_import_seed(installData->ticket->titleId); if(installData->ticket->titleId == 0x0004013800000002 || installData->ticket->titleId == 0x0004013820000002) { res = AM_InstallFirm(installData->ticket->titleId); } } } if(R_SUCCEEDED(installData->installInfo.result) && R_SUCCEEDED(res)) { if(installData->finishedPrompt) { prompt_display("Success", "Install finished.", COLOR_TEXT, false, installData->ticket, NULL, ui_draw_ticket_info, NULL); } } else { AM_InstallTitleAbort(); if(R_FAILED(res)) { error_display_res(NULL, installData->ticket, ui_draw_ticket_info, res, "Failed to install CDN title."); } } action_install_cdn_free_data(installData); return; }
void action_install_tickets(file_info* info, bool* populated) { install_tickets_data* data = (install_tickets_data*) calloc(1, sizeof(install_tickets_data)); data->base = info; data->installInfo.data = data; data->installInfo.op = DATAOP_COPY; data->installInfo.copyEmpty = false; data->installInfo.isSrcDirectory = action_install_tickets_is_src_directory; data->installInfo.makeDstDirectory = action_install_tickets_make_dst_directory; data->installInfo.openSrc = action_install_tickets_open_src; data->installInfo.closeSrc = action_install_tickets_close_src; data->installInfo.getSrcSize = action_install_tickets_get_src_size; data->installInfo.readSrc = action_install_tickets_read_src; data->installInfo.openDst = action_install_tickets_open_dst; data->installInfo.closeDst = action_install_tickets_close_dst; data->installInfo.writeDst = action_install_tickets_write_dst; data->installInfo.error = action_install_tickets_error; data->cancelEvent = 0; Result res = 0; if(R_FAILED(res = util_populate_contents(&data->contents, &data->installInfo.total, info->archive, info->path, false, false, ".tik", util_filter_file_extension))) { error_display_res(NULL, info, ui_draw_file_info, res, "Failed to retrieve content list."); free(data); return; } prompt_display("Confirmation", "Install the selected ticket(s)?", COLOR_TEXT, true, data, NULL, action_install_tickets_draw_top, action_install_tickets_onresponse); }
void files_open(FS_Archive archive) { files_data* data = (files_data*) calloc(1, sizeof(files_data)); data->archive = archive; if(data->archive.lowPath.size > 0) { data->archivePath = calloc(1, data->archive.lowPath.size); memcpy(data->archivePath, data->archive.lowPath.data, data->archive.lowPath.size); data->archive.lowPath.data = data->archivePath; } data->archive.handle = 0; Result res = 0; if(R_FAILED(res = FSUSER_OpenArchive(&data->archive))) { error_display_res(NULL, NULL, NULL, res, "Failed to open file listing archive."); if(data->archivePath != NULL) { free(data->archivePath); } free(data); return; } data->currDir.archive = &data->archive; snprintf(data->currDir.path, PATH_MAX, "/"); util_get_path_file(data->currDir.name, data->currDir.path, NAME_MAX); data->currDir.isDirectory = true; data->currDir.containsCias = false; data->currDir.size = 0; data->currDir.isCia = false; memcpy(&data->parentDir, &data->currDir, sizeof(data->parentDir)); list_display("Files", "A: Select, B: Back, X: Refresh, Y: Directory Action", data, files_update, files_draw_top); }
void action_paste_contents(linked_list* items, list_item* selected) { if(!clipboard_has_contents()) { prompt_display("Failure", "Clipboard empty.", COLOR_TEXT, false, NULL, NULL, NULL); return; } paste_files_data* data = (paste_files_data*) calloc(1, sizeof(paste_files_data)); if(data == NULL) { error_display(NULL, NULL, "Failed to allocate paste files data."); return; } data->items = items; data->target = (file_info*) selected->data; data->pasteInfo.data = data; data->pasteInfo.op = DATAOP_COPY; data->pasteInfo.copyBufferSize = 256 * 1024; data->pasteInfo.copyEmpty = true; data->pasteInfo.isSrcDirectory = action_paste_files_is_src_directory; data->pasteInfo.makeDstDirectory = action_paste_files_make_dst_directory; data->pasteInfo.openSrc = action_paste_files_open_src; data->pasteInfo.closeSrc = action_paste_files_close_src; data->pasteInfo.getSrcSize = action_paste_files_get_src_size; data->pasteInfo.readSrc = action_paste_files_read_src; data->pasteInfo.openDst = action_paste_files_open_dst; data->pasteInfo.closeDst = action_paste_files_close_dst; data->pasteInfo.writeDst = action_paste_files_write_dst; data->pasteInfo.suspendCopy = action_paste_files_suspend_copy; data->pasteInfo.restoreCopy = action_paste_files_restore_copy; data->pasteInfo.suspend = action_paste_files_suspend; data->pasteInfo.restore = action_paste_files_restore; data->pasteInfo.error = action_paste_files_error; data->pasteInfo.finished = true; linked_list_init(&data->contents); populate_files_data popData; memset(&popData, 0, sizeof(popData)); popData.items = &data->contents; popData.archive = clipboard_get_archive(); strncpy(popData.path, clipboard_get_path(), FILE_PATH_MAX); popData.recursive = true; popData.includeBase = !clipboard_is_contents_only() || !util_is_dir(clipboard_get_archive(), clipboard_get_path()); popData.filter = NULL; popData.filterData = NULL; Result listRes = task_populate_files(&popData); if(R_FAILED(listRes)) { error_display_res(NULL, NULL, listRes, "Failed to initiate clipboard content list population."); action_paste_files_free_data(data); return; } while(!popData.finished) { svcSleepThread(1000000); } if(R_FAILED(popData.result)) { error_display_res(NULL, NULL, popData.result, "Failed to populate clipboard content list."); action_paste_files_free_data(data); return; } data->pasteInfo.total = linked_list_size(&data->contents); data->pasteInfo.processed = data->pasteInfo.total; prompt_display("Confirmation", "Paste clipboard contents to the current directory?", COLOR_TEXT, true, data, action_paste_files_draw_top, action_paste_files_onresponse); }
static void files_action_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) { files_action_data* actionData = (files_action_data*) data; if(hidKeysDown() & KEY_B) { ui_pop(); list_destroy(view); free(data); return; } 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; ui_pop(); list_destroy(view); if(selected == © || selected == ©_all_contents) { file_info* info = (file_info*) actionData->selected->data; Result res = 0; if(R_SUCCEEDED(res = clipboard_set_contents(actionData->parent->archiveId, &actionData->parent->archivePath, 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, NULL, ui_draw_file_info, NULL); } else { error_display_res(NULL, info, ui_draw_file_info, res, "Failed to copy to clipboard."); } } else { action(actionData->items, actionData->selected); } free(data); return; } if(linked_list_size(items) == 0) { file_info* info = (file_info*) actionData->selected->data; if(info->isDirectory) { if(info->containsCias) { linked_list_add(items, &install_all_cias); linked_list_add(items, &install_and_delete_all_cias); linked_list_add(items, &delete_all_cias); } if(info->containsTickets) { linked_list_add(items, &install_all_tickets); linked_list_add(items, &install_and_delete_all_tickets); linked_list_add(items, &delete_all_tickets); } linked_list_add(items, &delete_all_contents); linked_list_add(items, ©_all_contents); linked_list_add(items, &delete_dir); } else { if(info->isCia) { linked_list_add(items, &install_cia); linked_list_add(items, &install_and_delete_cia); } if(info->isTicket) { linked_list_add(items, &install_ticket); linked_list_add(items, &install_and_delete_ticket); } linked_list_add(items, &delete_file); } linked_list_add(items, ©); linked_list_add(items, &paste); } }
static void files_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) { files_data* listData = (files_data*) data; if(listData->populated) { // Detect whether the current directory was renamed by an action. 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)) { char parentDir[FILE_PATH_MAX] = {'\0'}; util_get_parent_path(parentDir, listData->currDir, FILE_PATH_MAX); files_navigate(listData, items, parentDir); } if(hidKeysDown() & KEY_B) { if(strncmp(listData->currDir, "/", FILE_PATH_MAX) == 0) { ui_pop(); files_free_data(listData); task_clear_files(items); list_destroy(view); return; } else { char parentDir[FILE_PATH_MAX] = {'\0'}; util_get_parent_path(parentDir, listData->currDir, FILE_PATH_MAX); files_navigate(listData, items, parentDir); } } if(hidKeysDown() & KEY_SELECT) { files_filters_open(listData); return; } if(selected != NULL && selected->data != NULL && (selectedTouched || (hidKeysDown() & KEY_A))) { file_info* fileInfo = (file_info*) selected->data; if((fileInfo->attributes & FS_ATTRIBUTE_DIRECTORY) && strncmp(selected->name, "<current directory>", LIST_ITEM_NAME_MAX) != 0) { files_navigate(listData, items, fileInfo->path); } else { files_action_open(items, selected, listData); return; } } if(!listData->populated || (hidKeysDown() & KEY_X)) { files_repopulate(listData, items); } if(listData->populateData.finished && R_FAILED(listData->populateData.result)) { error_display_res(NULL, NULL, listData->populateData.result, "Failed to populate file list."); listData->populateData.result = 0; } }