From dfc02f9f811bd64336df0f6dac5f256b50a1c78f Mon Sep 17 00:00:00 2001 From: suchmememanyskill Date: Tue, 29 Dec 2020 16:51:47 +0100 Subject: [PATCH] Add keyboard, create folder, rename folder/file --- source/fs/menus/filemenu.c | 21 ++- source/fs/menus/foldermenu.c | 40 +++++- source/gfx/gfx.c | 6 + source/gfx/gfx.h | 1 + source/gfx/gfxutils.c | 6 +- source/gfx/gfxutils.h | 2 +- source/hid/hid.h | 4 + source/tegraexplorer/mainmenu.c | 4 + source/tegraexplorer/tools.c | 2 +- source/utils/utils.c | 227 ++++++++++++++++++++++++++++++++ source/utils/utils.h | 3 +- 11 files changed, 307 insertions(+), 9 deletions(-) diff --git a/source/fs/menus/filemenu.c b/source/fs/menus/filemenu.c index 6938f03..e0d6b3d 100644 --- a/source/fs/menus/filemenu.c +++ b/source/fs/menus/filemenu.c @@ -90,10 +90,29 @@ void RunScript(char *path, FSEntry_t entry){ hidWait(); } +void RenameFile(char *path, FSEntry_t entry){ + gfx_clearscreen(); + char *renameTo = ShowKeyboard(entry.name, false); + if (renameTo == NULL || !(*renameTo)) // smol memory leak but eh + return; + + char *src = CombinePaths(path, entry.name); + char *dst = CombinePaths(path, renameTo); + + int res = f_rename(src, dst); + if (res){ + DrawError(newErrCode(res)); + } + + free(src); + free(dst); + free(renameTo); +} + fileMenuPath FileMenuPaths[] = { CopyClipboard, MoveClipboard, - UnimplementedException, + RenameFile, DeleteFile, UnimplementedException, LaunchPayload, diff --git a/source/fs/menus/foldermenu.c b/source/fs/menus/foldermenu.c index f30da53..0b8405a 100644 --- a/source/fs/menus/foldermenu.c +++ b/source/fs/menus/foldermenu.c @@ -64,12 +64,48 @@ int DeleteFolder(const char *path){ return 0; } +int RenameFolder(const char *path){ + char *prev = EscapeFolder(path); + gfx_clearscreen(); + + char *renameTo = ShowKeyboard(strrchr(path, '/') + 1, false); + if (renameTo == NULL || !(*renameTo)) // smol memory leak but eh + return 0; + + char *dst = CombinePaths(prev, renameTo); + + int res = f_rename(path, dst); + if (res){ + DrawError(newErrCode(res)); + } + + free(prev); + free(dst); + free(renameTo); + return 1; +} + +int CreateFolder(const char *path){ + gfx_clearscreen(); + + char *create = ShowKeyboard("New Folder", true); + if (create == NULL || !(*create)) // smol memory leak but eh + return 0; + + char *dst = CombinePaths(path, create); + f_mkdir(dst); + + free(dst); + free(create); + return 0; +} + folderMenuPath FolderMenuPaths[] = { FolderCopyClipboard, FolderMoveClipboard, - UnimplementedFolderException, + RenameFolder, DeleteFolder, - UnimplementedFolderException + CreateFolder }; int FolderMenu(const char *path){ diff --git a/source/gfx/gfx.c b/source/gfx/gfx.c index 0a4af6e..ad05859 100644 --- a/source/gfx/gfx.c +++ b/source/gfx/gfx.c @@ -486,6 +486,12 @@ void gfx_printf(const char *fmt, ...) va_end(ap); } +void gfx_putc_small(char c){ + gfx_con.fntsz = 8; + gfx_putc(c); + gfx_con.fntsz = 16; +} + void gfx_hexdump(u32 base, const u8 *buf, u32 len) { if (gfx_con.mute) diff --git a/source/gfx/gfx.h b/source/gfx/gfx.h index b85efa0..a8f82df 100644 --- a/source/gfx/gfx.h +++ b/source/gfx/gfx.h @@ -69,6 +69,7 @@ void gfx_hexdump(u32 base, const u8 *buf, u32 len); void gfx_hexdiff(u32 base, const u8 *buf1, const u8 *buf2, u32 len); void gfx_puts_limit(const char *s, u32 limit); void gfx_puts_small(const char *s); +void gfx_putc_small(char c); void gfx_set_pixel(u32 x, u32 y, u32 color); void gfx_set_pixel_horz(int x, int y, u32 color); diff --git a/source/gfx/gfxutils.c b/source/gfx/gfxutils.c index 84ad587..ed5fdeb 100644 --- a/source/gfx/gfxutils.c +++ b/source/gfx/gfxutils.c @@ -25,12 +25,12 @@ MenuEntry_t YesNoEntries[] = { }; int MakeYesNoHorzMenu(int spacesBetween, u32 bg){ - return MakeHorizontalMenu(YesNoEntries, ARR_LEN(YesNoEntries), spacesBetween, bg); + return MakeHorizontalMenu(YesNoEntries, ARR_LEN(YesNoEntries), spacesBetween, bg, 0); } -int MakeHorizontalMenu(MenuEntry_t *entries, int len, int spacesBetween, u32 bg){ +int MakeHorizontalMenu(MenuEntry_t *entries, int len, int spacesBetween, u32 bg, int startPos){ u32 initialX = 0, initialY = 0; - u32 highlight = 0; + u32 highlight = startPos; gfx_con_getpos(&initialX, &initialY); while (1){ diff --git a/source/gfx/gfxutils.h b/source/gfx/gfxutils.h index ca448b7..6ed4ed8 100644 --- a/source/gfx/gfxutils.h +++ b/source/gfx/gfxutils.h @@ -14,5 +14,5 @@ #define RGBUnionToU32(optionUnion) (optionUnion | 0xFF000000) void gfx_clearscreen(); -int MakeHorizontalMenu(MenuEntry_t *entries, int len, int spacesBetween, u32 bg); +int MakeHorizontalMenu(MenuEntry_t *entries, int len, int spacesBetween, u32 bg, int startPos); int MakeYesNoHorzMenu(int spacesBetween, u32 bg); \ No newline at end of file diff --git a/source/hid/hid.h b/source/hid/hid.h index 5d85314..285c3d7 100644 --- a/source/hid/hid.h +++ b/source/hid/hid.h @@ -7,11 +7,15 @@ #define JoyX BIT(1) #define JoyB BIT(2) #define JoyA BIT(3) +#define JoyRB BIT(6) #define JoyMenu BIT(12) #define JoyLDown BIT(16) #define JoyLUp BIT(17) #define JoyLRight BIT(18) #define JoyLLeft BIT(19) +#define JoyLB BIT(22) +#define BtnVolP BIT(25) +#define BtnVolM BIT(26) #define JoyRDown BIT(27) #define JoyRUp BIT(28) #define JoyRRight BIT(29) diff --git a/source/tegraexplorer/mainmenu.c b/source/tegraexplorer/mainmenu.c index 9ee9d3b..d2b9d44 100644 --- a/source/tegraexplorer/mainmenu.c +++ b/source/tegraexplorer/mainmenu.c @@ -15,6 +15,10 @@ #include #include "../fs/fsutils.h" +#include +#include "../utils/utils.h" +#include + enum { MainExplore = 0, MainBrowseSd, diff --git a/source/tegraexplorer/tools.c b/source/tegraexplorer/tools.c index 761749d..32c8619 100644 --- a/source/tegraexplorer/tools.c +++ b/source/tegraexplorer/tools.c @@ -137,7 +137,7 @@ void FormatSD(){ return; gfx_printf("\nDo you want to partition for an emummc?\n"); - res = MakeHorizontalMenu(FatAndEmu, ARR_LEN(FatAndEmu), 3, COLOR_DEFAULT); + res = MakeHorizontalMenu(FatAndEmu, ARR_LEN(FatAndEmu), 3, COLOR_DEFAULT, 0); if (!res) return; diff --git a/source/utils/utils.c b/source/utils/utils.c index 24f57fc..96e1ad6 100644 --- a/source/utils/utils.c +++ b/source/utils/utils.c @@ -3,6 +3,11 @@ #include #include #include +#include "vector.h" +#include "../gfx/gfxutils.h" +#include "../gfx/gfx.h" +#include "../gfx/menu.h" +#include "../hid/hid.h" char *CpyStr(const char* in){ int len = strlen(in); @@ -35,4 +40,226 @@ bool StrEndsWith(char *begin, char *end){ void WaitFor(u32 ms){ u32 a = get_tmr_ms(); while (a + ms > get_tmr_ms()); +} + +/* + +MenuEntry_t KeyboardHeader[] = { + {.optionUnion = COLORTORGB(COLOR_GREEN), .name = "Cancel"}, + {.optionUnion = COLORTORGB(COLOR_BLUE), .name = "Save"}, + {.optionUnion = COLORTORGB(COLOR_ORANGE), .name = "Remove last char"}, + {.optionUnion = COLORTORGB(COLOR_VIOLET), .name = "Add a char"}, + {.optionUnion = COLORTORGB(COLOR_WHITE), .name = "Edit"} +}; + +char *ShowKeyboard(const char *in){ + u32 len = strlen(in); + + Vector_t menuEntries = newVec(sizeof(MenuEntry_t), len + 1); + MenuEntry_t a = {.optionUnion = COLORTORGB(COLOR_ORANGE), .name = "<- Back "}; + vecAddElem(&menuEntries, a); + + for (int i = 0; i < len; i++){ + MenuEntry_t b = {.optionUnion = COLORTORGB(COLOR_WHITE)}; + b.name = calloc(2,1); + b.name[0] = in[i]; + vecAddElem(&menuEntries, b); + } + + MenuEntry_t *characters = calloc(sizeof(MenuEntry_t), 126 - 32 + 2); + characters[0].name = CpyStr("Cancel"); + characters[0].optionUnion = COLORTORGB(COLOR_ORANGE); + characters[1].name = CpyStr("Space"); + characters[1].optionUnion = COLORTORGB(COLOR_WHITE); + + for (int i = 34; i <= 127; i++){ + characters[i - 32].name = calloc(2,1); + characters[i - 32].name[0] = i - 1; + characters[i - 32].optionUnion = COLORTORGB(COLOR_WHITE); + } + + Vector_t temp = vecFromArray(characters, 126 - 32 + 2, sizeof(MenuEntry_t)); + + u32 x, y; + gfx_con_getpos(&x, &y); + + int res = 0; + + while (1){ + gfx_con_setpos(x,y); + RESETCOLOR; + gfx_boxGrey(x, y, YLEFT, y + 16, 0x1B); + vecDefArray(MenuEntry_t*, entries , menuEntries); + for (int i = 1; i < menuEntries.count; i++){ + gfx_putc(entries[i].name[0]); + } + gfx_putc('\n'); + res = MakeHorizontalMenu(KeyboardHeader, ARR_LEN(KeyboardHeader), 2, COLOR_DEFAULT, res); + + if (res <= 1){ + break; + } + else if (res == 2){ + if (menuEntries.count > 1) + menuEntries.count--; + } + else if (res == 3){ + if (menuEntries.count <= 64){ + MenuEntry_t b = {.optionUnion = COLORTORGB(COLOR_WHITE), .name = CpyStr("a")}; + vecAddElem(&menuEntries, b); + } + } + else if (res == 4){ + int newRes = 0; + while (1){ + gfx_con_setpos(x,y); + RESETCOLOR; + gfx_boxGrey(x, y, YLEFT, y + 32, 0x1B); + newRes = MakeHorizontalMenu(entries, menuEntries.count, 0, COLOR_DEFAULT, newRes); + if (newRes == 0) + break; + else { + gfx_printf("\n\nCharacter select: "); + int selectedChar = newMenu(&temp, entries[newRes].name[0] - 31, 8, 10, ENABLEB, temp.count); + if (selectedChar) + entries[newRes].name[0] = selectedChar + 31; + gfx_boxGrey(x, y, YLEFT, y + 16 * 14, 0x1B); + } + } + for (int i = 1; i < menuEntries.count; i++){ + if (strchr("\\/:*\"<>|", entries[i].name[0]) != NULL){ + entries[i].name[0] = '_'; + } + } + } + } + + char *reconstruct = calloc(menuEntries.count, 1); + + vecDefArray(MenuEntry_t*, entries, menuEntries); + for (int i = 1; i < menuEntries.count; i++){ + reconstruct[i - 1] = entries[i].name[0]; + free(entries[i].name); + } + vecFree(menuEntries); + + for (int i = 0; i < 126 - 32 + 2; i++){ + free(characters[i].name); + } + free(characters); + + if (!res){ + free(reconstruct); + return NULL; + } + + return reconstruct; +} +*/ + +char *lines[] = { + "1234567890*", // 0 - 10 + "qwertyuiop~", // 11 - 21 + "asdfghjkl.+", // 22 - 32 + "^zxcvbnm_<>" // 33 - 43 +}; + +char *ShowKeyboard(const char *toEdit, u8 alwaysRet){ + char *ret = CpyStr(toEdit); + int pos = 0; + int posOnWord = 0; + bool shift = 0; + + gfx_printf("* = exit | ~ = backspace | ^(left) = shift | _ = Space | + = add char\n\n"); + + u32 x, y; + gfx_con_getpos(&x, &y); + + while (1){ + gfx_con_setpos(x, y); + + for (int i = 0; i < strlen(ret); i++){ + (i == posOnWord) ? SETCOLOR(COLOR_WHITE, COLOR_VIOLET) : SETCOLOR(COLOR_WHITE, COLOR_DEFAULT); + gfx_putc(ret[i]); + } + + RESETCOLOR; + gfx_putc(' '); + + for (int a = 0; a < 4; a++){ + for (int b = 0; b < 11; b++){ + (pos == ((b % 11) + (a * 11))) ? SETCOLOR(COLOR_DEFAULT, COLOR_WHITE) : SETCOLOR(COLOR_WHITE, COLOR_DEFAULT); + gfx_con_setpos(x + 16 + (b * 2 * 16), y + a * 16 * 2 + 32); + if (shift && lines[a][b] >= 'a' && lines[a][b] <= 'z') + gfx_putc(lines[a][b] & ~BIT(5)); + else + gfx_putc(lines[a][b]); + } + } + + Input_t *input = hidWait(); + if (input->buttons & (JoyA | JoyLB | JoyRB)){ + if (pos == 10){ + break; + } + else if (pos == 21){ + u32 wordLen = strlen(ret); + if (!wordLen) + continue; + + for (int i = posOnWord; i < wordLen - 1; i++){ + ret[i] = ret[i + 1]; + } + ret[wordLen - 1] = 0; + if (posOnWord > wordLen - 2) + posOnWord--; + } + else if (pos == 32){ + u32 wordLen = strlen(ret); + char *copy = calloc(wordLen + 2, 1); + memcpy(copy, ret, wordLen); + copy[wordLen] = 'a'; + free(ret); + ret = copy; + } + else if (pos == 33){ + shift = !shift; + } + else if (pos == 42 || input->l){ + if (posOnWord > 0) + posOnWord--; + } + else if (pos == 43 || input->r){ + if (strlen(ret) - 1 > posOnWord) + posOnWord++; + } + else { + char toPut = lines[pos / 11][pos % 11]; + if (shift) + toPut &= ~BIT(5); + ret[posOnWord] = toPut; + } + } + int val = (input->up || input->down) ? 11 : 1; + + if (input->buttons & (JoyLLeft | JoyLUp | BtnVolM)){ + if (pos > -1 + val) + pos -= val; + } + if (input->buttons & (JoyLRight | JoyLDown | BtnVolP)){ + if (pos < 44 - val) + pos += val; + } + + if (input->b){ + break; + } + } + + if (!strcmp(ret, toEdit) && !alwaysRet){ + free(ret); + return NULL; + } + + return ret; } \ No newline at end of file diff --git a/source/utils/utils.h b/source/utils/utils.h index df8c5e2..5c79840 100644 --- a/source/utils/utils.h +++ b/source/utils/utils.h @@ -6,4 +6,5 @@ void MaskIn(char *mod, u32 bitstream, char mask); bool StrEndsWith(char *begin, char *end); void WaitFor(u32 ms); -#define FREE(x) free(x); x = NULL; \ No newline at end of file +#define FREE(x) free(x); x = NULL; +char *ShowKeyboard(const char *toEdit, u8 alwaysRet); \ No newline at end of file