From a3df044ab161dd2e6d1f06c71fe4a447d92d4f28 Mon Sep 17 00:00:00 2001 From: ragnarok-clanker Date: Thu, 29 Oct 2026 21:03:08 +0000 Subject: [PATCH] Decompile fn_11211 (UITextViewer::AddTipLinks) Batch #2914 by youko: 0 byte-identical, 1 confirmed by peer review. - fn_11211 UITextViewer::AddTipLinks: logic confirmed by peer review Peer-reviewed-by: meitogi, alisonrag, superintelligence Accepted without human review: peers confirmed the logic ("same" ahead by at least 3, with 70% of the votes). --- Source/UI/Text/UITextViewerLinks.cpp | 97 ++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/Source/UI/Text/UITextViewerLinks.cpp b/Source/UI/Text/UITextViewerLinks.cpp index 3821934e..43bfc94d 100644 --- a/Source/UI/Text/UITextViewerLinks.cpp +++ b/Source/UI/Text/UITextViewerLinks.cpp @@ -197,6 +197,103 @@ bool UITextViewer::AddQuestLinks(std::string text, unsigned addedLines) { } // OFFSET: 0x00877B00 +// FUNCTION: fn_11211 +void UITextViewer::AddTipLinks(std::string text, unsigned addedLines) { + auto& owner = this->m_text->list; + std::string parsed = RemoveTextColors(text.c_str(), owner.codePage); + parsed = DisplayTextTag(std::move(parsed), "", ""); + parsed = DisplayTextTag(std::move(parsed), "", ""); + parsed = DisplayTextTag(std::move(parsed), "", ""); + parsed = DisplayTextTag(std::move(parsed), "", ""); + + if (this->m_text->chatConversions) { + parsed = this->ConvertChat(std::move(parsed)); + } + + std::string navigation; + DisplayNavigationLink(navigation, parsed); + parsed = std::move(navigation); + + std::vector extracted; + ExtractTextLinks(parsed, "", "", extracted); + + if (extracted.empty()) { + return; + } + + for (unsigned index = 0; index < extracted.size(); ++index) { + const TextLink& link = extracted[index]; + + if (this->splitTipLinks == 1) { + std::vector labels; + const char* begin = link.display.c_str(); + const char* const end = begin + std::strlen(begin); + std::uintptr_t limit = reinterpret_cast(begin) + 32u - link.position; + const char* current = begin; + const char* breakAt = begin; + + while (current < end) { + current = CharNextExA(owner.codePage, current, 0); + + while (*current == ' ') { + breakAt = ++current; + } + + if (reinterpret_cast(current) >= limit || *current == '\n') { + if (*current == '\n') { + breakAt = current++; + } + + if (breakAt > begin) { + labels.push_back(std::string(begin, breakAt)); + begin = breakAt; + } else { + labels.push_back(std::string(begin, current)); + begin = current; + } + + limit = reinterpret_cast(begin) + 32u; + } + } + + if (begin < current) { + labels.push_back(std::string(begin, current)); + } + + for (unsigned fragment = 0; fragment < labels.size(); ++fragment) { + auto* button = new UITextButton(*this->m_context, this->m_text->buttons); + button->Configure(labels[fragment].c_str(), 0x00F4934A, 0, 12, 0, 1); + const int height = button->geometry.height; + const int width = this->TextWidth(owner.fonts, owner.locale, labels[fragment].c_str(), 0, 0, 12, 0, 0); + button->Resize(width + 1, height); + button->m_hoverColor = 0x00FF7864; + button->SetId(517); + SplitTextLinkArguments(link.metadata, button->m_lines); + const auto position = this->LinkPosition(fragment == 0 ? link.position : 0, addedLines - fragment); + button->m_value = position.first; + button->Move(position.second, -100); + this->AddChild(button); + this->links.push_back(button); + } + } else { + auto* button = new UITextButton(*this->m_context, this->m_text->buttons); + button->Configure(link.display.c_str(), 0x00F4934A, 0, 12, 0, 1); + const int height = button->geometry.height; + const int width = this->TextWidth(owner.fonts, owner.locale, link.display.c_str(), 0, 0, 12, 0, 0); + button->Resize(width + 1, height); + button->m_hoverColor = 0x00FF7864; + button->SetId(517); + SplitTextLinkArguments(link.metadata, button->m_lines); + const auto position = this->LinkPosition(link.position, addedLines); + button->m_value = position.first; + button->Move(position.second, -100); + this->AddChild(button); + this->links.push_back(button); + } + } + + this->SendMsg(nullptr, 7, 0, 0, 0, 0); +} // OFFSET: 0x00878750 // OFFSET: 0x00878750