forked from Mirror/GodMode9
Enabled basic file searching
This commit is contained in:
parent
b51af7ceb4
commit
dfd0a4e306
@ -34,7 +34,7 @@
|
||||
/ 2: Enable with LF-CRLF conversion. */
|
||||
|
||||
|
||||
#define _USE_FIND 1
|
||||
#define _USE_FIND 0
|
||||
/* This option switches filtered directory read functions, f_findfirst() and
|
||||
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
|
||||
|
||||
|
44
source/fatfs/store.c
Normal file
44
source/fatfs/store.c
Normal file
@ -0,0 +1,44 @@
|
||||
#include "store.h"
|
||||
#include "ff.h"
|
||||
|
||||
#define STORE_BUFFER ((DirStruct*)0x21300000)
|
||||
|
||||
static bool is_stored = false;
|
||||
|
||||
bool IsStoredDrive(const char* path) {
|
||||
return is_stored && (strncmp(path, "Z:", 3) == 0);
|
||||
}
|
||||
|
||||
void StoreDirContents(DirStruct* contents) {
|
||||
memcpy(STORE_BUFFER, contents, sizeof(DirStruct));
|
||||
is_stored = true;
|
||||
}
|
||||
|
||||
void GetStoredDirContents(DirStruct* contents) {
|
||||
// warning: this assumes the store buffer is filled with data that makes sense
|
||||
DirStruct* stored = STORE_BUFFER;
|
||||
u32 skip = 0;
|
||||
|
||||
// basic sanity checking
|
||||
if (!is_stored || (stored->n_entries > MAX_ENTRIES)) return;
|
||||
|
||||
// copy available entries, remove missing from storage
|
||||
for (u32 i = 0; i < stored->n_entries; i++) {
|
||||
DirEntry* entry = &(stored->entry[i]);
|
||||
if (strncmp(entry->name, "..", 3) == 0) continue; // disregard dotdot entry
|
||||
if (f_stat(entry->path, NULL) != FR_OK) {
|
||||
skip++; // remember this has to be removed from the stored struct
|
||||
} else { // entry is valid
|
||||
if (skip) { // move remaining entries to the left
|
||||
stored->n_entries -= skip;
|
||||
memmove(entry - skip, entry, (stored->n_entries - i) * sizeof(DirEntry));
|
||||
entry -= skip;
|
||||
skip = 0;
|
||||
}
|
||||
if (contents->n_entries < MAX_ENTRIES)
|
||||
memcpy(&(contents->entry[contents->n_entries++]), entry, sizeof(DirEntry));
|
||||
else break;
|
||||
}
|
||||
}
|
||||
stored->n_entries -= skip;
|
||||
}
|
7
source/fatfs/store.h
Normal file
7
source/fatfs/store.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "fs.h"
|
||||
|
||||
bool IsStoredDrive(const char* path);
|
||||
void StoreDirContents(DirStruct* contents);
|
||||
void GetStoredDirContents(DirStruct* contents);
|
50
source/fs.c
50
source/fs.c
@ -2,6 +2,7 @@
|
||||
#include "fs.h"
|
||||
#include "virtual.h"
|
||||
#include "image.h"
|
||||
#include "store.h"
|
||||
#include "sha.h"
|
||||
#include "sdmmc.h"
|
||||
#include "ff.h"
|
||||
@ -74,7 +75,7 @@ void DeinitSDCardFS() {
|
||||
int PathToNumFS(const char* path) {
|
||||
int fsnum = *path - (int) '0';
|
||||
if ((fsnum < 0) || (fsnum >= NORM_FS) || (path[1] != ':')) {
|
||||
if (!GetVirtualSource(path)) ShowPrompt(false, "Invalid path (%s)", path);
|
||||
if (!GetVirtualSource(path) && !IsStoredDrive(path)) ShowPrompt(false, "Invalid path (%s)", path);
|
||||
return -1;
|
||||
}
|
||||
return fsnum;
|
||||
@ -949,6 +950,34 @@ void SortDirStruct(DirStruct* contents) {
|
||||
}
|
||||
}
|
||||
|
||||
// inspired by http://www.geeksforgeeks.org/wildcard-character-matching/
|
||||
bool MatchName(const char *pattern, const char *path) {
|
||||
// handling non asterisk chars
|
||||
for (; *pattern != '*'; pattern++, path++) {
|
||||
if ((*pattern == '\0') && (*path == '\0')) {
|
||||
return true; // end reached simultaneously, match found
|
||||
} else if ((*pattern == '\0') || (*path == '\0')) {
|
||||
return false; // end reached on only one, failure
|
||||
} else if ((*pattern != '?') && (tolower(*pattern) != tolower(*path))) {
|
||||
return false; // chars don't match, failure
|
||||
}
|
||||
}
|
||||
// handling the asterisk (matches one or more chars in path)
|
||||
if ((*(pattern+1) == '?') || (*(pattern+1) == '*')) {
|
||||
return false; // stupid user shenanigans, failure
|
||||
} else if (*path == '\0') {
|
||||
return false; // asterisk, but end reached on path, failure
|
||||
} else if (*(pattern+1) == '\0') {
|
||||
return true; // nothing after the asterisk, match found
|
||||
} else { // we couldn't really go without recursion here
|
||||
for (path++; *path != '\0'; path++) {
|
||||
if (MatchName(pattern + 1, path)) return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GetRootDirContentsWorker(DirStruct* contents) {
|
||||
static const char* drvname[] = {
|
||||
"SDCARD",
|
||||
@ -986,11 +1015,12 @@ bool GetRootDirContentsWorker(DirStruct* contents) {
|
||||
return contents->n_entries;
|
||||
}
|
||||
|
||||
bool GetVirtualDirContentsWorker(DirStruct* contents, const char* path) {
|
||||
bool GetVirtualDirContentsWorker(DirStruct* contents, const char* path, const char* pattern) {
|
||||
if (strchr(path, '/')) return false; // only top level paths
|
||||
for (u32 n = 0; (n < virtualFileList_size) && (contents->n_entries < MAX_ENTRIES); n++) {
|
||||
VirtualFile vfile;
|
||||
DirEntry* entry = &(contents->entry[contents->n_entries]);
|
||||
if (pattern && !MatchName(pattern, virtualFileList[n])) continue;
|
||||
snprintf(entry->path, 256, "%s/%s", path, virtualFileList[n]);
|
||||
if (!FindVirtualFile(&vfile, entry->path, 0)) continue;
|
||||
entry->name = entry->path + strnlen(path, 256) + 1;
|
||||
@ -1003,7 +1033,7 @@ bool GetVirtualDirContentsWorker(DirStruct* contents, const char* path) {
|
||||
return true; // not much we can check here
|
||||
}
|
||||
|
||||
bool GetDirContentsWorker(DirStruct* contents, char* fpath, int fnsize, bool recursive) {
|
||||
bool GetDirContentsWorker(DirStruct* contents, char* fpath, int fnsize, const char* pattern, bool recursive) {
|
||||
DIR pdir;
|
||||
FILINFO fno;
|
||||
char* fname = fpath + strnlen(fpath, fnsize - 1);
|
||||
@ -1020,7 +1050,7 @@ bool GetDirContentsWorker(DirStruct* contents, char* fpath, int fnsize, bool rec
|
||||
if (fno.fname[0] == 0) {
|
||||
ret = true;
|
||||
break;
|
||||
} else {
|
||||
} else if (!pattern || MatchName(pattern, fname)) {
|
||||
DirEntry* entry = &(contents->entry[contents->n_entries]);
|
||||
strncpy(entry->path, fpath, 256);
|
||||
entry->name = entry->path + (fname - fpath);
|
||||
@ -1037,7 +1067,7 @@ bool GetDirContentsWorker(DirStruct* contents, char* fpath, int fnsize, bool rec
|
||||
break;
|
||||
}
|
||||
if (recursive && (fno.fattrib & AM_DIR)) {
|
||||
if (!GetDirContentsWorker(contents, fpath, fnsize, recursive))
|
||||
if (!GetDirContentsWorker(contents, fpath, fnsize, pattern, recursive))
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1046,7 +1076,7 @@ bool GetDirContentsWorker(DirStruct* contents, char* fpath, int fnsize, bool rec
|
||||
return ret;
|
||||
}
|
||||
|
||||
void GetDirContents(DirStruct* contents, const char* path) {
|
||||
void SearchDirContents(DirStruct* contents, const char* path, const char* pattern, bool recursive) {
|
||||
contents->n_entries = 0;
|
||||
if (!(*path)) { // root directory
|
||||
if (!GetRootDirContentsWorker(contents))
|
||||
@ -1060,18 +1090,22 @@ void GetDirContents(DirStruct* contents, const char* path) {
|
||||
contents->entry->size = 0;
|
||||
contents->n_entries = 1;
|
||||
if (GetVirtualSource(path)) {
|
||||
if (!GetVirtualDirContentsWorker(contents, path))
|
||||
if (!GetVirtualDirContentsWorker(contents, path, pattern))
|
||||
contents->n_entries = 0;
|
||||
} else {
|
||||
char fpath[256]; // 256 is the maximum length of a full path
|
||||
strncpy(fpath, path, 256);
|
||||
if (!GetDirContentsWorker(contents, fpath, 256, false))
|
||||
if (!GetDirContentsWorker(contents, fpath, 256, pattern, recursive))
|
||||
contents->n_entries = 0;
|
||||
}
|
||||
SortDirStruct(contents);
|
||||
}
|
||||
}
|
||||
|
||||
void GetDirContents(DirStruct* contents, const char* path) {
|
||||
SearchDirContents(contents, path, NULL, false);
|
||||
}
|
||||
|
||||
uint64_t GetFreeSpace(const char* path)
|
||||
{
|
||||
DWORD free_clusters;
|
||||
|
@ -90,6 +90,9 @@ bool DirCreate(const char* cpath, const char* dirname);
|
||||
/** Create a screenshot of the current framebuffer **/
|
||||
void CreateScreenshot();
|
||||
|
||||
/** Search under a given path **/
|
||||
void SearchDirContents(DirStruct* contents, const char* path, const char* pattern, bool recursive);
|
||||
|
||||
/** Get directory content under a given path **/
|
||||
void GetDirContents(DirStruct* contents, const char* path);
|
||||
|
||||
|
@ -6,8 +6,9 @@
|
||||
#include "nand.h"
|
||||
#include "virtual.h"
|
||||
#include "image.h"
|
||||
#include "store.h"
|
||||
|
||||
#define VERSION "0.6.2"
|
||||
#define VERSION "0.6.3"
|
||||
|
||||
#define N_PANES 2
|
||||
#define IMG_DRV "789I"
|
||||
@ -544,13 +545,26 @@ u32 GodMode() {
|
||||
}
|
||||
|
||||
// basic navigation commands
|
||||
if ((pad_state & BUTTON_A) && (curr_entry->type != T_FILE) && (curr_entry->type != T_DOTDOT)) { // one level up
|
||||
if ((pad_state & BUTTON_A) && (curr_entry->type != T_FILE) && (curr_entry->type != T_DOTDOT)) { // for dirs
|
||||
if (switched) { // search directory
|
||||
char searchstr[256];
|
||||
char namestr[20+1];
|
||||
snprintf(searchstr, 256, "*.*");
|
||||
TruncateString(namestr, curr_entry->name, 20, 8);
|
||||
if (ShowStringPrompt(searchstr, 256, "Search %s?\nEnter search below.", namestr)) {
|
||||
ShowString("Searching path, please wait...");
|
||||
snprintf(current_path, 256, "Z:");
|
||||
SearchDirContents(current_dir, curr_entry->path, searchstr, true);
|
||||
StoreDirContents(current_dir);
|
||||
}
|
||||
} else { // one level up
|
||||
strncpy(current_path, curr_entry->path, 256);
|
||||
GetDirContents(current_dir, current_path);
|
||||
if (*current_path && (current_dir->n_entries > 1)) {
|
||||
cursor = 1;
|
||||
scroll = 0;
|
||||
} else cursor = 0;
|
||||
}
|
||||
} else if ((pad_state & BUTTON_A) && (curr_entry->type == T_FILE)) { // process a file
|
||||
u32 file_type = IdentifyImage(curr_entry->path);
|
||||
bool injectable = (clipboard->n_entries == 1) &&
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "nand.h"
|
||||
#include "image.h"
|
||||
|
||||
#define NAND_BUFFER ((u8*)0x21300000)
|
||||
#define NAND_BUFFER ((u8*)0x21400000)
|
||||
#define NAND_BUFFER_SIZE (0x100000) // must be multiple of 0x200
|
||||
#define NAND_MIN_SECTORS ((GetUnitPlatform() == PLATFORM_N3DS) ? 0x26C000 : 0x1D7800)
|
||||
|
||||
|
@ -440,7 +440,7 @@ bool ShowInputPrompt(char* inputstr, u32 max_size, u32 resize, const char* alpha
|
||||
}
|
||||
|
||||
bool ShowStringPrompt(char* inputstr, u32 max_size, const char *format, ...) {
|
||||
const char* alphabet = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz(){}[]'`^,~!@#$%&0123456789=+-_.";
|
||||
const char* alphabet = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz(){}[]'`^,~*?!@#$%&0123456789=+-_.";
|
||||
bool ret = false;
|
||||
va_list va;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user