From 9f562dbd39eb68f887c3d04692a112162ef07245 Mon Sep 17 00:00:00 2001 From: d0k3 Date: Mon, 14 Mar 2016 23:38:43 +0100 Subject: [PATCH] Added ability to rename files --- source/draw.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++ source/draw.h | 1 + source/fs.c | 10 +++++ source/fs.h | 3 ++ source/godmode.c | 20 +++++++-- 5 files changed, 142 insertions(+), 3 deletions(-) diff --git a/source/draw.c b/source/draw.c index 5743a76..6a3f265 100644 --- a/source/draw.c +++ b/source/draw.c @@ -264,6 +264,117 @@ bool ShowUnlockSequence(u32 seqlvl, const char *format, ...) { return (lvl >= len); } +bool ShowInputPrompt(char* inputstr, u32 max_size, const char *format, ...) { + const char* alphabet = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz(){}[]'`^,~!@#$%&0123456789=+-_."; + const u32 alphabet_size = strnlen(alphabet, 256); + const u32 input_shown = 22; + const u32 fast_scroll = 4; + + u32 str_width, str_height; + u32 x, y; + + char str[512] = {}; // 512 should be more than enough + va_list va; + + va_start(va, format); + vsnprintf(str, 512, format, va); + va_end(va); + + // check / fix up the inputstring if required + if (max_size < 2) return false; // catching this, too + if (*inputstr == '\0') snprintf(inputstr, 2, "%c", alphabet[0]); // set the string if it is not set + + str_width = GetDrawStringWidth(str); + str_height = GetDrawStringHeight(str) + (8*10); + if (str_width < 24) str_width = 24; + x = (str_width >= SCREEN_WIDTH_TOP) ? 0 : (SCREEN_WIDTH_TOP - str_width) / 2; + y = (str_height >= SCREEN_HEIGHT) ? 0 : (SCREEN_HEIGHT - str_height) / 2; + + ClearScreenF(true, false, COLOR_STD_BG); + DrawStringF(true, x, y, COLOR_STD_FONT, COLOR_STD_BG, str); + DrawStringF(true, x + 8, y + str_height - 38, COLOR_STD_FONT, COLOR_STD_BG, "R - (\x18\x19) fast scroll\nL - clear string\nX - remove char\nY - insert char"); + + int cursor_s = 0; + int cursor_a = -1; + int scroll = 0; + bool ret = false; + + while (true) { + u32 inputstr_size = strnlen(inputstr, max_size - 1); + if (cursor_s < scroll) scroll = cursor_s; + else if (cursor_s - scroll >= input_shown) scroll = cursor_s - input_shown + 1; + DrawStringF(true, x, y + str_height - 68, COLOR_STD_FONT, COLOR_STD_BG, "%c%-*.*s%c%-*.*s\n%-*.*s^%-*.*s", + (scroll) ? '<' : '|', + (inputstr_size > input_shown) ? input_shown : inputstr_size, + (inputstr_size > input_shown) ? input_shown : inputstr_size, + inputstr + scroll, + (inputstr_size - scroll > input_shown) ? '>' : '|', + (inputstr_size > input_shown) ? 0 : input_shown - inputstr_size, + (inputstr_size > input_shown) ? 0 : input_shown - inputstr_size, + "", + 1 + cursor_s - scroll, + 1 + cursor_s - scroll, + "", + input_shown - (cursor_s - scroll), + input_shown - (cursor_s - scroll), + "" + ); + if (cursor_a < 0) { + for (cursor_a = alphabet_size - 1; (cursor_a > 0) && (alphabet[cursor_a] != inputstr[cursor_s]); cursor_a--); + } + u32 pad_state = InputWait(); + if (pad_state & BUTTON_A) { + ret = true; + break; + } else if (pad_state & BUTTON_B) { + break; + } else if (pad_state & BUTTON_L1) { + cursor_a = 0; + cursor_s = 0; + inputstr[0] = alphabet[0]; + inputstr[1] = '\0'; + } else if (pad_state & BUTTON_X) { + if (inputstr_size > 1) { + inputstr_size--; + memmove(&inputstr[cursor_s], &inputstr[cursor_s + 1], max_size - (cursor_s + 1)); + if (cursor_s >= inputstr_size) { + cursor_s--; + cursor_a = -1; + } + } else inputstr[0] = alphabet[0]; + } else if (pad_state & BUTTON_Y) { + if (inputstr_size < max_size - 1) { + inputstr_size--; + memmove(&inputstr[cursor_s + 1], &inputstr[cursor_s], max_size - (cursor_s + 1)); + inputstr[cursor_s] = alphabet[0]; + cursor_a = 0; + } else inputstr[0] = alphabet[0]; + } else if (pad_state & BUTTON_UP) { + cursor_a += (pad_state & BUTTON_R1) ? fast_scroll : 1; + cursor_a = cursor_a % alphabet_size; + inputstr[cursor_s] = alphabet[cursor_a]; + } else if (pad_state & BUTTON_DOWN) { + cursor_a -= (pad_state & BUTTON_R1) ? fast_scroll : 1; + if (cursor_a < 0) cursor_a = alphabet_size + cursor_a; + inputstr[cursor_s] = alphabet[cursor_a]; + } else if (pad_state & BUTTON_LEFT) { + if (cursor_s > 0) cursor_s--; + cursor_a = -1; + } else if (pad_state & BUTTON_RIGHT) { + if (cursor_s < max_size - 2) cursor_s++; + if (cursor_s >= inputstr_size) { + inputstr[cursor_s] = alphabet[0]; + inputstr[cursor_s+1] = '\0'; + } + cursor_a = -1; + } + } + + ClearScreenF(true, false, COLOR_STD_BG); + + return ret; +} + bool ShowProgress(u64 current, u64 total, const char* opstr) { static u32 last_prog_width = 0; diff --git a/source/draw.h b/source/draw.h index 989b020..ffae9f5 100644 --- a/source/draw.h +++ b/source/draw.h @@ -70,4 +70,5 @@ void FormatBytes(char* str, u64 bytes); bool ShowPrompt(bool ask, const char *format, ...); bool ShowUnlockSequence(u32 seqlvl, const char *format, ...); +bool ShowInputPrompt(char* inputstr, u32 max_size, const char *format, ...); bool ShowProgress(u64 current, u64 total, const char* opstr); diff --git a/source/fs.c b/source/fs.c index 2549592..d1fe654 100644 --- a/source/fs.c +++ b/source/fs.c @@ -288,6 +288,16 @@ bool PathDelete(const char* path) { return PathDeleteWorker(fpath); } +bool PathRename(const char* path, const char* newname) { + char npath[256]; // 256 is the maximum length of a full path + char* oldname = strrchr(path, '/'); + if (!oldname) return false; + oldname++; + strncpy(npath, path, oldname - path); + strncpy(npath + (oldname - path), newname, strnlen(newname, 255 - (oldname - path))); + return (f_rename(path, npath) == FR_OK); +} + void CreateScreenshot() { const u8 bmp_header[54] = { 0x42, 0x4D, 0x36, 0xCA, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00, diff --git a/source/fs.h b/source/fs.h index 1e9bc86..f0cd179 100644 --- a/source/fs.h +++ b/source/fs.h @@ -49,6 +49,9 @@ bool PathCopy(const char* destdir, const char* orig); /** Recursively delete a file or directory **/ bool PathDelete(const char* path); +/** Rename file / folder in path to new name **/ +bool PathRename(const char* path, const char* newname); + /** Create a screenshot of the current framebuffer **/ void CreateScreenshot(); diff --git a/source/godmode.c b/source/godmode.c index 597bd7b..1f3ec1b 100644 --- a/source/godmode.c +++ b/source/godmode.c @@ -75,7 +75,7 @@ void DrawUserInterface(const char* curr_path, DirEntry* curr_entry, DirStruct* c // bottom: inctruction block char instr[256]; snprintf(instr, 256, "%s%s%s%s%s", - "GodMode9 Explorer v0.0.9\n", // generic start part + "GodMode9 Explorer v0.1.1\n", // generic start part (*curr_path) ? ((clipboard->n_entries == 0) ? "L - MARK files (use with \x18\x19\x1A\x1B)\nX - DELETE / [+R] RENAME file(s)\nY - COPY file(s) / [+R] CREATE dir\n" : "L - MARK files (use with \x18\x19\x1A\x1B)\nX - DELETE / [+R] RENAME file(s)\nY - PASTE file(s) / [+R] CREATE dir\n") : ((GetWritePermissions() <= 1) ? "X - Unlock EmuNAND writing\nY - Unlock SysNAND writing\n" : @@ -166,7 +166,7 @@ u32 GodMode() { } else { // type == T_FAT_DIR || type == T_VRT_ROOT strncpy(current_path, current_dir->entry[cursor].path, 256); } - GetDirContents(current_dir, current_path); + GetDirContents(current_dir, current_path); // maybe start cursor at 1 instead of 0? (!!!) cursor = 0; } else if (pad_state & BUTTON_B) { // one level down char* last_slash = strrchr(current_path, '/'); @@ -270,7 +270,21 @@ u32 GodMode() { ClearScreenF(true, false, COLOR_STD_BG); } } else { // switched command set - // not implemented yet + if (pad_state & BUTTON_X) { // rename a file + char newname[256]; + char namestr[20+1]; + TruncateString(namestr, current_dir->entry[cursor].name, 20, 12); + snprintf(newname, 255, current_dir->entry[cursor].name); + if (ShowInputPrompt(newname, 256, "Rename %s?\nEnter new name below.", namestr)) { + if (!PathRename(current_dir->entry[cursor].path, newname)) + ShowPrompt(false, "Failed renaming path:\n%s", namestr); + else GetDirContents(current_dir, current_path); + } + } else if (pad_state & BUTTON_Y) { // create a folder + char dirname[256]; + snprintf(dirname, 255, "newdir"); + ShowInputPrompt(dirname, 256, "Create a new folder here?\nEnter name below."); + } } if (pad_state & BUTTON_START) {