Added support for swkbd [6.0.0+] functionality. Added swkbdConfigSet*() funcs which should now be used instead of accessing the arg structs directly. Added version checking for some swkbdInlineSet*() funcs. Various other changes.

This commit is contained in:
yellows8 2019-04-09 18:32:54 -04:00
parent a469a68b20
commit 57b028fec5
No known key found for this signature in database
GPG Key ID: 0AF90DA3F1E60E43
2 changed files with 340 additions and 89 deletions

View File

@ -23,7 +23,7 @@ typedef enum {
SwkbdType_QWERTY = 2, ///< QWERTY (and variants) keyboard only.
} SwkbdType;
/// Bitmask for \ref SwkbdArgV0 keySetDisableBitmask. This disables keys on the keyboard when the corresponding bit(s) are set.
/// Bitmask for SwkbdArgCommon::keySetDisableBitmask. This disables keys on the keyboard when the corresponding bit(s) are set.
enum {
SwkbdKeyDisableBitmask_Space = BIT(1), ///< Disable space-bar.
SwkbdKeyDisableBitmask_At = BIT(2), ///< Disable '@'.
@ -35,7 +35,7 @@ enum {
SwkbdKeyDisableBitmask_UserName = BIT(8), ///< Used for \ref swkbdConfigMakePresetUserName. Disables '@', '%', and '\'.
};
/// Value for \ref SwkbdArgV0 textDrawType. Only applies when stringLenMax is 1..32, otherwise swkbd will only use SwkbdTextDrawType_Box.
/// Value for SwkbdArgCommon::textDrawType. Only applies when stringLenMax is 1..32, otherwise swkbd will only use SwkbdTextDrawType_Box.
typedef enum {
SwkbdTextDrawType_Line = 0, ///< The text will be displayed on a line. Also enables displaying the Header and Sub text.
SwkbdTextDrawType_Box = 1, ///< The text will be displayed in a box.
@ -44,25 +44,28 @@ typedef enum {
/// SwkbdInline Interactive input storage request ID.
typedef enum {
SwkbdRequestCommand_Finalize = 0x4,
SwkbdRequestCommand_SetUserWordInfo = 0x6,
SwkbdRequestCommand_SetCustomizeDic = 0x7,
SwkbdRequestCommand_Calc = 0xA,
SwkbdRequestCommand_Finalize = 0x4,
SwkbdRequestCommand_SetUserWordInfo = 0x6,
SwkbdRequestCommand_SetCustomizeDic = 0x7,
SwkbdRequestCommand_Calc = 0xA,
SwkbdRequestCommand_SetCustomizedDictionaries = 0xB,
SwkbdRequestCommand_UnsetCustomizedDictionaries = 0xC,
} SwkbdRequestCommand;
/// SwkbdInline Interactive output storage reply ID.
typedef enum {
SwkbdReplyType_FinishedInitialize = 0x0,
SwkbdReplyType_ChangedString = 0x2,
SwkbdReplyType_MovedCursor = 0x3,
SwkbdReplyType_MovedTab = 0x4,
SwkbdReplyType_DecidedEnter = 0x5,
SwkbdReplyType_DecidedCancel = 0x6,
SwkbdReplyType_ChangedStringUtf8 = 0x7,
SwkbdReplyType_MovedCursorUtf8 = 0x8,
SwkbdReplyType_DecidedEnterUtf8 = 0x9,
SwkbdReplyType_UnsetCustomizeDic = 0xA,
SwkbdReplyType_ReleasedUserWordInfo = 0xB,
SwkbdReplyType_FinishedInitialize = 0x0,
SwkbdReplyType_ChangedString = 0x2,
SwkbdReplyType_MovedCursor = 0x3,
SwkbdReplyType_MovedTab = 0x4,
SwkbdReplyType_DecidedEnter = 0x5,
SwkbdReplyType_DecidedCancel = 0x6,
SwkbdReplyType_ChangedStringUtf8 = 0x7,
SwkbdReplyType_MovedCursorUtf8 = 0x8,
SwkbdReplyType_DecidedEnterUtf8 = 0x9,
SwkbdReplyType_UnsetCustomizeDic = 0xA,
SwkbdReplyType_ReleasedUserWordInfo = 0xB,
SwkbdReplyType_UnsetCustomizedDictionaries = 0xC,
} SwkbdReplyType;
/// SwkbdInline State
@ -84,6 +87,23 @@ typedef enum {
/// TextCheck callback set by \ref swkbdConfigSetTextCheckCallback, for validating the input string when the swkbd ok-button is pressed. This buffer contains an UTF-8 string. This callback should validate the input string, then return a \ref SwkbdTextCheckResult indicating success/failure. On failure, this function must write an error message to the tmp_string buffer, which will then be displayed by swkbd.
typedef SwkbdTextCheckResult (*SwkbdTextCheckCb)(char* tmp_string, size_t tmp_string_size);
/// User dictionary word.
typedef struct {
u8 unk_x0[0x64];
} SwkbdDictWord;
/// Input data for SwkbdInline request SetCustomizeDic.
typedef struct {
u8 unk_x0[0x70];
} SwkbdCustomizeDicInfo;
typedef struct {
void* buffer; ///< 0x1000-byte aligned buffer.
u32 buffer_size; ///< 0x1000-byte aligned buffer size.
u64 entries[0x18];
u16 total_entries;
} PACKED SwkbdCustomizedDictionarySet;
/// Base swkbd arg struct.
typedef struct {
SwkbdType type; ///< See \ref SwkbdType.
@ -110,16 +130,30 @@ typedef struct {
u32 userDicOffset;
s32 userDicEntries;
u8 textCheckFlag;
} SwkbdArgCommon;
typedef struct {
SwkbdArgCommon arg;
u8 pad_x3d1[7];
SwkbdTextCheckCb textCheckCb; ///< This really doesn't belong in a struct sent to another process, but official sw does this.
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;
u32 unk_x3e0[8]; ///< When set and enabled via \ref SwkbdTextDrawType, controls displayed text grouping (inserts spaces, without affecting output string).
u32 textGrouping[8]; ///< When set and enabled via \ref SwkbdTextDrawType, controls displayed text grouping (inserts spaces, without affecting output string).
} SwkbdArgV7;
/// Arg struct for version 0x6000B+.
typedef struct {
SwkbdArgCommon arg;
u8 pad_x3d1[3];
u32 textGrouping[8]; ///< Same as SwkbdArgV7::textGrouping.
u64 entries[0x18]; ///< This is SwkbdCustomizedDictionarySet::entries.
u8 total_entries; ///< This is SwkbdCustomizedDictionarySet::total_entries.
u8 pad_x4b5[0x13];
} SwkbdArgVB;
typedef struct {
SwkbdArgV7 arg;
@ -127,19 +161,11 @@ typedef struct {
size_t workbuf_size;
s32 max_dictwords;
SwkbdCustomizedDictionarySet customizedDictionarySet;
u32 version;
} SwkbdConfig;
/// User dictionary word.
typedef struct {
u8 unk_x0[0x64];
} SwkbdDictWord;
/// Input data for SwkbdInline request SetCustomizeDic.
typedef struct {
u8 unk_x0[0x70];
} SwkbdCustomizeDicInfo;
typedef struct {
u32 unk_x0;
u8 mode; ///< See \ref SwkbdInlineMode.
@ -198,8 +224,10 @@ typedef struct {
float balloonScale; ///< Flags bitmask 0x200.
float unk_x48c;
u8 unk_x490[0xc];
u8 seGroup; ////< Flags bitmask: enable=0x2000, disable=0x4000. Only available with 5.0.0+.
u8 pad_x49d[3];
u8 seGroup; ///< Flags bitmask: enable=0x2000, disable=0x4000. Only available with 5.0.0+.
u8 triggerFlag; ///< [6.0.0+] Enables using the trigger field when set.
u8 trigger; ///< [6.0.0+] Trigger
u8 pad_x49f;
} PACKED SwkbdInlineCalcArg;
/// Struct data for SwkbdInline Interactive reply storage ChangedString*, at the end following the string.
@ -252,6 +280,7 @@ typedef struct {
SwkbdState state;
bool dicCustomInitialized;
bool customizedDictionariesInitialized;
AppletStorage dicStorage;
bool wordInfoInitialized;
@ -286,7 +315,7 @@ void swkbdClose(SwkbdConfig* c);
/**
* @brief Clears the args in the SwkbdConfig struct and initializes it with the Default Preset.
* @note Do not use this before \ref swkbdCreate.
* @note Sets the following fields: type = \ref SwkbdType_QWERTY, initialCursorPos = 1, returnButtonFlag = 1, blurBackground = 1. Pre-5.0.0: textDrawType = SwkbdTextDrawType_Box.
* @note Uses the following: swkbdConfigSetType() with \ref SwkbdType_QWERTY, swkbdConfigSetInitialCursorPos() with value 1, swkbdConfigSetReturnButtonFlag() with value 1, and swkbdConfigSetBlurBackground() with value 1. Pre-5.0.0: swkbdConfigSetTextDrawType() with \ref SwkbdTextDrawType_Box.
* @param c SwkbdConfig struct.
*/
void swkbdConfigMakePresetDefault(SwkbdConfig* c);
@ -294,7 +323,7 @@ void swkbdConfigMakePresetDefault(SwkbdConfig* c);
/**
* @brief Clears the args in the SwkbdConfig struct and initializes it with the Password Preset.
* @note Do not use this before \ref swkbdCreate.
* @note Sets the following fields: type = \ref SwkbdType_QWERTY, initialCursorPos = 1, passwordFlag = 1, blurBackground = 1.
* @note Uses the following: swkbdConfigSetType() with \ref SwkbdType_QWERTY, swkbdConfigSetInitialCursorPos() with value 1, swkbdConfigSetPasswordFlag() with value 1, and swkbdConfigSetBlurBackground() with value 1.
* @param c SwkbdConfig struct.
*/
void swkbdConfigMakePresetPassword(SwkbdConfig* c);
@ -302,7 +331,7 @@ void swkbdConfigMakePresetPassword(SwkbdConfig* c);
/**
* @brief Clears the args in the SwkbdConfig struct and initializes it with the UserName Preset.
* @note Do not use this before \ref swkbdCreate.
* @note Sets the following fields: type = \ref SwkbdType_Normal, keySetDisableBitmask = SwkbdKeyDisableBitmask_UserName, initialCursorPos = 1, blurBackground = 1.
* @note Uses the following: swkbdConfigSetType() with \ref SwkbdType_Normal, swkbdConfigSetKeySetDisableBitmask() with SwkbdKeyDisableBitmask_UserName, swkbdConfigSetInitialCursorPos() with value 1, and swkbdConfigSetBlurBackground() with value 1.
* @param c SwkbdConfig struct.
*/
void swkbdConfigMakePresetUserName(SwkbdConfig* c);
@ -310,7 +339,7 @@ void swkbdConfigMakePresetUserName(SwkbdConfig* c);
/**
* @brief Clears the args in the SwkbdConfig struct and initializes it with the DownloadCode Preset.
* @note Do not use this before \ref swkbdCreate.
* @note Sets the following fields: type = \ref SwkbdType_Normal (\ref SwkbdType_QWERTY on 5.0.0+), keySetDisableBitmask = SwkbdKeyDisableBitmask_DownloadCode, initialCursorPos = 1, blurBackground = 1. 5.0.0+: stringLenMax = 16, stringLenMaxExt = 1, textDrawType = SwkbdTextDrawType_DownloadCode. unk_x3e0[0-2] = 0x3, 0x7, and 0xb.
* @note Uses the following: swkbdConfigSetType() with \ref SwkbdType_Normal (\ref SwkbdType_QWERTY on 5.0.0+), swkbdConfigSetKeySetDisableBitmask() with SwkbdKeyDisableBitmask_DownloadCode, swkbdConfigSetInitialCursorPos() with value 1, and swkbdConfigSetBlurBackground() with value 1. 5.0.0+: swkbdConfigSetStringLenMax() with value 16, swkbdConfigSetStringLenMaxExt() with value 1, and swkbdConfigSetTextDrawType() with SwkbdTextDrawType_DownloadCode. Uses swkbdConfigSetTextGrouping() for [0-2] with: 0x3, 0x7, and 0xb.
* @param c SwkbdConfig struct.
*/
void swkbdConfigMakePresetDownloadCode(SwkbdConfig* c);
@ -338,7 +367,7 @@ void swkbdConfigSetRightOptionalSymbolKey(SwkbdConfig* c, const char* str);
/**
* @brief Sets the Header text. The default is "".
* @note See \ref SwkbdArgV0 stringLenMax.
* @note See SwkbdArgCommon::stringLenMax.
* @param c SwkbdConfig struct.
* @param str UTF-8 input string.
*/
@ -346,7 +375,7 @@ void swkbdConfigSetHeaderText(SwkbdConfig* c, const char* str);
/**
* @brief Sets the Sub text. The default is "".
* @note See \ref SwkbdArgV0 stringLenMax.
* @note See SwkbdArgCommon::stringLenMax.
* @param c SwkbdConfig struct.
* @param str UTF-8 input string.
*/
@ -375,6 +404,14 @@ void swkbdConfigSetInitialText(SwkbdConfig* c, const char* str);
*/
void swkbdConfigSetDictionary(SwkbdConfig* c, const SwkbdDictWord *input, s32 entries);
/**
* @brief Sets the CustomizedDictionaries.
* @note Only available on [6.0.0+].
* @param c SwkbdConfig struct.
* @param dic Input \ref SwkbdCustomizedDictionarySet
*/
Result swkbdConfigSetCustomizedDictionaries(SwkbdConfig* c, const SwkbdCustomizedDictionarySet *dic);
/**
* @brief Sets the TextCheck callback.
* @param c SwkbdConfig struct.
@ -382,6 +419,106 @@ void swkbdConfigSetDictionary(SwkbdConfig* c, const SwkbdDictWord *input, s32 en
*/
void swkbdConfigSetTextCheckCallback(SwkbdConfig* c, SwkbdTextCheckCb cb);
/**
* @brief Sets SwkbdArgCommon::SwkbdType.
* @param c SwkbdConfig struct.
* @param type \ref SwkbdType
*/
static inline void swkbdConfigSetType(SwkbdConfig* c, SwkbdType type) {
c->arg.arg.arg.type = type;
}
/**
* @brief Sets SwkbdArgCommon::dicFlag.
* @param c SwkbdConfig struct.
* @param flag Flag
*/
static inline void swkbdConfigSetDicFlag(SwkbdConfig* c, u8 flag) {
c->arg.arg.arg.dicFlag = flag;
}
/**
* @brief Sets SwkbdArgCommon::keySetDisableBitmask.
* @param c SwkbdConfig struct.
* @param keySetDisableBitmask keySetDisableBitmask
*/
static inline void swkbdConfigSetKeySetDisableBitmask(SwkbdConfig* c, u32 keySetDisableBitmask) {
c->arg.arg.arg.keySetDisableBitmask = keySetDisableBitmask;
}
/**
* @brief Sets SwkbdArgCommon::initialCursorPos.
* @param c SwkbdConfig struct.
* @param initialCursorPos initialCursorPos
*/
static inline void swkbdConfigSetInitialCursorPos(SwkbdConfig* c, u32 initialCursorPos) {
c->arg.arg.arg.initialCursorPos = initialCursorPos;
}
/**
* @brief Sets SwkbdArgCommon::stringLenMax.
* @param c SwkbdConfig struct.
* @param stringLenMax stringLenMax
*/
static inline void swkbdConfigSetStringLenMax(SwkbdConfig* c, u32 stringLenMax) {
c->arg.arg.arg.stringLenMax = stringLenMax;
}
/**
* @brief Sets SwkbdArgCommon::stringLenMaxExt.
* @param c SwkbdConfig struct.
* @param stringLenMaxExt stringLenMaxExt
*/
static inline void swkbdConfigSetStringLenMaxExt(SwkbdConfig* c, u32 stringLenMaxExt) {
c->arg.arg.arg.stringLenMaxExt = stringLenMaxExt;
}
/**
* @brief Sets SwkbdArgCommon::passwordFlag.
* @param c SwkbdConfig struct.
* @param flag Flag
*/
static inline void swkbdConfigSetPasswordFlag(SwkbdConfig* c, u32 flag) {
c->arg.arg.arg.passwordFlag = flag;
}
/**
* @brief Sets SwkbdArgCommon::textDrawType.
* @param c SwkbdConfig struct.
* @param textDrawType \ref SwkbdTextDrawType
*/
static inline void swkbdConfigSetTextDrawType(SwkbdConfig* c, SwkbdTextDrawType textDrawType) {
c->arg.arg.arg.textDrawType = textDrawType;
}
/**
* @brief Sets SwkbdArgCommon::returnButtonFlag.
* @param c SwkbdConfig struct.
* @param flag Flag
*/
static inline void swkbdConfigSetReturnButtonFlag(SwkbdConfig* c, u16 flag) {
c->arg.arg.arg.returnButtonFlag = flag;
}
/**
* @brief Sets SwkbdArgCommon::blurBackground.
* @param c SwkbdConfig struct.
* @param blurBackground blurBackground
*/
static inline void swkbdConfigSetBlurBackground(SwkbdConfig* c, u8 blurBackground) {
c->arg.arg.arg.blurBackground = blurBackground;
}
/**
* @brief Sets SwkbdArgV7::textGrouping.
* @param index Array index.
* @param value Value to write.
*/
static inline void swkbdConfigSetTextGrouping(SwkbdConfig* c, u32 index, u32 value) {
if (index >= sizeof(c->arg.textGrouping)/sizeof(u32)) return;
c->arg.textGrouping[index] = value;
}
/**
* @brief Launch swkbd with the specified config. This will return once swkbd is finished running.
* @note The string buffer is also used for the buffer passed to the \ref SwkbdTextCheckCb, when it's set. Hence, in that case this buffer should be large enough to handle TextCheck string input/output. The size passed to the callback is the same size passed here, -1.
@ -392,7 +529,7 @@ void swkbdConfigSetTextCheckCallback(SwkbdConfig* c, SwkbdTextCheckCb cb);
Result swkbdShow(SwkbdConfig* c, char* out_string, size_t out_string_size);
/**
* @brief Creates a SwkbdInline object. Only available on 2.0.0+.
* @brief Creates a SwkbdInline object. Only available on [2.0.0+].
* @note This is essentially an asynchronous version of the regular swkbd.
* @note This calls \ref swkbdInlineSetUtf8Mode internally with flag=true.
* @param s SwkbdInline object.
@ -465,10 +602,20 @@ void swkbdInlineSetReleasedUserWordInfoCallback(SwkbdInline* s, VoidFn cb);
/**
* @brief Appear the kbd and set \ref SwkbdAppearArg.
* @note \ref swkbdInlineUpdate must be called at some point afterwards for this to take affect.
* @note Wrapper for \ref swkbdInlineAppearEx, with trigger=0.
* @param s SwkbdInline object.
* @param arg Input SwkbdAppearArg.
*/
void swkbdInlineAppear(SwkbdInline* s, SwkbdAppearArg* arg);
void swkbdInlineAppear(SwkbdInline* s, const SwkbdAppearArg* arg);
/**
* @brief Appear the kbd and set \ref SwkbdAppearArg.
* @note \ref swkbdInlineUpdate must be called at some point afterwards for this to take affect.
* @param s SwkbdInline object.
* @param arg Input SwkbdAppearArg.
* @param trigger Trigger, default is 0. Requires [6.0.0+], on eariler versions this will always use value 0 internally.
*/
void swkbdInlineAppearEx(SwkbdInline* s, const SwkbdAppearArg* arg, u8 trigger);
/**
* @brief Disappear the kbd.
@ -561,7 +708,7 @@ void swkbdInlineSetUtf8Mode(SwkbdInline* s, bool flag);
/**
* @brief Sets the CustomizeDic.
* @note Not avilable when \ref SwkbdState is above ::SwkbdState_Initialized. Can't be used if this was already used previously.
* @note Not avilable when \ref SwkbdState is above ::SwkbdState_Initialized. Can't be used if this or \ref swkbdInlineSetCustomizedDictionaries was already used previously.
* @note The specified buffer must not be used after this, until \ref swkbdInlineClose is used. However, it will also become available once \ref swkbdInlineUpdate handles SwkbdReplyType_UnsetCustomizeDic internally.
* @param s SwkbdInline object.
* @param buffer 0x1000-byte aligned buffer.
@ -578,6 +725,24 @@ Result swkbdInlineSetCustomizeDic(SwkbdInline* s, void* buffer, size_t size, Swk
*/
void swkbdInlineUnsetCustomizeDic(SwkbdInline* s);
/**
* @brief Sets the CustomizedDictionaries.
* @note Not avilable when \ref SwkbdState is above ::SwkbdState_Initialized. Can't be used if this or \ref swkbdInlineSetCustomizeDic was already used previously.
* @note The specified buffer in dic must not be used after this, until \ref swkbdInlineClose is used. However, it will also become available once \ref swkbdInlineUpdate handles SwkbdReplyType_UnsetCustomizedDictionaries internally.
* @note Only available on [6.0.0+].
* @param s SwkbdInline object.
* @param dic Input \ref SwkbdCustomizedDictionarySet
*/
Result swkbdInlineSetCustomizedDictionaries(SwkbdInline* s, const SwkbdCustomizedDictionarySet *dic);
/**
* @brief Request UnsetCustomizedDictionaries.
* @note Not avilable when \ref SwkbdState is above ::SwkbdState_Initialized.
* @note Only available on [6.0.0+].
* @param s SwkbdInline object.
*/
Result swkbdInlineUnsetCustomizedDictionaries(SwkbdInline* s);
/**
* @brief Sets InputModeFadeType.
* @note \ref swkbdInlineUpdate must be called at some point afterwards for this to take affect.
@ -660,16 +825,18 @@ void swkbdInlineSetTouchFlag(SwkbdInline* s, bool flag);
void swkbdInlineSetUSBKeyboardFlag(SwkbdInline* s, bool flag);
/**
* @brief Sets whether DirectionalButtonAssign is enabled. The default is disabled. Only available on 4.0.0+.
* @brief Sets whether DirectionalButtonAssign is enabled. The default is disabled.
* @note \ref swkbdInlineUpdate must be called at some point afterwards for this to take affect.
* @note Only available on [4.0.0+].
* @param s SwkbdInline object.
* @param flag Flag
*/
void swkbdInlineSetDirectionalButtonAssignFlag(SwkbdInline* s, bool flag);
/**
* @brief Sets whether the specified SeGroup (sound effect) is enabled. The default is enabled. Only available on 5.0.0+.
* @brief Sets whether the specified SeGroup (sound effect) is enabled. The default is enabled.
* @note \ref swkbdInlineUpdate must be called at some point afterwards for this to take affect. If called again with a different seGroup, \ref swkbdInlineUpdate must be called prior to calling this again.
* @note Only available on [5.0.0+].
* @param s SwkbdInline object.
* @param seGroup SeGroup
* @param flag Flag
@ -677,8 +844,9 @@ void swkbdInlineSetDirectionalButtonAssignFlag(SwkbdInline* s, bool flag);
void swkbdInlineSetSeGroup(SwkbdInline* s, u8 seGroup, bool flag);
/**
* @brief Sets whether the backspace button is enabled. The default is enabled. Only available on 5.0.0+.
* @brief Sets whether the backspace button is enabled. The default is enabled.
* @note \ref swkbdInlineUpdate must be called at some point afterwards for this to take affect.
* @note Only available on [5.0.0+].
* @param s SwkbdInline object.
* @param flag Flag
*/

View File

@ -47,12 +47,14 @@ static void _swkbdClampFloat(float *val) {
static void _swkbdConfigClear(SwkbdConfig* c) {
memset(&c->arg.arg, 0, sizeof(c->arg.arg));
memset(c->arg.unk_x3e0, 0xff, sizeof(c->arg.unk_x3e0));
memset(c->arg.textGrouping, 0xff, sizeof(c->arg.textGrouping));
}
static void _swkbdInitVersion(u32* version) {
u32 hosver = hosversionGet();
if (hosver >= MAKEHOSVERSION(5,0,0))
if (hosver >= MAKEHOSVERSION(6,0,0))
*version = 0x6000B;
else if (hosver >= MAKEHOSVERSION(5,0,0))
*version = 0x50009;
else if (hosver >= MAKEHOSVERSION(4,0,0))
*version = 0x40008;
@ -95,82 +97,82 @@ void swkbdClose(SwkbdConfig* c) {
void swkbdConfigMakePresetDefault(SwkbdConfig* c) {
_swkbdConfigClear(c);
c->arg.arg.type = SwkbdType_QWERTY;
c->arg.arg.initialCursorPos = 1;
if (c->version < 0x50009) c->arg.arg.textDrawType = SwkbdTextDrawType_Box;//removed with 5.x
c->arg.arg.returnButtonFlag = 1;
c->arg.arg.blurBackground = 1;
swkbdConfigSetType(c, SwkbdType_QWERTY);
swkbdConfigSetInitialCursorPos(c, 1);
if (c->version < 0x50009) swkbdConfigSetTextDrawType(c, SwkbdTextDrawType_Box);//removed with 5.x
swkbdConfigSetReturnButtonFlag(c, 1);
swkbdConfigSetBlurBackground(c, 1);
}
void swkbdConfigMakePresetPassword(SwkbdConfig* c) {
_swkbdConfigClear(c);
c->arg.arg.type = SwkbdType_QWERTY;
c->arg.arg.initialCursorPos = 1;
c->arg.arg.passwordFlag = 1;
c->arg.arg.blurBackground = 1;
swkbdConfigSetType(c, SwkbdType_QWERTY);
swkbdConfigSetInitialCursorPos(c, 1);
swkbdConfigSetPasswordFlag(c, 1);
swkbdConfigSetBlurBackground(c, 1);
}
void swkbdConfigMakePresetUserName(SwkbdConfig* c) {
_swkbdConfigClear(c);
c->arg.arg.type = SwkbdType_Normal;
c->arg.arg.keySetDisableBitmask = SwkbdKeyDisableBitmask_UserName;
c->arg.arg.initialCursorPos = 1;
c->arg.arg.blurBackground = 1;
swkbdConfigSetType(c, SwkbdType_Normal);
swkbdConfigSetKeySetDisableBitmask(c, SwkbdKeyDisableBitmask_UserName);
swkbdConfigSetInitialCursorPos(c, 1);
swkbdConfigSetBlurBackground(c, 1);
}
void swkbdConfigMakePresetDownloadCode(SwkbdConfig* c) {
_swkbdConfigClear(c);
c->arg.arg.type = SwkbdType_Normal;
c->arg.arg.keySetDisableBitmask = SwkbdKeyDisableBitmask_DownloadCode;
c->arg.arg.initialCursorPos = 1;
swkbdConfigSetType(c, SwkbdType_Normal);
swkbdConfigSetKeySetDisableBitmask(c, SwkbdKeyDisableBitmask_DownloadCode);
swkbdConfigSetInitialCursorPos(c, 1);
if (c->version >= 0x50009) {//5.x
c->arg.arg.type = SwkbdType_QWERTY;
swkbdConfigSetType(c, SwkbdType_QWERTY);
c->arg.arg.stringLenMax = 16;
c->arg.arg.stringLenMaxExt = 1;
c->arg.arg.textDrawType = SwkbdTextDrawType_DownloadCode;
swkbdConfigSetStringLenMax(c, 16);
swkbdConfigSetStringLenMaxExt(c, 1);
swkbdConfigSetTextDrawType(c, SwkbdTextDrawType_DownloadCode);
}
c->arg.arg.blurBackground = 1;
swkbdConfigSetBlurBackground(c, 1);
if (c->version >= 0x50009) {//5.x
c->arg.unk_x3e0[0] = 0x3;
c->arg.unk_x3e0[1] = 0x7;
c->arg.unk_x3e0[2] = 0xb;
swkbdConfigSetTextGrouping(c, 0, 0x3);
swkbdConfigSetTextGrouping(c, 1, 0x7);
swkbdConfigSetTextGrouping(c, 2, 0xb);
}
}
void swkbdConfigSetOkButtonText(SwkbdConfig* c, const char* str) {
_swkbdConvertToUTF16ByteSize(c->arg.arg.okButtonText, str, sizeof(c->arg.arg.okButtonText));
_swkbdConvertToUTF16ByteSize(c->arg.arg.arg.okButtonText, str, sizeof(c->arg.arg.arg.okButtonText));
}
void swkbdConfigSetLeftOptionalSymbolKey(SwkbdConfig* c, const char* str) {
_swkbdConvertToUTF16(&c->arg.arg.leftButtonText, str, 1);
_swkbdConvertToUTF16(&c->arg.arg.arg.leftButtonText, str, 1);
}
void swkbdConfigSetRightOptionalSymbolKey(SwkbdConfig* c, const char* str) {
_swkbdConvertToUTF16(&c->arg.arg.rightButtonText, str, 1);
_swkbdConvertToUTF16(&c->arg.arg.arg.rightButtonText, str, 1);
}
void swkbdConfigSetHeaderText(SwkbdConfig* c, const char* str) {
_swkbdConvertToUTF16ByteSize(c->arg.arg.headerText, str, sizeof(c->arg.arg.headerText));
_swkbdConvertToUTF16ByteSize(c->arg.arg.arg.headerText, str, sizeof(c->arg.arg.arg.headerText));
}
void swkbdConfigSetSubText(SwkbdConfig* c, const char* str) {
_swkbdConvertToUTF16ByteSize(c->arg.arg.subText, str, sizeof(c->arg.arg.subText));
_swkbdConvertToUTF16ByteSize(c->arg.arg.arg.subText, str, sizeof(c->arg.arg.arg.subText));
}
void swkbdConfigSetGuideText(SwkbdConfig* c, const char* str) {
_swkbdConvertToUTF16ByteSize(c->arg.arg.guideText, str, sizeof(c->arg.arg.guideText));
_swkbdConvertToUTF16ByteSize(c->arg.arg.arg.guideText, str, sizeof(c->arg.arg.arg.guideText));
}
void swkbdConfigSetInitialText(SwkbdConfig* c, const char* str) {
c->arg.arg.initialStringOffset = 0;
c->arg.arg.initialStringSize = 0;
c->arg.arg.arg.initialStringOffset = 0;
c->arg.arg.arg.initialStringSize = 0;
if (c->workbuf==NULL) return;
u32 offset=0x14;
@ -178,25 +180,33 @@ void swkbdConfigSetInitialText(SwkbdConfig* c, const char* str) {
ssize_t units = _swkbdConvertToUTF16ByteSize((u16*)&c->workbuf[offset], str, 0x1f4);
if (units<=0) return;
c->arg.arg.initialStringOffset = offset;
c->arg.arg.initialStringSize = units;
c->arg.arg.arg.initialStringOffset = offset;
c->arg.arg.arg.initialStringSize = units;
}
void swkbdConfigSetDictionary(SwkbdConfig* c, const SwkbdDictWord *buffer, s32 entries) {
c->arg.arg.userDicOffset = 0;
c->arg.arg.userDicEntries = 0;
c->arg.arg.arg.userDicOffset = 0;
c->arg.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;
c->arg.arg.arg.userDicOffset = offset;
c->arg.arg.arg.userDicEntries = entries;
memcpy(&c->workbuf[offset], buffer, entries*sizeof(SwkbdDictWord));
}
Result swkbdConfigSetCustomizedDictionaries(SwkbdConfig* c, const SwkbdCustomizedDictionarySet *dic) {
if (c->version < 0x6000B) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); // [6.0.0+]
memcpy(&c->customizedDictionarySet, dic, sizeof(*dic));
return 0;
}
void swkbdConfigSetTextCheckCallback(SwkbdConfig* c, SwkbdTextCheckCb cb) {
c->arg.arg.textCheckFlag = cb!=0;
c->arg.arg.arg.textCheckFlag = cb!=0;
c->arg.arg.textCheckCb = cb;
}
@ -214,7 +224,7 @@ static Result _swkbdProcessInteractive(SwkbdConfig* c, AppletHolder* h, uint16_t
if (R_SUCCEEDED(rc)) rc = appletStorageRead(&storage, sizeof(strsize), strbuf, strsize);
appletStorageClose(&storage);
if (R_SUCCEEDED(rc) && (c->arg.arg.textCheckFlag && c->arg.arg.textCheckCb)) {
if (R_SUCCEEDED(rc) && (c->arg.arg.arg.textCheckFlag && c->arg.arg.textCheckCb)) {
_swkbdConvertToUTF8(tmp_string, strbuf, tmp_string_size-1);
res = c->arg.arg.textCheckCb(tmp_string, tmp_string_size-1);
@ -257,12 +267,14 @@ Result swkbdShow(SwkbdConfig* c, char* out_string, size_t out_string_size) {
Result rc=0;
AppletHolder holder;
AppletStorage storage;
AppletStorage customizedDictionarySet_storage;
uint16_t* strbuf = NULL;
size_t strbuf_size = 0x7D4;
if (out_string==NULL || out_string_size==0) return MAKERESULT(Module_Libnx, LibnxError_BadInput);
memset(&storage, 0, sizeof(AppletStorage));
memset(&customizedDictionarySet_storage, 0, sizeof(customizedDictionarySet_storage));
strbuf = (u16*)malloc(strbuf_size+2);
if (strbuf==NULL) rc = MAKERESULT(Module_Libnx, LibnxError_OutOfMemory);
@ -280,9 +292,19 @@ Result swkbdShow(SwkbdConfig* c, char* out_string, size_t out_string_size) {
rc = libappletArgsPush(&commonargs, &holder);
if (R_SUCCEEDED(rc)) {
//3.0.0+ has a larger struct.
if (c->version < 0x30007) rc = libappletPushInData(&holder, &c->arg.arg, sizeof(c->arg.arg));
if (c->version >= 0x30007) rc = libappletPushInData(&holder, &c->arg, sizeof(c->arg));
if (c->version >= 0x6000B) {
SwkbdArgVB arg_vb;
memset(&arg_vb, 0, sizeof(arg_vb));
memcpy(&arg_vb.arg, &c->arg.arg.arg, sizeof(arg_vb.arg));
memcpy(arg_vb.textGrouping, c->arg.textGrouping, sizeof(arg_vb.textGrouping));
memcpy(arg_vb.entries, c->customizedDictionarySet.entries, sizeof(arg_vb.entries));
arg_vb.total_entries = c->customizedDictionarySet.total_entries;
rc = libappletPushInData(&holder, &arg_vb, sizeof(arg_vb));
}
else if (c->version >= 0x30007) rc = libappletPushInData(&holder, &c->arg, sizeof(c->arg)); // [3.0.0+] has a larger struct.
else rc = libappletPushInData(&holder, &c->arg.arg, sizeof(c->arg.arg));
}
if (R_SUCCEEDED(rc)) {
@ -290,6 +312,11 @@ Result swkbdShow(SwkbdConfig* c, char* out_string, size_t out_string_size) {
if (R_SUCCEEDED(rc)) rc = appletHolderPushInData(&holder, &storage);
}
if (R_SUCCEEDED(rc) && c->version >= 0x6000B && c->customizedDictionarySet.buffer_size && c->customizedDictionarySet.total_entries) { // [6.0.0+]
rc = appletCreateHandleStorageTmem(&customizedDictionarySet_storage, c->customizedDictionarySet.buffer, c->customizedDictionarySet.buffer_size);
if (R_SUCCEEDED(rc)) rc = appletHolderPushInData(&holder, &customizedDictionarySet_storage);
}
if (R_SUCCEEDED(rc)) rc = appletHolderStart(&holder);
if (R_SUCCEEDED(rc)) {
@ -317,6 +344,7 @@ Result swkbdShow(SwkbdConfig* c, char* out_string, size_t out_string_size) {
appletHolderClose(&holder);
appletStorageCloseTmem(&storage);
appletStorageCloseTmem(&customizedDictionarySet_storage);
free(strbuf);
@ -521,9 +549,11 @@ static void _swkbdProcessReply(SwkbdInline* s, SwkbdReplyType ReplyType, size_t
break;
case SwkbdReplyType_UnsetCustomizeDic:
case SwkbdReplyType_UnsetCustomizedDictionaries:
if (s->dicCustomInitialized) {
appletStorageCloseTmem(&s->dicStorage);
s->dicCustomInitialized = false;
s->customizedDictionariesInitialized = false;
}
break;
@ -631,15 +661,27 @@ static void _swkbdInlineUpdateAppearFlags(SwkbdInline* s) {
u32 tmp = s->calcArg.appearArg.flags;
if (!s->directionalButtonAssignFlag) tmp &= ~mask;
if (s->directionalButtonAssignFlag) tmp |= mask;
mask = 0x10000;
if (!s->calcArg.triggerFlag) tmp &= ~mask; // Official sw doesn't clear this bitmask.
if (s->calcArg.triggerFlag) tmp |= mask;
s->calcArg.appearArg.flags = tmp;
}
void swkbdInlineAppear(SwkbdInline* s, SwkbdAppearArg* arg) {
void swkbdInlineAppearEx(SwkbdInline* s, const SwkbdAppearArg* arg, u8 trigger) {
memcpy(&s->calcArg.appearArg, arg, sizeof(SwkbdAppearArg));
if (s->version < 0x6000B) trigger=0; // [6.0.0+]
s->calcArg.trigger = trigger;
s->calcArg.triggerFlag = s->calcArg.trigger!=0;
_swkbdInlineUpdateAppearFlags(s);
s->calcArg.flags = (s->calcArg.flags & ~0x80) | 0x4;
}
void swkbdInlineAppear(SwkbdInline* s, const SwkbdAppearArg* arg) {
swkbdInlineAppearEx(s, arg, 0);
}
void swkbdInlineDisappear(SwkbdInline* s) {
s->calcArg.flags = (s->calcArg.flags & ~0x4) | 0x80;
}
@ -760,6 +802,44 @@ void swkbdInlineUnsetCustomizeDic(SwkbdInline* s) {
s->calcArg.flags |= 0x40;
}
Result swkbdInlineSetCustomizedDictionaries(SwkbdInline* s, const SwkbdCustomizedDictionarySet *dic) {
Result rc=0;
u8 tmpdata[0xd0];
if (s->state > SwkbdState_Initialized || s->dicCustomInitialized) return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized);
if (s->version < 0x6000B) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); // [6.0.0+]
rc = appletCreateHandleStorageTmem(&s->dicStorage, dic->buffer, dic->buffer_size);
if (R_FAILED(rc)) return rc;
rc = appletHolderPushInteractiveInData(&s->holder, &s->dicStorage);
if (R_FAILED(rc)) {
appletStorageCloseTmem(&s->dicStorage);
return rc;
}
s->dicCustomInitialized = true;
s->customizedDictionariesInitialized = true;
memcpy(tmpdata, dic, sizeof(*dic));
tmpdata[0xce] = 0;
tmpdata[0xcf] = 0;
rc = _swkbdSendRequest(s, SwkbdRequestCommand_SetCustomizedDictionaries, tmpdata, sizeof(tmpdata));
return rc;
}
Result swkbdInlineUnsetCustomizedDictionaries(SwkbdInline* s) {
Result rc=0;
if (s->state > SwkbdState_Initialized || !s->dicCustomInitialized || !s->customizedDictionariesInitialized) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (s->version < 0x6000B) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); // [6.0.0+]
rc = _swkbdSendRequest(s, SwkbdRequestCommand_UnsetCustomizedDictionaries, NULL, 0);
return rc;
}
void swkbdInlineSetInputModeFadeType(SwkbdInline* s, u8 type) {
if (s->calcArg.inputModeFadeType == type) return;
s->calcArg.inputModeFadeType = type;
@ -828,17 +908,20 @@ void swkbdInlineSetUSBKeyboardFlag(SwkbdInline* s, bool flag) {
}
void swkbdInlineSetDirectionalButtonAssignFlag(SwkbdInline* s, bool flag) {
if (s->version < 0x40008) return; // [4.0.0+]
s->directionalButtonAssignFlag = flag;
_swkbdInlineUpdateAppearFlags(s);
s->calcArg.flags |= 0x1000;
}
void swkbdInlineSetSeGroup(SwkbdInline* s, u8 seGroup, bool flag) {
if (s->version < 0x50009) return; // [5.0.0+]
s->calcArg.seGroup = seGroup;
s->calcArg.flags |= flag ? 0x2000 : 0x4000;
}
void swkbdInlineSetBackspaceFlag(SwkbdInline* s, bool flag) {
if (s->version < 0x50009) return; // [5.0.0+]
s->calcArg.enableBackspace = flag!=0;
s->calcArg.flags |= 0x8000;
}