diff --git a/romfs/kbd_layout.png b/romfs/kbd_layout.png new file mode 100644 index 0000000..08644a8 Binary files /dev/null and b/romfs/kbd_layout.png differ diff --git a/romfs/kbd_press_overlay.png b/romfs/kbd_press_overlay.png new file mode 100644 index 0000000..6cd73dc Binary files /dev/null and b/romfs/kbd_press_overlay.png differ diff --git a/romfs/kbd_text_bg.png b/romfs/kbd_text_bg.png new file mode 100644 index 0000000..0904265 Binary files /dev/null and b/romfs/kbd_text_bg.png differ diff --git a/romfs/kbd_text_fg.png b/romfs/kbd_text_fg.png new file mode 100644 index 0000000..1da3316 Binary files /dev/null and b/romfs/kbd_text_fg.png differ diff --git a/source/core/screen.c b/source/core/screen.c index 7fd7004..ac837c1 100644 --- a/source/core/screen.c +++ b/source/core/screen.c @@ -244,6 +244,10 @@ void screen_init() { screen_load_texture_file(TEXTURE_WIFI_1, "wifi1.png", true); screen_load_texture_file(TEXTURE_WIFI_2, "wifi2.png", true); screen_load_texture_file(TEXTURE_WIFI_3, "wifi3.png", true); + screen_load_texture_file(TEXTURE_KBD_LAYOUT, "kbd_layout.png", true); + screen_load_texture_file(TEXTURE_KBD_PRESS_OVERLAY, "kbd_press_overlay.png", true); + screen_load_texture_file(TEXTURE_KBD_TEXT_BG, "kbd_text_bg.png", true); + screen_load_texture_file(TEXTURE_KBD_TEXT_FG, "kbd_text_fg.png", true); } void screen_exit() { @@ -540,7 +544,11 @@ void screen_select(gfxScreen_t screen) { C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, shaderInstanceGetUniformLocation(program.vertexShader, "projection"), screen == GFX_TOP ? &projection_top : &projection_bottom); } -void screen_draw_quad(float x1, float y1, float x2, float y2, float tx1, float ty1, float tx2, float ty2) { +void screen_set_scissor(bool enabled, u32 x, u32 y, u32 width, u32 height) { + C3D_SetScissor(enabled ? GPU_SCISSOR_NORMAL : GPU_SCISSOR_DISABLE, 240 - (y + height), x, 240 - y, x + width); +} + +static void screen_draw_quad(float x1, float y1, float x2, float y2, float tx1, float ty1, float tx2, float ty2) { C3D_ImmDrawBegin(GPU_TRIANGLES); C3D_ImmSendAttrib(x1, y1, 0.5f, 0.0f); @@ -584,7 +592,7 @@ void screen_draw_texture_crop(u32 id, float x, float y, float width, float heigh screen_draw_quad(x, y, x + width, y + height, 0, 0, width / (float) textures[id].pow2Width, height / (float) textures[id].pow2Height); } -static void screen_get_string_size_internal(float* width, float* height, const char* text, float scaleX, float scaleY, bool oneLine) { +static void screen_get_string_size_internal(float* width, float* height, const char* text, float scaleX, float scaleY, bool oneLine, bool wrap, float wrapX) { float w = 0; float h = 0; float lineWidth = 0; @@ -593,27 +601,38 @@ static void screen_get_string_size_internal(float* width, float* height, const c h = scaleY * fontGetInfo()->lineFeed; const uint8_t* p = (const uint8_t*) text; - uint32_t code = 0; + const uint8_t* lastAlign = p; + u32 code = 0; ssize_t units = -1; while(*p && (units = decode_utf8(&code, p)) != -1 && code > 0) { p += units; - if(code == '\n') { - if(*p) { - if(lineWidth > w) { - w = lineWidth; - } + if(code == '\n' || (wrap && lineWidth + scaleX * fontGetCharWidthInfo(fontGlyphIndexFromCodePoint(code))->charWidth >= wrapX)) { + lastAlign = p; - lineWidth = 0; - - if(oneLine) { - break; - } - - h += scaleY * fontGetInfo()->lineFeed; + if(lineWidth > w) { + w = lineWidth; } - } else { - lineWidth += scaleX * fontGetCharWidthInfo(fontGlyphIndexFromCodePoint(code))->charWidth; + + lineWidth = 0; + + if(oneLine) { + break; + } + + h += scaleY * fontGetInfo()->lineFeed; + } + + if(code != '\n') { + u32 num = 1; + if(code == '\t') { + code = ' '; + num = 4 - (p - units - lastAlign) % 4; + + lastAlign = p; + } + + lineWidth += (scaleX * fontGetCharWidthInfo(fontGlyphIndexFromCodePoint(code))->charWidth) * num; } } } @@ -628,10 +647,14 @@ static void screen_get_string_size_internal(float* width, float* height, const c } void screen_get_string_size(float* width, float* height, const char* text, float scaleX, float scaleY) { - screen_get_string_size_internal(width, height, text, scaleX, scaleY, false); + screen_get_string_size_internal(width, height, text, scaleX, scaleY, false, false, 0); } -void screen_draw_string(const char* text, float x, float y, float scaleX, float scaleY, u32 colorId, bool baseline) { +void screen_get_string_size_wrap(float* width, float* height, const char* text, float scaleX, float scaleY, float wrapX) { + screen_get_string_size_internal(width, height, text, scaleX, scaleY, false, true, wrapX); +} + +static void screen_draw_string_internal(const char* text, float x, float y, float scaleX, float scaleY, u32 colorId, bool centerLines, bool wrap, float wrapX) { if(text == NULL) { return; } @@ -650,40 +673,60 @@ void screen_draw_string(const char* text, float x, float y, float scaleX, float C3D_TexEnvColor(env, colorConfig[colorId]); float stringWidth; - screen_get_string_size_internal(&stringWidth, NULL, text, scaleX, scaleY, false); + screen_get_string_size_internal(&stringWidth, NULL, text, scaleX, scaleY, false, wrap, wrapX); float lineWidth; - screen_get_string_size_internal(&lineWidth, NULL, text, scaleX, scaleY, true); + screen_get_string_size_internal(&lineWidth, NULL, text, scaleX, scaleY, true, wrap, wrapX); - float currX = x + (stringWidth - lineWidth) / 2; + float currX = x; + if(centerLines) { + currX += (stringWidth - lineWidth) / 2; + } - u32 flags = GLYPH_POS_CALC_VTXCOORD | (baseline ? GLYPH_POS_AT_BASELINE : 0); int lastSheet = -1; const uint8_t* p = (const uint8_t*) text; - uint32_t code = 0; + const uint8_t* lastAlign = p; + u32 code = 0; ssize_t units = -1; while(*p && (units = decode_utf8(&code, p)) != -1 && code > 0) { p += units; - if(code == '\n') { - if(*p) { - screen_get_string_size_internal(&lineWidth, NULL, (const char*) p, scaleX, scaleY, true); - currX = x + (stringWidth - lineWidth) / 2; - y += scaleY * fontGetInfo()->lineFeed; + if(code == '\n' || (wrap && currX + scaleX * fontGetCharWidthInfo(fontGlyphIndexFromCodePoint(code))->charWidth >= wrapX)) { + lastAlign = p; + + screen_get_string_size_internal(&lineWidth, NULL, (const char*) p, scaleX, scaleY, true, wrap, wrapX); + + currX = x; + if(centerLines) { + currX += (stringWidth - lineWidth) / 2; } - } else { + + y += scaleY * fontGetInfo()->lineFeed; + } + + if(code != '\n') { + u32 num = 1; + if(code == '\t') { + code = ' '; + num = 4 - (p - units - lastAlign) % 4; + + lastAlign = p; + } + fontGlyphPos_s data; - fontCalcGlyphPos(&data, fontGlyphIndexFromCodePoint(code), flags, scaleX, scaleY); + fontCalcGlyphPos(&data, fontGlyphIndexFromCodePoint(code), GLYPH_POS_CALC_VTXCOORD, scaleX, scaleY); if(data.sheetIndex != lastSheet) { lastSheet = data.sheetIndex; C3D_TexBind(0, &glyphSheets[lastSheet]); } - screen_draw_quad(currX + data.vtxcoord.left, y + data.vtxcoord.top, currX + data.vtxcoord.right, y + data.vtxcoord.bottom, data.texcoord.left, data.texcoord.top, data.texcoord.right, data.texcoord.bottom); + for(u32 i = 0; i < num; i++) { + screen_draw_quad(currX + data.vtxcoord.left, y + data.vtxcoord.top, currX + data.vtxcoord.right, y + data.vtxcoord.bottom, data.texcoord.left, data.texcoord.top, data.texcoord.right, data.texcoord.bottom); - currX += data.xAdvance; + currX += data.xAdvance; + } } } @@ -697,3 +740,11 @@ void screen_draw_string(const char* text, float x, float y, float scaleX, float C3D_TexEnvOp(env, C3D_Both, 0, 0, 0); C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE); } + +void screen_draw_string(const char* text, float x, float y, float scaleX, float scaleY, u32 colorId, bool centerLines) { + screen_draw_string_internal(text, x, y, scaleX, scaleY, colorId, centerLines, false, 0); +} + +void screen_draw_string_wrap(const char* text, float x, float y, float scaleX, float scaleY, u32 colorId, bool centerLines, float wrapX) { + screen_draw_string_internal(text, x, y, scaleX, scaleY, colorId, centerLines, true, wrapX); +} \ No newline at end of file diff --git a/source/core/screen.h b/source/core/screen.h index 8acea50..37fd94c 100644 --- a/source/core/screen.h +++ b/source/core/screen.h @@ -39,7 +39,12 @@ #define TEXTURE_WIFI_1 28 #define TEXTURE_WIFI_2 29 #define TEXTURE_WIFI_3 30 -#define TEXTURE_AUTO_START 31 +#define TEXTURE_KBD_LAYOUT 31 +#define TEXTURE_KBD_PRESS_OVERLAY 32 +#define TEXTURE_KBD_TEXT_BG 33 +#define TEXTURE_KBD_TEXT_FG 34 + +#define TEXTURE_AUTO_START 33 #define NUM_COLORS 9 @@ -66,7 +71,10 @@ void screen_get_texture_size(u32* width, u32* height, u32 id); void screen_begin_frame(); void screen_end_frame(); void screen_select(gfxScreen_t screen); +void screen_set_scissor(bool enabled, u32 x, u32 y, u32 width, u32 height); void screen_draw_texture(u32 id, float x, float y, float width, float height); void screen_draw_texture_crop(u32 id, float x, float y, float width, float height); void screen_get_string_size(float* width, float* height, const char* text, float scaleX, float scaleY); -void screen_draw_string(const char* text, float x, float y, float scaleX, float scaleY, u32 colorId, bool baseline); \ No newline at end of file +void screen_get_string_size_wrap(float* width, float* height, const char* text, float scaleX, float scaleY, float wrapX); +void screen_draw_string(const char* text, float x, float y, float scaleX, float scaleY, u32 colorId, bool centerLines); +void screen_draw_string_wrap(const char* text, float x, float y, float scaleX, float scaleY, u32 colorId, bool centerLines, float wrapX); \ No newline at end of file diff --git a/source/ui/error.c b/source/ui/error.c index cfb6944..f26e473 100644 --- a/source/ui/error.c +++ b/source/ui/error.c @@ -602,7 +602,7 @@ void error_display(volatile bool* dismissed, void* data, void (*drawTop)(ui_view vsnprintf(errorData->fullText, 4096, text, list); va_end(list); - prompt_display("Error", errorData->fullText, COLOR_TEXT, false, errorData, NULL, error_draw_top, error_onresponse); + prompt_display("Error", errorData->fullText, COLOR_TEXT, false, errorData, error_draw_top, error_onresponse); } void error_display_res(volatile bool* dismissed, void* data, void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2), Result result, const char* text, ...) { @@ -628,7 +628,7 @@ void error_display_res(volatile bool* dismissed, void* data, void (*drawTop)(ui_ int description = R_DESCRIPTION(result); snprintf(errorData->fullText, 4096, "%s\nResult code: 0x%08lX\nLevel: %s (%d)\nSummary: %s (%d)\nModule: %s (%d)\nDesc: %s (%d)", textBuf, result, level_to_string(result), level, summary_to_string(result), summary, module_to_string(result), module, description_to_string(result), description); - prompt_display("Error", errorData->fullText, COLOR_TEXT, false, errorData, NULL, error_draw_top, error_onresponse); + prompt_display("Error", errorData->fullText, COLOR_TEXT, false, errorData, error_draw_top, error_onresponse); } void error_display_errno(volatile bool* dismissed, void* data, void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2), int err, const char* text, ...) { @@ -654,5 +654,5 @@ void error_display_errno(volatile bool* dismissed, void* data, void (*drawTop)(u snprintf(errorData->fullText, 4096, "%s\nI/O Error: %s (%d)", textBuf, strerror(err), err); - prompt_display("Error", errorData->fullText, COLOR_TEXT, false, errorData, NULL, error_draw_top, error_onresponse); + prompt_display("Error", errorData->fullText, COLOR_TEXT, false, errorData, error_draw_top, error_onresponse); } \ No newline at end of file diff --git a/source/ui/info.c b/source/ui/info.c index 843010f..1d6b1f4 100644 --- a/source/ui/info.c +++ b/source/ui/info.c @@ -64,7 +64,7 @@ static void info_draw_bottom(ui_view* view, void* data, float x1, float y1, floa textY = progressBarBgY + progressBarBgHeight + 10; } - screen_draw_string(infoData->text, textX, textY, 0.5f, 0.5f, COLOR_TEXT, false); + screen_draw_string(infoData->text, textX, textY, 0.5f, 0.5f, COLOR_TEXT, true); } void info_display(const char* name, const char* info, bool bar, void* data, void (*update)(ui_view* view, void* data, float* progress, char* text), diff --git a/source/ui/kbd.c b/source/ui/kbd.c new file mode 100644 index 0000000..ce7186f --- /dev/null +++ b/source/ui/kbd.c @@ -0,0 +1,374 @@ +#include +#include +#include + +#include <3ds.h> + +#include "error.h" +#include "ui.h" +#include "../core/screen.h" + +#define MAX_INPUT_SIZE 1024 + +typedef struct { + char input[MAX_INPUT_SIZE]; + size_t inputPos; + + bool shift; + bool capsLock; + + float scrollPos; + u32 lastTouchY; + + bool keyboardTouched; + u64 nextRepeatTime; + + void* data; + void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2); + void (*finished)(void* data, char* input); + void (*canceled)(void* data); +} kbd_data; + +typedef struct { + char normal; + char special; + + void (*press)(ui_view* view, kbd_data* data); + + u32 x; + u32 y; + u32 width; + u32 height; +} LayoutKey; + +static void kbd_backspace(ui_view* view, kbd_data* data) { + if(data->inputPos > 0) { + data->input[--data->inputPos] = '\0'; + } +} + +static void kbd_capslock(ui_view* view, kbd_data* data) { + data->capsLock = !data->capsLock; +} + +static void kbd_shift(ui_view* view, kbd_data* data) { + data->shift = !data->shift; +} + +static void kbd_cancel(ui_view* view, kbd_data* data) { + ui_pop(); + + if(data->canceled != NULL) { + data->canceled(view->data); + } + + free(data); + free(view); +} + +static void kbd_finish(ui_view* view, kbd_data* data) { + ui_pop(); + + if(data->finished != NULL) { + data->finished(view->data, data->input); + } + + free(data); + free(view); +} + +#define NUM_KEYS 56 + +static LayoutKey layout[NUM_KEYS] = { + // Row 1 + {'`', '~', NULL, 1, 1, 21, 21}, + {'1', '!', NULL, 22, 1, 21, 21}, + {'2', '@', NULL, 43, 1, 21, 21}, + {'3', '#', NULL, 64, 1, 21, 21}, + {'4', '$', NULL, 85, 1, 21, 21}, + {'5', '%', NULL, 106, 1, 21, 21}, + {'6', '^', NULL, 127, 1, 21, 21}, + {'7', '&', NULL, 148, 1, 21, 21}, + {'8', '*', NULL, 169, 1, 21, 21}, + {'9', '(', NULL, 190, 1, 21, 21}, + {'0', ')', NULL, 211, 1, 21, 21}, + {'-', '_', NULL, 232, 1, 21, 21}, + {'=', '+', NULL, 253, 1, 21, 21}, + {'\0', '\0', kbd_backspace, 274, 1, 42, 21}, + + // Row 2 + {'\t', '\t', NULL, 1, 22, 31, 21}, + {'q', 'Q', NULL, 32, 22, 21, 21}, + {'w', 'W', NULL, 53, 22, 21, 21}, + {'e', 'E', NULL, 74, 22, 21, 21}, + {'r', 'R', NULL, 95, 22, 21, 21}, + {'t', 'T', NULL, 116, 22, 21, 21}, + {'y', 'Y', NULL, 137, 22, 21, 21}, + {'u', 'U', NULL, 158, 22, 21, 21}, + {'i', 'I', NULL, 179, 22, 21, 21}, + {'o', 'O', NULL, 200, 22, 21, 21}, + {'p', 'P', NULL, 221, 22, 21, 21}, + {'[', '{', NULL, 242, 22, 21, 21}, + {']', '}', NULL, 263, 22, 21, 21}, + {'\\', '|', NULL, 284, 22, 32, 21}, + + // Row 3 + {'\0', '\0', kbd_capslock, 1, 43, 36, 21}, + {'a', 'A', NULL, 37, 43, 21, 21}, + {'s', 'S', NULL, 58, 43, 21, 21}, + {'d', 'D', NULL, 79, 43, 21, 21}, + {'f', 'F', NULL, 100, 43, 21, 21}, + {'g', 'G', NULL, 121, 43, 21, 21}, + {'h', 'H', NULL, 142, 43, 21, 21}, + {'j', 'J', NULL, 163, 43, 21, 21}, + {'k', 'K', NULL, 184, 43, 21, 21}, + {'l', 'L', NULL, 205, 43, 21, 21}, + {';', ':', NULL, 226, 43, 21, 21}, + {'\'', '"', NULL, 247, 43, 21, 21}, + {'\n', '\n', NULL, 268, 43, 48, 21}, + + // Row 4 + {'\0', '\0', kbd_shift, 1, 64, 47, 21}, + {'z', 'Z', NULL, 48, 64, 21, 21}, + {'x', 'X', NULL, 69, 64, 21, 21}, + {'c', 'C', NULL, 90, 64, 21, 21}, + {'v', 'V', NULL, 111, 64, 21, 21}, + {'b', 'B', NULL, 132, 64, 21, 21}, + {'n', 'N', NULL, 153, 64, 21, 21}, + {'m', 'M', NULL, 174, 64, 21, 21}, + {',', '<', NULL, 195, 64, 21, 21}, + {'.', '>', NULL, 216, 64, 21, 21}, + {'/', '?', NULL, 237, 64, 21, 21}, + {'\0', '\0', kbd_shift, 258, 64, 58, 21}, + + // Row 5 + {'\0', '\0', kbd_cancel, 1, 85, 94, 21}, + {' ', ' ', NULL, 95, 85, 127, 21}, + {'\0', '\0', kbd_finish, 222, 85, 94, 21}, +}; + +static void kbd_update(ui_view* view, void* data, float bx1, float by1, float bx2, float by2) { + kbd_data* kbdData = (kbd_data*) data; + + if(hidKeysDown() & KEY_A) { + kbd_finish(view, kbdData); + return; + } + + if(hidKeysDown() & KEY_B) { + kbd_cancel(view, kbdData); + return; + } + + u32 kbdTextWidth = 0; + u32 kbdTextHeight = 0; + screen_get_texture_size(&kbdTextWidth, &kbdTextHeight, TEXTURE_KBD_TEXT_BG); + + float kbdTextX = bx1 + (bx2 - bx1 - kbdTextWidth) / 2; + + float inputHeight = 0; + screen_get_string_size_wrap(NULL, &inputHeight, kbdData->input, 0.5f, 0.5f, kbdTextX + kbdTextWidth); + + if(hidKeysHeld() & KEY_TOUCH) { + touchPosition pos; + hidTouchRead(&pos); + + u32 kbdWidth = 0; + u32 kbdHeight = 0; + screen_get_texture_size(&kbdWidth, &kbdHeight, TEXTURE_KBD_LAYOUT); + + float kbdX = bx1 + (bx2 - bx1 - kbdWidth) / 2; + float kbdY = by2 - kbdHeight - 2; + + if(pos.px >= kbdX && pos.py >= kbdY && pos.px < kbdX + kbdWidth && pos.py < kbdY + kbdHeight) { + if((hidKeysDown() & KEY_TOUCH) || (kbdData->keyboardTouched && osGetTime() >= kbdData->nextRepeatTime)) { + kbdData->keyboardTouched = true; + kbdData->nextRepeatTime = osGetTime() + ((hidKeysDown() & KEY_TOUCH) ? 500 : 100); + + for(u32 i = 0; i < NUM_KEYS; i++) { + LayoutKey key = layout[i]; + if(pos.px >= kbdX + key.x && pos.py >= kbdY + key.y && pos.px < kbdX + key.x + key.width && pos.py < kbdY + key.y + key.height) { + if(key.press != NULL) { + key.press(view, kbdData); + } else if(kbdData->inputPos < MAX_INPUT_SIZE) { + kbdData->input[kbdData->inputPos++] = (kbdData->shift || kbdData->capsLock) ? key.special : key.normal; + + if(key.normal != key.special) { + kbdData->shift = false; + } + + screen_get_string_size_wrap(NULL, &inputHeight, kbdData->input, 0.5f, 0.5f, kbdTextX + kbdTextWidth); + + if(inputHeight > kbdTextHeight && kbdData->scrollPos < inputHeight - kbdTextHeight) { + kbdData->scrollPos = inputHeight - kbdTextHeight; + } + } + + break; + } + } + } + } else { + kbdData->keyboardTouched = false; + } + + if(!(hidKeysDown() & KEY_TOUCH)) { + float kbdTextX = bx1 + (bx2 - bx1 - kbdTextWidth) / 2; + float kbdTextY = by1 + 2; + + if(pos.px >= kbdTextX && pos.py >= kbdTextY && pos.px < kbdTextX + kbdTextWidth && pos.py < kbdTextY + kbdTextHeight) { + kbdData->scrollPos += -((int) pos.py - (int) kbdData->lastTouchY); + } + } + + kbdData->lastTouchY = pos.py; + } else { + kbdData->keyboardTouched = false; + } + + if(kbdData->scrollPos > inputHeight - kbdTextHeight) { + kbdData->scrollPos = inputHeight - kbdTextHeight; + } + + if(kbdData->scrollPos < 0) { + kbdData->scrollPos = 0; + } +} + +static void kbd_draw_top(ui_view* view, void* data, float x1, float y1, float x2, float y2) { + kbd_data* kbdData = (kbd_data*) data; + + if(kbdData->drawTop != NULL) { + kbdData->drawTop(view, kbdData->data, x1, y1, x2, y2); + } +} + +static void kbd_draw_bottom(ui_view* view, void* data, float x1, float y1, float x2, float y2) { + kbd_data* kbdData = (kbd_data*) data; + + touchPosition pos; + hidTouchRead(&pos); + + u32 kbdTextWidth = 0; + u32 kbdTextHeight = 0; + screen_get_texture_size(&kbdTextWidth, &kbdTextHeight, TEXTURE_KBD_TEXT_BG); + + float kbdTextX = x1 + (x2 - x1 - kbdTextWidth) / 2; + float kbdTextY = y1 + 2; + screen_draw_texture(TEXTURE_KBD_TEXT_BG, kbdTextX, kbdTextY, kbdTextWidth, kbdTextHeight); + + screen_set_scissor(true, (u32) (kbdTextX + 1), (u32) (kbdTextY + 1), kbdTextWidth - 1, kbdTextHeight - 1); + screen_draw_string_wrap(kbdData->input, kbdTextX + 1, kbdTextY + 1 - kbdData->scrollPos, 0.5f, 0.5f, COLOR_TEXT, false, kbdTextX + kbdTextWidth); + screen_set_scissor(false, 0, 0, 0, 0); + + u32 kbdTextFgWidth = 0; + u32 kbdTextFgHeight = 0; + screen_get_texture_size(&kbdTextFgWidth, &kbdTextFgHeight, TEXTURE_KBD_TEXT_FG); + + float kbdTextFgX = kbdTextX + (((int) kbdTextWidth - (int) kbdTextFgWidth) / 2); + float kbdTextFgY = kbdTextY + (((int) kbdTextHeight - (int) kbdTextFgHeight) / 2); + screen_draw_texture(TEXTURE_KBD_TEXT_FG, kbdTextFgX, kbdTextFgY, kbdTextFgWidth, kbdTextFgHeight); + + float inputHeight = 0; + screen_get_string_size_wrap(NULL, &inputHeight, kbdData->input, 0.5f, 0.5f, kbdTextX + kbdTextWidth); + + if(inputHeight > kbdTextHeight) { + u32 scrollBarWidth = 0; + screen_get_texture_size(&scrollBarWidth, NULL, TEXTURE_SCROLL_BAR); + + float scrollBarHeight = (kbdTextHeight / inputHeight) * kbdTextHeight; + + float scrollBarX = kbdTextX + kbdTextWidth - scrollBarWidth; + float scrollBarY = kbdTextY + (kbdData->scrollPos / inputHeight) * kbdTextHeight; + + screen_draw_texture(TEXTURE_SCROLL_BAR, scrollBarX, scrollBarY, scrollBarWidth, scrollBarHeight); + } + + u32 kbdWidth = 0; + u32 kbdHeight = 0; + screen_get_texture_size(&kbdWidth, &kbdHeight, TEXTURE_KBD_LAYOUT); + + float kbdX = x1 + (x2 - x1 - kbdWidth) / 2; + float kbdY = y2 - kbdHeight - 2; + screen_draw_texture(TEXTURE_KBD_LAYOUT, kbdX, kbdY, kbdWidth, kbdHeight); + + for(u32 i = 0; i < NUM_KEYS; i++) { + LayoutKey key = layout[i]; + + char text[16]; + if(key.press == kbd_backspace) { + snprintf(text, sizeof(text), "Del"); + } else if(key.press == kbd_capslock) { + snprintf(text, sizeof(text), "Caps"); + } else if(key.press == kbd_shift) { + snprintf(text, sizeof(text), "Shift"); + } else if(key.press == kbd_cancel) { + snprintf(text, sizeof(text), "Cancel (B)"); + } else if(key.press == kbd_finish) { + snprintf(text, sizeof(text), "Finish (A)"); + } else if(key.normal == '\t') { + snprintf(text, sizeof(text), "Tab"); + } else if(key.normal == '\n') { + snprintf(text, sizeof(text), "Enter"); + } else if(key.normal == ' ') { + snprintf(text, sizeof(text), "Space"); + } else { + snprintf(text, sizeof(text), "%c", (kbdData->shift || kbdData->capsLock) ? key.special : key.normal); + } + + float textWidth = 0; + float textHeight = 0; + screen_get_string_size(&textWidth, &textHeight, text, 0.5f, 0.5f); + + float textX = kbdX + key.x + (key.width - textWidth) / 2; + float textY = kbdY + key.y + (key.height - textHeight) / 2; + screen_draw_string(text, textX, textY, 0.5f, 0.5f, COLOR_TEXT, true); + + if((key.press == kbd_capslock && kbdData->capsLock) + || (key.press == kbd_shift && kbdData->shift) + || ((hidKeysHeld() & KEY_TOUCH) && pos.px >= kbdX + key.x && pos.py >= kbdY + key.y && pos.px < kbdX + key.x + key.width && pos.py < kbdY + key.y + key.height)) { + screen_draw_texture(TEXTURE_KBD_PRESS_OVERLAY, kbdX + key.x, kbdY + key.y, key.width, key.height); + } + } +} + +void kbd_display(const char* name, void* data, void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2), + void (*finished)(void* data, char* input), + void (*canceled)(void* data)) { + kbd_data* kbdData = (kbd_data*) calloc(1, sizeof(kbd_data)); + if(kbdData == NULL) { + error_display(NULL, NULL, NULL, "Failed to allocate info data."); + return; + } + + memset(kbdData->input, '\0', MAX_INPUT_SIZE); + kbdData->inputPos = 0; + + kbdData->shift = false; + kbdData->capsLock = false; + + kbdData->scrollPos = 0; + kbdData->lastTouchY = 0; + + kbdData->keyboardTouched = false; + kbdData->nextRepeatTime = 0; + + kbdData->data = data; + kbdData->drawTop = drawTop; + kbdData->finished = finished; + kbdData->canceled = canceled; + + ui_view* view = (ui_view*) calloc(1, sizeof(ui_view)); + if(view == NULL) { + error_display(NULL, NULL, NULL, "Failed to allocate UI view."); + return; + } + + view->name = name; + view->info = ""; + view->data = kbdData; + view->update = kbd_update; + view->drawTop = kbd_draw_top; + view->drawBottom = kbd_draw_bottom; + ui_push(view); +} \ No newline at end of file diff --git a/source/ui/kbd.h b/source/ui/kbd.h new file mode 100644 index 0000000..bd48dd4 --- /dev/null +++ b/source/ui/kbd.h @@ -0,0 +1,7 @@ +#pragma once + +typedef struct ui_view_s ui_view; + +void kbd_display(const char* name, void* data, void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2), + void (*finished)(void* data, char* input), + void (*canceled)(void* data)); \ No newline at end of file diff --git a/source/ui/list.c b/source/ui/list.c index 5aea00e..bc89d48 100644 --- a/source/ui/list.c +++ b/source/ui/list.c @@ -229,7 +229,7 @@ static void list_draw_bottom(ui_view* view, void* data, float x1, float y1, floa x -= listData->selectionScroll; } - screen_draw_string(item->name, x, y, 0.5f, 0.5f, item->color, false); + screen_draw_string(item->name, x, y, 0.5f, 0.5f, item->color, true); if(i == listData->selectedIndex) { u32 selectionOverlayWidth = 0; diff --git a/source/ui/prompt.c b/source/ui/prompt.c index 0a0eba7..c4452fa 100644 --- a/source/ui/prompt.c +++ b/source/ui/prompt.c @@ -9,10 +9,9 @@ typedef struct { const char* text; - u32 rgba; + u32 color; bool option; void* data; - void (*update)(ui_view* view, void* data); void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2); void (*onResponse)(ui_view* view, void* data, bool response); } prompt_data; @@ -76,10 +75,6 @@ static void prompt_update(ui_view* view, void* data, float bx1, float by1, float } } } - - if(promptData->update != NULL) { - promptData->update(view, promptData->data); - } } static void prompt_draw_top(ui_view* view, void* data, float x1, float y1, float x2, float y2) { @@ -112,12 +107,12 @@ static void prompt_draw_bottom(ui_view* view, void* data, float x1, float y1, fl float yesWidth; float yesHeight; screen_get_string_size(&yesWidth, &yesHeight, yes, 0.5f, 0.5f); - screen_draw_string(yes, yesButtonX + (buttonWidth - yesWidth) / 2, yesButtonY + (buttonHeight - yesHeight) / 2, 0.5f, 0.5f, promptData->rgba, false); + screen_draw_string(yes, yesButtonX + (buttonWidth - yesWidth) / 2, yesButtonY + (buttonHeight - yesHeight) / 2, 0.5f, 0.5f, promptData->color, true); float noWidth; float noHeight; screen_get_string_size(&noWidth, &noHeight, no, 0.5f, 0.5f); - screen_draw_string(no, noButtonX + (buttonWidth - noWidth) / 2, noButtonY + (buttonHeight - noHeight) / 2, 0.5f, 0.5f, promptData->rgba, false); + screen_draw_string(no, noButtonX + (buttonWidth - noWidth) / 2, noButtonY + (buttonHeight - noHeight) / 2, 0.5f, 0.5f, promptData->color, true); } else { screen_get_texture_size(&buttonWidth, &buttonHeight, TEXTURE_BUTTON_LARGE); @@ -130,18 +125,17 @@ static void prompt_draw_bottom(ui_view* view, void* data, float x1, float y1, fl float okayWidth; float okayHeight; screen_get_string_size(&okayWidth, &okayHeight, okay, 0.5f, 0.5f); - screen_draw_string(okay, okayButtonX + (buttonWidth - okayWidth) / 2, okayButtonY + (buttonHeight - okayHeight) / 2, 0.5f, 0.5f, promptData->rgba, false); + screen_draw_string(okay, okayButtonX + (buttonWidth - okayWidth) / 2, okayButtonY + (buttonHeight - okayHeight) / 2, 0.5f, 0.5f, promptData->color, true); } float textWidth; float textHeight; screen_get_string_size(&textWidth, &textHeight, promptData->text, 0.5f, 0.5f); - screen_draw_string(promptData->text, x1 + (x2 - x1 - textWidth) / 2, y1 + (y2 - 5 - buttonHeight - y1 - textHeight) / 2, 0.5f, 0.5f, promptData->rgba, false); + screen_draw_string(promptData->text, x1 + (x2 - x1 - textWidth) / 2, y1 + (y2 - 5 - buttonHeight - y1 - textHeight) / 2, 0.5f, 0.5f, promptData->color, true); } -void prompt_display(const char* name, const char* text, u32 rgba, bool option, void* data, void (*update)(ui_view* view, void* data), - void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2), - void (*onResponse)(ui_view* view, void* data, bool response)) { +void prompt_display(const char* name, const char* text, u32 color, bool option, void* data, void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2), + void (*onResponse)(ui_view* view, void* data, bool response)) { prompt_data* promptData = (prompt_data*) calloc(1, sizeof(prompt_data)); if(promptData == NULL) { error_display(NULL, NULL, NULL, "Failed to allocate prompt data."); @@ -150,10 +144,9 @@ void prompt_display(const char* name, const char* text, u32 rgba, bool option, v } promptData->text = text; - promptData->rgba = rgba; + promptData->color = color; promptData->option = option; promptData->data = data; - promptData->update = update; promptData->drawTop = drawTop; promptData->onResponse = onResponse; diff --git a/source/ui/prompt.h b/source/ui/prompt.h index 7e4e971..3951540 100644 --- a/source/ui/prompt.h +++ b/source/ui/prompt.h @@ -2,6 +2,5 @@ typedef struct ui_view_s ui_view; -void prompt_display(const char* name, const char* text, u32 rgba, bool option, void* data, void (*update)(ui_view* view, void* data), - void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2), - void (*onResponse)(ui_view* view, void* data, bool response)); \ No newline at end of file +void prompt_display(const char* name, const char* text, u32 color, bool option, void* data, void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2), + void (*onResponse)(ui_view* view, void* data, bool response)); \ No newline at end of file diff --git a/source/ui/section/action/deletecontents.c b/source/ui/section/action/deletecontents.c index 1593d80..3bd1ecb 100644 --- a/source/ui/section/action/deletecontents.c +++ b/source/ui/section/action/deletecontents.c @@ -92,7 +92,7 @@ static bool action_delete_contents_error(void* data, u32 index, Result res) { delete_contents_data* deleteData = (delete_contents_data*) data; if(res == R_FBI_CANCELLED) { - prompt_display("Failure", "Delete cancelled.", COLOR_TEXT, false, NULL, NULL, NULL, NULL); + prompt_display("Failure", "Delete cancelled.", COLOR_TEXT, false, NULL, NULL, NULL); return false; } else { volatile bool dismissed = false; @@ -122,7 +122,7 @@ static void action_delete_contents_update(ui_view* view, void* data, float* prog info_destroy(view); if(R_SUCCEEDED(deleteData->deleteInfo.result)) { - prompt_display("Success", "Deleted.", COLOR_TEXT, false, NULL, NULL, NULL, NULL); + prompt_display("Success", "Deleted.", COLOR_TEXT, false, NULL, NULL, NULL); } action_delete_contents_free_data(deleteData); @@ -211,7 +211,7 @@ static void action_delete_contents_internal(linked_list* items, list_item* selec data->deleteInfo.total = linked_list_size(&data->contents); data->deleteInfo.processed = data->deleteInfo.total; - prompt_display("Confirmation", message, COLOR_TEXT, true, data, NULL, action_delete_contents_draw_top, action_delete_contents_onresponse); + prompt_display("Confirmation", message, COLOR_TEXT, true, data, action_delete_contents_draw_top, action_delete_contents_onresponse); } void action_delete_file(linked_list* items, list_item* selected) { diff --git a/source/ui/section/action/deleteextsavedata.c b/source/ui/section/action/deleteextsavedata.c index 0397f24..9d78391 100644 --- a/source/ui/section/action/deleteextsavedata.c +++ b/source/ui/section/action/deleteextsavedata.c @@ -37,7 +37,7 @@ static void action_delete_ext_save_data_update(ui_view* view, void* data, float* linked_list_remove(deleteData->items, deleteData->selected); task_free_ext_save_data(deleteData->selected); - prompt_display("Success", "Ext save data deleted.", COLOR_TEXT, false, NULL, NULL, NULL, NULL); + prompt_display("Success", "Ext save data deleted.", COLOR_TEXT, false, NULL, NULL, NULL); } free(data); @@ -62,5 +62,5 @@ void action_delete_ext_save_data(linked_list* items, list_item* selected) { data->items = items; data->selected = selected; - prompt_display("Confirmation", "Delete the selected ext save data?", COLOR_TEXT, true, data, NULL, action_delete_ext_save_data_draw_top, action_delete_ext_save_data_onresponse); + prompt_display("Confirmation", "Delete the selected ext save data?", COLOR_TEXT, true, data, action_delete_ext_save_data_draw_top, action_delete_ext_save_data_onresponse); } \ No newline at end of file diff --git a/source/ui/section/action/deletependingtitles.c b/source/ui/section/action/deletependingtitles.c index 43db2c5..37b7d81 100644 --- a/source/ui/section/action/deletependingtitles.c +++ b/source/ui/section/action/deletependingtitles.c @@ -69,7 +69,7 @@ static bool action_delete_pending_titles_error(void* data, u32 index, Result res delete_pending_titles_data* deleteData = (delete_pending_titles_data*) data; if(res == R_FBI_CANCELLED) { - prompt_display("Failure", "Delete cancelled.", COLOR_TEXT, false, NULL, NULL, NULL, NULL); + prompt_display("Failure", "Delete cancelled.", COLOR_TEXT, false, NULL, NULL, NULL); return false; } else { volatile bool dismissed = false; @@ -97,7 +97,7 @@ static void action_delete_pending_titles_update(ui_view* view, void* data, float info_destroy(view); if(R_SUCCEEDED(deleteData->deleteInfo.result)) { - prompt_display("Success", "Pending title(s) deleted.", COLOR_TEXT, false, NULL, NULL, NULL, NULL); + prompt_display("Success", "Pending title(s) deleted.", COLOR_TEXT, false, NULL, NULL, NULL); } action_delete_pending_titles_free_data(deleteData); @@ -185,7 +185,7 @@ void action_delete_pending_titles(linked_list* items, list_item* selected, const data->deleteInfo.total = linked_list_size(&data->contents); data->deleteInfo.processed = data->deleteInfo.total; - prompt_display("Confirmation", message, COLOR_TEXT, true, data, NULL, !all ? action_delete_pending_titles_draw_top : NULL, action_delete_pending_titles_onresponse); + prompt_display("Confirmation", message, COLOR_TEXT, true, data, !all ? action_delete_pending_titles_draw_top : NULL, action_delete_pending_titles_onresponse); } void action_delete_pending_title(linked_list* items, list_item* selected) { diff --git a/source/ui/section/action/deletesecurevalue.c b/source/ui/section/action/deletesecurevalue.c index 2843e8f..66bf00e 100644 --- a/source/ui/section/action/deletesecurevalue.c +++ b/source/ui/section/action/deletesecurevalue.c @@ -25,7 +25,7 @@ static void action_delete_secure_value_update(ui_view* view, void* data, float* if(R_FAILED(res)) { error_display_res(NULL, info, ui_draw_title_info, res, "Failed to delete secure value."); } else { - prompt_display("Success", "Secure value deleted.", COLOR_TEXT, false, info, NULL, ui_draw_title_info, NULL); + prompt_display("Success", "Secure value deleted.", COLOR_TEXT, false, info, ui_draw_title_info, NULL); } } @@ -36,5 +36,5 @@ static void action_delete_secure_value_onresponse(ui_view* view, void* data, boo } void action_delete_secure_value(linked_list* items, list_item* selected) { - prompt_display("Confirmation", "Delete the secure value of the selected title?", COLOR_TEXT, true, selected->data, NULL, ui_draw_title_info, action_delete_secure_value_onresponse); + prompt_display("Confirmation", "Delete the secure value of the selected title?", COLOR_TEXT, true, selected->data, ui_draw_title_info, action_delete_secure_value_onresponse); } \ No newline at end of file diff --git a/source/ui/section/action/deletesystemsavedata.c b/source/ui/section/action/deletesystemsavedata.c index 8309ff3..3938fc2 100644 --- a/source/ui/section/action/deletesystemsavedata.c +++ b/source/ui/section/action/deletesystemsavedata.c @@ -38,7 +38,7 @@ static void action_delete_system_save_data_update(ui_view* view, void* data, flo 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, NULL); + prompt_display("Success", "System save data deleted.", COLOR_TEXT, false, NULL, NULL, NULL); } free(data); @@ -63,5 +63,5 @@ void action_delete_system_save_data(linked_list* items, list_item* selected) { data->items = items; data->selected = selected; - prompt_display("Confirmation", "Delete the selected system save data?", COLOR_TEXT, true, data, NULL, action_delete_system_save_data_draw_top, action_delete_system_save_data_onresponse); + 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); } \ No newline at end of file diff --git a/source/ui/section/action/deleteticket.c b/source/ui/section/action/deleteticket.c index d235694..61773ec 100644 --- a/source/ui/section/action/deleteticket.c +++ b/source/ui/section/action/deleteticket.c @@ -37,7 +37,7 @@ static void action_delete_ticket_update(ui_view* view, void* data, float* progre linked_list_remove(deleteData->items, deleteData->selected); task_free_ticket(deleteData->selected); - prompt_display("Success", "Ticket deleted.", COLOR_TEXT, false, NULL, NULL, NULL, NULL); + prompt_display("Success", "Ticket deleted.", COLOR_TEXT, false, NULL, NULL, NULL); } free(data); @@ -62,5 +62,5 @@ void action_delete_ticket(linked_list* items, list_item* selected) { data->items = items; data->selected = selected; - prompt_display("Confirmation", "Delete the selected ticket?", COLOR_TEXT, true, data, NULL, action_delete_ticket_draw_top, action_delete_ticket_onresponse); + prompt_display("Confirmation", "Delete the selected ticket?", COLOR_TEXT, true, data, action_delete_ticket_draw_top, action_delete_ticket_onresponse); } \ No newline at end of file diff --git a/source/ui/section/action/deletetitle.c b/source/ui/section/action/deletetitle.c index 6f6bdf7..5e9149b 100644 --- a/source/ui/section/action/deletetitle.c +++ b/source/ui/section/action/deletetitle.c @@ -37,7 +37,7 @@ static void action_delete_title_update(ui_view* view, void* data, float* progres linked_list_remove(deleteData->items, deleteData->selected); task_free_title(deleteData->selected); - prompt_display("Success", "Title deleted.", COLOR_TEXT, false, NULL, NULL, NULL, NULL); + prompt_display("Success", "Title deleted.", COLOR_TEXT, false, NULL, NULL, NULL); } free(data); @@ -62,5 +62,5 @@ void action_delete_title(linked_list* items, list_item* selected) { data->items = items; data->selected = selected; - prompt_display("Confirmation", "Delete the selected title?", COLOR_TEXT, true, data, NULL, action_delete_title_draw_top, action_delete_title_onresponse); + prompt_display("Confirmation", "Delete the selected title?", COLOR_TEXT, true, data, action_delete_title_draw_top, action_delete_title_onresponse); } \ No newline at end of file diff --git a/source/ui/section/action/exportsecurevalue.c b/source/ui/section/action/exportsecurevalue.c index 2f003ca..7550f22 100644 --- a/source/ui/section/action/exportsecurevalue.c +++ b/source/ui/section/action/exportsecurevalue.c @@ -25,7 +25,7 @@ static void action_export_secure_value_update(ui_view* view, void* data, float* ui_pop(); info_destroy(view); - prompt_display("Failure", "Secure value not set.", COLOR_TEXT, false, info, NULL, ui_draw_title_info, NULL); + prompt_display("Failure", "Secure value not set.", COLOR_TEXT, false, info, ui_draw_title_info, NULL); return; } @@ -59,7 +59,7 @@ static void action_export_secure_value_update(ui_view* view, void* data, float* info_destroy(view); if(R_SUCCEEDED(res)) { - prompt_display("Success", "Secure value exported.", COLOR_TEXT, false, info, NULL, ui_draw_title_info, NULL); + prompt_display("Success", "Secure value exported.", COLOR_TEXT, false, info, ui_draw_title_info, NULL); } else { error_display_res(NULL, info, ui_draw_title_info, res, "Failed to export secure value."); } @@ -72,5 +72,5 @@ static void action_export_secure_value_onresponse(ui_view* view, void* data, boo } void action_export_secure_value(linked_list* items, list_item* selected) { - prompt_display("Confirmation", "Export the secure value of the selected title?", COLOR_TEXT, true, selected->data, NULL, ui_draw_title_info, action_export_secure_value_onresponse); + prompt_display("Confirmation", "Export the secure value of the selected title?", COLOR_TEXT, true, selected->data, ui_draw_title_info, action_export_secure_value_onresponse); } \ No newline at end of file diff --git a/source/ui/section/action/extractsmdh.c b/source/ui/section/action/extractsmdh.c index 7046419..eeea5f1 100644 --- a/source/ui/section/action/extractsmdh.c +++ b/source/ui/section/action/extractsmdh.c @@ -65,7 +65,7 @@ static void action_extract_smdh_update(ui_view* view, void* data, float* progres info_destroy(view); if(R_SUCCEEDED(res)) { - prompt_display("Success", "SMDH extracted.", COLOR_TEXT, false, info, NULL, ui_draw_title_info, NULL); + prompt_display("Success", "SMDH extracted.", COLOR_TEXT, false, info, ui_draw_title_info, NULL); } else { error_display_res(NULL, info, ui_draw_title_info, res, "Failed to extract SMDH."); } @@ -78,5 +78,5 @@ static void action_extract_smdh_onresponse(ui_view* view, void* data, bool respo } void action_extract_smdh(linked_list* items, list_item* selected) { - prompt_display("Confirmation", "Extract the SMDH of the selected title?", COLOR_TEXT, true, selected->data, NULL, ui_draw_title_info, action_extract_smdh_onresponse); + prompt_display("Confirmation", "Extract the SMDH of the selected title?", COLOR_TEXT, true, selected->data, ui_draw_title_info, action_extract_smdh_onresponse); } \ No newline at end of file diff --git a/source/ui/section/action/importsecurevalue.c b/source/ui/section/action/importsecurevalue.c index 78a19ba..22c129b 100644 --- a/source/ui/section/action/importsecurevalue.c +++ b/source/ui/section/action/importsecurevalue.c @@ -43,7 +43,7 @@ static void action_import_secure_value_update(ui_view* view, void* data, float* info_destroy(view); if(R_SUCCEEDED(res)) { - prompt_display("Success", "Secure value imported.", COLOR_TEXT, false, info, NULL, ui_draw_title_info, NULL); + prompt_display("Success", "Secure value imported.", COLOR_TEXT, false, info, ui_draw_title_info, NULL); } else { error_display_res(NULL, info, ui_draw_title_info, res, "Failed to import secure value."); } @@ -56,5 +56,5 @@ static void action_import_secure_value_onresponse(ui_view* view, void* data, boo } void action_import_secure_value(linked_list* items, list_item* selected) { - prompt_display("Confirmation", "Import the secure value of the selected title?", COLOR_TEXT, true, selected->data, NULL, ui_draw_title_info, action_import_secure_value_onresponse); + prompt_display("Confirmation", "Import the secure value of the selected title?", COLOR_TEXT, true, selected->data, ui_draw_title_info, action_import_secure_value_onresponse); } \ No newline at end of file diff --git a/source/ui/section/action/importseed.c b/source/ui/section/action/importseed.c index 6b996c5..9b6e888 100644 --- a/source/ui/section/action/importseed.c +++ b/source/ui/section/action/importseed.c @@ -22,7 +22,7 @@ static void action_import_seed_update(ui_view* view, void* data, float* progress info_destroy(view); if(R_SUCCEEDED(res)) { - prompt_display("Success", "Seed imported.", COLOR_TEXT, false, info, NULL, ui_draw_title_info, NULL); + prompt_display("Success", "Seed imported.", COLOR_TEXT, false, info, ui_draw_title_info, NULL); } else { error_display_res(NULL, info, ui_draw_title_info, res, "Failed to import seed."); } @@ -35,5 +35,5 @@ static void action_import_seed_onresponse(ui_view* view, void* data, bool respon } void action_import_seed(linked_list* items, list_item* selected) { - prompt_display("Confirmation", "Import the seed of the selected title?", COLOR_TEXT, true, selected->data, NULL, ui_draw_title_info, action_import_seed_onresponse); + prompt_display("Confirmation", "Import the seed of the selected title?", COLOR_TEXT, true, selected->data, ui_draw_title_info, action_import_seed_onresponse); } \ No newline at end of file diff --git a/source/ui/section/action/installcdn.c b/source/ui/section/action/installcdn.c index 83e74f6..deeaad2 100644 --- a/source/ui/section/action/installcdn.c +++ b/source/ui/section/action/installcdn.c @@ -183,7 +183,7 @@ 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); + prompt_display("Failure", "Install cancelled.", COLOR_TEXT, false, installData->ticket, 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 { @@ -227,7 +227,7 @@ static void action_install_cdn_update(ui_view* view, void* data, float* progress 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); + prompt_display("Success", "Install finished.", COLOR_TEXT, false, installData->ticket, ui_draw_ticket_info, NULL); } } else { AM_InstallTitleAbort(); @@ -332,5 +332,5 @@ static void action_install_cdn_onresponse(ui_view* view, void* data, bool respon } void action_install_cdn(linked_list* items, list_item* selected) { - prompt_display("Confirmation", "Install the selected title from the CDN?", COLOR_TEXT, true, selected->data, NULL, ui_draw_ticket_info, action_install_cdn_onresponse); + prompt_display("Confirmation", "Install the selected title from the CDN?", COLOR_TEXT, true, selected->data, ui_draw_ticket_info, action_install_cdn_onresponse); } \ No newline at end of file diff --git a/source/ui/section/action/installcias.c b/source/ui/section/action/installcias.c index 20f76a3..6f7d9ad 100644 --- a/source/ui/section/action/installcias.c +++ b/source/ui/section/action/installcias.c @@ -191,7 +191,7 @@ bool action_install_cias_error(void* data, u32 index, Result res) { install_cias_data* installData = (install_cias_data*) data; if(res == R_FBI_CANCELLED) { - prompt_display("Failure", "Install cancelled.", COLOR_TEXT, false, NULL, NULL, NULL, NULL); + prompt_display("Failure", "Install cancelled.", COLOR_TEXT, false, NULL, NULL, NULL); return false; } else { volatile bool dismissed = false; @@ -223,7 +223,7 @@ static void action_install_cias_update(ui_view* view, void* data, float* progres info_destroy(view); if(R_SUCCEEDED(installData->installInfo.result)) { - prompt_display("Success", "Install finished.", COLOR_TEXT, false, NULL, NULL, NULL, NULL); + prompt_display("Success", "Install finished.", COLOR_TEXT, false, NULL, NULL, NULL); } action_install_cias_free_data(installData); @@ -331,7 +331,7 @@ static void action_install_cias_internal(linked_list* items, list_item* selected data->installInfo.total = linked_list_size(&data->contents); data->installInfo.processed = data->installInfo.total; - prompt_display("Confirmation", message, COLOR_TEXT, true, data, NULL, action_install_cias_draw_top, action_install_cias_onresponse); + prompt_display("Confirmation", message, COLOR_TEXT, true, data, action_install_cias_draw_top, action_install_cias_onresponse); } void action_install_cia(linked_list* items, list_item* selected) { diff --git a/source/ui/section/action/installtickets.c b/source/ui/section/action/installtickets.c index b5ddf14..c261275 100644 --- a/source/ui/section/action/installtickets.c +++ b/source/ui/section/action/installtickets.c @@ -164,7 +164,7 @@ 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, NULL, NULL, NULL, NULL); + prompt_display("Failure", "Install cancelled.", COLOR_TEXT, false, NULL, NULL, NULL); return false; } else { volatile bool dismissed = false; @@ -196,7 +196,7 @@ static void action_install_tickets_update(ui_view* view, void* data, float* prog info_destroy(view); if(R_SUCCEEDED(installData->installInfo.result)) { - prompt_display("Success", "Install finished.", COLOR_TEXT, false, NULL, NULL, NULL, NULL); + prompt_display("Success", "Install finished.", COLOR_TEXT, false, NULL, NULL, NULL); } action_install_tickets_free_data(installData); @@ -229,7 +229,7 @@ static void action_install_tickets_cdn_check_onresponse(ui_view* view, void* dat static void action_install_tickets_onresponse(ui_view* view, void* data, bool response) { if(response) { - prompt_display("Optional", "Install ticket titles from CDN?", COLOR_TEXT, true, data, NULL, action_install_tickets_draw_top, action_install_tickets_cdn_check_onresponse); + prompt_display("Optional", "Install ticket titles from CDN?", COLOR_TEXT, true, data, action_install_tickets_draw_top, action_install_tickets_cdn_check_onresponse); } else { action_install_tickets_free_data((install_tickets_data*) data); } @@ -308,7 +308,7 @@ static void action_install_tickets_internal(linked_list* items, list_item* selec data->installInfo.total = linked_list_size(&data->contents); data->installInfo.processed = data->installInfo.total; - prompt_display("Confirmation", message, COLOR_TEXT, true, data, NULL, action_install_tickets_draw_top, action_install_tickets_onresponse); + prompt_display("Confirmation", message, COLOR_TEXT, true, data, action_install_tickets_draw_top, action_install_tickets_onresponse); } void action_install_ticket(linked_list* items, list_item* selected) { diff --git a/source/ui/section/action/launchtitle.c b/source/ui/section/action/launchtitle.c index ba6b6bf..35919c9 100644 --- a/source/ui/section/action/launchtitle.c +++ b/source/ui/section/action/launchtitle.c @@ -40,5 +40,5 @@ static void action_launch_title_onresponse(ui_view* view, void* data, bool respo } void action_launch_title(linked_list* items, list_item* selected) { - prompt_display("Confirmation", "Launch the selected title?", COLOR_TEXT, true, selected->data, NULL, ui_draw_title_info, action_launch_title_onresponse); + prompt_display("Confirmation", "Launch the selected title?", COLOR_TEXT, true, selected->data, ui_draw_title_info, action_launch_title_onresponse); } \ No newline at end of file diff --git a/source/ui/section/action/pastefiles.c b/source/ui/section/action/pastefiles.c index 6f6a7e7..73d24e6 100644 --- a/source/ui/section/action/pastefiles.c +++ b/source/ui/section/action/pastefiles.c @@ -195,7 +195,7 @@ 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, NULL); + prompt_display("Failure", "Paste cancelled.", COLOR_TEXT, false, NULL, NULL, NULL); return false; } else { volatile bool dismissed = false; @@ -243,7 +243,7 @@ static void action_paste_files_update(ui_view* view, void* data, float* progress info_destroy(view); if(R_SUCCEEDED(pasteData->pasteInfo.result)) { - prompt_display("Success", "Contents pasted.", COLOR_TEXT, false, NULL, NULL, NULL, NULL); + prompt_display("Success", "Contents pasted.", COLOR_TEXT, false, NULL, NULL, NULL); } action_paste_files_free_data(pasteData); @@ -277,7 +277,7 @@ static void action_paste_files_onresponse(ui_view* view, void* data, bool respon 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, NULL); + prompt_display("Failure", "Clipboard empty.", COLOR_TEXT, false, NULL, NULL, NULL); return; } @@ -363,5 +363,5 @@ void action_paste_contents(linked_list* items, list_item* selected) { 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, NULL, action_paste_files_draw_top, action_paste_files_onresponse); + prompt_display("Confirmation", "Paste clipboard contents to the current directory?", COLOR_TEXT, true, data, action_paste_files_draw_top, action_paste_files_onresponse); } \ No newline at end of file diff --git a/source/ui/section/dumpnand.c b/source/ui/section/dumpnand.c index d99b6d3..a48f88b 100644 --- a/source/ui/section/dumpnand.c +++ b/source/ui/section/dumpnand.c @@ -66,7 +66,7 @@ static Result dumpnand_restore(void* data, u32 index) { 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); + prompt_display("Failure", "Dump cancelled.", COLOR_TEXT, false, NULL, NULL, NULL); } else { error_display_res(NULL, NULL, NULL, res, "Failed to dump NAND."); } @@ -82,7 +82,7 @@ static void dumpnand_update(ui_view* view, void* data, float* progress, char* te info_destroy(view); if(R_SUCCEEDED(dumpData->result)) { - prompt_display("Success", "NAND dumped.", COLOR_TEXT, false, NULL, NULL, NULL, NULL); + prompt_display("Success", "NAND dumped.", COLOR_TEXT, false, NULL, NULL, NULL); } free(dumpData); @@ -151,5 +151,5 @@ void dumpnand_open() { data->finished = true; - prompt_display("Confirmation", "Dump raw NAND image to the SD card?", COLOR_TEXT, true, data, NULL, NULL, dumpnand_onresponse); + prompt_display("Confirmation", "Dump raw NAND image to the SD card?", COLOR_TEXT, true, data, NULL, dumpnand_onresponse); } \ No newline at end of file diff --git a/source/ui/section/files.c b/source/ui/section/files.c index be58eff..c7c63f6 100644 --- a/source/ui/section/files.c +++ b/source/ui/section/files.c @@ -91,7 +91,7 @@ static void files_action_update(ui_view* view, void* data, linked_list* items, l 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); + 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, ui_draw_file_info, NULL); } else { error_display_res(NULL, info, ui_draw_file_info, res, "Failed to copy to clipboard."); } diff --git a/source/ui/section/networkinstall.c b/source/ui/section/networkinstall.c index 5598760..1e8a005 100644 --- a/source/ui/section/networkinstall.c +++ b/source/ui/section/networkinstall.c @@ -204,7 +204,7 @@ static Result networkinstall_restore(void* data, u32 index) { static bool networkinstall_error(void* data, u32 index, Result res) { if(res == R_FBI_CANCELLED) { - prompt_display("Failure", "Install cancelled.", COLOR_TEXT, false, NULL, NULL, NULL, NULL); + prompt_display("Failure", "Install cancelled.", COLOR_TEXT, false, NULL, NULL, NULL); } else if(res == R_FBI_ERRNO) { error_display_errno(NULL, NULL, NULL, errno, "Failed to install over the network."); } else { @@ -247,7 +247,7 @@ static void networkinstall_install_update(ui_view* view, void* data, float* prog info_destroy(view); if(R_SUCCEEDED(networkInstallData->installInfo.result)) { - prompt_display("Success", "Install finished.", COLOR_TEXT, false, data, NULL, NULL, NULL); + prompt_display("Success", "Install finished.", COLOR_TEXT, false, NULL, NULL, NULL); } return; @@ -278,7 +278,7 @@ static void networkinstall_cdn_check_onresponse(ui_view* view, void* data, bool static void networkinstall_confirm_onresponse(ui_view* view, void* data, bool response) { if(response) { - prompt_display("Optional", "Install ticket titles from CDN?", COLOR_TEXT, true, data, NULL, NULL, networkinstall_cdn_check_onresponse); + prompt_display("Optional", "Install ticket titles from CDN?", COLOR_TEXT, true, data, NULL, networkinstall_cdn_check_onresponse); } else { networkinstall_close_client((network_install_data*) data); } @@ -311,7 +311,7 @@ static void networkinstall_wait_update(ui_view* view, void* data, float* progres networkInstallData->installInfo.total = ntohl(networkInstallData->installInfo.total); networkInstallData->clientSocket = sock; - prompt_display("Confirmation", "Install the received file(s)?", COLOR_TEXT, true, data, NULL, NULL, networkinstall_confirm_onresponse); + prompt_display("Confirmation", "Install the received file(s)?", COLOR_TEXT, true, data, NULL, networkinstall_confirm_onresponse); } else if(errno != EAGAIN) { if(errno == 22 || errno == 115) { ui_pop(); diff --git a/source/ui/section/qrinstall.c b/source/ui/section/qrinstall.c index 6eb8b4f..ed365a4 100644 --- a/source/ui/section/qrinstall.c +++ b/source/ui/section/qrinstall.c @@ -206,7 +206,7 @@ static bool qrinstall_error(void* data, u32 index, Result res) { qr_install_data* qrInstallData = (qr_install_data*) data; if(res == R_FBI_CANCELLED) { - prompt_display("Failure", "Install cancelled.", COLOR_TEXT, false, NULL, NULL, NULL, NULL); + prompt_display("Failure", "Install cancelled.", COLOR_TEXT, false, NULL, NULL, NULL); return false; } else { char* url = qrInstallData->urls[index]; @@ -242,7 +242,7 @@ static void qrinstall_install_update(ui_view* view, void* data, float* progress, info_destroy(view); if(R_SUCCEEDED(qrInstallData->installInfo.result)) { - prompt_display("Success", "Install finished.", COLOR_TEXT, false, data, NULL, NULL, NULL); + prompt_display("Success", "Install finished.", COLOR_TEXT, false, NULL, NULL, NULL); } return; @@ -271,7 +271,7 @@ static void qrinstall_cdn_check_onresponse(ui_view* view, void* data, bool respo static void qrinstall_confirm_onresponse(ui_view* view, void* data, bool response) { if(response) { - prompt_display("Optional", "Install ticket titles from CDN?", COLOR_TEXT, true, data, NULL, NULL, qrinstall_cdn_check_onresponse); + prompt_display("Optional", "Install ticket titles from CDN?", COLOR_TEXT, true, data, NULL, qrinstall_cdn_check_onresponse); } } @@ -406,7 +406,7 @@ static void qrinstall_wait_update(ui_view* view, void* data, float* progress, ch currStart = currEnd + 1; } - prompt_display("Confirmation", "Install from the scanned URL(s)?", COLOR_TEXT, true, data, NULL, NULL, qrinstall_confirm_onresponse); + prompt_display("Confirmation", "Install from the scanned URL(s)?", COLOR_TEXT, true, data, NULL, qrinstall_confirm_onresponse); } } diff --git a/source/ui/section/update.c b/source/ui/section/update.c index 040d3a8..c356eb7 100644 --- a/source/ui/section/update.c +++ b/source/ui/section/update.c @@ -141,7 +141,7 @@ static bool update_error(void* data, u32 index, Result res) { update_data* updateData = (update_data*) data; if(res == R_FBI_CANCELLED) { - prompt_display("Failure", "Install cancelled.", COLOR_TEXT, false, NULL, NULL, NULL, NULL); + prompt_display("Failure", "Install cancelled.", COLOR_TEXT, false, NULL, NULL, NULL); } else if(res == R_FBI_HTTP_RESPONSE_CODE) { error_display(NULL, NULL, NULL, "Failed to update FBI.\nHTTP server returned response code %d", updateData->responseCode); } else { @@ -159,7 +159,7 @@ static void update_install_update(ui_view* view, void* data, float* progress, ch info_destroy(view); if(R_SUCCEEDED(updateData->installInfo.result)) { - prompt_display("Success", "Update complete.", COLOR_TEXT, false, NULL, NULL, NULL, NULL); + prompt_display("Success", "Update complete.", COLOR_TEXT, false, NULL, NULL, NULL); } free(updateData); @@ -285,7 +285,7 @@ static void update_check_update(ui_view* view, void* data, float* progress, char error_display_res(NULL, NULL, NULL, res, "Failed to check for update."); } } else { - prompt_display("Success", "No updates available.", COLOR_TEXT, false, NULL, NULL, NULL, NULL); + prompt_display("Success", "No updates available.", COLOR_TEXT, false, NULL, NULL, NULL); } free(data); @@ -340,5 +340,5 @@ void update_open() { data->installInfo.finished = true; - prompt_display("Confirmation", "Check for FBI updates?", COLOR_TEXT, true, data, NULL, NULL, update_onresponse); + prompt_display("Confirmation", "Check for FBI updates?", COLOR_TEXT, true, data, NULL, update_onresponse); } \ No newline at end of file diff --git a/source/ui/ui.c b/source/ui/ui.c index 9d694dd..213f548 100644 --- a/source/ui/ui.c +++ b/source/ui/ui.c @@ -112,15 +112,16 @@ static void ui_draw_top(ui_view* ui) { float verWidth; float verHeight; screen_get_string_size(&verWidth, &verHeight, verText, 0.5f, 0.5f); - screen_draw_string(verText, topScreenTopBarX + 2, topScreenTopBarY + (topScreenTopBarHeight - verHeight) / 2, 0.5f, 0.5f, COLOR_TEXT, false); + screen_draw_string(verText, topScreenTopBarX + 2, topScreenTopBarY + (topScreenTopBarHeight - verHeight) / 2, 0.5f, 0.5f, COLOR_TEXT, true); time_t t = time(NULL); char* timeText = ctime(&t); + timeText[strlen(timeText) - 1] = '\0'; float timeTextWidth; float timeTextHeight; screen_get_string_size(&timeTextWidth, &timeTextHeight, timeText, 0.5f, 0.5f); - screen_draw_string(timeText, topScreenTopBarX + (topScreenTopBarWidth - timeTextWidth) / 2, topScreenTopBarY + (topScreenTopBarHeight - timeTextHeight) / 2, 0.5f, 0.5f, COLOR_TEXT, false); + screen_draw_string(timeText, topScreenTopBarX + (topScreenTopBarWidth - timeTextWidth) / 2, topScreenTopBarY + (topScreenTopBarHeight - timeTextHeight) / 2, 0.5f, 0.5f, COLOR_TEXT, true); u32 batteryIcon = 0; u8 batteryChargeState = 0; @@ -204,7 +205,7 @@ static void ui_draw_top(ui_view* ui) { float freeSpaceHeight; screen_get_string_size(NULL, &freeSpaceHeight, buffer, 0.35f, 0.35f); - screen_draw_string(buffer, topScreenBottomBarX + 2, topScreenBottomBarY + (topScreenBottomBarHeight - freeSpaceHeight) / 2, 0.35f, 0.35f, COLOR_TEXT, false); + screen_draw_string(buffer, topScreenBottomBarX + 2, topScreenBottomBarY + (topScreenBottomBarHeight - freeSpaceHeight) / 2, 0.35f, 0.35f, COLOR_TEXT, true); } static void ui_draw_bottom(ui_view* ui) { @@ -249,14 +250,14 @@ static void ui_draw_bottom(ui_view* ui) { float nameWidth; float nameHeight; screen_get_string_size(&nameWidth, &nameHeight, ui->name, 0.5f, 0.5f); - screen_draw_string(ui->name, (BOTTOM_SCREEN_WIDTH - nameWidth) / 2, (bottomScreenTopBarHeight - nameHeight) / 2, 0.5f, 0.5f, COLOR_TEXT, false); + screen_draw_string(ui->name, (BOTTOM_SCREEN_WIDTH - nameWidth) / 2, (bottomScreenTopBarHeight - nameHeight) / 2, 0.5f, 0.5f, COLOR_TEXT, true); } if(ui->info != NULL) { float infoWidth; float infoHeight; screen_get_string_size(&infoWidth, &infoHeight, ui->info, 0.5f, 0.5f); - screen_draw_string(ui->info, (BOTTOM_SCREEN_WIDTH - infoWidth) / 2, BOTTOM_SCREEN_HEIGHT - (bottomScreenBottomBarHeight + infoHeight) / 2, 0.5f, 0.5f, COLOR_TEXT, false); + screen_draw_string(ui->info, (BOTTOM_SCREEN_WIDTH - infoWidth) / 2, BOTTOM_SCREEN_HEIGHT - (bottomScreenBottomBarHeight + infoHeight) / 2, 0.5f, 0.5f, COLOR_TEXT, true); } } @@ -290,8 +291,6 @@ bool ui_update() { void ui_draw_ext_save_data_info(ui_view* view, void* data, float x1, float y1, float x2, float y2) { ext_save_data_info* info = (ext_save_data_info*) data; - char buf[64]; - if(info->hasMeta) { u32 metaInfoBoxShadowWidth; u32 metaInfoBoxShadowHeight; @@ -329,65 +328,45 @@ void ui_draw_ext_save_data_info(ui_view* view, void* data, float x1, float y1, f float metaTextX = metaInfoBoxX + 64; float shortDescriptionY = metaInfoBoxY + (64 - shortDescriptionHeight - 2 - longDescriptionHeight - 2 - publisherHeight) / 2; - screen_draw_string(info->meta.shortDescription, metaTextX, shortDescriptionY, 0.5f, 0.5f, COLOR_TEXT, false); + screen_draw_string(info->meta.shortDescription, metaTextX, shortDescriptionY, 0.5f, 0.5f, COLOR_TEXT, true); float longDescriptionY = shortDescriptionY + shortDescriptionHeight + 2; - screen_draw_string(info->meta.longDescription, metaTextX, longDescriptionY, 0.5f, 0.5f, COLOR_TEXT, false); + screen_draw_string(info->meta.longDescription, metaTextX, longDescriptionY, 0.5f, 0.5f, COLOR_TEXT, true); float publisherY = longDescriptionY + longDescriptionHeight + 2; - screen_draw_string(info->meta.publisher, metaTextX, publisherY, 0.5f, 0.5f, COLOR_TEXT, false); + screen_draw_string(info->meta.publisher, metaTextX, publisherY, 0.5f, 0.5f, COLOR_TEXT, true); } - snprintf(buf, 64, "Ext Save Data ID: %016llX", info->extSaveDataId); + char infoText[512]; - float saveDataIdWidth; - float saveDataIdHeight; - screen_get_string_size(&saveDataIdWidth, &saveDataIdHeight, buf, 0.5f, 0.5f); + snprintf(infoText, sizeof(infoText), + "Ext Save Data ID: %016llX\n" + "Shared: %s", + info->extSaveDataId, + info->shared ? "Yes" : "No"); - float saveDataIdX = x1 + (x2 - x1 - saveDataIdWidth) / 2; - float saveDataIdY = y1 + (y2 - y1) / 2 - 8; - screen_draw_string(buf, saveDataIdX, saveDataIdY, 0.5f, 0.5f, COLOR_TEXT, false); + float infoWidth; + screen_get_string_size(&infoWidth, NULL, infoText, 0.5f, 0.5f); - snprintf(buf, 64, "Shared: %s", info->shared ? "Yes" : "No"); - - float sharedWidth; - float sharedHeight; - screen_get_string_size(&sharedWidth, &sharedHeight, buf, 0.5f, 0.5f); - - float sharedX = x1 + (x2 - x1 - sharedWidth) / 2; - float sharedY = saveDataIdY + saveDataIdHeight + 2; - screen_draw_string(buf, sharedX, sharedY, 0.5f, 0.5f, COLOR_TEXT, false); + float infoX = x1 + (x2 - x1 - infoWidth) / 2; + float infoY = y1 + (y2 - y1) / 2 - 8; + screen_draw_string(infoText, infoX, infoY, 0.5f, 0.5f, COLOR_TEXT, true); } void ui_draw_file_info(ui_view* view, void* data, float x1, float y1, float x2, float y2) { file_info* info = (file_info*) data; - char buf[64]; + char infoText[512]; + size_t infoTextPos = 0; if(strlen(info->name) > 48) { - snprintf(buf, 64, "Name: %.45s...", info->name); + infoTextPos += snprintf(infoText + infoTextPos, sizeof(infoText) - infoTextPos, "Name: %.45s...\n", info->name); } else { - snprintf(buf, 64, "Name: %.48s", info->name); + infoTextPos += snprintf(infoText + infoTextPos, sizeof(infoText) - infoTextPos, "Name: %.48s\n", info->name); } - float nameWidth; - float nameHeight; - screen_get_string_size(&nameWidth, &nameHeight, buf, 0.5f, 0.5f); - - float nameX = x1 + (x2 - x1 - nameWidth) / 2; - float nameY = y1 + (y2 - y1) / 2 - 8; - screen_draw_string(buf, nameX, nameY, 0.5f, 0.5f, COLOR_TEXT, false); - if(!info->isDirectory) { - snprintf(buf, 64, "Size: %.2f MiB", info->size / 1024.0 / 1024.0); - - float sizeWidth; - float sizeHeight; - screen_get_string_size(&sizeWidth, &sizeHeight, buf, 0.5f, 0.5f); - - float sizeX = x1 + (x2 - x1 - sizeWidth) / 2; - float sizeY = nameY + nameHeight + 2; - screen_draw_string(buf, sizeX, sizeY, 0.5f, 0.5f, COLOR_TEXT, false); + infoTextPos += snprintf(infoText + infoTextPos, sizeof(infoText) - infoTextPos, "Size: %.2f MiB\n", info->size / 1024.0 / 1024.0); if(info->isCia) { if(info->ciaInfo.hasMeta) { @@ -427,141 +406,91 @@ void ui_draw_file_info(ui_view* view, void* data, float x1, float y1, float x2, float metaTextX = metaInfoBoxX + 64; float shortDescriptionY = metaInfoBoxY + (64 - shortDescriptionHeight - 2 - longDescriptionHeight - 2 - publisherHeight) / 2; - screen_draw_string(info->ciaInfo.meta.shortDescription, metaTextX, shortDescriptionY, 0.5f, 0.5f, COLOR_TEXT, false); + screen_draw_string(info->ciaInfo.meta.shortDescription, metaTextX, shortDescriptionY, 0.5f, 0.5f, COLOR_TEXT, true); float longDescriptionY = shortDescriptionY + shortDescriptionHeight + 2; - screen_draw_string(info->ciaInfo.meta.longDescription, metaTextX, longDescriptionY, 0.5f, 0.5f, COLOR_TEXT, false); + screen_draw_string(info->ciaInfo.meta.longDescription, metaTextX, longDescriptionY, 0.5f, 0.5f, COLOR_TEXT, true); float publisherY = longDescriptionY + longDescriptionHeight + 2; - screen_draw_string(info->ciaInfo.meta.publisher, metaTextX, publisherY, 0.5f, 0.5f, COLOR_TEXT, false); + screen_draw_string(info->ciaInfo.meta.publisher, metaTextX, publisherY, 0.5f, 0.5f, COLOR_TEXT, true); } - snprintf(buf, 64, "Title ID: %016llX", info->ciaInfo.titleId); - - float titleIdWidth; - float titleIdHeight; - screen_get_string_size(&titleIdWidth, &titleIdHeight, buf, 0.5f, 0.5f); - - float titleIdX = x1 + (x2 - x1 - titleIdWidth) / 2; - float titleIdY = sizeY + sizeHeight + 2; - screen_draw_string(buf, titleIdX, titleIdY, 0.5f, 0.5f, COLOR_TEXT, false); - - snprintf(buf, 64, "Version: %hu", info->ciaInfo.version); - - float versionWidth; - float versionHeight; - screen_get_string_size(&versionWidth, &versionHeight, buf, 0.5f, 0.5f); - - float versionX = x1 + (x2 - x1 - versionWidth) / 2; - float versionY = titleIdY + titleIdHeight + 2; - screen_draw_string(buf, versionX, versionY, 0.5f, 0.5f, COLOR_TEXT, false); - - snprintf(buf, 64, "Installed Size: %.2f MiB", info->ciaInfo.installedSize / 1024.0 / 1024.0); - - float installedSizeWidth; - float installedSizeHeight; - screen_get_string_size(&installedSizeWidth, &installedSizeHeight, buf, 0.5f, 0.5f); - - float installedSizeX = x1 + (x2 - x1 - installedSizeWidth) / 2; - float installedSizeY = versionY + versionHeight + 2; - screen_draw_string(buf, installedSizeX, installedSizeY, 0.5f, 0.5f, COLOR_TEXT, false); + infoTextPos += snprintf(infoText + infoTextPos, sizeof(infoText) - infoTextPos, + "Title ID: %016llX\n" + "Version: %hu\n" + "Installed Size: %.2f MiB", + info->ciaInfo.titleId, + info->ciaInfo.version, + info->ciaInfo.installedSize / 1024.0 / 1024.0); } else if(info->isTicket) { - snprintf(buf, 64, "Ticket ID: %016llX", info->ticketInfo.titleId); - - float ticketIdWidth; - float ticketIdHeight; - screen_get_string_size(&ticketIdWidth, &ticketIdHeight, buf, 0.5f, 0.5f); - - float ticketIdX = x1 + (x2 - x1 - ticketIdWidth) / 2; - float ticketIdY = sizeY + sizeHeight + 2; - screen_draw_string(buf, ticketIdX, ticketIdY, 0.5f, 0.5f, COLOR_TEXT, false); + infoTextPos += snprintf(infoText + infoTextPos, sizeof(infoText) - infoTextPos, "Ticket ID: %016llX", info->ticketInfo.titleId); } } else { - snprintf(buf, 64, "Directory"); - - float directoryWidth; - float directoryHeight; - screen_get_string_size(&directoryWidth, &directoryHeight, buf, 0.5f, 0.5f); - - float directoryX = x1 + (x2 - x1 - directoryWidth) / 2; - float directoryY = nameY + nameHeight + 2; - screen_draw_string(buf, directoryX, directoryY, 0.5f, 0.5f, COLOR_TEXT, false); + infoTextPos += snprintf(infoText + infoTextPos, sizeof(infoText) - infoTextPos, "Directory"); } + + float infoWidth; + screen_get_string_size(&infoWidth, NULL, infoText, 0.5f, 0.5f); + + float infoX = x1 + (x2 - x1 - infoWidth) / 2; + float infoY = y1 + (y2 - y1) / 2 - 8; + screen_draw_string(infoText, infoX, infoY, 0.5f, 0.5f, COLOR_TEXT, true); } void ui_draw_pending_title_info(ui_view* view, void* data, float x1, float y1, float x2, float y2) { pending_title_info* info = (pending_title_info*) data; - char buf[64]; + char infoText[512]; - snprintf(buf, 64, "Pending Title ID: %016llX", info->titleId); + snprintf(infoText, sizeof(infoText), + "Pending Title ID: %016llX\n" + "Media Type: %s\n" + "Version: %hu", + info->titleId, + info->mediaType == MEDIATYPE_NAND ? "NAND" : info->mediaType == MEDIATYPE_SD ? "SD" : "Game Card", + info->version); - float titleIdWidth; - float titleIdHeight; - screen_get_string_size(&titleIdWidth, &titleIdHeight, buf, 0.5f, 0.5f); + float infoWidth; + screen_get_string_size(&infoWidth, NULL, infoText, 0.5f, 0.5f); - float titleIdX = x1 + (x2 - x1 - titleIdWidth) / 2; - float titleIdY = y1 + (y2 - y1) / 2 - 8; - screen_draw_string(buf, titleIdX, titleIdY, 0.5f, 0.5f, COLOR_TEXT, false); - - snprintf(buf, 64, "Media Type: %s", info->mediaType == MEDIATYPE_NAND ? "NAND" : info->mediaType == MEDIATYPE_SD ? "SD" : "Game Card"); - - float mediaTypeWidth; - float mediaTypeHeight; - screen_get_string_size(&mediaTypeWidth, &mediaTypeHeight, buf, 0.5f, 0.5f); - - float mediaTypeX = x1 + (x2 - x1 - mediaTypeWidth) / 2; - float mediaTypeY = titleIdY + titleIdHeight + 2; - screen_draw_string(buf, mediaTypeX, mediaTypeY, 0.5f, 0.5f, COLOR_TEXT, false); - - snprintf(buf, 64, "Version: %hu", info->version); - - float versionWidth; - float versionHeight; - screen_get_string_size(&versionWidth, &versionHeight, buf, 0.5f, 0.5f); - - float versionX = x1 + (x2 - x1 - versionWidth) / 2; - float versionY = mediaTypeY + mediaTypeHeight + 2; - screen_draw_string(buf, versionX, versionY, 0.5f, 0.5f, COLOR_TEXT, false); + float infoX = x1 + (x2 - x1 - infoWidth) / 2; + float infoY = y1 + (y2 - y1) / 2 - 8; + screen_draw_string(infoText, infoX, infoY, 0.5f, 0.5f, COLOR_TEXT, true); } void ui_draw_system_save_data_info(ui_view* view, void* data, float x1, float y1, float x2, float y2) { system_save_data_info* info = (system_save_data_info*) data; - char buf[64]; + char infoText[512]; - snprintf(buf, 64, "System Save Data ID: %08lX", info->systemSaveDataId); + snprintf(infoText, sizeof(infoText), "System Save Data ID: %08lX", info->systemSaveDataId); - float saveDataIdWidth; - float saveDataIdHeight; - screen_get_string_size(&saveDataIdWidth, &saveDataIdHeight, buf, 0.5f, 0.5f); + float infoWidth; + screen_get_string_size(&infoWidth, NULL, infoText, 0.5f, 0.5f); - float saveDataIdX = x1 + (x2 - x1 - saveDataIdWidth) / 2; - float saveDataIdY = y1 + (y2 - y1) / 2 - 8; - screen_draw_string(buf, saveDataIdX, saveDataIdY, 0.5f, 0.5f, COLOR_TEXT, false); + float infoX = x1 + (x2 - x1 - infoWidth) / 2; + float infoY = y1 + (y2 - y1) / 2 - 8; + screen_draw_string(infoText, infoX, infoY, 0.5f, 0.5f, COLOR_TEXT, true); } void ui_draw_ticket_info(ui_view* view, void* data, float x1, float y1, float x2, float y2) { ticket_info* info = (ticket_info*) data; - char buf[64]; + char infoText[512]; - snprintf(buf, 64, "Title ID: %016llX", info->titleId); + snprintf(infoText, sizeof(infoText), "Title ID: %016llX", info->titleId); - float titleIdWidth; - float titleIdHeight; - screen_get_string_size(&titleIdWidth, &titleIdHeight, buf, 0.5f, 0.5f); + float infoWidth; + screen_get_string_size(&infoWidth, NULL, infoText, 0.5f, 0.5f); - float titleIdX = x1 + (x2 - x1 - titleIdWidth) / 2; - float titleIdY = y1 + (y2 - y1) / 2 - 8; - screen_draw_string(buf, titleIdX, titleIdY, 0.5f, 0.5f, COLOR_TEXT, false); + float infoX = x1 + (x2 - x1 - infoWidth) / 2; + float infoY = y1 + (y2 - y1) / 2 - 8; + screen_draw_string(infoText, infoX, infoY, 0.5f, 0.5f, COLOR_TEXT, true); } void ui_draw_title_info(ui_view* view, void* data, float x1, float y1, float x2, float y2) { title_info* info = (title_info*) data; - char buf[64]; - if(info->hasMeta) { u32 metaInfoBoxShadowWidth; u32 metaInfoBoxShadowHeight; @@ -599,62 +528,33 @@ void ui_draw_title_info(ui_view* view, void* data, float x1, float y1, float x2, float metaTextX = metaInfoBoxX + 64; float shortDescriptionY = metaInfoBoxY + (64 - shortDescriptionHeight - 2 - longDescriptionHeight - 2 - publisherHeight) / 2; - screen_draw_string(info->meta.shortDescription, metaTextX, shortDescriptionY, 0.5f, 0.5f, COLOR_TEXT, false); + screen_draw_string(info->meta.shortDescription, metaTextX, shortDescriptionY, 0.5f, 0.5f, COLOR_TEXT, true); float longDescriptionY = shortDescriptionY + shortDescriptionHeight + 2; - screen_draw_string(info->meta.longDescription, metaTextX, longDescriptionY, 0.5f, 0.5f, COLOR_TEXT, false); + screen_draw_string(info->meta.longDescription, metaTextX, longDescriptionY, 0.5f, 0.5f, COLOR_TEXT, true); float publisherY = longDescriptionY + longDescriptionHeight + 2; - screen_draw_string(info->meta.publisher, metaTextX, publisherY, 0.5f, 0.5f, COLOR_TEXT, false); + screen_draw_string(info->meta.publisher, metaTextX, publisherY, 0.5f, 0.5f, COLOR_TEXT, true); } - snprintf(buf, 64, "Title ID: %016llX", info->titleId); + char infoText[512]; - float titleIdWidth; - float titleIdHeight; - screen_get_string_size(&titleIdWidth, &titleIdHeight, buf, 0.5f, 0.5f); + snprintf(infoText, sizeof(infoText), + "Title ID: %016llX\n" + "Media Type: %s\n" + "Version: %hu\n" + "Product Code: %s\n" + "Installed Size: %.2f MiB", + info->titleId, + info->mediaType == MEDIATYPE_NAND ? "NAND" : info->mediaType == MEDIATYPE_SD ? "SD" : "Game Card", + info->version, + info->productCode, + info->installedSize / 1024.0 / 1024.0); - float titleIdX = x1 + (x2 - x1 - titleIdWidth) / 2; - float titleIdY = y1 + (y2 - y1) / 2 - 8; - screen_draw_string(buf, titleIdX, titleIdY, 0.5f, 0.5f, COLOR_TEXT, false); + float infoWidth; + screen_get_string_size(&infoWidth, NULL, infoText, 0.5f, 0.5f); - snprintf(buf, 64, "Media Type: %s", info->mediaType == MEDIATYPE_NAND ? "NAND" : info->mediaType == MEDIATYPE_SD ? "SD" : "Game Card"); - - float mediaTypeWidth; - float mediaTypeHeight; - screen_get_string_size(&mediaTypeWidth, &mediaTypeHeight, buf, 0.5f, 0.5f); - - float mediaTypeX = x1 + (x2 - x1 - mediaTypeWidth) / 2; - float mediaTypeY = titleIdY + titleIdHeight + 2; - screen_draw_string(buf, mediaTypeX, mediaTypeY, 0.5f, 0.5f, COLOR_TEXT, false); - - snprintf(buf, 64, "Product Code: %s", info->productCode); - - float productCodeWidth; - float productCodeHeight; - screen_get_string_size(&productCodeWidth, &productCodeHeight, buf, 0.5f, 0.5f); - - float productCodeX = x1 + (x2 - x1 - productCodeWidth) / 2; - float productCodeY = mediaTypeY + mediaTypeHeight + 2; - screen_draw_string(buf, productCodeX, productCodeY, 0.5f, 0.5f, COLOR_TEXT, false); - - snprintf(buf, 64, "Version: %hu", info->version); - - float versionWidth; - float versionHeight; - screen_get_string_size(&versionWidth, &versionHeight, buf, 0.5f, 0.5f); - - float versionX = x1 + (x2 - x1 - versionWidth) / 2; - float versionY = productCodeY + productCodeHeight + 2; - screen_draw_string(buf, versionX, versionY, 0.5f, 0.5f, COLOR_TEXT, false); - - snprintf(buf, 64, "Installed Size: %.2f MiB", info->installedSize / 1024.0 / 1024.0); - - float installedSizeWidth; - float installedSizeHeight; - screen_get_string_size(&installedSizeWidth, &installedSizeHeight, buf, 0.5f, 0.5f); - - float installedSizeX = x1 + (x2 - x1 - installedSizeWidth) / 2; - float installedSizeY = versionY + versionHeight + 2; - screen_draw_string(buf, installedSizeX, installedSizeY, 0.5f, 0.5f, COLOR_TEXT, false); + float infoX = x1 + (x2 - x1 - infoWidth) / 2; + float infoY = y1 + (y2 - y1) / 2 - 8; + screen_draw_string(infoText, infoX, infoY, 0.5f, 0.5f, COLOR_TEXT, true); }