diff --git a/Source/UI/Lists/UIListBox.h b/Source/UI/Lists/UIListBox.h index ef37d3b2..9908a0ee 100644 --- a/Source/UI/Lists/UIListBox.h +++ b/Source/UI/Lists/UIListBox.h @@ -10,6 +10,7 @@ struct FrameFocus; class ResourceMgr; class UIScrollBar; class WindowManagerWindows; +struct UIButtonContext; struct UIListBoxContext { FrameFocus& capture; @@ -18,6 +19,7 @@ struct UIListBoxContext { const TextLocale& locale; const unsigned short& codePage; WindowManagerWindows& windows; + UIButtonContext& buttons; }; class UIListBox : public UIWindow { diff --git a/Source/UI/Lists/UITagListBox.cpp b/Source/UI/Lists/UITagListBox.cpp index 413bac3b..7a10d7c8 100644 --- a/Source/UI/Lists/UITagListBox.cpp +++ b/Source/UI/Lists/UITagListBox.cpp @@ -10,6 +10,7 @@ #include "UI/Text/PixelTextWrapping.h" #include "UI/Text/TextWrapping.h" #include "UI/Window/UIWindowMgr.h" +#include "Utility/Text/TextTokens.h" #include #include @@ -401,8 +402,8 @@ void UITagListBox::sub_9B9EA0(std::intptr_t argument1, std::intptr_t argument2, if (width == 138) { WrapPlainText(text, lines, 38, owner.codePage); - for (const std::string& line : lines) { - this->AddLine(line.c_str()); + for (std::size_t index = 0; index < lines.size(); ++index) { + this->AddLine(lines[index].c_str()); } this->unknown_00BC = (this->unknown_00BC & ~255) | 1; @@ -414,12 +415,12 @@ void UITagListBox::sub_9B9EA0(std::intptr_t argument1, std::intptr_t argument2, } WrapPixelText(*this->geometry.surface, owner.codePage, text, lines, this->geometry.width - extra - 4); - for (const std::string& line : lines) { - this->AddLine(line.c_str()); + for (std::size_t index = 0; index < lines.size(); ++index) { + this->AddLine(lines[index].c_str()); } } else { std::vector tags; - const std::string parsed = this->sub_9B8AA0(std::string(text)); + const std::string parsed = this->sub_9B8AA0(std::string(text), tags); this->sub_9BB8E0(parsed, tags, width == 0 ? 35 : width); } @@ -562,3 +563,114 @@ void UITagListBox::sub_9BC0A0(std::intptr_t type, UIWindow* sender) { break; } } + +// OFFSET: 0x009B8AA0 +// FUNCTION: fn_13874 +std::string UITagListBox::sub_9B8AA0(std::string text, std::vector& tags) { + std::vector extracted = ExtractTextTags(text); + if (extracted.empty()) { + return text; + } + + tags.clear(); + std::sort(extracted.begin(), extracted.end(), [](const STagString& left, const STagString& right) { + return static_cast(left.position) < static_cast(right.position); + }); + + std::string result; + std::size_t position = 0; + for (std::size_t index = 0; index < extracted.size(); ++index) { + const STagString& source = extracted[index]; + STagInfoV2 tag; + result += text.substr(position, source.position - position); + tag.unknown_0008 = static_cast(result.size()); + const std::pair parsed = this->ParseTag(source.text, source.tag); + result += parsed.first; + tag.unknown_000C = static_cast(result.size()); + tag.unknown_0010 = parsed.first; + tag.unknown_0028 = parsed.second; + tag.unknown_0004 = g_textTagRegistry[source.tag].type; + tags.push_back(tag); + position = source.position + source.text.size(); + } + + if (position < text.size() - 1) { + result += text.substr(position, text.size() - position); + } + return result; +} + +// OFFSET: 0x009BB8E0 + +// OFFSET: 0x009B7A20 +// FUNCTION: fn_13870 +void UITagListBox::AddTagButton(STagInfoV2 tag, int lineCount) { + if (tag.unknown_0010.empty()) { + return; + } + + UITagButton* button = new UITagButton(*this->m_context, this->m_listContext->buttons); + button->Configure(tag.unknown_0010.c_str(), 0x00F4934A, 0, 12, 0, 1); + const int height = button->geometry.height; + button->ResizeToTextClipped( + this->TextWidth(this->m_listContext->fonts, this->m_listContext->locale, tag.unknown_0010.c_str(), 0, 0, 12, 0, 0) + 1, height + ); + button->m_hoverColor = 0x00FF7864; + button->SetId(tag.unknown_0004); + + std::string data = tag.unknown_0028; + if (!data.empty()) { + switch (tag.unknown_0004) { + case 438: + case 464: { + std::string remaining = data; + std::size_t separator = remaining.find(','); + while (separator != std::string::npos) { + const std::string field = remaining.substr(0, separator); + button->AddString(field); + remaining = remaining.substr(separator + 1); + separator = remaining.find(','); + } + button->AddString(remaining); + if (tag.unknown_0004 == 464) { + int id = 0; + if (!button->GetString(1).empty()) { + id = std::atoi(button->GetString(1).c_str()); + } + button->item.unknown_0000[0] = id; + button->item.identified = 1; + button->item.unknown_0060 = 0; + button->item.itemId = button->GetString(0); + } + break; + } + case 501: { + std::vector fields; + this->DecodeItemFields(data, fields); + this->ItemFromFields(fields, button->item); + break; + } + } + } + + int x = 0; + unsigned int line = 0; + int bytes = 0; + const unsigned int count = static_cast(this->lines.size()); + for (unsigned int index = count - lineCount; index < count; ++index) { + bytes += static_cast(this->lines[index].size()); + if (tag.unknown_0008 < bytes) { + const int prefixLength = static_cast(this->lines[index].size()) - bytes + tag.unknown_0008; + const std::string stripped = StripColorTokens(this->lines[index].c_str(), prefixLength); + const std::string prefix = stripped.substr(0, prefixLength); + x = this->TextWidth(this->m_listContext->fonts, this->m_listContext->locale, prefix.c_str(), 0, 0, 12, 0, 0) + 2; + line = index; + break; + } + } + + button->m_value = line; + button->Move(x, -100); + this->AddChild(button); + this->m_tagWindows.push_back(button); +} diff --git a/Source/UI/Lists/UITagListBox.h b/Source/UI/Lists/UITagListBox.h index 745fe43e..16fe1ad1 100644 --- a/Source/UI/Lists/UITagListBox.h +++ b/Source/UI/Lists/UITagListBox.h @@ -33,7 +33,7 @@ public: void sub_9B9EA0(std::intptr_t argument1, std::intptr_t argument2, std::intptr_t argument3, std::intptr_t argument4); void sub_9BC0A0(std::intptr_t type, UIWindow* sender); - std::string sub_9B8AA0(std::string text); + std::string sub_9B8AA0(std::string text, std::vector& tags); std::pair ParseTag(std::string text, int tagIndex); void sub_9BB8E0(std::string text, std::vector& tags, int width); int DecodeNumber(std::string text); @@ -41,6 +41,7 @@ public: bool ItemFromFields(const std::vector& fields, ITEM_INFO& item); void DecodeValues(std::vector& values, const char* text, int& position, const int& end, const char& separator, const char& alternate); int DecodeCards(std::vector& fields, const char* text, int& position, const char& separator, const int& end, int index); + void AddTagButton(STagInfoV2 tag, int lineCount); protected: /* 00D4 */ std::vector m_tagWindows;