Added swkbdInlineSetUserWordInfo/swkbdInlineUnsetUserWordInfo. Handle storage-tmem closing in _swkbdProcessReply. Better CustomizeDic handling. Other changes.

This commit is contained in:
yellows8 2019-01-22 22:29:48 -05:00
parent 4a119e4028
commit 6b91ac26a5
2 changed files with 132 additions and 29 deletions

View File

@ -43,6 +43,7 @@ typedef enum {
/// SwkbdInline Interactive input storage request ID.
typedef enum {
SwkbdRequestCommand_Finalize = 0x4,
SwkbdRequestCommand_SetUserWordInfo = 0x6,
SwkbdRequestCommand_SetCustomizeDic = 0x7,
SwkbdRequestCommand_Calc = 0xA,
} SwkbdRequestCommand;
@ -251,6 +252,9 @@ typedef struct {
bool dicCustomInitialized;
AppletStorage dicStorage;
bool wordInfoInitialized;
AppletStorage wordInfoStorage;
u8* interactive_tmpbuf;
size_t interactive_tmpbuf_size;
char* interactive_strbuf;
@ -505,6 +509,26 @@ void swkbdInlineSetInputText(SwkbdInline* s, const char* str);
*/
void swkbdInlineSetCursorPos(SwkbdInline* s, s32 pos);
/**
* @brief Sets the UserWordInfo.
* @note Not avilable when \ref SwkbdState is above \ref SwkbdState_Initialized. Can't be used if this was already used previously.
* @note The specified buffer must not be used after this, until \ref swkbdInlineClose is used.
* @note \ref swkbdInlineUpdate must be called at some point afterwards.
* @note If input==NULL or total_entries==0, this will just call \ref swkbdInlineUnsetUserWordInfo internally.
* @param s SwkbdInline object.
* @param input Input data.
* @param entries Total entries in the buffer.
*/
Result swkbdInlineSetUserWordInfo(SwkbdInline* s, const SwkbdDictWord *input, s32 entries);
/**
* @brief Request UnsetUserWordInfo.
* @note \ref swkbdInlineUpdate must be called at some point afterwards for this to take affect.
* @note Not avilable when \ref SwkbdState is above \ref SwkbdState_Initialized.
* @param s SwkbdInline object.
*/
Result swkbdInlineUnsetUserWordInfo(SwkbdInline* s);
/**
* @brief Sets the utf8Mode.
* @note \ref swkbdInlineUpdate must be called at some point afterwards for this to take affect.
@ -517,7 +541,7 @@ void swkbdInlineSetUtf8Mode(SwkbdInline* s, bool flag);
/**
* @brief Sets the CustomizeDic.
* @note Not avilable when \ref SwkbdState is above \ref SwkbdState_Initialized. Can't be used if this was already used previously.
* @note The specified buffer must not be used after this, until \ref swkbdInlineClose is used.
* @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.
* @param size 0x1000-byte aligned buffer size.

View File

@ -9,6 +9,8 @@
#include "applets/swkbd.h"
#include "runtime/util/utf.h"
static Result _swkbdGetReplies(SwkbdInline* s);
static void _swkbdConvertToUTF8(char* out, const u16* in, size_t max) {
if (out==NULL || in==NULL) return;
out[0] = 0;
@ -76,7 +78,7 @@ Result swkbdCreate(SwkbdConfig* c, s32 max_dictwords) {
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->max_dictwords*sizeof(SwkbdDictWord) + 0x7e8;
c->workbuf_size = (c->workbuf_size + 0xfff) & ~0xfff;
}
@ -192,7 +194,7 @@ void swkbdConfigSetDictionary(SwkbdConfig* c, const SwkbdDictWord *buffer, s32 e
c->arg.arg.userDicOffset = offset;
c->arg.arg.userDicEntries = entries;
memcpy(&c->workbuf[offset], buffer, entries*0x64);
memcpy(&c->workbuf[offset], buffer, entries*sizeof(SwkbdDictWord));
}
void swkbdConfigSetTextCheckCallback(SwkbdConfig* c, SwkbdTextCheckCb cb) {
@ -406,15 +408,28 @@ Result swkbdInlineClose(SwkbdInline* s) {
{
_swkbdSendRequest(s, SwkbdRequestCommand_Finalize, NULL, 0);//Finalize cmd
int cnt=0;
while (s->dicCustomInitialized && cnt<9) {
rc = _swkbdGetReplies(s);
if (R_FAILED(rc)) break;
if (s->dicCustomInitialized) {
cnt++;
svcSleepThread(100000000ULL);
}
}
appletHolderJoin(&s->holder);
LibAppletExitReason reason = appletHolderGetExitReason(&s->holder);
if (R_SUCCEEDED(rc)) {
LibAppletExitReason reason = appletHolderGetExitReason(&s->holder);
if (reason == LibAppletExitReason_Canceled) {
rc = MAKERESULT(Module_Libnx, LibnxError_LibAppletBadExit);
}
else if (reason == LibAppletExitReason_Abnormal || reason == LibAppletExitReason_Unexpected) {
rc = MAKERESULT(Module_Libnx, LibnxError_LibAppletBadExit);
if (reason == LibAppletExitReason_Canceled) {
rc = MAKERESULT(Module_Libnx, LibnxError_LibAppletBadExit);
}
else if (reason == LibAppletExitReason_Abnormal || reason == LibAppletExitReason_Unexpected) {
rc = MAKERESULT(Module_Libnx, LibnxError_LibAppletBadExit);
}
}
appletHolderClose(&s->holder);
@ -427,7 +442,8 @@ Result swkbdInlineClose(SwkbdInline* s) {
s->interactive_strbuf = NULL;
s->interactive_strbuf_size = 0;
appletStorageCloseTmem(&s->dicStorage);
if (s->dicCustomInitialized) appletStorageCloseTmem(&s->dicStorage);
if (s->wordInfoInitialized) appletStorageCloseTmem(&s->wordInfoStorage);
memset(s, 0, sizeof(SwkbdInline));
@ -503,8 +519,20 @@ static void _swkbdProcessReply(SwkbdInline* s, SwkbdReplyType ReplyType, size_t
}
break;
case SwkbdReplyType_UnsetCustomizeDic:
if (s->dicCustomInitialized) {
appletStorageCloseTmem(&s->dicStorage);
s->dicCustomInitialized = false;
}
break;
case SwkbdReplyType_ReleasedUserWordInfo:
if (s->releasedUserWordInfoCb) s->releasedUserWordInfoCb();
if (s->wordInfoInitialized) {
appletStorageCloseTmem(&s->wordInfoStorage);
s->wordInfoInitialized = false;
}
break;
default:
@ -512,11 +540,34 @@ static void _swkbdProcessReply(SwkbdInline* s, SwkbdReplyType ReplyType, size_t
}
}
Result swkbdInlineUpdate(SwkbdInline* s, SwkbdState* out_state) {
static Result _swkbdGetReplies(SwkbdInline* s) {
Result rc=0;
AppletStorage storage;
SwkbdReplyType ReplyType=0;
while(R_SUCCEEDED(appletHolderPopInteractiveOutData(&s->holder, &storage))) {
s64 tmpsize=0;
rc = appletStorageGetSize(&storage, &tmpsize);
memset(s->interactive_tmpbuf, 0, s->interactive_tmpbuf_size);
if (R_SUCCEEDED(rc) && (tmpsize < 8 || tmpsize-8 > s->interactive_tmpbuf_size)) rc = MAKERESULT(Module_Libnx, LibnxError_BadInput);
if (R_SUCCEEDED(rc)) rc = appletStorageRead(&storage, 0x0, &s->state, sizeof(s->state));
if (R_SUCCEEDED(rc)) rc = appletStorageRead(&storage, 0x4, &ReplyType, sizeof(u32));
if (R_SUCCEEDED(rc) && tmpsize >= 8) rc = appletStorageRead(&storage, 0x8, s->interactive_tmpbuf, tmpsize-8);
appletStorageClose(&storage);
if (R_FAILED(rc)) break;
_swkbdProcessReply(s, ReplyType, tmpsize-8);
}
return rc;
}
Result swkbdInlineUpdate(SwkbdInline* s, SwkbdState* out_state) {
Result rc=0;
u8 fadetype=0;
if (s->calcArg.footerScalable) {
swkbdInlineSetFooterBgAlpha(s, s->calcArg.keytopBgAlpha);
@ -543,22 +594,7 @@ Result swkbdInlineUpdate(SwkbdInline* s, SwkbdState* out_state) {
if (R_FAILED(rc)) return rc;
}
while(R_SUCCEEDED(appletHolderPopInteractiveOutData(&s->holder, &storage))) {
s64 tmpsize=0;
rc = appletStorageGetSize(&storage, &tmpsize);
memset(s->interactive_tmpbuf, 0, s->interactive_tmpbuf_size);
if (R_SUCCEEDED(rc) && (tmpsize < 8 || tmpsize-8 > s->interactive_tmpbuf_size)) rc = MAKERESULT(Module_Libnx, LibnxError_BadInput);
if (R_SUCCEEDED(rc)) rc = appletStorageRead(&storage, 0x0, &s->state, sizeof(s->state));
if (R_SUCCEEDED(rc)) rc = appletStorageRead(&storage, 0x4, &ReplyType, sizeof(u32));
if (R_SUCCEEDED(rc) && tmpsize >= 8) rc = appletStorageRead(&storage, 0x8, s->interactive_tmpbuf, tmpsize-8);
appletStorageClose(&storage);
if (R_FAILED(rc)) break;
_swkbdProcessReply(s, ReplyType, tmpsize-8);
}
rc = _swkbdGetReplies(s);
if (out_state) *out_state = s->state;
@ -674,6 +710,45 @@ void swkbdInlineSetCursorPos(SwkbdInline* s, s32 pos) {
s->calcArg.flags |= 0x10;
}
Result swkbdInlineSetUserWordInfo(SwkbdInline* s, const SwkbdDictWord *input, s32 entries) {
Result rc=0;
size_t size=0;
if (s->state > SwkbdState_Initialized || s->wordInfoInitialized) return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized);
if (entries < 0 || entries > 0x3e8) return MAKERESULT(Module_Libnx, LibnxError_BadInput);
if (input==NULL || entries==0) return swkbdInlineUnsetUserWordInfo(s);
size = size*sizeof(SwkbdDictWord) + 0x8;
size = (size + 0xfff) & ~0xfff;
rc = appletCreateTransferMemoryStorage(&s->wordInfoStorage, NULL, size, true);
if (R_FAILED(rc)) return rc;
u32 req = SwkbdRequestCommand_SetUserWordInfo;
rc = appletStorageWrite(&s->wordInfoStorage, 0x0, &req, sizeof(req));
if (R_SUCCEEDED(rc)) rc = appletStorageWrite(&s->wordInfoStorage, 0x4, &entries, sizeof(entries));
if (R_SUCCEEDED(rc) && entries>0) rc = appletStorageWrite(&s->wordInfoStorage, 0x8, input, sizeof(SwkbdDictWord) * entries);
if (R_SUCCEEDED(rc)) rc = appletHolderPushInteractiveInData(&s->holder, &s->wordInfoStorage);
if (R_FAILED(rc)) appletStorageCloseTmem(&s->wordInfoStorage);
if (R_SUCCEEDED(rc)) {
s->wordInfoInitialized = true;
s->calcArg.flags &= ~0x400;
}
return rc;
}
Result swkbdInlineUnsetUserWordInfo(SwkbdInline* s) {
if (s->state > SwkbdState_Initialized) return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized);
if (!s->wordInfoInitialized) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
s->calcArg.flags |= 0x400;
return 0;
}
static void _swkbdInlineSetBoolFlag(SwkbdInline* s, u8* arg, bool flag, u64 bitmask) {
u8 tmp = flag!=0;
if (*arg == tmp) return;
@ -696,9 +771,13 @@ Result swkbdInlineSetCustomizeDic(SwkbdInline* s, void* buffer, size_t size, Swk
rc = appletCreateHandleStorageTmem(&s->dicStorage, buffer, size);
if (R_FAILED(rc)) return rc;
s->dicCustomInitialized = true;
rc = appletHolderPushInteractiveInData(&s->holder, &s->dicStorage);
if (R_FAILED(rc)) return rc;
if (R_FAILED(rc)) {
appletStorageCloseTmem(&s->dicStorage);
return rc;
}
s->dicCustomInitialized = true;
rc = _swkbdSendRequest(s, SwkbdRequestCommand_SetCustomizeDic, info, sizeof(SwkbdCustomizeDicInfo));