mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-25 06:12:40 +02:00
Handle <=3.0.0 swkbd versions, and filled in the arg struct. Handle the workbuf. Added a param to swkbdCreate and added swkbdClose. Added swkbdConfigSet*Text and swkbdConfigSet*OptionalSymbolKey. Various other changes.
This commit is contained in:
parent
854e3058ba
commit
901dc817e7
@ -8,19 +8,132 @@
|
|||||||
#include "../types.h"
|
#include "../types.h"
|
||||||
#include "../services/applet.h"
|
#include "../services/applet.h"
|
||||||
|
|
||||||
|
typedef bool (*SwkbdTextCheckCb)(void *); ///< TextCheck callback. TODO
|
||||||
|
|
||||||
|
/// Base swkbd arg struct.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 data[0x3E0];//TODO: Fill this in.
|
u32 unk_x0;
|
||||||
} SwkbdArg;
|
u16 okButtonText[18/2];
|
||||||
|
u16 leftButtonText;
|
||||||
|
u16 rightButtonText;
|
||||||
|
u16 unk_x1a;
|
||||||
|
u32 keySetDisableBitmask;
|
||||||
|
u32 initialCursorPos;
|
||||||
|
u16 headerText[130/2];
|
||||||
|
u16 subText[258/2];
|
||||||
|
u16 guideText[514/2];
|
||||||
|
u16 pad_x3aa;
|
||||||
|
u32 stringLenMax;
|
||||||
|
u32 unk_x3b0;
|
||||||
|
u32 passwordFlag;
|
||||||
|
u32 unk_x3b8;
|
||||||
|
u16 returnButtonFlag; ///< Controls whether the Return button is enabled, for newlines input. 0 = disabled, non-zero = enabled.
|
||||||
|
u8 blurBackground; ///< When enabled with value 1, the background is blurred.
|
||||||
|
u8 pad_x3bf;
|
||||||
|
u32 initialStringOffset;
|
||||||
|
u32 initialStringSize;
|
||||||
|
u32 userDicOffset;
|
||||||
|
s32 userDicEntries;
|
||||||
|
u8 textCheckFlag;
|
||||||
|
u8 pad_x3d1[7];
|
||||||
|
SwkbdTextCheckCb textCheckCb; ///< This really doesn't belong in a struct sent to another process, but official sw does this.
|
||||||
|
} SwkbdArgV0;
|
||||||
|
|
||||||
|
/// Arg struct for version 0x30007+.
|
||||||
|
typedef struct {
|
||||||
|
SwkbdArgV0 arg;
|
||||||
|
u64 unk_x3e0[4];
|
||||||
|
} SwkbdArgV7;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
SwkbdArg arg;
|
SwkbdArgV7 arg;
|
||||||
|
|
||||||
|
u8* workbuf;
|
||||||
|
size_t workbuf_size;
|
||||||
|
s32 max_dictwords;
|
||||||
} SwkbdConfig;
|
} SwkbdConfig;
|
||||||
|
|
||||||
|
/// User dictionary word.
|
||||||
|
typedef struct {
|
||||||
|
u8 unk_x0[0x64];
|
||||||
|
} SwkbdDictWord;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates a SwkbdConfig struct.
|
* @brief Creates a SwkbdConfig struct.
|
||||||
* @param c SwkbdConfig struct.
|
* @param c SwkbdConfig struct.
|
||||||
|
* @param max_dictwords Max \ref SwkbdDictWord entries, 0 for none.
|
||||||
*/
|
*/
|
||||||
void swkbdCreate(SwkbdConfig* c);
|
Result swkbdCreate(SwkbdConfig* c, s32 max_dictwords);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Closes a SwkbdConfig struct.
|
||||||
|
* @param c SwkbdConfig struct.
|
||||||
|
*/
|
||||||
|
void swkbdClose(SwkbdConfig* c);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the Ok button text. The default is "".
|
||||||
|
* @param c SwkbdConfig struct.
|
||||||
|
* @param str UTF-8 input string.
|
||||||
|
*/
|
||||||
|
void swkbdConfigSetOkButtonText(SwkbdConfig* c, const char* str);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the LeftOptionalSymbolKey. The default is "".
|
||||||
|
* @param c SwkbdConfig struct.
|
||||||
|
* @param str UTF-8 input string.
|
||||||
|
*/
|
||||||
|
void swkbdConfigSetLeftOptionalSymbolKey(SwkbdConfig* c, const char* str);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the RightOptionalSymbolKey. The default is "".
|
||||||
|
* @param c SwkbdConfig struct.
|
||||||
|
* @param str UTF-8 input string.
|
||||||
|
*/
|
||||||
|
void swkbdConfigSetRightOptionalSymbolKey(SwkbdConfig* c, const char* str);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the Header text. The default is "".
|
||||||
|
* @param c SwkbdConfig struct.
|
||||||
|
* @param str UTF-8 input string.
|
||||||
|
*/
|
||||||
|
void swkbdConfigSetHeaderText(SwkbdConfig* c, const char* str);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the Sub text. The default is "".
|
||||||
|
* @param c SwkbdConfig struct.
|
||||||
|
* @param str UTF-8 input string.
|
||||||
|
*/
|
||||||
|
void swkbdConfigSetSubText(SwkbdConfig* c, const char* str);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the Guide text. The default is "".
|
||||||
|
* @param c SwkbdConfig struct.
|
||||||
|
* @param str UTF-8 input string.
|
||||||
|
*/
|
||||||
|
void swkbdConfigSetGuideText(SwkbdConfig* c, const char* str);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the Initial text. The default is "".
|
||||||
|
* @param c SwkbdConfig struct.
|
||||||
|
* @param str UTF-8 input string.
|
||||||
|
*/
|
||||||
|
void swkbdConfigSetInitialText(SwkbdConfig* c, const char* str);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the user dictionary.
|
||||||
|
* @param c SwkbdConfig struct.
|
||||||
|
* @param input Input data.
|
||||||
|
* @param entries Total entries in the buffer.
|
||||||
|
*/
|
||||||
|
void swkbdConfigSetDictionary(SwkbdConfig* c, const SwkbdDictWord *input, s32 entries);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the TextCheck callback. TODO: this is not yet used.
|
||||||
|
* @param c SwkbdConfig struct.
|
||||||
|
* @param cb callback
|
||||||
|
*/
|
||||||
|
void swkbdConfigSetTextCheckCallback(SwkbdConfig* c, SwkbdTextCheckCb cb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Launch swkbd with the specified config. This will return once swkbd is finished running.
|
* @brief Launch swkbd with the specified config. This will return once swkbd is finished running.
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "result.h"
|
#include "result.h"
|
||||||
|
#include "kernel/detect.h"
|
||||||
#include "services/applet.h"
|
#include "services/applet.h"
|
||||||
#include "applets/libapplet.h"
|
#include "applets/libapplet.h"
|
||||||
#include "applets/swkbd.h"
|
#include "applets/swkbd.h"
|
||||||
@ -9,19 +10,111 @@
|
|||||||
|
|
||||||
//TODO: InlineKeyboard currently isn't supported.
|
//TODO: InlineKeyboard currently isn't supported.
|
||||||
|
|
||||||
void swkbdCreate(SwkbdConfig* c) {
|
|
||||||
memset(c, 0, sizeof(SwkbdConfig));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _swkbdConvertToUTF8(char* out, const u16* in, size_t max) {
|
static void _swkbdConvertToUTF8(char* out, const u16* in, size_t max) {
|
||||||
out[0] = 0;
|
|
||||||
if (out==NULL || in==NULL) return;
|
if (out==NULL || in==NULL) return;
|
||||||
|
out[0] = 0;
|
||||||
|
|
||||||
ssize_t units = utf16_to_utf8((uint8_t*)out, in, max);
|
ssize_t units = utf16_to_utf8((uint8_t*)out, in, max);
|
||||||
if (units < 0) return;
|
if (units < 0) return;
|
||||||
out[units] = 0;
|
out[units] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t _swkbdConvertToUTF16(u16* out, const char* in, size_t max) {
|
||||||
|
if (out==NULL || in==NULL) return 0;
|
||||||
|
out[0] = 0;
|
||||||
|
|
||||||
|
ssize_t units = utf8_to_utf16(out, (uint8_t*)in, max);
|
||||||
|
if (units < 0 || max<=1) return 0;
|
||||||
|
out[units] = 0;
|
||||||
|
|
||||||
|
return units;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t _swkbdConvertToUTF16ByteSize(u16* out, const char* in, size_t max) {
|
||||||
|
return _swkbdConvertToUTF16(out, in, (max/sizeof(u16)) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result swkbdCreate(SwkbdConfig* c, s32 max_dictwords) {
|
||||||
|
Result rc=0;
|
||||||
|
|
||||||
|
memset(c, 0, sizeof(SwkbdConfig));
|
||||||
|
memset(c->arg.unk_x3e0, 0xff, sizeof(c->arg.unk_x3e0));
|
||||||
|
c->workbuf_size = 0x1000;
|
||||||
|
if (max_dictwords > 0 && max_dictwords <= 0x3e8) c->max_dictwords = max_dictwords;
|
||||||
|
|
||||||
|
if (c->max_dictwords) {
|
||||||
|
c->workbuf_size = c->max_dictwords*0x64 + 0x7e8;
|
||||||
|
c->workbuf_size = (c->workbuf_size + 0xfff) & ~0xfff;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->workbuf = (u8*)memalign(0x1000, c->workbuf_size);
|
||||||
|
if (c->workbuf==NULL) rc = MAKERESULT(Module_Libnx, LibnxError_OutOfMemory);
|
||||||
|
if (R_SUCCEEDED(rc)) memset(c->workbuf, 0, c->workbuf_size);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void swkbdClose(SwkbdConfig* c) {
|
||||||
|
free(c->workbuf);
|
||||||
|
memset(c, 0, sizeof(SwkbdConfig));
|
||||||
|
}
|
||||||
|
|
||||||
|
void swkbdConfigSetOkButtonText(SwkbdConfig* c, const char* str) {
|
||||||
|
_swkbdConvertToUTF16ByteSize(c->arg.arg.okButtonText, str, sizeof(c->arg.arg.okButtonText));
|
||||||
|
}
|
||||||
|
|
||||||
|
void swkbdConfigSetLeftOptionalSymbolKey(SwkbdConfig* c, const char* str) {
|
||||||
|
_swkbdConvertToUTF16(&c->arg.arg.leftButtonText, str, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void swkbdConfigSetRightOptionalSymbolKey(SwkbdConfig* c, const char* str) {
|
||||||
|
_swkbdConvertToUTF16(&c->arg.arg.rightButtonText, str, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void swkbdConfigSetHeaderText(SwkbdConfig* c, const char* str) {
|
||||||
|
_swkbdConvertToUTF16ByteSize(c->arg.arg.headerText, str, sizeof(c->arg.arg.headerText));
|
||||||
|
}
|
||||||
|
|
||||||
|
void swkbdConfigSetSubText(SwkbdConfig* c, const char* str) {
|
||||||
|
_swkbdConvertToUTF16ByteSize(c->arg.arg.subText, str, sizeof(c->arg.arg.subText));
|
||||||
|
}
|
||||||
|
|
||||||
|
void swkbdConfigSetGuideText(SwkbdConfig* c, const char* str) {
|
||||||
|
_swkbdConvertToUTF16ByteSize(c->arg.arg.guideText, str, sizeof(c->arg.arg.guideText));
|
||||||
|
}
|
||||||
|
|
||||||
|
void swkbdConfigSetInitialText(SwkbdConfig* c, const char* str) {
|
||||||
|
c->arg.arg.initialStringOffset = 0;
|
||||||
|
c->arg.arg.initialStringSize = 0;
|
||||||
|
|
||||||
|
if (c->workbuf==NULL) return;
|
||||||
|
u32 offset=0x14;
|
||||||
|
|
||||||
|
ssize_t units = _swkbdConvertToUTF16ByteSize((u16*)&c->workbuf[offset], str, 0x1f4);
|
||||||
|
if (units<=0) return;
|
||||||
|
|
||||||
|
c->arg.arg.initialStringOffset = offset;
|
||||||
|
c->arg.arg.initialStringSize = units;
|
||||||
|
}
|
||||||
|
|
||||||
|
void swkbdConfigSetDictionary(SwkbdConfig* c, const SwkbdDictWord *buffer, s32 entries) {
|
||||||
|
c->arg.arg.userDicOffset = 0;
|
||||||
|
c->arg.arg.userDicEntries = 0;
|
||||||
|
|
||||||
|
if (c->workbuf==NULL) return;
|
||||||
|
if (entries < 1 || entries > c->max_dictwords) return;
|
||||||
|
u32 offset=0x7e8;
|
||||||
|
|
||||||
|
c->arg.arg.userDicOffset = offset;
|
||||||
|
c->arg.arg.userDicEntries = entries;
|
||||||
|
memcpy(&c->workbuf[offset], buffer, entries*0x64);
|
||||||
|
}
|
||||||
|
|
||||||
|
void swkbdConfigSetTextCheckCallback(SwkbdConfig* c, SwkbdTextCheckCb cb) {
|
||||||
|
c->arg.arg.textCheckFlag = cb!=0;
|
||||||
|
c->arg.arg.textCheckCb = cb;
|
||||||
|
}
|
||||||
|
|
||||||
static Result _swkbdProcessOutput(AppletHolder* h, char* out_string, size_t out_string_size) {
|
static Result _swkbdProcessOutput(AppletHolder* h, char* out_string, size_t out_string_size) {
|
||||||
Result rc=0;
|
Result rc=0;
|
||||||
AppletStorage outstorage;
|
AppletStorage outstorage;
|
||||||
@ -52,22 +145,32 @@ Result swkbdShow(SwkbdConfig* c, char* out_string, size_t out_string_size) {
|
|||||||
Result rc=0;
|
Result rc=0;
|
||||||
AppletHolder holder;
|
AppletHolder holder;
|
||||||
AppletStorage storage;
|
AppletStorage storage;
|
||||||
u8 *workbuf = NULL;//TODO
|
u32 version=0x5;//1.0.0+ version
|
||||||
size_t workbuf_size = 0x1000;//TODO
|
|
||||||
|
|
||||||
memset(&storage, 0, sizeof(AppletStorage));
|
memset(&storage, 0, sizeof(AppletStorage));
|
||||||
|
|
||||||
|
//TODO: >3.0.0 versions.
|
||||||
|
if (kernelAbove300()) {
|
||||||
|
version = 0x30007;
|
||||||
|
}
|
||||||
|
else if (kernelAbove200()) {
|
||||||
|
version = 0x10006;
|
||||||
|
}
|
||||||
|
|
||||||
rc = appletCreateLibraryApplet(&holder, AppletId_swkbd, LibAppletMode_AllForeground);
|
rc = appletCreateLibraryApplet(&holder, AppletId_swkbd, LibAppletMode_AllForeground);
|
||||||
if (R_FAILED(rc)) return rc;
|
if (R_FAILED(rc)) return rc;
|
||||||
|
|
||||||
LibAppletArgs commonargs;
|
LibAppletArgs commonargs;
|
||||||
libappletArgsCreate(&commonargs, 0x5);//1.0.0+ version
|
libappletArgsCreate(&commonargs, version);
|
||||||
rc = libappletArgsPush(&commonargs, &holder);
|
rc = libappletArgsPush(&commonargs, &holder);
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) rc = libappletPushInData(&holder, &c->arg, sizeof(c->arg));
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
if (version < 0x30007) rc = libappletPushInData(&holder, &c->arg.arg, sizeof(c->arg.arg));
|
||||||
|
if (version >= 0x30007) rc = libappletPushInData(&holder, &c->arg, sizeof(c->arg));
|
||||||
|
}
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
if (R_SUCCEEDED(rc)) {
|
||||||
if (R_SUCCEEDED(rc)) rc = appletCreateTransferMemoryStorage(&storage, workbuf, workbuf_size, true);
|
if (R_SUCCEEDED(rc)) rc = appletCreateTransferMemoryStorage(&storage, c->workbuf, c->workbuf_size, true);
|
||||||
appletHolderPushInData(&holder, &storage);
|
appletHolderPushInData(&holder, &storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user