#include "utils.h" #include #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); char *out = malloc(len + 1); out[len] = 0; memcpy(out, in, len); return out; } void MaskIn(char *mod, u32 bitstream, char mask){ u32 len = strlen(mod); for (int i = 0; i < len; i++){ if (!(bitstream & 1)) *mod = mask; bitstream >>= 1; mod++; } } // non-zero is yes, zero is no bool StrEndsWith(char *begin, char *end){ begin = strrchr(begin, *end); if (begin != NULL) return !strcmp(begin, end); return 0; } 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; }