From 03804e0ff4cdf928e3134f0334d60303421f83e4 Mon Sep 17 00:00:00 2001 From: VDm Date: Mon, 9 Dec 2024 22:10:40 +0400 Subject: [PATCH 1/9] chore(ui): add CSimpleFrame_SetBackdropColor and CSimpleFrame_SetBackdropBorderColor --- src/net/connection/RealmConnection.cpp | 2 +- src/ui/CBackdropGenerator.cpp | 7 +++++ src/ui/CBackdropGenerator.hpp | 1 + src/ui/CSimpleFrame.cpp | 14 ++++++++- src/ui/CSimpleFrame.hpp | 1 + src/ui/CSimpleFrameScript.cpp | 43 ++++++++++++++++++++++++-- 6 files changed, 64 insertions(+), 4 deletions(-) diff --git a/src/net/connection/RealmConnection.cpp b/src/net/connection/RealmConnection.cpp index 64d5c48..345686d 100644 --- a/src/net/connection/RealmConnection.cpp +++ b/src/net/connection/RealmConnection.cpp @@ -110,7 +110,7 @@ int32_t RealmConnection::HandleAuthChallenge(AuthenticationChallenge* challenge) // TODO switch to WDataStore CDataStore msg; - uint32_t localChallenge; + uint32_t localChallenge = 0; msg.Put(static_cast(CMSG_AUTH_SESSION)); diff --git a/src/ui/CBackdropGenerator.cpp b/src/ui/CBackdropGenerator.cpp index 5be5ac0..467b472 100644 --- a/src/ui/CBackdropGenerator.cpp +++ b/src/ui/CBackdropGenerator.cpp @@ -152,6 +152,13 @@ void CBackdropGenerator::LoadXML(XMLNode* node, CStatus* status) { } } +void CBackdropGenerator::SetVertexColor(const CImVector& color) { + this->m_color = color; + if (this->m_backgroundTexture) { + this->m_backgroundTexture->SetVertexColor(color); + } +} + void CBackdropGenerator::SetBorderVertexColor(const CImVector& borderColor) { this->m_borderColor = borderColor; diff --git a/src/ui/CBackdropGenerator.hpp b/src/ui/CBackdropGenerator.hpp index 06f248e..ce9fca6 100644 --- a/src/ui/CBackdropGenerator.hpp +++ b/src/ui/CBackdropGenerator.hpp @@ -42,6 +42,7 @@ class CBackdropGenerator { CBackdropGenerator(); void Generate(const CRect* rect); void LoadXML(XMLNode* node, CStatus* status); + void SetVertexColor(const CImVector& color); void SetBorderVertexColor(const CImVector& borderColor); void SetOutput(CSimpleFrame* frame); }; diff --git a/src/ui/CSimpleFrame.cpp b/src/ui/CSimpleFrame.cpp index f0ef022..6aa167a 100644 --- a/src/ui/CSimpleFrame.cpp +++ b/src/ui/CSimpleFrame.cpp @@ -1327,7 +1327,19 @@ void CSimpleFrame::SetBeingScrolled(int32_t a2, int32_t a3) { } void CSimpleFrame::SetFrameAlpha(uint8_t alpha) { - // TODO + if (this->m_alpha == alpha) { + return; + } + + this->m_alpha = alpha; + + for (auto region = this->m_regions.Head(); region; region = this->m_regions.Link(region)->Next()) { + region->OnColorChanged(true); + } + + for (auto child = this->m_children.Head(); child; child = this->m_children.Link(child)->Next()) { + child->frame->SetFrameAlpha(alpha); + } } void CSimpleFrame::SetFrameFlag(int32_t flag, int32_t on) { diff --git a/src/ui/CSimpleFrame.hpp b/src/ui/CSimpleFrame.hpp index 02eb4ab..86fd306 100644 --- a/src/ui/CSimpleFrame.hpp +++ b/src/ui/CSimpleFrame.hpp @@ -37,6 +37,7 @@ class CSimpleFrame : public CScriptRegion { float m_depth = 0.0; FRAME_STRATA m_strata = FRAME_STRATA_MEDIUM; int32_t m_level = 0; + uint8_t m_alpha = 255; uint32_t m_eventmask = 0; int32_t m_shown = 0; int32_t m_visible = 0; diff --git a/src/ui/CSimpleFrameScript.cpp b/src/ui/CSimpleFrameScript.cpp index dd9e075..752578f 100644 --- a/src/ui/CSimpleFrameScript.cpp +++ b/src/ui/CSimpleFrameScript.cpp @@ -2,6 +2,7 @@ #include "gx/Coordinate.hpp" #include "ui/CSimpleFrame.hpp" #include "ui/FrameScript.hpp" +#include "ui/CBackdropGenerator.hpp" #include "util/Lua.hpp" #include "util/Unimplemented.hpp" #include @@ -460,7 +461,26 @@ int32_t CSimpleFrame_GetBackdropColor(lua_State* L) { } int32_t CSimpleFrame_SetBackdropColor(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (lua_type(L, 1) != LUA_TTABLE) { + luaL_error(L, "Attempt to find 'this' in non-table object (used '.' instead of ':' ?)"); + } + + lua_rawgeti(L, 1, 0); + auto object = reinterpret_cast(lua_touserdata(L, -1)); + lua_settop(L, -2); + + STORM_ASSERT(object); + + CImVector color; + auto red = lua_tonumber(L, 2); + auto green = lua_tonumber(L, 3); + auto blue = lua_tonumber(L, 4); + auto alpha = lua_isnumber(L, 5) ? lua_tonumber(L, 5) : 1.0; + color.Set(alpha, red, green, blue); + + if (object->m_backdrop) { + object->m_backdrop->SetVertexColor(color); + } } int32_t CSimpleFrame_GetBackdropBorderColor(lua_State* L) { @@ -468,7 +488,26 @@ int32_t CSimpleFrame_GetBackdropBorderColor(lua_State* L) { } int32_t CSimpleFrame_SetBackdropBorderColor(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (lua_type(L, 1) != LUA_TTABLE) { + luaL_error(L, "Attempt to find 'this' in non-table object (used '.' instead of ':' ?)"); + } + + lua_rawgeti(L, 1, 0); + auto object = reinterpret_cast(lua_touserdata(L, -1)); + lua_settop(L, -2); + + STORM_ASSERT(object); + + CImVector color; + auto red = lua_tonumber(L, 2); + auto green = lua_tonumber(L, 3); + auto blue = lua_tonumber(L, 4); + auto alpha = lua_isnumber(L, 5) ? lua_tonumber(L, 5) : 1.0; + color.Set(alpha, red, green, blue); + + if (object->m_backdrop) { + object->m_backdrop->SetBorderVertexColor(color); + } } int32_t CSimpleFrame_SetDepth(lua_State* L) { From 382d9629006344065ec634efcf7d095088926067 Mon Sep 17 00:00:00 2001 From: VDm Date: Tue, 10 Dec 2024 00:12:26 +0400 Subject: [PATCH 2/9] feat(ui): add temporary solution for CSimpleFontString_SetFormattedText --- src/ui/CSimpleEditBoxScript.cpp | 27 +++- src/ui/CSimpleFontStringScript.cpp | 175 ++++++++++++++++++++- src/ui/CSimpleFrameScript.cpp | 4 + src/ui/ScriptFunctionsGlueScriptEvents.cpp | 11 +- 4 files changed, 212 insertions(+), 5 deletions(-) diff --git a/src/ui/CSimpleEditBoxScript.cpp b/src/ui/CSimpleEditBoxScript.cpp index 7b98f94..d24ad96 100644 --- a/src/ui/CSimpleEditBoxScript.cpp +++ b/src/ui/CSimpleEditBoxScript.cpp @@ -176,11 +176,34 @@ int32_t CSimpleEditBox_GetTextInsets(lua_State* L) { } int32_t CSimpleEditBox_SetFocus(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (lua_type(L, 1) != LUA_TTABLE) { + luaL_error(L, "Attempt to find 'this' in non-table object (used '.' instead of ':' ?)"); + } + + lua_rawgeti(L, 1, 0); + auto object = reinterpret_cast(lua_touserdata(L, -1)); + lua_settop(L, -2); + + STORM_ASSERT(object); + + CSimpleEditBox::SetKeyboardFocus(object); + return 0; } int32_t CSimpleEditBox_ClearFocus(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (lua_type(L, 1) != LUA_TTABLE) { + luaL_error(L, "Attempt to find 'this' in non-table object (used '.' instead of ':' ?)"); + } + + lua_rawgeti(L, 1, 0); + auto object = reinterpret_cast(lua_touserdata(L, -1)); + lua_settop(L, -2); + + STORM_ASSERT(object); + + // TODO + // CSimpleEditBox::ClearKeyboardFocus(object); + return 0; } int32_t CSimpleEditBox_HasFocus(lua_State* L) { diff --git a/src/ui/CSimpleFontStringScript.cpp b/src/ui/CSimpleFontStringScript.cpp index f789928..489e9e5 100644 --- a/src/ui/CSimpleFontStringScript.cpp +++ b/src/ui/CSimpleFontStringScript.cpp @@ -4,6 +4,162 @@ #include "util/Lua.hpp" #include "util/Unimplemented.hpp" #include +#include + + +// TEMPORARY SOLUTION (based on lstrlib.c from LUA) +/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ +#define MAX_ITEM 512 +/* valid flags in a format specification */ +#define FLAGS "-+ #0" +/* +** maximum size of each format specification (such as '%-099.99d') +** (+10 accounts for %99.99x plus margin of error) +*/ +#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) + +#define uchar(c) ((unsigned char)(c)) + + +static void addchar(char* b, char ch) { + auto len = strlen(b); + b[len++] = ch; + b[len] = '\0'; +} + +static void addquoted(lua_State* L, char* b, int arg) { + size_t l; + const char* s = luaL_checklstring(L, arg, &l); + addchar(b, '"'); + while (l--) { + switch (*s) { + case '"': + case '\\': + case '\n': { + addchar(b, '\\'); + addchar(b, *s); + break; + } + case '\r': { + strcat(b, "\\r"); + break; + } + case '\0': { + strcat(b, "\\000"); + break; + } + default: { + addchar(b, *s); + break; + } + } + s++; + } + addchar(b, '"'); +} + +static const char* scanformat(lua_State* L, const char* strfrmt, char* form) { + const char* p = strfrmt; + while (*p != '\0' && strchr(FLAGS, *p) != NULL) + p++; /* skip flags */ + if ((size_t)(p - strfrmt) >= sizeof(FLAGS)) + luaL_error(L, "invalid format (repeated flags)"); + if (isdigit(uchar(*p))) + p++; /* skip width */ + if (isdigit(uchar(*p))) + p++; /* (2 digits at most) */ + if (*p == '.') { + p++; + if (isdigit(uchar(*p))) + p++; /* skip precision */ + if (isdigit(uchar(*p))) + p++; /* (2 digits at most) */ + } + if (isdigit(uchar(*p))) + luaL_error(L, "invalid format (width or precision too long)"); + *(form++) = '%'; + strncpy(form, strfrmt, p - strfrmt + 1); + form += p - strfrmt + 1; + *form = '\0'; + return p; +} + +static void addintlen(char* form) { + size_t l = strlen(form); + char spec = form[l - 1]; + strcpy(form + l - 1, LUA_INTFRMLEN); + form[l + sizeof(LUA_INTFRMLEN) - 2] = spec; + form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0'; +} + +static int str_format(lua_State* L, char* b) { + int arg = 2; + size_t sfl; + const char* strfrmt = luaL_checklstring(L, arg, &sfl); + const char* strfrmt_end = strfrmt + sfl; + while (strfrmt < strfrmt_end) { + if (*strfrmt != '%') + addchar(b, *strfrmt++); + else if (*++strfrmt == '%') + addchar(b, *strfrmt++); /* %% */ + else { /* format item */ + char form[MAX_FORMAT]; /* to store the format (`%...') */ + char buff[MAX_ITEM]; /* to store the formatted item */ + arg++; + strfrmt = scanformat(L, strfrmt, form); + switch (*strfrmt++) { + case 'c': { + sprintf(buff, form, (int)luaL_checknumber(L, arg)); + break; + } + case 'd': + case 'i': { + addintlen(form); + sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); + break; + } + case 'o': + case 'u': + case 'x': + case 'X': { + addintlen(form); + sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); + break; + } + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': { + sprintf(buff, form, (double)luaL_checknumber(L, arg)); + break; + } + case 'q': { + addquoted(L, b, arg); + continue; /* skip the 'addsize' at the end */ + } + case 's': { + size_t l; + const char* s = luaL_checklstring(L, arg, &l); + if (!strchr(form, '.') && l >= 100) { + /* no precision and string is too long to be formatted; + keep original string */ + continue; /* skip the `addsize' at the end */ + } else { + sprintf(buff, form, s); + break; + } + } + default: { /* also treat cases `pnLlh' */ + return luaL_error(L, "invalid option " LUA_QL("%%%c") " to " LUA_QL("format"), *(strfrmt - 1)); + } + } + strcat(b, buff); + } + } + return 1; +} +// END OF TEMPORARY SOLUTION int32_t CSimpleFontString_IsObjectType(lua_State* L) { WHOA_UNIMPLEMENTED(0); @@ -132,7 +288,24 @@ int32_t CSimpleFontString_SetText(lua_State* L) { } int32_t CSimpleFontString_SetFormattedText(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (lua_type(L, 1) != LUA_TTABLE) { + luaL_error(L, "Attempt to find 'this' in non-table object (used '.' instead of ':' ?)"); + return 0; + } + + auto type = CSimpleFontString::GetObjectType(); + auto string = static_cast(FrameScript_GetObjectThis(L, type)); + + if (!string->m_font) { + luaL_error(L, "%s:SetText(): Font not set", string->GetDisplayName()); + return 0; + } + + char b[2048] = {}; + str_format(L, b); + string->SetText(b, 0); + + return 0; } int32_t CSimpleFontString_GetTextColor(lua_State* L) { diff --git a/src/ui/CSimpleFrameScript.cpp b/src/ui/CSimpleFrameScript.cpp index 752578f..470035e 100644 --- a/src/ui/CSimpleFrameScript.cpp +++ b/src/ui/CSimpleFrameScript.cpp @@ -481,6 +481,8 @@ int32_t CSimpleFrame_SetBackdropColor(lua_State* L) { if (object->m_backdrop) { object->m_backdrop->SetVertexColor(color); } + + return 0; } int32_t CSimpleFrame_GetBackdropBorderColor(lua_State* L) { @@ -508,6 +510,8 @@ int32_t CSimpleFrame_SetBackdropBorderColor(lua_State* L) { if (object->m_backdrop) { object->m_backdrop->SetBorderVertexColor(color); } + + return 0; } int32_t CSimpleFrame_SetDepth(lua_State* L) { diff --git a/src/ui/ScriptFunctionsGlueScriptEvents.cpp b/src/ui/ScriptFunctionsGlueScriptEvents.cpp index 376524a..e97945e 100644 --- a/src/ui/ScriptFunctionsGlueScriptEvents.cpp +++ b/src/ui/ScriptFunctionsGlueScriptEvents.cpp @@ -19,7 +19,12 @@ int32_t Script_IsShiftKeyDown(lua_State* L) { } int32_t Script_GetBuildInfo(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + lua_pushstring(L, "WHOA"); + lua_pushstring(L, "Release"); + lua_pushstring(L, "3.3.5"); + lua_pushstring(L, "12340"); + lua_pushstring(L, "Jun 24 2010"); + return 5; } int32_t Script_GetLocale(lua_State* L) { @@ -27,7 +32,9 @@ int32_t Script_GetLocale(lua_State* L) { } int32_t Script_GetSavedAccountName(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + // TODO + lua_pushstring(L, ""); + return 1; } int32_t Script_SetSavedAccountName(lua_State* L) { From 02e683d699fb3e2fa341880d0107ef045aaadb9e Mon Sep 17 00:00:00 2001 From: VDm Date: Tue, 10 Dec 2024 01:34:59 +0400 Subject: [PATCH 3/9] feat(script): implement FrameScript_Sprintf --- src/ui/CSimpleFontStringScript.cpp | 160 +--------------- src/ui/FrameScript.cpp | 211 +++++++++++++++++++++ src/ui/FrameScript.hpp | 2 + src/ui/ScriptFunctionsGlueScriptEvents.cpp | 7 +- 4 files changed, 221 insertions(+), 159 deletions(-) diff --git a/src/ui/CSimpleFontStringScript.cpp b/src/ui/CSimpleFontStringScript.cpp index 489e9e5..247918b 100644 --- a/src/ui/CSimpleFontStringScript.cpp +++ b/src/ui/CSimpleFontStringScript.cpp @@ -7,160 +7,6 @@ #include -// TEMPORARY SOLUTION (based on lstrlib.c from LUA) -/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ -#define MAX_ITEM 512 -/* valid flags in a format specification */ -#define FLAGS "-+ #0" -/* -** maximum size of each format specification (such as '%-099.99d') -** (+10 accounts for %99.99x plus margin of error) -*/ -#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) - -#define uchar(c) ((unsigned char)(c)) - - -static void addchar(char* b, char ch) { - auto len = strlen(b); - b[len++] = ch; - b[len] = '\0'; -} - -static void addquoted(lua_State* L, char* b, int arg) { - size_t l; - const char* s = luaL_checklstring(L, arg, &l); - addchar(b, '"'); - while (l--) { - switch (*s) { - case '"': - case '\\': - case '\n': { - addchar(b, '\\'); - addchar(b, *s); - break; - } - case '\r': { - strcat(b, "\\r"); - break; - } - case '\0': { - strcat(b, "\\000"); - break; - } - default: { - addchar(b, *s); - break; - } - } - s++; - } - addchar(b, '"'); -} - -static const char* scanformat(lua_State* L, const char* strfrmt, char* form) { - const char* p = strfrmt; - while (*p != '\0' && strchr(FLAGS, *p) != NULL) - p++; /* skip flags */ - if ((size_t)(p - strfrmt) >= sizeof(FLAGS)) - luaL_error(L, "invalid format (repeated flags)"); - if (isdigit(uchar(*p))) - p++; /* skip width */ - if (isdigit(uchar(*p))) - p++; /* (2 digits at most) */ - if (*p == '.') { - p++; - if (isdigit(uchar(*p))) - p++; /* skip precision */ - if (isdigit(uchar(*p))) - p++; /* (2 digits at most) */ - } - if (isdigit(uchar(*p))) - luaL_error(L, "invalid format (width or precision too long)"); - *(form++) = '%'; - strncpy(form, strfrmt, p - strfrmt + 1); - form += p - strfrmt + 1; - *form = '\0'; - return p; -} - -static void addintlen(char* form) { - size_t l = strlen(form); - char spec = form[l - 1]; - strcpy(form + l - 1, LUA_INTFRMLEN); - form[l + sizeof(LUA_INTFRMLEN) - 2] = spec; - form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0'; -} - -static int str_format(lua_State* L, char* b) { - int arg = 2; - size_t sfl; - const char* strfrmt = luaL_checklstring(L, arg, &sfl); - const char* strfrmt_end = strfrmt + sfl; - while (strfrmt < strfrmt_end) { - if (*strfrmt != '%') - addchar(b, *strfrmt++); - else if (*++strfrmt == '%') - addchar(b, *strfrmt++); /* %% */ - else { /* format item */ - char form[MAX_FORMAT]; /* to store the format (`%...') */ - char buff[MAX_ITEM]; /* to store the formatted item */ - arg++; - strfrmt = scanformat(L, strfrmt, form); - switch (*strfrmt++) { - case 'c': { - sprintf(buff, form, (int)luaL_checknumber(L, arg)); - break; - } - case 'd': - case 'i': { - addintlen(form); - sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); - break; - } - case 'o': - case 'u': - case 'x': - case 'X': { - addintlen(form); - sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); - break; - } - case 'e': - case 'E': - case 'f': - case 'g': - case 'G': { - sprintf(buff, form, (double)luaL_checknumber(L, arg)); - break; - } - case 'q': { - addquoted(L, b, arg); - continue; /* skip the 'addsize' at the end */ - } - case 's': { - size_t l; - const char* s = luaL_checklstring(L, arg, &l); - if (!strchr(form, '.') && l >= 100) { - /* no precision and string is too long to be formatted; - keep original string */ - continue; /* skip the `addsize' at the end */ - } else { - sprintf(buff, form, s); - break; - } - } - default: { /* also treat cases `pnLlh' */ - return luaL_error(L, "invalid option " LUA_QL("%%%c") " to " LUA_QL("format"), *(strfrmt - 1)); - } - } - strcat(b, buff); - } - } - return 1; -} -// END OF TEMPORARY SOLUTION - int32_t CSimpleFontString_IsObjectType(lua_State* L) { WHOA_UNIMPLEMENTED(0); } @@ -301,9 +147,9 @@ int32_t CSimpleFontString_SetFormattedText(lua_State* L) { return 0; } - char b[2048] = {}; - str_format(L, b); - string->SetText(b, 0); + char text[2048] = {}; + FrameScript_Sprintf(L, 2, text, sizeof(text)); + string->SetText(text, 0); return 0; } diff --git a/src/ui/FrameScript.cpp b/src/ui/FrameScript.cpp index 558c517..fb51ca6 100644 --- a/src/ui/FrameScript.cpp +++ b/src/ui/FrameScript.cpp @@ -10,6 +10,7 @@ #include #include #include +#include const char* g_glueScriptEvents[41]; const char* g_scriptEvents[722]; @@ -867,6 +868,216 @@ void FrameScript_UnregisterScriptEvent(FrameScript_Object* object, FrameScript_E } } +static void addchar(char* buffer, size_t bufferSize, char ch) { + auto length = SStrLen(buffer); + if (length + 1 < bufferSize) + { + buffer[length++] = ch; + buffer[length] = '\0'; + } +} + +static void addstring(char* buffer, size_t bufferSize, const char* source) { + uint32_t dsize = 0; + uint32_t size = 0; + + dsize = SStrLen(buffer); + size = SStrLen(source); + + if (dsize + size >= bufferSize) { + size = bufferSize - dsize; + // Check for space for trailing zero + if (size < 2) { + size = 0; + } else { + size--; + } + } + + if (size > 0) + memmove(&buffer[dsize], source, size); + + buffer[dsize + size] = '\0'; +} + +static void addstring(char* buffer, size_t bufferSize, const char* source, size_t count) { + uint32_t dsize = 0; + uint32_t size = 0; + + dsize = SStrLen(buffer); + size = std::min(SStrLen(source), count); + + if (dsize + size >= bufferSize) { + size = bufferSize - dsize; + // Check for space for trailing zero + if (size < 2) { + size = 0; + } else { + size--; + } + } + + if (size > 0) + memmove(&buffer[dsize], source, size); + + buffer[dsize + size] = '\0'; +} + +static void addquoted(lua_State* L, char* buffer, size_t bufferSize, int arg) { + size_t l; + const char* s = luaL_checklstring(L, arg, &l); + addchar(buffer, bufferSize, '"'); + while (l--) { + switch (*s) { + case '"': + case '\\': + case '\n': { + addchar(buffer, bufferSize, '\\'); + addchar(buffer, bufferSize, *s); + break; + } + case '\r': { + addstring(buffer, bufferSize, "\\r"); + break; + } + case '\0': { + addstring(buffer, bufferSize, "\\000"); + break; + } + default: { + addchar(buffer, bufferSize, *s); + break; + } + } + s++; + } + addchar(buffer, bufferSize, '"'); +} + +#define FORMAT_FLAGS "-+ #0" + +static const char* scanformat(lua_State* L, const char* strfrmt, char* form) { + const char* flags = "-+ #0"; + const char* p = strfrmt; + + while (*p != '\0' && SStrChrR(FORMAT_FLAGS, *p) != NULL) { + p++; /* skip flags */ + } + + if ((size_t)(p - strfrmt) >= sizeof(FORMAT_FLAGS)) { + luaL_error(L, "invalid format (repeated flags)"); + } + + if (isdigit((unsigned char)(*p))) { + p++; /* skip width */ + } + + if (isdigit((unsigned char)(*p))) { + p++; /* (2 digits at most) */ + } + + if (*p == '.') { + p++; + if (isdigit((unsigned char)(*p))) { + p++; /* skip precision */ + } + if (isdigit((unsigned char)(*p))) { + p++; /* (2 digits at most) */ + } + } + if (isdigit((unsigned char)(*p))) { + luaL_error(L, "invalid format (width or precision too long)"); + } + + *(form++) = '%'; + strncpy(form, strfrmt, p - strfrmt + 1); + form += p - strfrmt + 1; + *form = '\0'; + return p; +} + +static void addintlen(char* form) { + size_t l = SStrLen(form); + char spec = form[l - 1]; + strcpy(form + l - 1, LUA_INTFRMLEN); + form[l + sizeof(LUA_INTFRMLEN) - 2] = spec; + form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0'; +} + +void FrameScript_Sprintf(lua_State* L, int startIndex, char* buffer, uint32_t bufferSize) { + // maximum size of each formatted item (> len(format('%99.99f', -1e308))) + const size_t MAX_ITEM = 512; + + // maximum size of each format specification (such as '%-099.99d') + // (+10 accounts for %99.99x plus margin of error) + const size_t MAX_FORMAT = sizeof(FORMAT_FLAGS) + sizeof(LUA_INTFRMLEN) + 10; + + int arg = startIndex; + size_t sfl; + const char* strfrmt = luaL_checklstring(L, arg, &sfl); + const char* strfrmt_end = strfrmt + sfl; + while (strfrmt < strfrmt_end) { + if (*strfrmt != '%') { + addchar(buffer, bufferSize, *strfrmt++); + } else if (*++strfrmt == '%') { + addchar(buffer, bufferSize, *strfrmt++); /* %% */ + } else { /* format item */ + char form[MAX_FORMAT]; /* to store the format (`%...') */ + char buff[MAX_ITEM]; /* to store the formatted item */ + arg++; + strfrmt = scanformat(L, strfrmt, form); + switch (*strfrmt++) { + case 'c': { + sprintf(buff, form, (int)luaL_checknumber(L, arg)); + break; + } + case 'd': + case 'i': { + addintlen(form); + sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); + break; + } + case 'o': + case 'u': + case 'x': + case 'X': { + addintlen(form); + sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); + break; + } + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': { + sprintf(buff, form, (double)luaL_checknumber(L, arg)); + break; + } + case 'q': { + addquoted(L, buffer, bufferSize, arg); + continue; /* skip the 'addsize' at the end */ + } + case 's': { + size_t l; + const char* s = luaL_checklstring(L, arg, &l); + if (!strchr(form, '.') && l >= 100) { + /* no precision and string is too long to be formatted; + keep original string */ + continue; /* skip the `addsize' at the end */ + } else { + sprintf(buff, form, s); + break; + } + } + default: { /* also treat cases `pnLlh' */ + luaL_error(L, "invalid option " LUA_QL("%%%c") " to " LUA_QL("format"), *(strfrmt - 1)); + } + } + addstring(buffer, bufferSize, buff); + } + } +} + void GlueScriptEventsInitialize() { g_glueScriptEvents[0] = "SET_GLUE_SCREEN"; g_glueScriptEvents[1] = "START_GLUE_MUSIC"; diff --git a/src/ui/FrameScript.hpp b/src/ui/FrameScript.hpp index debf40f..6221927 100644 --- a/src/ui/FrameScript.hpp +++ b/src/ui/FrameScript.hpp @@ -100,6 +100,8 @@ void FrameScript_SignalEvent(uint32_t index, const char* format, ...); void FrameScript_UnregisterScriptEvent(FrameScript_Object* object, FrameScript_EventObject* event); +void FrameScript_Sprintf(lua_State* L, int startIndex, char* buffer, uint32_t bufferSize); + void GlueScriptEventsInitialize(); void ScriptEventsInitialize(); diff --git a/src/ui/ScriptFunctionsGlueScriptEvents.cpp b/src/ui/ScriptFunctionsGlueScriptEvents.cpp index e97945e..e34011a 100644 --- a/src/ui/ScriptFunctionsGlueScriptEvents.cpp +++ b/src/ui/ScriptFunctionsGlueScriptEvents.cpp @@ -19,8 +19,11 @@ int32_t Script_IsShiftKeyDown(lua_State* L) { } int32_t Script_GetBuildInfo(lua_State* L) { - lua_pushstring(L, "WHOA"); - lua_pushstring(L, "Release"); + auto szVersion = FrameScript_GetText("VERSION", -1, GENDER_NOT_APPLICABLE); + auto szVersionType = FrameScript_GetText("RELEASE_BUILD", -1, GENDER_NOT_APPLICABLE); + + lua_pushstring(L, szVersion); + lua_pushstring(L, szVersionType); lua_pushstring(L, "3.3.5"); lua_pushstring(L, "12340"); lua_pushstring(L, "Jun 24 2010"); From 6f108b306741208eb95d8a0584766257afc9f905 Mon Sep 17 00:00:00 2001 From: VDm Date: Tue, 10 Dec 2024 20:37:18 +0400 Subject: [PATCH 4/9] chore(ui): add TAB button handler for CSimpleEditBox --- src/ui/CSimpleEditBox.cpp | 11 +++++++++++ src/ui/CSimpleEditBox.hpp | 1 + 2 files changed, 12 insertions(+) diff --git a/src/ui/CSimpleEditBox.cpp b/src/ui/CSimpleEditBox.cpp index 6945ce9..5f0b9ae 100644 --- a/src/ui/CSimpleEditBox.cpp +++ b/src/ui/CSimpleEditBox.cpp @@ -871,6 +871,11 @@ int32_t CSimpleEditBox::OnLayerKeyDown(const CKeyEvent& evt) { return 1; } + case KEY_TAB: { + // TODO correct implementation + this->RunOnTabPressedScript(); + } + // TODO // - remaining keys @@ -994,6 +999,12 @@ void CSimpleEditBox::RunOnEnterPressedScript() { } } +void CSimpleEditBox::RunOnTabPressedScript() { + if (this->m_onTabPressed.luaRef) { + this->RunScript(this->m_onTabPressed, 0, 0); + } +} + void CSimpleEditBox::RunOnTextChangedScript(int32_t changed) { if (this->m_onTextChanged.luaRef) { auto L = FrameScript_GetContext(); diff --git a/src/ui/CSimpleEditBox.hpp b/src/ui/CSimpleEditBox.hpp index 5fb7e26..2c264d8 100644 --- a/src/ui/CSimpleEditBox.hpp +++ b/src/ui/CSimpleEditBox.hpp @@ -98,6 +98,7 @@ class CSimpleEditBox : public CSimpleFrame, CSimpleFontedFrame { void RunOnEditFocusGainedScript(); void RunOnEditFocusLostScript(); void RunOnEnterPressedScript(); + void RunOnTabPressedScript(); void RunOnTextChangedScript(int32_t changed); void SetCursorPosition(int32_t position); void SetHistoryLines(int32_t a2); From 5fb8536fced775515ac0387a6860088a11c2f011 Mon Sep 17 00:00:00 2001 From: VDm Date: Wed, 11 Dec 2024 00:20:01 +0400 Subject: [PATCH 5/9] fix(d3d): fix hardware cursor --- lib/squall | 2 +- src/console/Device.cpp | 1 + src/gx/d3d/CGxDeviceD3d.cpp | 16 +++++++++++++--- src/gx/d3d/CGxDeviceD3d.hpp | 1 + 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/lib/squall b/lib/squall index 9722c1e..22e9686 160000 --- a/lib/squall +++ b/lib/squall @@ -1 +1 @@ -Subproject commit 9722c1e8c35e14e57f9a4f1e45806d8237df957b +Subproject commit 22e9686d64db308a9b480ecf6e1fba43c2563315 diff --git a/src/console/Device.cpp b/src/console/Device.cpp index 5a1df3b..2d87392 100644 --- a/src/console/Device.cpp +++ b/src/console/Device.cpp @@ -274,6 +274,7 @@ void ConsoleDeviceInitialize(const char* title) { s_requestedFormat.hwTnL = true; // TODO + s_requestedFormat.hwCursor = true; CGxFormat format; memcpy(&format, &s_requestedFormat, sizeof(s_requestedFormat)); diff --git a/src/gx/d3d/CGxDeviceD3d.cpp b/src/gx/d3d/CGxDeviceD3d.cpp index b60fc97..eeaa104 100644 --- a/src/gx/d3d/CGxDeviceD3d.cpp +++ b/src/gx/d3d/CGxDeviceD3d.cpp @@ -334,11 +334,17 @@ LRESULT CGxDeviceD3d::WindowProcD3d(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM case WM_SETCURSOR: { if (device) { - if (device->m_d3dDevice && lParam == 1) { + if (device->m_d3dDevice && LOWORD(lParam) == HTCLIENT) { SetCursor(nullptr); BOOL show = device->m_cursorVisible && device->m_hardwareCursor ? TRUE : FALSE; device->m_d3dDevice->ShowCursor(show); + } else { + // Uncomment when the "glove" cursor will be fixed + //break; } + } else { + // Uncomment when the "glove" cursor will be fixed + //break; } return 1; @@ -488,8 +494,7 @@ int32_t CGxDeviceD3d::DeviceSetFormat(const CGxFormat& format) { if (this->ICreateWindow(createFormat) && this->ICreateD3dDevice(createFormat) && this->CGxDevice::DeviceSetFormat(format)) { this->intF64 = 1; - - // TODO + this->m_hwCursorNeedsUpdate = 1; if (this->m_format.window == 0) { RECT windowRect; @@ -1249,6 +1254,11 @@ void CGxDeviceD3d::CursorSetVisible(int32_t visible) { } } +void CGxDeviceD3d::CursorUnlock(uint32_t x, uint32_t y) { + CGxDevice::CursorUnlock(x, y); + this->m_hwCursorNeedsUpdate = 1; +} + void CGxDeviceD3d::ICursorDraw() { if (!this->m_hardwareCursor) { this->ISceneBegin(); diff --git a/src/gx/d3d/CGxDeviceD3d.hpp b/src/gx/d3d/CGxDeviceD3d.hpp index 16c9f3e..ceeee09 100644 --- a/src/gx/d3d/CGxDeviceD3d.hpp +++ b/src/gx/d3d/CGxDeviceD3d.hpp @@ -252,6 +252,7 @@ class CGxDeviceD3d : public CGxDevice { virtual void ICursorDestroy(); virtual void ICursorDraw(); virtual void CursorSetVisible(int32_t visible); + virtual void CursorUnlock(uint32_t x, uint32_t y); virtual int32_t DeviceCreate(int32_t (*windowProc)(void* window, uint32_t message, uintptr_t wparam, intptr_t lparam), const CGxFormat& format); virtual int32_t DeviceSetFormat(const CGxFormat& format); virtual void* DeviceWindow(); From 6191acb291c14abd6eb0ca20fe698ebf61ec26ab Mon Sep 17 00:00:00 2001 From: VDm Date: Thu, 12 Dec 2024 01:53:04 +0400 Subject: [PATCH 6/9] feat(d3d): add GxRs_Lighting case for CGxDeviceD3d::IRsSendToHw --- src/gx/d3d/CGxDeviceD3d.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/gx/d3d/CGxDeviceD3d.cpp b/src/gx/d3d/CGxDeviceD3d.cpp index eeaa104..12c621c 100644 --- a/src/gx/d3d/CGxDeviceD3d.cpp +++ b/src/gx/d3d/CGxDeviceD3d.cpp @@ -1107,6 +1107,17 @@ void CGxDeviceD3d::IRsSendToHw(EGxRenderState which) { break; } + case GxRs_Lighting: { + int32_t lightingEnable = 0; + + if (this->MasterEnable(GxMasterEnable_Lighting)) { + lightingEnable = static_cast(state->m_value); + } + + this->m_d3dDevice->SetRenderState(D3DRS_LIGHTING, lightingEnable); + break; + } + case GxRs_DepthTest: case GxRs_DepthFunc: { auto depthTest = static_cast((&this->m_appRenderStates[GxRs_DepthTest])->m_value); From f22485952b742f185a057b17088b3df4a9aba443 Mon Sep 17 00:00:00 2001 From: VDm Date: Sat, 14 Dec 2024 18:17:55 +0400 Subject: [PATCH 7/9] chore(gx): store software cursor workaround --- src/gx/CGxDevice.cpp | 5 ++++- src/gx/glsdl/GLSDLDevice.cpp | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/gx/CGxDevice.cpp b/src/gx/CGxDevice.cpp index 8e07f12..32f888c 100644 --- a/src/gx/CGxDevice.cpp +++ b/src/gx/CGxDevice.cpp @@ -333,7 +333,7 @@ void CGxDevice::ICursorDraw() { // Turn off everything GxRsSet(GxRs_PolygonOffset, 0); GxRsSet(GxRs_NormalizeNormals, 0); - GxRsSet(GxRs_BlendingMode, 1); + GxRsSet(GxRs_BlendingMode, GxBlend_AlphaKey); GxRsSetAlphaRef(); GxRsSet(GxRs_Lighting, 0); GxRsSet(GxRs_Fog, 0); @@ -355,6 +355,9 @@ void CGxDevice::ICursorDraw() { float cursorDepth = 1.0f; C44Matrix projection; + // Workaround for software cursor + // C44Matrix projection(2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0.002, 0, -1, -1, 0, 1); + // this->XformSetProjection(projection); if (!this->StereoEnabled() || (CGxDevice::s_uiVertexShader == 0 || !s_uiVertexShader->Valid()) || diff --git a/src/gx/glsdl/GLSDLDevice.cpp b/src/gx/glsdl/GLSDLDevice.cpp index 81bfa15..6e67dac 100644 --- a/src/gx/glsdl/GLSDLDevice.cpp +++ b/src/gx/glsdl/GLSDLDevice.cpp @@ -1578,7 +1578,7 @@ GLTexture* GLSDLDevice::CreateTextureCubeMap(uint32_t size, uint32_t numMipMap, } void GLSDLDevice::Draw(GLEnum primitive, uint32_t a3, uint32_t a4) { - // TODO + this->GLSDLDraw(primitive, a3, a3 + a4, 0, 0, 0); } void GLSDLDevice::DrawIndexed(GLEnum primitive, uint32_t a3, uint32_t a4, uint32_t a5, uint32_t a6, uint32_t count) { From 9df49cd3f7da8f069151adb7db4927ea792c19a0 Mon Sep 17 00:00:00 2001 From: VDm Date: Sun, 15 Dec 2024 16:29:00 +0400 Subject: [PATCH 8/9] fix(input): convert local code-page characters to Unicode ones --- src/event/win/Input.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/event/win/Input.cpp b/src/event/win/Input.cpp index 687892b..a08b241 100644 --- a/src/event/win/Input.cpp +++ b/src/event/win/Input.cpp @@ -539,7 +539,10 @@ int32_t OsWindowProc(void* window, uint32_t message, uintptr_t wparam, intptr_t uint32_t character = wparam; if (wparam >= 128) { - // TODO + // Workaround + wchar_t u16_character = 0; + ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, reinterpret_cast(&wparam), 1, &u16_character, 1); + character = u16_character; } OsQueuePut(OS_INPUT_CHAR, character, LOWORD(lparam), 0, 0); From eeab0356646a3d68086c6fcb4ce956f9f59d3df0 Mon Sep 17 00:00:00 2001 From: VDm Date: Sat, 1 Mar 2025 21:53:08 +0400 Subject: [PATCH 9/9] fix(console): use SUniSPutUTF8 in OnChar handler --- src/console/Handlers.cpp | 9 ++---- src/glue/CGlueMgr.cpp | 66 +++++++++++++++++++++------------------- 2 files changed, 37 insertions(+), 38 deletions(-) diff --git a/src/console/Handlers.cpp b/src/console/Handlers.cpp index 6bf03d5..b5e30d9 100644 --- a/src/console/Handlers.cpp +++ b/src/console/Handlers.cpp @@ -4,6 +4,7 @@ #include "console/Command.hpp" #include "console/Screen.hpp" #include "event/Event.hpp" +#include "storm/Unicode.hpp" #include static int32_t s_historyIndex = 0; @@ -11,24 +12,20 @@ static int32_t s_historyIndex = 0; namespace { int32_t OnChar(const EVENT_DATA_CHAR* data, void* param) { - char character[2]; + char character[8] = {}; if (ConsoleAccessGetEnabled() && EventIsKeyDown(ConsoleGetHotKey())) { return 0; } if (ConsoleGetActive()) { - character[0] = char(data->ch); - character[1] = 0; + SUniSPutUTF8(data->ch, character); PasteInInputLine(character); ResetHighlight(); return 0; } - // SUniSPutUTF8(data->ch, character); - - return 1; } diff --git a/src/glue/CGlueMgr.cpp b/src/glue/CGlueMgr.cpp index 1061cde..93a6bd3 100644 --- a/src/glue/CGlueMgr.cpp +++ b/src/glue/CGlueMgr.cpp @@ -366,46 +366,48 @@ void CGlueMgr::PollAccountLogin(int32_t errorCode, const char* msg, int32_t comp FrameScript_SignalEvent(4, "%s", msg); } - if (complete) { - if (result == 0) { - if (errorCode != 2) { + if (!complete) { + return; + } + + if (result == 0) { + if (errorCode != 2) { + // TODO + } + + CGlueMgr::m_idleState = IDLE_NONE; + CGlueMgr::m_showedDisconnect = 0; + + if (errorCode == 2) { + // TODO CGlueMgr::m_disconnectPending = 1; + // TODO ClientServices::Connection()->Disconnect(); + } + + if (errorCode != 13) { + // TODO CCharacterSelection::ClearCharacterList(); + + if (ClientServices::GetInstance()->m_realmList.Count()) { + FrameScript_SignalEvent(5, nullptr); + CRealmList::UpdateList(); + } else { // TODO } - CGlueMgr::m_idleState = IDLE_NONE; - CGlueMgr::m_showedDisconnect = 0; - - if (errorCode == 2) { - // TODO CGlueMgr::m_disconnectPending = 1; - // TODO ClientServices::Connection()->Disconnect(); - } - - if (errorCode != 13) { - // TODO CCharacterSelection::ClearCharacterList(); - - if (ClientServices::GetInstance()->m_realmList.Count()) { - FrameScript_SignalEvent(5, nullptr); - CRealmList::UpdateList(); - } else { - // TODO - } - - return; - } - - if (!SStrCmpI(CGlueMgr::m_currentScreen, "charselect", STORM_MAX_STR)) { - CGlueMgr::SetScreen("login"); - return; - } - return; } - if (op == COP_CONNECT) { - // TODO - + if (!SStrCmpI(CGlueMgr::m_currentScreen, "charselect", STORM_MAX_STR)) { + CGlueMgr::SetScreen("login"); return; } + + return; + } + + if (op == COP_CONNECT) { + // TODO + + return; } }