#include "ui/FrameXML.hpp" #include "ui/CSimpleButton.hpp" #include "ui/CSimpleCheckbox.hpp" #include "ui/CSimpleEditBox.hpp" #include "ui/CSimpleFont.hpp" #include "ui/CSimpleFrame.hpp" #include "ui/CSimpleHTML.hpp" #include "ui/CSimpleModel.hpp" #include "ui/CSimpleMovieFrame.hpp" #include "ui/CSimpleScrollFrame.hpp" #include "ui/CSimpleMessageScrollFrame.hpp" #include "ui/CSimpleSlider.hpp" #include "ui/CSimpleStatusBar.hpp" #include "util/CStatus.hpp" #include "util/SFile.hpp" #include #include #include #include int32_t FrameXML::s_debugLevel; TSHashTable FrameXML::s_factoryHash; TSHashTable FrameXML::s_nodeHash; CSimpleFrame* Create_SimpleButton(CSimpleFrame* parent) { // TODO // auto m = CDataAllocator::GetData(CSimpleFrame::s_simpleButtonHeap, 0, __FILE__, __LINE__); auto m = SMemAlloc(sizeof(CSimpleButton), __FILE__, __LINE__, 0x0); return new (m) CSimpleButton(parent); } CSimpleFrame* Create_SimpleCheckButton(CSimpleFrame* parent) { // TODO // auto m = CDataAllocator::GetData(CSimpleCheckbox::s_simpleCheckboxHeap, 0, __FILE__, __LINE__); auto m = SMemAlloc(sizeof(CSimpleCheckbox), __FILE__, __LINE__, 0x0); return new (m) CSimpleCheckbox(parent); } CSimpleFrame* Create_SimpleEditBox(CSimpleFrame* parent) { // TODO // auto m = CDataAllocator::GetData(CSimpleEditBox::s_simpleEditBoxHeap, 0, __FILE__, __LINE__); auto m = SMemAlloc(sizeof(CSimpleEditBox), __FILE__, __LINE__, 0x0); return new (m) CSimpleEditBox(parent); } CSimpleFrame* Create_SimpleFrame(CSimpleFrame* parent) { // TODO // auto m = CDataAllocator::GetData(CSimpleFrame::s_simpleFrameHeap, 0, __FILE__, __LINE__); auto m = SMemAlloc(sizeof(CSimpleFrame), __FILE__, __LINE__, 0x0); return new (m) CSimpleFrame(parent); } CSimpleFrame* Create_SimpleMessageFrame(CSimpleFrame* parent) { // TODO return nullptr; } CSimpleFrame* Create_SimpleModel(CSimpleFrame* parent) { // TODO // auto m = CDataAllocator::GetData(CSimpleFrame::s_simpleModelHeap, 0, __FILE__, __LINE__); auto m = SMemAlloc(sizeof(CSimpleModel), __FILE__, __LINE__, 0x0); return new (m) CSimpleModel(parent); } CSimpleFrame* Create_SimpleScrollFrame(CSimpleFrame* parent) { // TODO // auto m = CDataAllocator::GetData(CSimpleScrollFrame::s_simpleScrollHeap, 0, __FILE__, __LINE__); auto m = SMemAlloc(sizeof(CSimpleScrollFrame), __FILE__, __LINE__, 0x0); return new (m) CSimpleScrollFrame(parent); } CSimpleFrame* Create_SimpleScrollingMessageFrame(CSimpleFrame* parent) { // TODO auto m = SMemAlloc(sizeof(CSimpleMessageScrollFrame), __FILE__, __LINE__, 0x0); return new (m) CSimpleMessageScrollFrame(parent); } CSimpleFrame* Create_SimpleSlider(CSimpleFrame* parent) { // TODO // auto m = CDataAllocator::GetData(CSimpleSlider::s_simpleSliderHeap, 0, __FILE__, __LINE__); auto m = SMemAlloc(sizeof(CSimpleSlider), __FILE__, __LINE__, 0x0); return new (m) CSimpleSlider(parent); } CSimpleFrame* Create_SimpleHTML(CSimpleFrame* parent) { // TODO // auto m = CDataAllocator::GetData(CSimpleHTML::s_simpleHTMLHeap, 0, __FILE__, __LINE__); auto m = SMemAlloc(sizeof(CSimpleHTML), __FILE__, __LINE__, 0x0); return new (m) CSimpleHTML(parent); } CSimpleFrame* Create_SimpleStatusBar(CSimpleFrame* parent) { // TODO auto m = SMemAlloc(sizeof(CSimpleStatusBar), __FILE__, __LINE__, 0x0); return new (m) CSimpleStatusBar(parent); } CSimpleFrame* Create_SimpleColorSelect(CSimpleFrame* parent) { // TODO return nullptr; } CSimpleFrame* Create_SimpleMovieFrame(CSimpleFrame* parent) { // TODO // auto m = CDataAllocator::GetData(CSimpleMovie::s_simpleMovieHeap, 0, __FILE__, __LINE__); auto m = SMemAlloc(sizeof(CSimpleMovieFrame), __FILE__, __LINE__, 0x0); return new (m) CSimpleMovieFrame(parent); } XMLNode* FrameXML_AcquireHashNode(const char* name, const char*& tainted, bool& locked) { HashedNode* hashedNode = FrameXML::s_nodeHash.Ptr(name); if (!hashedNode) { return nullptr; } locked = hashedNode->locked; tainted = hashedNode->tainted; hashedNode->locked = true; return hashedNode->node; } int32_t FrameXML_CheckSignature(const char* tocPath, const char* a2, const unsigned char* key, unsigned char* digest) { // TODO return 3; } /** * Find and return the appropriate parent name. * * Parent priorities: * 1. parent attribute on local node * 2. parent attribute on last inherited node with parent attribute present */ const char* FindParent(XMLNode* node) { const char* parentName = node->GetAttributeByName("parent"); if (parentName && *parentName) { return parentName; } const char* inheritNames = node->GetAttributeByName("inherits"); if (!inheritNames || !*inheritNames) { return nullptr; } char inheritName[1024]; do { SStrTokenize(&inheritNames, inheritName, 0x400u, " ,", 0); if (!*inheritName) { break; } auto hashedNode = FrameXML::s_nodeHash.Ptr(inheritName); if (hashedNode) { auto inheritNode = hashedNode->node; int32_t v10 = hashedNode->locked; hashedNode->locked = true; if (inheritNode && !v10) { parentName = inheritNode->GetAttributeByName("parent"); FrameXML::s_nodeHash.Ptr(inheritName)->locked = false; } } } while (*inheritName); return parentName; } CSimpleFrame* FrameXML_CreateFrame(XMLNode* node, CSimpleFrame* parent, CStatus* status) { if (FrameXML::s_debugLevel > 0) { const char* name = node->GetAttributeByName("name"); if (name && *name) { status->Add(STATUS_INFO, "-- Creating %s named %s", node->m_name.m_str, name); } else { status->Add(STATUS_INFO, "-- Creating unnamed %s", node->m_name.m_str); } } auto factoryNode = FrameXML::s_factoryHash.Ptr(node->m_name.m_str); if (!factoryNode) { status->Add(STATUS_WARNING, "Unknown frame type: %s", node->m_name.m_str); return nullptr; } const char* parentName = FindParent(node); if (parentName && *parentName) { int32_t parentType = CSimpleFrame::GetObjectType(); parent = static_cast(CScriptObject::GetScriptObjectByName(parentName, parentType)); if (!parent) { status->Add(STATUS_WARNING, "Couldn't find frame parent: %s", parentName); } } CSimpleFrame* frame = factoryNode->m_factory(parent); if (frame) { if (factoryNode->m_unique) { // TODO // Delete the factory node // sub_565030(factoryNode); // FrameXML::s_factoryHash.InternalDelete(factoryNode); } frame->PreLoadXML(node, status); frame->LoadXML(node, status); frame->PostLoadXML(node, status); return frame; } else { status->Add(STATUS_WARNING, "Unable to create frame type: %s", node->m_name.m_str); return nullptr; } } int32_t FrameXML_CreateFrames(const char* tocPath, const char* a2, MD5_CTX* md5, CStatus* status) { if (!status) { status = new CStatus; } char v15[260]; v15[0] = 0; memset(v15 + 1, 0, 259); const char* v5 = tocPath; const char* v6 = SStrChrR(tocPath, '\\'); if (v6) { uintptr_t v7 = v6 - tocPath + 1; uintptr_t v8 = v7; if (v7 < 259) { SStrCopy(v15, tocPath, v7 + 1); v15[v8] = 0; } } void* tocBuffer; size_t tocBytes; if (!SFile::Load(nullptr, tocPath, &tocBuffer, &tocBytes, 1, 1, nullptr)) { status->Add(STATUS_ERROR, "Couldn't open %s", a2); return 0; } MD5Update(md5, static_cast(tocBuffer), tocBytes); const char* tocData = static_cast(tocBuffer); // Advance past UTF-8 BOM if present if (*tocData == static_cast(0xEF) && *(tocData + 1) == static_cast(0xBB) && *(tocData + 2) == static_cast(0xBF)) { tocData = tocData + 3; } CStatus frameStatus; char tocLine[1024]; char tocEntryPath[260]; int32_t v25 = 0; do { SStrTokenize(&tocData, tocLine, 1024, "\r\n", 0); if (!*tocLine) { break; } if (*tocLine == '#') { continue; } SStrCopy(tocEntryPath, v15, 260); SStrPack(tocEntryPath, tocLine, 260); size_t v10 = SStrLen(tocEntryPath); bool v11 = tocEntryPath[v10 - 1] == ' '; char* v12 = &tocEntryPath[v10]; if (v11) { do { if (v12 <= tocEntryPath) { break; } --v12; } while (*(v12 - 1) == ' '); } *v12 = 0; FrameXML_ProcessFile(tocEntryPath, a2, md5, &frameStatus); // TODO // if (s_progressCallback && s_progressFiles < s_progressTotal) { // ++s_progressFiles; // v20 = s_progressTotal; // v13 = (double)(unsigned int)s_progressFiles / (double)(unsigned int)s_progressTotal; // s_progressCallback(LODWORD(v13), s_progressParam); // v5 = a2; // } } while (*tocLine); // TODO // XMLTree_Cleanup(); SFile::Unload(tocBuffer); if (FrameXML::s_debugLevel > 0 || v25 > 0) { frameStatus.Prepend(STATUS_INFO, "** Loading table of contents %s", v5); } status->Add(frameStatus); return 1; } void FrameXML_FreeHashNodes() { FrameXML::s_nodeHash.Clear(); } XMLTree* FrameXML_LoadXML(const char* filePath, MD5_CTX* md5, CStatus* status) { void* xmlBuffer; size_t xmlBytes; if (SFile::Load(nullptr, filePath, &xmlBuffer, &xmlBytes, 0, 1, nullptr)) { MD5Update(md5, static_cast(xmlBuffer), xmlBytes); XMLTree* tree = XMLTree_Load(static_cast(xmlBuffer), xmlBytes); if (!tree) { status->Add(STATUS_ERROR, "Couldn't parse XML in %s", filePath); } SFile::Unload(xmlBuffer); return tree; } else { status->Add(STATUS_ERROR, "Couldn't open %s", filePath); return nullptr; } } int32_t FrameXML_ProcessFile(const char* filePath, const char* a2, MD5_CTX* md5, CStatus* status) { const char* v5 = filePath; char v25[260]; char* i; char* j; // Deal with relative file paths if (SStrStr(filePath, "..")) { SStrCopy(v25, filePath, 260); for (i = (char*)SStrStr(v25, ".."); i; i = (char*)SStrStr(v25, "..")) { char v7 = *(i - 1); if (v7 != '\\' && v7 != '/') { break; } char v8 = i[2]; if (v8 != '\\' && v8 != '/') { break; } for (j = i - 2; j >= v25; --j) { if (*j == '\\') { break; } if (*j == '/') { break; } } SStrCopy(j + 1, i + 3, 0x7FFFFFFF); } filePath = v25; v5 = v25; } const char* v10 = SStrChrR(v5, '.'); // If file ends in .lua, execute it and return if (v10 && !SStrCmpI(v10, ".lua", 0x7FFFFFFFu)) { return FrameScript_ExecuteFile(v5, a2, md5, status); } // Assume all other files are xml XMLTree* tree = FrameXML_LoadXML(v5, md5, status); if (!tree) { return 0; } CStatus fileStatus; XMLNode* node = XMLTree_GetRoot(tree)->m_child; char v26[271]; char v27[264]; // TODO // Should come from some kind of Lua headers const char* lua_tainted = nullptr; int32_t v34 = 0; while (node) { // if (!SStrCmpI(node->GetName(), "Include", 0x7FFFFFFFu)) { const char* v14 = node->GetAttributeByName("file"); if (v14) { const char* v15 = SStrChrR(v5, 92); if (v15) { uint32_t v13 = v15 - v5 + 1; if (v13 < 260 ) { SStrCopy(v27, v5, 260); v27[v13] = 0; SStrPack(v27, v14, 260); } } else { SStrCopy(v27, v14, 260); } FrameXML_ProcessFile(v27, a2, md5, &fileStatus); } else { fileStatus.Add(STATUS_ERROR, "Element 'Include' without file attribute"); } //